Desktop-oriented kernel scheduler?

I’m running NixOS on my laptop, and sometimes the GUI hangs when a lot of CPU is used. For example, doing a Jitsi meeting and opening a VS Code project that starts running a lot of linters etc.

For the rest the system is very responsive, so I’m wondering if there is maybe a setting I’m missing to give the desktop processes priority over other processes?

I’m using Xorg but that’s only because Wayland can’t do screen sharing and some other small issues.

1 Like

I have this in my configuration, FWIW:

  boot.kernel.sysctl = {
    "vm.swappiness" = 90; # when swapping to ssd, otherwise change to 1
    "vm.vfs_cache_pressure" = 50;
    "vm.dirty_background_ratio" = 20;
    "vm.dirty_ratio" = 50;
    # these are the zen-kernel tweaks to CFS defaults (mostly)
    "kernel.sched_latency_ns" = 4000000;
    # should be one-eighth of sched_latency (this ratio is not
    # configurable, apparently -- so while zen changes that to
    # one-tenth, we cannot):
    "kernel.sched_min_granularity_ns" = 500000;
    "kernel.sched_wakeup_granularity_ns" = 50000;
    "kernel.sched_migration_cost_ns" = 250000;
    "kernel.sched_cfs_bandwidth_slice_us" = 3000;
    "kernel.sched_nr_migrate" = 128;
  };

no hard numbers on how much all that really helps, but definitely doesn’t seem to make things worse.

Oh, it’s also important to realize that tweaking scheduler parameters is only one half of it – that just lowers its granularity so it can do its prioritization with higher frequency. The other half is telling it what to prioritize (or, rather, what to de-prioritize). To that end:

  # Tell kernel to use cgroups_v2 exclusively
  boot.kernelParams = [ "cgroup_no_v1=all" "systemd.unified_cgroup_hierarchy=yes" ];
  # Let users put things in appropriately-weighted scopes
  systemd = {
    extraConfig = ''
      DefaultCPUAccounting=yes
      DefaultMemoryAccounting=yes
      DefaultIOAccounting=yes
    '';
    user.extraConfig = ''
      DefaultCPUAccounting=yes
      DefaultMemoryAccounting=yes
      DefaultIOAccounting=yes
    '';
    services."user@".serviceConfig.Delegate = true;
  };

And then you get to define what you consider non-interactive. I just have this on the system configuration side:

  systemd.services.nix-daemon.serviceConfig = {
    CPUWeight = 20;
    IOWeight = 20;
  };

And this script to wrap heavy builds etc. with (I call it “nicely”):

#! /bin/sh -f
exec systemd-run --user --quiet --scope --same-dir --collect -p CPUWeight=20 -p IOWeight=20 "$@"
2 Likes

And no tweakpost should be considered complete without a honest “what doesn’t work and what we haven’t tried” part, yes? Yes.

  • The standard CFS scheduler does not appear to have any (or at least any that actually work) smarts to automatically recognize interactive tasks and prioritize them for you. This is regrettable, but CFS is basically the only game in town (even the Zen kernel, while including an alternative scheduler, does not actually enable it)

  • A very important thing to watch for is free space on SSD. Avoid getting too close to full consumption – if you do, I/O latencies will grow by an order of magnitude (due to flash gc or trimming or who knows what) and the effects cannot be mitigated

1 Like

You could use the MultiQueue Skiplist Scheduler (MuQSS).
The patches for Linux 5.11 can be found here: Index of /patches/5.0/5.11/5.11-ck1/patches

Very interesting, thanks!

Is it possible to choose weights based on executable filename? That would be great! Maybe some daemon that monitors processes?