Skip to content

Diff command to compare two memory dumps #96

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,43 @@ Path from 0x7f94a1856260
+---------------------------+
```

## Comparing two memory dumps
Will allow you to see which objects counts and size have changed.

```bash
$ bin/analyzer diff [options] [--] <first-file> <second-file>

Arguments:
first-file PHP Meminfo Dump File in JSON format
second-file PHP Meminfo Dump File in JSON format to compare first file with

Options:
-s, --sort[=SORT] Define sorting order when displaying diff. Available options are :
- c : Sort by count
- s : Sort by size
- dc : Sort by the count differene
- ds : Sort by the size difference
-d, --only-diff If set, objects for which count is the same in both dumps will not be showed
```

### Example

Following example displays the diff sorting them by difference in size.

```bash
$ bin/analyzer diff eXpansion-mem-dump-2018-01-06T11\:37\:38+0000.json eXpansion-mem-dump-2018-01-06T12\:04\:23+0000.json -sds
+-------------------------------------------------------------+-----------------------+-----------------------------------+-----------------------+--------------------------+
| Type | First Instances Count | First Cumulated Self Size (bytes) | Second Instances Diff | Second Size Diff (bytes) |
+-------------------------------------------------------------+-----------------------+-----------------------------------+-----------------------+--------------------------+
| string | 7495 | 436324 | +372 | +23447 |
| array | 2097 | 150984 | +28 | +2016 |
| integer | 769 | 12304 | +61 | +976 |
| DateTime | 10 | 720 | +8 | +576 |
| boolean | 795 | 12720 | +15 | +240 |
| eXpansion\Bundle\LocalRecords\Model\Record | 2 | 144 | +2 | +144 |
| eXpansion\Framework\Core\Listener\BaseStorageUpdateListener | 3 | 216 | +1 | +72 |
```

A worflow to find and understand memory leak by using PHP Meminfo
-----------------------------------------------------------------

Expand Down
120 changes: 120 additions & 0 deletions analyzer/spec/BitOne/PhpMemInfo/Analyzer/SummaryDifferSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?php

namespace spec\BitOne\PhpMemInfo\Analyzer;

use PhpSpec\ObjectBehavior;

class SummaryDifferSpec extends ObjectBehavior
{

public function it_is_initializable()
{
$this->beConstructedWith([], []);
$this->shouldHaveType('BitOne\PhpMemInfo\Analyzer\SummaryDiffer');
}

public function it_generates_diff()
{
$firstItems = [
"0x7fb321a94050" => [
"type" => "string",
"size" => "29"
],
"0x7fb321a94080" => [
"type" => "string",
"size" => "29"
],
"0x7fb321a94108" => [
"type" => "string",
"size" => "37"
],
"0x7fe321a94108" => [
"type" => "string",
"size" => "45"
],
"0x7fb321a941e0" => [
"type" => "integer",
"size" => "24"
],
"0x7fb321a94268" => [
"type" => "integer",
"size" => "24"
],
"0x7fc321a94050" => [
"type" => "object",
"class" => "MyClassA",
"size" => "56"
],
"0x7fc321a94080" => [
"type" => "object",
"class" => "MyClassA",
"size" => "56"
],
"0x7fc321a94378" => [
"type" => "object",
"class" => "MyClassB",
"size" => "56"
]
];

$secondItems = [
"0x7fd04f5d4bb8" => [
"type" => "string",
"size" => "24"
],
"0x7fc321a94050" => [
"type" => "object",
"class" => "MyClassA",
"size" => "56"
],
"0x7fc321a94080" => [
"type" => "object",
"class" => "MyClassA",
"size" => "56"
],
"0x7fd04f5d4bc8" => [
"type" => "object",
"class" => "MyClassA",
"size" => "26",
],
"0x7fd04f5d4bd8" => [
"type" => "object",
"class" => "MyClassA",
"size" => "16",
],
"0x7fb321a941e0" => [
"type" => "integer",
"size" => "24"
],
"0x7fb321a94268" => [
"type" => "integer",
"size" => "24"
],
"0x7fd04f5d4bf8" => [
"type" => "object",
"class" => "MyClassC",
"size" => "56"
],
"0x7fd04f5d4bf9" => [
"type" => "object",
"class" => "MyClassC",
"size" => "56"
],
"0x7fd04f5d4bfa" => [
"type" => "object",
"class" => "MyClassC",
"size" => "56"
]
];

$this->beConstructedWith($firstItems, $secondItems);

$this->generateDiff()->shouldReturn([
['MyClassA', 2, 112, '+2', '+42'],
['MyClassC', 0, 0, '+3', '+168'],
['integer', 2, 48, '0', '0'],
['string', 4, 140, '-3', '-116'],
['MyClassB', 1, 56, '-1', '-56'],
]);
}
}
104 changes: 104 additions & 0 deletions analyzer/src/BitOne/PhpMemInfo/Analyzer/SummaryDiffer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

namespace BitOne\PhpMemInfo\Analyzer;

/**
* Analyzer to generate the differences between two memory dumps
*
* @author oliver de Cramer <[email protected]>
* @author Axel Ducret <[email protected]>
* @license http://opensource.org/licenses/MIT MIT
*/
class SummaryDiffer
{
/** @var array */
protected $firstItems;

/** @var array */
protected $secondItems;

/**
* @param array $firstItems
* @param array $secondItems
*/
public function __construct(array $firstItems, array $secondItems)
{
$this->firstItems = $firstItems;
$this->secondItems = $secondItems;
}

/**
* @return array
*/
public function generateDiff()
{
$firstSummary = $this->getSummaryForItems($this->firstItems);
$secondSummary = $this->getSummaryForItems($this->secondItems);
$rows = [];

foreach($secondSummary as $type => $stats) {
$firstSummaryCount = 0;
$firstSummarySize = 0;

if (isset($firstSummary[$type])) {
$firstSummaryCount = $firstSummary[$type]['count'];
$firstSummarySize = $firstSummary[$type]['self_size'];
unset($firstSummary[$type]);
}

$countDiff = $stats['count'] - $firstSummaryCount;
$sizeDiff = $stats['self_size'] - $firstSummarySize;

$rows[] = [
$type,
$firstSummaryCount,
$firstSummarySize,
$this->formatDiffValue($countDiff),
$this->formatDiffValue($sizeDiff)
];
}

// Let's not forget all elements completely removed from memory.
foreach ($firstSummary as $type => $stats) {
$countDiff = -$stats['count'];
$sizeDiff = -$stats['self_size'];

$rows[] = [
$type,
$stats['count'],
$stats['self_size'],
$this->formatDiffValue($countDiff),
$this->formatDiffValue($sizeDiff)
];
}

return $rows;
}

/**
* @param array $items
* @return array
*/
protected function getSummaryForItems(array $items)
{
$summaryCreator = new SummaryCreator($items);

return $summaryCreator->createSummary();
}

/**
* Format diff value for display
*
* @param int $value
*
* @return string
*/
protected function formatDiffValue($value)
{
if ($value > 0) {
return '+' . $value;
}

return strval($value);
}
}
3 changes: 2 additions & 1 deletion analyzer/src/BitOne/PhpMemInfo/Console/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
use BitOne\PhpMemInfo\Console\Command\QueryCommand;
use BitOne\PhpMemInfo\Console\Command\ReferencePathCommand;
use BitOne\PhpMemInfo\Console\Command\SummaryCommand;
use BitOne\PhpMemInfo\Console\Command\DiffCommand;
use BitOne\PhpMemInfo\Console\Command\TopChildrenCommand;
use BitOne\PhpMemInfo\Console\Command\TopSizeCommand;
use Symfony\Component\Console\Application as BaseApplication;

/**
Expand All @@ -23,6 +23,7 @@ public function __construct()
$this->add(new QueryCommand());
$this->add(new ReferencePathCommand());
$this->add(new SummaryCommand());
$this->add(new DiffCommand());
$this->add(new TopChildrenCommand());
}
}
Loading