From b5467b02a6386a4badc81dc6bdedd18a7eb5ff0f Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Sat, 24 Jan 2026 02:42:44 +0300 Subject: [PATCH 1/5] Add benchmarks --- composer.json | 4 ++- phpbench.json | 7 ++++ tests/Benchmark/LoggerBench.php | 43 +++++++++++++++++++++++++ tests/Benchmark/MessageBench.php | 55 ++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 phpbench.json create mode 100644 tests/Benchmark/LoggerBench.php create mode 100644 tests/Benchmark/MessageBench.php diff --git a/composer.json b/composer.json index a374d16a..4c7f7123 100644 --- a/composer.json +++ b/composer.json @@ -36,6 +36,7 @@ }, "require-dev": { "maglnet/composer-require-checker": "^4.4", + "phpbench/phpbench": "^1.0", "phpunit/phpunit": "^9.6.23", "rector/rector": "^2.0.17", "roave/infection-static-analysis-plugin": "^1.25", @@ -82,6 +83,7 @@ }, "scripts": { "test": "phpunit --testdox --no-interaction", - "test-watch": "phpunit-watcher watch" + "test-watch": "phpunit-watcher watch", + "bench": "phpbench run --report=default" } } diff --git a/phpbench.json b/phpbench.json new file mode 100644 index 00000000..447d3202 --- /dev/null +++ b/phpbench.json @@ -0,0 +1,7 @@ +{ + "runner.bootstrap": "vendor/autoload.php", + "runner.path": "tests/Benchmark", + "runner.revs": 1000, + "runner.iterations": 10, + "runner.retry_threshold": 2 +} diff --git a/tests/Benchmark/LoggerBench.php b/tests/Benchmark/LoggerBench.php new file mode 100644 index 00000000..6e0f284f --- /dev/null +++ b/tests/Benchmark/LoggerBench.php @@ -0,0 +1,43 @@ +logger = new Logger([new class () extends Target { + protected function export(): void + { + // noop + } + }]); + } + + public function benchLogSimple(): void + { + $this->logger->log(LogLevel::INFO, 'simple message'); + } + + public function benchLogWithPlaceholder(): void + { + $this->logger->log(LogLevel::INFO, 'has {foo} placeholder', ['foo' => 'some']); + } + + public function benchLogWithMultiplePlaceholders(): void + { + $this->logger->log( + LogLevel::INFO, + 'Placeholder 1: {p1} - Placeholder 2: {p2}', + ['p1' => 'hello', 'p2' => 'world'], + ); + } +} diff --git a/tests/Benchmark/MessageBench.php b/tests/Benchmark/MessageBench.php new file mode 100644 index 00000000..24b5a878 --- /dev/null +++ b/tests/Benchmark/MessageBench.php @@ -0,0 +1,55 @@ + 'some']); + } + + public function benchSinglePlaceholderScalar(): void + { + new Message(LogLevel::INFO, 'has {foo} placeholder', ['foo' => 'some']); + } + + public function benchPlaceholderMissing(): void + { + new Message(LogLevel::INFO, 'has {foo} placeholder', []); + } + + public function benchPlaceholderNull(): void + { + new Message(LogLevel::INFO, 'has "{foo}" placeholder', ['foo' => null]); + } + + public function benchPlaceholderArray(): void + { + new Message(LogLevel::INFO, 'has "{foo}" placeholder', ['foo' => ['bar' => 7]]); + } + + public function benchNestedPlaceholder(): void + { + new Message(LogLevel::INFO, 'has "{foo.bar}" placeholder', ['foo' => ['bar' => 7]]); + } + + public function benchDeeplyNestedPlaceholder(): void + { + new Message(LogLevel::INFO, 'has "{foo.bar.baz}" placeholder', ['foo' => ['bar' => ['baz' => 7]]]); + } + + public function benchMultiplePlaceholders(): void + { + new Message( + LogLevel::INFO, + 'Placeholder 1: {p1} - Placeholder 2: {p2}', + ['p1' => 'hello', 'p2' => 'world'], + ); + } +} From 0a198a059151b1533a408a6929323bc3f1c59cc4 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Sat, 24 Jan 2026 03:00:11 +0300 Subject: [PATCH 2/5] Add fast path exit, remove redundant escaping from regex --- src/Message.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Message.php b/src/Message.php index bc0df4b2..4f18aedd 100644 --- a/src/Message.php +++ b/src/Message.php @@ -206,9 +206,13 @@ private function parse(string|Stringable $message, array $context): string { $message = (string) $message; + if (!str_contains($message, '{')) { + return $message; + } + /** @var string */ return preg_replace_callback( - '/\{([\w\._]+)\}/', + '/{([\w._]+)}/', static function (array $matches) use ($context) { [$exist, $value] = ContextValueExtractor::extract($context, $matches[1]); if ($exist) { From 8af5cb60f28b9ed561267d46bf814ba6ba483c15 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Sat, 24 Jan 2026 03:03:48 +0300 Subject: [PATCH 3/5] Add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6439b25a..1d2f7062 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Bug #130: Updated `Message::parse()` to correctly support multiple placeholders (@technicated) - Chg #130: Changed `Message::parse()` to conform to PSR-3, removing support for placeholders with arbitrary names and nested placeholders (@technicated) +- Enh #xxx: Add benchmarks, improve performance of `Message::parse()` (@samdark) ## 2.2.0 December 13, 2025 From def8f5b7dde49859d9bd2a7cc31d7bd7ac2909d6 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Sat, 24 Jan 2026 03:04:47 +0300 Subject: [PATCH 4/5] Add number to CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d2f7062..f492f6c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ - Bug #130: Updated `Message::parse()` to correctly support multiple placeholders (@technicated) - Chg #130: Changed `Message::parse()` to conform to PSR-3, removing support for placeholders with arbitrary names and nested placeholders (@technicated) -- Enh #xxx: Add benchmarks, improve performance of `Message::parse()` (@samdark) +- Enh #132: Add benchmarks, improve performance of `Message::parse()` (@samdark) ## 2.2.0 December 13, 2025 From 48d34a7452115592bea4e0338e528dd262823a5f Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Tue, 27 Jan 2026 09:54:58 +0300 Subject: [PATCH 5/5] Update CHANGELOG.md Co-authored-by: Sergei Predvoditelev --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f6429f9..b97922af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 2.2.1 under development - Enh #132: Add benchmarks, improve performance of `Message::parse()` (@samdark) +- Bug #130: Updated `Message::parse()` to correctly support multiple placeholders (@technicated) - Chg #130, #133: Changed `Message::parse()` to conform to PSR-3 (@technicated, @vjik) ## 2.2.0 December 13, 2025