Reduce TupleHashEntryData struct size by half

From: Jeff Davis <pgsql(at)j-davis(dot)com>
To: pgsql-hackers(at)postgresql(dot)org
Subject: Reduce TupleHashEntryData struct size by half
Date: 2024-11-18 00:01:49
Message-ID: 817d244237878cebdff0bc363718feaf49a1ea7d.camel@j-davis.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers


TupleHashEntryData is the size of a hash bucket, and it's currently 24
bytes. The size of the structure is important for HashAgg and other
callers that can build up large hashtables of small tuples. Waste in
this structure is even worse when the hash table is sparse, because the
space is consumed whether the bucket is occupied or not.

The attached patch series brings it down to 12. There are several
unappealing hacks, so ideally we'd find something cleaner, but halving
the bucket size seems quite desirable if it can be done in an
acceptable way.

test:
create table big(i int, j int);
insert into big select g, 1 from generate_series(1,10000000) g;
vacuum freeze analyze big; checkpoint;
select pg_prewarm('big'::regclass);
set hash_mem_multiplier = 1;
set work_mem = '10GB';
explain analyze select count(*) from
(select i from big group by i) s;

results:
master: 768MiB memory, 4110ms
patches: 576MiB memory, 4070ms

(Timing difference is within test noise, so the benefit is reduced
memory footprint.)

This change is related to the problem and potential solutions discussed
at [1].

Patches:

0001: This patch makes the structure private, so that it's easier to
control the way the structure is accessed.

0002: Removes the "additional" pointer, instead storing it right after
the tuple, which is already stored in a separate chunk. Hack: this
crams the "additional" pointer after the MinimalTuple in the same chunk
of memory to avoid adding additional palloc()s.

0003: simplehash: allow the caller to decide which entries are empty vs
in-use rather than requiring a separate "status" field. This may limit
other possible status values in the future (i.e. adding on to the
enum), but I'm not sure what those other stutus values might be.

0004: Removes the "status" field from TupleHashEntryData, using
firstTuple==NULL to mean "empty", otherwise "in use". Hack: need an
additional "special" pointer value to mean "input slot" now that NULL
means "empty".

0005: Pack TupleHashEntryData. IIUC, this is fine even on machines that
can't do unaligned access, so long as we are accessing the fields
through the struct, and not taking the address of individual members.

Regards,
Jeff Davis

[1]
https://www.postgresql.org/message-id/e061c5439996e13c0fb51997e92d6a09834a7796.camel%40j-davis.com

Attachment Content-Type Size
v1-0001-Hide-details-of-TupleHashEntryData-struct.patch text/x-patch 10.6 KB
v1-0002-TupleHashTable-remove-additional-pointer.patch text/x-patch 2.0 KB
v1-0003-simplehash-don-t-require-a-status-field.patch text/x-patch 7.1 KB
v1-0004-TupleHashTable-reduce-overhead-by-removing-status.patch text/x-patch 4.9 KB
v1-0005-TupleHashTable-Pack-TupleHashEntryData-struct.patch text/x-patch 960 bytes

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Andy Fan 2024-11-18 00:23:52 Re: Extract numeric filed in JSONB more effectively
Previous Message Alexander Korotkov 2024-11-17 23:19:49 Re: POC, WIP: OR-clause support for indexes