Completed
Push — develop ( ca99c7...b953bd )
by Alec
03:03
created

BenchmarkReport::updateFunctions()   A

Complexity

Conditions 6
Paths 4

Size

Total Lines 23
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 6

Importance

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