File tree Expand file tree Collapse file tree
Sources/JavaScriptEventLoop Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -20,10 +20,8 @@ extension JavaScriptEventLoop {
2020 return performanceNow ! . now ( this : performanceNow ! . performance ) . number !
2121 }
2222
23- func hasRun ( since start : DrainInstant , for interval : Duration ) -> Bool {
24- let ( seconds , attoseconds ) = interval . components
25- let intervalMilliseconds = Double ( seconds ) * 1_000 + Double ( attoseconds ) / 1_000_000_000_000_000
26- return drainClockNow ( ) - start >= intervalMilliseconds
23+ func drainElapsed ( since start : DrainInstant ) -> Duration {
24+ . milliseconds ( drainClockNow ( ) - start )
2725 }
2826 #else
2927 typealias DrainInstant = ContinuousClock . Instant
@@ -32,8 +30,8 @@ extension JavaScriptEventLoop {
3230 ContinuousClock . now
3331 }
3432
35- func hasRun ( since start : DrainInstant , for interval : Duration ) -> Bool {
36- start . duration ( to : . now ) >= interval
33+ func drainElapsed ( since start : DrainInstant ) -> Duration {
34+ start . duration ( to : . now )
3735 }
3836 #endif
3937
Original file line number Diff line number Diff line change @@ -45,6 +45,10 @@ extension JavaScriptEventLoop {
4545
4646 // The clock is only read while `yieldInterval` is set.
4747 var start : DrainInstant ? = yieldInterval == nil ? nil : drainClockNow ( )
48+ // A clock read costs more than a small job. Read it every `clockStride` jobs, and double
49+ // the stride (up to 256) while the drain is far from the interval.
50+ var clockStride = 1
51+ var jobsUntilClockRead = 1
4852 while let job = self . claimNextFromQueue ( ) {
4953 #if compiler( >= 5 . 9 )
5054 job . runSynchronously ( on : self . asUnownedSerialExecutor ( ) )
@@ -54,11 +58,18 @@ extension JavaScriptEventLoop {
5458
5559 if let yieldInterval , queueState . headJob != nil {
5660 if let start {
57- if hasRun ( since : start , for : yieldInterval ) {
61+ jobsUntilClockRead -= 1
62+ if jobsUntilClockRead > 0 { continue }
63+ let elapsed = drainElapsed ( since : start )
64+ if elapsed >= yieldInterval {
5865 // Keep `isSpinning` set so new jobs wait for the continuation.
5966 queueHostTask { self . runAllJobs ( ) }
6067 return
6168 }
69+ if elapsed * 4 < yieldInterval {
70+ clockStride = min ( clockStride * 2 , 256 )
71+ }
72+ jobsUntilClockRead = clockStride
6273 } else {
6374 start = drainClockNow ( )
6475 }
You can’t perform that action at this time.
0 commit comments