perl5ever has asked for the wisdom of the Perl Monks concerning the following question:

I am testing sharing of pages between a parent and child process. However, my script is reporting that very little sharing is going on.

Basically, all it is doing is allocating a large string in the parent, forking a child and having the child report how many pages of memory are shared (by looking at /proc/self/statm).

When I run it, however, the space used by the string seems to be in the UNSHARED pages. Is that really correct?

Some typical output:

$ ./size-check SIZE: 3792.000 SHARED: 324.000 UNSHARED: 3468.000 LENGTH($x): 0 $ ./size-check Allocating a large string SIZE: 23332.000 SHARED: 444.000 UNSHARED: 22888.000 LENGTH($x): 100000 +00 $
#!/usr/bin/perl our $x; if (rand(10) < 5) { print "Allocating a large string\n"; $x = ' ' x 10_000_000; } my $pid = fork(); die "unable to fork: $!" unless defined($pid); if ($pid) { # parent wait; } else { report_size(); } sub report_size{ my ($total, $shared) = _linux_size_check(); my $unshared = $total - $shared; printf "SIZE: %.3f SHARED: %.3f UNSHARED: %.3f LENGTH(\$x): %d\n", $ +total, $shared, $unshared, length($x); } # borrowed rom Apache::SizeLimit sub _linux_size_check { my ( $size, $share ) = ( 0, 0 ); if ( open my $fh, '<', '/proc/self/statm' ) { ( $size, $share ) = ( split /\s/, scalar <$fh> )[0,2]; close $fh; } else { die "Fatal Error: couldn't access /proc/self/status"; } # linux on intel x86 has 4KB page size... return ( $size * 4, $share * 4 ); }

Replies are listed 'Best First'.
Re: shared pages between parent and child
by almut (Canon) on Dec 11, 2009 at 00:46 UTC

    The shared memory reported by statm is not what you think it is.  See fork doesn't handle copy-on-write correctly and in particular Rik van Riel's reply:

    The shared pages statistic is reported so low because they are measured differently, not because any deficiency in COW. COW still works fine.

    Older kernels used to walk all the page table entries to count how many of the pages were shared with other processes.

    This was too inefficient. Think of a server with a thousand Oracle processes, each having 2.7GB of virtual memory. Every screen update in top(1) would end up scanning the ptes for 2.7TB of memory!

    Because of this, the newer kernels no longer look at page table entries. Instead, they count entire MAP_SHARED VMAs as shared memory. They no longer count the still shared COW pages in anonymous memory, since it is way too inefficient to count those.