Bug #79660 [Com]: Shared memory is dirty in child proc after pcntl_fork

From: Date: Mon, 08 Jun 2020 20:11:59 +0000
Subject: Bug #79660 [Com]: Shared memory is dirty in child proc after pcntl_fork
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-227360@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=79660&edit=1

 ID:                 79660
 Comment by:         alexinbeijing at gmail dot com
 Reported by:        phpbugs at muglug dot com
 Summary:            Shared memory is dirty in child proc after
                     pcntl_fork
 Status:             Open
 Type:               Bug
 Package:            Performance problem
 Operating System:   Linux
 PHP Version:        7.4.6
 Block user comment: N
 Private report:     N

 New Comment:

Thanks for raising this interesting question. In short, it appears you are misinterpreting what
"Shared_Dirty" memory areas actually mean in Linux.

Try this: Do the same check on /proc/<PID>/smaps *before* forking. You will find that the
"Shared_Dirty" regions are just the same both before and after the fork.

So there is nothing in the child which is writing to all those COW'd pages. They were
"dirty" before the fork (meaning they have been written to, and if they were mmap'd
from a file, the changes would need to be flushed out to disk). They are still "dirty"
after the fork. That is not a problem.

The fact that the memory regions are "Shared_Dirty" is actually *good* for you. It means
that the memory is... well... shared! If all the pages had been written in the child, causing the OS
to copy them, they would display as either "Private_Clean" or "Private_Dirty",
not "shared". "Shared" is what you want.

So this is not actually a bug. Thanks for submitting your concern, though. It was interesting to
investigate.


Previous Comments:
------------------------------------------------------------------------
[2020-06-01 14:17:14] phpbugs at muglug dot com

Description:
------------
I have a cross-platform command-line application that uses pcntl_fork to spawn child processes.

pcntl_fork's implementation is very simple – it's just a call to fork(), which has
copy-on-write behaviour (no memory should be duplicated unless the program modifies it).

On Macs, memory appears to be shared effectively – it's only dirtied if there is some
change made to the data.

When the same script is run on Linux it appears that the shared memory is dirtied instantly, which
increases the cost of pcntl_fork both in terms of memory (whicch is multiplied by the number of
calls to that function) and also time, as each call to pcntl_fork is more costly.

Test script:
---------------
<?php

$a = [];

for ($i = 0; $i < 1000000; $i++) {
    $a[] = "$i";
}

$pid = pcntl_fork();
if ($pid == -1) {
     die('could not fork');
} else if ($pid) {
     // we are the parent
     pcntl_wait($status); //Protect against Zombie children
} else {
     echo shell_exec('cat /proc/' . posix_getpid() . '/smaps | grep Shared_ | grep -v
"0 kB"');
     echo $a[0];
}

Expected result:
----------------
There should be no large areas of Shared_Dirty memory in the output, since most memory should be
shared.



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=79660&edit=1


Thread (4 messages)

« previous php.bugs (#227360) next »