Feature description
What Users Actually Experience
Let me start with a concrete example.
You have a Node.js project with about 2,800 JavaScript files – a typical modern web application. On a normal Linux machine, loading these files takes milliseconds. On Termux with proot-distro, the same operation takes 8.5 seconds just to run --version.
Why? Because proot intercepts every single system call via ptrace(). Every time your program opens a file, reads a directory, or checks a stat – each of those is a system call. And each one requires two context switches: from your program to the kernel, from the kernel to proot's handler, back to the kernel, and finally back to your program.
For 2,800 files, that's thousands of round trips. The fix in that case was to bundle everything into a single file – 2,800 files became 1, and the cold start dropped from 8.5 seconds to 3.6 seconds. The entire gateway went from 20 seconds to 6.4 seconds.
The lesson is clear: when your syscall overhead is non-trivial, the number of files matters more than their total size.
The Root Cause: ptrace() Overhead
Proot works by using ptrace() – a debugging interface – to intercept every system call made by a program running inside it. This is the same mechanism debuggers use to pause and inspect programs.
For a simple bash shell, the overhead is barely noticeable. But for anything heavier – Node.js, Python with heavy I/O, Chromium, or any application that makes thousands of system calls – the overhead becomes crippling.
In UNIXbench, proot-distro scores 44% lower than docker/chroot. CPU performance drops by 7-10% compared to native, while GPU performance drops by over 7 times.
The Solution: Proroot
Proroot is a drop-in replacement for proot that eliminates the ptrace() bottleneck entirely.
Instead of using ptrace() to intercept syscalls from outside the process, proroot handles everything inside the process itself using two complementary techniques:
- LD_PRELOAD interception – Intercepts calls to glibc functions like openat, stat, execve, and dlopen at the PLT (Procedure Linkage Table) level
- Binary patching – Scans the ELF binary at load time and patches raw syscall instructions (svc #0) to call through a trampoline, catching even glibc-internal syscalls that bypass LD_PRELOAD
The result: zero context switches per syscall. Path translation and environment isolation still work, but without the performance penalty.
Here's the architectural difference:
proot:
App ──ptrace──▶ Kernel ──ptrace──▶ Handler ──ptrace──▶ Kernel ──▶ Done
↑ 2 context switches per syscall
proroot:
App ──LD_PRELOAD──▶ translate() ──SVC──▶ Kernel ──▶ Done
↑ 0 context switches, in-process path translation
The Numbers That Matter
CPU Performance:
On Geekbench 6 multi-core, proroot achieves the exact same scores as native Android peak performance. In fact, one tester noted: "CPU/GPU/RAM all run at native performance. From a performance perspective, there are literally no downsides".
GPU Performance:
This is where the improvement is most dramatic. Running the Vulkan benchmark vkmark:
Environment vkmark Score
proot-distro 1,442
Proroot 10,746
That's a 7.45x improvement.
In another test, the proroot-based runtime scored 11,283 on vkmark, virtually identical to the 11,133 score of Termux's native Bionic Mesa Turnip.
Real-World Impact:
A developer working on an Android app that bundles Linux to run an AI gateway saw end-to-end performance improve from 20 seconds to 6.4 seconds – a 3x improvement – simply by reducing the number of syscalls. Now imagine that improvement applied to everything.
Beyond Performance: A Complete Linux Runtime
Proroot's ambition extends beyond being a faster proot. It's designed as a standalone glibc Linux runtime for Android.
The architecture looks like this:
[proroot]
Android host environment
├─ Android APK
│ ├─ libproroot.so (launcher - NDK/bionic)
│ ├─ libproroot-runtime.so (LD_PRELOAD runtime - glibc)
│ ├─ libproroot-bridge.so (child exec trampoline - NDK static)
│ ├─ libproroot-linker.so (clean-room glibc-compatible dynamic linker)
│ └─ files/rootfs/
│ └─ glibc Linux rootfs
└─ Existing rootfs run by proroot in an X server embedded in the APK
This means proroot can be bundled directly into an Android APK – a complete Linux system that runs with native performance. The runtime can access all Android APIs through a bridge, including hardware acceleration for video encoding/decoding via MediaCodec.
Key advantages:
· Full native performance – CPU, GPU, and RAM all run at native speed
· Universal GPU acceleration – Unlike the current Termux + proot setup, which only supports Adreno GPUs via Mesa Turnip/Freedreno KGSL, proroot can theoretically support all SoCs – Mali, Xclipse, PowerVR, and others
· Full Android API access – Through a runtime bridge
· No root required – Just like proot
Current Status
Proroot is under active development by a Korean developer (coderredlab):
· Architecture: arm64-only for now
· Distribution: Currently distributed as binaries; source code will be released after more testing and stabilization
· CLI Compatibility: Usage is kept as close to proot as possible – flags like -r, -w, and --link2symlink work the same
· Tested Workloads: Node.js 24/npm, Python 3.12, Git 2.43, curl, jq, OpenSSL, Chromium headless_shell 131 (Playwright), XFCE 4 + TigerVNC, OpenClaw, Codex CLI, esbuild
· Android Version: Android 8.0+ (API 26)
How to Integrate Proroot into Termux: A Step-by-Step Guide
Step 1: Obtain the Proroot Binaries
Download the four .so files from the proroot releases:
libproroot.so
libproroot-runtime.so
libproroot-bridge.so
libproroot-linker.so
Place them in /data/data/com.termux/files/usr/lib/proroot/:
mkdir -p $PREFIX/lib/proroot
# Copy the four .so files to $PREFIX/lib/proroot/
Step 2: Obtain a glibc Rootfs
Proroot requires a standard glibc Linux rootfs. You can use any distribution's arm64 rootfs:
# Example: Download Ubuntu arm64 rootfs
cd $HOME
wget https://cdimage.ubuntu.com/ubuntu-base/releases/22.04/release/ubuntu-base-22.04-base-arm64.tar.gz
mkdir -p $HOME/proroot-rootfs
tar -xzf ubuntu-base-22.04-base-arm64.tar.gz -C $HOME/proroot-rootfs
Or use proot-distro to get a rootfs and then run it with proroot:
pkg install proot-distro
proot-distro install ubuntu
# The rootfs is at $PREFIX/var/lib/proot-distro/installed-rootfs/ubuntu/
Step 3: Create a Wrapper Script
Create $PREFIX/bin/proroot with the following content:
#!/data/data/com.termux/files/usr/bin/bash
PROROOT_LIB_PATH="$PREFIX/lib/proroot/libproroot-runtime.so"
PROROOT_TRAMPOLINE_PATH="$PREFIX/lib/proroot/libproroot-bridge.so"
PROROOT_LINKER_PATH="$PREFIX/lib/proroot/libproroot-linker.so"
PROROOT_TMP_DIR="$HOME/proroot-tmp"
export PROROOT_LIB_PATH
export PROROOT_TRAMPOLINE_PATH
export PROROOT_LINKER_PATH
export PROROOT_TMP_DIR
exec "$PREFIX/lib/proroot/libproroot.so" "$@"
Make it executable:
chmod +x $PREFIX/bin/proroot
Step 4: Basic Usage
To start a shell inside a proroot environment:
proroot -r $HOME/proroot-rootfs -0 --link2symlink -w /root /bin/sh -c 'bash'
To run a specific command:
proroot -r $HOME/proroot-rootfs -0 --link2symlink -w /root /bin/sh -c 'node --version'
To run with bind mounts (similar to proot):
proroot -r $HOME/proroot-rootfs -0 --link2symlink -b /sdcard:/mnt/sdcard -w /root /bin/sh
Step 5: Create a proroot-distro Replacement
Create $PREFIX/bin/proroot-distro as a drop-in replacement for proot-distro:
#!/data/data/com.termux/files/usr/bin/bash
ROOTFS="$PREFIX/var/lib/proot-distro/installed-rootfs/${1:-ubuntu}"
if [ ! -d "$ROOTFS" ]; then
echo "Error: Rootfs not found. Install with: proot-distro install ubuntu"
exit 1
fi
shift # Remove the distro name from arguments
exec proroot -r "$ROOTFS" -0 --link2symlink -b /dev -b /proc -b /sys -w /root "$@"
Usage:
proroot-distro ubuntu bash
proroot-distro ubuntu node --version
Step 6: Integrate with Termux-X11 for GUI Applications
To run GUI applications with hardware acceleration:
# In Termux
pkg install termux-x11-nightly
# Start X server in Termux
termux-x11 :0 &
# In proroot environment
proroot -r $HOME/proroot-rootfs -0 --link2symlink -w /root /bin/sh -c '
export DISPLAY=:0
export PULSE_SERVER=127.0.0.1
# Install and run a GUI app
apt update && apt install -y firefox-esr
firefox
'
Step 7: Android API Access (Advanced)
Proroot's architecture allows direct Android API access through a runtime bridge. To enable this, you would need to:
- Build a bridge library that exposes Android APIs to the glibc environment
- Preload this bridge via LD_PRELOAD alongside libproroot-runtime.so
This is an advanced feature that requires significant development work but represents the ultimate potential of proroot.
What Termux Needs to Change
- Package the Proroot Binaries
Add a new package proroot to the Termux package repository. The build.sh should:
TERMUX_PKG_HOMEPAGE="https://github.com/coderredlab/proroot"
TERMUX_PKG_DESCRIPTION="Zero-overhead proot replacement for Android"
TERMUX_PKG_LICENSE="OTHER"
TERMUX_PKG_VERSION="0.1.0"
TERMUX_PKG_SRCURL="https://github.com/coderredlab/proroot/archive/refs/tags/v${TERMUX_PKG_VERSION}.tar.gz"
TERMUX_PKG_SKIP_SRC_EXTRACT=true
termux_step_make_install() {
# Download prebuilt binaries from releases
mkdir -p $TERMUX_PREFIX/lib/proroot
# Copy .so files to lib/proroot/
# Create wrapper script at bin/proroot
}
- Modify proot-distro to Support Proroot
Update proot-distro to allow choosing between proot and proroot:
# Option 1: Use proot (default)
proot-distro login ubuntu
# Option 2: Use proroot
proot-distro --runtime=proroot login ubuntu
Or create a separate proroot-distro command.
- Update Documentation
· Add proroot to the Termux wiki
· Document performance comparison and use cases
· Provide migration guides for existing proot users
- Default Runtime Strategy
For performance-sensitive workloads, consider making proroot the default:
· Node.js/npm projects: proroot default
· Python with heavy I/O: proroot default
· Chromium/Playwright: proroot default
· GUI applications (XFCE, etc.): proroot default
· Simple shell scripts: proot (fallback for compatibility)
The Long-Term Vision
Proroot represents a fundamental shift in what's possible on Android. With native-level performance, full glibc compatibility, and GPU acceleration, it enables:
· Running full desktop Linux applications on Android without root
· Game development and gaming via SteamOS ARM64 + Proton
· Professional development workflows with IDE-level performance
· Complete Linux toolchains without the proot overhead
As one observer noted: "This is a total game-changer".
Conclusion
The performance objections to moving Termux toward a standard Linux foundation are no longer valid. Proroot achieves native-level performance – CPU, GPU, and memory all run at the same speed as Bionic native.
The choice is no longer between:
· "Fast but incompatible" (Bionic native)
· "Compatible but slow" (proot)
Now we have:
· "Compatible AND fast" (proroot)
Proroot represents the future of Linux on Android. Termux should embrace it.
References:
· UNIXbench: proot-distro scores 44% lower than docker/chroot
· vkmark: proot-distro 1,442 vs proroot 10,746 – 7.45x improvement
· Geekbench 6: proroot achieves native Android peak scores
· Architecture: LD_PRELOAD + binary patching
· Tested workloads: Node.js, Python, Git, Chromium, XFCE
· Proroot repository: github.com/coderredlab/proroot
Additional information
https://github.com/coderredlab/proroot
#5239
Feature description
What Users Actually Experience
Let me start with a concrete example.
You have a Node.js project with about 2,800 JavaScript files – a typical modern web application. On a normal Linux machine, loading these files takes milliseconds. On Termux with proot-distro, the same operation takes 8.5 seconds just to run --version.
Why? Because proot intercepts every single system call via ptrace(). Every time your program opens a file, reads a directory, or checks a stat – each of those is a system call. And each one requires two context switches: from your program to the kernel, from the kernel to proot's handler, back to the kernel, and finally back to your program.
For 2,800 files, that's thousands of round trips. The fix in that case was to bundle everything into a single file – 2,800 files became 1, and the cold start dropped from 8.5 seconds to 3.6 seconds. The entire gateway went from 20 seconds to 6.4 seconds.
The lesson is clear: when your syscall overhead is non-trivial, the number of files matters more than their total size.
The Root Cause: ptrace() Overhead
Proot works by using ptrace() – a debugging interface – to intercept every system call made by a program running inside it. This is the same mechanism debuggers use to pause and inspect programs.
For a simple bash shell, the overhead is barely noticeable. But for anything heavier – Node.js, Python with heavy I/O, Chromium, or any application that makes thousands of system calls – the overhead becomes crippling.
In UNIXbench, proot-distro scores 44% lower than docker/chroot. CPU performance drops by 7-10% compared to native, while GPU performance drops by over 7 times.
The Solution: Proroot
Proroot is a drop-in replacement for proot that eliminates the ptrace() bottleneck entirely.
Instead of using ptrace() to intercept syscalls from outside the process, proroot handles everything inside the process itself using two complementary techniques:
The result: zero context switches per syscall. Path translation and environment isolation still work, but without the performance penalty.
Here's the architectural difference:
The Numbers That Matter
CPU Performance:
On Geekbench 6 multi-core, proroot achieves the exact same scores as native Android peak performance. In fact, one tester noted: "CPU/GPU/RAM all run at native performance. From a performance perspective, there are literally no downsides".
GPU Performance:
This is where the improvement is most dramatic. Running the Vulkan benchmark vkmark:
Environment vkmark Score
proot-distro 1,442
Proroot 10,746
That's a 7.45x improvement.
In another test, the proroot-based runtime scored 11,283 on vkmark, virtually identical to the 11,133 score of Termux's native Bionic Mesa Turnip.
Real-World Impact:
A developer working on an Android app that bundles Linux to run an AI gateway saw end-to-end performance improve from 20 seconds to 6.4 seconds – a 3x improvement – simply by reducing the number of syscalls. Now imagine that improvement applied to everything.
Beyond Performance: A Complete Linux Runtime
Proroot's ambition extends beyond being a faster proot. It's designed as a standalone glibc Linux runtime for Android.
The architecture looks like this:
This means proroot can be bundled directly into an Android APK – a complete Linux system that runs with native performance. The runtime can access all Android APIs through a bridge, including hardware acceleration for video encoding/decoding via MediaCodec.
Key advantages:
· Full native performance – CPU, GPU, and RAM all run at native speed
· Universal GPU acceleration – Unlike the current Termux + proot setup, which only supports Adreno GPUs via Mesa Turnip/Freedreno KGSL, proroot can theoretically support all SoCs – Mali, Xclipse, PowerVR, and others
· Full Android API access – Through a runtime bridge
· No root required – Just like proot
Current Status
Proroot is under active development by a Korean developer (coderredlab):
· Architecture: arm64-only for now
· Distribution: Currently distributed as binaries; source code will be released after more testing and stabilization
· CLI Compatibility: Usage is kept as close to proot as possible – flags like -r, -w, and --link2symlink work the same
· Tested Workloads: Node.js 24/npm, Python 3.12, Git 2.43, curl, jq, OpenSSL, Chromium headless_shell 131 (Playwright), XFCE 4 + TigerVNC, OpenClaw, Codex CLI, esbuild
· Android Version: Android 8.0+ (API 26)
How to Integrate Proroot into Termux: A Step-by-Step Guide
Step 1: Obtain the Proroot Binaries
Download the four .so files from the proroot releases:
Place them in /data/data/com.termux/files/usr/lib/proroot/:
Step 2: Obtain a glibc Rootfs
Proroot requires a standard glibc Linux rootfs. You can use any distribution's arm64 rootfs:
Or use proot-distro to get a rootfs and then run it with proroot:
pkg install proot-distro proot-distro install ubuntu # The rootfs is at $PREFIX/var/lib/proot-distro/installed-rootfs/ubuntu/Step 3: Create a Wrapper Script
Create $PREFIX/bin/proroot with the following content:
Make it executable:
chmod +x $PREFIX/bin/prorootStep 4: Basic Usage
To start a shell inside a proroot environment:
To run a specific command:
To run with bind mounts (similar to proot):
proroot -r $HOME/proroot-rootfs -0 --link2symlink -b /sdcard:/mnt/sdcard -w /root /bin/shStep 5: Create a proroot-distro Replacement
Create $PREFIX/bin/proroot-distro as a drop-in replacement for proot-distro:
Usage:
Step 6: Integrate with Termux-X11 for GUI Applications
To run GUI applications with hardware acceleration:
Step 7: Android API Access (Advanced)
Proroot's architecture allows direct Android API access through a runtime bridge. To enable this, you would need to:
This is an advanced feature that requires significant development work but represents the ultimate potential of proroot.
What Termux Needs to Change
Add a new package proroot to the Termux package repository. The build.sh should:
Update proot-distro to allow choosing between proot and proroot:
Or create a separate proroot-distro command.
· Add proroot to the Termux wiki
· Document performance comparison and use cases
· Provide migration guides for existing proot users
For performance-sensitive workloads, consider making proroot the default:
· Node.js/npm projects: proroot default
· Python with heavy I/O: proroot default
· Chromium/Playwright: proroot default
· GUI applications (XFCE, etc.): proroot default
· Simple shell scripts: proot (fallback for compatibility)
The Long-Term Vision
Proroot represents a fundamental shift in what's possible on Android. With native-level performance, full glibc compatibility, and GPU acceleration, it enables:
· Running full desktop Linux applications on Android without root
· Game development and gaming via SteamOS ARM64 + Proton
· Professional development workflows with IDE-level performance
· Complete Linux toolchains without the proot overhead
As one observer noted: "This is a total game-changer".
Conclusion
The performance objections to moving Termux toward a standard Linux foundation are no longer valid. Proroot achieves native-level performance – CPU, GPU, and memory all run at the same speed as Bionic native.
The choice is no longer between:
· "Fast but incompatible" (Bionic native)
· "Compatible but slow" (proot)
Now we have:
· "Compatible AND fast" (proroot)
Proroot represents the future of Linux on Android. Termux should embrace it.
References:
· UNIXbench: proot-distro scores 44% lower than docker/chroot
· vkmark: proot-distro 1,442 vs proroot 10,746 – 7.45x improvement
· Geekbench 6: proroot achieves native Android peak scores
· Architecture: LD_PRELOAD + binary patching
· Tested workloads: Node.js, Python, Git, Chromium, XFCE
· Proroot repository: github.com/coderredlab/proroot
Additional information
https://github.com/coderredlab/proroot
#5239