krakjoe / apcu

APCu - APC User Cache
Other
964 stars 196 forks source link

Reduce shared memory usage storing the empty array #466

Closed TysonAndre closed 1 year ago

TysonAndre commented 1 year ago

Reduce shared memory usage in php 7.3+ for apc.serializer=default. Store the pointer to the immutable zend_empty_array rather than a brand new array. (APCu is already storing a pointer to static variables elsewhere, e.g. uninitialized_bucket)

nikic commented 1 year ago

I don't think this is correct in this form. Not every empty array is a zend_empty_array.

Another thing to keep in mind is that empty arrays have have different next free elements, though I'd have to check whether apcu preserves that, possibly it's already ignored.

TysonAndre commented 1 year ago

I fixed the error - the earlier commit made this use 0 memory, but didn't set the zval to zend_empty_array when persisting.

I don't think this is correct in this form. Not every empty array is a zend_empty_array.

I know, but the question is whether any empty array (in userland arrays) can be replaced with the zend_empty_array without observable effects. On unpersist, this is already using the EMPTY_ARRAY from #323

        case IS_ARRAY:
#if PHP_VERSION_ID >= 70300
            if (Z_ARR_P(zv)->nNumOfElements == 0) {
                ZVAL_EMPTY_ARRAY(zv); /* #323 */
                return;
            }
#endif
            Z_ARR_P(zv) = apc_unpersist_ht(ctxt, Z_ARR_P(zv));
            return;

Another thing to keep in mind is that empty arrays have have different next free elements, though I'd have to check whether apcu preserves that, possibly it's already ignored.

apc_persist_copy_ht ignores that. serialize() functions also ignore that by design.

    if (ht->nNumUsed == 0) {
#if PHP_VERSION_ID >= 70400
        ht->u.flags = HASH_FLAG_UNINITIALIZED;
#else
        ht->u.flags &= ~(HASH_FLAG_INITIALIZED|HASH_FLAG_PACKED);
#endif
        ht->nNextFreeElement = 0;
        ht->nTableMask = HT_MIN_MASK;
        HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
        return ht;
    }