Everything leaks; How it mm suppose to work?

Started by Maurice Gittensalmost 28 years ago16 messages
#1Maurice Gittens
mgittens@david.gits.nl

Hi,

I added these lines to tcop/postgres.c just before the ReadCommand call
(which is in an infinite loop).

+ 		printf("Allocount: %ld; FreeCount: %ld; Diff:%ld\n", 
+ 				getPAllocCount(),
+ 				getPFreeCount(),
+ 				getPAllocCount() - getPFreeCount());
+ 

And the following lines to mmgr/palloc.c

+ static long pallocCount = 0;
+ static long pfreeCount = 0;
+ 
+ long getPAllocCount()
+ {
+ 	return pallocCount;
+ }
+ 
+ long getPFreeCount()
+ {
+ 	return pfreeCount;
+ }

void *
palloc(Size size)
{
+ pallocCount++;
...

void
pfree(void *pointer)
{
+ pfreeCount++;
...

Running postgresql in interactive mode shows that for each query I
type there is memory lost. The exact amount of memory lost depends on
the query I use. The amount of memory not freed is also a function
of the number of tuples returned.

Now I'm hoping there is an easy way to find out about how this is _supposed_
to work. Any one feel like giving a nice little explanation?

Thanks, with regards from Maurice.

#2Bruce Momjian
maillist@candle.pha.pa.us
In reply to: Maurice Gittens (#1)
Re: [HACKERS] Everything leaks; How it mm suppose to work?

Hi,

I added these lines to tcop/postgres.c just before the ReadCommand call
(which is in an infinite loop).

+ 		printf("Allocount: %ld; FreeCount: %ld; Diff:%ld\n", 
+ 				getPAllocCount(),
+ 				getPFreeCount(),
+ 				getPAllocCount() - getPFreeCount());
+ 

And the following lines to mmgr/palloc.c

+ static long pallocCount = 0;
+ static long pfreeCount = 0;
+ 
+ long getPAllocCount()
+ {
+ 	return pallocCount;
+ }
+ 
+ long getPFreeCount()
+ {
+ 	return pfreeCount;
+ }

void *
palloc(Size size)
{
+ pallocCount++;
...

void
pfree(void *pointer)
{
+ pfreeCount++;
...

Running postgresql in interactive mode shows that for each query I
type there is memory lost. The exact amount of memory lost depends on
the query I use. The amount of memory not freed is also a function
of the number of tuples returned.

Now I'm hoping there is an easy way to find out about how this is _supposed_
to work. Any one feel like giving a nice little explanation?

Thanks, with regards from Maurice.

The way I was looking at it was to first find the context that is
loosing the memory. I called AllocSetDump(GlobalMemory->setData) to
dump out the allocated memory pointers. The problem is that only
certain ones are do-able, as portals each have their own context, I
think, and there is no macro that enables all the memory debugging
operations.

Not sure how to proceed.

-- 
Bruce Momjian                          |  830 Blythe Avenue
maillist@candle.pha.pa.us              |  Drexel Hill, Pennsylvania 19026
  +  If your life is a hard drive,     |  (610) 353-9879(w)
  +  Christ can be your backup.        |  (610) 853-3000(h)
#3Maurice Gittens
mgittens@gits.nl
In reply to: Bruce Momjian (#2)
Re: [HACKERS] Everything leaks; How it mm suppose to work?

Running postgresql in interactive mode shows that for each query I
type there is memory lost. The exact amount of memory lost depends on
the query I use. The amount of memory not freed is also a function
of the number of tuples returned.

Oops, it seems some palloced memory is not freed by pfree but
using some other function(s).
My mistake, sorry.

Thanks, with regards from Maurice.

#4Noname
dg@illustra.com
In reply to: Maurice Gittens (#1)
Re: [HACKERS] Everything leaks; How it mm suppose to work?

Hi,

I added these lines to tcop/postgres.c just before the ReadCommand call
(which is in an infinite loop).

+ 		printf("Allocount: %ld; FreeCount: %ld; Diff:%ld\n", 
+ 				getPAllocCount(),
+ 				getPFreeCount(),
+ 				getPAllocCount() - getPFreeCount());
+ 

And the following lines to mmgr/palloc.c

+ static long pallocCount = 0;
+ static long pfreeCount = 0;
+ 
+ long getPAllocCount()
+ {
+ 	return pallocCount;
+ }
+ 
+ long getPFreeCount()
+ {
+ 	return pfreeCount;
+ }

void *
palloc(Size size)
{
+ pallocCount++;
...

void
pfree(void *pointer)
{
+ pfreeCount++;
...

Running postgresql in interactive mode shows that for each query I
type there is memory lost. The exact amount of memory lost depends on
the query I use. The amount of memory not freed is also a function
of the number of tuples returned.

Now I'm hoping there is an easy way to find out about how this is _supposed_
to work. Any one feel like giving a nice little explanation?

Thanks, with regards from Maurice.

The term "getPAllocCount() - getPFreeCount())" returns the amount of
memory not explicitly freed. The rest of the memory was (probably) released
by MemoryContextDestroy() when the context went out of scope.

This is normal behavior under the current scheme.

-dg

David Gould dg@illustra.com 510.628.3783 or 510.305.9468
Informix Software (No, really) 300 Lakeside Drive Oakland, CA 94612
If simplicity worked, the world would be overrun with insects.

#5Edwin S. Ramirez
ramirez@doc.mssm.edu
In reply to: Noname (#4)
Problem with 6.3.1 under Linux RH5.0

Hello,

I recall reading about a problem with subselects taking a long time to
return. I am experiencing similar problems under 6.3.1 running on Linux
RedHat5.0. The tables only contains approx 2k records and the command
ran for about 10 minutes.

Thanks,

Edwin Ramirez

#6Bruce Momjian
maillist@candle.pha.pa.us
In reply to: Maurice Gittens (#3)
Re: [HACKERS] Everything leaks; How it mm suppose to work?

Running postgresql in interactive mode shows that for each query I
type there is memory lost. The exact amount of memory lost depends on
the query I use. The amount of memory not freed is also a function
of the number of tuples returned.

Oops, it seems some palloced memory is not freed by pfree but
using some other function(s).
My mistake, sorry.

One thing I have found is that:

select * from test where 1=0;

do not leak memory while

select * from test where x=-999;

does leak memory, even though neither returns any rows. Strange. Would
seem to point to the optimizer or executor.

-- 
Bruce Momjian                          |  830 Blythe Avenue
maillist@candle.pha.pa.us              |  Drexel Hill, Pennsylvania 19026
  +  If your life is a hard drive,     |  (610) 353-9879(w)
  +  Christ can be your backup.        |  (610) 853-3000(h)
#7Bruce Momjian
maillist@candle.pha.pa.us
In reply to: Maurice Gittens (#3)
Re: [HACKERS] Everything leaks; How it mm suppose to work?

Running postgresql in interactive mode shows that for each query I
type there is memory lost. The exact amount of memory lost depends on
the query I use. The amount of memory not freed is also a function
of the number of tuples returned.

Oops, it seems some palloc'ed memory is not freed by pfree() but
using some other function(s).
My mistake, sorry.

OK, I think I know where the leak is from. I checked AllocSetDump(), and
it did not show any problems with any context growing, so I started to
suspect direct calls to malloc(). I tried trapping on malloc(), but
there are too many calls.

Then I ran profiling on the two queries I mentioned, where one leaks and
one doesn't, and found that the leaking one had 500 extra calls to
malloc. Grep'ing out the calls and comparing the output of the two
profiles, I found:

0.00 0.00 1/527 ___irs_gen_acc [162]
0.00 0.00 35/527 _GetDatabasePath [284]
0.00 0.00 491/527 _GetDatabaseName [170]
[166]: 0.8 0.00 0.00 527 _strdup [166] 0.00 0.00 527/2030 _malloc [105] 0.00 0.00 527/604 _strlen [508] 0.00 0.00 527/532 _bcopy [515]
0.00 0.00 527/2030 _malloc [105]
0.00 0.00 527/604 _strlen [508]
0.00 0.00 527/532 _bcopy [515]

I believe this code was modified by Vadim to fix our problem with blind
write errors when using psql while the regression tests were being run.

Am I correct on this? I have not developed a fix yet.

-- 
Bruce Momjian                          |  830 Blythe Avenue
maillist@candle.pha.pa.us              |  Drexel Hill, Pennsylvania 19026
  +  If your life is a hard drive,     |  (610) 353-9879(w)
  +  Christ can be your backup.        |  (610) 853-3000(h)
#8Noname
darrenk@insightdist.com
In reply to: Bruce Momjian (#7)
Re: [HACKERS] Everything leaks; How it mm suppose to work?

Running postgresql in interactive mode shows that for each query I
type there is memory lost. The exact amount of memory lost depends on
the query I use. The amount of memory not freed is also a function
of the number of tuples returned.

Oops, it seems some palloc'ed memory is not freed by pfree() but
using some other function(s).
My mistake, sorry.

OK, I think I know where the leak is from. I checked AllocSetDump(), and
it did not show any problems with any context growing, so I started to
suspect direct calls to malloc(). I tried trapping on malloc(), but
there are too many calls.

Then I ran profiling on the two queries I mentioned, where one leaks and
one doesn't, and found that the leaking one had 500 extra calls to
malloc. Grep'ing out the calls and comparing the output of the two
profiles, I found:

0.00 0.00 1/527 ___irs_gen_acc [162]
0.00 0.00 35/527 _GetDatabasePath [284]
0.00 0.00 491/527 _GetDatabaseName [170]
[166] 0.8 0.00 0.00 527 _strdup [166]
0.00 0.00 527/2030 _malloc [105]
0.00 0.00 527/604 _strlen [508]
0.00 0.00 527/532 _bcopy [515]

I believe this code was modified by Vadim to fix our problem with blind
write errors when using psql while the regression tests were being run.

Am I correct on this? I have not developed a fix yet.

How about changing the strdup()'s in src/backend/utils/init/miscinit.c to
the pstrdup() that is in palloc.c so the memory is palloc()/pfree()'d?

I seem to recall a discussion a long time ago about using strdup and how
it would leak when using the postgres memory contexts, and that the pstrdup
code was created to be used instead of strdup to "fix" this.

darrenk

#9Vadim B. Mikheev
vadim@sable.krasnoyarsk.su
In reply to: Bruce Momjian (#7)
Re: [HACKERS] Everything leaks; How it mm suppose to work?

Bruce Momjian wrote:

Then I ran profiling on the two queries I mentioned, where one leaks and
one doesn't, and found that the leaking one had 500 extra calls to
malloc. Grep'ing out the calls and comparing the output of the two
profiles, I found:

0.00 0.00 1/527 ___irs_gen_acc [162]
0.00 0.00 35/527 _GetDatabasePath [284]
0.00 0.00 491/527 _GetDatabaseName [170]
[166] 0.8 0.00 0.00 527 _strdup [166]
0.00 0.00 527/2030 _malloc [105]
0.00 0.00 527/604 _strlen [508]
0.00 0.00 527/532 _bcopy [515]

I believe this code was modified by Vadim to fix our problem with blind
write errors when using psql while the regression tests were being run.

Am I correct on this? I have not developed a fix yet.

Only src/backend/storage/smgr/md.c:mdblindwrt() was changed...

Vadim

#10Noname
dg@illustra.com
In reply to: Bruce Momjian (#6)
Re: [HACKERS] Everything leaks; How it mm suppose to work?

Bruce:

Maurice:

Running postgresql in interactive mode shows that for each query I
type there is memory lost. The exact amount of memory lost depends on
the query I use. The amount of memory not freed is also a function
of the number of tuples returned.

Oops, it seems some palloced memory is not freed by pfree but
using some other function(s).
My mistake, sorry.

One thing I have found is that:

select * from test where 1=0;

do not leak memory while

select * from test where x=-999;

does leak memory, even though neither returns any rows. Strange. Would
seem to point to the optimizer or executor.

In the first case, the where clause is constant and evaluates false, so
not much is done. In the second case, the table is scanned and presumably
some memory is allocated for each row, probably to evaluate the expression.
Since this memory is allocated into a per statement duration, it will not
be freed until the end of the statement when the context is destroyed.

-dg

David Gould dg@illustra.com 510.628.3783 or 510.305.9468
Informix Software (No, really) 300 Lakeside Drive Oakland, CA 94612
- Linux. Not because it is free. Because it is better.

#11Massimo Dal Zotto
dz@cs.unitn.it
In reply to: Noname (#10)
Re: [HACKERS] Everything leaks; How it mm suppose to work?

Bruce:

Maurice:

Running postgresql in interactive mode shows that for each query I
type there is memory lost. The exact amount of memory lost depends on
the query I use. The amount of memory not freed is also a function
of the number of tuples returned.

Oops, it seems some palloced memory is not freed by pfree but
using some other function(s).
My mistake, sorry.

One thing I have found is that:

select * from test where 1=0;

do not leak memory while

select * from test where x=-999;

does leak memory, even though neither returns any rows. Strange. Would
seem to point to the optimizer or executor.

In the first case, the where clause is constant and evaluates false, so
not much is done. In the second case, the table is scanned and presumably
some memory is allocated for each row, probably to evaluate the expression.
Since this memory is allocated into a per statement duration, it will not
be freed until the end of the statement when the context is destroyed.

-dg

Does it make sense to have a 'row' context which is released just before
starting with a new tuple ? The total number or free is the same but they
are distributed over the query and unused memory should not accumulate.
I have seen backends growing to 40-60MB with queries which scan a very
large number of rows.

Massimo Dal Zotto

+----------------------------------------------------------------------+
|  Massimo Dal Zotto                e-mail:  dz@cs.unitn.it            |
|  Via Marconi, 141                 phone:  ++39-461-534251            |
|  38057 Pergine Valsugana (TN)     www:  http://www.cs.unitn.it/~dz/  |
|  Italy                            pgp:  finger dz@tango.cs.unitn.it  |
+----------------------------------------------------------------------+
#12Maurice Gittens
mgittens@gits.nl
In reply to: Massimo Dal Zotto (#11)
Re: [HACKERS] Everything leaks; How it mm suppose to work?

Does it make sense to have a 'row' context which is released just before
starting with a new tuple ? The total number or free is the same but they
are distributed over the query and unused memory should not accumulate.
I have seen backends growing to 40-60MB with queries which scan a very
large number of rows.

I think this would be appropiate.

With regards from Maurice.

#13Thomas G. Lockhart
lockhart@alumni.caltech.edu
In reply to: Maurice Gittens (#12)
Re: [HACKERS] Everything leaks; How it mm suppose to work?

Does it make sense to have a 'row' context which is released just
before starting with a new tuple ? The total number or free is the
same but they are distributed over the query and unused memory should
not accumulate.
I have seen backends growing to 40-60MB with queries which scan a
very large number of rows.

I think this would be appropiate.

It seems that the CPU overhead on all queries would increase trying to
deallocate/reuse memory during the query. There are lots of places in
the backend where memory is palloc'd and then left lying around after
use; I had assumed it was sort-of-intentional to avoid having extra
cleanup overhead during a query.

- Tom

#14Bruce Momjian
maillist@candle.pha.pa.us
In reply to: Noname (#10)
Re: [HACKERS] Everything leaks; How it mm suppose to work?

Bruce:

Maurice:

Running postgresql in interactive mode shows that for each query I
type there is memory lost. The exact amount of memory lost depends on
the query I use. The amount of memory not freed is also a function
of the number of tuples returned.

Oops, it seems some palloced memory is not freed by pfree but
using some other function(s).
My mistake, sorry.

One thing I have found is that:

select * from test where 1=0;

do not leak memory while

select * from test where x=-999;

does leak memory, even though neither returns any rows. Strange. Would
seem to point to the optimizer or executor.

In the first case, the where clause is constant and evaluates false, so
not much is done. In the second case, the table is scanned and presumably
some memory is allocated for each row, probably to evaluate the expression.
Since this memory is allocated into a per statement duration, it will not
be freed until the end of the statement when the context is destroyed.

This will be fixed in the 6.3.2 patch, due out soon.

-- 
Bruce Momjian                          |  830 Blythe Avenue
maillist@candle.pha.pa.us              |  Drexel Hill, Pennsylvania 19026
  +  If your life is a hard drive,     |  (610) 353-9879(w)
  +  Christ can be your backup.        |  (610) 853-3000(h)
#15Vadim B. Mikheev
vadim@sable.krasnoyarsk.su
In reply to: Maurice Gittens (#12)
Re: [HACKERS] Everything leaks; How it mm suppose to work?

Thomas G. Lockhart wrote:

Does it make sense to have a 'row' context which is released just
before starting with a new tuple ? The total number or free is the
same but they are distributed over the query and unused memory should
not accumulate.
I have seen backends growing to 40-60MB with queries which scan a
very large number of rows.

I think this would be appropiate.

It seems that the CPU overhead on all queries would increase trying to
deallocate/reuse memory during the query. There are lots of places in
the backend where memory is palloc'd and then left lying around after
use; I had assumed it was sort-of-intentional to avoid having extra
cleanup overhead during a query.

This problem (introduced in 6.3) is already fixed by Bruce - will be
in 6.3.2

Vadim

#16Noname
dg@illustra.com
In reply to: Thomas G. Lockhart (#13)
Re: [HACKERS] Everything leaks; How it mm suppose to work?

Thomas G. Lockhart replies to Maurice:

Does it make sense to have a 'row' context which is released just
before starting with a new tuple ? The total number or free is the
same but they are distributed over the query and unused memory should
not accumulate.
I have seen backends growing to 40-60MB with queries which scan a
very large number of rows.

I think this would be appropiate.

It seems that the CPU overhead on all queries would increase trying to
deallocate/reuse memory during the query. There are lots of places in
the backend where memory is palloc'd and then left lying around after
use; I had assumed it was sort-of-intentional to avoid having extra
cleanup overhead during a query.

This is exactly right. Destroying a memory context in the current
implementationis a very high overhead operation. Doing it once per row
would be a performance disaster.

-dg

David Gould dg@illustra.com 510.628.3783 or 510.305.9468
Informix Software (No, really) 300 Lakeside Drive Oakland, CA 94612
- Linux. Not because it is free. Because it is better.