Skip to content

Commit dda0cea

Browse files
MaxSemnikic
authored andcommitted
run-tests: add skip cache
Currently every --SKIPIF-- section in every test file results in 1 extra execution of PHP, every --EXTENSIONS-- section - in 2 executions. This is quite wasteful, as skip checking code is extremely repetitive and extensions are fixed for every binary/ini/command parameters combination. This patch adds caching to all such checks. On my machine, the gains are quite noticeable: 36s instead of 43s with -j16, 292s instead of 337s without concurrency. Cache stats are 3780 hits, 1247 misses in the latter case. In the future, tests could be adjusted to have more uniform skip checks to improve performance even more. Closes GH-6681.
1 parent b84e3b1 commit dda0cea

File tree

1 file changed

+82
-13
lines changed

1 file changed

+82
-13
lines changed

run-tests.php

Lines changed: 82 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1832,6 +1832,11 @@ function run_test(string $php, $file, array $env): string
18321832
/** @var JUnit */
18331833
global $junit;
18341834

1835+
static $skipCache;
1836+
if (!$skipCache) {
1837+
$skipCache = new SkipCache($cfg['keep']['skip']);
1838+
}
1839+
18351840
$temp_filenames = null;
18361841
$org_file = $file;
18371842

@@ -2155,9 +2160,8 @@ function run_test(string $php, $file, array $env): string
21552160
$ext_params = [];
21562161
settings2array($ini_overwrites, $ext_params);
21572162
$ext_params = settings2params($ext_params);
2158-
$ext_dir = `$php $pass_options $extra_options $ext_params $no_file_cache -d display_errors=0 -r "echo ini_get('extension_dir');"`;
21592163
$extensions = preg_split("/[\n\r]+/", trim($section_text['EXTENSIONS']));
2160-
$loaded = explode(",", `$php $pass_options $extra_options $ext_params $no_file_cache -d display_errors=0 -r "echo implode(',', get_loaded_extensions());"`);
2164+
[$ext_dir, $loaded] = $skipCache->getExtensions("$php $pass_options $extra_options $ext_params $no_file_cache");
21612165
$ext_prefix = IS_WINDOWS ? "php_" : "";
21622166
foreach ($extensions as $req_ext) {
21632167
if (!in_array($req_ext, $loaded)) {
@@ -2217,7 +2221,6 @@ function run_test(string $php, $file, array $env): string
22172221
if (array_key_exists('SKIPIF', $section_text)) {
22182222
if (trim($section_text['SKIPIF'])) {
22192223
show_file_block('skip', $section_text['SKIPIF']);
2220-
save_text($test_skipif, $section_text['SKIPIF'], $temp_skipif);
22212224
$extra = !IS_WINDOWS ?
22222225
"unset REQUEST_METHOD; unset QUERY_STRING; unset PATH_TRANSLATED; unset SCRIPT_FILENAME; unset REQUEST_METHOD;" : "";
22232226

@@ -2229,8 +2232,9 @@ function run_test(string $php, $file, array $env): string
22292232
$junit->startTimer($shortname);
22302233

22312234
$startTime = microtime(true);
2232-
$output = system_with_timeout("$extra $php $pass_options $extra_options -q $orig_ini_settings $no_file_cache -d display_errors=1 -d display_startup_errors=0 \"$test_skipif\"", $env);
2233-
$output = trim($output);
2235+
$commandLine = "$extra $php $pass_options $extra_options -q $orig_ini_settings $no_file_cache -d display_errors=1 -d display_startup_errors=0";
2236+
$output = $skipCache->checkSkip($commandLine, $section_text['SKIPIF'], $test_skipif, $temp_skipif, $env);
2237+
22342238
$time = microtime(true) - $startTime;
22352239

22362240
$junit->stopTimer($shortname);
@@ -2245,21 +2249,13 @@ function run_test(string $php, $file, array $env): string
22452249
];
22462250
}
22472251

2248-
if (!$cfg['keep']['skip']) {
2249-
@unlink($test_skipif);
2250-
}
2251-
22522252
if (!strncasecmp('skip', $output, 4)) {
22532253
if (preg_match('/^skip\s*(.+)/i', $output, $m)) {
22542254
show_result('SKIP', $tested, $tested_file, "reason: $m[1]", $temp_filenames);
22552255
} else {
22562256
show_result('SKIP', $tested, $tested_file, '', $temp_filenames);
22572257
}
22582258

2259-
if (!$cfg['keep']['skip']) {
2260-
@unlink($test_skipif);
2261-
}
2262-
22632259
$message = !empty($m[1]) ? $m[1] : '';
22642260
$junit->markTestAs('SKIP', $shortname, $tested, null, $message);
22652261
return 'SKIPPED';
@@ -3716,6 +3712,79 @@ private function mergeSuites(array &$dest, array $source): void
37163712
}
37173713
}
37183714

3715+
class SkipCache
3716+
{
3717+
private bool $keepFile;
3718+
3719+
private array $skips = [];
3720+
private array $extensions = [];
3721+
3722+
private int $hits = 0;
3723+
private int $misses = 0;
3724+
private int $extHits = 0;
3725+
private int $extMisses = 0;
3726+
3727+
public function __construct(bool $keepFile)
3728+
{
3729+
$this->keepFile = $keepFile;
3730+
}
3731+
3732+
public function checkSkip(string $php, string $code, string $checkFile, string $tempFile, array $env): string
3733+
{
3734+
// Extension tests frequently use something like <?php require 'skipif.inc';
3735+
// for skip checks. This forces us to cache per directory to avoid pollution.
3736+
$dir = dirname($checkFile);
3737+
$key = "$php => $dir";
3738+
3739+
if (isset($this->skips[$key][$code])) {
3740+
$this->hits++;
3741+
if ($this->keepFile) {
3742+
save_text($checkFile, $code, $tempFile);
3743+
}
3744+
return $this->skips[$key][$code];
3745+
}
3746+
3747+
save_text($checkFile, $code, $tempFile);
3748+
$result = trim(system_with_timeout("$php \"$checkFile\"", $env));
3749+
$this->skips[$key][$code] = $result;
3750+
$this->misses++;
3751+
3752+
if (!$this->keepFile) {
3753+
@unlink($checkFile);
3754+
}
3755+
3756+
return $result;
3757+
}
3758+
3759+
public function getExtensions(string $php): array
3760+
{
3761+
if (isset($this->extensions[$php])) {
3762+
$this->extHits++;
3763+
return $this->extensions[$php];
3764+
}
3765+
3766+
$extDir = `$php -d display_errors=0 -r "echo ini_get('extension_dir');"`;
3767+
$extensions = explode(",", `$php -d display_errors=0 -r "echo implode(',', get_loaded_extensions());"`);
3768+
3769+
$result = [$extDir, $extensions];
3770+
$this->extensions[$php] = $result;
3771+
$this->extMisses++;
3772+
3773+
return $result;
3774+
}
3775+
3776+
// public function __destruct()
3777+
// {
3778+
// echo "Skips: {$this->hits} hits, {$this->misses} misses.\n";
3779+
// echo "Extensions: {$this->extHits} hits, {$this->extMisses} misses.\n";
3780+
// echo "Cache distribution:\n";
3781+
//
3782+
// foreach ($this->skips as $php => $cache) {
3783+
// echo "$php: " . count($cache) . "\n";
3784+
// }
3785+
// }
3786+
}
3787+
37193788
class RuntestsValgrind
37203789
{
37213790
protected $version = '';

0 commit comments

Comments
 (0)