Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show combined memory usage in parallel mode #2027

Merged
merged 6 commits into from Jan 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 $peakMemoryUsageBytes,
)
{
$this->unorderedErrors = $errors;
Expand Down Expand Up @@ -97,4 +98,9 @@ public function hasReachedInternalErrorsCountLimit(): bool
return $this->reachedInternalErrorsCountLimit;
}

public function getPeakMemoryUsageBytes(): int
{
return $this->peakMemoryUsageBytes;
}

}
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->getPeakMemoryUsageBytes(),
), $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;
$memoryUsageBytes = memory_get_peak_usage(true);
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->getPeakMemoryUsageBytes(),
);
}

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

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,
$memoryUsageBytes,
);
}

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
30 changes: 16 additions & 14 deletions src/Command/AnalyseCommand.php
Expand Up @@ -157,7 +157,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int

if ($generateBaselineFile === null && $allowEmptyBaseline) {
$inceptionResult->getStdOutput()->getStyle()->error('You must pass the --generate-baseline option alongside --allow-empty-baseline.');
return $inceptionResult->handleReturn(1);
return $inceptionResult->handleReturn(1, null);
}

$errorOutput = $inceptionResult->getErrorOutput();
Expand Down Expand Up @@ -200,13 +200,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$baselineExtension = pathinfo($generateBaselineFile, PATHINFO_EXTENSION);
if ($baselineExtension === '') {
$inceptionResult->getStdOutput()->getStyle()->error(sprintf('Baseline filename must have an extension, %s provided instead.', pathinfo($generateBaselineFile, PATHINFO_BASENAME)));
return $inceptionResult->handleReturn(1);
return $inceptionResult->handleReturn(1, null);
}

if ($baselineExtension !== 'neon') {
$inceptionResult->getStdOutput()->getStyle()->error(sprintf('Baseline filename extension must be .neon, .%s was used instead.', $baselineExtension));

return $inceptionResult->handleReturn(1);
return $inceptionResult->handleReturn(1, null);
}
}

Expand Down Expand Up @@ -267,7 +267,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$previous = $previous->getPrevious();
}

return $inceptionResult->handleReturn(1);
return $inceptionResult->handleReturn(1, null);
}

throw $t;
Expand All @@ -278,12 +278,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$inceptionResult->getStdOutput()->getStyle()->error('No errors were found during the analysis. Baseline could not be generated.');
$inceptionResult->getStdOutput()->writeLineFormatted('To allow generating empty baselines, pass <fg=cyan>--allow-empty-baseline</> option.');

return $inceptionResult->handleReturn(1);
return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes());
}
if ($analysisResult->hasInternalErrors()) {
$inceptionResult->getStdOutput()->getStyle()->error('An internal error occurred. Baseline could not be generated. Re-run PHPStan without --generate-baseline to see what\'s going on.');

return $inceptionResult->handleReturn(1);
return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes());
}

$baselineFileDirectory = dirname($generateBaselineFile);
Expand All @@ -308,7 +308,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
if ($mkdirResult === false) {
$inceptionResult->getStdOutput()->writeLineFormatted(sprintf('Failed to create directory "%s".', $baselineFileDirectory));

return $inceptionResult->handleReturn(1);
return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes());
}
}

Expand All @@ -317,7 +317,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
} catch (CouldNotWriteFileException $e) {
$inceptionResult->getStdOutput()->writeLineFormatted($e->getMessage());

return $inceptionResult->handleReturn(1);
return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes());
}

$errorsCount = 0;
Expand Down Expand Up @@ -348,15 +348,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$inceptionResult->getStdOutput()->getStyle()->warning($message . "\nSome errors could not be put into baseline. Re-run PHPStan and fix them.");
}

return $inceptionResult->handleReturn(0);
return $inceptionResult->handleReturn(0, $analysisResult->getPeakMemoryUsageBytes());
}

if ($fix) {
$ciDetector = new CiDetector();
if ($ciDetector->isCiDetected()) {
$inceptionResult->getStdOutput()->writeLineFormatted('PHPStan Pro can\'t run in CI environment yet. Stay tuned!');

return $inceptionResult->handleReturn(1);
return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes());
}
$container->getByType(ResultCacheClearer::class)->clearTemporaryCaches();
$hasInternalErrors = $analysisResult->hasInternalErrors();
Expand All @@ -379,6 +379,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$analysisResult->isDefaultLevelUsed(),
$analysisResult->getProjectConfigFile(),
$analysisResult->isResultCacheSaved(),
$analysisResult->getPeakMemoryUsageBytes(),
);

$stdOutput = $inceptionResult->getStdOutput();
Expand All @@ -395,15 +396,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$stdOutput->writeLineFormatted(sprintf('nonIgnorableErrorsByExceptionCount: %d', count($nonIgnorableErrorsByException)));
}

return $inceptionResult->handleReturn(1);
return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes());
}

if (!$analysisResult->isResultCacheSaved() && !$onlyFiles) {
// this can happen only if there are some regex-related errors in ignoreErrors configuration
$stdOutput = $inceptionResult->getStdOutput();
if (count($analysisResult->getFileSpecificErrors()) > 0) {
$stdOutput->getStyle()->error('Unknown error. Please report this as a bug.');
return $inceptionResult->handleReturn(1);
return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes());
}

$stdOutput->getStyle()->error('PHPStan Pro can\'t be launched because of these errors:');
Expand All @@ -418,10 +419,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$stdOutput->writeLineFormatted('Result cache was not saved.');
}

return $inceptionResult->handleReturn(1);
return $inceptionResult->handleReturn(1, $analysisResult->getPeakMemoryUsageBytes());
}

$inceptionResult->handleReturn(0);
$inceptionResult->handleReturn(0, $analysisResult->getPeakMemoryUsageBytes());

/** @var FixerApplication $fixerApplication */
$fixerApplication = $container->getByType(FixerApplication::class);
Expand All @@ -443,6 +444,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int

return $inceptionResult->handleReturn(
$errorFormatter->formatErrors($analysisResult, $inceptionResult->getStdOutput()),
$analysisResult->getPeakMemoryUsageBytes(),
);
}

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 $peakMemoryUsageBytes,
)
{
usort(
Expand Down Expand Up @@ -123,4 +124,9 @@ public function isResultCacheSaved(): bool
return $this->savedResultCache;
}

public function getPeakMemoryUsageBytes(): int
{
return $this->peakMemoryUsageBytes;
}

}
1 change: 1 addition & 0 deletions src/Command/ErrorFormatter/TableErrorFormatter.php
Expand Up @@ -46,6 +46,7 @@ public function formatErrors(

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

if ($this->showTipsOfTheDay) {
if ($analysisResult->isDefaultLevelUsed()) {
$output->writeLineFormatted('💡 Tip of the Day:');
Expand Down
30 changes: 30 additions & 0 deletions src/Command/ErrorsConsoleStyle.php
Expand Up @@ -119,6 +119,11 @@ public function createProgressBar(int $max = 0): ProgressBar
{
$this->progressBar = parent::createProgressBar($max);

$format = $this->getProgressBarFormat();
if ($format !== null) {
$this->progressBar->setFormat($format);
}

$ci = $this->isCiDetected();
$this->progressBar->setOverwrite(!$ci);

Expand All @@ -136,6 +141,31 @@ public function createProgressBar(int $max = 0): ProgressBar
return $this->progressBar;
}

private function getProgressBarFormat(): ?string
{
switch ($this->getVerbosity()) {
case OutputInterface::VERBOSITY_NORMAL:
$formatName = ProgressBar::FORMAT_NORMAL;
break;
case OutputInterface::VERBOSITY_VERBOSE:
$formatName = ProgressBar::FORMAT_VERBOSE;
break;
case OutputInterface::VERBOSITY_VERY_VERBOSE:
case OutputInterface::VERBOSITY_DEBUG:
$formatName = ProgressBar::FORMAT_VERY_VERBOSE;
break;
default:
$formatName = null;
break;
}

if ($formatName === null) {
return null;
}

return ProgressBar::getFormatDefinition($formatName);
}

public function progressStart(int $max = 0): void
{
if (!$this->showProgress) {
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->getPeakMemoryUsageBytes(),
);
}

Expand Down
7 changes: 3 additions & 4 deletions src/Command/InceptionResult.php
Expand Up @@ -4,7 +4,6 @@

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

class InceptionResult
Expand Down Expand Up @@ -79,10 +78,10 @@ public function getGenerateBaselineFile(): ?string
return $this->generateBaselineFile;
}

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

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