On-demand and auto performance optimizer for Linux applications
ZLIB License
guapow is an on-demand and auto performance optimizer for Linux applications. This project's name is an abbreviation for Guarana powder (Guaraná is a fruit from the Amazon rainforest with a highly caffeinated seed).
Key features
yay -S guapow
pacman
and git
installed)git clone https://aur.archlinux.org/guapow.git
cd guapow
makepkg -si
pip
installedsudo apt-get install python3 python3-pip python3-aiofiles python3-aiohttp python3-pycryptodome
sudo pip3 install guapow
After installing guapow, its optimizer service must be started and enabled (the current definition requires systemd installed). The optimizer service is the component responsible to apply most of the available optimizations.
To start and enable the service, you can use the utility tool guapow-cli
or do it manually (described below). Both methods require systemctl installed.
Method 1: Starting and enabling with guapow-cli
guapow-cli install-optimizer # may require sudo for non-root users
Method 2: Starting and enabling manually
/usr/lib/systemd/system
systemctl enable --now guapow-opt.service
(may require sudo
for non-root users)To check:
ps -Ao pid,comm | grep guapow-opt
journalctl -efu guapow-opt.service
To quickly test guapow, you have to use the guapow
command to start and optimize a target application. The example below starts the vlc media player:
GUAPOW_CONFIG="cpu.performance proc.nice=-1" guapow vlc
The environment variable GUAPOW_CONFIG
should be used to define the optimizations that must be applied when the target application starts. In the example above two were defined:
cpu.performance
: changes all CPUs frequency governors to performance (for supported Intel cpus, also the energy policy level)proc.nice=-1
: defines a CPU nice level for the started application. In simple words: a negative nice level will give more CPU priority and time for the application (more on this here)The guapow
command is responsible to start a target application and requests the defined optimizations for it.
How to check if the optimizations were applied ?
ps -Ao comm,nice | grep vlc
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
cat /sys/devices/system/cpu/cpu*/power/energy_perf_bias
(values must be 0
)journalctl -efu guapow-opt.service
When you close the optimized vlc, the optimizer service should rollback the CPU governors changes (use the commands above to re-checking)
GUAPOW_CONFIG
with all the wanted optimization settings for every application, you can create a profile file.guapow-cli gen-profile default
~/.config/guapow
(or /etc/guapow
for root users)cat ~/.config/guapow/default.profile
(or cat /etc/guapow/default.profile
)guapow
, you have to define the environment variable GUAPOW_PROFILE=profile_name
(without the extension .profile). Example below:GUAPOW_PROFILE=default guapow vlc
By default, if you do not specify neither the GUAPOW_PROFILE
variable nor GUAPOW_CONFIG
, the guapow
command assumes that you are requesting optimizations based on a profile named default. In other words: the command guapow vlc
would be equivalent to GUAPOW_PROFILE=default guapow vlc
If both GUAPOW_PROFILE
and GUAPOW_CONFIG
were defined, GUAPOW_PROFILE
will be ignored.
Existing profile file priority:
~/.config/guapow/{name}.profile
> /etc/guapow/{name}.profile
/etc/guapow/{name}.profile
If a given profile file does not exist:
If you are not willing to add the guapow
command for every applicaton you want to optimize, you can the enable the watcher service.
The watcher service keeps looking for mapped applications/commands to be optimized, and request optimizations for them when they start.
Two ways of starting and enabling it:
guapow-cli install-watcher
(do not run this command with sudo, unless you are root: this service ideally should be run at the user level)~/.config/systemd/user
systemctl enable --user --now guapow-opt.service
To check:
ps -Ao pid,comm | grep guapow-watch
journalctl --user -efu guapow-watch.service
To define which applications should be watched, you have to create (or edit) the watch.map
file (located at ~/.config/guapow
or /etc/guapow
for root users). If the file does not exist, create it before proceeding.
Edit the file and add the following content: vlc
After that, start the vlc application normally and check if the optimizations defined in the default profile were applied.
To map applications to diferrent profiles, you can use the pattern: command_name=profile_name
. Example:
vlc=media
tuxracer=game
If the mapping line only contains the application name, the default profile is assumed.
The watcher service supports wild-cards and Python regex patterns for processes names or commands (more on that here)
proc.nice=level
(e.g: proc.nice=-2
).-20 to 19
). Negative values have higher prioprity.proc.nice.watch
(or proc.nice.watch=true
).
nice.check.interval
).proc.nice.delay=seconds
proc.nice.delay=1
) or float (proc.nice.delay=0.5
) higher than zero.Every time your application needs to write or read something from the disk, it competes with other applications.
The applications I/O needs are split into classes. The supported classes are described below:
best_effort
: default class. Divided in 8 levels (from 0 to 7). Lower levels have higher priority (e.g: 0 > 1).idle
: for applications that should only perform I/O operations when no other application is doing so.realtime
: first access to the disk. Divided in 8 levels (like best_effort
). Not allowed for non-root users.This optimization requires the ionice
command installed.
Property definition:
proc.io.class=class_name
(e.g: proc.io.class=best_effort
)proc.io.nice=level
: an integer within 0 and 7. 0 is the default value for classes supporting priority. (e.g: proc.io.nice=1
)The application I/O niceness is changed after the target application starts.
The application IO class and priority can be checked though the command: ionice -p pid
Applications CPU scheduling behavior are split into policies.
The supported policies are described below:
other
: default CPU time-sharing scheduling.
idle
: should be defined for applications with very low priority.
batch
: should be defined for non-interactive CPU-intensive applications.
fifo
: should be defined for very important applications. A FIFO application will lock the CPUs until it finishes to execute the demanded instructions. This policy is divided into priority groups from 1 to 99. Higher values = higher priority.
rr
(round-robin): similar to fifo
, but the applications have a limited time slice to execute with others of the same policy and priority.
The policies fifo and rr are designed for realtime applications and have higher priorities than the others. Applications associated with these policies can interrupt other running processes in order to execute. They should be used with care, since they can lock the entire system.
Properties definitions:
proc.policy=policy_name
(e.g proc.policy=rr
)proc.policy.priority=value
: value must be an integer between 1 and 99 (only supported by fifo and rr)The application CPU scheduling is changed after the target application starts.
CPU affinity means the instructions requested by a given application will be executed by determined CPU cores.
Some applications performance can be improved when tied to less CPU cores, while keeping the other cores free for other tasks (like graphics rendering).
Property definition: proc.affinity=cpu
or proc.affinity=cpu0,cpu1
Example 1 (affinity for CPUs 0 and 1):
proc.affinity=0
proc.affinity=1
Example 2 (affinity for CPUs 2 and 3):
proc.affinity=2,3
The application CPU affinity is changed after the target application starts.
The application CPU affinity can be checked though the command: taskset -pc pid
cpu.performance
(equivalents: cpu.performance=true
or cpu.performance=1
)cpu.performance
. So if application A and B require cpu.performance
and A finishes after a while, the performance governor will be kept until B finishes.cpu.performance
(equivalents: cpu.performance=true
or cpu.performance=1
)0
) until the optimized application finishes. It handles the state if two or more optimized applications require cpu.performance
. So if application A and B require cpu.performance
and A finishes after a while, the performance level will be kept until B finishes.gpu.performance
(equivalents: gpu.performance=true
or gpu.performance=1
)gpu.performance
. So if application A and B require gpu.performance
and A finishes after a while, the performance state will be kept until B finishes.compositor.off
(equivalents: compositor.off=true
or compositor.off=1
)compositor.off
. So if application A and B require compositor.off
and A finishes after a while, the disabled state will be kept until B finishes.inxi
installed) on the first request defining compositor.off
. So the first request will take more time, then the subsequent ones. To prevent that, the installed compositor can be predefined on the optimizer service settings.Some applications can impact the performance of others while running at the same time.
guapow allows to stop target applications while the optimized one is running. The applications can be stopped at two possible moments:
Property definition:
stop.{moment}=name_1,name_2,...
Example:
stop.before=a
stop.before=b
stop.before=c,d # multiple can be defined on the same line using commas
stop.after=f,g
In the example above:
The optimizer service will not restart the stopped applications when the optimized application finishes, unless the property stop.{moment}.relaunch
(or stop.{moment}.relaunch=true
) is defined. Example:
stop.before=a,b
stop.before.relaunch # 'a' and 'b' will be restarted when the optimized application finishes
stop.before
is only available for applications started through the runner.
guapow can execute custom commands and scripts in three possible moments:
Property definition: scripts.{moment}=command_or_script_path_1,command_or_script_path_2,...
Examples:
scripts.before=vlc,firefox # vlc and firefox commands
scripts.before=/home/user/my_script.sh # my_script.sh path
scripts.after=/usr/bin/app # app full binary path
scripts.finish=poweroff # poweroff command
In the example above:
vlc
and firefox
, and the script /home/user/my_script.sh will be executed before the application to be optimized starts/usr/bin/app
will be executed right after the application to be optimized startspoweroff
will be executed when the optimized application finishesYou can work with the two additional properties below if the commands/scripts should only be executed when the previous finishes:
scripts.{moment}.wait
: will wait a script to finish before starting the next. Example: scripts.before=my_script.sh
scripts.before=my_script_2.sh
scripts.before.wait # 'my_script_2.sh' will only be executed when 'my_script.sh' finishes.
scripts.{moment}.timeout
: will wait the script to finish for a limited time (in seconds), otherwise the next one in the chain will be executed. Example: scripts.after=vlc
scripts.after=firefox
scripts.after.timeout=5.5 # 'vlc' execution will be waited for `5.5`seconds. If it does not finish, 'firefox' will be started.
Executing scripts at the root level:
scripts.allow_root
(or scripts.allow_root=true
) to the optimizer service settings.scripts.{moment}.root
(or scripts.{moment}.root=true
) to the configuration or profile file. Example: scripts.after=/path/to/my_script.sh
scripts.after=/path/to/my_script_2.sh
scripts.after.root # with this property defined, both scripts above will be executed as root
scripts.before
does not suport root execution (unless the user calling the guapow
command is root)mouse.hidden
(equivalents: mouse.hidden=true
or mouse.hidden=1
)mouse.hidden
. So if application A and B require mouse.hidden
and A finishes after a while, the pointer will be kept hidden until B finishes.proc.env=MY_VAR:MY_VAR_VALUE
# the variable name and value are separated with the symbol :
proc.env=VAR_TO_REMOVE
# when no separator (:
) is declared, the variable is removedproc.env=COLOR:red (adds the environment variable named 'COLOR' with 'red' as value)
proc.env=THEME:dark (adds another environment variable)
proc.env=LD_PRELOAD # (removes the environment variable named 'LD_PRELOAD')
If the actual application to be optimized is a child of the target process, how can I tell guapow to optimize it instead ?
guapow understand this sort of application as a launcher. It is possible to provide a mapping telling that when application A starts optimizes B instead.
Two possible ways:
launcher=exe_name:name_or_command
. Several launchers can be defined. Example: launcher=abc:abc-full # this would map the executable 'abc' to an application named 'abc-full'. So 'abc-full' would be optimized instead of 'abc'
launcher=def:def-bin # this would map the executable 'def' to an application named 'def-bin'. So 'def-bin' would be optimized instead of 'def'
launchers
file located in ~/.config/guapow
(for non-root users) or /etc/guapow
(for global or root usage) following the pattern exe_name=name_or_command
. The advantage of this approach is that you don't have to provide a per-profile/configuration mapping. But at the same time, tons of mappings may impact the matching process time. Example:abc=abc-full
def=def-bin
fgh=/fgh-java.sh
Wild-cards: the asterisk symbol *
can be used when you want to match anything inside a word. Example:
vlc=vlc-* # the first started application whose name starts with 'vlc-' would be optimized instead of 'vlc'
abc=def # as 'def' does not starts with a forward-slash, guapow will look for an application named 'def'
fgh=n%/xpto # as the prefix 'n%' was provided, guapow will look for an application named '/xpto'
abc=/abc-full # as 'abc-full' starts with a forward-slash, guapow will look for an application launched with the command '/abc-full'
def=c%xpto # as the prefix 'c%' was provided, guapow will look for an application launched with the command 'xpto'
launcher.skip_mapping
(or launcher.skip_mapping=true
)steam
(or steam=true
) to your configuration or profile file.The runner is responsible for launching a target application and request optimizations for it.
To launch a target application you have to use the command guapow
. There are 3 possible ways to inform the wanted optimizations:
GUAPOW_CONFIG
environment variable: you can provide all the optimization properties with this variable separated by commas.GUAPOW_CONFIG="cpu.performance proc.nice=-1" guapow abc # starts 'abc' and request some optimizations for it
/.config/guapow/{name}.profile
or /etc/guapow/{name}.profile
) and the environment variable GUAPOW_PROFILE. The variable value must consist of the profile file name without the extension. GUAPOW_PROFILE=media guapow abc # starts 'abc' and requests the optimizations defined in the profile file '~/.config/guapow/media.profile`
c) If you launch a command without defining the environment variables described above, guapow considers that you are requesting optimizations based on a profile file called default. In other words: guapow command
is equivalent to GUAPOW_PROFILE=default guapow command
It is possible to define extra optimization properties on-demand for a given profile through the environment variable GUAPOW_PROFILE_ADD
(follows the same pattern as the environment variable GUAPOW_CONFIG
).
GUAPOW_PROFILE=media GUAPOW_PROFILE_ADD="compositor.off" guapow abc # requests optimizations declared in the 'media' profile + 'compositor.off'
To use the runner for launching Steam games, you can change the game Launch options and add something like: GUAPOW_PROFILE=steam guapow %command%
(or GUAPOW_CONFIG="properties" guapow %command%
). Make sure to add the steam property to your configuration/profile for better optimization handling.
Logs:
GUAPOW_LOG=1
(1 enables / 0 disables)GUAPOW_LOG_FILE=1
(log directory: ~/.local/share/guapow/log
)The optimizer service is responsible to apply most of the optimizations and tweaks to a target application and/or the system.
Ideally, it should be run at the root level, otherwise some optimizations will not be possible.
It applies the optimizations changes only once per optimization request. So, if it changes the CPUs governors to performance, and you manually change them later to something else, it will not set the governors to performance again (unless another optimization request arrives).
By default, it runs at port 5087 and demands encrypted requests for security reasons (all done automatically).
~/.config/guapow/opt.conf
(user) or /etc/guapow/opt.conf
(system). Preference: user > system (if running as root, system is the only option)
port = 5087 (TCP port)
compositor = (pre-defines the installed compositor. Options: kwin, compiz, marco, picom, compton, nvidia)
scripts.allow_root = false (allow custom scripts/commands to run at the root level)
check.finished.interval = 3 (finished applications checking interval in seconds. Min accepted value: 0.5)
launcher.mapping.timeout = 60 (maximum time in seconds to look for a process mapped to a different process. This property also affects the period to look for Steam subprocesses. float values are allowed)
launcher.mapping.found_timeout = 10 (maximum time in seconds to still keep looking for a process mapped to a different process after a match. This property also affects the period to look for Steam subprocesses. float values are allowed)
gpu.cache = false (if 'true': maps all available GPUs once after the first request (if running as a system service) or during startup (if not running as system service). Otherwise, GPUs will be mapped for every request)
gpu.id = # comma separated list of integers representing which GPU cards should be optimized (e.g: 0, 1). If not defined, all available GPUs are considered (default)
gpu.vendor = # pre-defines your GPU vendor for faster GPUs mapping. Supported: nvidia, amd
cpu.performance = false (set cpu governors and energy policy levels to full performance on startup)
request.allowed_users = (restricts users that can request optimizations, separated by comma. e.g: root,xpto)
request.encrypted = true (only accepts encrypted requests for security reasons)
profile.cache = false (cache profile files on demand to skip I/O operations. Changes to profile files require restarting)
profile.pre_caching = false (loads all existing profile files on disk in memory during the intialization process. Requires 'profile.cache' enabled)
nice.check.interval = 5 (processes nice levels monitoring interval in seconds)
optimize_children.timeout: maximum period in seconds to keep looking for the target process children (default: 30). 0 can be defined if children should be ignored.
optimize_children.found_timeout: maximum period in seconds to still keep looking for the target process children after a child in found (default: 10). 0 can be defined if the search process should be interrupted immediately after a child is found.
Its installation can be managed using the guapow-cli tool:
guapow-cli install-optimizer
: copies the service definition file to the appropriate directory, starts and enables it.guapow-cli uninstall-optimizer
: revert changes from the command below.For manual installation, check here.
Logs:
GUAPOW_OPT_LOG
: enables/disables logs. Options: 1 (enables, default) and 0 (disables).GUAPOW_OPT_LOG_LEVEL
: controls the type of logging. Options: info
, debug
, error
and warning
(debug
is the most detailed type). Default: info
./usr/lib/systemd/system/guapow-opt.service
)journalctl -efu guapow-opt.service
The watcher is an optional service that can automatically requests optimizations. It keeps looking for new started applications matching its mapping settings.
It should ideally run at the user level, as it should act as the user.
Its installation can be managed using the guapow-cli tool:
guapow-cli install-watcher
: copies the service definition file to the appropriate directory, starts and enables it.guapow-cli uninstall-watcher
: revert changes from the command below.For manual installation, check here.
Application mappings are defined on the file ~/.config/guapow/watch.map
(user) or /etc/guapow/watch.map
(system). Preference: user > system (if running as root, system is the only option).
Mappings patterns: name_or_command=profile_file_name
abc=media # maps an application named 'abc' to the 'media' profile (~/.config/guapow/media.profile)
/bin/def=power # maps an application started with the command '/bin/def' to the 'power' profile (~/.config/guapow/power.profile)
*
can be used in the name/command as a replacement for anything. Example:
a*bc=media # maps a process named 'a[anything]bc' to the 'media' profile
/bin/*=power # map any process started with the command '/bin/{anything}' to the 'power' profile
r:
r:/bin/.+/xpto=media # all applications started with commands following the pattern '/bin/[anything]/xpto' will be mapped to the 'media' profile
r:abc.+=power # all applications named 'abc[anything]' will be mapped to the 'power' profile
__word__
that are evaulated as a regex.
__steam__
: defines a regex for any game launched through Steam (native and Proton). Example here.Ignoring processes: it is possible to define patterns to ignore specific processes through the file ~/.config/guapow/watch.ignore
(user) (or /etc/guapow/watch.ignore
(system)). Preference: user > system (if running as root, system is the only option).
watch.map
, but you don't need to provide the profile names (as it makes no sense). e.g:
my_app_name
my_app_name*
/bin/my_proc
r:/bin/.+/xpto
watch.map
(e.g: /usr/bin/*
), but want to ignore specific onesSettings
~/.config/guapow/watch.conf
(user) or /etc/guapow/watch.conf
(system). Preference: user > system (if running as root, system is the only option).
interval = 1 (in seconds to check for new-born applications and request optimizations)
regex.cache = true (caches pre-compiled regex mapping patterns in memory)
mapping.cache = false (if 'true', caches the all mapping in memory to skip I/O calls. Changes to watch.map won't have effect until the service is restarted.
ignored.cache = false (if 'true', caches the all ignored patterns in memory to skip I/O calls. Changes to watch.ignore won't have effect until the service is restarted.
Logs:
GUAPOW_WATCH_LOG
: enables/disables logs. Options: 1 (enables, default), 0 (disables).GUAPOW_WATCH_LOG_LEVEL
: controls the type of logging that should be printed. Options: info
, debug
, error
and warning
(debug
is the most detailed type). Default: info
.~.config/systemd/user/guapow-watch.service
)journalctl --user -efu guapow-watch.service
guapow-cli --help
[install-uninstall]-optimizer
: install/uninstalls the optimizer service (requires root).[install-uninstall]-watcher
: install/uninstalls the watcher service.gen-profile name
: generates a pre-defined profile. Check the available profiles through the --help
parameter.The optimizations timing can be improved by tweaking some of guapow components settings:
request.encrypted=false
. This can save time, since the request encryption/decryption process is heavy.profile.cache=true
and profile.pre_caching=true
. This can save time, since all the defined profiles files are pre-loaded in memory during the service initialization and will not be read for every request.gpu.vendor=vendor_name
.gpu.cache=true
to skip the GPUs mapping for every request. This property is not enabled by default, since hybrid-gpu users might load their dGPU drivers on demand.compositor={name}
property.mapping.cache=true
to skip the reading calls for every checking iteration.Requires the watcher service installed and enabled (more on that here)
Add the following entry to the watcher mapping file (~/.config/guapow/watch.map
or /etc/guapow/watch.map
):
__steam__=steam
Now use the guapow-cli to generate a Steam profile template by typing:
guapow-cli gen-profile steam
Start a Steam game and check if the optimizations were applied.