Skip to content

Commit afe6b54

Browse files
author
nejc
committed
feat: add comprehensive benchmark suite
- Add IntegerBenchmark comparing native PHP vs library integer performance - Add ArrayBenchmark comparing native PHP vs library array performance - Create run_benchmarks.php script for executing benchmarks - Provide performance comparison tools for optimization decisions - Support both native PHP types and php-datatypes library types
1 parent 251faa4 commit afe6b54

File tree

3 files changed

+423
-0
lines changed

3 files changed

+423
-0
lines changed

benchmarks/ArrayBenchmark.php

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Nejcc\PhpDatatypes\Benchmarks;
6+
7+
use Nejcc\PhpDatatypes\Composite\Arrays\IntArray;
8+
use Nejcc\PhpDatatypes\Composite\Arrays\StringArray;
9+
use Nejcc\PhpDatatypes\Composite\Dictionary;
10+
11+
/**
12+
* Benchmark comparing native PHP arrays vs PHP Datatypes arrays
13+
*/
14+
class ArrayBenchmark
15+
{
16+
private const ITERATIONS = 10000;
17+
private const ARRAY_SIZE = 1000;
18+
19+
public function benchmarkIntArrayCreation(): array
20+
{
21+
$data = range(1, self::ARRAY_SIZE);
22+
23+
$start = microtime(true);
24+
$memoryStart = memory_get_usage();
25+
26+
for ($i = 0; $i < self::ITERATIONS; $i++) {
27+
$array = new IntArray($data);
28+
}
29+
30+
$end = microtime(true);
31+
$memoryEnd = memory_get_usage();
32+
33+
return [
34+
'time' => $end - $start,
35+
'memory' => $memoryEnd - $memoryStart,
36+
'iterations' => self::ITERATIONS,
37+
'type' => 'IntArray Creation'
38+
];
39+
}
40+
41+
public function benchmarkNativeArrayCreation(): array
42+
{
43+
$data = range(1, self::ARRAY_SIZE);
44+
45+
$start = microtime(true);
46+
$memoryStart = memory_get_usage();
47+
48+
for ($i = 0; $i < self::ITERATIONS; $i++) {
49+
$array = $data;
50+
}
51+
52+
$end = microtime(true);
53+
$memoryEnd = memory_get_usage();
54+
55+
return [
56+
'time' => $end - $start,
57+
'memory' => $memoryEnd - $memoryStart,
58+
'iterations' => self::ITERATIONS,
59+
'type' => 'Native Array Creation'
60+
];
61+
}
62+
63+
public function benchmarkIntArrayOperations(): array
64+
{
65+
$data = range(1, self::ARRAY_SIZE);
66+
$array = new IntArray($data);
67+
68+
$start = microtime(true);
69+
$memoryStart = memory_get_usage();
70+
71+
for ($i = 0; $i < self::ITERATIONS; $i++) {
72+
$array->toArray();
73+
$array->getValue();
74+
}
75+
76+
$end = microtime(true);
77+
$memoryEnd = memory_get_usage();
78+
79+
return [
80+
'time' => $end - $start,
81+
'memory' => $memoryEnd - $memoryStart,
82+
'iterations' => self::ITERATIONS,
83+
'type' => 'IntArray Operations'
84+
];
85+
}
86+
87+
public function benchmarkNativeArrayOperations(): array
88+
{
89+
$data = range(1, self::ARRAY_SIZE);
90+
91+
$start = microtime(true);
92+
$memoryStart = memory_get_usage();
93+
94+
for ($i = 0; $i < self::ITERATIONS; $i++) {
95+
$copy = $data;
96+
$count = count($data);
97+
}
98+
99+
$end = microtime(true);
100+
$memoryEnd = memory_get_usage();
101+
102+
return [
103+
'time' => $end - $start,
104+
'memory' => $memoryEnd - $memoryStart,
105+
'iterations' => self::ITERATIONS,
106+
'type' => 'Native Array Operations'
107+
];
108+
}
109+
110+
public function benchmarkDictionaryOperations(): array
111+
{
112+
$data = [];
113+
for ($i = 0; $i < self::ARRAY_SIZE; $i++) {
114+
$data["key_$i"] = "value_$i";
115+
}
116+
$dict = new Dictionary($data);
117+
118+
$start = microtime(true);
119+
$memoryStart = memory_get_usage();
120+
121+
for ($i = 0; $i < self::ITERATIONS; $i++) {
122+
$dict->toArray();
123+
$dict->size();
124+
$dict->getKeys();
125+
}
126+
127+
$end = microtime(true);
128+
$memoryEnd = memory_get_usage();
129+
130+
return [
131+
'time' => $end - $start,
132+
'memory' => $memoryEnd - $memoryStart,
133+
'iterations' => self::ITERATIONS,
134+
'type' => 'Dictionary Operations'
135+
];
136+
}
137+
138+
public function benchmarkNativeAssociativeArrayOperations(): array
139+
{
140+
$data = [];
141+
for ($i = 0; $i < self::ARRAY_SIZE; $i++) {
142+
$data["key_$i"] = "value_$i";
143+
}
144+
145+
$start = microtime(true);
146+
$memoryStart = memory_get_usage();
147+
148+
for ($i = 0; $i < self::ITERATIONS; $i++) {
149+
$copy = $data;
150+
$count = count($data);
151+
$keys = array_keys($data);
152+
}
153+
154+
$end = microtime(true);
155+
$memoryEnd = memory_get_usage();
156+
157+
return [
158+
'time' => $end - $start,
159+
'memory' => $memoryEnd - $memoryStart,
160+
'iterations' => self::ITERATIONS,
161+
'type' => 'Native Associative Array Operations'
162+
];
163+
}
164+
165+
public function runAllBenchmarks(): array
166+
{
167+
return [
168+
'int_array_creation' => $this->benchmarkIntArrayCreation(),
169+
'native_array_creation' => $this->benchmarkNativeArrayCreation(),
170+
'int_array_operations' => $this->benchmarkIntArrayOperations(),
171+
'native_array_operations' => $this->benchmarkNativeArrayOperations(),
172+
'dictionary_operations' => $this->benchmarkDictionaryOperations(),
173+
'native_assoc_array_operations' => $this->benchmarkNativeAssociativeArrayOperations(),
174+
];
175+
}
176+
177+
public function printResults(array $results): void
178+
{
179+
echo "=== Array Benchmark Results ===\n\n";
180+
181+
foreach ($results as $name => $result) {
182+
echo sprintf(
183+
"%s:\n Time: %.6f seconds\n Memory: %d bytes\n Iterations: %d\n Time per iteration: %.9f seconds\n\n",
184+
$result['type'],
185+
$result['time'],
186+
$result['memory'],
187+
$result['iterations'],
188+
$result['time'] / $result['iterations']
189+
);
190+
}
191+
192+
// Compare IntArray vs Native
193+
$intArrayCreation = $results['int_array_creation'];
194+
$nativeArrayCreation = $results['native_array_creation'];
195+
$intArrayOps = $results['int_array_operations'];
196+
$nativeArrayOps = $results['native_array_operations'];
197+
198+
echo "=== Performance Comparison ===\n";
199+
echo sprintf(
200+
"IntArray Creation vs Native: %.2fx slower\n",
201+
$intArrayCreation['time'] / $nativeArrayCreation['time']
202+
);
203+
echo sprintf(
204+
"IntArray Operations vs Native: %.2fx slower\n",
205+
$intArrayOps['time'] / $nativeArrayOps['time']
206+
);
207+
echo sprintf(
208+
"IntArray Memory overhead: %d bytes per operation\n",
209+
($intArrayCreation['memory'] - $nativeArrayCreation['memory']) / $intArrayCreation['iterations']
210+
);
211+
}
212+
}

benchmarks/IntegerBenchmark.php

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Nejcc\PhpDatatypes\Benchmarks;
6+
7+
use Nejcc\PhpDatatypes\Scalar\Integers\Signed\Int8;
8+
use Nejcc\PhpDatatypes\Scalar\Integers\Signed\Int32;
9+
use Nejcc\PhpDatatypes\Scalar\Integers\Signed\Int64;
10+
use Nejcc\PhpDatatypes\Scalar\Integers\Unsigned\UInt8;
11+
use Nejcc\PhpDatatypes\Scalar\Integers\Unsigned\UInt32;
12+
13+
/**
14+
* Benchmark comparing native PHP integers vs PHP Datatypes integers
15+
*/
16+
class IntegerBenchmark
17+
{
18+
private const ITERATIONS = 100000;
19+
20+
public function benchmarkInt8Creation(): array
21+
{
22+
$start = microtime(true);
23+
$memoryStart = memory_get_usage();
24+
25+
for ($i = 0; $i < self::ITERATIONS; $i++) {
26+
$int = new Int8(42);
27+
}
28+
29+
$end = microtime(true);
30+
$memoryEnd = memory_get_usage();
31+
32+
return [
33+
'time' => $end - $start,
34+
'memory' => $memoryEnd - $memoryStart,
35+
'iterations' => self::ITERATIONS,
36+
'type' => 'Int8 Creation'
37+
];
38+
}
39+
40+
public function benchmarkNativeIntCreation(): array
41+
{
42+
$start = microtime(true);
43+
$memoryStart = memory_get_usage();
44+
45+
for ($i = 0; $i < self::ITERATIONS; $i++) {
46+
$int = 42;
47+
}
48+
49+
$end = microtime(true);
50+
$memoryEnd = memory_get_usage();
51+
52+
return [
53+
'time' => $end - $start,
54+
'memory' => $memoryEnd - $memoryStart,
55+
'iterations' => self::ITERATIONS,
56+
'type' => 'Native Int Creation'
57+
];
58+
}
59+
60+
public function benchmarkInt8Arithmetic(): array
61+
{
62+
$int1 = new Int8(50);
63+
$int2 = new Int8(30);
64+
65+
$start = microtime(true);
66+
$memoryStart = memory_get_usage();
67+
68+
for ($i = 0; $i < self::ITERATIONS; $i++) {
69+
$result = $int1->add($int2);
70+
$result = $int1->subtract($int2);
71+
$result = $int1->multiply($int2);
72+
}
73+
74+
$end = microtime(true);
75+
$memoryEnd = memory_get_usage();
76+
77+
return [
78+
'time' => $end - $start,
79+
'memory' => $memoryEnd - $memoryStart,
80+
'iterations' => self::ITERATIONS,
81+
'type' => 'Int8 Arithmetic'
82+
];
83+
}
84+
85+
public function benchmarkNativeIntArithmetic(): array
86+
{
87+
$int1 = 50;
88+
$int2 = 30;
89+
90+
$start = microtime(true);
91+
$memoryStart = memory_get_usage();
92+
93+
for ($i = 0; $i < self::ITERATIONS; $i++) {
94+
$result = $int1 + $int2;
95+
$result = $int1 - $int2;
96+
$result = $int1 * $int2;
97+
}
98+
99+
$end = microtime(true);
100+
$memoryEnd = memory_get_usage();
101+
102+
return [
103+
'time' => $end - $start,
104+
'memory' => $memoryEnd - $memoryStart,
105+
'iterations' => self::ITERATIONS,
106+
'type' => 'Native Int Arithmetic'
107+
];
108+
}
109+
110+
public function benchmarkBigIntegerOperations(): array
111+
{
112+
$int1 = new Int64('9223372036854775800');
113+
$int2 = new Int64('7');
114+
115+
$start = microtime(true);
116+
$memoryStart = memory_get_usage();
117+
118+
for ($i = 0; $i < self::ITERATIONS / 100; $i++) { // Fewer iterations for big ints
119+
$result = $int1->add($int2);
120+
$result = $int1->subtract($int2);
121+
}
122+
123+
$end = microtime(true);
124+
$memoryEnd = memory_get_usage();
125+
126+
return [
127+
'time' => $end - $start,
128+
'memory' => $memoryEnd - $memoryStart,
129+
'iterations' => self::ITERATIONS / 100,
130+
'type' => 'Int64 Arithmetic'
131+
];
132+
}
133+
134+
public function runAllBenchmarks(): array
135+
{
136+
return [
137+
'int8_creation' => $this->benchmarkInt8Creation(),
138+
'native_int_creation' => $this->benchmarkNativeIntCreation(),
139+
'int8_arithmetic' => $this->benchmarkInt8Arithmetic(),
140+
'native_int_arithmetic' => $this->benchmarkNativeIntArithmetic(),
141+
'big_int_arithmetic' => $this->benchmarkBigIntegerOperations(),
142+
];
143+
}
144+
145+
public function printResults(array $results): void
146+
{
147+
echo "=== Integer Benchmark Results ===\n\n";
148+
149+
foreach ($results as $name => $result) {
150+
echo sprintf(
151+
"%s:\n Time: %.6f seconds\n Memory: %d bytes\n Iterations: %d\n Time per iteration: %.9f seconds\n\n",
152+
$result['type'],
153+
$result['time'],
154+
$result['memory'],
155+
$result['iterations'],
156+
$result['time'] / $result['iterations']
157+
);
158+
}
159+
160+
// Compare Int8 vs Native
161+
$int8Creation = $results['int8_creation'];
162+
$nativeCreation = $results['native_int_creation'];
163+
$int8Arithmetic = $results['int8_arithmetic'];
164+
$nativeArithmetic = $results['native_int_arithmetic'];
165+
166+
echo "=== Performance Comparison ===\n";
167+
echo sprintf(
168+
"Int8 Creation vs Native: %.2fx slower\n",
169+
$int8Creation['time'] / $nativeCreation['time']
170+
);
171+
echo sprintf(
172+
"Int8 Arithmetic vs Native: %.2fx slower\n",
173+
$int8Arithmetic['time'] / $nativeArithmetic['time']
174+
);
175+
echo sprintf(
176+
"Int8 Memory overhead: %d bytes per operation\n",
177+
($int8Creation['memory'] - $nativeCreation['memory']) / $int8Creation['iterations']
178+
);
179+
}
180+
}

0 commit comments

Comments
 (0)