فهرست منبع

Optimizations

walkor 1 سال پیش
والد
کامیت
f1ec924a72
1فایلهای تغییر یافته به همراه34 افزوده شده و 15 حذف شده
  1. 34 15
      src/Events/Select.php

+ 34 - 15
src/Events/Select.php

@@ -115,6 +115,13 @@ final class Select implements EventInterface
     private int $selectTimeout = 100000000;
 
     /**
+     * Next run time of the timer.
+     *
+     * @var float
+     */
+    private float $nextTickTime = 0;
+
+    /**
      * @var ?callable
      */
     private $errorHandler = null;
@@ -137,10 +144,8 @@ final class Select implements EventInterface
         $runTime = microtime(true) + $delay;
         $this->scheduler->insert($timerId, -$runTime);
         $this->eventTimer[$timerId] = [$func, $args];
-        $selectTimeout = ($runTime - microtime(true)) * 1000000;
-        $selectTimeout = $selectTimeout <= 0 ? 1 : (int)$selectTimeout;
-        if ($this->selectTimeout > $selectTimeout) {
-            $this->selectTimeout = $selectTimeout;
+        if ($this->nextTickTime == 0 || $this->nextTickTime > $runTime) {
+            $this->setNextTickTime($runTime);
         }
         return $timerId;
     }
@@ -154,10 +159,8 @@ final class Select implements EventInterface
         $runTime = microtime(true) + $interval;
         $this->scheduler->insert($timerId, -$runTime);
         $this->eventTimer[$timerId] = [$func, $args, $interval];
-        $selectTimeout = ($runTime - microtime(true)) * 1000000;
-        $selectTimeout = $selectTimeout <= 0 ? 1 : (int)$selectTimeout;
-        if ($this->selectTimeout > $selectTimeout) {
-            $this->selectTimeout = $selectTimeout;
+        if ($this->nextTickTime == 0 || $this->nextTickTime > $runTime) {
+            $this->setNextTickTime($runTime);
         }
         return $timerId;
     }
@@ -338,11 +341,27 @@ final class Select implements EventInterface
         if (!$this->scheduler->isEmpty()) {
             $schedulerData = $this->scheduler->top();
             $nextRunTime = -$schedulerData['priority'];
-            $timeNow = microtime(true);
-            $this->selectTimeout = max((int)(($nextRunTime - $timeNow) * 1000000), 0);
+            $this->setNextTickTime($nextRunTime);
+            return;
+        }
+        $this->setNextTickTime(0);
+    }
+
+    /**
+     * Set next tick time.
+     *
+     * @param float $nextTickTime
+     * @return void
+     */
+    protected function setNextTickTime(float $nextTickTime): void
+    {
+        $this->nextTickTime = $nextTickTime;
+        if ($nextTickTime == 0) {
+            $this->selectTimeout = 10000000;
             return;
         }
-        $this->selectTimeout = 100000000;
+        $timeNow = microtime(true);
+        $this->selectTimeout = max((int)(($nextTickTime - $timeNow) * 1000000), 0);
     }
 
     /**
@@ -375,10 +394,6 @@ final class Select implements EventInterface
                 $this->selectTimeout >= 1 && usleep($this->selectTimeout);
             }
 
-            if (!$this->scheduler->isEmpty()) {
-                $this->tick();
-            }
-
             foreach ($read as $fd) {
                 $fdKey = (int)$fd;
                 if (isset($this->readEvents[$fdKey])) {
@@ -400,6 +415,10 @@ final class Select implements EventInterface
                 }
             }
 
+            if ($this->nextTickTime > 0 && microtime(true) >= $this->nextTickTime) {
+                $this->tick();
+            }
+
             if ($this->signalEvents) {
                 // Calls signal handlers for pending signals
                 pcntl_signal_dispatch();