From 18d99ee4b724f9ecd18122abacfac5767bfbfb48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 8 Oct 2025 10:10:16 +0200 Subject: [PATCH] json: Improve performance of `php_json_encode_array()` (#20092) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of using a boolean flag to check for each element whether or not it is the first, we just unconditionally append a comma after each element and then remove the last comma at the end. For: s)[ZSTR_LEN(buf->s) - 1] != ','; + if (!empty) { + /* Drop the trailing comma. */ + ZSTR_LEN(buf->s)--; } PHP_JSON_HASH_UNPROTECT_RECURSION(obj); @@ -197,7 +198,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, } --encoder->depth; - if (need_comma) { + if (!empty) { php_json_pretty_print_char(buf, options, '\n'); php_json_pretty_print_indent(buf, options, encoder); } @@ -235,6 +236,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, uint32_t i = myht ? zend_hash_num_elements(myht) : 0; + bool empty = true; if (i > 0) { zend_string *key; zval *data; @@ -247,12 +249,6 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, if (!encode_as_object) { ZEND_ASSERT(Z_TYPE_P(data) != IS_PTR); - if (need_comma) { - smart_str_appendc(buf, ','); - } else { - need_comma = true; - } - php_json_pretty_print_char(buf, options, '\n'); php_json_pretty_print_indent(buf, options, encoder); } else { @@ -276,11 +272,6 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, } } - if (need_comma) { - smart_str_appendc(buf, ','); - } else { - need_comma = true; - } php_json_pretty_print_char(buf, options, '\n'); php_json_pretty_print_indent(buf, options, encoder); @@ -293,12 +284,6 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, smart_str_appendl(buf, "\"\"", 2); } } else { - if (need_comma) { - smart_str_appendc(buf, ','); - } else { - need_comma = true; - } - php_json_pretty_print_char(buf, options, '\n'); php_json_pretty_print_indent(buf, options, encoder); @@ -319,7 +304,15 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, return FAILURE; } zval_ptr_dtor(&tmp); + + smart_str_appendc(buf, ','); } ZEND_HASH_FOREACH_END(); + + empty = ZSTR_VAL(buf->s)[ZSTR_LEN(buf->s) - 1] != ','; + if (!empty) { + /* Drop the trailing comma. */ + ZSTR_LEN(buf->s)--; + } } PHP_JSON_HASH_UNPROTECT_RECURSION(recursion_rc); @@ -334,7 +327,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, --encoder->depth; /* Only keep closing bracket on same line for empty arrays/objects */ - if (need_comma) { + if (!empty) { php_json_pretty_print_char(buf, options, '\n'); php_json_pretty_print_indent(buf, options, encoder); }