KDE laggy after suspend until reboot? Your clock may be running 8% slow (dual-boot / RTC in local time)

After waking my laptop from suspend, KDE Plasma sometimes became very slow and choppy. Animations, window moves and even the cursor were affected. Only a reboot fixed it. A friend with a different laptop (Huawei, 13th-gen Intel, no dGPU) on Fedora 44 KDE had the same problem.

I spent a long time checking the GPU, KWin, PSR, CPU throttling and timer latency. Everything measured healthy. The actual cause was the system clock.

Setup: Lenovo ThinkBook 16p G5 (i9-14900HX), Fedora 44, kernel 7.2.7, Plasma 6.7.5 on Wayland, Windows dual-boot.

What was happening

timedatectl showed RTC in local TZ: yes, which is the Windows dual-boot default. After resume, the clock came back 3 hours off, exactly my UTC offset:

chronyd[1511]: System clock wrong by -10799.997000 seconds

Fedora’s default makestep 1.0 3 only lets chrony step the clock right after boot. After that, chrony slews the clock instead. On my machine the kernel tick was 9167 instead of 10000, so CLOCK_MONOTONIC ran at 0.917× real speed. At that rate, correcting 3 hours takes about 36 hours. Everything timed against that clock, including compositor animations and frame scheduling, ran slow and out of step with the 60 Hz panel.

A quick way to see it:

chronyc tracking | grep "System time"

# System time : 10681.26 seconds fast of NTP time

Fix

Instant, no reboot needed. The lag disappears immediately:

sudo chronyc makestep

Permanent fix: keep the RTC in UTC.

sudo timedatectl set-local-rtc 0

And on Windows, in an admin Command Prompt:

reg add "HKLM\System\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /d 1 /t REG_DWORD /f

If you would rather not touch Windows, changing makestep 1.0 3 to makestep 1.0 -1 in /etc/chrony.conf makes chrony step large offsets at any time instead of slewing them.

I put a small read-only check script and the full write-up here: GitHub - EOLO03/kde-suspend-lag-rtc-fix: Desktop laggy after suspend until reboot? Your system clock may be running 8% slow (RTC in local time / dual-boot). Diagnosis, check script and fix. · GitHub

Hope this saves someone a few hours. If you hit the same thing, please post your hardware so we can see how widespread it is.

That in itself sounds like a bug that should be reported and looked at.

RTC in local TZ is suboptimal (e.g. for the handling of daylight savings), but it shouldn’t cause the clock to jump just because you woke the system from suspend.

Thanks, agreed: the jump itself is the real bug. I’ve reported it here:

I filed it against chrony because the ~36 h slew is what makes the desktop unusable, but I noted in the report that the root cause (the local-time RTC apparently being read as UTC on resume) may belong to the kernel, and asked for it to be reassigned if so.

The raw measurements are attached to the bug and also in the repo (EVIDENCE.md).

On window 11 Run as Administrator the following command:

reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /d 1 /t REG_DWORD /f

Then Adjust data and time to ensure it’s the right time.

Now boot into fedora and set RTC to UTC.

That should eliminate issues with timezones and dual booting.

Is that the same command that’s already in the OP?

Yes, same command (HKLM is short for HKEY_LOCAL_MACHINE), and it’s already applied here. Thanks anyway, Barry!

Update: root cause found, it is a kernel bug, and a patch has been sent.

The 3-hour jump after resume comes from the kernel’s resume path, not from chrony and not from the desktop.

In short: on x86 the kernel does not save the RTC and system time when it suspends, because the CMOS clock is supposed to provide the sleep time. With s2idle, if the last freeze before wake-up is shorter than a second, the CMOS clock has not moved, so the kernel falls back to the RTC driver. That code then works with values that were never saved and adds “RTC time minus system time” to the clock. With the RTC in UTC that is about zero. With the RTC in local time east of UTC it is your UTC offset.

That explains why it only shows up on dual-boot machines with the RTC in local time, and why it only happens on some resumes.

I can now trigger it on demand with a script. On the same laptop:

Kernel Control cycles Test cycles
7.2.8-200.fc44 0 of 8 jumped 7 of 30 jumped
7.3-rc5, unpatched 0 of 8 jumped 4 of 30 jumped
7.3-rc5, patched 0 of 8 jumped 0 of 30 jumped

Until a fixed kernel arrives, the workaround is unchanged: keep the RTC in UTC (sudo timedatectl set-local-rtc 0, plus RealTimeIsUniversal on Windows), and use sudo chronyc makestep if the desktop is already lagging.