FnQL: 0.1.0.94 (318b5e3), MSVC Win32 client, under Proton (proton-cachyos 11, winewayland), Vulkan renderer.
Hardware: i5-8600K, RTX 4060 Ti (NVIDIA 615.71.09), KDE Plasma 6.7.5 Wayland, 240 Hz VRR.
Settings: com_maxfps 250, com_yieldCPU 0, r_swapInterval 0.
All numbers are MangoHud per-frame logs, 60 s per run, from demo replays at 250 fps.
1. Steam integration: ~70 ms stalls in a replay of a busy public CA match
The demo was recorded by FnQL itself (.dm_68) from a public CA match.
| config |
stalls >15 ms / min |
worst frame |
| Steam on, WebUI disabled (3 runs) |
1-3 |
69-73 ms |
| Steam on, WebUI on with browser hidden (2 runs) |
3-5 |
71-72 ms |
+set com_steamIntegration 0 (2 runs) |
0 |
4.5 / 6.1 ms |
What the profile shows:
- Nothing is rendered during a stall. A user-space
perf profile of the main thread shows no driver or Vulkan samples for the ~70 ms.
- The thread is waiting on Steam IPC. Most of the stall is spent off-CPU in short waits. The samples that do land are in
steamclient.so / lsteamclient.dll (including poll), in engine code, and in libc.
The exact call is unconfirmed because the provider is closed source. My suspect is CL_RegisterSteamAvatarShader. It calls FNQL_Steam_GetAvatarRGBA twice synchronously (cl_webui.cpp:1157 and :1173) for LARGE avatars, is reached from the cgame's CG_QL_IMPORT_GET_AVATAR_IMAGE_HANDLE, and then calls RegisterShaderFromRGBA on the main thread.
The stalls did not reproduce on two retail-recorded (.dm_91) demos: a 3v3 CA match and a public CTF match. So the trigger looks match-specific; it might be players joining or changing, which forces avatar fetches. Retail QL was stall-free on those same two demos too, but it can't play the .dm_68 demo, so I have no retail control for the stall case.
Suggested fixes:
- Fetch avatars asynchronously or on a worker thread, and upload the texture on a later frame.
- Or prefetch avatars when a player connects.
- Or use smaller avatars in-game.
2. An open WebUI main menu stalls the engine
While the web main menu is visible, I see two things:
- Spikes: ~7.7 ms frames in ~4 s bursts every 10 s (about 85 per minute). They're in phase with
awesomium_process CPU bursts, probably the friends list refresh.
- Stalls: 54-78 ms frames several times a minute, even with
com_steamIntegration 0.
Hiding the browser clears both in-game. The same replay with the browser hidden had 0 stalls, max 5.9 ms.
The menu also stays up in a way users are likely to hit. After demo <name> from the console, the web main menu stays over the playing demo and togglemenu doesn't close it. Only web_hideBrowser does, which is what the menu's "You are currently in-game. Click here to return to your match" bar calls.
3. com_speeds rf/bk always read 0 on the Vulkan renderer
ri.Milliseconds is CL_ScaledMilliseconds(), which returns the per-frame cls.realtime (cl_main.cpp:4661). Every renderer-internal delta is therefore 0, and all render, acquire and present time lands in cl.
Notes
- Source line numbers refer to master
e24b4df. The tested build was 0.1.0.94.
- Tested under Proton. The synchronous call path is the same on every platform, but the Steam IPC route under Proton (
steam_api.dll -> lsteamclient -> Linux steamclient.so) likely makes each stall longer than on native Windows.
FnQL: 0.1.0.94 (318b5e3), MSVC Win32 client, under Proton (proton-cachyos 11, winewayland), Vulkan renderer.
Hardware: i5-8600K, RTX 4060 Ti (NVIDIA 615.71.09), KDE Plasma 6.7.5 Wayland, 240 Hz VRR.
Settings:
com_maxfps 250,com_yieldCPU 0,r_swapInterval 0.All numbers are MangoHud per-frame logs, 60 s per run, from demo replays at 250 fps.
1. Steam integration: ~70 ms stalls in a replay of a busy public CA match
The demo was recorded by FnQL itself (
.dm_68) from a public CA match.+set com_steamIntegration 0(2 runs)What the profile shows:
perfprofile of the main thread shows no driver or Vulkan samples for the ~70 ms.steamclient.so/lsteamclient.dll(includingpoll), in engine code, and in libc.The exact call is unconfirmed because the provider is closed source. My suspect is
CL_RegisterSteamAvatarShader. It callsFNQL_Steam_GetAvatarRGBAtwice synchronously (cl_webui.cpp:1157 and :1173) for LARGE avatars, is reached from the cgame'sCG_QL_IMPORT_GET_AVATAR_IMAGE_HANDLE, and then callsRegisterShaderFromRGBAon the main thread.The stalls did not reproduce on two retail-recorded (
.dm_91) demos: a 3v3 CA match and a public CTF match. So the trigger looks match-specific; it might be players joining or changing, which forces avatar fetches. Retail QL was stall-free on those same two demos too, but it can't play the.dm_68demo, so I have no retail control for the stall case.Suggested fixes:
2. An open WebUI main menu stalls the engine
While the web main menu is visible, I see two things:
awesomium_processCPU bursts, probably the friends list refresh.com_steamIntegration 0.Hiding the browser clears both in-game. The same replay with the browser hidden had 0 stalls, max 5.9 ms.
The menu also stays up in a way users are likely to hit. After
demo <name>from the console, the web main menu stays over the playing demo andtogglemenudoesn't close it. Onlyweb_hideBrowserdoes, which is what the menu's "You are currently in-game. Click here to return to your match" bar calls.3.
com_speedsrf/bkalways read 0 on the Vulkan rendererri.MillisecondsisCL_ScaledMilliseconds(), which returns the per-framecls.realtime(cl_main.cpp:4661). Every renderer-internal delta is therefore 0, and all render, acquire and present time lands incl.Notes
e24b4df. The tested build was 0.1.0.94.steam_api.dll->lsteamclient-> Linuxsteamclient.so) likely makes each stall longer than on native Windows.