diff --git a/content/post/kde-plasma-performance.md b/content/post/kde-plasma-performance.md new file mode 100644 index 0000000..1b860d8 --- /dev/null +++ b/content/post/kde-plasma-performance.md @@ -0,0 +1,293 @@ +--- +title: "Taming the KDE Plasma Beast: Desktop Responsiveness on Arch Linux" +date: 2026-01-04 +lastmod: 2026-01-04 +categories: ["Blog"] +tags: ["linux", "kde", "performance"] +--- +When your beefy Ryzen 9 system locks up during a simple `pacman -Syu`, something +is very wrong. Here's how to stop Baloo, ClamAV, and poor IO scheduling from +hijacking your desktop. + + + +# The Problem + +Picture this: you're running system updates on a Ryzen 9 7945HX3D with 62GB of +RAM and dual NVMe drives. DKMS starts compiling the nvidia module and suddenly +your entire desktop freezes. Mouse cursor? Frozen. Keyboard? Unresponsive. The +only option is reaching for the power button. + +**This should not happen.** A modern system with this kind of hardware should +handle background compilation without breaking a sweat. Time to investigate. + +# The Culprits + +After some digging, three major offenders emerged: + +## 1. Baloo File Indexer + +KDE's file indexer was the worst offender: + +```bash +$ balooctl6 status +Total files indexed: 845,512 +Files waiting for content indexing: 103,138 +Current size of index is 24.27 GiB +``` + +**Twenty-five gigabytes** of index data, with over 100,000 files still queued. +Worse, checking mounted filesystems revealed the real problem: + +```bash +$ mount | grep cifs +//truenas.localdomain/share on /mnt/share type cifs ... +``` + +Baloo was trying to index a network share. Every file access over the network +was blocking IO and competing with the desktop for resources. Classic. + +## 2. ClamAV Daemon + +The antivirus daemon was consuming 1.2GB of RAM just sitting there: + +```bash +$ systemctl status clamav-daemon +Memory: 1.2G (peak: 2.1G) +``` + +On Linux, ClamAV is honestly overkill for a desktop system. It's designed for +mail servers and file shares, not personal workstations where you control what +gets executed. + +## 3. Wrong IO Scheduler + +Both NVMe drives were using the BFQ scheduler: + +```bash +$ cat /sys/block/nvme*/queue/scheduler +[bfq] +[bfq] +``` + +BFQ is great for HDDs and SATA SSDs where the kernel needs to optimize head +movement and queue depth. NVMe drives have their own hardware schedulers with +massive parallel queue support. Adding kernel-level scheduling just creates +overhead. + +# The Fixes + +## Step 1: Kill Baloo + +If you don't use KDE's file search (and let's be honest, most terminal users +don't), just disable it: + +```bash +# Disable the indexer +balooctl6 disable + +# Delete the bloated database +rm -rf ~/.local/share/baloo +``` + +The config file at `~/.config/baloofilerc` will now show: + +```ini +[Basic Settings] +Indexing-Enabled=false +``` + +This persists across reboots. Done. + +## Step 2: Remove or Throttle ClamAV + +> **Security Consideration:** Removing antivirus software is a trade-off +> between performance and security. While Linux desktops are less targeted than +> Windows, threats do exist — especially if you download software from untrusted +> sources, open email attachments, or share files with Windows users. **Proceed +> at your own risk.** + +For a personal desktop where you're not scanning incoming mail or shared files, +you have a few options: + +### Option A: Remove ClamAV entirely (at your own risk) + +```bash +sudo systemctl disable --now clamav-daemon clamav-freshclam +sudo pacman -Rns clamav +``` + +### Option B: Keep ClamAV but throttle it + +If you want to keep real-time protection but prevent it from impacting system +responsiveness, create a systemd override: + +```bash +sudo mkdir -p /etc/systemd/system/clamav-daemon.service.d +sudo tee /etc/systemd/system/clamav-daemon.service.d/override.conf << 'EOF' +[Service] +Nice=19 +IOSchedulingClass=idle +IOSchedulingPriority=7 +CPUSchedulingPolicy=idle +CPUQuota=30% +MemoryMax=1G +EOF +sudo systemctl daemon-reload +sudo systemctl restart clamav-daemon +``` + +This forces ClamAV to only use idle CPU/IO time and caps its resource usage. + +### Option C: Manual scans only + +Disable the daemon but keep the package for on-demand scanning: + +```bash +sudo systemctl disable --now clamav-daemon clamav-freshclam +# Scan manually when needed: +# clamscan -r /path/to/scan +``` + +### Alternatives to ClamAV + +If you remove ClamAV, consider these complementary security measures: + +- **[Firejail](https://wiki.archlinux.org/title/Firejail)** — Sandbox untrusted + applications with minimal effort +- **[AppArmor](https://wiki.archlinux.org/title/AppArmor)** — Mandatory access + control for limiting application capabilities +- **[USBGuard](https://wiki.archlinux.org/title/USBGuard)** — Protect against + rogue USB devices +- **Common sense** — Don't run random binaries from the internet, verify + checksums, use official repositories + +For most Linux desktop users who stick to official repos and don't open +suspicious attachments, the risk is manageable. But if you're handling sensitive +data or files from untrusted sources, keep some form of scanning available. + +## Step 3: Fix the IO Scheduler + +Create a udev rule to set the correct scheduler per drive type: + +```bash +sudo tee /etc/udev/rules.d/60-ioschedulers.rules << 'EOF' +# NVMe drives have hardware schedulers - use none +ACTION=="add|change", KERNEL=="nvme[0-9]*n[0-9]*", ATTR{queue/scheduler}="none" +# HDDs benefit from BFQ +ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="bfq" +# SATA SSDs - none is fine +ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="none" +EOF + +# Apply immediately +echo none | sudo tee /sys/block/nvme*/queue/scheduler +``` + +## Step 4: Install ananicy-cpp + +This is the real game-changer. [Ananicy-cpp](https://gitlab.com/ananicy-cpp/ananicy-cpp) +automatically adjusts process priorities based on what's running: + +```bash +sudo pacman -S ananicy-cpp +yay -S cachyos-ananicy-rules-git # Community rules +sudo systemctl enable --now ananicy-cpp +``` + +Now add custom rules for package management and compilation: + +```bash +sudo tee /etc/ananicy.d/package-managers.rules << 'EOF' +# Package managers and compilers - lowest priority +{"name": "pacman", "type": "BG_CPUIO"} +{"name": "yay", "type": "BG_CPUIO"} +{"name": "makepkg", "type": "BG_CPUIO"} +{"name": "dkms", "type": "BG_CPUIO"} +{"name": "mkinitcpio", "type": "BG_CPUIO"} +{"name": "gcc", "type": "BG_CPUIO"} +{"name": "cc1", "type": "BG_CPUIO"} +{"name": "cc1plus", "type": "BG_CPUIO"} +{"name": "rustc", "type": "BG_CPUIO"} +{"name": "cargo", "type": "BG_CPUIO"} +{"name": "ninja", "type": "BG_CPUIO"} +{"name": "make", "type": "BG_CPUIO"} +EOF +``` + +The `BG_CPUIO` type sets `nice=16`, `ioclass=idle`, and `sched=idle`. These +processes will only get CPU and disk time when nothing else needs it. + +## Step 5: Tune VM Dirty Page Handling + +The kernel's default dirty page settings are tuned for servers, not desktops. +With 62GB of RAM, the defaults would allow gigabytes of dirty pages to +accumulate before flushing — causing massive IO storms that freeze everything. + +```bash +sudo tee /etc/sysctl.d/99-desktop-responsiveness.conf << 'EOF' +# Use absolute byte limits instead of percentages +vm.dirty_ratio = 0 +vm.dirty_background_ratio = 0 + +# Start background writeback at 256MB +vm.dirty_background_bytes = 268435456 +# Force sync at 1GB max +vm.dirty_bytes = 1073741824 + +# Flush dirty pages faster +vm.dirty_expire_centisecs = 1000 +vm.dirty_writeback_centisecs = 100 + +# Keep 256MB always free +vm.min_free_kbytes = 262144 + +# Desktop-friendly swappiness +vm.swappiness = 10 +vm.vfs_cache_pressure = 50 +EOF + +sudo sysctl --system +``` + +# The Results + +| Before | After | +|:-------|:------| +| System freezes during updates | Desktop stays responsive | +| 25GB Baloo database | 0 bytes | +| 1.2GB ClamAV RAM usage | 0 bytes | +| BFQ overhead on NVMe | Direct hardware scheduling | +| Compilation starves desktop | Compilation yields to UI | + +DKMS can now compile nvidia modules while I continue working. Package updates +run in the background without the mouse cursor freezing. The system finally +behaves like it should on modern hardware. + +# Diagnostic Commands + +When things go wrong, these help identify the culprit: + +```bash +# What's causing IO wait? +iotop -oPa + +# System IO-bound? +vmstat 1 5 + +# Processes stuck in disk wait (D state)? +ps auxf | grep " D " + +# Current dirty page status +grep -E "^(Dirty|Writeback):" /proc/meminfo +``` + +# The Takeaway + +A powerful system shouldn't freeze during routine operations. The defaults in +most Linux distributions are tuned for servers or general compatibility, not +desktop responsiveness. A few targeted tweaks — killing unnecessary indexers, +fixing IO schedulers, and prioritizing interactive processes — make all the +difference. + +No more hard resets during system updates :^)