Changeset 291476 in webkit
- Timestamp:
- Mar 18, 2022, 4:58:07 AM (3 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r291474 r291476 1 2022-03-18 Cameron McCormack <heycam@apple.com> 2 3 Remove the 1ms minimum for setTimeout 4 https://bugs.webkit.org/show_bug.cgi?id=221124 5 <rdar://problem/73852354> 6 7 Reviewed by Sam Weinig. 8 9 The HTML spec makes no mention of a 1ms minimum for timers. Removing 10 the 1ms minimum for setTimeout results in a 0.7-2.1% improvement on 11 Speedometer, depending on platform and hardware. 12 13 The WPT added here demonstrates how this change can affect pages: if a 14 page schedules a 1ms and then a 0ms timeout in the same turn of the 15 event loop, then with this patch they will now be fired in the reverse 16 order. Firefox and Chrome do not impose a 1ms minimum, which reduces 17 the risk of this being a problem. 18 19 Not addressing the setTimeout 1ms minimum here, which should likely also 20 be removed. 21 22 While we're here, settle on "one shot" rather rather than "single 23 shot" as the term for timers that fire once. 24 25 Tests: imported/w3c/web-platform-tests/html/webappapis/timers/zero-settimeout.any.html 26 imported/w3c/web-platform-tests/html/webappapis/timers/zero-settimeout.any.worker.html 27 28 * page/DOMTimer.h: 29 * page/DOMTimer.cpp: 30 (WebCore::DOMTimer::DOMTimer): We must pass oneShot into 31 intervalClampedToMinimum, since the way isOneShot determines whether 32 we are a one shot timer is by checking repeatInterval, which is only 33 set once startRepeating is called. 34 (WebCore::DOMTimer::install): 35 (WebCore::DOMTimer::fired): 36 (WebCore::DOMTimer::updateTimerIntervalIfNecessary): 37 (WebCore::DOMTimer::isOneShot const): 38 (WebCore::DOMTimer::intervalClampedToMinimum const): 39 1 40 2022-03-18 Antti Koivisto <antti@apple.com> 2 41 -
trunk/Source/WebCore/page/DOMTimer.cpp
r289058 r291476 50 50 51 51 static const Seconds minIntervalForNonUserObservableChangeTimers { 1_s }; // Empirically determined to maximize battery life. 52 static const Seconds minIntervalForOneShotTimers { 0_ms }; 53 static const Seconds minIntervalForRepeatingTimers { 1_ms }; 52 54 static const int maxTimerNestingLevel = 5; 53 55 … … 156 158 bool NestedTimersMap::isTrackingNestedTimers = false; 157 159 158 DOMTimer::DOMTimer(ScriptExecutionContext& context, Function<void(ScriptExecutionContext&)>&& action, Seconds interval, bool singleShot)160 DOMTimer::DOMTimer(ScriptExecutionContext& context, Function<void(ScriptExecutionContext&)>&& action, Seconds interval, bool oneShot) 159 161 : SuspendableTimerBase(&context) 160 162 , m_nestingLevel(context.timerNestingLevel()) … … 162 164 , m_originalInterval(interval) 163 165 , m_throttleState(Undetermined) 164 , m_currentTimerInterval(intervalClampedToMinimum( ))166 , m_currentTimerInterval(intervalClampedToMinimum(oneShot)) 165 167 , m_userGestureTokenToForward(UserGestureIndicator::currentUserGesture()) 166 168 { 167 if ( singleShot)169 if (oneShot) 168 170 startOneShot(m_currentTimerInterval); 169 171 else … … 173 175 DOMTimer::~DOMTimer() = default; 174 176 175 int DOMTimer::install(ScriptExecutionContext& context, std::unique_ptr<ScheduledAction> action, Seconds timeout, bool singleShot)177 int DOMTimer::install(ScriptExecutionContext& context, std::unique_ptr<ScheduledAction> action, Seconds timeout, bool oneShot) 176 178 { 177 179 auto actionFunction = [action = WTFMove(action)](ScriptExecutionContext& context) mutable { 178 180 action->execute(context); 179 181 }; 180 return DOMTimer::install(context, WTFMove(actionFunction), timeout, singleShot);181 } 182 183 int DOMTimer::install(ScriptExecutionContext& context, Function<void(ScriptExecutionContext&)>&& action, Seconds timeout, bool singleShot)184 { 185 Ref<DOMTimer> timer = adoptRef(*new DOMTimer(context, WTFMove(action), timeout, singleShot));182 return DOMTimer::install(context, WTFMove(actionFunction), timeout, oneShot); 183 } 184 185 int DOMTimer::install(ScriptExecutionContext& context, Function<void(ScriptExecutionContext&)>&& action, Seconds timeout, bool oneShot) 186 { 187 Ref<DOMTimer> timer = adoptRef(*new DOMTimer(context, WTFMove(action), timeout, oneShot)); 186 188 timer->suspendIfNeeded(); 187 189 … … 191 193 } while (!context.addTimeout(timer->m_timeoutId, timer.get())); 192 194 193 InspectorInstrumentation::didInstallTimer(context, timer->m_timeoutId, timeout, singleShot);195 InspectorInstrumentation::didInstallTimer(context, timer->m_timeoutId, timeout, oneShot); 194 196 195 197 // Keep track of nested timer installs. … … 199 201 if (is<Document>(context)) { 200 202 auto& document = downcast<Document>(context); 201 document.contentChangeObserver().didInstallDOMTimer(timer.get(), timeout, singleShot);203 document.contentChangeObserver().didInstallDOMTimer(timer.get(), timeout, oneShot); 202 204 if (DeferDOMTimersForScope::isDeferring()) 203 205 document.domTimerHoldingTank().add(timer.get()); … … 289 291 Ref<DOMTimer> protectedThis(*this); 290 292 291 bool oneShot = !repeatInterval();293 bool oneShot = isOneShot(); 292 294 293 295 ASSERT(scriptExecutionContext()); … … 351 353 for (auto& idAndTimer : *nestedTimers) { 352 354 auto& timer = idAndTimer.value; 353 if (timer->isActive() && !timer->repeatInterval())355 if (timer->isActive() && timer->isOneShot()) 354 356 timer->updateThrottlingStateIfNecessary(fireState); 355 357 } … … 375 377 return; 376 378 377 if (repeatInterval()) { 379 if (isOneShot()) { 380 LOG(DOMTimers, "%p - Updating DOMTimer's fire interval from %.2f ms to %.2f ms due to throttling.", this, previousInterval.milliseconds(), m_currentTimerInterval.milliseconds()); 381 augmentFireInterval(m_currentTimerInterval - previousInterval); 382 } else { 378 383 ASSERT(repeatInterval() == previousInterval); 379 384 LOG(DOMTimers, "%p - Updating DOMTimer's repeat interval from %.2f ms to %.2f ms due to throttling.", this, previousInterval.milliseconds(), m_currentTimerInterval.milliseconds()); 380 385 augmentRepeatInterval(m_currentTimerInterval - previousInterval); 381 } else { 382 LOG(DOMTimers, "%p - Updating DOMTimer's fire interval from %.2f ms to %.2f ms due to throttling.", this, previousInterval.milliseconds(), m_currentTimerInterval.milliseconds()); 383 augmentFireInterval(m_currentTimerInterval - previousInterval); 384 } 386 } 387 } 388 389 bool DOMTimer::isOneShot() const 390 { 391 return !repeatInterval(); 385 392 } 386 393 387 394 Seconds DOMTimer::intervalClampedToMinimum() const 395 { 396 return intervalClampedToMinimum(isOneShot()); 397 } 398 399 Seconds DOMTimer::intervalClampedToMinimum(bool oneShot) const 388 400 { 389 401 ASSERT(scriptExecutionContext()); 390 402 ASSERT(m_nestingLevel <= maxTimerNestingLevel); 391 403 392 Seconds interval = std::max( 1_ms, m_originalInterval);404 Seconds interval = std::max(oneShot ? minIntervalForOneShotTimers : minIntervalForRepeatingTimers, m_originalInterval); 393 405 394 406 // Only apply throttling to repeating timers. -
trunk/Source/WebCore/page/DOMTimer.h
r289058 r291476 70 70 71 71 WEBCORE_EXPORT Seconds intervalClampedToMinimum() const; 72 Seconds intervalClampedToMinimum(bool oneShot) const; 73 bool isOneShot() const; 72 74 73 75 bool isDOMTimersThrottlingEnabled(Document&) const;
Note:
See TracChangeset
for help on using the changeset viewer.