> On Aug 1, 2026, at 16:35, David Rowley <[email protected]> wrote:
>
> a0942f441 added ExecCopySlotMinimalTupleExtra(), which accepts a
> parameter to specify the number of "extra" bytes that we want to
> allocate along with the MinimalTuple. That's now used in
> execGrouping.c to save some memory.
>
> The same optimisation can be applied in nodeMemoize.c. MemoizeTuple
> has a field for the tuple being stored and 1 other field to point to
> the next tuple cached for this MemoizeEntry. Here we could use
> ExecCopySlotMinimalTupleExtra() to specify that we want a pointer's
> worth of extra bytes palloc'd for the MinimalTuple, and then store the
> pointer to the next tuple in those bytes. This saves 16 bytes per
> cached tuple. 24 bytes less because we don't palloc a MemoizeTuple
> (including the MemoryChunk's 8 bytes), and 8 bytes more for the
> ExecCopySlotMinimalTupleExtra bytes, a net saving of 16 bytes per
> tuple.
>
> Making Memoize use less memory is useful in cases where the cache
> would otherwise have to reload entries that were cached previously but
> were evicted due to reaching memory limits.
>
> A quick example:
>
> create table t1 (a int not null);
> create table t2 (a int not null);
> insert into t1 select x from generate_series(1,100000) x,
> generate_series(1,100);
> create index on t1 (a);
> insert into t2 select x%1000+1 from generate_series(1,1000000)x;
> analyze t1,t2;
>
> explain analyze select count(*) from t1 inner join t2 on t1.a=t2.a;
>
> Master: Memory Usage: 3583kB
> Patched: Memory Usage: 2801kB
>
> Really, the savings are double what's reported by EXPLAIN ANALYZE, as
> CACHE_TUPLE_BYTES doesn't account for any of the MemoryChunks that are
> consumed by palloc. We're now doing 1 fewer palloc per tuple due to
> the removal of the palloc_object(MemoizeTuple) code, so more like 30%
> less memory for this case.
>
> Patch attached.
>
> David
> <v1-0001-Reduce-memory-overheads-for-storing-a-Memoize-tup.patch>
The optimized data structure looks good to me. The test result on my side
exactly matches yours: 3583kB vs. 2801kB. I had to turn off hash join,
otherwise the planner always chose a parallel hash join.
I have only one nitpick. MAXALIGN(sizeof(MinimalTuple)) appears 4 times. Would
it make sense to define a macro for it, say MEMOIZE_TUPLE_LINK_SIZE?
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/