- C++ 88.6%
- CMake 9.2%
- C 2.2%
| assets | ||
| external | ||
| include | ||
| src | ||
| .clang-format | ||
| .gitignore | ||
| .gitlab-ci.yml | ||
| .gitmodules | ||
| ananicy-cpp.service | ||
| CMakeLists.txt | ||
| LICENSE | ||
| README.md | ||
Ananicy Cpp
Ananicy rewritten in C++ for much lower CPU and memory usage.
Beta status
What works
- Rule and configuration loading
- Process detection and scanning
- Renicing
- Changing CPU scheduler
- Changing IO class and IO nice
- Setting OOM score
- Change default configuration file and rules directory using environment variables (
ANANICY_CPP_{CONF,CONFDIR}) - Cgroups
- V1
- V2 (Limited support, see #21)
- Autogroup
- Systemd integration
- Unit file
- Hardening unit file
- Working sd_notify
- CLI compatibility with Ananicy
- Something else... ?
Installation
Dependencies
- CMake 3.17+
- fmtlib 8.0+ (can be automatically downloaded)
- spdlog 1.9+ (can be automatically downloaded)
- nlohmann_json 3.9+ (can be automatically downloaded)
- C++ compiler compatible with C++20 (
g++ >= 10orclang++ >= 10). Notably,<concepts>andstd::jthreadare required. Work is in progress to add support tog++ ~= 9, see https://gitlab.com/ananicy-cpp/ananicy-cpp/-/issues/28 for more info. - Optional: libsystemd (if you want systemd support)
Linux
It should be a fully drop-in replacement from Ananicy.
If you detect a difference in behavior (except for bugs in Ananicy that are fixed in ananicy-cpp),
please create an issue.
If you want pre-made community rules, you can use the rules from the original Ananicy project.
Simply copy them to your rules directory (by default, /etc/ananicy.d).
Available CMake options
CMAKE_BUILD_TYPE:STRING: EitherNone(default),Release, orDebug. The effects are mainly on the default compiler flagsananicy-cppis built with.USE_EXTERNAL_JSON:BOOL: Use system nlohmann_json library,USE_EXTERNAL_SPDLOG:BOOL: Use system spdlog library,USE_EXTERNAL_FMTLIB:BOOL: Use system fmtlib,ENABLE_SYSTEMD:BOOL: Add systemd support,STATIC:BOOL: Build a static binary,
Building
In order to actually build ananicy-cpp, open a terminal,
clone the repository (or download a release archive), and do the following commands:
- If using the
gitrepo (development version):git clone --recurse-submodules https://gitlab.com/ananicy-cpp/ananicy-cpp.gitcd ananicy-cpp
- If using release archive:
wget https://gitlab.com/ananicy-cpp/ananicy-cpp/-/archive/v1.0.0-rc5/ananicy-cpp-v1.0.0-rc5.tar.gztar -xvf ananicy-cpp-v1.0.0-rc5.tar.gzcd ananicy-cpp-v1.0.0-rc5
cmake -B build \
-DCMAKE_RELEASE_TYPE=Release \
-D[Your Option Here] -D[Another Option] \
-S .
cmake --build build --target ananicy-cpp
sudo cmake --install build --component Runtime
Service
To enable the systemd service,
enable Systemd support with -DENABLE_SYSTEMD=ON on cmake invocation, and run this command after installing ananicy-cpp:
systemctl enable --now ananicy-cpp.service
If you want to stop or disable it later, you can use:
systemctl (stop|disable) ananicy-cpp.service
You can have more information in systemd's man page (man systemd on Linux)
Distro-specific
Arch-based distros
There is an AUR package named ananicy-cpp, which is maintained by me.
You can simply use your preferred AUR-helper to install it.
There is also binaries in chaotic-aur, although ananicy-cpp is relatively fast to build.
Configuration
Global configuration
Rules
Add rules in /etc/ananicy.d. This path can be overridden with ANANICY_CPP_CONFDIR
environment variable.
Rules are defined in files ending with .rules.
For instance, to add a rule for GCC, you could do the following:
- Create the
/etc/ananicy.d/10-compilersfolder. - Create the
/etc/ananicy.d/10-compilers/gcc.rulesfile - Add
{"name": "gcc", "nice": 19, "sched": "batch", "ioclass": "idle"}to the file.
You can then (re)start ananicy-cpp.service.
Supported attributes
nice: [-20-19]: Set the nice value of the process. A process with a higher nice value will be more "polite", and will get less cpu time than processes with a lower nice value.sched: {"fifo", "rr", "normal", "batch", "idle"}: Set the scheduling policy.fifoandrr(for round-robin) are realtime scheduling policies, and must only be used for latency critical programs, likeXorgorpulseaudiofor instance. Nice values are ignored,rtprioshould be used instead.deadline: Special realtime scheduling policy which can't be set byananicy-cpp, but can be reported by it.normalis well... normal, the default behavior for the current OS. Specifying this option can be useful if you want to force the child of a realtime process to have a normal scheduling policy.batch: Very useful for compilers or other CPU-hungry, non-interactive programs, like compilers for instance. It can actually improve their performance with almost no cost on the rest of the system.idle: Very, very low priority, even lower than a nice value of19. Useful for background, low priority stuff, like file indexer for instance.
rtprio: [0, 99]: Sets the static priority of a process. Only relevant if the actual scheduling policy of a process is a realtime one, i.e.fifo,rrordeadline. A higher value means a higher priority.ioclass: {"best-effort", "realtime", "idle", "none"}: Define the IO scheduling policy. By default, it isbest-effort.
Only the CFQ I/O scheduler supportsioclassandionice, see ioprio_set.realtimeis to be used cautiously, as the process will have the absolute priority above allbest-effortprocesses, and can starve them. This could prevent you from starting a shell, for instance.ionice: [0, 7]. Lower value is higher priority.
idle: Process gets I/O resources after all other processes. This could starve the process.ioniceis completely ignored.
none: Reset I/O policy to system default,ionicemust be0.best-effort: Try to fairly share I/O resources between processes.ionice: [0, 7]. Lower value is higher priority.
oom_score_adj: [-999, 999]: Adjust the Out Of Memory killer score of a process. Negative value decrease the score of the process, making it less likely to be killed if available memory gets very low. It is recommended to use it on critical programs which must be killed last if you lack memory.cgroup: Put the process in the specified cgroup. This can be any cgroup, including those created outsideananicy-cpp.type: Set the type of the rule. All options defined in the type will be used as if written explicitly in the rule, although you can override each option if needed.
Types
To avoid repeating yourself, you can add types.
It must be defined in a .types file.
The syntax is the following:
{"type": "my_type", "nice": 19, "other_parameter": "value"}
It can then be used in any rule by simply adding the type property to the rule.
For instance, {"name": "gcc", "type": "compiler"}
Parameters can be overridden, for instance:
{"type": "compiler", "nice": 19, "sched": "batch", "ioclass": "idle"}
{"name": "gcc", "type": "compiler", "ioclass": "none", "ionice": 0}
Cgroups
They are defined in .cgroups files.
cgroup_v1 are recommended for proper functionality (see issue #21), they can be forced by
passing systemd.unified_cgroup_hierarchy=0 to your kernel cmdline (by editing /etc/default/grub for instance).
Only one attribute is supported, CPUQuota:
{"cgroup": "cpu80", "CPUQuota": 80}
One major limitations of cgroups right now is that they can only be created by the root user.
You can not use a CAP_SYS_CGROUP capability thing like for other things, because it simply does not exist yet.
If it is ever implemented in the Linux kernel, please create an issue.
Community rules
From the original project
You can use the original Ananicy's rules by copying the 00-default, 00-types.types and 00-cgroups.cgroups to you ananicy.d directory (by default, in /etc).
Why rewriting ananicy?
I mostly used Ananicy on older computers to improve interactivity. However, having Ananicy use megabytes of RAM and a decent amount of CPU time troubled me. Thus I decided to rewrite it in C++, using an event based approach. RAM usage is much lower (only a few thousands of bytes !), and CPU usage is almost always zero thanks to its event-based implementation.