Completed
Push — develop ( a0bdf0...500e55 )
by Alec
02:54
created

BenchmarkReport::getFormatter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AlecRabbit\Tools\Reports;
6
7
use AlecRabbit\Tools\Benchmark;
8
use AlecRabbit\Tools\Internal\BenchmarkFunction;
9
use AlecRabbit\Tools\Internal\BenchmarkRelative;
10
use AlecRabbit\Tools\Reports\Contracts\BenchmarkReportInterface;
11
use AlecRabbit\Tools\Reports\Contracts\ReportableInterface;
12
use AlecRabbit\Tools\Reports\Contracts\ReportInterface;
13
use AlecRabbit\Tools\Reports\Core\Report;
14
use AlecRabbit\Tools\Reports\Formatters\Contracts\FormatterInterface;
15
use AlecRabbit\Tools\Traits\BenchmarkFields;
16
use const AlecRabbit\Traits\Constants\DEFAULT_NAME;
17
18
class BenchmarkReport extends Report implements BenchmarkReportInterface
19
{
20
    use BenchmarkFields;
21
22 6
    protected static function getFormatter(): FormatterInterface
23
    {
24
        return
25 6
            Factory::getBenchmarkReportFormatter();
26
    }
27
28
    /**
29
     * @param ReportableInterface $benchmark
30
     * @return Contracts\ReportInterface
31
     * @throws \RuntimeException
32
     * @throws \Exception
33
     */
34 10
    public function buildOn(ReportableInterface $benchmark): ReportInterface
35
    {
36 10
        if ($benchmark instanceof Benchmark) {
37 9
            $this->added = $benchmark->getAdded();
38 9
            $this->benchmarked = $benchmark->getBenchmarked();
39 9
            $this->memoryUsageReport = $benchmark->getMemoryUsageReport();
40 9
            $this->doneIterations = $benchmark->getDoneIterations();
41 9
            $this->doneIterationsCombined = $benchmark->getDoneIterationsCombined();
42 9
            $this->functions = $this->updateFunctions($benchmark->getFunctions());
43 9
            $this->timer = $benchmark->getTimer();
44
        } else {
45 1
            $this->wrongReportable(Benchmark::class, $benchmark);
46
        }
47 9
        return $this;
48
    }
49
50
    /**
51
     * @param array $functions
52
     * @return array
53
     */
54 9
    private function updateFunctions(array $functions): array
55
    {
56 9
        $averages = $this->computeAverages($functions);
57 9
        $relatives = $this->computeRelatives($averages);
58 9
        $updatedFunctions = [];
59 9
        if (!empty($relatives)) {
60 5
            $rank = 0;
61 5
            foreach ($relatives as $name => $relative) {
62 5
                $function = $functions[$name] ?? null;
63 5
                $average = $averages[$name] ?? null;
64 5
                if (null !== $function && null !== $average) {
65 5
                    $function->setBenchmarkRelative(
66 5
                        new BenchmarkRelative(++$rank, (float)$relative - 1, (float)$average)
67
                    );
68
                }
69 5
                unset($functions[$name]);
70 5
                $updatedFunctions[$name] = $function;
71
            }
72
        }
73 9
        foreach ($functions as $name => $function) {
74 5
            $updatedFunctions[$name] = $function;
75
        }
76 9
        return $updatedFunctions;
77
    }
78
79
    /**
80
     * @param array $functions
81
     * @return array
82
     */
83 9
    private function computeAverages(array $functions): array
84
    {
85 9
        $averages = [];
86
        /** @var BenchmarkFunction $f */
87 9
        foreach ($functions as $f) {
88 6
            $timer = $f->getTimer();
89 6
            if ((DEFAULT_NAME !== $name = $timer->getName())
90 6
                && 0.0 !== $avg = $timer->getAverageValue()) {
91 5
                $averages[$name] = $avg;
92
            }
93
        }
94 9
        return $averages;
95
    }
96
97 9
    private function computeRelatives(array $averages): array
98
    {
99 9
        $rel = [];
100 9
        if (!empty($averages)) {
101 5
            $min = min($averages);
102
103 5
            foreach ($averages as $name => $average) {
104 5
                $rel[$name] = $average / $min;
105
            }
106 5
            asort($rel);
107
        }
108 9
        return $rel;
109
    }
110
111
    /** {@inheritdoc} */
112 1
    public function noReturns(): BenchmarkReportInterface
113
    {
114 1
        foreach ($this->functions as $function) {
115 1
            $function->setShowReturns(false);
116
        }
117 1
        return $this;
118
    }
119
}
120