I'm fine with the concept; I haven't looked too hard at the implementation, but it looks like it's doing the right thing.
--Wez. On 9/7/05, Andi Gutmans <[EMAIL PROTECTED]> wrote: > Hey all, > > Has anyone had a chance to review this patch. > I think it'd be good to apply it. I've seen quite a few instances > where PHP processes blow up during a request and then hand around > with 100MB+. No one here had that problem? > > Andi > > At 09:27 AM 8/30/2005, Alexander Veremyev wrote: > >Some people have mentioned having problems where idle PHP processes > >hang around without freeing their memory (in a FastCGI or Apache module > >modes). > > > >As I have found, it's not really a memory fragmentation problem. > >The core of the problem is the fact, that free() doesn't return > >memory to the OS immediately. So, if we have memory hungry PHP > >scripts and use PHP in a FastCGI or Apache module environment, then > >large amount of memory could still remain allocated for a process > >while it's waiting for the next HTTP request. > > > >Attached is a patch which resolves this problem by forcing the > >memory allocator to return free pages to the operating system at the > >end of the request. Especially in instances where some of your PHP > >scripts use a lot of memory, this maybe be quite useful in reducing > >the machine's overall memory consumption at a given time. > > > >I think it's probably best for this explicit memory collector mode > >not to be used in the multithreaded environment (for performance > >reasons), but the patch works properly if ZTS is enabled. > > > >Two new configuration variables could be set in a php.ini: > > > >memory_trim_limit (default is 1M) - is a minimum memory grow per > >request limit until malloc_trim mechanism will be invoked. "0" value > >disables it. > > > >memory_grow_limit (default is 128M) - is a memory grow limit. If > >process reaches it, then force_exit SAPI global is turned on and > >could be used in SAPI modules to force process exit. This is for the > >case when we have persistent objects on the top of memory or memory > >leaks in external libraries. "0" value disables it. > > > >Patch also includes processing of force_exit SAPI global for CGI > >SAPI module (for FastCGI mode), Apache SAPI module and Apache 2.0 > >Handler SAPI module (for prefork Apache2 mode). > > > >Please review it, try it and send me feedback. > > > >With best regards, > > Alexander Veremyev. > > > > > > > >Index: php-src/Zend/zend_alloc.c > >=================================================================== > >RCS file: /repository/ZendEngine2/zend_alloc.c,v > >retrieving revision 1.144 > >diff -u -r1.144 zend_alloc.c > >--- php-src/Zend/zend_alloc.c 3 Aug 2005 13:30:47 -0000 1.144 > >+++ php-src/Zend/zend_alloc.c 9 Aug 2005 23:18:58 -0000 > >@@ -23,6 +23,7 @@ > > #include "zend_alloc.h" > > #include "zend_globals.h" > > #include "zend_fast_cache.h" > >+#include "SAPI.h" > > #ifdef HAVE_SIGNAL_H > > # include <signal.h> > > #endif > >@@ -455,6 +456,52 @@ > > } > > > > > >+ZEND_API int zend_set_memory_trim_limit(unsigned int memory_trim_limit) > >+{ > >+ TSRMLS_FETCH(); > >+ > >+ AG(memory_trim_limit) = memory_trim_limit; > >+ return SUCCESS; > >+} > >+ > >+ > >+ZEND_API int zend_set_memory_grow_limit(unsigned int memory_grow_limit) > >+{ > >+ TSRMLS_FETCH(); > >+ > >+ AG(memory_grow_limit) = memory_grow_limit; > >+ return SUCCESS; > >+} > >+ > >+ > >+#if defined(ZEND_WIN32) > >+static inline unsigned int HeapCommittedSize( HANDLE memory_heap ) > >+{ > >+ PROCESS_HEAP_ENTRY heap_entry; > >+ unsigned int mem_size; > >+ int cnt; > >+ > >+ cnt=0; > >+ > >+ mem_size = 0; > >+ memset(&heap_entry,0,sizeof(heap_entry)); > >+ heap_entry.wFlags = PROCESS_HEAP_REGION; > >+ > >+ while( HeapWalk(memory_heap,&heap_entry) ) { > >+ if( heap_entry.wFlags & PROCESS_HEAP_REGION ) { > >+ mem_size += heap_entry.Region.dwCommittedSize; > >+ } > >+ } > >+ > >+ if( GetLastError() != ERROR_NO_MORE_ITEMS ) { > >+ fprintf(stderr, "HeapCommittedSize: Heap is corrupted\n" ); > >+ return 0; > >+ } > >+ return mem_size; > >+} > >+#endif > >+ > >+ > > ZEND_API void start_memory_manager(TSRMLS_D) > > { > > AG(head) = NULL; > >@@ -483,6 +530,15 @@ > > memset(AG(cache_stats), 0, sizeof(AG(cache_stats))); > > memset(AG(fast_cache_stats), 0, sizeof(AG(fast_cache_stats))); > > #endif > >+ > >+#ifdef ZEND_WIN32 > >+ /* Heap is just created, so it costs us nothing to get heap size */ > >+ AG(startup_memory) = AG(request_start_memory) = > >HeapCommittedSize( AG(memory_heap) ); > >+#elif HAVE_SBRK > >+ AG(startup_memory) = AG(request_start_memory) = (unsigned > >int)sbrk(0); > >+#else > >+ AG(startup_memory) = AG(request_start_memory) = 0; > >+#endif > > } > > > > > >@@ -648,6 +704,39 @@ > > return; > > } > > #endif > >+ > >+ if ( !full_shutdown && (AG(memory_trim_limit) != > >0 || AG(memory_grow_limit) != 0) ) { > >+ unsigned int process_memory; > >+#ifdef ZEND_WIN32 > >+ process_memory = HeapCommittedSize( AG(memory_heap) ); > >+ if( AG(memory_trim_limit) && > >+ (int)(process_memory - > >AG(request_start_memory)) > AG(memory_trim_limit) ) { > >+ HeapCompact( AG(memory_heap), HEAP_NO_SERIALIZE ); > >+ process_memory = HeapCommittedSize( AG(memory_heap) > >); > >+ } > >+#elif HAVE_SBRK > >+ process_memory = (unsigned int)sbrk(0); > >+ #if HAVE_MALLOC_TRIM > >+ if( AG(memory_trim_limit) && > >+ (int)(process_memory - > >AG(request_start_memory)) > AG(memory_trim_limit) ) { > >+ malloc_trim(0); > >+ process_memory = (unsigned int)sbrk(0); > >+ } > >+ #endif > >+#else > >+ process_memory = 0; > >+#endif > >+ > >+ if( AG(memory_grow_limit) && > >+ (int)(process_memory - AG(startup_memory)) > > >AG(memory_grow_limit) ) { > >+ SG(force_exit) = 1; > >+ } > >+ > >+ /* Current process memory size should be used as > >request_start_memory > >+ * for next request > >+ */ > >+ AG(request_start_memory) = process_memory; > >+ } > > } > > > > > >Index: php-src/Zend/zend_alloc.h > >=================================================================== > >RCS file: /repository/ZendEngine2/zend_alloc.h,v > >retrieving revision 1.63 > >diff -u -r1.63 zend_alloc.h > >--- php-src/Zend/zend_alloc.h 3 Aug 2005 13:30:47 -0000 1.63 > >+++ php-src/Zend/zend_alloc.h 9 Aug 2005 23:18:58 -0000 > >@@ -172,6 +172,9 @@ > > > > ZEND_API int zend_set_memory_limit(unsigned int memory_limit); > > > >+ZEND_API int zend_set_memory_trim_limit(unsigned int memory_trim_limit); > >+ZEND_API int zend_set_memory_grow_limit(unsigned int memory_grow_limit); > >+ > > ZEND_API void start_memory_manager(TSRMLS_D); > > ZEND_API void shutdown_memory_manager(int silent, int > > full_shutdown TSRMLS_DC); > > > >Index: php-src/Zend/zend_globals.h > >=================================================================== > >RCS file: /repository/ZendEngine2/zend_globals.h,v > >retrieving revision 1.141 > >diff -u -r1.141 zend_globals.h > >--- php-src/Zend/zend_globals.h 3 Aug 2005 13:30:52 -0000 1.141 > >+++ php-src/Zend/zend_globals.h 9 Aug 2005 23:18:58 -0000 > >@@ -261,6 +261,10 @@ > > #ifdef ZEND_MM > > zend_mm_heap mm_heap; > > #endif > >+ unsigned int memory_trim_limit; > >+ unsigned int memory_grow_limit; > >+ unsigned int startup_memory; > >+ unsigned int request_start_memory; > > }; > > > > struct _zend_scanner_globals { > >Index: php-src/Zend/Zend.m4 > >=================================================================== > >RCS file: /repository/ZendEngine2/Zend.m4,v > >retrieving revision 1.58 > >diff -u -r1.58 Zend.m4 > >--- php-src/Zend/Zend.m4 14 Jun 2005 12:23:26 -0000 1.58 > >+++ php-src/Zend/Zend.m4 9 Aug 2005 23:18:58 -0000 > >@@ -313,3 +313,6 @@ > > > > ]) > > > >+ > >+AC_CHECK_FUNC(sbrk,[AC_DEFINE(HAVE_SBRK, 1,[ ])]) > >+AC_CHECK_FUNC(malloc_trim,[AC_DEFINE(HAVE_MALLOC_TRIM, 1,[ ])]) > >Index: php-src/main/SAPI.h > >=================================================================== > >RCS file: /repository/php-src/main/SAPI.h,v > >retrieving revision 1.114 > >diff -u -r1.114 SAPI.h > >--- php-src/main/SAPI.h 3 Aug 2005 14:08:28 -0000 1.114 > >+++ php-src/main/SAPI.h 9 Aug 2005 23:18:59 -0000 > >@@ -129,6 +129,7 @@ > > zend_bool sapi_started; > > time_t global_request_time; > > HashTable known_post_content_types; > >+ int force_exit; > > } sapi_globals_struct; > > > > > >Index: php-src/main/php_globals.h > >=================================================================== > >RCS file: /repository/php-src/main/php_globals.h,v > >retrieving revision 1.98 > >diff -u -r1.98 php_globals.h > >--- php-src/main/php_globals.h 3 Aug 2005 14:08:33 -0000 1.98 > >+++ php-src/main/php_globals.h 9 Aug 2005 23:18:59 -0000 > >@@ -76,6 +76,9 @@ > > long memory_limit; > > long max_input_time; > > > >+ long memory_trim_limit; > >+ long memory_grow_limit; > >+ > > zend_bool track_errors; > > zend_bool display_errors; > > zend_bool display_startup_errors; > >Index: php-src/main/main.c > >=================================================================== > >RCS file: /repository/php-src/main/main.c,v > >retrieving revision 1.639 > >diff -u -r1.639 main.c > >--- php-src/main/main.c 3 Aug 2005 14:08:30 -0000 1.639 > >+++ php-src/main/main.c 9 Aug 2005 23:18:59 -0000 > >@@ -119,6 +119,31 @@ > > /* }}} */ > > #endif > > > >+/* {{{ PHP_INI_MH > >+ */ > >+static PHP_INI_MH(OnChangeMemoryTrimLimit) > >+{ > >+ if (new_value) { > >+ PG(memory_trim_limit) = zend_atoi(new_value, > >new_value_length); > >+ } else { > >+ PG(memory_trim_limit) = 1024*1024; > >+ } > >+ return zend_set_memory_trim_limit(PG(memory_trim_limit)); > >+} > >+/* }}} */ > >+ > >+/* {{{ PHP_INI_MH > >+ */ > >+static PHP_INI_MH(OnChangeMemoryGrowLimit) > >+{ > >+ if (new_value) { > >+ PG(memory_grow_limit) = zend_atoi(new_value, > >new_value_length); > >+ } else { > >+ PG(memory_grow_limit) = 128*1024*1024; > >+ } > >+ return zend_set_memory_grow_limit(PG(memory_grow_limit)); > >+} > >+/* }}} */ > > > > /* {{{ php_disable_functions > > */ > >@@ -313,6 +338,8 @@ > > #if MEMORY_LIMIT > > PHP_INI_ENTRY("memory_limit", > > "8M", PHP_INI_ALL, OnChangeMemoryLimit) > > #endif > >+ PHP_INI_ENTRY("memory_trim_limit", > >"1M", PHP_INI_ALL, OnChangeMemoryTrimLimit) > >+ PHP_INI_ENTRY("memory_grow_limit", > >"128M", PHP_INI_ALL, OnChangeMemoryGrowLimit) > > PHP_INI_ENTRY("precision", > > "14", PHP_INI_ALL, OnSetPrecision) > > PHP_INI_ENTRY("sendmail_from", > > NULL, PHP_INI_ALL, NULL) > > PHP_INI_ENTRY("sendmail_path", DEFAULT_SENDMAIL_PATH, > > PHP_INI_SYSTEM, NULL) > >Index: php-src/sapi/cgi/cgi_main.c > >=================================================================== > >RCS file: /repository/php-src/sapi/cgi/cgi_main.c,v > >retrieving revision 1.267 > >diff -u -r1.267 cgi_main.c > >--- php-src/sapi/cgi/cgi_main.c 3 Aug 2005 11:12:17 -0000 1.267 > >+++ php-src/sapi/cgi/cgi_main.c 9 Aug 2005 23:18:59 -0000 > >@@ -1644,7 +1644,7 @@ > > if (!fastcgi) break; > > /* only fastcgi will get here */ > > requests++; > >- if (max_requests && (requests == max_requests)) { > >+ if ( SG(force_exit) || (max_requests && > >(requests == max_requests)) ) { > > FCGX_Finish_r(&request); > > #ifndef PHP_WIN32 > > if (bindpath) { > >Index: php-src/sapi/apache/sapi_apache.c > >=================================================================== > >RCS file: /repository/php-src/sapi/apache/sapi_apache.c,v > >retrieving revision 1.47 > >diff -u -r1.47 sapi_apache.c > >--- php-src/sapi/apache/sapi_apache.c 3 Aug 2005 14:08:46 -0000 1.47 > >+++ php-src/sapi/apache/sapi_apache.c 9 Aug 2005 23:19:00 -0000 > >@@ -58,6 +58,10 @@ > > zend_try { > > php_request_shutdown(NULL); > > } zend_end_try(); > >+ > >+ if( SG(force_exit) ) { > >+ ap_child_terminate( ((request_rec *)SG(server_context)) ); > >+ } > > > > return retval; > > } > >Index: php-src/sapi/apache2handler/sapi_apache2.c > >=================================================================== > >RCS file: /repository/php-src/sapi/apache2handler/sapi_apache2.c,v > >retrieving revision 1.57 > >diff -u -r1.57 sapi_apache2.c > >--- php-src/sapi/apache2handler/sapi_apache2.c 3 Aug 2005 14:08:48 > >-0000 1.57 > >+++ php-src/sapi/apache2handler/sapi_apache2.c 9 Aug 2005 23:19:00 -0000 > >@@ -592,6 +592,12 @@ > > ctx->r = parent_req; > > } > > > >+#ifndef ZTS > >+ if (SG(force_exit)) { > >+ exit(0); > >+ } > >+#endif > >+ > > return OK; > > } > > > > > > > > > > > >-- > >PHP Internals - PHP Runtime Development Mailing List > >To unsubscribe, visit: http://www.php.net/unsub.php > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > > -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php