diff --git a/src/Psalm/Progress/DefaultProgress.php b/src/Psalm/Progress/DefaultProgress.php
index 4f08807d990..f91db00ce3b 100644
--- a/src/Psalm/Progress/DefaultProgress.php
+++ b/src/Psalm/Progress/DefaultProgress.php
@@ -6,8 +6,8 @@
 
 use Override;
 
+use function hrtime;
 use function max;
-use function microtime;
 use function str_repeat;
 use function strlen;
 
@@ -17,10 +17,13 @@ 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
@@ -28,21 +31,21 @@ 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,