読者です 読者をやめる 読者になる 読者になる

脳みそスワップアウト

揮発性なもので。おもにPHPのこととか。

phpunitが遅い

phpunit php

PHPUnitが遅い

カバレッジを出力しているわけでもないのに、phpunitの動作が遅い。
調べたのでメモ。

なぜ遅いか

PHPUnit_TextUI_TestRunner

PHPUnit_TextUI_Command::main() → run() → createRunner() という流れで作られる。
このコンストラクタ

if ($filter === null) {
    $filter = $this->getCodeCoverageFilter();
}
$this->codeCoverageFilter = $filter;
$this->loader             = $loader;
$runtime = new Runtime;
$this->canCollectCodeCoverage = $runtime->canCollectCodeCoverage();

getCodeCoverageFilter()

private function getCodeCoverageFilter()
    {
        $filter = new PHP_CodeCoverage_Filter;
        if (defined('__PHPUNIT_PHAR__')) {
            $filter->addFileToBlacklist(__PHPUNIT_PHAR__);
        }
        $blacklist = new PHPUnit_Util_Blacklist;
        foreach ($blacklist->getBlacklistedDirectories() as $directory) {
            $filter->addDirectoryToBlacklist($directory);
        }
        return $filter;
    }

カバレッジ対象の Blacklist/Whitelist を準備している。

PHPUnit_Util_Blacklist は、phpunitの依存ライブラリが定義されている。

PHP_CodeCoverage_Filter の addFileToBlacklist(), addDirectoryToBlacklist() は、
最終的にブラックリスト対象のファイルのフルパスをhashに作る。
$black[realpath($path)] = true のような。

addDirectoryToBlacklist() の方は、ディレクトリを再帰的に渡っていくため、
さらに SplFileInfo::realpath() を使っている。

ディスクの遅い環境だと、この realpath() と SplFileInfo::realpath() が遅くなる。
それが大量に実行されるため、強烈に遅くなる。

カバレッジを出力するのなら仕方ないのだけど、
カバレッジなしのテスト時にまでこれが実行されるのは困った問題。

暫定対応

このような仕様になったのは 4.6.4 からのようなので、4.6.3 を使うことにした。
これだけ違う。

phpunit 4.7.5

[02:35:04 vagrant@phpvm appname]$ php -d auto_prepend_file=xhprof_prepend.php ./vendor/bin/phpunit tests/TestCase/Model/
PHPUnit 4.7.5 by Sebastian Bergmann and contributors.

.....................

Time: 1.58 minutes, Memory: 18.50Mb

OK (21 tests, 81 assertions)

phpunit 4.6.3

[02:37:09 vagrant@phpvm appname]$ php -d auto_prepend_file=xhprof_prepend.php ./vendor/bin/phpunit tests/TestCase/Model/
PHPUnit 4.6.3 by Sebastian Bergmann and contributors.

Configuration read from /projects/prj1/appname/phpunit.xml

.....................

Time: 2.64 seconds, Memory: 17.00Mb

OK (21 tests, 81 assertions)

Blacklist対象の数にもよるが、今回は45倍早くなった。