Bug #12866
openWt 4.10.4 has a 2 second delay with bootstrap init on some recent versions of Firefox
100%
Description
I have encountered consistent two-second start-up delays with Wt applications accessed from recent versions of Firefox running Wayland under Linux with KDE Plasma 6. The 2 second delay can be observed in the Network tab of the Web Developer Tools when pressing F5 (refresh) on a page that has a bootstrap initialization such as: https://www.webtoolkit.eu/widgets/forms/check-boxes. The delay appears to be associated with the CSS request, e.g."request=style".
The issue appears to be hardware dependent, but you can hopefully reproduce it if you have access to a recent Firefox running Wayland with KDE Plasma 6. Most of my testing has been done with a laptop running NixOS 24.05.20240721.63d37cc which includes Firefox 128.0 and KDE Plasma 6.0.5. I have also been able to reproduce the issue in a libvirt (virt-manager) Virtual Machine running at a default resolution of 1024x768 with either a NixOS 24.05 Plasma Desktop Live ISO or a Fedora KDE Plasma Desktop 40 Live ISO.
The Fedora KDE Plasma Desktop 40 (with Firefox 124.0.1 and KDE Plasma 6.0.3) can be downloaded from: https://fedoraproject.org/spins/kde/download. I tested Fedora-KDE-Live-x86_64-40-1.14.iso with a release date of Tuesday, April 23, 2024. Alternatively, a NixOS 24.05 Plasma Desktop can be downloaded from: https://nixos.org/download/
To test with either the Fedora or NixOS ISO, you just need to boot the ISO, then exit the installer (which comes up by default), and click on the firefox icon. Then, visit: https://www.webtoolkit.eu/widgets/forms/check-boxes and press F5 (refresh) to observe the delay.
As a workaround to avoid the delay, firefox can be run in XWayland mode. Just exit firefox and start a terminal session (konsole). Then, start firefox with:
MOZ_ENABLE_WAYLAND=0 firefox
There should then be minimal delay on refresh (F5) when you visit: https://www.webtoolkit.eu/widgets/forms/check-boxes.
As a note, I found that setting the display resolution in the virtual machine to the full native resolution of my display (1920x1080) also eliminated the two-second delay -- even with firefox in its default Wayland configuration.
When running directly on hardware, I found that some system configurations exhibited the two second delay consistently and some did not (also consistently). Lowering the display resolution on some systems had an impact on whether the two-second delay occurred.
I have not been able to reproduce the two-second delay with Firefox 128 running Wayland with either Plasma 5 or Gnome. So, I'm not certain if the issue lies with Firefox, Plasma 6, Wt or elsewhere. However, I suspect it may at least be partially due to the "setTimeout(doLoad, 0)" in Boot.js.
I've attached a small patch for Boot.js to help observe the issue. Running a local Wt 4.10.4 widgetgallery.wt with the patch applied and using an affected Firefox/Wayland/Plasma6 configuration, I get the following output on the web developer console (omitting favicon.ico related output):
about to call setTimeout(doLoad, 0) check-boxes:304:11
doLoad called check-boxes:65:13
time for setTimeout(doLoad, 0) to call doLoad: 2015ms
Here is the corresponding output from widgetgallery.wt deployed at /test
note the 2000.35 ms WebRequest and corresponding gap in the logged times....
[2024-Jul-31 14:47:23.255] 232570 - [info] "Wt: session created (#sessions = 6)"
[2024-Jul-31 14:47:23.256] 232570 [/test B95IDlUdR0dxBRMl] [info] "WEnvironment: UserAgent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
[2024-Jul-31 14:47:23.257] 232570 - [info] "WebRequest: took 1.101 ms"
[2024-Jul-31 14:47:25.288] 232570 - [info] "WebRequest: took 2000.35 ms"
[2024-Jul-31 14:47:25.300] 232570 [/test B95IDlUdR0dxBRMl] [warning] "WApplication: WApplication::addMetaHeader() with no effect"
[2024-Jul-31 14:47:25.300] 232570 [/test B95IDlUdR0dxBRMl] [warning] "WMenu: unknown path: 'forms/check-boxes/'"
[2024-Jul-31 14:47:25.369] 232570 [/test B95IDlUdR0dxBRMl] [warning] "WMenu: unknown path: 'check-boxes/'"
[2024-Jul-31 14:47:25.385] 232570 - [info] "WebRequest: took 86.08 ms"
[2024-Jul-31 14:47:25.429] 232570 [/test B95IDlUdR0dxBRMl] [info] "WebRequest: took 0.22 ms"
[2024-Jul-31 14:47:25.429] 232570 [/test B95IDlUdR0dxBRMl] [info] "WebRequest: took 0.393 ms"
[2024-Jul-31 14:47:25.469] 232570 [/test B95IDlUdR0dxBRMl] [info] "WebRequest: took 0.069 ms"
So, it appears that the delay is due to the setTimeout taking over 2 seconds before calling doLoad. Accessing the page with browsers that are not affected, the setTimeout delay is minimal.
As a test, I tried replacing the "setTimeout(doLoad, 0);" with "doLoad();" in Boot.js and the 2-second issue no longer occurred. Looking at the Mozilla documentation for setTimeout(), it seems that there is no guarantee that a setTimeout with 0 delay will have a short delay. See: https://developer.mozilla.org/en-US/docs/Web/API/setTimeout. In particular, the section on "Deferral of timeouts during pageload" states that:
Firefox will defer firing setTimeout() timers while the current tab is loading. Firing is deferred until the main thread is deemed idle (similar to window.requestIdleCallback()), or until the load event is fired.
I'm not sure how this section should be interpreted, but I do believe that the setTimeout in Boot.js is called before the load event is fired and thus might be subject to delay. I also recall seeing sporadic 2-second delays in Firefox in the past. So, maybe this is not so much a completely new issue with Plasma 6, but rather one that tends to be more repeatable?
NOTE: #11378 is another boot-time issue that appears to only occur with Firefox. You may encounter it when trying to reproduce this issue. I'm not sure if they are otherwise related.
If I can provide any additional information, please let me know.
Files
Updated by Matthias Van Ceulebroeck 4 months ago
- Target version set to 4.11.2
Hey Bruce,
thanks for the detailed submission, and the thorough testing. What really throws me off is that:
As a note, I found that setting the display resolution in the virtual machine to the full native resolution of my display (1920x1080) also eliminated the two-second delay -- even with firefox in its default Wayland configuration.
We will investigate some more, if we can hopefully reproduce it. It's potentially an edge case with the JS handler itself, but I can't rule out that Wt may be doing something with the tab in certain cases that would keep the handler busy for too long.
Updated by Bruce Toll 4 months ago
Hey Matthias,
Thanks for following-up. For what it is worth, my guess is that Firefox is deferring the callback on the setTimeout(doLoad, 0) in Boot.js because it (incorrectly) believes that there is nothing productive that Wt could do at that point -- it is waiting for the CSS to load. However, the Wt server won't complete the load of the CSS until it gets the request for its javascript via doLoad. So, nothing happens until the timeout on the CSS expires -- and then Firefox calls the doLoad that was queued by setTimeout. The curious thing, as you note, is why the behavior is varying with screen resolution -- and whether this reflects a bug in Firefox (or its dependencies) -- or is just unspecified behavior. I did make some effort to search for setTimeout issues in Firefox, but didn't see anything relevant.
One other observation that I didn't mention in the original report is that the length of the startup delay is affected by a timeout constant in WebSession.C. If you increase the constant from 2000 milliseconds to 4000 milliseconds, the delay on startup goes up to four seconds. Higher values for the constant do not increase the startup delay. Presumably, there is another timeout occurring at four seconds in Wt (or firefox?).
Here's a diff showing the constant set to 4000 milliseconds for testing:
$ git diff
diff --git a/src/web/WebSession.C b/src/web/WebSession.C
index dd3f6178..7f62db1e 100644
--- a/src/web/WebSession.C
+++ b/src/web/WebSession.C
@@ -1623,7 +1623,7 @@ void WebSession::handleRequest(Handler& handler)
handler.setRequest(nullptr, nullptr);
controller_->server()
- ->schedule(std::chrono::milliseconds{2000}, sessionId_,
+ ->schedule(std::chrono::milliseconds{4000}, sessionId_,
std::bind(&WebSession::flushBootStyleResponse,
this));
} else {
I captured a 3 minute screencast with Fedora in a VM that demonstrates the two second delay occurring at 1024x768 resolution, but not at 1920x1080, with the network tab of the Web Developer tools open. The file is too large for the issue tracker (9.6MB), but I can get it to you another way if you have trouble reproducing the issue locally and would find it helpful.
Updated by Bruce Toll 4 months ago
A few more items that may be relevant:
This is the Firefox issue tracking a feature to: "make setTimeout() low priority during page load"
https://bugzilla.mozilla.org/show_bug.cgi?id=1270059
This is a portion of the patch that introduces dom.timeout.defer_during_load and dom.timeout.max_idle_defer_ms
https://bugzilla.mozilla.org/attachment.cgi?id=9039226&action=diff#a/modules/libpref/init/StaticPrefList.h_sec2
Using about:config to filter on "dom.timeout" and then changing dom.timeout.defer_during_load from true to false effectively eliminated the two second delay at start-up.
Alternatively, reducing the dom.timeout.max_idle_defer_ms from 10000 to 1000 reduced the two second delay at start-up to one second.
So, I believe this dom.timeout.defer_during_load is the mechanism responsible for the observed two second delay. Of course, this still does not explain why the issue seems to primarily happen when using Wayland and Plasma 6, or why it is sensitive to screen resolution.
Updated by Matthias Van Ceulebroeck 3 months ago
- Assignee set to Romain Mardulyn
Updated by Matthias Van Ceulebroeck 3 months ago
Hello Bruce,
it seems this issue isn't reliably reproducable (performed in Oracle's VirtualBox).
What seems to be happening is that the browser itself decided to simply wait, potentially doing something else with the JS engine to remain "busy".
Now, I'm a bit unsure as how we can handle this in Wt. This is during set-up, and depend on browser configuration not accessible to the JS environment. So we cannot explicitly take this value into account, nor can we decide to just remove the setTimeout()
. While intuitively this wouldn't lead to problems, according to my estimation. I cannot guarantee no developer would try to inject some other JS before this call.
I can document this occurrence, and allow a wt config flag to manage this. Say something close to progressive-bootstrap
, called skip-boot-js-delay
(bool) (of course to be renamed, likely). This can then either immediately call the doLoad()
if enabled, or rely on setTimeout()
(by default).
Updated by Bruce Toll 3 months ago
Hello Matthew,
First, I want to thank you for taking the time to investigate this issue. I very much appreciate the work you're doing and recognize that this is both a minor issue and one that is unlikely to affect more than a tiny percentage of browsers.
I think your proposal to add a configuration variable, e.g. skip-boot-js-delay, makes a lot of sense. It provides an option for anyone that encounters the issue in their environment and will position Wt well if the issue becomes more prevalent. I would certainly use the option and provide feedback if it results in any undesirable side-effects.
I regret that I was not able to provide you with a reliable way to reproduce the issue locally; it seems to be very environment-specific.
--Bruce
Updated by Bruce Toll 3 months ago
Hi Matthias,
I apologize for getting your name wrong in the previous message. Thanks, again, for all of your help.
--Bruce
Updated by Romain Mardulyn 3 months ago
- Status changed from InProgress to Review
- Assignee deleted (
Romain Mardulyn)
Updated by Matthias Van Ceulebroeck about 2 months ago
- Assignee set to Matthias Van Ceulebroeck
Updated by Matthias Van Ceulebroeck 13 days ago
- Status changed from Review to Implemented @Emweb
- Assignee changed from Matthias Van Ceulebroeck to Romain Mardulyn
- % Done changed from 0 to 100
Updated by Matthias Van Ceulebroeck 13 days ago
Hey Bruce,
a small update. We eventually settled on delay-load-at-boot
for the name of the option. As we were not able to reproduce it, we also cannot verify the fix. According to our assumptions this should work.
Best,
Matthias
Updated by Bruce Toll 12 days ago
Hey Matthias,
Thanks for the update. I look forward to testing with the new delay-load-at-boot option once it is released. I really appreciate the great work that you, Romain, and the Emweb team have been doing to advance Wt!
Regards,
Bruce