]> granicus.if.org Git - php/commitdiff
Compact HashTables before storing them in shared memory
authorDmitry Stogov <dmitry@zend.com>
Mon, 10 Jun 2013 07:22:19 +0000 (11:22 +0400)
committerDmitry Stogov <dmitry@zend.com>
Mon, 10 Jun 2013 07:22:19 +0000 (11:22 +0400)
ext/opcache/ZendAccelerator.c
ext/opcache/zend_accelerator_util_funcs.c
ext/opcache/zend_accelerator_util_funcs.h

index b62f245f4c21b5a506d2923b511ca68f6c92fbe0..212e1e68d0c8f90b2cc1ead1eee580c05e5c76ed 100644 (file)
@@ -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);
 
index 33ecf7f18309b92c69aa432b65baf9dadce62daf..c24d9f1304517a0018d2c6286a4b25ca15ba0ae2 100644 (file)
@@ -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) {
index a926145c98659baeb851675cf4c535ccec6907c3..ddaae86b2874fe19a39cf69d7428ed1b6d18218f 100644 (file)
@@ -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);