Freeing transient memory in aggregate functions

Started by Matt Magoffinover 4 years ago3 messagesgeneral
Jump to latest
#1Matt Magoffin
postgresql.org@msqr.us

I have a question about trying to keep memory from growing too much in a C aggregate function with pass-by-reference types. I am trying to keep track of a last-seen value in my aggregate state, so I have code roughly doing this:

Datum current;
MemoryContext aggContext;
AggCheckCallContext(fcinfo, &aggContext);
old = MemoryContextSwitchTo(aggContext);

if (!PG_ARGISNULL(0)) {
current = PG_GETARG_DATUM(0);
state->last = datumCopy(&current, typbyval, typlen);
}
MemoryContextSwitchTo(old);

I’m essentially doing a datumCopy() on every non-null input value. I was wondering if there is a way to free the previously copied datum, since I don’t really need it anymore? Something like

if (!PG_ARGISNULL(0)) {
current = PG_GETARG_DATUM(0);
if (state->last != NULL) {
pfree(state->last);
}
state->last = datumCopy(&current, typbyval, typlen);
}

I wasn’t sure it was allowed to call pfree() like this. My actual function is dealing with array input values, and for large sets of inputs I didn’t want to grow memory use as large as the entire data set being aggregated.

Kind regards,
Matt

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Matt Magoffin (#1)
Re: Freeing transient memory in aggregate functions

Matt Magoffin <postgresql.org@msqr.us> writes:

I’m essentially doing a datumCopy() on every non-null input value.

If you're doing that in the aggContext, you definitely need to free
the prior one(s).

I was wondering if there is a way to free the previously copied datum, since I don’t really need it anymore? Something like

if (state->last != NULL) {
pfree(state->last);
}

Not quite like that. Look into nodeAgg.c, which solves a similar problem
for the transvalues themselves with code like

/* forget the old value, if any */
if (!oldIsNull && !pertrans->inputtypeByVal)
pfree(DatumGetPointer(oldVal));

regards, tom lane

#3Matt Magoffin
postgresql.org@msqr.us
In reply to: Tom Lane (#2)
Re: Freeing transient memory in aggregate functions

On 21/12/2021, at 10:25 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Not quite like that. Look into nodeAgg.c, which solves a similar problem
for the transvalues themselves with code like

/* forget the old value, if any */
if (!oldIsNull && !pertrans->inputtypeByVal)
pfree(DatumGetPointer(oldVal));

Oh great, thanks for the tip!

— m@