Completed
Push — master ( ba86a8...110e22 )
by Alec
04:16 queued 41s
created

BenchmarkReport::computeRelatives()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

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