Test Setup Failed
Push — develop ( 7cd2b2...750858 )
by Alec
03:42
created

BenchmarkReport::buildOn()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

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