packages/deriver/bench/CliBench.php
1<?php
2
3declare(strict_types=1);
4
5namespace Bench;
6
7use Deriver\Deriver;
8use Deriver\Deriver\BranchEvaluators;
9use Deriver\Deriver\Candidate\CandidateCollection;
10use Deriver\Deriver\DeriverConfig;
11use Deriver\Deriver\MicroEvaluator;
12use Deriver\Finder;
13use PhpBench\Attributes as Bench;
14use RuntimeException;
15
16#[Bench\Iterations(5)]
17#[Bench\Revs(1)]
18#[Bench\Warmup(0)]
19#[Bench\OutputTimeUnit('milliseconds')]
20final class CliBench
21{
22 private const QUERIES = [
23 'HarborOps\Queue\RetryPolicy::delay#return',
24 'HarborOps\Moderation\ReviewPolicy::initialState#return',
25 'HarborOps\Moderation\ReviewPolicy::resolutionState#return',
26 'HarborOps\Import\Importer::import#return',
27 ];
28
29 /** @var list<string> */
30 private array $files;
31 private DeriverConfig $configuration;
32 private Deriver $prepared;
33 /** @var list<CandidateCollection> */
34 private array $results = [];
35
36 public function locate(): void
37 {
38 $this->locateWithEvaluators([]);
39 }
40
41 public function locateWithBranchPruning(): void
42 {
43 $this->locateWithEvaluators(BranchEvaluators::truth());
44 }
45
46 /** @param list<MicroEvaluator> $evaluators */
47 public function locateWithEvaluators(array $evaluators): void
48 {
49 $root = __DIR__ . '/target/cli';
50 $this->files = (new Finder())->in($root)
51 ->include('**/*.php', 'bin/harbor')
52 ->exclude('vendor', 'tests', 'var')
53 ->files();
54 $this->configuration = new DeriverConfig(phpVersion: '8.4', evaluators: $evaluators);
55 }
56
57 public function prepare(): void
58 {
59 $this->locate();
60 $this->prepared = Deriver::prepare($this->files, $this->configuration);
61 }
62
63 public function prepareWithBranchPruning(): void
64 {
65 $this->locateWithBranchPruning();
66 $this->prepared = Deriver::prepare($this->files, $this->configuration);
67 }
68
69 #[Bench\BeforeMethods('locate')]
70 #[Bench\Groups(['preparation'])]
71 public function benchPrepare(): void
72 {
73 $this->prepared = Deriver::prepare($this->files, $this->configuration);
74 }
75
76 #[Bench\BeforeMethods('prepare')]
77 #[Bench\Groups(['first-query'])]
78 #[Bench\AfterMethods('verifyResults')]
79 public function benchFirstQuery(): void
80 {
81 $this->results = [$this->prepared->derive(self::QUERIES[0])];
82 }
83
84 #[Bench\BeforeMethods('prepare')]
85 #[Bench\Groups(['query-batch'])]
86 #[Bench\AfterMethods('verifyResults')]
87 public function benchQueryBatch(): void
88 {
89 $this->results = [];
90 foreach (self::QUERIES as $query) {
91 $this->results[] = $this->prepared->derive($query);
92 }
93 }
94
95 #[Bench\BeforeMethods('locateWithBranchPruning')]
96 #[Bench\Groups(['preparation', 'branch-pruning'])]
97 public function benchPrepareWithBranchPruning(): void
98 {
99 $this->benchPrepare();
100 }
101
102 #[Bench\BeforeMethods('prepareWithBranchPruning')]
103 #[Bench\Groups(['first-query', 'branch-pruning'])]
104 #[Bench\AfterMethods('verifyResults')]
105 public function benchFirstQueryWithBranchPruning(): void
106 {
107 $this->benchFirstQuery();
108 }
109
110 #[Bench\BeforeMethods('prepareWithBranchPruning')]
111 #[Bench\Groups(['query-batch', 'branch-pruning'])]
112 #[Bench\AfterMethods('verifyResults')]
113 public function benchQueryBatchWithBranchPruning(): void
114 {
115 $this->benchQueryBatch();
116 }
117
118 public function verifyResults(): void
119 {
120 foreach ($this->results as $collection) {
121 if (count($collection) === 0) {
122 throw new RuntimeException('A benchmark query returned no candidates.');
123 }
124 }
125 }
126}
127