post: kde plasma performance improvements on arch
This commit is contained in:
293
content/post/kde-plasma-performance.md
Normal file
293
content/post/kde-plasma-performance.md
Normal 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 :^)
|
||||
Reference in New Issue
Block a user