Completed
Push — develop ( d2e190...d276d7 )
by Alec
10:43 queued 07:55
created

BenchmarkReport::getFormatter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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