post: kde plasma performance improvements on arch

This commit is contained in:
Bastian de Byl
2026-01-04 14:23:11 -05:00
parent 4a269c01d8
commit da7c837fc0

View File

@@ -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.
<!--more-->
# 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 :^)