Skip to content

Commit

Permalink
Show combined memory usage in parallel mode
Browse files Browse the repository at this point in the history
  • Loading branch information
janedbal committed Nov 23, 2022
1 parent 85ac37b commit 2eb2503
Show file tree
Hide file tree
Showing 18 changed files with 57 additions and 13 deletions.
2 changes: 2 additions & 0 deletions src/Analyser/Analyser.php
Expand Up @@ -10,6 +10,7 @@
use function array_fill_keys;
use function array_merge;
use function count;
use function memory_get_peak_usage;
use function sprintf;

class Analyser
Expand Down Expand Up @@ -110,6 +111,7 @@ public function analyse(
$internalErrorsCount === 0 ? $dependencies : null,
$exportedNodes,
$reachedInternalErrorsCountLimit,
memory_get_peak_usage(true),
);
}

Expand Down
6 changes: 6 additions & 0 deletions src/Analyser/AnalyserResult.php
Expand Up @@ -26,6 +26,7 @@ public function __construct(
private ?array $dependencies,
private array $exportedNodes,
private bool $reachedInternalErrorsCountLimit,
private int $estimatedPeakMemoryUsage,
)
{
$this->unorderedErrors = $errors;
Expand Down Expand Up @@ -97,4 +98,9 @@ public function hasReachedInternalErrorsCountLimit(): bool
return $this->reachedInternalErrorsCountLimit;
}

public function getEstimatedPeakMemoryUsage(): int
{
return $this->estimatedPeakMemoryUsage;
}

}
1 change: 1 addition & 0 deletions src/Analyser/ResultCache/ResultCacheManager.php
Expand Up @@ -424,6 +424,7 @@ public function process(AnalyserResult $analyserResult, ResultCache $resultCache
$dependencies,
$exportedNodes,
$analyserResult->hasReachedInternalErrorsCountLimit(),
$analyserResult->getEstimatedPeakMemoryUsage(),
), $saved);
}

Expand Down
7 changes: 6 additions & 1 deletion src/Command/AnalyseApplication.php
Expand Up @@ -71,6 +71,7 @@ public function analyse(
$internalErrors = [];
$collectedData = [];
$savedResultCache = false;
$estimatedMemoryUsage = 0;
if ($errorOutput->isDebug()) {
$errorOutput->writeLineFormatted('Result cache was not saved because of ignoredErrorHelperResult errors.');
}
Expand All @@ -97,6 +98,7 @@ public function analyse(
$intermediateAnalyserResult->getDependencies(),
$intermediateAnalyserResult->getExportedNodes(),
$intermediateAnalyserResult->hasReachedInternalErrorsCountLimit(),
$intermediateAnalyserResult->getEstimatedPeakMemoryUsage(),
);
}

Expand All @@ -105,6 +107,8 @@ public function analyse(
$internalErrors = $analyserResult->getInternalErrors();
$errors = $analyserResult->getErrors();
$hasInternalErrors = count($internalErrors) > 0 || $analyserResult->hasReachedInternalErrorsCountLimit();
$estimatedMemoryUsage = $analyserResult->getEstimatedPeakMemoryUsage();

if (!$hasInternalErrors) {
foreach ($this->getCollectedDataErrors($analyserResult->getCollectedData()) as $error) {
$errors[] = $error;
Expand Down Expand Up @@ -139,6 +143,7 @@ public function analyse(
$defaultLevelUsed,
$projectConfigFile,
$savedResultCache,
$estimatedMemoryUsage,
);
}

Expand Down Expand Up @@ -195,7 +200,7 @@ private function runAnalyser(
$errorOutput->getStyle()->progressStart($allAnalysedFilesCount);
$errorOutput->getStyle()->progressAdvance($allAnalysedFilesCount);
$errorOutput->getStyle()->progressFinish();
return new AnalyserResult([], [], [], [], [], false);
return new AnalyserResult([], [], [], [], [], false, memory_get_peak_usage(true));
}

if (!$debug) {
Expand Down
1 change: 1 addition & 0 deletions src/Command/AnalyseCommand.php
Expand Up @@ -379,6 +379,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$analysisResult->isDefaultLevelUsed(),
$analysisResult->getProjectConfigFile(),
$analysisResult->isResultCacheSaved(),
$analysisResult->getEstimatedPeakMemoryUsage(),
);

$stdOutput = $inceptionResult->getStdOutput();
Expand Down
3 changes: 2 additions & 1 deletion src/Command/AnalyserRunner.php
Expand Up @@ -14,6 +14,7 @@
use function count;
use function function_exists;
use function is_file;
use function memory_get_peak_usage;

class AnalyserRunner
{
Expand Down Expand Up @@ -48,7 +49,7 @@ public function runAnalyser(
{
$filesCount = count($files);
if ($filesCount === 0) {
return new AnalyserResult([], [], [], [], [], false);
return new AnalyserResult([], [], [], [], [], false, memory_get_peak_usage(true));
}

$schedule = $this->scheduler->scheduleWork($this->cpuCoreCounter->getNumberOfCpuCores(), $files);
Expand Down
6 changes: 6 additions & 0 deletions src/Command/AnalysisResult.php
Expand Up @@ -30,6 +30,7 @@ public function __construct(
private bool $defaultLevelUsed,
private ?string $projectConfigFile,
private bool $savedResultCache,
private int $estimatedPeakMemoryUsage,
)
{
usort(
Expand Down Expand Up @@ -123,4 +124,9 @@ public function isResultCacheSaved(): bool
return $this->savedResultCache;
}

public function getEstimatedPeakMemoryUsage(): int
{
return $this->estimatedPeakMemoryUsage;
}

}
10 changes: 10 additions & 0 deletions src/Command/ErrorFormatter/TableErrorFormatter.php
Expand Up @@ -8,6 +8,7 @@
use PHPStan\Command\Output;
use PHPStan\File\RelativePathHelper;
use PHPStan\File\SimpleRelativePathHelper;
use PHPStan\Internal\BytesHelper;
use Symfony\Component\Console\Formatter\OutputFormatter;
use function array_map;
use function count;
Expand Down Expand Up @@ -45,6 +46,11 @@ public function formatErrors(

if (!$analysisResult->hasErrors() && !$analysisResult->hasWarnings()) {
$style->success('No errors');

if ($output->isVerbose()) {
$output->writeLineFormatted(sprintf('Took about %s memory', BytesHelper::bytes($analysisResult->getEstimatedPeakMemoryUsage())));
}

if ($this->showTipsOfTheDay) {
if ($analysisResult->isDefaultLevelUsed()) {
$output->writeLineFormatted('💡 Tip of the Day:');
Expand Down Expand Up @@ -117,6 +123,10 @@ public function formatErrors(
$style->warning($finalMessage);
}

if ($output->isVerbose()) {
$output->writeLineFormatted(sprintf('Took about %s memory', BytesHelper::bytes($analysisResult->getEstimatedPeakMemoryUsage())));
}

return $analysisResult->getTotalErrorsCount() > 0 ? 1 : 0;
}

Expand Down
3 changes: 2 additions & 1 deletion src/Command/FixerApplication.php
Expand Up @@ -60,6 +60,7 @@
use function is_dir;
use function is_file;
use function is_string;
use function memory_get_peak_usage;
use function min;
use function mkdir;
use function parse_url;
Expand Down Expand Up @@ -507,7 +508,7 @@ private function reanalyseAfterFileChanges(
$resultCache = $resultCacheManager->restore($inceptionFiles, false, false, $projectConfigArray, $inceptionResult->getErrorOutput(), $fixerSuggestionId);
if (count($resultCache->getFilesToAnalyse()) === 0) {
$result = $resultCacheManager->process(
new AnalyserResult([], [], [], [], [], false),
new AnalyserResult([], [], [], [], [], false, memory_get_peak_usage(true)),
$resultCache,
$inceptionResult->getErrorOutput(),
false,
Expand Down
1 change: 1 addition & 0 deletions src/Command/FixerWorkerCommand.php
Expand Up @@ -268,6 +268,7 @@ private function switchTmpFileInAnalyserResult(
$dependencies,
$exportedNodes,
$analyserResult->hasReachedInternalErrorsCountLimit(),
$analyserResult->getEstimatedPeakMemoryUsage(),
);
}

Expand Down
7 changes: 0 additions & 7 deletions src/Command/InceptionResult.php
Expand Up @@ -3,9 +3,6 @@
namespace PHPStan\Command;

use PHPStan\DependencyInjection\Container;
use PHPStan\Internal\BytesHelper;
use function memory_get_peak_usage;
use function sprintf;

class InceptionResult
{
Expand Down Expand Up @@ -81,10 +78,6 @@ public function getGenerateBaselineFile(): ?string

public function handleReturn(int $exitCode): int
{
if ($this->getErrorOutput()->isVerbose()) {
$this->getErrorOutput()->writeLineFormatted(sprintf('Used memory: %s', BytesHelper::bytes(memory_get_peak_usage(true))));
}

return $exitCode;
}

Expand Down
2 changes: 2 additions & 0 deletions src/Command/WorkerCommand.php
Expand Up @@ -30,6 +30,7 @@
use function is_array;
use function is_bool;
use function is_string;
use function memory_get_peak_usage;
use function sprintf;

class WorkerCommand extends Command
Expand Down Expand Up @@ -242,6 +243,7 @@ private function runWorker(
'result' => [
'errors' => $errors,
'collectedData' => $collectedData,
'memoryUsage' => memory_get_peak_usage(true),
'dependencies' => $dependencies,
'exportedNodes' => $exportedNodes,
'filesCount' => count($files),
Expand Down
9 changes: 8 additions & 1 deletion src/Parallel/ParallelAnalyser.php
Expand Up @@ -19,6 +19,7 @@
use function array_map;
use function array_pop;
use function array_reverse;
use function array_sum;
use function count;
use function defined;
use function escapeshellarg;
Expand Down Expand Up @@ -64,6 +65,7 @@ public function analyse(

$numberOfProcesses = $schedule->getNumberOfProcesses();
$errors = [];
$peakMemoryUsages = [];
$internalErrors = [];
$collectedData = [];

Expand Down Expand Up @@ -138,7 +140,7 @@ public function analyse(
$commandOptions,
$input,
), $loop, $this->processTimeout);
$process->start(function (array $json) use ($process, &$internalErrors, &$errors, &$collectedData, &$dependencies, &$exportedNodes, &$jobs, $postFileCallback, &$internalErrorsCount, &$reachedInternalErrorsCountLimit, $processIdentifier): void {
$process->start(function (array $json) use ($process, &$internalErrors, &$errors, &$collectedData, &$dependencies, &$exportedNodes, &$peakMemoryUsages, &$jobs, $postFileCallback, &$internalErrorsCount, &$reachedInternalErrorsCountLimit, $processIdentifier): void {
foreach ($json['errors'] as $jsonError) {
if (is_string($jsonError)) {
$internalErrors[] = sprintf('Internal error: %s', $jsonError);
Expand Down Expand Up @@ -179,6 +181,10 @@ public function analyse(
$postFileCallback($json['filesCount']);
}

if (!isset($peakMemoryUsages[$processIdentifier]) || $peakMemoryUsages[$processIdentifier] < $json['memoryUsage']) {
$peakMemoryUsages[$processIdentifier] = $json['memoryUsage'];
}

$internalErrorsCount += $json['internalErrorsCount'];
if ($internalErrorsCount >= $this->internalErrorsCountLimit) {
$reachedInternalErrorsCountLimit = true;
Expand Down Expand Up @@ -221,6 +227,7 @@ public function analyse(
$internalErrorsCount === 0 ? $dependencies : null,
$exportedNodes,
$reachedInternalErrorsCountLimit,
(int) array_sum($peakMemoryUsages), // not 100% correct as the peak usages of workers might not have met
);
}

Expand Down
1 change: 1 addition & 0 deletions src/Testing/ErrorFormatterTestCase.php
Expand Up @@ -100,6 +100,7 @@ protected function getAnalysisResult(int $numFileErrors, int $numGenericErrors):
false,
null,
true,
0,
);
}

Expand Down
1 change: 1 addition & 0 deletions tests/PHPStan/Command/AnalysisResultTest.php
Expand Up @@ -43,6 +43,7 @@ public function testErrorsAreSortedByFileNameAndLine(): void
false,
null,
true,
0,
))->getFileSpecificErrors(),
);
}
Expand Down
Expand Up @@ -148,6 +148,7 @@ public function testFormatErrorMessagesRegexEscape(): void
false,
null,
true,
0,
);
$formatter->formatErrors(
$result,
Expand Down Expand Up @@ -185,6 +186,7 @@ public function testEscapeDiNeon(): void
false,
null,
true,
0,
);

$formatter->formatErrors(
Expand Down Expand Up @@ -249,6 +251,7 @@ public function testOutputOrdering(array $errors): void
false,
null,
true,
0,
);

$formatter->formatErrors(
Expand Down Expand Up @@ -406,6 +409,7 @@ public function testEndOfFileNewlines(
false,
null,
true,
0,
);

$resource = fopen('php://memory', 'w', false);
Expand Down
Expand Up @@ -154,6 +154,7 @@ public function testTraitPath(): void
false,
null,
true,
0,
), $this->getOutput());
$this->assertXmlStringEqualsXmlString('<checkstyle>
<file name="FooTrait.php">
Expand Down
Expand Up @@ -210,7 +210,7 @@ public function testEditorUrlWithTrait(): void
{
$formatter = $this->createErrorFormatter('editor://%file%/%line%');
$error = new Error('Test', 'Foo.php (in context of trait)', 12, true, 'Foo.php', 'Bar.php');
$formatter->formatErrors(new AnalysisResult([$error], [], [], [], [], false, null, true), $this->getOutput());
$formatter->formatErrors(new AnalysisResult([$error], [], [], [], [], false, null, true, 0), $this->getOutput());

$this->assertStringContainsString('Bar.php', $this->getOutputContent());
}
Expand All @@ -219,7 +219,7 @@ public function testEditorUrlWithRelativePath(): void
{
$formatter = $this->createErrorFormatter('editor://custom/path/%relFile%/%line%');
$error = new Error('Test', 'Foo.php', 12, true, self::DIRECTORY_PATH . '/rel/Foo.php');
$formatter->formatErrors(new AnalysisResult([$error], [], [], [], [], false, null, true), $this->getOutput(true));
$formatter->formatErrors(new AnalysisResult([$error], [], [], [], [], false, null, true, 0), $this->getOutput(true));

$this->assertStringContainsString('editor://custom/path/rel/Foo.php', $this->getOutputContent(true));
}
Expand All @@ -244,6 +244,7 @@ public function testBug6727(): void
false,
null,
true,
0,
),
$this->getOutput(),
);
Expand Down

0 comments on commit 2eb2503

Please sign in to comment.