WebKit icon indicating copy to clipboard operation
WebKit copied to clipboard

[GLIB] Use timerfd to improve timer resolution

Open GeorgesStavracas opened this issue 1 month ago • 3 comments

cacb4e808ca82a8b72423dc33b223b72fdfee19b

[GLIB] Use timerfd to improve timer resolution
https://bugs.webkit.org/show_bug.cgi?id=303921

Reviewed by NOBODY (OOPS!).

WebKit timers in GLib have a big lateness range (up or more than 1ms).
We can have better timers by using timerfd in a few selected places.

Make RunLoopSource use a timerfd when starting RunLoop::TimerBase
instances. The timerfd itself is created as late as possible, and
only when the timer has an interval set. That's because some timers
are created but rarely started, so we can save a few fds by delaying
the timerfd creation.

Some measurements. Before this patch:

```
WebPageProxy::GeneratePageLoadTimingTimer lateness: 59µs
MainThreadSharedTimer::timer lateness: 613µs
MainThreadSharedTimer::timer lateness: 92µs
MainThreadSharedTimer::timer lateness: 500µs
BitmapTexturePool::ReleaseUnusedTexturesTimer lateness: 2µs
BitmapTexturePool::ReleaseUnusedTexturesTimer lateness: 867µs
MainThreadSharedTimer::timer lateness: 605µs
BitmapTexturePool::ReleaseUnusedTexturesTimer lateness: 527µs
MainThreadSharedTimer::timer lateness: 194µs
MainThreadSharedTimer::timer lateness: 487µs
BitmapTexturePool::ReleaseUnusedTexturesTimer lateness: 612µs
MainThreadSharedTimer::timer lateness: 687µs
BitmapTexturePool::ReleaseUnusedTexturesTimer lateness: 423µs
MainThreadSharedTimer::timer lateness: 305µs
MainThreadSharedTimer::timer lateness: 161µs
MainThreadSharedTimer::timer lateness: 49µs
BitmapTexturePool::ReleaseUnusedTexturesTimer lateness: 41µs
MainThreadSharedTimer::timer lateness: 431µs
MainThreadSharedTimer::timer lateness: 883µs
JSRunLoopTimer::Manager::PerVMData::Timer lateness: 738µs
BitmapTexturePool::ReleaseUnusedTexturesTimer lateness: 496µs
JSRunLoopTimer::Manager::PerVMData::Timer lateness: 255µs
JSRunLoopTimer::Manager::PerVMData::Timer lateness: 124µs
```

After this patch:

```
WebPageProxy::GeneratePageLoadTimingTimer lateness: 15µs
BitmapTexturePool::ReleaseUnusedTexturesTimer lateness: 10µs
BitmapTexturePool::ReleaseUnusedTexturesTimer lateness: 6µs
MainThreadSharedTimer::timer lateness: 9µs
MainThreadSharedTimer::timer lateness: 10µs
BitmapTexturePool::ReleaseUnusedTexturesTimer lateness: 9µs
MainThreadSharedTimer::timer lateness: 7µs
MainThreadSharedTimer::timer lateness: 416µs
BitmapTexturePool::ReleaseUnusedTexturesTimer lateness: 10µs
MainThreadSharedTimer::timer lateness: 10µs
BitmapTexturePool::ReleaseUnusedTexturesTimer lateness: 12µs
MainThreadSharedTimer::timer lateness: 8µs
MainThreadSharedTimer::timer lateness: 7µs
BitmapTexturePool::ReleaseUnusedTexturesTimer lateness: 10µs
MainThreadSharedTimer::timer lateness: 19µs
MainThreadSharedTimer::timer lateness: 20µs
JSRunLoopTimer::Manager::PerVMData::Timer lateness: 35µs
BitmapTexturePool::ReleaseUnusedTexturesTimer lateness: 15µs
JSRunLoopTimer::Manager::PerVMData::Timer lateness: 24µs
JSRunLoopTimer::Manager::PerVMData::Timer lateness: 12µs
PrivateClickMeasurementManager::FirePendingAttributionRequestsTimer lateness: 24µs
HysteresisActivity::Timer lateness: 14µs
```

It doesn't seem to affect MotionMark results.

* Source/WTF/wtf/CMakeLists.txt:
* Source/WTF/wtf/glib/RunLoopGLib.cpp:
(WTF::RunLoop::RunLoop):
(WTF::RunLoop::TimerBase::TimerBase):
(WTF::RunLoop::TimerBase::start):

https://github.com/WebKit/WebKit/commit/cacb4e808ca82a8b72423dc33b223b72fdfee19b

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe ✅ 🛠 win
✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug ✅ 🧪 wpe-wk2 ⏳ 🧪 win-tests
✅ 🧪 webkitperl ✅ 🧪 ios-wk2 ✅ 🧪 api-mac ✅ 🧪 api-wpe
✅ 🧪 ios-wk2-wpt ✅ 🧪 api-mac-debug ✅ 🛠 wpe-cairo-libwebrtc
✅ 🛠 🧪 jsc ✅ 🧪 api-ios ✅ 🧪 mac-wk1 ✅ 🛠 gtk
✅ 🛠 🧪 jsc-arm64 ✅ 🛠 vision ✅ 🧪 mac-wk2 ✅ 🧪 gtk-wk2
✅ 🛠 vision-sim ✅ 🧪 mac-AS-debug-wk2 ✅ 🧪 api-gtk
✅ 🧪 vision-wk2 ✅ 🧪 mac-wk2-stress ✅ 🛠 playstation
✅ 🛠 tv ✅ 🧪 mac-intel-wk2 ✅ 🛠 jsc-armv7
✅ 🛠 tv-sim ✅ 🛠 mac-safer-cpp ⏳ 🧪 jsc-armv7-tests
✅ 🛠 watch
✅ 🛠 watch-sim

GeorgesStavracas avatar Dec 10 '25 15:12 GeorgesStavracas

The new code checks for timerfd_create() at build time and enables this code path based on that.

Or it was supposed to do that, except that the new define doesn't seem to ever reach the config.h file, so the new code path is effectively never enabled.

@aperezdc any idea?

GeorgesStavracas avatar Dec 12 '25 16:12 GeorgesStavracas

The new code checks for timerfd_create() at build time and enables this code path based on that.

Or it was supposed to do that, except that the new define doesn't seem to ever reach the config.h file, so the new code path is effectively never enabled.

@aperezdc any idea?

Usually we don't check for specific functions/symbols in each of the libraries' subdirectory, but instead somewhere in Source/cmake/*.cmake. In this case I think the most appropriate place would be Source/cmake/OptionsCommon.cmake, where there are already a few checks for functions, and we also have a macro that would be handy:

# Check for functions
# [...]
WEBKIT_CHECK_HAVE_FUNCTION(HAVE_TIMERFD timerfd_create sys/timerfd.h)

Note that for results of function checks we typically use the HAVE_ prefix. The USE_ prefix is used for dependencies that may be toggleable at build time—but we always want to use timerfd_create() and friends where available.

(IIRC, the reason for placing the checks there is that the configuration file is generated after the port-specific Options*.cmake file ends processing options, so calling SET_AND_EXPOSE_TO_BUILD afterwards does record the setting to be added to the file, but the file was already created without that setting.)

aperezdc avatar Dec 15 '25 15:12 aperezdc

Thanks @aperezdc it works now!

GeorgesStavracas avatar Dec 15 '25 16:12 GeorgesStavracas

Committed 304553@main (3a7d28d2021a): https://commits.webkit.org/304553@main

Reviewed commits have been landed. Closing PR #55173 and removing active labels.

webkit-commit-queue avatar Dec 16 '25 23:12 webkit-commit-queue