1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

json: Improve performance of php_json_encode_array() for non-hooked fields (#20105)

`tmp` can only ever be non-undef if there's a hooked object property, which is
already an `UNEXPECTED()` case. Keep track of whether this case is hit or not
to avoid needlessly calling `zval_ptr_dtor()`.

For:

    <?php

    $len = 0;
    for ($i = 0; $i < 3_000_000; $i++) {
    	$len += strlen(json_encode(array_fill(0, 20, [])));
    }
    var_dump($len);

This is ~1.02 faster for a gcc 13.3 release build on a Intel(R) Core(TM)
i7-1365U.

    Benchmark 1: /tmp/bench/before /tmp/bench/test6.php
      Time (mean ± σ):     762.7 ms ±   3.2 ms    [User: 758.5 ms, System: 2.8 ms]
      Range (min … max):   759.2 ms … 769.3 ms    10 runs

    Benchmark 2: /tmp/bench/after /tmp/bench/test6.php
      Time (mean ± σ):     748.3 ms ±   9.0 ms    [User: 744.3 ms, System: 3.1 ms]
      Range (min … max):   740.8 ms … 766.2 ms    10 runs

    Summary
      /tmp/bench/after /tmp/bench/test6.php ran
        1.02 ± 0.01 times faster than /tmp/bench/before /tmp/bench/test6.php
This commit is contained in:
Tim Düsterhus
2025-10-08 22:59:54 +02:00
committed by GitHub
parent 4b2bb20731
commit baa5319632

View File

@@ -243,6 +243,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options,
zend_ulong index;
ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, data) {
bool need_dtor = false;
zval tmp;
ZVAL_UNDEF(&tmp);
@@ -264,6 +265,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options,
if ((prop_info->flags & ZEND_ACC_VIRTUAL) && !prop_info->hooks[ZEND_PROPERTY_HOOK_GET]) {
continue;
}
need_dtor = true;
data = zend_read_property_ex(prop_info->ce, Z_OBJ_P(val), prop_info->name, /* silent */ true, &tmp);
if (EG(exception)) {
PHP_JSON_HASH_UNPROTECT_RECURSION(recursion_rc);
@@ -303,7 +305,9 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options,
zval_ptr_dtor(&tmp);
return FAILURE;
}
zval_ptr_dtor(&tmp);
if (UNEXPECTED(need_dtor)) {
zval_ptr_dtor(&tmp);
}
smart_str_appendc(buf, ',');
} ZEND_HASH_FOREACH_END();