Skip to content

Commit addb1ef

Browse files
authored
Create ExecComparator.php
1 parent aa7ba56 commit addb1ef

File tree

1 file changed

+316
-0
lines changed

1 file changed

+316
-0
lines changed

src/Util/ExecComparator.php

Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
<?php
2+
/**
3+
* Created by PhpStorm.
4+
* User: inhere
5+
* Date: 2017-12-21
6+
* Time: 9:51
7+
*/
8+
9+
namespace Inhere\Extra\Components;
10+
11+
use Toolkit\Stdlib\OS;
12+
13+
/**
14+
* Class ExecComparator - PHP code exec speed comparator
15+
* @package Inhere\Extra\Components
16+
*/
17+
class ExecComparator
18+
{
19+
/**
20+
* @var string
21+
*/
22+
private $tmpDir;
23+
24+
/**
25+
* @var array
26+
*/
27+
private $vars = [];
28+
29+
/**
30+
* @var array
31+
*/
32+
private $results = [];
33+
34+
/** @var string[] */
35+
private $sample1 = [
36+
'code' => '',
37+
'title' => '',
38+
];
39+
40+
/** @var string[] */
41+
private $sample2 = [
42+
'code' => '',
43+
'title' => '',
44+
];
45+
46+
/** @var string */
47+
private $common;
48+
49+
/** @var int */
50+
private $loops = 100000;
51+
52+
/** @var string */
53+
private $time;
54+
55+
/**
56+
* ExecComparator constructor.
57+
* @param string|null $tmpDir
58+
*/
59+
public function __construct(string $tmpDir = null)
60+
{
61+
$this->tmpDir = $tmpDir ?? OS::getTempDir();
62+
}
63+
64+
/**
65+
* @param string $code
66+
* @return $this
67+
*/
68+
public function setCommon(string $code)
69+
{
70+
$this->common = $code;
71+
72+
return $this;
73+
}
74+
75+
/**
76+
* @param int $times
77+
* @return $this
78+
*/
79+
public function setLoops(int $times)
80+
{
81+
if ($times <= 0) {
82+
throw new \InvalidArgumentException('The time must be gt zero');
83+
}
84+
85+
$this->loops = $times;
86+
87+
return $this;
88+
}
89+
90+
/**
91+
* @param string $code
92+
* @param string $title
93+
* @return $this
94+
*/
95+
public function setSample1(string $code, string $title)
96+
{
97+
$this->sample1['code'] = $code;
98+
$this->sample1['title'] = $title;
99+
100+
return $this;
101+
}
102+
103+
/**
104+
* @param string $code
105+
* @param string $title
106+
* @return $this
107+
*/
108+
public function setSample2(string $code, string $title)
109+
{
110+
$this->sample2['code'] = $code;
111+
$this->sample2['title'] = $title;
112+
113+
return $this;
114+
}
115+
116+
/**
117+
* @param int $loops
118+
* @return $this
119+
*/
120+
public function compare(int $loops = 0)
121+
{
122+
if ($loops) {
123+
$this->setLoops($loops);
124+
}
125+
126+
$sTime = microtime(1);
127+
$this->time = date('ymdH');
128+
129+
$id = 1;
130+
$file1 = $this->dump($this->sample1['code'], $id);
131+
$this->results['sample1'] = $this->runSampleFile($file1, $id);
132+
133+
$id = 2;
134+
$file2 = $this->dump($this->sample2['code'], $id);
135+
$this->results['sample2'] = $this->runSampleFile($file2, $id);
136+
$eTime = microtime(1);
137+
138+
$this->results['total'] = [
139+
'startTime' => $sTime,
140+
'endTime' => $eTime,
141+
'timeDiff' => round($eTime - $sTime, 3),
142+
];
143+
144+
return $this;
145+
}
146+
147+
/**
148+
* @param string $as
149+
* @return array|string
150+
*/
151+
public function getResults(string $as = 'text')
152+
{
153+
$ret = $this->results;
154+
$s1 = $ret['sample1'];
155+
$s2 = $ret['sample2'];
156+
$t1 = $this->sample1['title'];
157+
$t2 = $this->sample2['title'];
158+
159+
$ret['title'] = 'Code execution speed comparison';
160+
$ret['description'] = "sample1({$t1}) VS sample2({$t2})";
161+
$timeDiff = round($s1['timeConsumption'] - $s2['timeConsumption'], 4);
162+
$memDiff = round(($s1['memConsumption'] - $s2['memConsumption']) / 1024, 4);
163+
164+
$faster = $timeDiff > 0 ? $t2 : $t1;
165+
$eatMore = $memDiff > 0 ? $t1 : $t2;
166+
167+
if ((string)$memDiff === '0') {
168+
$eatMore = '[IGNORE - can be ignored]';
169+
}
170+
// $fastDiff = abs($timeDiff);
171+
// $memDiff = abs($memDiff);
172+
173+
switch ($as) {
174+
case 'text':
175+
$results = <<<TXT
176+
{$ret['title']}
177+
178+
- loop times: {$this->loops}
179+
- {$ret['description']}
180+
181+
DETAIL
182+
183+
item sample 1 sample 2 diff(1 - 2)
184+
time {$s1['timeConsumption']} {$s2['timeConsumption']} $timeDiff s
185+
memory {$s1['memConsumption']} b {$s2['memConsumption']} b $memDiff k
186+
187+
RESULT
188+
189+
- Run faster is: $faster
190+
- Consume more memory is: $eatMore
191+
- Test the total time spent: {$ret['total']['timeDiff']} s
192+
TXT;
193+
break;
194+
case 'json':
195+
$results = json_encode($ret, JSON_PRETTY_PRINT);
196+
break;
197+
case 'md':
198+
case 'markdown':
199+
$results = <<<TXT
200+
# {$ret['title']}
201+
202+
- loop times: {$this->loops}
203+
- {$ret['description']}
204+
205+
## Detail
206+
207+
item | sample 1 | sample 2 | diff(1 - 2)
208+
--------|----------|----------|--------------
209+
time | {$s1['timeConsumption']} | {$s2['timeConsumption']} | $timeDiff s
210+
memory | {$s1['memConsumption']} b | {$s2['memConsumption']} b | $memDiff k
211+
212+
## Result
213+
214+
- Run faster is: $faster
215+
- Consume more memory is: $eatMore
216+
- Test the total time spent: {$ret['total']['timeDiff']} s
217+
TXT;
218+
break;
219+
case 'array':
220+
default:
221+
return $ret;
222+
}
223+
224+
return $results;
225+
}
226+
227+
public function resultToText()
228+
{
229+
230+
}
231+
232+
/**
233+
* @param string $file
234+
* @param int $id
235+
* @return array
236+
*/
237+
public function runSampleFile(string $file, int $id): array
238+
{
239+
// load php file
240+
require $file;
241+
242+
$func = 'sample_func_' . $id;
243+
$sMem = memory_get_usage();
244+
$sTime = microtime(1);
245+
246+
// running
247+
// ob_start();
248+
$ret = $func();
249+
// $out = ob_get_clean();
250+
251+
$eMem = memory_get_usage();
252+
$eTime = microtime(1);
253+
254+
return [
255+
'startTime' => $sTime,
256+
'endTime' => $eTime,
257+
'startMem' => $sMem,
258+
'endMem' => $eMem,
259+
// 'output' => $out,
260+
'return' => $ret,
261+
'memConsumption' => round($eMem - $sMem, 4),
262+
'timeConsumption' => round($eTime - $sTime, 5),
263+
];
264+
}
265+
266+
/**
267+
* @param string $code
268+
* @param int $id
269+
* @return string
270+
*/
271+
public function dump(string $code, int $id): string
272+
{
273+
$file = $this->tmpDir . '/' . $this->time . '_' . md5($code . random_int(1000, 100000)) . '.php';
274+
$common = $this->common;
275+
276+
$content = <<<CODE
277+
function sample_func_{$id}() {
278+
// prepare
279+
$common
280+
281+
// exec
282+
for (\$i = 0; \$i < $this->loops; \$i++) {
283+
$code
284+
}
285+
}
286+
CODE;
287+
288+
file_put_contents($file, '<?php' . PHP_EOL . $content);
289+
290+
return $file;
291+
}
292+
293+
/**
294+
* @return array
295+
*/
296+
public function getVars(): array
297+
{
298+
return $this->vars;
299+
}
300+
301+
/**
302+
* @param array $vars
303+
*/
304+
public function setVars(array $vars)
305+
{
306+
$this->vars = $vars;
307+
}
308+
309+
/**
310+
* @param array $results
311+
*/
312+
public function setResults(array $results)
313+
{
314+
$this->results = $results;
315+
}
316+
}

0 commit comments

Comments
 (0)