Skip to content

Commit 1977c03

Browse files
committed
no issue - add benchmarking along a few converter fixes
1 parent 79cedf4 commit 1977c03

File tree

7 files changed

+265
-9
lines changed

7 files changed

+265
-9
lines changed

BENCHMARK.md

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Benchmark
2+
3+
Benchmarks uses `phpbench/phpbench` library.
4+
5+
## Usage
6+
7+
Arbitrarily run benchmarks:
8+
9+
```sh
10+
./vendor/bin/phpbench run tests/Benchmark --report=aggregate
11+
```
12+
13+
Run and tag benchmark (for later comparison):
14+
15+
```sh
16+
./vendor/bin/phpbench run tests/Benchmark --report=aggregate --tag=v30
17+
```
18+
19+
Run benchmark and compare with tag:
20+
21+
```sh
22+
./vendor/bin/phpbench run tests/Benchmark --report=aggregate --ref=v30
23+
```
24+
25+
## Preliminary results
26+
27+
### 1.0 results
28+
29+
_Testing conditions: AMD Ryzen 7 PRO 6850U, PHP 8.3.4_
30+
31+
```
32+
+-----------------+------------------------------+-----+------+-----+----------+-----------+--------+
33+
| benchmark | subject | set | revs | its | mem_peak | mode | rstdev |
34+
+-----------------+------------------------------+-----+------+-----+----------+-----------+--------+
35+
| WriterBench | benchArbitrary | | 1000 | 5 | 2.338mb | 1.002ms | ±0.60% |
36+
| ConversionBench | benchIntFromSql | | 3000 | 5 | 1.964mb | 49.645μs | ±2.89% |
37+
| ConversionBench | benchIntToSql | | 3000 | 5 | 1.964mb | 53.701μs | ±0.92% |
38+
| ConversionBench | benchIntToSqlNullType | | 3000 | 5 | 1.964mb | 55.940μs | ±2.76% |
39+
| ConversionBench | benchRamseyUuidFromSql | | 3000 | 5 | 1.964mb | 36.084μs | ±3.07% |
40+
| ConversionBench | benchRamseyUuidToSql | | 3000 | 5 | 1.964mb | 37.128μs | ±0.45% |
41+
| ConversionBench | benchRamseyUuidToSqlNullType | | 3000 | 5 | 1.964mb | 64.340μs | ±0.22% |
42+
| ConversionBench | benchArrayFromSql | | 3000 | 5 | 1.964mb | 298.337μs | ±0.77% |
43+
| ConversionBench | benchArrayToSql | | 3000 | 5 | 1.964mb | 177.520μs | ±1.39% |
44+
| ConversionBench | benchArrayToSqlNullType | | 3000 | 5 | 1.964mb | 189.586μs | ±0.48% |
45+
+-----------------+------------------------------+-----+------+-----+----------+-----------+--------+
46+
```

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"require-dev" : {
3535
"doctrine/dbal": "^3.7",
3636
"friendsofphp/php-cs-fixer": "^3.40",
37-
"phpbench/phpbench": "^1.0",
37+
"phpbench/phpbench": "^1.2",
3838
"phpstan/phpstan": "^1.10",
3939
"phpunit/phpunit" : "^10.3",
4040
"ramsey/uuid": ">=3.8",

phpbench.json

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"runner.bootstrap": "vendor/autoload.php",
3+
"runner.path": "tests/Benchmark"
4+
}

src/Converter/Converter.php

+9-7
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,6 @@ public function fromSql(string $type, int|float|string $value): mixed
129129
return null;
130130
}
131131

132-
// @todo Maybe later, too slow for hydration. Never do this automatically.
133-
// if (null === $type) {
134-
// $type = $this->guessOutputType($value);
135-
// }
136-
137132
if (\str_ends_with($type, '[]')) {
138133
return $this->parseArrayRecursion(\substr($type, 0, -2), ArrayRowParser::parseArray($value));
139134
}
@@ -157,6 +152,12 @@ public function fromSql(string $type, int|float|string $value): mixed
157152
*/
158153
public function guessInputType(mixed $value): string
159154
{
155+
if (\is_array($value)) {
156+
foreach ($value as $candidate) {
157+
return $this->guessInputType($candidate) . '[]';
158+
}
159+
}
160+
160161
if (\is_object($value)) {
161162
foreach ($this->getConverterPluginRegistry()->getTypeGuessers() as $plugin) {
162163
\assert($plugin instanceof InputTypeGuesser);
@@ -202,8 +203,9 @@ public function toSql(mixed $value, ?string $type = null): null|int|float|string
202203
}
203204

204205
if (\str_ends_with($type, '[]')) {
205-
// @todo Handle array.
206-
throw new ValueConversionError(\sprintf("Handling arrays is not implemented yet, found type '%s'.", $type));
206+
$valueType = \substr($type, 0, -2);
207+
208+
return ArrayRowParser::writeArray($value, fn (mixed $value) => $this->toSql($value, $valueType));
207209
}
208210

209211
try {

src/Converter/ConverterPluginRegistry.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function __construct(?iterable $plugins = null)
4141
$this->register(new DateInputConverter());
4242
$this->register(new DateOutputConverter());
4343
$this->register(new IntervalInputConverter());
44-
if (\class_exists(UuidInterface::class)) {
44+
if (\interface_exists(UuidInterface::class)) {
4545
$this->register(new RamseyUuidInputConverter());
4646
$this->register(new RamseyUuidOutputConverter());
4747
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Goat\Benchmark\Converter;
6+
7+
use MakinaCorpus\QueryBuilder\Converter\Converter;
8+
use MakinaCorpus\QueryBuilder\Type\Type;
9+
use Ramsey\Uuid\Uuid;
10+
use Ramsey\Uuid\UuidInterface;
11+
12+
/**
13+
* @BeforeMethods({"setUp"})
14+
*/
15+
final class ConversionBench
16+
{
17+
private Converter $converter;
18+
19+
private array $arrayData;
20+
private string $arrayDataAsString;
21+
private Type $arrayType;
22+
private Type $intType;
23+
private UuidInterface $ramseyUuidData;
24+
private string $ramseyUuidDataAsString;
25+
private Type $ramseyUuidType;
26+
27+
public function setUp(): void
28+
{
29+
$this->converter = new Converter();
30+
31+
$this->arrayData = ["foo", "bar", "l''och"];
32+
$this->arrayDataAsString = "{foo,bar,l''och}";
33+
// $this->arrayType = Type::varchar()->toArray();
34+
// $this->intType = Type::int();
35+
$this->ramseyUuidData = Uuid::fromString('a9336bfe-1a3b-4d14-a2da-38b819da0e96');
36+
$this->ramseyUuidDataAsString = 'a9336bfe-1a3b-4d14-a2da-38b819da0e96';
37+
// $this->ramseyUuidType = Type::uuid();
38+
}
39+
40+
/**
41+
* @Revs(3000)
42+
* @Iterations(5)
43+
*/
44+
public function benchIntFromSql(): void
45+
{
46+
$this->converter->fromSQL('int', '152485788');
47+
}
48+
49+
/**
50+
* @Revs(3000)
51+
* @Iterations(5)
52+
*/
53+
public function benchIntToSql(): void
54+
{
55+
$this->converter->toSQL(152485788, 'int8');
56+
}
57+
58+
/**
59+
* @Revs(3000)
60+
* @Iterations(5)
61+
*/
62+
public function benchIntToSqlNullType(): void
63+
{
64+
$this->converter->toSQL(152485788, null);
65+
}
66+
67+
/**
68+
* @Revs(3000)
69+
* @Iterations(5)
70+
*
71+
public function benchIntToSqlWithType(): void
72+
{
73+
$this->converter->toSQL(152485788, $this->intType);
74+
}
75+
*/
76+
77+
/**
78+
* @Revs(3000)
79+
* @Iterations(5)
80+
*/
81+
public function benchRamseyUuidFromSql(): void
82+
{
83+
$this->converter->fromSQL(UuidInterface::class, $this->ramseyUuidDataAsString);
84+
}
85+
86+
/**
87+
* @Revs(3000)
88+
* @Iterations(5)
89+
*/
90+
public function benchRamseyUuidToSql(): void
91+
{
92+
$this->converter->toSQL($this->ramseyUuidData, 'uuid');
93+
}
94+
95+
/**
96+
* @Revs(3000)
97+
* @Iterations(5)
98+
*/
99+
public function benchRamseyUuidToSqlNullType(): void
100+
{
101+
$this->converter->toSQL($this->ramseyUuidData, null);
102+
}
103+
104+
/**
105+
* @Revs(3000)
106+
* @Iterations(5)
107+
*
108+
public function benchRamseyUuidToSqlWithType(): void
109+
{
110+
$this->converter->toSQL($this->ramseyUuidData, $this->ramseyUuidType);
111+
}
112+
*/
113+
114+
/**
115+
* @Revs(3000)
116+
* @Iterations(5)
117+
*/
118+
public function benchArrayFromSql(): void
119+
{
120+
$this->converter->fromSQL('string[]', $this->arrayDataAsString);
121+
}
122+
123+
/**
124+
* @Revs(3000)
125+
* @Iterations(5)
126+
*/
127+
public function benchArrayToSql(): void
128+
{
129+
$this->converter->toSQL($this->arrayData, 'varchar[]');
130+
}
131+
132+
/**
133+
* @Revs(3000)
134+
* @Iterations(5)
135+
*/
136+
public function benchArrayToSqlNullType(): void
137+
{
138+
$this->converter->toSQL($this->arrayData, null);
139+
}
140+
141+
/**
142+
* @Revs(3000)
143+
* @Iterations(5)
144+
*
145+
public function benchArrayToSqlWithType(): void
146+
{
147+
$this->converter->toSQL($this->arrayData, $this->arrayType);
148+
}
149+
*/
150+
}
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Goat\Benchmark\Converter;
6+
7+
use MakinaCorpus\QueryBuilder\Expression\Raw;
8+
use MakinaCorpus\QueryBuilder\Query\Query;
9+
use MakinaCorpus\QueryBuilder\Query\Select;
10+
use MakinaCorpus\QueryBuilder\Writer\Writer;
11+
12+
/**
13+
* @BeforeMethods({"setUp"})
14+
*/
15+
final class WriterBench
16+
{
17+
private Writer $writer;
18+
private Query $query;
19+
20+
public function setUp(): void
21+
{
22+
$this->writer = new Writer();
23+
24+
$query = new Select('task', 't');
25+
$query->column('t.*');
26+
$query->column('n.type');
27+
$query->columnAgg('avg', 'views');
28+
$query->column(new Raw('count(n.id)'), 'comment_count');
29+
// Add and remove a column for fun
30+
$query->column('some_field', 'some_alias')->removeColumn('some_alias');
31+
$query->leftJoin('task_note', 'n.task_id = t.id', 'n');
32+
$query->groupBy('t.id');
33+
$query->groupBy('n.type');
34+
$query->orderBy('n.type');
35+
$query->orderBy(new Raw('count(n.nid)'), Query::ORDER_DESC);
36+
$query->range(7, 42);
37+
$where = $query->getWhere();
38+
$where->isEqual('t.user_id', 12);
39+
$where->isLess('t.deadline', new Raw('current_timestamp'));
40+
$having = $query->getHaving();
41+
$having->withRaw('count(n.nid) < ?', 3);
42+
43+
$this->query = $query;
44+
}
45+
46+
/**
47+
* @Revs(1000)
48+
* @Iterations(5)
49+
*/
50+
public function benchArbitrary(): void
51+
{
52+
$this->writer->prepare($this->query);
53+
}
54+
}

0 commit comments

Comments
 (0)