You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Bill Moseley <mo...@hank.org> on 2006/05/01 19:56:14 UTC

GTop vs. pmap on Linux

Apache/2.0.55 (Debian) mod_perl/2.0.2 Perl/v5.8.8

I'm testing out a Catalyst application running under mod_perl (was
using fastcgi before).  I'm trying to get a grasp on the memory used
by the processes.


Anyone familiar with pmap on linux?  There's this description of using
pmap to determine shared memory of a process:

    http://virtualthreads.blogspot.com/2006/02/understanding-memory-usage-on-linux.html

But, I'm seeing different values from GTop.  GTop is showing about 25M
shared, where pmap is only showing 5.7M shared.

I tend (and hope!) to believe GTop.  But, now I'm wondering what's
the difference.  Can anyone explain?



I'm also using a mmapped cache file for sessions.  So, I'm not clear
how that is counted, if at all.  Granted, it's not that big:

$ ls -lh /tmp/ws2_session-0
-rw-r----- 1 root root 5.6M 2006-05-01 07:05 /tmp/ws2_session-0

But I'm wondering if that's counted in the memory of each process,
and in GTop's shared count.



The other somewhat curious thing is that I'm not seeing any difference
in memory when I preload modules.  Granted, I'm using Catalyst which
has a setup() method that brings in most code at module load time.
Do you think that accounts for the similar results below?

I'm preloading about 300 modules.  (I just dumpped %INC for my tests.)


In this first test I'm using PerlLoadModule:


    total = 905892K
    shared =  0K
    used = 845768K
    free = 60124K
    21229 size = 63008k
    21229 vsize = 63008k
    21229 resident = 44856k
    21229 share = 24752k
    21229 rss = 44856k

    pmap -d 21229 | grep write
    mapped: 63012K    writeable/private: 39836K    shared: 5752K


Loading 360 in startup.pl as "use Foo ();"

    total = 905892K
    shared =  0K
    used = 865904K
    free = 39988K
    21873 size = 62936k
    21873 vsize = 62936k
    21873 resident = 44800k
    21873 share = 24752k
    21873 rss = 44800k

    pmap -d 21873 | grep write
    mapped: 62940K    writeable/private: 39764K    shared: 5752K


Only PerlLoadModule one module -- the main Catalyst application
module:

    total = 905892K
    shared =  0K
    used = 857464K
    free = 48428K
    22024 size = 61628k
    22024 vsize = 61628k
    22024 resident = 43528k
    22024 share = 24752k
    22024 rss = 43528k

    pmap -d 22024 | grep write
    mapped: 61632K    writeable/private: 38456K    shared: 5752K

Not much difference.



-- 
Bill Moseley
moseley@hank.org


Re: GTop vs. pmap on Linux

Posted by Bill Moseley <mo...@hank.org>.
On Tue, May 02, 2006 at 10:00:20AM +0200, Torsten Foertsch wrote:
> For 2.4 kernel series the figures got from /proc/PID/statm are as valid as the 
> figures from Linux::Smaps for kernels 2.6.14 and higher. For 2.6.0 up to 
> 2.6.13 there is no way to count COW (shared by copy-on-write) pages. Since 
> COW is the main way of sharing memory in a mod_perl environment figures that 
> don't take these pages into account are useless.

Ok, I'm running 2.6.15 with 1GB.

I tried looking over the kernel source, but didn't get too far.

I realize I can't total up shared_* memory and have it mean anything
(since I don't really know which other processes it is shared with),
but can I total up private data and get an idea of the minimum
required virtual memory?

This prints out the values and totals them up at the end, which is not
very meaningful, but I'm curious about the private_* values:

$ perl smaps.pl `pidof apache2`  (5 pids)
[...]

[9677]
           size:    62028K
            rss:    43140K
   shared_clean:     4388K
   shared_dirty:    18500K
  private_clean:        0K
  private_dirty:    20252K

[9675]
           size:    56360K
            rss:    38164K
   shared_clean:     4472K
   shared_dirty:    21144K
  private_clean:        0K
  private_dirty:    12548K

[totals]
           size:   299780K
            rss:   206820K
   shared_clean:    20860K
   shared_dirty:    97476K
  private_clean:        0K
  private_dirty:    88484K

Compare that to MySQL, which is statically linked on this machine:

$ perl smaps.pl `pidof mysqld--kernis`  (21 pids)
[...]

[9265]
           size:   145668K
            rss:    36576K
   shared_clean:     4040K
   shared_dirty:        0K
  private_clean:        0K
  private_dirty:    32536K

[9264]
           size:   145668K
            rss:    36576K
   shared_clean:     4040K
   shared_dirty:        0K
  private_clean:        0K
  private_dirty:    32536K

[totals]
           size:  3059028K
            rss:   768096K
   shared_clean:    84840K
   shared_dirty:        0K
  private_clean:        0K
  private_dirty:   683256K

Looks like I don't want all those MySQL processes swapped in at the
same time.

Compare that with postgres on the same machine:


$ perl smaps.pl 28321 28322 28323 9681 9682 9683 9684
[...]

[9683]
           size:    21248K
            rss:    15164K
   shared_clean:     2992K
   shared_dirty:     8348K
  private_clean:        0K
  private_dirty:     3824K

[9684]
           size:    21736K
            rss:    15740K
   shared_clean:     3780K
   shared_dirty:     7732K
  private_clean:        0K
  private_dirty:     4228K

[totals]
           size:   116744K
            rss:    68432K
   shared_clean:    19708K
   shared_dirty:    33912K
  private_clean:        0K
  private_dirty:    14812K




-- 
Bill Moseley
moseley@hank.org


Re: GTop vs. pmap on Linux

Posted by Torsten Foertsch <to...@gmx.net>.
On Monday 01 May 2006 21:00, Perrin Harkins wrote:
> No.  The current best bet is Linux::Smaps, which Apache2::SizeLimit now
> uses.

For 2.4 kernel series the figures got from /proc/PID/statm are as valid as the 
figures from Linux::Smaps for kernels 2.6.14 and higher. For 2.6.0 up to 
2.6.13 there is no way to count COW (shared by copy-on-write) pages. Since 
COW is the main way of sharing memory in a mod_perl environment figures that 
don't take these pages into account are useless.

But even with Linux::Smaps a problem remains when swapping/paging is allowed. 
When a page is erased from memory and lives only in swap space there is no 
other way on Linux to determine to how many processes it belongs than to page 
it in. And this is certainly to much overhead only for that.

To overcome this problem either disable all swap space or put these lines into 
your startup.pl:

------------ %< -------------------------------
require 'syscall.ph';
require 'sys/mmap.ph';

0==syscall &SYS_mlockall, &MCL_CURRENT | &MCL_FUTURE
  or die "ERROR: mlockall failed: $!\n";
------------ %< -------------------------------

or a little shorter:

------------ %< -------------------------------
0==syscall 152, 3 or die "ERROR: mlockall failed: $!\n";
------------ %< -------------------------------

This locks the parent apache completely into memory making it unpageable. The 
worker processes remain pageable. Now you waste a few megabytes of main 
memory but since the parent process is completely in core and, hence, all 
shared portions are so as well the private memory for each child is correctly 
determined by counting private pages plus swapped pages. This can be done by 
reading /proc/PID/smaps for >=2.6.14 or by reading /proc/PID/statm for 2.4.x.

Torsten

Re: GTop vs. pmap on Linux

Posted by Perrin Harkins <pe...@elem.com>.
On Mon, 2006-05-01 at 10:56 -0700, Bill Moseley wrote:
> Anyone familiar with pmap on linux?

No.  The current best bet is Linux::Smaps, which Apache2::SizeLimit now
uses.

> I tend (and hope!) to believe GTop.

Don't believe it.  It's probably getting the same numbers you'd get
from /proc/self/statm, and not accounting for copy-on-write well.  There
was a lot of discussion about this a few months back on the list.

> I'm also using a mmapped cache file for sessions.

That probably affects GTop, but I couldn't say for sure.

> The other somewhat curious thing is that I'm not seeing any difference
> in memory when I preload modules.  Granted, I'm using Catalyst which
> has a setup() method that brings in most code at module load time.
> Do you think that accounts for the similar results below?

Probably.  Try dumping %INC at the end of your startup.pl when you don't
preload.  If the list is similar, that would account for it.

One simple approach for memory tuning that avoids all of these issues is
to just look at the output of "free."  That will show you how much real
memory is unused.  If your tuning is working, that should be going up.

- Perrin