APC's performance improvement patch for single process multithreaded php
| From: | Basant Kukreja | Date: | Wed, 07 Oct 2009 00:49:42 +0000 |
| Subject: | APC's performance improvement patch for single process multithreaded php | ||
| Groups: | php.pecl.dev | ||
| Request: | Send a blank email to pecl-dev+get-6673@lists.php.net to get a copy of this message | ||
Hi developers,
On Unix platforms, APC can be compiled with mmap or shared memory. This
performs good for multiprocess php. However when we run inside single process
multi-threaded Web Servers e.g Sun Web Server or Apache worker mpm with single
process, mmap is simply overkill. Reading APC's compiled cache from in-process
memory is much efficient than from mmap.
To achieve the above, I introduced a configurable variable apc.single_proc which
is set to 0 by default. When apc.single_proc is set to 1, cache is created
inside process memory. Also mutex which is used to synchronize the cache can
also be created as PTHREAD_PROCESS_PRIVATE. apc.single_proc can only be set to 1
when ZTS is enabled.
Attached is the patch from APC trunk which achieve this.
Regards,
Basant.
Index: php_apc.c =================================================================== --- php_apc.c (revision 289260) +++ php_apc.c (working copy) @@ -95,6 +95,7 @@ apc_globals->report_autofilter = 0; apc_globals->include_once = 0; apc_globals->apc_optimize_function = NULL; + apc_globals->single_proc = 0; #ifdef MULTIPART_EVENT_FORMDATA apc_globals->rfc1867 = 0; memset(&(apc_globals->rfc1867_data), 0, sizeof(apc_rfc1867_data)); @@ -257,6 +258,9 @@ STD_PHP_INI_BOOLEAN("apc.write_lock", "1", PHP_INI_SYSTEM, OnUpdateBool, write_lock, zend_apc_globals, apc_globals) STD_PHP_INI_BOOLEAN("apc.slam_defense", "1", PHP_INI_SYSTEM, OnUpdateBool, slam_defense, zend_apc_globals, apc_globals) STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool, report_autofilter,zend_apc_globals, apc_globals) +#ifdef ZTS +STD_PHP_INI_BOOLEAN("apc.single_proc", "0", PHP_INI_ALL, OnUpdateBool, single_proc, zend_apc_globals, apc_globals) +#endif #ifdef MULTIPART_EVENT_FORMDATA STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals) STD_PHP_INI_ENTRY("apc.rfc1867_prefix", "upload_", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_prefix, zend_apc_globals, apc_globals) Index: apc_pthreadmutex.c =================================================================== --- apc_pthreadmutex.c (revision 289260) +++ apc_pthreadmutex.c (working copy) @@ -20,6 +20,7 @@ /* $Id$ */ #include "apc_pthreadmutex.h" +#include "apc_globals.h" #ifdef APC_PTHREADMUTEX_LOCKS @@ -27,6 +28,8 @@ { int result; pthread_mutexattr_t* attr; + int shared; + TSRMLS_FETCH(); attr = malloc(sizeof(pthread_mutexattr_t)); result = pthread_mutexattr_init(attr); @@ -46,7 +49,13 @@ #endif /* pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ERRORCHECK); */ - result = pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED); + + if (APCG(single_proc)) + shared = PTHREAD_PROCESS_PRIVATE; + else + shared = PTHREAD_PROCESS_SHARED; + + result = pthread_mutexattr_setpshared(attr, shared); if(result == EINVAL) { apc_eprint("pthread mutex error: attr is not an initialized mutex attribute object, or pshared is not a valid process-shared state setting."); } else if(result == EFAULT) { Index: apc_sma.c =================================================================== --- apc_sma.c (revision 289260) +++ apc_sma.c (working copy) @@ -336,6 +336,7 @@ void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask) { uint i; + TSRMLS_FETCH(); if (sma_initialized) { return; @@ -367,12 +368,17 @@ block_t* block; void* shmaddr; + if (APCG(single_proc)) { + sma_segments[i].shmaddr = calloc(1, sma_segsize); + sma_segments[i].size = sma_segsize; + } else { #if APC_MMAP - sma_segments[i] = apc_mmap(mmap_file_mask, sma_segsize); - if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6); + sma_segments[i] = apc_mmap(mmap_file_mask, sma_segsize); + if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6); #else - sma_segments[i] = apc_shm_attach(apc_shm_create(NULL, i, sma_segsize)); + sma_segments[i] = apc_shm_attach(apc_shm_create(NULL, i, sma_segsize)); #endif + } sma_segments[i].size = sma_segsize; @@ -423,16 +429,21 @@ void apc_sma_cleanup() { uint i; + TSRMLS_FETCH(); assert(sma_initialized); for (i = 0; i < sma_numseg; i++) { apc_lck_destroy(SMA_LCK(i)); + if (APCG(single_proc)) { + free(sma_segments[i].shmaddr); + } else { #if APC_MMAP - apc_unmap(&sma_segments[i]); + apc_unmap(&sma_segments[i]); #else - apc_shm_detach(&sma_segments[i]); + apc_shm_detach(&sma_segments[i]); #endif + } } sma_initialized = 0; apc_efree(sma_segments); Index: apc_globals.h =================================================================== --- apc_globals.h (revision 289260) +++ apc_globals.h (working copy) @@ -76,6 +76,8 @@ /* module variables */ zend_bool initialized; /* true if module was initialized */ + zend_bool single_proc; /* true if single process shared the APC cache. + useful for performance */ apc_stack_t* cache_stack; /* the stack of cached executable code */ zend_bool cache_by_default; /* true if files should be cached unless filtered out */ /* false if files should only be cached if filtered in */
Index: php_apc.c =================================================================== --- php_apc.c (revision 289260) +++ php_apc.c (working copy) @@ -95,6 +95,7 @@ apc_globals->report_autofilter = 0; apc_globals->include_once = 0; apc_globals->apc_optimize_function = NULL; + apc_globals->single_proc = 0; #ifdef MULTIPART_EVENT_FORMDATA apc_globals->rfc1867 = 0; memset(&(apc_globals->rfc1867_data), 0, sizeof(apc_rfc1867_data)); @@ -257,6 +258,9 @@ STD_PHP_INI_BOOLEAN("apc.write_lock", "1", PHP_INI_SYSTEM, OnUpdateBool, write_lock, zend_apc_globals, apc_globals) STD_PHP_INI_BOOLEAN("apc.slam_defense", "1", PHP_INI_SYSTEM, OnUpdateBool, slam_defense, zend_apc_globals, apc_globals) STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool, report_autofilter,zend_apc_globals, apc_globals) +#ifdef ZTS +STD_PHP_INI_BOOLEAN("apc.single_proc", "0", PHP_INI_ALL, OnUpdateBool, single_proc, zend_apc_globals, apc_globals) +#endif #ifdef MULTIPART_EVENT_FORMDATA STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals) STD_PHP_INI_ENTRY("apc.rfc1867_prefix", "upload_", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_prefix, zend_apc_globals, apc_globals) Index: apc_pthreadmutex.c =================================================================== --- apc_pthreadmutex.c (revision 289260) +++ apc_pthreadmutex.c (working copy) @@ -20,6 +20,7 @@ /* $Id$ */ #include "apc_pthreadmutex.h" +#include "apc_globals.h" #ifdef APC_PTHREADMUTEX_LOCKS @@ -27,6 +28,8 @@ { int result; pthread_mutexattr_t* attr; + int shared; + TSRMLS_FETCH(); attr = malloc(sizeof(pthread_mutexattr_t)); result = pthread_mutexattr_init(attr); @@ -46,7 +49,13 @@ #endif /* pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ERRORCHECK); */ - result = pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED); + + if (APCG(single_proc)) + shared = PTHREAD_PROCESS_PRIVATE; + else + shared = PTHREAD_PROCESS_SHARED; + + result = pthread_mutexattr_setpshared(attr, shared); if(result == EINVAL) { apc_eprint("pthread mutex error: attr is not an initialized mutex attribute object, or pshared is not a valid process-shared state setting."); } else if(result == EFAULT) { Index: apc_sma.c =================================================================== --- apc_sma.c (revision 289260) +++ apc_sma.c (working copy) @@ -336,6 +336,7 @@ void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask) { uint i; + TSRMLS_FETCH(); if (sma_initialized) { return; @@ -367,12 +368,17 @@ block_t* block; void* shmaddr; + if (APCG(single_proc)) { + sma_segments[i].shmaddr = calloc(1, sma_segsize); + sma_segments[i].size = sma_segsize; + } else { #if APC_MMAP - sma_segments[i] = apc_mmap(mmap_file_mask, sma_segsize); - if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6); + sma_segments[i] = apc_mmap(mmap_file_mask, sma_segsize); + if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6); #else - sma_segments[i] = apc_shm_attach(apc_shm_create(NULL, i, sma_segsize)); + sma_segments[i] = apc_shm_attach(apc_shm_create(NULL, i, sma_segsize)); #endif + } sma_segments[i].size = sma_segsize; @@ -423,16 +429,21 @@ void apc_sma_cleanup() { uint i; + TSRMLS_FETCH(); assert(sma_initialized); for (i = 0; i < sma_numseg; i++) { apc_lck_destroy(SMA_LCK(i)); + if (APCG(single_proc)) { + free(sma_segments[i].shmaddr); + } else { #if APC_MMAP - apc_unmap(&sma_segments[i]); + apc_unmap(&sma_segments[i]); #else - apc_shm_detach(&sma_segments[i]); + apc_shm_detach(&sma_segments[i]); #endif + } } sma_initialized = 0; apc_efree(sma_segments); Index: apc_globals.h =================================================================== --- apc_globals.h (revision 289260) +++ apc_globals.h (working copy) @@ -76,6 +76,8 @@ /* module variables */ zend_bool initialized; /* true if module was initialized */ + zend_bool single_proc; /* true if single process shared the APC cache. + useful for performance */ apc_stack_t* cache_stack; /* the stack of cached executable code */ zend_bool cache_by_default; /* true if files should be cached unless filtered out */ /* false if files should only be cached if filtered in */