diff --git a/analyzer/src/BitOne/PhpMemInfo/Analyzer/TopRanges.php b/analyzer/src/BitOne/PhpMemInfo/Analyzer/TopRanges.php new file mode 100644 index 0000000..4d9870d --- /dev/null +++ b/analyzer/src/BitOne/PhpMemInfo/Analyzer/TopRanges.php @@ -0,0 +1,82 @@ +getMinMax($sortedDumpFiles); + + $allTypes = []; + foreach (array_keys($min) as $type) { + $allTypes[$type] = $type; + } + foreach (array_keys($max) as $type) { + $allTypes[$type] = $type; + } + + $ranges = []; + foreach ($allTypes as $type) { + $minVal = $min[$type] ?? 0; + $maxVal = $max[$type] ?? 0; + + $rangeVal = $maxVal - $minVal; + + if (($showZeroRange && 0 === $rangeVal) || $rangeVal > 0) { + $ranges[$type] = $rangeVal; + } + } + + arsort($ranges, SORT_NUMERIC); + + return $ranges; + } + + private function getTypeCount(array $items) + { + $typeCount = []; + + foreach ($items as $item) { + $type = ('object' === $item['type']) ? $item['class'] : $item['type']; + + if (!array_key_exists($type, $typeCount)) { + $typeCount[$type] = 0; + } + + ++$typeCount[$type]; + } + + return $typeCount; + } + + private function getMinMax(Finder $sortedDumpFiles) + { + $loader = new Loader(); + $min = []; + $max = []; + + /** @var SplFileInfo $sortedDumpFile */ + foreach ($sortedDumpFiles as $sortedDumpFile) { + $items = $loader->load($sortedDumpFile->getPathname()); + + $typeCount = $this->getTypeCount($items); + + foreach ($typeCount as $type => $count) { + if (!array_key_exists($type, $min) || $count < $min[$type]) { + $min[$type] = $count; + } + + if (!array_key_exists($type, $max) || $count > $max[$type]) { + $max[$type] = $count; + } + } + } + + return [$min, $max]; + } +} diff --git a/analyzer/src/BitOne/PhpMemInfo/Console/Application.php b/analyzer/src/BitOne/PhpMemInfo/Console/Application.php index 6c9bcb4..f307845 100644 --- a/analyzer/src/BitOne/PhpMemInfo/Console/Application.php +++ b/analyzer/src/BitOne/PhpMemInfo/Console/Application.php @@ -6,6 +6,7 @@ use BitOne\PhpMemInfo\Console\Command\ReferencePathCommand; use BitOne\PhpMemInfo\Console\Command\SummaryCommand; use BitOne\PhpMemInfo\Console\Command\TopChildrenCommand; +use BitOne\PhpMemInfo\Console\Command\TopRangesCommand; use BitOne\PhpMemInfo\Console\Command\TopSizeCommand; use Symfony\Component\Console\Application as BaseApplication; @@ -24,5 +25,6 @@ public function __construct() $this->add(new ReferencePathCommand()); $this->add(new SummaryCommand()); $this->add(new TopChildrenCommand()); + $this->add(new TopRangesCommand()); } } diff --git a/analyzer/src/BitOne/PhpMemInfo/Console/Command/TopRangesCommand.php b/analyzer/src/BitOne/PhpMemInfo/Console/Command/TopRangesCommand.php new file mode 100644 index 0000000..5be8954 --- /dev/null +++ b/analyzer/src/BitOne/PhpMemInfo/Console/Command/TopRangesCommand.php @@ -0,0 +1,62 @@ +setName('top-ranges') + ->setDescription('Given a directory of dump files sorted by name, this command displays the top ranges (difference between the largest and smallest values) of the dumped types.') + ->addArgument( + 'dump-dir', + InputArgument::REQUIRED, + 'PHP Meminfo Dump Files directory' + ) + ->addOption('show-zero', null, InputOption::VALUE_NONE, 'Show zero ranges') + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $dumpDir = $input->getArgument('dump-dir'); + + if (!file_exists($dumpDir)) { + throw new \InvalidArgumentException(sprintf('Directory %s does not exist.', $dumpDir)); + } + + $sortedDumpFiles = Finder::create()->files()->in($dumpDir)->name('*.json')->sortByName(true); + $output->writeln(sprintf('%d dump files found.', $sortedDumpFiles->count())); + + $topRanges = new TopRanges(); + $topRangeByType = $topRanges->get($sortedDumpFiles, (bool) $input->getOption('show-zero')); + + $table = new Table($output); + + $table->setHeaders(['Type', 'Range']); + + foreach ($topRangeByType as $type => $range) { + $table->addRow([$type, $range]); + } + + $table->render(); + + return Command::SUCCESS; + } +}