From 21bea751d0108e48de35408ecdfe189ea6ed0539 Mon Sep 17 00:00:00 2001 From: Filip Halaxa <filip@halaxa.cz> Date: Sat, 23 Nov 2024 22:18:44 +0100 Subject: [PATCH] Recursive focused performace optimizations. Ops outside the main foreach in Parser now matter as new Parser is created for each level --- src/JsonDecoder/ExtJsonDecoder.php | 14 ++++++++++++++ src/JsonDecoder/StringOnlyDecoder.php | 14 ++++++++++++++ src/Parser.php | 22 ++++++++++++---------- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/JsonDecoder/ExtJsonDecoder.php b/src/JsonDecoder/ExtJsonDecoder.php index 7a3df20..31ec068 100644 --- a/src/JsonDecoder/ExtJsonDecoder.php +++ b/src/JsonDecoder/ExtJsonDecoder.php @@ -21,6 +21,11 @@ class ExtJsonDecoder implements ItemDecoder */ private $options; + /** + * @var self + */ + private static $instance; + public function __construct($assoc = false, $depth = 512, $options = 0) { $this->assoc = $assoc; @@ -37,4 +42,13 @@ class ExtJsonDecoder implements ItemDecoder return new ValidResult($decoded); } + + public static function instance(): self + { + if ( ! self::$instance) { + self::$instance = new self(); + } + + return self::$instance; + } } diff --git a/src/JsonDecoder/StringOnlyDecoder.php b/src/JsonDecoder/StringOnlyDecoder.php index ebdf544..2858379 100644 --- a/src/JsonDecoder/StringOnlyDecoder.php +++ b/src/JsonDecoder/StringOnlyDecoder.php @@ -9,6 +9,11 @@ class StringOnlyDecoder implements ItemDecoder /** @var ItemDecoder */ private $innerDecoder; + /** + * @var self + */ + private static $instance; + public function __construct(ItemDecoder $innerDecoder) { $this->innerDecoder = $innerDecoder; @@ -22,4 +27,13 @@ class StringOnlyDecoder implements ItemDecoder return new ValidResult($jsonValue); } + + public static function instance(ItemDecoder $innerDecoder): self + { + if ( ! self::$instance) { + self::$instance = new self($innerDecoder); + } + + return self::$instance; + } } diff --git a/src/Parser.php b/src/Parser.php index 57b6ac4..d6f62e5 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -67,7 +67,7 @@ class Parser implements \IteratorAggregate, PositionAware private $recursive; /** @var array */ - private static $allBytes; + private static $tokenTypes; /** * @param array|string $jsonPointer Follows json pointer RFC https://tools.ietf.org/html/rfc6901 @@ -97,10 +97,15 @@ class Parser implements \IteratorAggregate, PositionAware throw new InvalidArgumentException('$tokens must be either an instance of Iterator or IteratorAggregate.'); } - $this->jsonDecoder = $jsonDecoder ?: new ExtJsonDecoder(); - if ($recursive) { - $this->jsonDecoder = new StringOnlyDecoder($this->jsonDecoder); + if ($jsonDecoder instanceof StringOnlyDecoder) { + $this->jsonDecoder = $jsonDecoder; + } else { + $this->jsonDecoder = $jsonDecoder ?: new ExtJsonDecoder(); + if ($recursive) { + $this->jsonDecoder = new StringOnlyDecoder($this->jsonDecoder); + } } + $this->recursive = $recursive; } @@ -127,11 +132,11 @@ class Parser implements \IteratorAggregate, PositionAware */ private function createGenerator(): Generator { - if ( ! self::$allBytes) { - self::$allBytes = $this->tokenTypes(); + if ( ! self::$tokenTypes) { + self::$tokenTypes = $this->tokenTypes(); } - $tokenTypes = self::$allBytes; + $tokenTypes = self::$tokenTypes; $iteratorStruct = null; $currentPath = &$this->currentPath; @@ -333,9 +338,6 @@ class Parser implements \IteratorAggregate, PositionAware $generator = $this->getIterator(); while ($generator->valid()) { -// var_dump(is_object($generator->current()) ? get_class($generator->current()) : $generator->current()); -// $generator->key(); -// $generator->current(); $generator->next(); } }