From 540488bf55746a36363c56462e939a56550e3717 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 10 Jun 2013 11:22:19 +0400 Subject: [PATCH] Compact HashTables before storing them in shared memory --- ext/opcache/ZendAccelerator.c | 4 ++ ext/opcache/zend_accelerator_util_funcs.c | 47 +++++++++++++++++++++++ ext/opcache/zend_accelerator_util_funcs.h | 1 + 3 files changed, 52 insertions(+) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index b62f245f4c..212e1e68d0 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -1126,6 +1126,10 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr return new_persistent_script; } + if (!compact_persistent_script(new_persistent_script)) { + return new_persistent_script; + } + /* exclusive lock */ zend_shared_alloc_lock(TSRMLS_C); diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 33ecf7f183..c24d9f1304 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -86,6 +86,53 @@ zend_persistent_script* create_persistent_script(void) return persistent_script; } +static int compact_hash_table(HashTable *ht) +{ + uint i = 3; + uint nSize; + Bucket **t; + + if (!ht->nNumOfElements) { + /* Empty tables don't allocate space for Buckets */ + return 1; + } + + if (ht->nNumOfElements >= 0x80000000) { + /* prevent overflow */ + nSize = 0x80000000; + } else { + while ((1U << i) < ht->nNumOfElements) { + i++; + } + nSize = 1 << i; + } + + if (nSize >= ht->nTableSize) { + /* Keep the size */ + return 1; + } + + t = (Bucket **)pemalloc(nSize * sizeof(Bucket *), ht->persistent); + if (!t) { + return 0; + } + + pefree(ht->arBuckets, ht->persistent); + + ht->arBuckets = t; + ht->nTableSize = nSize; + ht->nTableMask = ht->nTableSize - 1; + zend_hash_rehash(ht); + + return 1; +} + +int compact_persistent_script(zend_persistent_script *persistent_script) +{ + return compact_hash_table(&persistent_script->function_table) && + compact_hash_table(&persistent_script->class_table); +} + void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements) { if (destroy_elements) { diff --git a/ext/opcache/zend_accelerator_util_funcs.h b/ext/opcache/zend_accelerator_util_funcs.h index a926145c98..ddaae86b28 100644 --- a/ext/opcache/zend_accelerator_util_funcs.h +++ b/ext/opcache/zend_accelerator_util_funcs.h @@ -28,6 +28,7 @@ void zend_accel_copy_internal_functions(TSRMLS_D); zend_persistent_script* create_persistent_script(void); +int compact_persistent_script(zend_persistent_script *script); void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements); void zend_accel_free_user_functions(HashTable *ht TSRMLS_DC); -- 2.40.0