Closed rotexdegba closed 6 months ago
The DirectoriesSourceLocator
will do tons of sequential path scans: check if you can use a PSR locator or such instead.
The
DirectoriesSourceLocator
will do tons of sequential path scans: check if you can use a PSR locator or such instead.
Thanks for that tip
@Ocramius I changed the follwoing lines in my script from:
system("cd $code_left_branch_path && composer update"); // install composer dependencies
system("cd $code_right_branch_path && composer update"); // install composer dependencies
to
system("cd $code_left_branch_path && composer install --no-dev"); // install composer dependencies
system("cd $code_right_branch_path && composer install --no-dev"); // install composer dependencies
That has drastically improved the performance since huge dev dependencies like rector, psalm & phpunit are not being pulled in and scanned. It went from running in like close to 3 hours to about 3 minutes.
Here's the more performant script that makes use of the composer install without dev dependencies and swaps out the DirectoriesSourceLocator with (new MakeLocatorForComposerJsonAndInstalledJson)->__invoke(string $installationPath, Locator $astLocator): SourceLocator . Runs under 2 minutes.
<?php
include './vendor/autoload.php';
use Roave\BetterReflection\BetterReflection;
use Roave\BetterReflection\Reflector\DefaultReflector;
use Roave\BetterReflection\SourceLocator\SourceStubber\ReflectionSourceStubber;
use Roave\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\PhpInternalSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\DirectoriesSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\Composer\Factory\MakeLocatorForComposerJsonAndInstalledJson;
ini_set('display_errors', '1' );
ini_set('error_reporting', E_ALL);
ini_set('memory_limit', '2048M');
function readableElapsedTime($microtime, $format = null, $round = 3) {
if (is_null($format)) {
$format = '%.3f%s';
}
if ($microtime >= 3600) {
$unit = ' hour(s)';
$time = round(($microtime / 3600), $round);
} elseif ($microtime >= 60) {
$unit = ' minute(s)';
$time = round(($microtime / 60), $round);
} elseif ($microtime >= 1) {
$unit = ' second(s)';
$time = round($microtime, $round);
} else {
$unit = 'ms';
$time = round($microtime*1000);
$format = preg_replace('/(%.[\d]+f)/', '%d', $format);
}
return sprintf($format, $time, $unit);
}
$tmp_dir = sys_get_temp_dir() . DIRECTORY_SEPARATOR;
if(is_writable($tmp_dir)) {
gc_enable();
$start_time = microtime(true);
$classes_to_compare = [
'\\LeanOrm\\Model',
'\\LeanOrm\\DBConnector',
'\\LeanOrm\\CachingModel',
'\\LeanOrm\\Model\\Collection',
'\\LeanOrm\\Model\\Record',
'\\LeanOrm\\Model\\ReadOnlyRecord',
];
$repo_url = 'https://github.com/rotexsoft/leanorm.git';
$repo_name = 'leanorm';
$left_branch = 'master';
$right_branch = '4.x';
$code_left_branch_path = "{$tmp_dir}{$repo_name}-{$left_branch}";
$code_right_branch_path = "{$tmp_dir}{$repo_name}-{$right_branch}";
$clone_left_branch = "git clone -b {$left_branch} {$repo_url} {$code_left_branch_path}";
$clone_right_branch = "git clone -b {$right_branch} {$repo_url} {$code_right_branch_path}";
(file_exists($code_left_branch_path)) || system($clone_left_branch); // if already cloned, file_exists($code_left_branch_path), don't clone again
(file_exists($code_right_branch_path)) || system($clone_right_branch); // if already cloned, file_exists($code_right_branch_path), don't clone again
$current_directory = __DIR__;
system("cd $code_left_branch_path && composer install --no-dev"); // install composer dependencies
system("cd $code_right_branch_path && composer install --no-dev"); // install composer dependencies
system ("cd {$current_directory}");
////////////////////////////////////////////////////////////////////////////
echo PHP_EOL ."Processing all Class Files...." . PHP_EOL;
$astLocator = (new BetterReflection())->astLocator();
// $directoriesSourceLocator = new DirectoriesSourceLocator(
// [
// $code_left_branch_path . DIRECTORY_SEPARATOR . 'src',
// $code_left_branch_path . DIRECTORY_SEPARATOR . 'vendor',
// ],
// $astLocator
// );
$directoriesSourceLocator = (new MakeLocatorForComposerJsonAndInstalledJson)
(
$code_left_branch_path,
$astLocator
);
$reflector = new DefaultReflector(
new AggregateSourceLocator(
[
$directoriesSourceLocator,
new PhpInternalSourceLocator($astLocator, new ReflectionSourceStubber())
]
)
);
////////////////////////////////////////////////////////
$astLocator2 = (new BetterReflection())->astLocator();
// $directoriesSourceLocator2 = new DirectoriesSourceLocator(
// [
// $code_right_branch_path . DIRECTORY_SEPARATOR . 'src',
// $code_right_branch_path . DIRECTORY_SEPARATOR . 'vendor',
// ],
// $astLocator2
// );
$directoriesSourceLocator2 = (new MakeLocatorForComposerJsonAndInstalledJson)
(
$code_right_branch_path,
$astLocator2
);
$reflector2 = new DefaultReflector(
new AggregateSourceLocator(
[
$directoriesSourceLocator2,
new PhpInternalSourceLocator($astLocator, new ReflectionSourceStubber())
]
)
);
foreach($classes_to_compare as $class_to_compare) {
echo PHP_EOL ."Processing `{$class_to_compare}`...." . PHP_EOL;
////////////////////////////////////////////////////////
$reflectionClass = $reflector->reflectClass($class_to_compare);
$method_objs1 = $reflectionClass->getMethods();
$method_names1 = array_keys($method_objs1);
sort($method_names1);
//var_dump($method_names1);
////////////////////////////////////////////////////////
$reflectionClass2 = $reflector2->reflectClass($class_to_compare);
$method_objs2 = $reflectionClass2->getMethods();
$method_names2 = array_keys($method_objs2);
sort($method_names2);
//var_dump($method_names2);
$methods_in_left_not_in_right_branch = array_diff($method_names1, $method_names2);
$methods_in_right_branch_not_in_left = array_diff($method_names2, $method_names1);
echo PHP_EOL . "`{$class_to_compare}'s` Methods in `{$left_branch}` branch not in `{$right_branch}` branch:" . PHP_EOL;
echo implode(PHP_EOL, $methods_in_left_not_in_right_branch) . PHP_EOL;
echo PHP_EOL . "`{$class_to_compare}'s` Methods in `{$right_branch}` branch not in `{$left_branch}` branch:" . PHP_EOL;
echo implode(PHP_EOL, $methods_in_right_branch_not_in_left) . PHP_EOL;
echo PHP_EOL ."DONE: Processing `{$class_to_compare}`...." . PHP_EOL;
gc_collect_cycles();
}
$end_time = microtime(true);
$elapsed = $end_time - $start_time;
echo PHP_EOL . 'Time taken: ' . readableElapsedTime($elapsed). PHP_EOL. PHP_EOL;
} else {
echo PHP_EOL . "`{$tmp_dir}` is not writable. Exiting..." . PHP_EOL;
} // if(is_writable($tmp_dir)){...} else {...}
@rotexdegba btw I don't know if it fits your use case exactly, but we also have a tool - roave/backward-compatibility-check; it does more or less what you're doing there I think :)
That said, glad you are sorted! Closing this 🤘
Thanks @asgrim
I am using this package to compare classes between two branches of a github repo.
Here is what I have in my composer.json
Here is the output from
Below is the script I wrote:
Can someone give me any tips to make it run faster.
Thanks!!!!