-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProfiler.php
More file actions
78 lines (67 loc) · 2.46 KB
/
Copy pathProfiler.php
File metadata and controls
78 lines (67 loc) · 2.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?php
declare(strict_types=1);
/*
* This file is part of the univeros/framework
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Altair\Profiling;
use Altair\Profiling\Model\ProfileReport;
use Altair\Profiling\Model\SampleLog;
use Altair\Profiling\Sampler\Contracts\SamplerInterface;
use Altair\Profiling\Tree\HotspotAnalyzer;
use Altair\Profiling\Tree\TreeBuilder;
/**
* In-process profiler: wraps a callable in start/stop sampler calls and folds
* the captured samples into a {@see ProfileReport}.
*
* Useful as a library API (`$profiler->profile(fn() => $svc->run(), 'svc.run')`)
* and as the inner engine for the CLI subprocess path. The Profiler does not
* persist anything — the caller passes the resulting report to a storage if
* they want it kept.
*/
final readonly class Profiler
{
public function __construct(
private SamplerInterface $sampler,
private TreeBuilder $treeBuilder = new TreeBuilder(),
private HotspotAnalyzer $hotspots = new HotspotAnalyzer(),
) {}
public function profile(callable $target, string $description, int $hotspotLimit = HotspotAnalyzer::DEFAULT_LIMIT): ProfileReport
{
$startNs = hrtime(true);
$this->sampler->start();
try {
$target();
} finally {
$log = $this->sampler->stop();
$durationMs = (int) ((hrtime(true) - $startNs) / 1_000_000);
}
return $this->buildReport($log, $description, $durationMs, $hotspotLimit);
}
public function fromSampleLog(SampleLog $log, string $description, int $durationMs, int $hotspotLimit = HotspotAnalyzer::DEFAULT_LIMIT): ProfileReport
{
return $this->buildReport($log, $description, $durationMs, $hotspotLimit);
}
private function buildReport(SampleLog $log, string $description, int $durationMs, int $hotspotLimit): ProfileReport
{
$tree = $this->treeBuilder->build($log->samples);
$hotspots = $this->hotspots->analyse($tree, $hotspotLimit);
return new ProfileReport(
$this->generateId(),
$description,
date(DATE_ATOM),
$log->totalSamples(),
$durationMs,
$log->periodUs,
$log->backend,
$tree,
$hotspots,
);
}
private function generateId(): string
{
return date('Ymd-His') . '-' . bin2hex(random_bytes(3));
}
}