清除PHP正在使用的内存

时间:2012-11-24 01:42:30

标签: php memory phpunit

我遇到了一个有趣的问题。我正在使用PHPUnit,我的测试每次运行时都会占用更多内存。即...

2.25 MB

2.5 MB

3.0 MB

3.5 MB .......

有谁知道如何清除正在消耗的内存,任何人都可以建议我深入探讨这个问题吗?当前的问题是我的一些较大的测试耗尽了内存,并且只是继续增加PHP中的最大内存分配还不够......我需要知道为什么从命令行运行的PHPUnit测试会有内存在跑步之间“徘徊”的用法。

4 个答案:

答案 0 :(得分:24)

内存增加有三到四个原因:

1)PHPUnit收集代码覆盖率数据

除了关闭代码覆盖率外,你无能为力。

2)PHPUnit缓存文件令牌以获取代码覆盖率

您可以在PHPUnit xml中使用<phpunit cacheTokens="false">。请参阅http://phpunit.de/manual/current/en/installation.html#installing.upgrading

中有关此内容的说明

3)PHPUnit自身没有正确清理

在其当前实现中,它保留了测试用例,因为存储结果数据的位置。在未来,这将变得更加有效,但现在它是如何运作的。

4)通往&#34; 4&#34;:你需要自己清理

由于保留了TestCase个实例,因此您的成员变量也会被保留。

意味着您可以使用

节省大量内存
public function tearDown() {
    unset($this->whatever);
}

但这样做非常乏味。

我的建议是为所有TestCase设置一个基础测试类并使用它:

class MyBaseTest extends \PHPUnit_Framework_TestCase {

    protected function tearDown()
    {
        $refl = new \ReflectionObject($this);
        foreach ($refl->getProperties() as $prop) {
            if (!$prop->isStatic() && 0 !== strpos($prop->getDeclaringClass()->getName(), 'PHPUnit_')) {
                $prop->setAccessible(true);
                $prop->setValue($this, null);
            }
        }
    }
}

这将以一种不错的自动方式清理完毕。

(该片段的道具转到:http://kriswallsmith.net/post/18029585104/faster-phpunit


PHPUnit不能以向后兼容的方式执行此操作,不会破坏人们的项目,因此您必须为自己添加它:)

答案 1 :(得分:5)

Calvin,正如chat中讨论的那样,这是由于缺少重置功能。

测试时,我们必须确保测试环境一致,以便我们能够获得准确的结果。计算是输入/输出,因此我们应该使用Fixtures in PHPUnit重置存储以防止像这样的“内存泄漏”。

答案 2 :(得分:4)

@Unorian和@mauris已经涵盖了PHPUnit垃圾收集背后的技术细节,但是我想补充一点,PHPUnit(至少在我正在运行的3.7.21版本中)让你能够添加评价:

/**
 * @backupGlobals disabled
 */
class MyClassTests extends PHPUnit_Framework_TestCase{}

在添加注释之前,我的每次运行测试套件的内存使用量大致翻了一倍,最后一次测试大约1100 MB。现在他们的运行速度为15 MB。

答案 3 :(得分:1)

如果您正在使用PDO(或类似的数据库抽象),那么您可以使用“sqlite :: memory:”作为DSN。这有三大优势:

  1. 每次测试后自动清理
  2. 不会意外触碰生产数据库(例如,即使您在生产服务器上运行单元测试)。
  3. 全部在内存中,因此测试可以更快地运行
  4. 缺点是您的SQL必须可以在MySQL和SQLite之间移植。这可能是相当多的工作(对于更大的项目,它通常是值得的,不仅仅是测试,而是它将改进代码设计的方式。)在你的情况下,你提到使用Doctrine,在聊天记录中,所以你可能已经有了很好的抽象,因此它可能只是在SQLite上没有变化的情况下运行。