--- 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. First, demote background tasks that shouldn't freeze your desktop: ```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"} # Coredump processing - can churn through 100MB+ dumps {"name": "systemd-coredump", "type": "BG_CPUIO"} {"name": "coredumpctl", "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. Next, boost interactive desktop applications that need to stay responsive: ```bash sudo tee /etc/ananicy.d/99-desktop-priority.rules << 'EOF' # Desktop apps that need high priority for responsiveness # Terminal emulators {"name": "warp", "type": "LowLatency_RT"} {"name": "kitty", "type": "LowLatency_RT"} {"name": "alacritty", "type": "LowLatency_RT"} # Plasma desktop - boost higher than defaults {"name": "plasmashell", "nice": -5, "ioclass": "best-effort", "ionice": 0, "latency_nice": -5} # Browsers - boost for snappier UI {"name": "vivaldi-bin", "nice": -3, "ioclass": "best-effort", "ionice": 2, "latency_nice": -3} {"name": "firefox", "nice": -3, "ioclass": "best-effort", "ionice": 2, "latency_nice": -3} EOF ``` The `LowLatency_RT` type sets `nice=-12` — these apps get CPU priority over almost everything else. The `99-` prefix ensures this file loads last and overrides any conflicting defaults. ## 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 | | Coredump processing freezes system | Runs at idle priority | | All processes equal priority | Desktop apps prioritized | The final priority hierarchy looks like this: | Process | Nice | Notes | |:--------|-----:|:------| | warp, kitty, kwin | -12 | `LowLatency_RT` — always responsive | | plasmashell | -5 | Boosted from default -1 | | vivaldi, firefox | -3 | Snappier than default | | _normal processes_ | 0 | Default | | pacman, dkms, gcc | +16 | `BG_CPUIO` — idle only | | systemd-coredump | +16 | Won't freeze on crash dumps | DKMS can now compile nvidia modules while I continue working. Package updates run in the background without the mouse cursor freezing. Even when an app crashes and generates a 100MB+ coredump, the desktop stays smooth. 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 :^)