summaryrefslogtreecommitdiff
path: root/ext/json
diff options
context:
space:
mode:
authorTyson Andre <tysonandre775@hotmail.com>2019-10-25 19:57:39 -0400
committerNikita Popov <nikita.ppv@gmail.com>2019-10-30 11:06:46 +0100
commit447f07cd28494caf6c9f08640bc6d355f93ed2f2 (patch)
tree37b6f70e7d5b3cf96f9d2a14cb71fac0eba013f9 /ext/json
parent78162752442e3f431243a2ad54177cad260aa7be (diff)
downloadphp-git-447f07cd28494caf6c9f08640bc6d355f93ed2f2.tar.gz
Optimize creation of empty arrays in json_decode
Use the shared empty array from ZVAL_EMPTY_ARRAY For code that created an 10 arrays of 100000 empty arrays (has the same result with `$assoc=true` and `{}`) - This is the worst-case comparison, but I'd expect 0-length arrays to be fairly common in regular data for json_decode - The parser implementation was using function pointers so that third party extension developers could reuse the json parser for their own data structures, etc. (I think). This PR is meant to let those third party extensions continue working without changes. Before this patch: In 0.126 seconds: added 97.99 MiB After this patch: In 0.096 seconds: added 41.99 MiB ```php <?php $json = '[' . str_repeat('[],', 100000) . "null]"; $start_memory = memory_get_usage(); $start_time = microtime(true); $result = []; for ($i = 0; $i < 10; $i++) { $result[] = json_decode($json); } $end_memory = memory_get_usage(); $end_time = microtime(true); // Before this patch: In 0.126 seconds: added 97.99 MiB // After this patch: In 0.096 seconds: added 41.99 MiB printf("In %.3f seconds: added %.2f MiB\n", $end_time - $start_time, ($end_memory - $start_memory)/1000000); // For objects $json = '[' . str_repeat('{},', 100000) . "null]"; $start_memory = memory_get_usage(); $start_time = microtime(true); for ($i = 0; $i < 10; $i++) { $result[] = json_decode($json, true); } $end_memory = memory_get_usage(); $end_time = microtime(true); // Before this patch: In 0.126 seconds: added 97.99 MiB // After this patch: In 0.096 seconds: added 41.99 MiB printf("In %.3f seconds: added %.2f MiB (objects decoded as arrays) \n", $end_time - $start_time, ($end_memory - $start_memory)/1000000); ``` Closes GH-4861.
Diffstat (limited to 'ext/json')
-rw-r--r--ext/json/json_parser.y14
1 files changed, 12 insertions, 2 deletions
diff --git a/ext/json/json_parser.y b/ext/json/json_parser.y
index ba7311c963..aec9b225b8 100644
--- a/ext/json/json_parser.y
+++ b/ext/json/json_parser.y
@@ -76,6 +76,8 @@ int json_yydebug = 1;
%code {
static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
static void php_json_yyerror(php_json_parser *parser, char const *msg);
+static int php_json_parser_array_create(php_json_parser *parser, zval *array);
+static int php_json_parser_object_create(php_json_parser *parser, zval *array);
}
@@ -120,7 +122,11 @@ object_end:
members:
/* empty */
{
- parser->methods.object_create(parser, &$$);
+ if ((parser->scanner.options & PHP_JSON_OBJECT_AS_ARRAY) && parser->methods.object_create == php_json_parser_object_create) {
+ ZVAL_EMPTY_ARRAY(&$$);
+ } else {
+ parser->methods.object_create(parser, &$$);
+ }
}
| member
;
@@ -180,7 +186,11 @@ array_end:
elements:
/* empty */
{
- parser->methods.array_create(parser, &$$);
+ if (parser->methods.array_create == php_json_parser_array_create) {
+ ZVAL_EMPTY_ARRAY(&$$);
+ } else {
+ parser->methods.array_create(parser, &$$);
+ }
}
| element
;