Skip to content

A daemon for X11 designed to automatically limit CPU usage of unfocused windows and run commands on focus and unfocus events.

License

Notifications You must be signed in to change notification settings

itz-me-zappex/flux

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 

Repository files navigation

flux

A daemon for X11 designed to automatically limit CPU usage of unfocused windows and run commands on focus and unfocus events.

Navigation

Dependencies

  • Arch Linux branch:

    Required: bash util-linux cpulimit coreutils xorg-xprop xorg-xwininfo

    Optional: mangohud lib32-mangohud

  • Debian/Ubuntu branch:

    Required: bash cpulimit coreutils x11-utils

    Optional: mangohud mangohud:i386

  • Void Linux:

    Required: bash util-linux cpulimit coreutils xprop xwininfo

    Optional: MangoHud MangoHud-32bit

  • Fedora branch:

    Required: bash util-linux cpulimit coreutils xprop xwininfo

    Optional: mangohud mangohud.i686

  • OpenSUSE Tumbleweed:

    Required: bash util-linux cpulimit coreutils xprop xwininfo

    Optional: MangoHud mangohud-32bit

  • Gentoo:

    Required: app-shells/bash sys-apps/util-linux app-admin/cpulimit sys-apps/coreutils x11-apps/xprop x11-apps/xwininfo

    Optional: mangohud (is not packaged)

Dependencies for other distributions will be added soon.

Installation

Manual installation

Make sure you have installed dependencies described above before continue.

$ fluxver='1.6.9'
$ mkdir flux && cd flux # create build directory
$ wget https://github.com/itz-me-zappex/flux/archive/refs/tags/v${fluxver}.tar.gz # download archive with release
$ tar -xvf v${fluxver}.tar.gz # extract it
$ sudo install -Dm 755 flux-${fluxver}/flux /usr/local/bin/flux # Install daemon to `/usr/local/bin`

Arch Linux (and based distributions)

Make sure you have installed base-devel package before continue.

$ fluxver='1.6.9'
$ mkdir flux && cd flux # create build directory
$ wget https://github.com/itz-me-zappex/flux/releases/download/v${fluxver}/PKGBUILD # download PKGBUILD
$ makepkg -sric # build a package and install it

Debian/Ubuntu (and based distributions)

$ fluxver='1.6.9'
$ mkdir flux && cd flux # create build directory
$ wget https://github.com/itz-me-zappex/flux/releases/download/v${fluxver}/build-deb.sh # download build script
$ chmod +x build-deb.sh # make it executable
$ ./build-deb.sh # build a package
$ sudo dpkg -i flux-v${fluxver}.deb ; sudo apt install -f # install a package

Other distributions

Use manual method, or if you can, help me create packages for other distributions.

Usage

Usage: flux [option] <value>
Options and values:
    -c, --config     <path-to-config>    Specify path to config file
    -f, --focused                        Display template for config from focused window
    -h, --help                           Display this help
    -H, --hot                            Apply actions to already unfocused windows before handling events
    -l, --lazy                           Avoid focus and unfocus commands on hot
    -p, --pick                           Display template for config by picking window
    -q, --quiet                          Display errors and warnings only
    -u, --usage                          Same as '--help'
    -v, --verbose                        Detailed output
    -V, --version                        Display release information

Autostart

Just add command to autostart using your DE settings or WM config. Running daemon as root also possible, but that feature almost useless.

Configuration

A simple INI is used for configuration. Available keys and description:

Key Description
name Name of process, gets from /proc/<PID>/comm, required if neither executable nor command is specified.
executable Path to binary of process, gets by reading /proc/<PID>/exe symlink, required if neither name nor command is specified.
owner User ID of process, gets from /proc/<PID>/status.
cpu-limit CPU-limit between 0% and 100%, defaults to -1% which means no CPU-limit, % symbol is optional.
delay Delay before applying CPU-limit, preferable to avoid freezing app on exit when windows closes but process still exists if cpu-limit equal to 0%, defaults to 0.
focus Command to execute on focus event, command runs via bash and will not be killed on daemon exit, output is hidden for avoid mess in output of daemon.
unfocus Command to execute on unfocus event, command runs via bash and will not be killed on daemon exit, output is hidden for avoid mess in output of daemon.
command Command of process, gets from /proc/<PID>/cmdline, required if neither name nor executable is specified.
mangohud-config Path to MangoHud config, required if you want change FPS-limits and requires fps-unfocus.
fps-unfocus FPS to set on unfocus, required by and requires mangohud-config.
fps-focus FPS to set on focus, requires fps-unfocus, defaults to 0 (i.e. full unlimit).

Config path

  • Daemon searches for following configuration files by priority:
    • /etc/flux.ini
    • $XDG_CONFIG_HOME/flux.ini
    • ~/.config/flux.ini

Limitations

Since INI is not standartized, I should mention all supported features here.

  • Supported:
    • Spaces in section names.
    • Single and double quoted strings.
    • Commented lines and inline comments using ; and/or # symbols.
    • Сase insensitive name of keys.
    • Insensetivity to spaces before and after = symbol.
  • Unsupported:
    • Regular expressions.
    • Inline comment on lines with section name.
    • Line continuation using \ symbol.
    • Anything else what unmentioned above.

Configuration example

Long examples
; Example using freezing with delay as that is single player game
[The Witcher 3: Wild Hunt]
name = witcher3.exe
executable = /home/zappex/.local/share/Steam/steamapps/common/Proton 8.0/dist/bin/wine64-preloader
command = Z:\run\media\zappex\WD-BLUE\Games\Steam\steamapps\common\The Witcher 3\bin\x64\witcher3.exe 
owner = 1000
cpu-limit = 0%
delay = 1
focus = killall picom
unfocus = picom

; Example using FPS-limit as that is online game and I use MangoHud
[Forza Horizon 4]
name = ForzaHorizon4.e
executable = /run/media/zappex/WD-BLUE/Games/Steam/steamapps/common/Proton 9.0 (Beta)/files/bin/wine64-preloader
command = Z:\run\media\zappex\WD-BLUE\Games\Steam\steamapps\common\ForzaHorizon4\ForzaHorizon4.exe 
owner = 1000
mangohud-config = /home/zappex/.config/MangoHud/wine-ForzaHorizon4.conf
fps-unfocus = 5 ; FPS to set on unfocus event
fps-focus = 60 ; I have 60 FPS lock, so I want restore it on focus event
focus = killall picom
unfocus = picom

; Example using CPU-limit to show this example, as game has connection to network, I do not want to freeze it completely in cases like downloading music or saving data on background
[Geometry Dash]
name = GeometryDash.ex
executable = /home/zappex/.local/share/Steam/steamapps/common/Proton 8.0/dist/bin/wine64-preloader
command = Z:\run\media\zappex\WD-BLUE\Games\Steam\steamapps\common\Geometry Dash\GeometryDash.exe 
owner = 1000
cpu-limit = 2%
delay = 1
focus = killall picom
unfocus = picom
Short examples
; Example using freezing with delay as that is single player game
[The Witcher 3: Wild Hunt]
name = witcher3.exe
cpu-limit = 0%
delay = 1

; Example using FPS-limit as that is online game and I use MangoHud
[Forza Horizon 4]
name = ForzaHorizon4.e
mangohud-config = /home/zappex/.config/MangoHud/wine-ForzaHorizon4.conf
fps-unfocus = 5 ; FPS to set on unfocus event
fps-focus = 60 ; I have 60 FPS lock, so I want restore it on focus event

; Example using CPU-limit to show this example, as game has connection to network, I do not want to freeze it completely in cases like downloading music or saving data on background
[Geometry Dash]
name = GeometryDash.ex
cpu-limit = 2%
delay = 1

Variables

Flux does not support environment variables, but passes them to commands in focus and unfocus keys.

Variable Description
FLUX_WINDOW_ID ID of focused window
FLUX_PROCESS_PID Process PID of focused window
FLUX_PROCESS_NAME Process name of focused window
FLUX_PROCESS_EXECUTABLE Path to process binary
FLUX_PROCESS_OWNER UID of process
FLUX_PROCESS_COMMAND Command of process

Daemon passes absolutely same values for both focus and unfocus keys.

Tips and tricks

Keybinding to obtain template from focused window for config
  • All you need is install xclip tool and bind this command: $ flux --focus | xclip -selection clipboard. Now you can easily grab templates from windows to use them in config by pasting content using Ctrl+v.
Apply changes in config file
  • Create shortcut for $ killall flux ; flux --hot --lazy command which restarts daemon and use it when you done config file editing.
Improve performance of daemon
  • Geeks only, casual users should not care about that. To do that, run daemon using command like $ chrt --batch 0 flux --hot --lazy. SCHED_BATCH scheduling policy is designed to improve performance of non-interactive tasks like daemons, timers, scripts etc..
Types of limits and which you should use
  • FPS-limits recommended for online and multiplayer games and if you do not mind to use MangoHud, this method reduces resource consumption when game unfocused/minimized.
  • CPU-limits greater than zero recommended for online and multiplayer games in case you do not use MangoHud, but you should be ready to stuttery audio since cpulimit tool interrupts process with SIGSTOP and SIGCONT signals.
  • CPU-limit equal to zero recommended for single player games or online games in offline mode, this method freezes game completely to make it just hang in RAM without using any CPU or GPU resources.

Possible questions

How does daemon work?
  • Daemon reads X11 events related to window focus, then it gets PID of process using window ID and uses it to collect info about process (process name, its executable path, command which is used and UID) to compare it with identifiers in config, when it finds window which matches with identifier(s) specified in specific section in config, it runs command from focus key (if specified), when you switching to another window - applies FPS or CPU-limit (if specified) and runs command from unfocus key (if specified). When window does not match with any section in config, nothing happens. To reduce CPU usage and speed up daemon a caching algorithm was implemented which stores info about windows into associative arrays, that allows to just collect info about process once and then use cache to get process info immediately after obtaining its PID when window appears focused again.
Does that daemon reduce performance?
  • Long story short, impact on neither performance nor battery life should be noticeable. It uses event-based algorithm to obtain info about windows and processes, when you switching between windows daemon consumes a bit CPU time, but it just chills out when you playing game or working in single window.
Is it safe?
  • Yes, read above. Neither I nor daemon has access to your data.
Should I trust you and this utility?
  • You can read entire code. If you are uncomfortable, feel free to avoid using it.
With which DE/WM/GPU daemon works correctly?
  • Daemon compatible with all X11 window managers and desktop environments and does not depend on neither GPU nor driver version as it relies on X11 event system.
Is not running commands on focus and unfocus makes system vulnerable?
  • Just put config file to /etc/flux.ini and make it read-only, also do something like that with scripts you interacting with from config file.
Can I get banned in a game because of this daemon?
  • Nowadays, anti-cheats are pure garbage, developed by freaks without balls, and you can get banned even for a wrong click. But that is should not be bannable except you are farmer and using sandboxing. Do not write me if you got a ban in game.
Why was that daemon developed?
  • Main task is to reduce CPU usage of games that have been minimized. Almost every engine fails to recognize that game is unfocused and continues to consume a lot of CPU and GPU resources, what can make system slow for other tasks like browsing stuff, transcoding video etc. or even unresponsive at all. Imagine users with weak laptop who upgraded their RAM to maximum and suffer from a weak processor, now they can simply play a game and then minimize it if needed without carrying about CPU usage or battery level since process just will hang in RAM. There are a lot of situations and usecases for it.
Bugs?
  • Nothing is perfect in this world. Almost all bugs I encountered during development have been fixed or will be fixed soon. If you find a bug, open an issue. Known issues that cannot be fixed are:
    • Inability to interact with "glxgears" and "vkcube" windows, as they do not report their PIDs.
    • Freezing online games (setting cpu-limit to 0%) causes disconnects from matches, so use less aggressive CPU-limit to allow game to send/receive packets.
    • Stuttery audio in game if CPU-limit is very aggressive, since cpulimit tool interrupts process, that should be expected.
Why is code so complicated?
  • Long story short, try removing at least one line of code (that does not affect output, of course) and see what happens. That sounds easy - just apply a CPU-limit to a window when unfocused and remove it when focused, but that is a bit more complicated. Just check how much logic is used for that "easy" task. Also I used built-in stuff in bash like shell parameter expansions instead of sed, loops for reading text line-by-line with regexp in if statements instead of grep etc. to make code faster, calling external binaries consumes much more time and CPU resources than built-in options.
Gamescope which allows limit FPS on unfocus exists, Wayland becomes more popular. Are you not late by any chance?
  • Well, not everyone is ready to switch to Wayland, there are a lot of reasons exists. Gamescope does not work well on my Nvidia desktop and Intel laptop, and I can bet it does not work well for others either. Also, there are a lot of old Nvidia GPUs that do not support Wayland at all because of old drivers, what makes Gamescope completely useless for owners of these GPUs.
What about Wayland support?
  • That is impossible, there is no any unified way to read window focus events and extract PIDs from windows on Wayland.
Why did you write it on Bash?
  • That is (scripting) language I know pretty good, despite a fact that Bash as all interpretators works slower than compilable languages, it still fits my needs almost perfectly.

About

A daemon for X11 designed to automatically limit CPU usage of unfocused windows and run commands on focus and unfocus events.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages