Passed
Push — master ( 5c7bad...ea47a1 )
by Alec
03:06
created

BenchmarkReport::__toString()   B

Complexity

Conditions 7
Paths 10

Size

Total Lines 33
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 7.0957

Importance

Changes 0
Metric Value
cc 7
eloc 24
nc 10
nop 0
dl 0
loc 33
ccs 21
cts 24
cp 0.875
crap 7.0957
rs 8.6026
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 AlecRabbit\Tools\Benchmark;
11
use AlecRabbit\Tools\Internal\BenchmarkFunction;
12
use AlecRabbit\Tools\Reports\Base\Report;
13
use AlecRabbit\Tools\Timer;
14
use AlecRabbit\Tools\Traits\BenchmarkFields;
15
use function AlecRabbit\brackets;
16
use function AlecRabbit\format_time;
17
use function AlecRabbit\typeOf;
18
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...
19
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...
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
        $this->totalIterations = $reportable->getTotalIterations();
34 2
        $this->withResults = $reportable->isWithResults();
35 2
        $this->exceptionMessages = $reportable->getExceptionMessages();
36 2
    }
37
38
    /**
39
     * @return string
40
     */
41 1
    public function __toString(): string
42
    {
43 1
        $profilerReport = (string)$this->getProfiler()->getReport();
44 1
        $r = 'Benchmark:' . PHP_EOL;
45 1
        foreach ($this->computeRelatives() as $indexName => $result) {
46 1
            $function = $this->getFunctionObject($indexName);
47 1
            $arguments = $function->getArgs();
48 1
            $types = [];
49 1
            if (!empty($arguments)) {
50 1
                foreach ($arguments as $argument) {
51 1
                    $types[] = typeOf($argument);
52
                }
53
            }
54 1
            $r .= sprintf(
55 1
                '+%s %s(%s) %s %s',
56 1
                $result,
57 1
                $function->getIndexedName(),
58 1
                implode(', ', $types),
59 1
                $function->getComment(),
60 1
                PHP_EOL
61
            );
62 1
            if ($this->withResults) {
63 1
                $r .= var_export($function->getResult(), true) . PHP_EOL;
64
            }
65
        }
66 1
        if (!empty($this->exceptionMessages)) {
67
            $r .= 'Exceptions:'. PHP_EOL;
68
            foreach ($this->exceptionMessages as $name => $exceptionMessage) {
69
                $r .= brackets($name). ': '. $exceptionMessage . PHP_EOL;
70
            }
71
        }
72
        return
73 1
            $r . PHP_EOL . $profilerReport;
74
    }
75
76
    /**
77
     * @return array
78
     */
79 1
    private function computeRelatives(): array
80
    {
81 1
        $averages = $this->computeAverages(
82 1
            $this->profiler->getTimers()
83
        );
84
85 1
        $min = min($averages);
86
87 1
        $relatives = [];
88 1
        foreach ($averages as $name => $average) {
89 1
            $relatives[$name] = $average / $min;
90
        }
91 1
        asort($relatives);
92
93 1
        foreach ($relatives as $name => $relative) {
94 1
            $relatives[$name] =
95 1
                $this->percent((float)$relative - 1) . ' ' .
96 1
                brackets(format_time($averages[$name]), BRACKETS_PARENTHESES);
97
        }
98 1
        return $relatives;
99
    }
100
101
    /**
102
     * @param array $timers
103
     * @return array
104
     */
105 1
    private function computeAverages(array $timers): array
106
    {
107 1
        $averages = [];
108
        /** @var Timer $timer */
109 1
        foreach ($timers as $timer) {
110 1
            if (DEFAULT_NAME !== $name = $timer->getName()) {
111 1
                $averages[$name] = $timer->getAverageValue();
112
            }
113
        }
114 1
        return $averages;
115
    }
116
117
    /**
118
     * @param float $relative
119
     * @return string
120
     */
121 1
    private function percent(float $relative): string
122
    {
123
        return
124 1
            number_format($relative * 100, 1) . '%';
125
    }
126
127
    /**
128
     * @param string $name
129
     * @return BenchmarkFunction
130
     */
131 1
    private function getFunctionObject(string $name): BenchmarkFunction
132
    {
133 1
        return $this->functions[$name];
134
    }
135
}
136