Skip to content

Commit 0e3dcce

Browse files
committed
Profiling.
1 parent 32fa907 commit 0e3dcce

File tree

4 files changed

+219
-0
lines changed

4 files changed

+219
-0
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"require": {
1919
"php": "^7.4|^8.0",
2020
"illuminate/contracts": "^8.0",
21+
"illuminate/support": "^7.0|^8.0",
2122
"laravel/slack-notification-channel": "^2.3"
2223
},
2324
"require-dev": {

src/Profiling/ServerMemory.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace Binarcode\LaravelDeveloper\Profiling;
4+
5+
class ServerMemory
6+
{
7+
/** @var array */
8+
protected $finishedEvents = [];
9+
10+
/** @var array */
11+
protected $startedEvents = [];
12+
13+
public function start(string $key = 'measure')
14+
{
15+
$this->startedEvents[$key] = memory_get_usage();
16+
17+
return $this;
18+
}
19+
20+
public function stop(string $key = 'measure')
21+
{
22+
if (! array_key_exists($key, $this->startedEvents)) {
23+
return $this;
24+
}
25+
26+
$this->setMemory(
27+
$key,
28+
memory_get_usage() - $this->startedEvents[$key]
29+
);
30+
31+
unset($this->startedEvents[$key]);
32+
33+
return $this;
34+
}
35+
36+
public function setMemory(string $key, $duration)
37+
{
38+
if (is_callable($duration)) {
39+
$this->start($key);
40+
41+
call_user_func($duration);
42+
43+
$this->stop($key);
44+
} else {
45+
$this->finishedEvents[$key] = $duration;
46+
}
47+
48+
return $this;
49+
}
50+
51+
public function getMemory(string $key = 'measure', $unit = 'mb')
52+
{
53+
return $this->finishedEvents[$key]
54+
? collect([
55+
56+
'byte' => fn ($v) => $v,
57+
'mb' => fn ($v) => $v / (1000 * 1000),
58+
'gb' => fn ($v) => $v / (1000 * 1000 * 1000),
59+
60+
])->get($unit, 'mb')($this->finishedEvents[$key])
61+
: null;
62+
}
63+
64+
public static function measure(string $key = 'measure'): ServerMemory
65+
{
66+
return app(static::class)->start($key);
67+
}
68+
}

src/Profiling/ServerTiming.php

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?php
2+
3+
namespace Binarcode\LaravelDeveloper\Profiling;
4+
5+
use Symfony\Component\Stopwatch\Stopwatch;
6+
7+
class ServerTiming
8+
{
9+
/** @var Stopwatch */
10+
protected $stopwatch;
11+
12+
/** @var array */
13+
protected $finishedEvents = [];
14+
15+
/** @var array */
16+
protected $startedEvents = [];
17+
18+
public function __construct(Stopwatch $stopwatch)
19+
{
20+
$this->stopwatch = $stopwatch;
21+
}
22+
23+
public function addMetric(string $metric)
24+
{
25+
$this->finishedEvents[$metric] = null;
26+
27+
return $this;
28+
}
29+
30+
public function hasStartedEvent(string $key): bool
31+
{
32+
return array_key_exists($key, $this->startedEvents);
33+
}
34+
35+
public function measure(string $key)
36+
{
37+
if (! $this->hasStartedEvent($key)) {
38+
return $this->start($key);
39+
}
40+
41+
return $this->stop($key);
42+
}
43+
44+
public function start(string $key)
45+
{
46+
$this->stopwatch->start($key);
47+
48+
$this->startedEvents[$key] = true;
49+
50+
return $this;
51+
}
52+
53+
public function stop(string $key = 'measure')
54+
{
55+
if ($this->stopwatch->isStarted($key)) {
56+
$event = $this->stopwatch->stop($key);
57+
58+
$this->setDuration($key, $event->getDuration());
59+
60+
unset($this->startedEvents[$key]);
61+
}
62+
63+
return $this;
64+
}
65+
66+
public function stopAllUnfinishedEvents()
67+
{
68+
foreach (array_keys($this->startedEvents) as $startedEventName) {
69+
$this->stop($startedEventName);
70+
}
71+
}
72+
73+
public function setDuration(string $key, $duration)
74+
{
75+
if (is_callable($duration)) {
76+
$this->start($key);
77+
78+
call_user_func($duration);
79+
80+
$this->stop($key);
81+
} else {
82+
$this->finishedEvents[$key] = $duration;
83+
}
84+
85+
return $this;
86+
}
87+
88+
public function getDuration(string $key = 'measure', $unit = 's')
89+
{
90+
return $this->finishedEvents[$key]
91+
? collect([
92+
93+
'ms' => fn ($v) => $v,
94+
's' => fn ($v) => $v / 1000,
95+
'm' => fn ($v) => $v / (1000 * 60),
96+
97+
])->get($unit, 's')($this->finishedEvents[$key])
98+
: null;
99+
}
100+
101+
public function events(): array
102+
{
103+
return $this->finishedEvents;
104+
}
105+
106+
public static function startWithoutKey(): ServerTiming
107+
{
108+
return app(static::class)->start('measure');
109+
}
110+
}

src/helpers.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
use Binarcode\LaravelDeveloper\Profiling\ServerMemory;
4+
use Binarcode\LaravelDeveloper\Profiling\ServerTiming;
5+
6+
if (! function_exists('measure_memory')) {
7+
function measure_memory($callable = null, string $key = 'action', string $unit = 'mb')
8+
{
9+
/** @var ServerMemory $timing */
10+
$timing = app(ServerMemory::class);
11+
12+
if (is_callable($callable)) {
13+
$timing->setMemory($key, $callable);
14+
15+
return dd($timing->getMemory($key, $unit));
16+
}
17+
18+
$timing->measure($key);
19+
20+
return dd($timing->getMemory($key, $unit));
21+
}
22+
}
23+
24+
if (! function_exists('measure_timing')) {
25+
function measure_timing($callable = null, string $key = 'action')
26+
{
27+
/** @var ServerTiming $timing */
28+
$timing = app(ServerTiming::class);
29+
30+
if (is_callable($callable)) {
31+
$timing->setDuration($key, $callable);
32+
33+
return dd($timing->getDuration($key));
34+
}
35+
36+
$timing->measure($key);
37+
38+
return dd($timing->getDuration($key));
39+
}
40+
}

0 commit comments

Comments
 (0)