Skip to content

Commit 97c24de

Browse files
committed
Add benchmark comparing with brute force method
1 parent 7f3d9ec commit 97c24de

File tree

5 files changed

+174
-1
lines changed

5 files changed

+174
-1
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"phpunit/phpunit": "^9",
2323
"phpstan/phpstan": "^0.12.91",
2424
"vimeo/psalm": "^4.8",
25-
"nunomaduro/phpinsights": "^2.0"
25+
"nunomaduro/phpinsights": "^2.0",
26+
"phpbench/phpbench": "^1.0"
2627
}
2728
}

phpbench.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"runner.bootstrap": "vendor/autoload.php",
3+
"runner.path": "tests/Benchmark",
4+
"runner.file_pattern": "*Bench.php"
5+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Danon\IntervalTree\Tests\Benchmark;
5+
6+
use Danon\IntervalTree\Interval;
7+
use Danon\IntervalTree\IntervalTree;
8+
use PhpBench\Benchmark\Metadata\Annotations\Revs;
9+
10+
/**
11+
* @BeforeMethods({"init"})
12+
*/
13+
class CountIntersectionsBench
14+
{
15+
use GenerateIntervalTrait;
16+
17+
private const AMOUNT_INTERVALS_IN_TREE = 10000;
18+
private const MAX_INTERVAL_HIGH = 250000;
19+
private const MAX_INTERVAL_OFFSET = 100;
20+
21+
/**
22+
* @var IntervalTree
23+
*/
24+
private $tree;
25+
26+
/**
27+
* @var Interval[]
28+
*/
29+
private $bruteForceList;
30+
31+
public function init(): void
32+
{
33+
$this->tree = new IntervalTree();
34+
$this->bruteForceList = [];
35+
36+
for ($i = 0; $i < self::AMOUNT_INTERVALS_IN_TREE; $i++) {
37+
$interval = $this->generateInterval();
38+
$this->tree->insert($interval);
39+
$this->bruteForceList[] = $interval;
40+
}
41+
}
42+
43+
/**
44+
* @Revs(1000)
45+
*/
46+
public function benchTree(): void
47+
{
48+
$searchedInterval = $this->generateInterval();
49+
$this->tree->countIntersections($searchedInterval);
50+
}
51+
52+
/**
53+
* @Revs(1000)
54+
*/
55+
public function benchBruteForce(): void
56+
{
57+
$searchedInterval = $this->generateInterval();
58+
foreach ($this->bruteForceList as $interval) {
59+
$interval->intersect($searchedInterval);
60+
}
61+
}
62+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Danon\IntervalTree\Tests\Benchmark;
5+
6+
use Danon\IntervalTree\Interval;
7+
use Exception;
8+
9+
trait GenerateIntervalTrait
10+
{
11+
/**
12+
* @return Interval
13+
*/
14+
private function generateInterval(): Interval
15+
{
16+
try {
17+
$low = random_int(0, self::MAX_INTERVAL_HIGH);
18+
$high = random_int($low, min($low + self::MAX_INTERVAL_OFFSET, self::MAX_INTERVAL_HIGH));
19+
} catch (Exception $exception) {
20+
echo 'Cannot generate interval: ' . $exception->getMessage();
21+
exit;
22+
}
23+
return new Interval($low, $high);
24+
}
25+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Danon\IntervalTree\Tests\Benchmark;
5+
6+
use Danon\IntervalTree\Interval;
7+
use Danon\IntervalTree\IntervalTree;
8+
use Exception;
9+
use PhpBench\Benchmark\Metadata\Annotations\Revs;
10+
11+
/**
12+
* @BeforeMethods({"init"})
13+
*/
14+
class HasIntersectionBench
15+
{
16+
use GenerateIntervalTrait;
17+
18+
private const AMOUNT_INTERVALS_IN_TREE = 10000;
19+
private const MAX_INTERVAL_HIGH = 250000;
20+
private const MAX_INTERVAL_OFFSET = 100;
21+
22+
/**
23+
* @var IntervalTree
24+
*/
25+
private $tree;
26+
27+
/**
28+
* @var Interval[]
29+
*/
30+
private $bruteForceList;
31+
32+
public function init(): void
33+
{
34+
$this->tree = new IntervalTree();
35+
$this->bruteForceList = [];
36+
37+
for ($i = 0; $i < self::AMOUNT_INTERVALS_IN_TREE; $i++) {
38+
$interval = $this->generateInterval();
39+
$this->tree->insert($interval);
40+
$this->bruteForceList[] = $interval;
41+
}
42+
}
43+
44+
/**
45+
* @Revs(1000)
46+
*/
47+
public function benchTree(): void
48+
{
49+
$searchedInterval = $this->generateInterval();
50+
$this->tree->hasIntersection($searchedInterval);
51+
}
52+
53+
/**
54+
* @Revs(1000)
55+
*/
56+
public function benchBruteForce(): void
57+
{
58+
$searchedInterval = $this->generateInterval();
59+
foreach ($this->bruteForceList as $interval) {
60+
if ($interval->intersect($searchedInterval)) {
61+
break;
62+
}
63+
}
64+
}
65+
66+
/**
67+
* @return Interval
68+
*/
69+
private function generateInterval(): Interval
70+
{
71+
try {
72+
$low = random_int(0, self::MAX_INTERVAL_HIGH);
73+
$high = random_int($low, min($low + self::MAX_INTERVAL_OFFSET, self::MAX_INTERVAL_HIGH));
74+
} catch (Exception $exception) {
75+
echo 'Cannot generate interval: ' . $exception->getMessage();
76+
exit;
77+
}
78+
return new Interval($low, $high);
79+
}
80+
}

0 commit comments

Comments
 (0)