Skip to content

Commit

Permalink
Reuse the immutable empty array in apcu_fetch
Browse files Browse the repository at this point in the history
Instead of allocating brand new arrays or looking them up in the hash
map, return php's shared immutable empty array starting in php 7.3.

For #323
  • Loading branch information
TysonAndre authored and nikic committed Oct 23, 2022
1 parent 8c05c51 commit 532dd62
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 2 deletions.
12 changes: 11 additions & 1 deletion apc_persist.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,11 +565,15 @@ static zend_array *apc_unpersist_ht(
apc_unpersist_add_already_copied(ctxt, orig_ht, ht);
memcpy(ht, orig_ht, sizeof(HashTable));
GC_TYPE_INFO(ht) = GC_ARRAY;

#if PHP_VERSION_ID >= 70300
/* Caller used ZVAL_EMPTY_ARRAY and set different zval flags instead */
ZEND_ASSERT(ht->nNumOfElements > 0 && ht->nNumUsed > 0);
#else
if (ht->nNumUsed == 0) {
HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
return ht;
}
#endif

HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht)));
memcpy(HT_GET_DATA_ADDR(ht), HT_GET_DATA_ADDR(orig_ht), HT_HASH_SIZE(ht->nTableMask));
Expand Down Expand Up @@ -628,6 +632,12 @@ static void apc_unpersist_zval_impl(apc_unpersist_context_t *ctxt, zval *zv) {
Z_REF_P(zv) = apc_unpersist_ref(ctxt, Z_REF_P(zv));
return;
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;
default:
Expand Down
3 changes: 2 additions & 1 deletion package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
<file name="apc_entry_002.phpt" role="test" />
<file name="apc_entry_003.phpt" role="test" />
<file name="apc_entry_recursion.phpt" role="test" />
<file name="apcu_fetch_empty_array_reference.phpt" role="test" />
<file name="apc_inc_perf.phpt" role="test" />
<file name="apc_store_array_int_keys.phpt" role="test" />
<file name="apc_store_array_with_refs.phpt" role="test" />
Expand Down Expand Up @@ -718,7 +719,7 @@ and unpersisting values.
- Bring back spinlocks, various issues (Joe)
- Fixed symbol clashing, windows debug mode, again (Anatol)
- apcu_key_info / apc_cache_stat functions (Joe)

</notes>
</release>
<release>
Expand Down
55 changes: 55 additions & 0 deletions tests/apcu_fetch_empty_array_reference.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
--TEST--
apcu_fetch should work for multiple reference groups
--SKIPIF--
<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
--INI--
apc.enabled=1
apc.enable_cli=1
--FILE--
<?php

$x = [];
$y = [];
$array = [&$x, &$x, &$y, &$y];
apcu_store("ary", $array);
$copy = apcu_fetch("ary");
$copy[0][1] = new stdClass();
var_dump($array);
var_dump($copy);

?>
--EXPECT--
array(4) {
[0]=>
&array(0) {
}
[1]=>
&array(0) {
}
[2]=>
&array(0) {
}
[3]=>
&array(0) {
}
}
array(4) {
[0]=>
&array(1) {
[1]=>
object(stdClass)#1 (0) {
}
}
[1]=>
&array(1) {
[1]=>
object(stdClass)#1 (0) {
}
}
[2]=>
&array(0) {
}
[3]=>
&array(0) {
}
}

0 comments on commit 532dd62

Please sign in to comment.