Nowadays, computing resources management in modern Linux is provided by Cgroups & System. Unfortunately, most Linux distributions ignore its power, because RAM and CPU abuse by modern applications is common practice. That is why we are faced with recurrent issues like CPU over-heating, memory over allocation and overall system slowness.

For example, trying to smoothly run Ubuntu 18.04 on an old laptop, in summer is no go. It is likely going to meld! Because system resources in Linux desktop distributions aren’t taking advantage of modern kernel functionality! Desktop apps are allowed to abuse system resources!

Let’s fix this!

Setting up Resource Control in Linux (4.5 and up)

  1. Setup a controlled slice of system resources for heavy apps. File: /etc/systemd/system/custom.slice

    [Unit]
    Description=Custom system resources slice
    Before=slices.target
    
    [Slice]
    MemoryAccounting=true
    MemoryHigh=35%
    MemoryMax=50%
    CPUAccounting=true
    CPUQuota=200%
    
    [Install]
    WantedBy=multi-user.target
    

    NOTE; CPUQuota=200% is equivalent to assigning 2 cores. 300% would be 3 and so on.

  2. Setup a wrapper for running desktop apps
    File: /usr/local/bin/rcrun

    #!/usr/bin/env sh
    
    CMD="/usr/bin/systemd-run -p NoNewPrivileges=yes -p WorkingDirectory=${HOME} \
      --slice=${1} --setenv DISPLAY=${DISPLAY} --setenv DBUS_SESSION_BUS_ADDRESS=${DBUS_SESSION_BUS_ADDRESS} \
      --uid ${USER} --gid ${USER} -- ${2} ${3}"
    
    eval $CMD
    

    Make the script executable: $ chmod a+x /usr/local/bin/rcrun

  3. Setup policykit (polkit) to allow invoking rcrun password less:

    1. Create a polkit rule for our rcrun (v0.106 and up): File: /usr/share/polkit-1/rules.d/99-nopass-rcrun.rules

      polkit.addRule(function(action, subject) {
        if (
          (action.id == "org.freedesktop.systemd1.manage-units") &&
          subject.local && subject.active &&
          (subject.isInGroup("sudo"))
        ) {
          return polkit.Result.YES;
        }
      });
      
    2. Create a polkit local authority for our rcrun (older than v0.106): File: /etc/polkit-1/localauthority/50-local.d/99-nopass-rcrun.pkla

      [Run user apps under resource control]
      Identity=unix-group:sudo
      Action=org.freedesktop.systemd1.manage-units
      ResultActive=yes
      
  4. Monitoring

     $ systemd-cgls # list of running services grouped by cgroup slice
     $ systemd-cgtop # list of running services interactively sorted by resource usage
    
  5. Testing

     $ journalctl --no-hostname --follow --unit=custom.slice
     $ rcrun custom.slice lua5.1 "-e 'a=1;t={}; while true do a=a+1;t[a]=10^10; end'"
    

Conclusion

Taking advantage of modern Linux kernel functionality, we are able effectively control and balance the use of system resources, so that we don’t burn another computer anymore!

Known issues

  • Failed to start transient service unit: Unit browser.service already exists!

    $ systemctl daemon-reload
    $ systemctl reset-failed
    

References