From cc7c7eb9c876f3701a275c53dd6f37f23623dada Mon Sep 17 00:00:00 2001 From: Bart Butler Date: Fri, 9 Jun 2023 18:18:16 +0200 Subject: [PATCH 1/7] Avoid poor scaling of array_search() with very long arrays --- src/Value/Value.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Value/Value.php b/src/Value/Value.php index ce6d5790..0656af44 100644 --- a/src/Value/Value.php +++ b/src/Value/Value.php @@ -70,20 +70,26 @@ public static function parseValue(ParserState $oParserState, array $aListDelimit if (count($aStack) === 1) { return $aStack[0]; } - $iStartPosition = null; - while (($iStartPosition = array_search($sDelimiter, $aStack, true)) !== false) { + $aNewStack = []; + for ($iStartPosition = 0; $iStartPosition < count($aStack); $iStartPosition += 1) { + if ($iStartPosition === (count($aStack) - 1) || $sDelimiter !== $aStack[$iStartPosition + 1]) { + $aNewStack[] = $aStack[$iStartPosition]; + continue; + } $iLength = 2; //Number of elements to be joined - for ($i = $iStartPosition + 2; $i < count($aStack); $i += 2, ++$iLength) { + for ($i = $iStartPosition + 3; $i < count($aStack); $i += 2, ++$iLength) { if ($sDelimiter !== $aStack[$i]) { break; } } $oList = new RuleValueList($sDelimiter, $oParserState->currentLine()); - for ($i = $iStartPosition - 1; $i - $iStartPosition + 1 < $iLength * 2; $i += 2) { + for ($i = $iStartPosition; $i - $iStartPosition < $iLength * 2; $i += 2) { $oList->addListComponent($aStack[$i]); } - array_splice($aStack, $iStartPosition - 1, $iLength * 2 - 1, [$oList]); + $aNewStack[] = $oList; + $iStartPosition += $iLength * 2 - 2; } + $aStack = $aNewStack; } if (!isset($aStack[0])) { throw new UnexpectedTokenException( From 0deb07bf6ec61e2767cc0eab6a03a30a4a8aaea9 Mon Sep 17 00:00:00 2001 From: Bart Butler Date: Fri, 23 Feb 2024 10:56:24 +0100 Subject: [PATCH 2/7] Use ++ rather than += 1 in loop increment Co-authored-by: JakeQZ --- src/Value/Value.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Value/Value.php b/src/Value/Value.php index 0656af44..ef02f13b 100644 --- a/src/Value/Value.php +++ b/src/Value/Value.php @@ -71,7 +71,7 @@ public static function parseValue(ParserState $oParserState, array $aListDelimit return $aStack[0]; } $aNewStack = []; - for ($iStartPosition = 0; $iStartPosition < count($aStack); $iStartPosition += 1) { + for ($iStartPosition = 0; $iStartPosition < count($aStack); ++$iStartPosition) { if ($iStartPosition === (count($aStack) - 1) || $sDelimiter !== $aStack[$iStartPosition + 1]) { $aNewStack[] = $aStack[$iStartPosition]; continue; From c05bb3fe251c7be21952434065eb938fac74f434 Mon Sep 17 00:00:00 2001 From: Bart Butler Date: Fri, 23 Feb 2024 12:07:56 +0100 Subject: [PATCH 3/7] Use local variable for count($aStack) within loop --- src/Value/Value.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Value/Value.php b/src/Value/Value.php index ef02f13b..d7fcd641 100644 --- a/src/Value/Value.php +++ b/src/Value/Value.php @@ -71,13 +71,14 @@ public static function parseValue(ParserState $oParserState, array $aListDelimit return $aStack[0]; } $aNewStack = []; - for ($iStartPosition = 0; $iStartPosition < count($aStack); ++$iStartPosition) { - if ($iStartPosition === (count($aStack) - 1) || $sDelimiter !== $aStack[$iStartPosition + 1]) { + $aStackLength = count($aStack); + for ($iStartPosition = 0; $iStartPosition < $aStackLength; ++$iStartPosition) { + if ($iStartPosition === ($aStackLength - 1) || $sDelimiter !== $aStack[$iStartPosition + 1]) { $aNewStack[] = $aStack[$iStartPosition]; continue; } $iLength = 2; //Number of elements to be joined - for ($i = $iStartPosition + 3; $i < count($aStack); $i += 2, ++$iLength) { + for ($i = $iStartPosition + 3; $i < $aStackLength; $i += 2, ++$iLength) { if ($sDelimiter !== $aStack[$i]) { break; } From fa61a4c36cca2170c37fcf1cdac073e4e337c31a Mon Sep 17 00:00:00 2001 From: Bart Butler Date: Sat, 24 Feb 2024 03:16:12 +0100 Subject: [PATCH 4/7] Correct stack length variable name --- src/Value/Value.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Value/Value.php b/src/Value/Value.php index d7fcd641..8621ccda 100644 --- a/src/Value/Value.php +++ b/src/Value/Value.php @@ -66,19 +66,19 @@ public static function parseValue(ParserState $oParserState, array $aListDelimit $oParserState->consumeWhiteSpace(); } // Convert the list to list objects + $iStackLength = count($aStack); foreach ($aListDelimiters as $sDelimiter) { - if (count($aStack) === 1) { + if ($iStackLength === 1) { return $aStack[0]; } $aNewStack = []; - $aStackLength = count($aStack); for ($iStartPosition = 0; $iStartPosition < $aStackLength; ++$iStartPosition) { - if ($iStartPosition === ($aStackLength - 1) || $sDelimiter !== $aStack[$iStartPosition + 1]) { + if ($iStartPosition === ($iStackLength - 1) || $sDelimiter !== $aStack[$iStartPosition + 1]) { $aNewStack[] = $aStack[$iStartPosition]; continue; } $iLength = 2; //Number of elements to be joined - for ($i = $iStartPosition + 3; $i < $aStackLength; $i += 2, ++$iLength) { + for ($i = $iStartPosition + 3; $i < $iStackLength; $i += 2, ++$iLength) { if ($sDelimiter !== $aStack[$i]) { break; } From 8b65d9474c7b175ad0e7428b36d1ebeacab6addf Mon Sep 17 00:00:00 2001 From: Bart Butler Date: Sat, 24 Feb 2024 03:19:49 +0100 Subject: [PATCH 5/7] Correct missed variable rename --- src/Value/Value.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Value/Value.php b/src/Value/Value.php index 8621ccda..eb9e0fa5 100644 --- a/src/Value/Value.php +++ b/src/Value/Value.php @@ -72,7 +72,7 @@ public static function parseValue(ParserState $oParserState, array $aListDelimit return $aStack[0]; } $aNewStack = []; - for ($iStartPosition = 0; $iStartPosition < $aStackLength; ++$iStartPosition) { + for ($iStartPosition = 0; $iStartPosition < $iStackLength; ++$iStartPosition) { if ($iStartPosition === ($iStackLength - 1) || $sDelimiter !== $aStack[$iStartPosition + 1]) { $aNewStack[] = $aStack[$iStartPosition]; continue; From 7b785360d9e7e4c9f0498b70db445e31aa69a282 Mon Sep 17 00:00:00 2001 From: Bart Butler Date: Sat, 24 Feb 2024 04:54:02 +0100 Subject: [PATCH 6/7] Compute $iStackLength inside loop --- src/Value/Value.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Value/Value.php b/src/Value/Value.php index eb9e0fa5..6be2110c 100644 --- a/src/Value/Value.php +++ b/src/Value/Value.php @@ -66,8 +66,8 @@ public static function parseValue(ParserState $oParserState, array $aListDelimit $oParserState->consumeWhiteSpace(); } // Convert the list to list objects - $iStackLength = count($aStack); foreach ($aListDelimiters as $sDelimiter) { + $iStackLength = count($aStack); if ($iStackLength === 1) { return $aStack[0]; } From fd33a67fd69b7e4672bad06e0617f19e4b983291 Mon Sep 17 00:00:00 2001 From: Bart Butler Date: Mon, 26 Feb 2024 05:17:22 +0100 Subject: [PATCH 7/7] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 063cad71..1f1ce788 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). ### Changed +- Improve performance of Value::parseValue with many delimiters by refactoring to remove array_search() - Add visibility to all class/interface constants (#469) ### Deprecated