FOR PORTION OF memory leak checking domains

From: Paul A Jungwirth <pj(at)illuminatedcomputing(dot)com>
To: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Cc: Tomas Vondra <tomas(at)vondra(dot)me>, Peter Eisentraut <peter(at)eisentraut(dot)org>
Subject: FOR PORTION OF memory leak checking domains
Date: 2026-09-04 23:14:21
Message-ID: CA+renyWRS01XFsjOUwZLsfF3093GXfav-6WPEj-RtkkVA2qOgw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi Hackers,

I received an off-list memory leak report from Tomas Vondra. Details below:

> CREATE DOMAIN leakdom AS daterange CHECK (VALUE IS NULL OR NOT
> isempty(VALUE));
>
> CREATE TABLE leak (id int, valid_at leakdom, name text);
> --CREATE TABLE leak (id int, valid_at daterange, name text);
>
> INSERT INTO leak
> SELECT g, daterange('2000-01-01','2010-01-01'), 'x'
> FROM generate_series(1, 200_000) g;
>
> SET log_executor_stats = on;
>
> UPDATE leak FOR PORTION OF valid_at FROM '2004-01-01' TO '2005-01-01'
> SET name = 'y';
> ---
>
> With the domain, I get this:
>
> DETAIL: ! system usage stats:
> ! 6.003382 s user, 1.508554 s system, 7.633776 s elapsed
> ! [6.724448 s user, 1.533475 s system total]
> ! 2633248 kB max resident size
> ! 0/74240 [0/114192] filesystem blocks in/out
> ! 0/646011 [0/651587] page faults/reclaims, 0 [0] swaps
> ! 0 [0] signals rcvd, 0/0 [0/0] messages rcvd/sent
> ! 13/309 [31/354] voluntary/involuntary context switches
>
> while with the plain daterange I get
>
> DETAIL: ! system usage stats:
> ! 3.857666 s user, 0.071827 s system, 4.046457 s elapsed
> ! [4.517879 s user, 0.114015 s system total]
> ! 79060 kB max resident size
> ! 0/92096 [0/149952] filesystem blocks in/out
> ! 0/7674 [0/14166] page faults/reclaims, 0 [0] swaps
> ! 0 [0] signals rcvd, 0/0 [0/0] messages rcvd/sent
> ! 23/130 [39/159] voluntary/involuntary context switches
>
> That's ~2.6GB vs. ~80MB for the RSS, which seems like a lot. It can be
> made worse by using more rows in the table.
>
> AFAIK the issues is in nodeModifyTable.c, which does this:
>
> /*
> * Does the new Datum violate domain checks? Row-level CHECK
> * constraints are validated by ExecInsert, so we don't need to do
> * anything here for those.
> */
> if (forPortionOf->isDomain)
> domain_check(leftover, false, forPortionOf->rangeVar->vartype,
> NULL, NULL);
>
> where the NULLs mean it's running with CurrentMemoryContext, which is
> es_query_ctx. And hence the query-wide leak.
>
> domain_check() has a way to cache stuff once - that's what the extra
> argument is about. I don't know enough about this code, maybe it could
> be a local scratch space, but maybe it'd be better to add it to the FPO
> executor state:
>
> /* src/include/nodes/execnodes.h — ForPortionOfState */
> void *fp_domaininfo; /* cache space for domain_check() */
>
> and call it like this:
>
> if (forPortionOf->isDomain)
> domain_check(leftover, false, forPortionOf->rangeVar->vartype,
> &fpoState->fp_domaininfo, NULL);

I agree that is clearly a leak. His fix works and makes the memory
usage consistent between the domain and non-domain cases. My only
change to the above is to pass estate->es_query_cxt explicitly instead
of assuming it's already the CurrentMemoryContext. I also added a test
with a multi-row domain FOR PORTION OF update to validate that the
caching functions correctly.

Yours,

--
Paul ~{:-)
pj(at)illuminatedcomputing(dot)com

Attachment Content-Type Size
v1-0001-Fix-memory-leak-in-FOR-PORTION-OF-domain-lookup.patch text/x-patch 6.3 KB

Browse pgsql-hackers by date

  From Date Subject
Next Message Si, Evan 2026-09-04 23:20:27 Re: Add ssl_(supported|shared)_groups to sslinfo
Previous Message Bharath Rupireddy 2026-09-04 23:13:42 Re: REPACK (CONCURRENTLY) doesn't check the table AM