Skip to content

Commit 160d0e6

Browse files
committed
chore: add benchmarks
Signed-off-by: azjezz <azjezz@protonmail.com>
1 parent 0356257 commit 160d0e6

File tree

6 files changed

+1055
-5
lines changed

6 files changed

+1055
-5
lines changed

Justfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ analyze:
2020
typos:
2121
typos -c config/typos.toml
2222

23+
bench:
24+
php -dmemory_limit=-1 vendor/bin/phpbench run --config=config/phpbench.json
25+
2326
test:
2427
XDEBUG_MODE=coverage php -dmemory_limit=-1 vendor/bin/phpunit -c config/phpunit.xml.dist
2528

benchmarks/EvaluationBenchmark.php

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Cel\Benchmarks;
6+
7+
use Cel\CommonExpressionLanguage;
8+
use Cel\Runtime\Environment\Environment;
9+
use Cel\Syntax\Expression;
10+
use PhpBench\Benchmark\Metadata\Annotations\Iterations;
11+
use PhpBench\Benchmark\Metadata\Annotations\Revs;
12+
use PhpBench\Benchmark\Metadata\Annotations\Warmup;
13+
use Symfony\Component\Cache\Adapter\NullAdapter;
14+
use Symfony\Component\ExpressionLanguage\ExpressionFunction;
15+
use Symfony\Component\ExpressionLanguage\ExpressionLanguage as SymfonyExpressionLanguage;
16+
use Symfony\Component\ExpressionLanguage\ParsedExpression as SymfonyExpression;
17+
18+
use function array_keys;
19+
use function assert;
20+
use function extract;
21+
22+
/**
23+
* @mago-expect lint:no-boolean-literal-comparison
24+
*/
25+
final class EvaluationBenchmark
26+
{
27+
private const string CEL_EXPRESSION = <<<'CEL'
28+
(account.balance >= transaction.withdrawal
29+
|| (account.overdraftProtection && account.overdraftLimit >= transaction.withdrawal - account.balance)
30+
|| false
31+
|| (false && true)) ? account.name.toUpper() : null
32+
CEL;
33+
34+
private const string SEL_EXPRESSION = <<<'SEL'
35+
(account['balance'] >= transaction['withdrawal']
36+
|| (account['overdraftProtection'] && account['overdraftLimit'] >= transaction['withdrawal'] - account['balance'])
37+
|| false
38+
|| (false && true)) ? toUpper(account['name']) : null
39+
SEL;
40+
41+
private const string PHP_EXPRESSION = <<<'PHP'
42+
$result = ($account['balance'] >= $transaction['withdrawal']
43+
|| ($account['overdraftProtection'] && $account['overdraftLimit'] >= $transaction['withdrawal'] - $account['balance'])
44+
|| false
45+
|| (false && true)) ? \mb_strtoupper($account['name']) : null;
46+
PHP;
47+
48+
private const array ENVIRONMENT = [
49+
'account' => [
50+
'name' => 'John Doe',
51+
'balance' => 500,
52+
'overdraftProtection' => true,
53+
'overdraftLimit' => 1000,
54+
],
55+
'transaction' => [
56+
'withdrawal' => 700,
57+
],
58+
];
59+
60+
/**
61+
* @Revs(5000)
62+
* @Iterations(20)
63+
* @Warmup(10)
64+
*/
65+
public function benchCelExpression(): void
66+
{
67+
$cel = new CommonExpressionLanguage();
68+
$expression = $cel->parseString(self::CEL_EXPRESSION);
69+
70+
$_ = $cel->run($expression, Environment::fromArray(self::ENVIRONMENT));
71+
}
72+
73+
/**
74+
* @Revs(5000)
75+
* @Iterations(20)
76+
* @Warmup(10)
77+
*/
78+
public function benchOptimizedCelExpression(): void
79+
{
80+
$cel = new CommonExpressionLanguage();
81+
$expression = $cel->parseString(self::CEL_EXPRESSION);
82+
$expression = $cel->optimize($expression);
83+
84+
$_ = $cel->run($expression, Environment::fromArray(self::ENVIRONMENT));
85+
}
86+
87+
/**
88+
* @Revs(5000)
89+
* @Iterations(20)
90+
* @Warmup(10)
91+
*/
92+
public function benchCachedCelExpression(): void
93+
{
94+
/**
95+
* @var Expression|null
96+
*/
97+
static $expression = null;
98+
99+
$cel = new CommonExpressionLanguage();
100+
if (null === $expression) {
101+
$expression = $cel->parseString(self::CEL_EXPRESSION);
102+
}
103+
104+
$_ = $cel->run($expression, Environment::fromArray(self::ENVIRONMENT));
105+
}
106+
107+
/**
108+
* @Revs(5000)
109+
* @Iterations(20)
110+
* @Warmup(10)
111+
*/
112+
public function benchCachedOptimizedCelExpression(): void
113+
{
114+
/**
115+
* @var Expression|null
116+
*/
117+
static $expression = null;
118+
119+
$cel = new CommonExpressionLanguage();
120+
if (null === $expression) {
121+
$expression = $cel->parseString(self::CEL_EXPRESSION);
122+
$expression = $cel->optimize($expression);
123+
}
124+
125+
$_ = $cel->run($expression, Environment::fromArray(self::ENVIRONMENT));
126+
}
127+
128+
/**
129+
* @Revs(5000)
130+
* @Iterations(20)
131+
* @Warmup(10)
132+
*/
133+
public function benchSymfonyExpression(): void
134+
{
135+
$symfony = new SymfonyExpressionLanguage(new NullAdapter());
136+
$symfony->addFunction(ExpressionFunction::fromPhp('mb_strtoupper', 'toUpper'));
137+
138+
$_ = $symfony->evaluate(self::SEL_EXPRESSION, self::ENVIRONMENT);
139+
}
140+
141+
/**
142+
* @Revs(5000)
143+
* @Iterations(20)
144+
* @Warmup(10)
145+
*/
146+
public function benchCachedSymfonyExpression(): void
147+
{
148+
/**
149+
* @var null|SymfonyExpression $expression
150+
*/
151+
static $expression = null;
152+
153+
$symfony = new SymfonyExpressionLanguage(new NullAdapter());
154+
$symfony->addFunction(ExpressionFunction::fromPhp('mb_strtoupper', 'toUpper'));
155+
156+
if ($expression === null) {
157+
$expression = $symfony->parse(self::SEL_EXPRESSION, array_keys(self::ENVIRONMENT));
158+
}
159+
160+
$_ = $symfony->evaluate($expression, self::ENVIRONMENT);
161+
}
162+
163+
/**
164+
* @Revs(5000)
165+
* @Iterations(20)
166+
* @Warmup(10)
167+
*
168+
* @mago-expect lint:no-eval
169+
*/
170+
public function benchPHPExpression(): void
171+
{
172+
$env = self::ENVIRONMENT;
173+
174+
extract($env);
175+
eval(self::PHP_EXPRESSION);
176+
}
177+
}

composer.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
},
1414
"autoload-dev": {
1515
"psr-4": {
16-
"Cel\\Tests\\": "tests/"
16+
"Cel\\Tests\\": "tests/",
17+
"Cel\\Benchmarks\\": "benchmarks/"
1718
}
1819
},
1920
"authors": [
@@ -32,7 +33,9 @@
3233
"carthage-software/mago": "^1.0.0-beta.15",
3334
"phpunit/phpunit": "^12.3",
3435
"php-coveralls/php-coveralls": "^2.8",
35-
"infection/infection": "^0.31.2"
36+
"infection/infection": "^0.31.2",
37+
"phpbench/phpbench": "^1.4",
38+
"symfony/expression-language": "^7.3"
3639
},
3740
"config": {
3841
"allow-plugins": {

0 commit comments

Comments
 (0)