asmblah/heap-walker

PHP用户空间堆遍历器

v1.1.0 2021-10-08 00:31 UTC

This package is auto-updated.

Last update: 2024-08-30 01:20:35 UTC


README

Build Status

尽可能遍历用户空间堆,寻找给定FQCN(完全限定类名)的实例。

这有助于确定给定对象被引用的位置,以帮助解决内存泄漏问题。

用法

安装

composer require --dev asmblah/heap-walker

使用

<?php

// ...

$heapWalk = new HeapWalk();
// Find all instances of Item and how to reach them.
$pathSets = $heapWalk->getInstancePathSets([Item::class]);

// Inspect the result as needed.

完整示例

<?php

use Asmblah\HeapWalk\HeapWalk;
use Asmblah\HeapWalk\Result\Path\InstancePathSet;

require_once __DIR__ . '/vendor/autoload.php';

class Item
{
    public $description;

    public function __construct($description)
    {
        $this->description = $description;
    }
}

class Bag
{
    // Note that visibility is ignored.
    private static $items = [];

    public static function init()
    {
        self::$items[] = new Item('a cabbage');
    }
}

Bag::init();

$heapWalk = new HeapWalk();
// Find all instances of Item and how to reach them.
$pathSets = $heapWalk->getInstancePathSets([Item::class]);

// Inspect the result as needed.
assert(count($pathSets) === 1);
assert($pathSets[0] instanceof InstancePathSet);
assert(count($pathSets[0]->getPaths()) === 1);
assert($pathSets[0]->getPaths()[0]->toString() === 'Bag::$items[0]');
assert($pathSets[0]->getPaths()[0]->getEventualValue() instanceof Item);
assert($pathSets[0]->getPaths()[0]->getEventualValue()->description === 'a cabbage');

注意事项与限制

  • 除了全局作用域之外的作用域不会被完全检查;只有通过使用debug_backtrace()捕获它们的参数。

  • 暂停的生成器的局部作用域不可访问。例如,如果暂停的生成器内部声明了一个没有其他引用的迭代变量$i,那么它将不会被找到。

  • 如果捕获的对象是另一个未捕获对象的子代,那么(目前)递归处理意味着只记录通过未捕获对象到达捕获对象的第一个路径。例如,在Symfony容器中的服务将通过$kernel->bundles->...->container[...]显示,而不会也通过$kernel->container[...]显示。

  • PHP对象之间的内部引用,这些引用不会暴露给用户空间,是无法发现的。例如,PDOStatement对其PDOConnection有一个内部强引用,但是无法从PDOStatement访问PDOConnection。可以使用uopz扩展挂钩PDOConnection->prepare(...)并将其从PDOStatement链接回来(例如,在未来的插件中),但是必须小心处理以避免阻止PDOConnection被GC。