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

Small performance improvement #11348

Merged
merged 2 commits into from
Mar 1, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions src/Psalm/Progress/DefaultProgress.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

use Override;

use function hrtime;
use function max;
use function microtime;
use function str_repeat;
use function strlen;

Expand All @@ -17,32 +17,35 @@ class DefaultProgress extends LongProgress

// Update the progress bar at most once per 0.1 seconds.
// This reduces flickering and reduces the amount of time spent writing to STDERR and updating the terminal.
private const PROGRESS_BAR_SAMPLE_INTERVAL = 0.1;
private const PROGRESS_BAR_SAMPLE_INTERVAL_NANOSECONDS = 100_000_000;

/** @var float the last time when the progress bar UI was updated */
private float $previous_update_time = 0.0;
/** the last time when the progress bar UI was updated (seconds) */
private int $previous_update_seconds = 0;

/** the last time when the progress bar UI was updated (nanoseconds) */
private int $previous_update_nseconds = 0;

#[Override]
public function taskDone(int $level): void
{
if ($this->fixed_size && $this->number_of_tasks > self::TOO_MANY_FILES) {
++$this->progress;

// Source for rate limiting:
// https://github.com/phan/phan/blob/9a788581ee1a4e1c35bebf89c435fd8a238c1d17/src/Phan/CLI.php
$time = microtime(true);
[$seconds, $nseconds] = hrtime();

// If not enough time has elapsed, then don't update the progress bar.
// Making the update frequency based on time (instead of the number of files)
// prevents the terminal from rapidly flickering while processing small/empty files,
// and reduces the time spent writing to stderr.
if ($time - $this->previous_update_time < self::PROGRESS_BAR_SAMPLE_INTERVAL) {
// Make sure to output the section for 100% completion regardless of limits, to avoid confusion.
if ($this->progress !== $this->number_of_tasks) {
return;
}
// Make sure to output the section for 100% completion regardless of limits, to avoid confusion.
if ($seconds === $this->previous_update_seconds
&& ($nseconds - $this->previous_update_nseconds < self::PROGRESS_BAR_SAMPLE_INTERVAL_NANOSECONDS)
&& $this->progress !== $this->number_of_tasks
) {
return;
}
$this->previous_update_time = $time;
$this->previous_update_seconds = $seconds;
$this->previous_update_nseconds = $nseconds;

$inner_progress = self::renderInnerProgressBar(
self::NUMBER_OF_COLUMNS,
Expand Down