Completed
Push — develop ( f10e50...4f888d )
by Alec
03:20
created

BenchmarkReport::computeRelatives()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 4
nop 0
dl 0
loc 20
ccs 13
cts 13
cp 1
crap 3
rs 9.8666
c 0
b 0
f 0
1
<?php
2
/**
3
 * User: alec
4
 * Date: 29.11.18
5
 * Time: 20:56
6
 */
7
8
namespace AlecRabbit\Tools\Reports;
9
10
use function AlecRabbit\brackets;
11
use const AlecRabbit\Constants\Accessories\DEFAULT_NAME;
0 ignored issues
show
Bug introduced by
The constant AlecRabbit\Constants\Accessories\DEFAULT_NAME was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
12
use const AlecRabbit\Constants\BRACKETS_PARENTHESES;
0 ignored issues
show
Bug introduced by
The constant AlecRabbit\Constants\BRACKETS_PARENTHESES was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
13
use function AlecRabbit\format_time;
14
use AlecRabbit\Tools\Benchmark;
15
use AlecRabbit\Tools\Internal\BenchmarkedFunction;
16
use AlecRabbit\Tools\Reports\Base\Report;
17
use AlecRabbit\Tools\Timer;
18
use AlecRabbit\Tools\Traits\BenchmarkFields;
19
use function AlecRabbit\typeOf;
20
21
class BenchmarkReport extends Report
22
{
23
    use BenchmarkFields;
24
25
    /**
26
     * BenchmarkReport constructor.
27
     * @param Benchmark $reportable
28
     */
29 2
    public function __construct(Benchmark $reportable)
30
    {
31 2
        $this->profiler = $reportable->getProfiler();
32 2
        $this->functions = $reportable->getFunctions();
33 2
    }
34
35
    /**
36
     * @return string
37
     */
38 1
    public function __toString(): string
39
    {
40 1
        $r = (string)$this->getProfiler()->report();
41 1
        $r .= 'Benchmark:' . PHP_EOL;
42 1
        foreach ($this->computeRelatives() as $indexName => $result) {
43 1
            $function = $this->getFunctionObject($indexName);
44 1
            $arguments = $function->getArgs();
45 1
            $types = [];
46 1
            if (!empty($arguments)) {
47
                foreach ($arguments as $argument) {
48
                    $types[] = typeOf($argument);
49
                }
50
            }
51 1
            $r .= sprintf(
52 1
                '+%s [%s] %s(%s) %s' . PHP_EOL,
53 1
                $result,
54 1
                $function->getIndex(),
55 1
                $function->getName(),
56 1
                implode(', ', $types),
57 1
                $function->getComment()
58
            );
59
        }
60
        return
61 1
            $r;
62
    }
63
64
    /**
65
     * @return array
66
     */
67 1
    private function computeRelatives(): array
68
    {
69 1
        $averages = $this->computeAverages(
70 1
            $this->profiler->getTimers()
71
        );
72
73 1
        $min = min($averages);
74
75 1
        $relatives = [];
76 1
        foreach ($averages as $name => $average) {
77 1
            $relatives[$name] = $average / $min;
78
        }
79 1
        asort($relatives);
80
81 1
        foreach ($relatives as $name => $relative) {
82 1
            $relatives[$name] =
83 1
                $this->percent((float)$relative - 1) . ' ' .
84 1
                brackets(format_time($averages[$name]), BRACKETS_PARENTHESES);
85
        }
86 1
        return $relatives;
87
    }
88
89
    /**
90
     * @param array $timers
91
     * @return array
92
     */
93 1
    private function computeAverages(array $timers): array
94
    {
95 1
        $averages = [];
96
        /** @var Timer $timer */
97 1
        foreach ($timers as $timer) {
98 1
            if (DEFAULT_NAME !== $name = $timer->getName()) {
99 1
                $averages[$name] = $timer->getAverageValue();
100
            }
101
        }
102 1
        return $averages;
103
    }
104
105
    /**
106
     * @param float $relative
107
     * @return string
108
     */
109 1
    private function percent(float $relative): string
110
    {
111
        return
112 1
            number_format($relative * 100, 1) . '%';
113
    }
114
115
    /**
116
     * @param string $name
117
     * @return BenchmarkedFunction
118
     */
119 1
    private function getFunctionObject(string $name): BenchmarkedFunction
120
    {
121 1
        return $this->functions[$name];
122
    }
123
}
124