From 98b26169d4145fef67df9e54e28f8af0720a5cdf Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 23 Oct 2022 14:42:39 -0400 Subject: [PATCH] Optimize unserializing arrays with apc.serializer=default The pointer data apcu sees is usually aligned to 16 bytes on 64-bit systems using emalloc. It is guaranteed to be aligned to a power of at least ZEND_MM_ALIGNMENT_LOG2. Preserve the original bits just in case, similar to opcache's zend_rotr3. Benchmarking this for repeatedly unserializing large arrays with small strings and apc.serializer=default, this showed a moderate performance improvement. (note that apcu_fetch returns a different array on every call due to the possibility of cache evictions) For an array with 65536 small string keys and values: Repeated apcu_fetch went from 3.5 seconds -> 3.0 seconds For an array with 4096 small string keys and values: Repeated apcu_fetch went from 1.2 seconds -> 0.9 seconds For #323 --- apc_persist.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apc_persist.c b/apc_persist.c index 4e4b3cef..b6f79fea 100644 --- a/apc_persist.c +++ b/apc_persist.c @@ -521,9 +521,14 @@ static zend_bool apc_unpersist_serialized( return 0; } +/* Used to reduce hash collisions when using pointers in hash tables. (#175) */ +static zend_ulong apc_shr3(zend_ulong index) { + return (index >> 3) | (index << (SIZEOF_ZEND_LONG * 8 - 3)); +} + static inline void *apc_unpersist_get_already_copied(apc_unpersist_context_t *ctxt, void *ptr) { if (ctxt->memoization_needed) { - return zend_hash_index_find_ptr(&ctxt->already_copied, (uintptr_t) ptr); + return zend_hash_index_find_ptr(&ctxt->already_copied, apc_shr3((zend_ulong)(uintptr_t)ptr)); } return NULL; } @@ -531,7 +536,7 @@ static inline void *apc_unpersist_get_already_copied(apc_unpersist_context_t *ct static inline void apc_unpersist_add_already_copied( apc_unpersist_context_t *ctxt, const void *old_ptr, void *new_ptr) { if (ctxt->memoization_needed) { - zend_hash_index_add_new_ptr(&ctxt->already_copied, (uintptr_t) old_ptr, new_ptr); + zend_hash_index_add_new_ptr(&ctxt->already_copied, apc_shr3((zend_ulong)(uintptr_t)old_ptr), new_ptr); } }