bug #15443 [Debug] Enhance DebugClassLoader performance on MacOSX (nicolas-grekas)
This PR was merged into the 2.7 branch.
Discussion
----------
[Debug] Enhance DebugClassLoader performance on MacOSX
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #15442
| License | MIT
| Doc PR | -
Commits
-------
af0b8eb
[Debug] Enhance DebugClassLoader performance on MacOSX
This commit is contained in:
commit
7231598b4c
@ -32,6 +32,7 @@ class DebugClassLoader
|
|||||||
private static $caseCheck;
|
private static $caseCheck;
|
||||||
private static $deprecated = array();
|
private static $deprecated = array();
|
||||||
private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
|
private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
|
||||||
|
private static $darwinCache = array('/' => array('/', array()));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@ -220,33 +221,73 @@ class DebugClassLoader
|
|||||||
|
|
||||||
throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file));
|
throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file));
|
||||||
}
|
}
|
||||||
if (self::$caseCheck && preg_match('#([/\\\\][a-zA-Z_\x7F-\xFF][a-zA-Z0-9_\x7F-\xFF]*)+\.(php|hh)$#D', $file, $tail)) {
|
if (self::$caseCheck && preg_match('#(?:[/\\\\][a-zA-Z_\x7F-\xFF][a-zA-Z0-9_\x7F-\xFF]*+)++\.(?:php|hh)$#D', $file, $tail)) {
|
||||||
$tail = $tail[0];
|
$tail = $tail[0];
|
||||||
|
$tailLen = strlen($tail);
|
||||||
$real = $refl->getFileName();
|
$real = $refl->getFileName();
|
||||||
|
|
||||||
if (2 === self::$caseCheck) {
|
if (2 === self::$caseCheck) {
|
||||||
// realpath() on MacOSX doesn't normalize the case of characters
|
// realpath() on MacOSX doesn't normalize the case of characters
|
||||||
$cwd = getcwd();
|
|
||||||
$basename = strrpos($real, '/');
|
$i = 1 + strrpos($real, '/');
|
||||||
chdir(substr($real, 0, $basename));
|
$file = substr($real, $i);
|
||||||
$basename = substr($real, $basename + 1);
|
$real = substr($real, 0, $i);
|
||||||
// glob() patterns are case-sensitive even if the underlying fs is not
|
|
||||||
if (!in_array($basename, glob($basename.'*', GLOB_NOSORT), true)) {
|
if (isset(self::$darwinCache[$real])) {
|
||||||
$real = getcwd().'/';
|
$kDir = $real;
|
||||||
$h = opendir('.');
|
} else {
|
||||||
while (false !== $f = readdir($h)) {
|
$kDir = strtolower($real);
|
||||||
if (0 === strcasecmp($f, $basename)) {
|
|
||||||
$real .= $f;
|
if (isset(self::$darwinCache[$kDir])) {
|
||||||
break;
|
$real = self::$darwinCache[$kDir][0];
|
||||||
|
} else {
|
||||||
|
$dir = getcwd();
|
||||||
|
chdir($real);
|
||||||
|
$real = getcwd().'/';
|
||||||
|
chdir($dir);
|
||||||
|
|
||||||
|
$dir = $real;
|
||||||
|
$k = $kDir;
|
||||||
|
$i = strlen($dir) - 1;
|
||||||
|
while (!isset(self::$darwinCache[$k])) {
|
||||||
|
self::$darwinCache[$k] = array($dir, array());
|
||||||
|
self::$darwinCache[$dir] = &self::$darwinCache[$k];
|
||||||
|
|
||||||
|
while ('/' !== $dir[--$i]) {
|
||||||
|
}
|
||||||
|
$k = substr($k, 0, ++$i);
|
||||||
|
$dir = substr($dir, 0, $i--);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir($h);
|
|
||||||
}
|
}
|
||||||
chdir($cwd);
|
|
||||||
|
$dirFiles = self::$darwinCache[$kDir][1];
|
||||||
|
|
||||||
|
if (isset($dirFiles[$file])) {
|
||||||
|
$kFile = $file;
|
||||||
|
} else {
|
||||||
|
$kFile = strtolower($file);
|
||||||
|
|
||||||
|
if (!isset($dirFiles[$kFile])) {
|
||||||
|
foreach (scandir($real, 2) as $f) {
|
||||||
|
if ('.' !== $f[0]) {
|
||||||
|
$dirFiles[$f] = $f;
|
||||||
|
if ($f === $file) {
|
||||||
|
$kFile = $k = $file;
|
||||||
|
} elseif ($f !== $k = strtolower($f)) {
|
||||||
|
$dirFiles[$k] = $f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self::$darwinCache[$kDir][1] = $dirFiles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$real .= $dirFiles[$kFile];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 === substr_compare($real, $tail, -strlen($tail), strlen($tail), true)
|
if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
|
||||||
&& 0 !== substr_compare($real, $tail, -strlen($tail), strlen($tail), false)
|
&& 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
|
||||||
) {
|
) {
|
||||||
throw new \RuntimeException(sprintf('Case mismatch between class and source file names: %s vs %s', $class, $real));
|
throw new \RuntimeException(sprintf('Case mismatch between class and source file names: %s vs %s', $class, $real));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user