Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
5eef904
fix: dosr no longer loses a backchannel message that arrives in parts
LeChatP Oct 23, 2026
324c50f
tests: a stdio terminal that is not dosr's own is not taken as the us…
LeChatP Oct 23, 2026
70c8209
fix: a stopped command suspends dosr like a shell job instead of bein…
LeChatP Oct 23, 2026
ae0b705
fix: two dosr of one pipeline no longer read their passwords from the…
LeChatP Oct 23, 2026
14bb6d7
fix: dosr stops a command like sudo, giving it time to clean up befor…
LeChatP Oct 23, 2026
3d4d19d
chore: bump to 4.2.0
LeChatP Oct 23, 2026
3460db4
fix: a duration of the policy is refused when a field has a sign or m…
LeChatP Oct 23, 2026
b1092a1
feat: dosr asks for the password up to 3 times, waiting 5 seconds aft…
LeChatP Oct 23, 2026
4fa0dac
fix: dosr refuses to go on when a PAM module changed the user
LeChatP Oct 23, 2026
8600b27
feat: the variables that PAM modules set reach the command, through t…
LeChatP Oct 23, 2026
f31f6bd
tests: end-to-end checks of the PAM environment and of the password r…
LeChatP Oct 23, 2026
82c3191
fix: a PPID timestamp cookie is bound to the session of dosr too
LeChatP Oct 23, 2026
6826331
fix: dosr and chsr no longer panic when their output is a closed pipe
LeChatP Oct 23, 2026
10d703e
fix: the PATH of a command never names its working directory
LeChatP Oct 23, 2026
841605c
fix: chsr creates policy files readable and writable by their owner only
LeChatP Oct 23, 2026
afb9905
fix: dosr says why it lacks its capabilities instead of a bare Permis…
LeChatP Oct 23, 2026
9816099
fix: chsr prints its usage without the policy and no longer panics on…
LeChatP Oct 23, 2026
2224114
chore: remove the upstream packaging leftovers
LeChatP Oct 23, 2026
105be6a
tests: remove a redundant clone that clippy --workspace refuses
LeChatP Oct 23, 2026
3091822
fix: chsr creates its temporary folder in /tmp, whatever TMPDIR says
LeChatP Oct 23, 2026
09d0ea1
fix: a failed lookup of an actor disables the roles with a separation…
LeChatP Oct 23, 2026
84e06b3
tests: end-to-end check of a failed group lookup under SSD
LeChatP Oct 23, 2026
b343c8c
fix: chsr refuses a duration too long instead of writing a wrong one …
LeChatP Oct 23, 2026
52b215b
feat: chsr edits the password option at each level
LeChatP Oct 23, 2026
5b4d5ed
fix: chsr writes only what a command sets in the options of a role or…
LeChatP Oct 23, 2026
72a7a78
fix: chsr options timeout set and unset keep the fields they do not name
LeChatP Oct 23, 2026
34a299d
fix: chsr accepts the variable names and patterns of the policy, and …
LeChatP Oct 23, 2026
a5c6c09
fix: chsr shows the option asked for at every level, and turns its pa…
LeChatP Oct 23, 2026
08ce3d7
fix: a timeout without a duration is read, instead of making the whol…
LeChatP Oct 23, 2026
512c189
fix: chsr keeps the unknown fields of path, workdir, setuid and stora…
LeChatP Oct 23, 2026
ead473d
fix: chsr purges a path or workdir list back to inheritance, and keep…
LeChatP Oct 23, 2026
50cb99a
fix: chsr saves the groups and the user given to cred set, and refuse…
LeChatP Oct 23, 2026
00db348
fix: chsr edits one file of a policy directory, and writes only the f…
LeChatP Oct 23, 2026
eeed93c
tests: end-to-end check of chsr on the policy directory of the instal…
LeChatP Oct 23, 2026
466fa4d
fix: chsr reads the setuid set like dosr, refusing the fields it does…
LeChatP Oct 23, 2026
69ceb2b
fix: cargo xtask install deploys the PAM service of dosr instead of a…
LeChatP Oct 23, 2026
63a351d
tests: the Vagrant provisioning builds and installs RootAsRole again
LeChatP Oct 23, 2026
9576a0a
fix: cargo xtask install installs a copy of root, not the build artif…
LeChatP Oct 23, 2026
79334f4
fix: dosr -r no longer lifts the separation of duties
LeChatP Oct 23, 2026
bb231cc
feat: chsr edits the separation of duties, the parents, the purpose, …
LeChatP Oct 23, 2026
3c6111c
fix: cargo xtask install writes in the root file whether the policy i…
LeChatP Oct 23, 2026
fdbbbe0
tests: the SSD check of e2e.sh no longer hides the check of a planted…
LeChatP Oct 23, 2026
dd1f1c7
fix: cargo xtask --dry-run changes nothing, and uninstall needs --apply
LeChatP Oct 24, 2026
4c6e766
fix: a dry run of the dependencies does not say that they were installed
LeChatP Oct 24, 2026
9f7555b
feat: xtask checks the packages to build and to run RootAsRole, it no…
LeChatP Oct 24, 2026
e132e04
chore: prefer clang over gcc
LeChatP Oct 25, 2026
4db9aee
fix: chsr keeps a regular expression on the arguments as typed, so th…
LeChatP Oct 25, 2026
8bb8374
fix: dosr -i shows None for a task without capabilities
LeChatP Oct 25, 2026
ba91615
fix: dosr -- ends the options of dosr, like sudo
LeChatP Oct 25, 2026
e44bdf3
fix: dosr logs under the name dosr instead of sr
LeChatP Oct 25, 2026
4267132
fix: the help of dosr and chsr lists what they accept
LeChatP Oct 25, 2026
e6b83c6
fix: chsr editor edits the file of the policy that the other commands…
LeChatP Oct 25, 2026
9762f7e
fix: chsr is confined by Landlock even when an editor or one of its f…
LeChatP Oct 25, 2026
81d8663
fix: chsr file says why a file of the policy directory cannot be loaded
LeChatP Oct 25, 2026
e5df878
fix: chsr prints the error of a failed command on its standard error
LeChatP Oct 25, 2026
7341273
tests: end-to-end checks of the fixes found while writing the dosr an…
LeChatP Oct 25, 2026
565f54c
feat: xtask builds with clang or gcc, and without pandoc
LeChatP Oct 25, 2026
d0d28a0
fix: a task that changes the user gives the command the groups of the…
LeChatP Oct 25, 2026
85d6078
feat: chsr cred set --setgid-from caller|target
LeChatP Oct 25, 2026
2669ef3
tests: end-to-end checks of the groups of a task that changes the user
LeChatP Oct 25, 2026
68ea667
fix: a task whose user or groups do not exist is left out instead of …
LeChatP Oct 25, 2026
b2cf239
tests: end-to-end check of a task whose group does not exist
LeChatP Oct 25, 2026
bfb4c05
fix: a regular expression on the arguments applies to the whole argum…
LeChatP Oct 25, 2026
bde245d
tests: end-to-end check of a top-level alternation on the arguments
LeChatP Oct 25, 2026
27c1d5c
tests: the final policy of the book is read by rootasrole-core and de…
LeChatP Oct 25, 2026
dd9ac92
fix: the PAM services that cargo xtask install deploys end with a new…
LeChatP Oct 25, 2026
4e2ce86
tests: the Arch machine of tests/vagrant uses the generic/arch box
LeChatP Oct 25, 2026
0c67f5e
feat: the tty option says who owns the terminal of the command, the c…
LeChatP Oct 25, 2026
c7f4e79
feat: chsr edits the tty option at each level
LeChatP Oct 25, 2026
d35f82c
tests: end-to-end checks of the owner of the terminal of a command ru…
LeChatP Oct 25, 2026
3b8624a
feat: the default owner of the terminal is the build variable RAR_TTY…
LeChatP Oct 25, 2026
5e4eb6a
docs: rewriting the file configuration completely.
LeChatP Oct 19, 2026
b8c3c45
docs: update usage
LeChatP Oct 19, 2026
54af4ba
docs: reorganisation
LeChatP Oct 19, 2026
9748f36
docs: update .gitignore to ignore hidden folders except two
LeChatP Oct 23, 2026
acb8ab3
docs: 4.2.0 news
LeChatP Oct 25, 2026
6859639
Merge branch 'main' into dev
LeChatP Oct 25, 2026
00604ca
tests: the read-logs task of the book is expected only where its grou…
LeChatP Oct 25, 2026
30cd12d
fix: dosr --help lists -S and -K once
LeChatP Oct 25, 2026
bb450d0
tests: performance indicators of the finder, ignored by default
LeChatP Oct 26, 2026
7c16d6b
perf: a path of the policy without pattern characters is not compiled…
LeChatP Oct 26, 2026
d488939
perf: the finder looks up each user and group name once
LeChatP Oct 26, 2026
f473694
fix: a task that skips the authentication gives no timestamp cookie
LeChatP Oct 26, 2026
7973e2a
perf: dosr keeps the groups of the caller as ids
LeChatP Oct 26, 2026
5fd8958
perf: the finder compares the commands of a task first, and resolves …
LeChatP Oct 26, 2026
3a92935
perf: a command of the policy that is only a path is not split
LeChatP Oct 26, 2026
573f9d5
perf: a decision searches a command in each PATH once
LeChatP Oct 26, 2026
675369d
perf: a pattern whose literal start differs from the command is not c…
LeChatP Oct 26, 2026
742b7f3
docs: update performance evaluation details
LeChatP Oct 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ RAR_CHSR_EDITOR_PATH = "/usr/bin/vim"
RAR_TIMEOUT_TYPE = "ppid"
RAR_TIMEOUT_DURATION = "00:05:00"
RAR_TIMEOUT_MAX_USAGE = ""
RAR_PASSWORD_TRIES = "3"
RAR_PASSWORD_DELAY = "00:00:05"
# Who owns the terminal of a command run as another user: caller, or target like sudo.
RAR_TTY_OWNER = "caller"
RAR_PATH_DEFAULT = "delete"
RAR_PATH_ADD_LIST = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
RAR_PATH_REMOVE_LIST = ""
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ jobs:
session [success=1 default=ignore] pam_permit.so
session requisite pam_permit.so
session required pam_permit.so" | tee /etc/pam.d/dosr'
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y clang pkg-config libpam0g-dev libseccomp-dev pandoc
- name: Install RootAsRole
run: cargo xtask install -bip sudo
run: cargo xtask install -bp sudo
- name: print config
run: dosr cat /etc/security/rootasrole.json
- name: getenv
Expand Down
13 changes: 6 additions & 7 deletions .github/workflows/install-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Install git and build dependencies
run: |
apt update -y
apt install -y git curl build-essential pkg-config libpam0g-dev
apt install -y git curl build-essential clang pkg-config libpam0g-dev libseccomp-dev pandoc
apt install -y sudo ca-certificates

- name: Checkout code
Expand All @@ -47,7 +47,7 @@ jobs:

- name: Install RootAsRole
run: |
cargo xtask install --debug -bip sudo
cargo xtask install --debug -bp sudo

- name: Verify installation
run: |
Expand All @@ -71,8 +71,7 @@ jobs:
dnf config-manager --set-enabled crb || true
dnf install -y epel-release || true
dnf makecache -y
dnf install -y pandoc || true
dnf install -y git gcc pkg-config pam-devel
dnf install -y git clang pkg-config pam-devel libseccomp-devel pandoc
dnf install -y sudo ca-certificates

- name: Checkout code
Expand All @@ -99,7 +98,7 @@ jobs:

- name: Install RootAsRole
run: |
cargo xtask install -bip sudo
cargo xtask install -bp sudo

- name: Verify installation
run: |
Expand All @@ -126,7 +125,7 @@ jobs:
- name: Install git and build dependencies
run: |
zypper refresh
zypper install -y bash rustup git curl gcc pkg-config pam-devel
zypper install -y bash rustup git curl clang pkg-config pam-devel libseccomp-devel pandoc
zypper install -y sudo
rustup toolchain install stable
rustup update
Expand All @@ -152,7 +151,7 @@ jobs:

- name: Install RootAsRole
run: |
cargo xtask install -bip sudo
cargo xtask install -bp sudo

- name: Verify installation
run: |
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ jobs:
components: clippy
override: false

- name: Install RootAsRole
run: cargo xtask dependencies -dip sudo
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y pkg-config libpam0g-dev libseccomp-dev pandoc

# if pull request review only
- uses: mbrobbel/rustfmt-check@master
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
session required pam_permit.so" | tee /etc/pam.d/dosr'

- name: Install Dependencies
run: cargo xtask dependencies -dip sudo
run: apt install -y pkg-config libpam0g-dev libseccomp-dev pandoc

- name: run integration coverage
run: cargo +nightly coverage
Expand Down
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ obj/
bin/

# Hidden folders (for Linux IDE)
/.idea/
*target/
*/src/xml_version.rs
/.*/
!/.cargo/
!/.github/

# Rust crates
*/Cargo.lock
Expand Down
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ exclude = ["fuzz", "book", "sudoers-reader"]
[workspace.package]
edition = "2024"
rust-version = "1.93.0"
version = "4.1.0"
version = "4.2.0"
license = "LGPL-3.0-or-later"
homepage = "https://lechatp.github.io/RootAsRole/"
repository = "https://github.com/LeChatP/RootAsRole"
Expand Down Expand Up @@ -97,8 +97,8 @@ undocumented_unsafe_blocks = { level = "warn", priority = 2 }
allow-unwrap-in-tests = true

[workspace.dependencies]
rootasrole-core = { version = "4.1.0", path = "core" }
rootasrole-exec = { version = "4.1.0", path = "exec" }
rootasrole-core = { version = "4.2.0", path = "core" }
rootasrole-exec = { version = "4.2.0", path = "exec" }

[dependencies]
rootasrole-core = { workspace = true }
Expand Down
75 changes: 65 additions & 10 deletions book/src/background/performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,34 @@ Infrastructure-as-code environments can generate large and complex privilege pol

With RaR policies, every role and task can introduce additional access control rules. In large infrastructures, this can result in thousands of policy entries being evaluated during production operations. Therefore, the privilege evaluation engine must scale efficiently.

The initial implementation of dosr revealed a scalability challenge. The first JSON-based policy engine was faster than sudo for small policies, but its execution time increased significantly as the number of tasks grew.
> Update for 4.2.0 of the performance evaluation is co-written with Claude for correctness.

![Performance degradation of the initial JSON-based dosr implementation as policy size increases from 1 to 100 tasks.](https://github.com/LeChatP/RaR-perf/raw/main/before_json_result.png)
## How it is measured

The measures are performed with the dedicated [RaR-perf](https://github.com/LeChatP/RaR-perf) repository. Each tool runs `/usr/bin/true` as root, without a password, with a policy of N rules where only the last rule allows the command. [hyperfine](https://github.com/sharkdp/hyperfine) measures the time of each run. Since a remark from reddit, 4.2.0 evaluations verifies the `/usr/bin/true` performance too for completeness.

The tools do not do the same work for the same rule: sudo and dosr (since 4.0) run the PAM account and session stacks, even when they ask no password, while doas and `please` do not call PAM when they ask no password. A comparison shows how much each design costs.

After some thoughts, run0 is not in the figures. Its rules aren't read at each run: polkitd loads them once, and keep it loaded in memory, while the other tools read their policy each time. Its numbers would not measure the same work. That said, the time to make a dbus call is significantly slower than reading a policy of 10000 tasks.
Another point is : polkit's run0 rules has no idea about what command is being executed as input. So that makes the comparison not even feasible.

## The first implementation

The initial implementation of the policy engine revealed a scalability challenge. It was measured in April 2025, while 3.1.0 was in development, when dosr was still named `sr`. The first JSON-based policy engine was faster than sudo for small policies, but its execution time increased significantly as the number of tasks grew.

![Performance degradation of the initial JSON-based policy engine (sr, 3.1.0 in development) as policy size increases from 1 to 90 tasks.](https://github.com/LeChatP/RaR-perf/raw/main/figures/25-04-16_sudo-sr-json/result.png)

As shown above, the initial implementation suffered from poor scalability. While it performed well with small policies, the execution time quickly surpassed sudo as policy size increased, making it unsuitable for large-scale deployments.

## Moving from JSON to CBOR
### Moving from JSON to CBOR

The first optimization focused on the policy storage format. JSON is human-readable and convenient, but parsing large JSON documents introduces unnecessary overhead. To reduce this cost, dosr introduced support for Compact Binary Object Representation (CBOR), a binary format designed for efficient serialization and parsing, and completely compatible with the JSON structure.

![Limited performance gain after switching to CBOR, showing the underlying scalability issue persists as policy size increases to 400 tasks.](https://github.com/LeChatP/RaR-perf/raw/main/before_cbor_result.png)
![Limited performance gain after switching to CBOR, showing the underlying scalability issue persists as policy size increases to 400 tasks (time in seconds).](https://github.com/LeChatP/RaR-perf/raw/main/figures/25-04-16_sudo-sr-cbor/result.png)

Although CBOR reduced part of the parsing overhead, the improvement remained limited. The performance curve continued to increase significantly with policy size, demonstrating that file parsing was only one part of the problem. The main bottleneck was located deeper in the policy evaluation architecture.

## Architectural Optimisation
### Architectural Optimisation

The next optimization phase focused on the complete execution path of dosr. Instead of only improving the policy format, the internal architecture was redesigned to remove unnecessary overhead.

Expand All @@ -31,21 +44,64 @@ The main improvements included:

These changes, combined with the CBOR policy format, resulted in a significant improvement in both execution time and scalability.

![Final scalability comparison showing the fully optimized dosr (with CBOR and architectural improvements) vastly outperforming sudo at scale, benchmarked up to 10,000 tasks.](https://github.com/LeChatP/RaR-perf/raw/main/result_25-07-04_15.44.png)
![Scalability of the optimized engine (sr, 3.1.0 in development, with CBOR and architectural improvements) and of sudo, benchmarked up to 10,000 tasks in July 2025.](https://github.com/LeChatP/RaR-perf/raw/main/figures/25-07-04_sudo-sr/result.png)

The optimized dosr engine now outperforms sudo by up to 77% for a single-rule policy. More importantly, its execution time scales linearly and grows approximately 40% slower than sudo, maintaining a performance advantage even with policies containing tens of thousands of tasks.
In July 2025, just before the release of 3.1.0, this engine ran 77% faster than sudo for a single-rule policy, and its execution time grew approximately 40% slower than sudo's as the policy grew.

<blockquote class="caroot">
Do you see these very straight lines compared to the previous ones? This is because we changed the way to way to plot the data. Instead of using a some arbitrary increase (e.g., 100, 200, 300), we used a logarithmic increase.
</blockquote>

## From 3.1.0 to 4.1.0

These numbers were not measured again for the releases that followed. In October 2026, every version was built again and measured on the same virtual machine, with the same policy:

| version | one rule | each additional rule |
|---|---|---|
| 3.1.0 | 5.4 ms | 1.9 µs |
| 4.0.0 | 13.9 ms | 2.5 µs |
| 4.0.2 | 14.4 ms | 2.5 µs |
| 4.1.0 | 11.7 ms | 13.4 µs |
| 4.2.0 | 9.4 ms | 2.3 µs |

![The versions of RootAsRole from 3.1.0 to 4.2.0 (rar-dev), measured in October 2026 with the same policy, from 1 to 10,000 tasks.](https://github.com/LeChatP/RaR-perf/raw/main/figures/26-10-27_versions/result.png)

In this figure, `rar-dev` is 4.2.0, just before its release.

**The time of a single rule grew with PAM.** Since 4.0.0, dosr runs the whole PAM transaction even for a task that skips the authentication: it starts PAM, checks the account, sets the credentials, then opens and closes a session. 3.1.0 did not call PAM at all for such a task. The account check is what refuses an account that has expired, or that may not log in at this hour; sudo runs it too for a `NOPASSWD` rule. This cost is therefore kept, as a security choice. Measured commit by commit, it added about 5 ms to a run. Part of it comes from `pam_unix`, which starts its `unix_chkpwd` helper to read the account, because dosr runs as the user with file capabilities instead of being setuid root. The rest of the difference, about 1.5 ms during 3.2 and 1 ms at the end of 4.0, was not traced to a single commit.

**The cost of each rule grew with patterns.** In 4.1.0, the command paths of the policy that contain wildcards were fixed: they never matched before (commit `1c3084f`). The fix matches them with globset patterns. But it compiled every command path of the policy as a pattern, even a path without any wildcard, which costs about 10 µs for each command of each task. In the same release, other changes made a run with a single rule about 2.7 ms faster.

## RootAsRole 4.2.0

4.2.0 now implement performance indicators unit tests, ignored by default, that print the cost of one task, so that a change can be measured before and after it:

```sh
cargo test --release --all-features --lib -- --ignored --nocapture --test-threads=1 finder::tests::perf
```

With 4.2.0, a run with one rule takes 9.4 ms, and each additional rule costs 2.3 µs. More than half of a run is the PAM transaction, which a timing probe measured at about 5.6 ms.

The other tools, measured the same way on the same machine:

![dosr 4.2.0, sudo, doas and please, from 1 to 10,000 rules, measured in October 2026.](https://github.com/LeChatP/RaR-perf/raw/main/figures/26-10-27_tools/result.png)

| tool | one rule | 10,000 rules | each additional rule |
|---|---|---|---|
| dosr 4.2.0 | 9.4 ms | 30.1 ms | 2.1 µs |
| sudo 1.9.17 | 10.5 ms | 41.1 ms | 3.0 µs |
| doas 6.4 | 2.0 ms | 186 ms | 18.4 µs |
| please 0.5.6 | 5.3 ms | 1,675 ms | 167 µs |

`/usr/bin/true` alone takes 0.7 ms. With one rule, most of the time of dosr and sudo is the PAM transaction, which doas and please programs do not run when they ask no password. As the policy grows, the cost of each rule depends on how the tool reads and compares its rules. The policy of this figure is written by confgen, and the one of the versions by genpol, which is why the numbers of dosr differ slightly between the two.

## Large-Scale Automation

This scalability improvement is particularly important in automation environments.

Tools such as Ansible frequently invoke privilege escalation through `become: true` configuration option. With RaR, every role and task can introduce additional access control rules, potentially resulting in thousands of policy entries on a single system.

The benchmark results show that this additional security granularity does not introduce a proportional performance cost. The optimized dosr engine can reach the execution time of a single sudo rule while evaluating approximately 4,000 RaR rules.
The benchmark results show that this additional security granularity does not introduce a proportional performance cost. With 4.2.0, a policy of 10,000 tasks adds about 21 ms to a run.

This enables administrators to define significantly more precise privilege policies while maintaining operational efficiency.

Expand All @@ -57,5 +113,4 @@ For comparison, **sudo-rs** provides performance comparable to sudo in standard

One potential direction is the integration of a SQLite-based policy backend. The RBAC model of RaR map to relational data structures. A relational database could provide additional advantages as we could do efficient indexing as an example.

The benchmarks presented above were performed in July 2025. Since then, additional performance optimisations have been implemented across the codebase, improving internal execution paths and reducing overhead further.
@@billo2025
The figures of the first engine were measured in 2025, with the scripts of that time. @@billo2025
Loading
Loading