diff --git a/src/Service/FilesObserver/Converter/Cost.php b/src/Service/FilesObserver/Converter/Cost.php index b5e63787..d96bab71 100644 --- a/src/Service/FilesObserver/Converter/Cost.php +++ b/src/Service/FilesObserver/Converter/Cost.php @@ -19,19 +19,19 @@ final class Cost implements \JsonSerializable public float $p_wt = 0; - /** @var int<0, max> */ + /** @var int */ public int $d_cpu = 0; - /** @var int<0, max> */ + /** @var int */ public int $d_ct = 0; - /** @var int<0, max> */ + /** @var int */ public int $d_mu = 0; - /** @var int<0, max> */ + /** @var int */ public int $d_pmu = 0; - /** @var int<0, max> */ + /** @var int */ public int $d_wt = 0; /** diff --git a/src/Service/FilesObserver/Converter/Edge.php b/src/Service/FilesObserver/Converter/Edge.php index 59bae540..7d30b748 100644 --- a/src/Service/FilesObserver/Converter/Edge.php +++ b/src/Service/FilesObserver/Converter/Edge.php @@ -9,6 +9,10 @@ */ final class Edge implements \JsonSerializable { + /** + * @param non-empty-string|null $caller + * @param non-empty-string $callee + */ public function __construct( public readonly ?string $caller, public readonly string $callee, diff --git a/src/Service/FilesObserver/Converter/XHProf.php b/src/Service/FilesObserver/Converter/XHProf.php index 83eaa837..8a0ab73e 100644 --- a/src/Service/FilesObserver/Converter/XHProf.php +++ b/src/Service/FilesObserver/Converter/XHProf.php @@ -19,6 +19,9 @@ * pmu: int<0, max> * }> * + * @psalm-import-type Metadata from \Buggregator\Trap\Proto\Frame\Profiler\Payload + * @psalm-import-type Calls from \Buggregator\Trap\Proto\Frame\Profiler\Payload + * * @internal */ final class XHProf implements FileFilterInterface @@ -33,16 +36,19 @@ public function validate(FileInfo $file): bool return $file->getExtension() === 'xhprof'; } + /** + * @return \Traversable + */ public function convert(FileInfo $file): \Traversable { try { + /** @var Metadata $metadata */ $metadata = [ 'date' => $file->mtime, 'hostname' => \explode('.', $file->getName(), 2)[0], 'filename' => $file->getName(), ]; - /** @psalm-suppress MixedArgumentTypeCoercion */ yield new ProfilerFrame( ProfilerFrame\Payload::new( type: ProfilerFrame\Type::XHProf, @@ -62,10 +68,10 @@ public function convert(FileInfo $file): \Traversable /** * @param RawData $data + * @return Calls */ private function dataToPayload(array $data): array { - /** @var array> $data */ $peaks = [ 'cpu' => 0, 'ct' => 0, @@ -77,15 +83,13 @@ private function dataToPayload(array $data): array /** @var Tree $tree */ $tree = new Tree(); - // \uasort($data, static function (array $a, array $b) { - // return $b['wt'] <=> $a['wt']; - // }); - foreach ($data as $key => $value) { - [$caller, $callee] = \explode('==>', $key, 2) + [1 => null]; - if ($callee === null) { + [$caller, $callee] = \explode('==>', $key, 2) + [1 => '']; + if ($callee === '') { [$caller, $callee] = [null, $caller]; } + $caller === '' and $caller = null; + \assert($callee !== ''); $edge = new Edge( caller: $caller, @@ -102,8 +106,10 @@ private function dataToPayload(array $data): array $tree->addItem($edge, $edge->callee, $edge->caller); } - // Calc percentages and delta - /** @var Branch $branch */ + /** + * Calc percentages and delta + * @var Branch $branch Needed for IDE + */ foreach ($tree->getIterator() as $branch) { $cost = $branch->item->cost; $cost->p_cpu = $peaks['cpu'] > 0 ? \round($cost->cpu / $peaks['cpu'] * 100, 3) : 0; @@ -114,11 +120,11 @@ private function dataToPayload(array $data): array if ($branch->parent !== null) { $parentCost = $branch->parent->item->cost; - $cost->d_cpu = $cost->cpu - ($parentCost->cpu); - $cost->d_ct = $cost->ct - ($parentCost->ct); - $cost->d_mu = $cost->mu - ($parentCost->mu); - $cost->d_pmu = $cost->pmu - ($parentCost->pmu); - $cost->d_wt = $cost->wt - ($parentCost->wt); + $cost->d_cpu = $cost->cpu - $parentCost->cpu; + $cost->d_ct = $cost->ct - $parentCost->ct; + $cost->d_mu = $cost->mu - $parentCost->mu; + $cost->d_pmu = $cost->pmu - $parentCost->pmu; + $cost->d_wt = $cost->wt - $parentCost->wt; } }