Home > Archive > Unix Programming > January 2008 > Does ever growing SZ from ps indicate memory leak?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Does ever growing SZ from ps indicate memory leak?
|
|
| apm35@student.open.ac.uk 2008-01-16, 7:12 pm |
| According to man, SZ is:
The total size of the process in virtual memory,
including all mapped files and devices, in pages
where on my system (solaris 8) a page is 8K.
But this does not tell me all that I need to know. I used to think
that SZ was the amount of heap storage used, as allocated typically
(but not exclusively) through malloc. But I am not sure now. I
originally assumed that no matter how many malloc and frees were done,
if they all matched and the app did not leak then SZ would not show an
ongoing upward trend. I think I need to understand more about SZ so I
have come here for help please.
Here's why I am not sure: I have a java program, a server, that uses
SWIG/JNI to talk to a C wrapper which in turn talks to a third-party C
API. I have been using ps to monitor the value of SZ over time in the
hope of spotting any memory leak. I am also using JMX via jconsole to
examine the java heap as mgd by the JVM. Jconsole tells me that the
heap is periodically GCd with a series of relatively frequent minor GC
efforts and a more major GC effort every two hours or so. It basically
says there are no leaks. But the value of SZ keeps going up. There are
fluctuations and one has to see the ps results over a 24 hour period
to see the overall trend. The trend is a slow climb of around 500
pages followed by a sharp spike every few hours of between 500 to 1500
pages. The overall effect is a definate upward trend with an average
growth of 1 MB per hour.
When I only had figures for the first hour or so and I saw a spike I
figured that because the values after the spike had gone down maybe
there weren't any leaks and any outstanding memory would be reclaimed
eventually. But the climb of SZ is relentless. It is one of the
biggest processes on the machine now and this has me worried.
Regards,
Andrew Marlow
| |
| Paul Pluzhnikov 2008-01-16, 7:12 pm |
| apm35@student.open.ac.uk writes:
> According to man, SZ is:
> The total size of the process in virtual memory,
> including all mapped files and devices, in pages
> where on my system (solaris 8) a page is 8K.
>
> But this does not tell me all that I need to know. I used to think
> that SZ was the amount of heap storage used, as allocated typically
> (but not exclusively) through malloc.
Your thinking was obviously incorrect: there are many other ways
to obtain storage from the system, and most of them affect SZ.
> I originally assumed that no matter how many malloc and frees were done,
> if they all matched and the app did not leak then SZ would not show an
> ongoing upward trend.
Correct, assuming the application doesn't anything other than
malloc/free.
> The overall effect is a definate upward trend with an average
> growth of 1 MB per hour.
So your application either has a leak, or contains a data structure
which keeps growing (which is different from a leak, but may be a
problem nonetheless).
> But the climb of SZ is relentless. It is one of the
> biggest processes on the machine now and this has me worried.
So, what is your question?
If you observe a 1MB/h growth over extended period of time, and if
such rate of growh is unacceptable to you (e.g. because you expect
the server to stay up for 1 year, and the system doesn't have extra
8GB of RAM), then contact developers and ask them to do something
about it.
Cheers,
--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
| |
| apm35@student.open.ac.uk 2008-01-17, 8:11 am |
| On 16 Jan, 22:49, Paul Pluzhnikov <ppluzhnikov-...@gmail.com> wrote:
>
> Your thinking was obviously incorrect: there are many other ways
> to obtain storage from the system, and most of them affect SZ.
Hmm, this is what I wondered so I came here for more information. Can
you tell me more please?
>
> Correct, assuming the application doesn't anything other than
> malloc/free.
I don't understand. The app does plently more. Do you mean the app
might do other allocations such as using sbrk? Please explain.
>
> So your application either has a leak, or contains a data structure
> which keeps growing (which is different from a leak, but may be a
> problem nonetheless).
Well, this is what I came here to check.
>
>
> So, what is your question?
My question is "does a slow but relentless climb of SZ indicate a
memory leak?". Sounds like the answer is "yes".
> If you observe a 1MB/h growth over extended period of time
I do.
> and if
> such rate of growh is unacceptable to you
It is.
> (e.g. because you expect
> the server to stay up for 1 year, and the system doesn't have extra
> 8GB of RAM), then contact developers and ask them to do something
> about it.
Er, I *am* the developer <ahem>. I am new to java but have been using C
++ for years. In C++ I can use purify to track down memory leaks but
not in java-land. I have been using JMX jconsole but this seems to
indicate there are no leaks. The graph of heap memory is a saw-tooth
as the GC kicks in every now and then. I thought I would use SZ from
ps as well as JMX since this java app is also calling a third-party C
API via SWIG-JNI.
Regards,
Andrew Marlow
| |
| Syren Baran 2008-01-17, 8:11 am |
| apm35@student.open.ac.uk schrieb:
> On 16 Jan, 22:49, Paul Pluzhnikov <ppluzhnikov-...@gmail.com> wrote:
> Er, I *am* the developer <ahem>. I am new to java but have been using C
> ++ for years.
Its pretty hard to "leak" memory in java. Practicly the only way to
consume more memory over time is bad design,e.g. you forget to derefence
unused objects (garbage collection does the rest), and Threads. If
Threads got started by a no longer referenced object they WONT be
garbage collected. Even after a couple of years of doing java thats the
only reason i ever found to use the finalize method (the equivalent of a
c++ destructor).
In C++ I can use purify to track down memory leaks but
> not in java-land. I have been using JMX jconsole but this seems to
> indicate there are no leaks.
Technicly there is no such thing as a memory leak in java.
The graph of heap memory is a saw-tooth
> as the GC kicks in every now and then. I thought I would use SZ from
> ps as well as JMX since this java app is also calling a third-party C
> API via SWIG-JNI.
I would check if the number of Threads you use is continously growing.
>
> Regards,
>
> Andrew Marlow
| |
| Scott Lurndal 2008-01-17, 7:14 pm |
| apm35@student.open.ac.uk writes:
>
>Er, I *am* the developer <ahem>. I am new to java but have been using C
>++ for years. In C++ I can use purify to track down memory leaks but
>not in java-land. I have been using JMX jconsole but this seems to
>indicate there are no leaks. The graph of heap memory is a saw-tooth
>as the GC kicks in every now and then. I thought I would use SZ from
>ps as well as JMX since this java app is also calling a third-party C
>API via SWIG-JNI.
>
when you fire up the JVM, typically one provides two arguments consisting
of an initial and maximum amount of memory. The JVM will grow up to the
maximum and not beyond over time. It will never get smaller.
If it's too large, adjust the maximum value -Xmx
(http://java.sun.com/j2se/1.4.2/docs...ndows/java.html)
scott
| |
| Barry Margolin 2008-01-18, 10:13 pm |
| User-Agent: MT-NewsWatcher/3.5.3b2 (PPC Mac OS X)
X-Copies-To: never
Date: Fri, 18 Jan 2008 22:29:14 -0500
Message-ID: <barmar-1B3F00.22291418012008@comcast.dca.giganews.com>
Lines: 30
X-Usenet-Provider: http://www.giganews.com
NNTP-Posting-Host: 24.34.108.171
X-Trace: sv3-TYUEW8BVNRZIBplguho33RcWFroJw/ KPbC6FsEcGskLqUzkN8C5DCeWQGdAsljNddnj+19
Si+oR4q4B!w73y5YeY7mGHNTqjuZkiXw1WBStehW
IBKoPqDPFzTT1fdDYLPhVcHo5qMog8335Sb2kBcZ
dcSHn9!hiwuupT60j0jWmW7zxUNzaOahYEOaNkA+
VMEgE4yYw==
X-Complaints-To: abuse@comcast.net
X-DMCA-Complaints-To: dmca@comcast.net
X-Abuse-and-DMCA-Info: Please be sure to forward a copy of ALL headers
X-Abuse-and-DMCA-Info: Otherwise we will be unable to process your complaint properly
X-Postfilter: 1.3.37
Bytes: 2892
Xref: number1.nntp.dca.giganews.com comp.unix.programmer:183438
In article <478f4321$0$27204$9b4e6d93@newsspool1.arcor-online.net>,
Syren Baran <syren@gmx.de> wrote:
> apm35@student.open.ac.uk schrieb:
> Its pretty hard to "leak" memory in java. Practicly the only way to
> consume more memory over time is bad design,e.g. you forget to derefence
> unused objects (garbage collection does the rest), and Threads. If
> Threads got started by a no longer referenced object they WONT be
> garbage collected. Even after a couple of years of doing java thats the
> only reason i ever found to use the finalize method (the equivalent of a
> c++ destructor).
> In C++ I can use purify to track down memory leaks but
> Technicly there is no such thing as a memory leak in java.
If you mean objects that can't be accessed, like if you forget to free()
something in C before reassigning the pointer, that's true. But more
practically, you effectively have a memory leak if you have objects that
can be guaranteed will never be accessed, i.e. they're taking up memory
unnecessarily.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
| |
| Logan Shaw 2008-01-19, 7:12 pm |
| Barry Margolin wrote:
> In article <478f4321$0$27204$9b4e6d93@newsspool1.arcor-online.net>,
> Syren Baran <syren@gmx.de> wrote:
[color=darkred]
> If you mean objects that can't be accessed, like if you forget to free()
> something in C before reassigning the pointer, that's true. But more
> practically, you effectively have a memory leak if you have objects that
> can be guaranteed will never be accessed, i.e. they're taking up memory
> unnecessarily.
To clarify, you're making a distinction between objects that *will*
never be reached vs. objects that *can* never be reached. That is,
if a path exists to reach the object through some data structure
but you can guarantee the code will never use that path even though
the path does exist, you're calling that a memory leak.
I tend to agree, although the terminology is a little ambiguous
and I wouldn't begrudge someone a desire to make the distinction
and reserve "memory leak" exclusively for describing the situation
where the memory *cannot* be reached. (On the other hand, once you
take into account that data structures' semantics are entirely
determined by the code that will access them[1], I suppose that
muddies the waters a bit and makes it harder to always make that
distinction clearly, but that's a side issue.)
- Logan
[1] I can XOR all my pointers with some random constant before I
store them and then XOR them back when I want to use them,
and with a naive look at the data structures, it might appear
that some memory is "unreachable". But it is reachable if
you know the "XOR trick". What matters is what loads and
stores the code will actually perform when it runs.
| |
| Syren Baran 2008-01-19, 7:12 pm |
| Barry Margolin schrieb:
>
> If you mean objects that can't be accessed, like if you forget to free()
> something in C before reassigning the pointer, that's true. But more
> practically, you effectively have a memory leak if you have objects that
> can be guaranteed will never be accessed, i.e. they're taking up memory
> unnecessarily.
Sure, the practical implications are similiar.
But its still two very distinctly different errors. Once the last
pointer has been reassigned the memory is leaked (barring wild guesses
two where the pointers could have pointed to). This is a definite
statement. On there other hand there is no way to distinguish an object
that has not been used for a long time from an object which is garanteed
to never be accesed again.
The first error is not recoverable to the lifetime of the application,
the later is.
To give a somewhat exagerated example. If an application forgets a
couple of free?s it will use more and more memory over time. If i use
the same application to open a document/file/webpage/whatsoever that i
can garantee i will never use again, is this leaked memory? After all,
the app uses more memory than it should.
Now how do free this memory? Close the app and restart? Or just close
the tab? With leaked memory i need a restart, with unused objects theres
lots of possibilities, e.g. some manual interface to reclaim this memory
or send a signal to app.
Sure, the wouldnt be a visible difference between an app that can
recover unused memory and an app with leaked memory that can sync its
contents to disk and restart.
Maybe i?m really overreacting a bit about a destinction that has little
to no practical implications.
My definition something like this.
Leaked memory can not be recovered during the life cycle of the
application. It is a programming error that can be analysed from an
other application.
Wasted memory can be recovered. It is a design error and is not
distingishable from other memory.
Well, if you started coding on more or less OS-less boxes with little to
no memory management you might be as pedantic as well ;)
| |
| Barry Margolin 2008-01-19, 10:15 pm |
| In article <47926cbd$0$5102$4c368faf@roadrunner.com>,
Logan Shaw <lshaw-usenet@austin.rr.com> wrote:
> Barry Margolin wrote:
>
>
>
> To clarify, you're making a distinction between objects that *will*
> never be reached vs. objects that *can* never be reached. That is,
> if a path exists to reach the object through some data structure
> but you can guarantee the code will never use that path even though
> the path does exist, you're calling that a memory leak.
>
> I tend to agree, although the terminology is a little ambiguous
> and I wouldn't begrudge someone a desire to make the distinction
> and reserve "memory leak" exclusively for describing the situation
> where the memory *cannot* be reached. (On the other hand, once you
> take into account that data structures' semantics are entirely
> determined by the code that will access them[1], I suppose that
> muddies the waters a bit and makes it harder to always make that
> distinction clearly, but that's a side issue.)
So if you don't use the term "memory leak", what's the terminology for
running out of memory because you retain references to lots of data that
you never need to reference?
And if both situations cause you to run out of memory, why is it
important to distinguish the terms? The main difference is that one
kind of leak can't happen in a GC'ed language.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
| |
| Logan Shaw 2008-01-20, 7:16 pm |
| Barry Margolin wrote:
> So if you don't use the term "memory leak", what's the terminology for
> running out of memory because you retain references to lots of data that
> you never need to reference?
>
> And if both situations cause you to run out of memory, why is it
> important to distinguish the terms? The main difference is that one
> kind of leak can't happen in a GC'ed language.
I don't know that it is useful to distinguish the terms. I do think
that based on my observations, a lot of people use the terminology
in a way that indicates they are making that distinction. And language
being based mainly on convention, that seems significant. At least
something to be aware of (if I have observed correctly).
- Logan
| |
| Rainer Weikusat 2008-01-20, 7:16 pm |
| Barry Margolin <barmar@alum.mit.edu> writes:
> Logan Shaw <lshaw-usenet@austin.rr.com> wrote:
[...]
>
> So if you don't use the term "memory leak", what's the terminology for
> running out of memory because you retain references to lots of data that
> you never need to reference?
>
> And if both situations cause you to run out of memory, why is it
> important to distinguish the terms? The main difference is that one
> kind of leak can't happen in a GC'ed language.
The second situation doesn't exist: Everything which is part of the
address space of a process is by definition 'reachable'. That's what
makes it part of this address space.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
unsigned long ul;
printf("%lu\n", (unsigned long)malloc(3));
fputs("please enter the value printed: ", stdout);
scanf("%lu", &ul);
free((void *)ul);
return 0;
}
At least for objects with indefinite extent (ie dynamically allocated
objects), 'garbage collection' is basically just a smokescreen:
Instead of freeing the memory after the object is no longer needed,
all references to the object must be 'cut' after it is no longer
needed, to enable the garbage collector to 'automatically' free the
memory. For sufficiently complex code, this is even more cumbersome
than 'manual freeing', because it is possible to just free an object
while pointer pointing to it still exist, but an object will be
considered 'garbage' while it is still referenced, which means that,
instead of calling a single subroutine at the 'right' time, n
references potentially scattered all across the various data
structures of some program need to be remembered and invalidated
(alternatively, each references must be invalidated immediatly once it
is no longer needed, which resembles malloc'n'free even more closely).
This is, of course, a heavily simplified description to express the
basic idea clearer.
| |
| Rainer Weikusat 2008-01-20, 7:16 pm |
| Barry Margolin <barmar@alum.mit.edu> writes:
> Logan Shaw <lshaw-usenet@austin.rr.com> wrote:
[...]
>
> So if you don't use the term "memory leak", what's the terminology for
> running out of memory because you retain references to lots of data that
> you never need to reference?
>
> And if both situations cause you to run out of memory, why is it
> important to distinguish the terms? The main difference is that one
> kind of leak can't happen in a GC'ed language.
The second situation doesn't exist: Everything which is part of the
address space of a process is by definition 'reachable'. That's what
makes it part of this address space.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
unsigned long ul;
printf("%lu\n", (unsigned long)malloc(3));
fputs("please enter the value printed: ", stdout);
scanf("%lu", &ul);
free((void *)ul);
return 0;
}
At least for objects with indefinite extent (ie dynamically allocated
objects), 'garbage collection' is basically just a smokescreen:
Instead of freeing the memory after the object is no longer needed,
all references to the object must be 'cut' after it is no longer
needed, to enable the garbage collector to 'automatically' free the
memory. For sufficiently complex code, this is even more cumbersome
than 'manual freeing', because it is possible to just free an object
while pointer pointing to it still exist, but an object will not be
considered 'garbage' while it is still referenced, which means that,
instead of calling a single subroutine at the 'right' time, n
references potentially scattered all across the various data
structures of some program need to be remembered and invalidated
(alternatively, each references must be invalidated immediatly once it
is no longer needed, which resembles malloc'n'free even more closely).
This is, of course, a heavily simplified description to express the
basic idea clearer.
| |
| Logan Shaw 2008-01-21, 4:33 am |
| Rainer Weikusat wrote:
> Barry Margolin <barmar@alum.mit.edu> writes:
[color=darkred]
> The second situation doesn't exist: Everything which is part of the
> address space of a process is by definition 'reachable'. That's what
> makes it part of this address space.
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main(void)
> {
> unsigned long ul;
>
> printf("%lu\n", (unsigned long)malloc(3));
> fputs("please enter the value printed: ", stdout);
> scanf("%lu", &ul);
> free((void *)ul);
>
> return 0;
> }
Let me give a slightly different example to illustrate why I think
the second situation does exist:
#include <stdlib.h>
int main(void)
{
char* p = malloc(10);
while (1) {}
*p = 0;
free(p);
return 0;
}
Now, the question is, has the memory that p points to been leaked?
It's certainly, as you say, in the address space. But there is only
one thread, it goes into an infinite loop which does not reference p
(or the same memory through any other path). So the code that
references p, though compiled into the executable and present in
memory, is not itself reachable. It is dead code. If dead code
is the only code that can reference the unreachable memory, is it
really reachable?
To put this whole thing another way, code is just data that will
be processed in a special way. To say that something is reachable
means it must be reachable by traversing the data structure, but
you must traverse the data structure by using reachable code. To
say that only the data structure matters and not the code is to
make an artificial distinction between code and data.
However, your example does illustrate a good point: it is only
in certain cases where we can make this determination. Even
leaving aside I/O, although it is a good illustration, you can
write this code:
#include <stdlib.h>
int main(void)
{
char* p = malloc(10);
some_function();
*p = 0;
free(p);
return 0;
}
To know whether the allocated memory is reachable after the call
to some_function(), you have to know whether that function
terminates. To know that in the general case, you have to solve
the Halting Problem. Which is, of course, impossible.
So I think the correct answer is that some memory really is
unreachable even though pointers to it are retained. The reason
is that there is no code that will or can ever deference the
pointers. There is no path (through both code and data) to the
memory even though the references still exist in memory.
HOWEVER, there is no general technique (that works for all code)
to show this in every case. There are some cases that do exist
where it can be proven that no code will reference the memory,
and there are some where it is true but nevertheless cannot be
proven.
A point about I/O: you can take this all a bit further and
consider what happens when you attach the debugger. Certainly
the debugger can only add to the list of possible memory locations
that will be accessed: using the debugger never decreases and
may increase the number of paths that will be taken. So you can
access memory with the debugger that the code never will access.
Does this mean that the memory should be considered reachable?
I would argue that you could say that the memory is reachable
if it can be reached by attaching a debugger, but that it is
not a useful view. The reason I think it is not a useful view
is that if you make that argument, then you must also agree
that this program *can* calculate the value of pi to 10
decimal places:
#include <stdio.h>
int main(void)
{
double pi = 3.0;
printf ("%f\n", pi);
return 0;
}
After all, you can attach the debugger and change the program's
behavior so that the variable 'pi' has the correct value,
right? :-)
The point I'm getting at is that I think the only reasonable
thing to ask is whether a given program running with a given
input (or a given set of inputs) leaks memory. Obviously it
is sometimes useful to ask whether a given program avoids
leaking memory for all possible inputs, but that's just one
case of the above (the program is given and the set of inputs
is also given: it's the set of all possible inputs).
- Logan
| |
| apm35@student.open.ac.uk 2008-01-23, 4:29 am |
| On 16 Jan, 16:05, ap...@student.open.ac.uk wrote:
> According to man, SZ is:
> The total size of the process in virtual memory,
> including all mapped files and devices, in pages
> where on my system (solaris 8) a page is 8K.
>
> But this does not tell me all that I need to know. I used to think
> that SZ was the amount of heap storage used, as allocated typically
> (but not exclusively) through malloc. But I am not sure now. I
> originally assumed that no matter how many malloc and frees were done,
> if they all matched and the app did not leak then SZ would not show an
> ongoing upward trend. I think I need to understand more about SZ so I
> have come here for help please.
I am not sure this question ever got answered but I can now report
that the app does NOT leak memory. I have monitored it via ps for a
w and the page count did go down to the original level eventually.
The page usage did not tally with the usage as reported by jconsole.
The jconsole graph was a sawtooth as expected. My worry was there
might be a leak in my C code I am calling via JNI.
I am satisfied now that the ps script I wrote is an ok way to monitor
this issue provided that it is allowed to run for long enough.
|
|
|
|
|