Edit report at http://bugs.php.net/bug.php?id=53669&edit=1
ID: 53669 Comment by: jeffwhiting at hotmail dot com Reported by: jille at hexon dot cx Summary: PHP does not return memory to system Status: Wont fix Type: Bug Package: Scripting Engine problem Operating System: Linux 2.6.29.2-smp PHP Version: 5.3.4 Block user comment: N Private report: N New Comment: Thanks, I looked into apache_child_terminate but it is only available for apache 1 sapi module. The documentation is pretty unclear but I found that out the hard way. If it was implemented for apache 2 it would have made things a lot easier for me. Previous Comments: ------------------------------------------------------------------------ [2011-04-18 20:53:00] ras...@php.net Yes, it is a significant performance hit, and you should have a look at the apache_child_terminate() function. ------------------------------------------------------------------------ [2011-04-18 20:43:35] jeffwhiting at hotmail dot com Is allocating memory really that much of a performance hit? It seems like allocating memory is pretty cheap. I could see a large performance hit if you were defragmenting the heap. Also something like that would be easily tunable via php.ini so users could choose if they wanted the performance penalty. We are currently working around the situation by using the following prepend file. What it does is monitor's the memory usage and tells the apache child to gracefully terminate after you get above a memory usage threshold. Sorry jille it is only useful with the apache sapi. Honestly it is a pretty ugly hack but it works... <?php function apacheMemoryUsage() { $result = 0; exec('ps -orss -p ' . getmypid(), $output); $result = trim($output[1]); return $result / 1024; } $memUseMB = apacheMemoryUsage(); $maxMem = get_cfg_var("apache_memory_limit_mb"); if (!$maxMem) $maxMem = 128; //error_log(getmypid()."> apache memory monitor: ". // "using $memUseMB MB of $maxMem MB."); if ($memUseMB > $maxMem && function_exists('posix_kill')) { error_log(getmypid()."> apache memory monitor: ". "$memUseMB MB > $maxMem MB. Sending graceful stop."); // Terminate Apache 2 child process after request has been // done by sending a SIGUSR1 POSIX signal (10) which // is a graceful stop. function killApacheChildOnExit() { error_log('posix_kill: '.getmypid()); posix_kill( getmypid(), 10 ); } register_shutdown_function( 'killApacheChildOnExit' ); } ?> ------------------------------------------------------------------------ [2011-04-12 22:40:42] jille at hexon dot cx I understand it won't be possible to free all of the used memory, mostly due to fragmentation. Our scripts use over 100MB of memory and I don't believe every page is used. When looking at zend_alloc.c in _zend_mm_free_int: (5.3.6) if (ZEND_MM_IS_FIRST_BLOCK(mm_block) && ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(mm_block, size))) { zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_AL IGNED_SEGMENT_SIZE)); } else [...] Shouldn't that free every segment no longer used? As segments are 2MB by default, it could be possible there are some parts used in every segment, but I don't think that is very likely when running over hundreds of megabytes. If above isn't suppose to "fix my problem", would it be possible to create a function that checks whether it can remove any segments? That way the performance hit can be controlled. ------------------------------------------------------------------------ [2011-04-12 22:17:07] ras...@php.net There are plenty random things that stay on the heap across requests. Persistent connections, the statcache and a number of other things, so it is pretty much impossible to do this in a heap-based allocator. For mmap stuff it would be technically possible, but again, the performance hit for doing so would be pretty nasty. ------------------------------------------------------------------------ [2011-04-12 21:42:10] jille at hexon dot cx When looking at zend_alloc.c it seems to support several memory allocators. As far as I know when you munmap() pages they should be returned to the system. Am I looking in the wrong page and is the problem somewhere the munmap()? We are using the CLI sapi instead of the Apache sapi as jeffwhiting does. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at http://bugs.php.net/bug.php?id=53669 -- Edit this bug report at http://bugs.php.net/bug.php?id=53669&edit=1