1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
/* |
6
|
|
|
* This file is part of DivineNii opensource projects. |
7
|
|
|
* |
8
|
|
|
* PHP version 7.4 and above required |
9
|
|
|
* |
10
|
|
|
* @author Divine Niiquaye Ibok <[email protected]> |
11
|
|
|
* @copyright 2019 DivineNii (https://divinenii.com/) |
12
|
|
|
* @license https://opensource.org/licenses/BSD-3-Clause License |
13
|
|
|
* |
14
|
|
|
* For the full copyright and license information, please view the LICENSE |
15
|
|
|
* file that was distributed with this source code. |
16
|
|
|
*/ |
17
|
|
|
|
18
|
|
|
namespace App\BenchMark\Reporter\Printer; |
19
|
|
|
|
20
|
|
|
use App\BenchMark\Reporter\BenchMark; |
21
|
|
|
|
22
|
|
|
class Text implements PrinterInterface |
23
|
|
|
{ |
24
|
|
|
protected BenchMark $benchmark; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* {@inheritdoc} |
28
|
|
|
*/ |
29
|
|
|
public function bind(BenchMark $benchmark): void |
30
|
|
|
{ |
31
|
|
|
$this->benchmark = $benchmark; |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* {@inheritdoc} |
36
|
|
|
*/ |
37
|
|
|
public function chart(): string |
38
|
|
|
{ |
39
|
|
|
$result = ''; |
40
|
|
|
$maxLength = $maxRate = 0; |
41
|
|
|
$ranking = $this->benchmark->getMatrix()->ranking(); |
42
|
|
|
|
43
|
|
|
foreach ($ranking as $task) { |
44
|
|
|
if ($task->failed()) { |
45
|
|
|
continue; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
if ($task->rate() > $maxRate) { |
49
|
|
|
$maxRate = $task->rate(); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
if (\mb_strlen($task->name()) > $maxLength) { |
53
|
|
|
$maxLength = \mb_strlen($task->name()); |
54
|
|
|
} |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
foreach ($ranking as $task) { |
58
|
|
|
$name = $task->name(); |
59
|
|
|
$result .= $this->strPad($name, $maxLength, ' ', \STR_PAD_RIGHT); |
60
|
|
|
|
61
|
|
|
if ($task->failed()) { |
62
|
|
|
$ratio = 0; |
63
|
|
|
$result .= $this->strPad('x', 10); |
64
|
|
|
} else { |
65
|
|
|
$rate = $task->rate(); |
66
|
|
|
$ratio = ($rate / $maxRate); |
67
|
|
|
$result .= $this->strPad(\round($ratio * 100) . '%', 10); |
68
|
|
|
} |
69
|
|
|
$result .= ' | '; |
70
|
|
|
|
71
|
|
|
$width = 60; |
72
|
|
|
$chars = (int) ($width * $ratio); |
73
|
|
|
$result .= \str_repeat('█', $chars); |
74
|
|
|
$result .= \str_repeat(' ', $width - $chars); |
75
|
|
|
$result .= " |\n"; |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
return $result; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Returns the report. |
83
|
|
|
* |
84
|
|
|
* @return string the report |
85
|
|
|
*/ |
86
|
|
|
public function table(): string |
87
|
|
|
{ |
88
|
|
|
$ranking = $this->benchmark->getMatrix()->ranking(); |
89
|
|
|
$matrix = $this->benchmark->getMatrix()->matrix(); |
90
|
|
|
|
91
|
|
|
if (!$ranking) { |
|
|
|
|
92
|
|
|
return ''; |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
$columnLength = []; |
96
|
|
|
$maxLength = 0; |
97
|
|
|
|
98
|
|
|
foreach ($ranking as $task) { |
99
|
|
|
$name = $task->name(); |
100
|
|
|
|
101
|
|
|
if (\preg_match('~^([\w\s]+)~', $name, $matches)) { |
102
|
|
|
$columnLength[$name] = \mb_strlen(\trim($matches[1])); |
103
|
|
|
} else { |
104
|
|
|
$columnLength[$name] = \mb_strlen($name); |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
if (\mb_strlen($name) > $maxLength) { |
108
|
|
|
$maxLength = \mb_strlen($name); |
109
|
|
|
} |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
$result = ''; |
113
|
|
|
$result .= $this->strPad('', $maxLength); |
114
|
|
|
$result .= $this->strPad('Rate', 10); |
115
|
|
|
$result .= $this->strPad('Mem', 8); |
116
|
|
|
|
117
|
|
|
foreach ($ranking as $task) { |
118
|
|
|
$name = $task->name(); |
119
|
|
|
|
120
|
|
|
if (\preg_match('~^([\w\s]+)~', $name, $matches)) { |
121
|
|
|
$result .= $this->strPad(\trim($matches[1]), $columnLength[$name] + 2); |
122
|
|
|
} else { |
123
|
|
|
$result .= $this->strPad($name, $columnLength[$name] + 2); |
124
|
|
|
} |
125
|
|
|
} |
126
|
|
|
$result .= "\n"; |
127
|
|
|
|
128
|
|
|
foreach ($ranking as $task1) { |
129
|
|
|
$name1 = $task1->name(); |
130
|
|
|
$result .= $this->strPad($name1, $maxLength, ' ', \STR_PAD_RIGHT); |
131
|
|
|
$task1 = $this->_benchmark->task($name1); |
|
|
|
|
132
|
|
|
|
133
|
|
|
$result .= $this->strPad($this->readableSize($task1->rate()) . '/s', 10); |
134
|
|
|
$result .= $this->strPad($this->readableSize($task1->memory(), 0, 1024) . 'B', 8); |
135
|
|
|
|
136
|
|
|
foreach ($ranking as $task2) { |
137
|
|
|
$name2 = $task2->name(); |
138
|
|
|
|
139
|
|
|
if ($task1->failed() || $task2->failed()) { |
140
|
|
|
$result .= $this->strPad('x', $columnLength[$name2] + 2); |
141
|
|
|
} else { |
142
|
|
|
$percent = $matrix[$name1][$name2] !== 100 ? $matrix[$name1][$name2] : '--'; |
143
|
|
|
$result .= $this->strPad($percent . '%', $columnLength[$name2] + 2); |
144
|
|
|
} |
145
|
|
|
} |
146
|
|
|
$result .= "\n"; |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
return $result; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* Humanizes values using an appropriate unit. |
154
|
|
|
* |
155
|
|
|
* @return int $value the value |
156
|
|
|
* @return int $precision the required precision |
157
|
|
|
* @return int $base the unit base |
158
|
|
|
* @return string the Humanized string value |
159
|
|
|
*/ |
160
|
|
|
public function readableSize($value, $precision = 0, $base = 1000): string |
161
|
|
|
{ |
162
|
|
|
$i = 0; |
163
|
|
|
|
164
|
|
|
if (!$value) { |
165
|
|
|
return '0'; |
|
|
|
|
166
|
|
|
} |
167
|
|
|
$isNeg = false; |
168
|
|
|
|
169
|
|
|
if ($value < 0) { |
170
|
|
|
$isNeg = true; |
171
|
|
|
$value = -$value; |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
if ($value >= 1) { |
175
|
|
|
$units = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']; |
176
|
|
|
|
177
|
|
|
while (($value / $base) >= 1) { |
178
|
|
|
$value = $value / $base; |
179
|
|
|
$i++; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
$unit = $units[$i] ?? '?'; |
183
|
|
|
} else { |
184
|
|
|
$units = ['', 'm', 'µ', 'n', 'p', 'f', 'a', 'z']; |
185
|
|
|
|
186
|
|
|
while (($value * $base) <= $base) { |
187
|
|
|
$value = $value * $base; |
188
|
|
|
$i++; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
$unit = $units[$i] ?? '?'; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
return \round($isNeg ? -$value : $value, $precision) . $unit; |
|
|
|
|
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* Pad a string to a certain length with another string. |
199
|
|
|
* |
200
|
|
|
* @param string $input the input string |
201
|
|
|
* @param string $length the padding length |
202
|
|
|
* @param string $string the padding string |
203
|
|
|
* @param string $type the type of padding |
204
|
|
|
* |
205
|
|
|
* @return string the padded string |
206
|
|
|
*/ |
207
|
|
|
public function strPad($input, $length, $string = ' ', $type = \STR_PAD_LEFT) |
208
|
|
|
{ |
209
|
|
|
return \str_pad($input, $length + \strlen($input) - \mb_strlen($input), $string, $type); |
|
|
|
|
210
|
|
|
} |
211
|
|
|
} |
212
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.