summaryrefslogtreecommitdiff
path: root/ext/opcache
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2013-06-10 11:22:19 +0400
committerDmitry Stogov <dmitry@zend.com>2013-06-10 11:22:19 +0400
commit540488bf55746a36363c56462e939a56550e3717 (patch)
treeeec7be20004da6b9ceebd65db3411564e886b76f /ext/opcache
parent2e9d3e8b39c19ffba559b685f7ed96fee28cba59 (diff)
downloadphp-git-540488bf55746a36363c56462e939a56550e3717.tar.gz
Compact HashTables before storing them in shared memory
Diffstat (limited to 'ext/opcache')
-rw-r--r--ext/opcache/ZendAccelerator.c4
-rw-r--r--ext/opcache/zend_accelerator_util_funcs.c47
-rw-r--r--ext/opcache/zend_accelerator_util_funcs.h1
3 files changed, 52 insertions, 0 deletions
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);