Skip to content

Commit 0853ab8

Browse files
committed
chore: Add base benchmarks
1 parent fe3eda3 commit 0853ab8

File tree

6 files changed

+140
-10
lines changed

6 files changed

+140
-10
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
fail-fast: true
1818
matrix:
19-
php: [ '8.1' ]
19+
php: [ '8.1', '8.2', '8.3', '8.4' ]
2020

2121
name: PHP ${{ matrix.php }}
2222

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.idea/
22
cache/
33
*.cache
4+
.phpbench/
45
/tests/coverage
56
/coverage.xml
67

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@
2626
]
2727
},
2828
"require-dev": {
29-
"laravel/pint": "*",
29+
"laravel/pint": "1.20.0",
3030
"pestphp/pest": "^2.36",
3131
"phpbench/phpbench": "^1.4"
3232
},
3333
"scripts": {
3434
"lint": "./vendor/bin/pint --config pint.json",
35-
"benchmark": "./vendor/bin/phpbench run tests/Benchmark/Benchmark.php",
35+
"benchmark": "./vendor/bin/phpbench run tests/Benchmark/Base.php --tag=base --quiet && ./vendor/bin/phpbench run tests/Benchmark/Benchmark.php --report=aggregate --ref=base",
3636
"test:lint": "./vendor/bin/pint --test",
3737
"test:coverage": "./vendor/bin/pest --coverage --parallel",
3838
"test:unit": "./vendor/bin/pest --colors=always --exclude-group=integration --parallel",

composer.lock

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Validator.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Attributes\Validation\Exceptions\ContextPropertyException;
88
use Attributes\Validation\Exceptions\ContinueValidationException;
9+
use Attributes\Validation\Exceptions\InvalidOptionException;
910
use Attributes\Validation\Exceptions\StopValidationException;
1011
use Attributes\Validation\Exceptions\ValidationException;
1112
use Attributes\Validation\Options as Options;
@@ -125,6 +126,7 @@ private function getDefaultPropertyValidator(): PropertyValidator
125126
* Retrieves the default alias generator for a given class
126127
*
127128
* @throws ContextPropertyException
129+
* @throws InvalidOptionException
128130
*/
129131
private function getDefaultAliasGenerator(ReflectionClass $reflectionClass): callable
130132
{

tests/Benchmark/Base.php

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php
2+
3+
namespace Attributes\Validation\Tests\Benchmark;
4+
5+
use Attributes\Validation\Tests\Models as Models;
6+
use DateTime;
7+
use DateTimeInterface;
8+
use Generator;
9+
use PhpBench\Attributes as Bench;
10+
use Respect\Validation\Validator as v;
11+
12+
class BenchValidator
13+
{
14+
#[Bench\Iterations(100)]
15+
public function benchBuiltins()
16+
{
17+
$data = [
18+
'bool' => 'true',
19+
'int' => '2',
20+
'float' => '-10e5',
21+
'array' => ['2', '3', '4', '5', '6', '7', '8', '9'],
22+
'object' => [
23+
'first' => 1,
24+
'second' => 2,
25+
],
26+
];
27+
v::keySet(
28+
v::key('bool', v::boolVal()->notOptional()),
29+
v::key('int', v::finite()->numericVal()),
30+
v::key('float', v::finite()->floatVal()->not(v::boolType())),
31+
v::key('array', v::arrayVal()),
32+
v::key('object', v::anyOf(v::objectType(), v::arrayVal())),
33+
)->assert($data);
34+
$model = new Models\Complex\MultipleBasic;
35+
$model->bool = $data['bool'] === 'true';
36+
$model->int = $data['int'] + 0;
37+
$model->float = $data['float'] + 0;
38+
$model->array = $data['array'];
39+
$model->object = (object) $data['object'];
40+
}
41+
42+
#[Bench\Iterations(100)]
43+
public function benchUnions()
44+
{
45+
$data = [
46+
'boolInt' => '12',
47+
'intFloat' => '2.9832',
48+
'floatArray' => ['-10e5'],
49+
'objectInt' => ['2', '3', '4', '5', '6', '7', '8', '9'],
50+
];
51+
v::keySet(
52+
v::key('boolInt', v::oneOf(v::boolVal(), v::intVal())),
53+
v::key('intFloat', v::oneOf(v::intVal(), v::floatVal())),
54+
v::key('floatArray', v::oneOf(v::floatVal(), v::arrayVal())),
55+
v::key('objectInt', v::oneOf(v::intVal(), v::arrayVal())),
56+
)->assert($data);
57+
$model = new Models\Complex\BasicUnion;
58+
$model->boolInt = is_bool(filter_var($data['boolInt'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)) ?: (int) $data['boolInt'];
59+
$model->intFloat = $data['intFloat'] + 0;
60+
$model->floatArray = is_numeric($data['floatArray']) ? (float) $data['floatArray'] : $data['floatArray'];
61+
$model->objectInt = is_array($data['objectInt']) ? (object) $data['objectInt'] : (int) $data['objectInt'];
62+
}
63+
64+
#[Bench\Iterations(100)]
65+
#[Bench\ParamProviders(['getSampleArray'])]
66+
public function benchArrays(array $params)
67+
{
68+
v::arrayVal()->each(v::intVal())->assert($params['data']);
69+
foreach ($params['data'] as &$value) {
70+
$value = (int) $value;
71+
}
72+
}
73+
74+
#[Bench\Iterations(100)]
75+
public function benchNestedAndAttributes()
76+
{
77+
$data = [
78+
'profile' => [
79+
'id' => '6d4238fd-eedf-4e79-b322-2b9f13a34a3f',
80+
'firstName' => 'Andre',
81+
'lastName' => 'Gil',
82+
'post' => [
83+
'id' => 1,
84+
'title' => 'How to validate data with classes in PHP',
85+
],
86+
],
87+
'userType' => 'moderator',
88+
'createdAt' => '2025-03-28T16:00:00+00:00',
89+
];
90+
v::keySet(
91+
v::key('profile', v::keySet(
92+
v::key('id', v::uuid()),
93+
v::key('firstName', v::stringVal()),
94+
v::key('lastName', v::stringVal()),
95+
v::key('post', v::keySet(
96+
v::key('id', v::anyOf(v::stringVal(), v::intVal())),
97+
v::key('title', v::stringVal()->notBlank()),
98+
)),
99+
)),
100+
v::key('userType', v::in(['admin', 'moderator', 'guest'])),
101+
v::key('createdAt', v::nullable(v::dateTime(DateTimeInterface::ATOM))),
102+
)->assert($data);
103+
$post = new Models\Nested\Post;
104+
$post->id = is_numeric($data['profile']['post']['id']) ? (int) $data['profile']['post']['id'] : (string) $data['profile']['post']['id'];
105+
$post->title = (string) $data['profile']['post']['title'];
106+
107+
$profile = new Models\Nested\Profile;
108+
$profile->id = $data['profile']['id'];
109+
$profile->firstName = (string) $data['profile']['firstName'];
110+
$profile->lastName = (string) $data['profile']['lastName'];
111+
$profile->post = $post;
112+
113+
$model = new Models\Nested\User;
114+
$model->profile = $profile;
115+
$model->userType = Models\Nested\UserType::from($data['userType']);
116+
$model->createdAt = DateTime::createFromFormat(DateTimeInterface::ATOM, (string) $data['createdAt']);
117+
}
118+
119+
public function getSampleArray(): Generator
120+
{
121+
$numbers = [];
122+
for ($i = 0; $i < 100; $i++) {
123+
$numbers[$i] = $i;
124+
}
125+
yield 'numbers' => ['data' => $numbers];
126+
}
127+
}

0 commit comments

Comments
 (0)