Thread: BUG #5516: Memory grows up problem

BUG #5516: Memory grows up problem

From
"Yuhui"
Date:
The following bug has been logged online:

Bug reference:      5516
Logged by:          Yuhui
Email address:      xingyuhui@gmail.com
PostgreSQL version: 8.3,8.2,8.1
Operating system:   Linux,Windows
Description:        Memory grows up problem
Details:

Do the follow setp to reproduce the problem:
1,
CREATE TABLE mem_leak(A INT, B char(50) default 'abcdefg');
2,
INSERT INTO mem_leak(a) VALUES(generate_series(1,200000000));

The memory which the execution process occupation will grows larger and
larger until all the memory is gone or the process is over or the process is
killed by the os.
If in create table statementthe "B char(50)" is changed to "B varchar(50)"
or delete the "default 'abcdefg'" the memory will not grow anymore.

The problem is not happen in the 8.4 above version.

Re: BUG #5516: Memory grows up problem

From
Greg Stark
Date:
On Mon, Jun 21, 2010 at 12:41 PM, Yuhui <xingyuhui@gmail.com> wrote:
>
> The following bug has been logged online:
>
> Bug reference: =A0 =A0 =A05516
> Logged by: =A0 =A0 =A0 =A0 =A0Yuhui
> Email address: =A0 =A0 =A0xingyuhui@gmail.com
> PostgreSQL version: 8.3,8.2,8.1
> Operating system: =A0 Linux,Windows
> Description: =A0 =A0 =A0 =A0Memory grows up problem
> Details:
>
> Do the follow setp to reproduce the problem:
> 1,
> CREATE TABLE mem_leak(A INT, B char(50) default 'abcdefg');
> 2,
> INSERT INTO mem_leak(a) VALUES(generate_series(1,200000000));
>
> The memory which the execution process occupation will grows larger and
> larger until all the memory is gone or the process is over or the process=
 is
> killed by the os.

I'm afraid that just how set-returning-functions like
generate_series() worked prior to 8.4. They build a result set in
memory for all their result records.

> If in create table statementthe "B char(50)" is changed to "B varchar(50)"
> or delete the "default 'abcdefg'" the memory will not grow anymore.
>
> The problem is not happen in the 8.4 above version.

There are lots of improvements in each version. Not every one can be
back patched as a bug fix. Definitely not major api changes like this.


--=20
greg

Re: BUG #5516: Memory grows up problem

From
Tom Lane
Date:
Greg Stark <gsstark@mit.edu> writes:
> On Mon, Jun 21, 2010 at 12:41 PM, Yuhui <xingyuhui@gmail.com> wrote:
>> CREATE TABLE mem_leak(A INT, B char(50) default 'abcdefg');
>> INSERT INTO mem_leak(a) VALUES(generate_series(1,200000000));
>>
>> The memory which the execution process occupation will grows larger and
>> larger until all the memory is gone or the process is over or the process is
>> killed by the os.

> I'm afraid that just how set-returning-functions like
> generate_series() worked prior to 8.4. They build a result set in
> memory for all their result records.

No, there hasn't been any change in the SRF protocols.  The Result node
generating the VALUES() output would still leak memory, per this code:

    /*
     * Check to see if we're still projecting out tuples from a previous scan
     * tuple (because there is a function-returning-set in the projection
     * expressions).  If so, try to project another one.
     */
    if (node->ps.ps_TupFromTlist)
    {
        resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
        if (isDone == ExprMultipleResult)
            return resultSlot;
        /* Done with that source tuple... */
        node->ps.ps_TupFromTlist = false;
    }

    /*
     * Reset per-tuple memory context to free any expression evaluation
     * storage allocated in the previous tuple cycle.  Note this can't happen
     * until we're done projecting out tuples from a scan tuple.
     */
    ResetExprContext(econtext);

It's actually more surprising that current releases don't leak memory on
this example than that older ones do.  I traced through it and realized
that the reason for the change in behavior is that current versions
constant-fold the 'abcdefg'::char(50) expression, whereas before 8.4
it was left to be done at runtime.  That's per this comment in
preprocess_expression():

    /*
     * Simplify constant expressions.
     *
     * Note: an essential effect of this is to convert named-argument function
     * calls to positional notation and insert the current actual values of
     * any default arguments for functions.  To ensure that happens, we *must*
     * process all expressions here.  Previous PG versions sometimes skipped
     * const-simplification if it didn't seem worth the trouble, but we can't
     * do that anymore.
     */
    expr = eval_const_expressions(root, expr);

We're not likely to consider back-patching that change, since it's only
accidental that it fixes this case, and there are lots of related cases
it wouldn't fix.

The best workaround is to not rely on an SRF in the values list.
Instead do something like

INSERT INTO mem_leak(a) SELECT a FROM generate_series(1,2000000) a;

As long as the SRF is in FROM, you shouldn't have a problem.

            regards, tom lane