libriscv: a RISC-V sandbox built for call latency rather than throughput
The fastest RVA23 RISC-V sandbox
At a glance
- What is it?
- A small, embeddable RISC-V emulator that the README says can call a guest function and return in 3 nanoseconds where other solutions take 50 to 150, with pause and resume, copy-on-write shared memories, and a JIT path for development. It is explicitly not aiming at wide Linux syscall coverage, and that is the trade everything else follows from.
- Who is it for?
- libriscv suits a team embedding a RISC-V sandbox for scripts, for example game server logic, where the dominant cost is the call into the guest and the return, and where the host needs to be able to pause, serialise and resume a VM.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The number the project leads with
libriscv is described as a simple, slim and complete sandbox that is highly embeddable and configurable, a specialty emulator that specialises in low-latency, low-footprint emulation. The repository description calls it the fastest RVA23 RISC-V sandbox.
The headline figure is in the first paragraph. Where other solutions routinely require roughly 50 to 150 nanoseconds to call a VM function and return, libriscv requires 3 nanoseconds. The README goes further and says libriscv is routinely faster than other interpreters, JIT compilers and binary translators, and that it has specialised APIs that make passing data in and out of the sandbox safe and low-latency.
Three nanoseconds is not a throughput number. It is a round trip. The whole design of the project follows from that distinction, and the goals list makes it explicit. The first goal is the lowest possible latency, with the note that calling a guest VM function can finish one to two orders of magnitude before other emulators begin executing the first instruction. Then a lightning-fast interpreter mode, modern type-safe VM call and system call interfaces, a secure speculation-safe sandbox linked from a `SECURITY.md` file, and a low attack surface of only 20k lines of code, 35k with RVA23 and binary translation.
The non-goals are equally explicit. Wide support for Linux system calls is not a goal, and neither is higher performance at the cost of call latency. That second one is the sharpest statement in the document, because it says the project will not chase peak emulation speed if doing so slows down the entry path.
The primary language is C++ and the project requires C++17 or later, the licence is BSD-3-Clause, and the repository is not archived with the last push on 2026-10-15.
The modes: interpreter, libtcc JIT and binary translation
There are three execution modes, and the README is careful about which is for development and which is for shipping.
The interpreter is the baseline. The README notes that RISC-V is a register machine architecture, which makes it easy to reach good interpreter performance without needing a register allocator, and the benchmark section compares interpreter against interpreter explicitly under the heading Register versus stack machines.
The just-in-time compilation mode is described as being for development usage. The library can be used to instantly improve emulation of RISC-V programs, and the README says this is currently enabled by default. The mechanism is libtcc, a small C compiler that runs at runtime, so a guest program can be compiled to machine code on the host rather than interpreted.
Binary translation is the third mode, and it is aimed at end-user systems. On those systems, where shared libraries are allowed, RISC-V programs can be cross-compiled to a binary translated `.dll` executable inside libriscv. On systems where shared libraries are not allowed, or where static builds are preferred, the README describes embeddable high-performance binary translations that can be baked into the final build. The stated goal is maximum final-build performance on all platforms, including consoles, mobiles and production systems.
The release history shows the backends evolving. v1.20, published on 2026-08-23, is titled RVA23U64 and the asmjit backend, and v1.19 was a correctness fixes release.
The Dockerfile shows how the modes are built in practice. The build script is invoked twice, once with the `--tcc` flag for a fast emulation build and once with `--bintr` for a fastest emulator build, producing two separate binaries from the same sources.
Pause and resume as a first-class capability
One goal stands out because it is not about speed at all: pause and resume is described as a first-class citizen.
The three capabilities under that heading are precise. You can pause on any instruction. You can make preemptive function calls. And you can pause and serialise the VM, then deserialise it and resume on another host or platform.
That third one is the most consequential. A serialisable VM means the state of an emulated program can be written to disk and resumed elsewhere, which turns the sandbox from a library call into something you can snapshot, migrate or checkpoint. For a server that runs many short-lived guest VMs, that is the difference between a process you can throw away and a process you have to keep.
The scalable deployment model follows from the same place. The README describes serving requests using ephemeral VMs in about a microsecond in production, and explains how execute segments are automatically shared among all instances, with or without forking, under a copy-on-write support and shared memories heading.
The security model is the other structural feature. The goal list links a secure speculation-safe sandbox in `SECURITY.md`, and the repository root has that file. For an emulator that runs untrusted guest code on a host, the boundary between guest and host is the whole design, and a project that documents the speculation-safety question in a dedicated file is treating it as a first-class concern.
The repository layout is consistent with all of this. There is a `c/` directory for the C API surface, `lib/` for the library, `emu128/` for the 128-bit emulation support, `emulator/` for the CLI, `binaries/` with example programs including a memory measurement one, `fuzz/` for fuzzing, and `tests/`.
The benchmarks, and how the author frames them
The benchmark section is unusually candid about its own limits, which is worth reading before the numbers.
The STREAM benchmark and a CoreMark result are linked, with CoreMark at 38223 against 41382 native, which the README puts at about 92 percent. Then there is the Doom example: run D00M 1 in libriscv and it should use around 2 percent CPU at 60 fps.
The comparisons against LuaJIT and Luau come with a caveat that is easy to skip and important to keep: most benchmarks are hand-picked for the purposes of game engine scripting, but there are still some classic benchmarks.
The interpreter comparison is the one that explains the design. The README says libriscv in interpreter mode is substantially faster than other interpreters, with charts for the STREAM memory benchmark on a Ryzen 7950X and a Ryzen 6860Z, and for a CoreMark 1.0 interpreter comparison from November 2024. The reason given is the register versus stack machine distinction: RISC-V is a register machine, which makes it easy to reach good interpreter performance without needing a register allocator.
And then the specific claim about short functions. For a rainbow colour calculation that is three sine functions, libriscv can call the function 5.25 to 7.25 times before wasmtime has called it once, and the README attributes this to its substantially lower latency for short-running functions.
That is the whole thesis in one measurement. For a long-running guest program, a slower emulator is fine. For a guest function called thousands of times per frame, the call overhead is the entire cost.
A CLI that can step and debug, and the sandboxing use case
There is a CLI alongside the library, and it is described as a way to run RISC-V programs and step through instructions one by one like a simulator, or to connect with GDB in order to remotely live-debug programs. The README points to the emulator's own README for the many build and run-time options.
A GDB connection into a sandbox is not a small feature. It means a host developer can debug guest code that is running inside a sandbox, with the debugger attached to the emulated address space rather than to the host process. For a project whose guests are scripts, that is a large part of the developer experience.
The sandboxing use case is the one the project is built for, and the README names the target: sandboxing certain programs, such as game scripts. The features that make that work are the specialised safe APIs for passing data in and out, the type-safe VM call and system call interfaces, and the type-safety rationale, which is stated plainly. The interfaces prevent all kinds of footguns that the author has personally suffered, and consequently blocked off forever.
That phrase, blocked off forever, is a design philosophy statement rather than a feature. In a sandbox, the host and guest share an address space in the sense that the emulator has to move data across the boundary, and the easiest way to get that wrong is an ad-hoc call interface.
There is also support for sandboxing language runtimes that use JIT compilation, for example V8 JavaScript and LuaJIT, with JIT-compiled segments detected, processed and able to use the fast-path dispatch. That is the hard case for any emulator, since the guest rewrites its own code while running.
Embedding it, and the examples that show how
Embedding is documented through a dedicated example project at `examples/embed` for directly embedding libriscv using CMake, and a package example for using it as a packaged artefact.
The examples tree is where the design is legible, because each directory answers a different question. There is `examples/doom` for the D00M 1 case, `examples/gamedev` for the game scripting case, `examples/per_request_isolation` for the ephemeral VM model, `examples/webapi` for serving over a web API, `examples/wasm` for the WebAssembly comparison, `examples/attribute_bench` and `examples/rust_attribute_bench` for the attribute performance measurements, `examples/coremark` for the CoreMark run, `examples/advanced` and `examples/expert` and `examples/rust_expert` for the harder cases, `examples/includeos` and `examples/noexcept` for unusual constraints, and `examples/msvc` for the Microsoft toolchain.
The last two are worth noting. An IncludeOS example suggests the project is used in environments with a very small operating system, and a noexcept example suggests attention to exception behaviour in a library that must be embeddable in a host with its own error handling.
The library claims to be platform-independent and super-easy to embed, supporting all architectures and all platforms, and the continuous integration badges back that up in a way that is worth reading: a Debian packaging workflow, a build configuration matrix, a unit tests workflow, an experimental unit tests workflow, a Linux emulator workflow, a MinGW 64-bit emulator build, and a workflow that verifies the example programs.
The verify-examples workflow is the interesting one, because it is what keeps the examples honest, and the experimental unit tests are separated from the regular ones, which is how a project distinguishes the tests it trusts from the ones it is still developing.
Where libriscv is the wrong choice
The first wrong case is a workload that needs a Linux userland. Wide support for Linux system calls is an explicit non-goal, so a guest that expects to open files, resolve DNS or talk to a network stack is out of scope. The RISC-V programs this library targets are programs with a narrow syscall surface.
The second wrong case is a workload that wants maximum emulation throughput. Higher performance at the cost of call latency is the other non-goal, and it is the right call for the project but the wrong one for a task like running a long CPU-bound job inside the sandbox. If the guest program runs for minutes, the interpreter mode is the bottleneck and the design is not trying to fix that.
The third is a host that cannot tolerate a C++17 dependency, or that wants a sandbox with a very small attack surface measured in a different unit. The library is 20k lines of C++ and it embeds a JIT, a binary translator and an emulator, so the total dependency weight is much larger than 20k lines of code suggests.
The fourth is a project that has already standardised on a general-purpose emulator such as wasmtime. Those tools trade call latency for breadth, which is the mirror image of this library's bet.
The fifth is a team that needs the RVA23 features and is on an older release. v1.20 names RVA23U64 and the asmjit backend, and the line count for the project goes from 20k to 35k with RVA23 and binary translation, so the newer baseline is a materially different thing.
What you get if the bet is right is a sandbox where calling into the guest is nearly free, which is a property no general-purpose emulator offers, and where the VM can be paused and resumed across hosts.
Editorial conclusion
libriscv suits a team embedding a RISC-V sandbox for scripts, for example game server logic, where the dominant cost is the call into the guest and the return, and where the host needs to be able to pause, serialise and resume a VM. It does not suit a workload that needs broad Linux syscall coverage, which the README lists as an explicit non-goal, and it does not suit a project that wants maximum emulation throughput, since higher performance at the cost of call latency is the other non-goal. Before adopting it, read `SECURITY.md` for the speculation-safe sandbox model, decide whether you want the interpreter, the libtcc JIT or the binary translation backend, and check the RVA23 requirement in v1.20, since the release notes for that version name RVA23U64 and the asmjit backend as the headline change.
Frequently asked questions
What is libriscv and what is it optimised for?
It is a simple, slim and complete RISC-V sandbox that is highly embeddable and configurable, specialising in low-latency, low-footprint emulation. The README says calling a guest VM function and returning takes 3 nanoseconds, where other solutions routinely take 50 to 150 nanoseconds.
Which execution modes does libriscv support?
An interpreter mode, a just-in-time compilation mode using libtcc that is enabled by default and aimed at development, and binary translation, either as a `.dll` on end-user systems or as embeddable code baked into a final build where shared libraries are not allowed.
Can a libriscv VM be paused and resumed on another host?
Yes. Pause and resume is described as a first-class citizen: you can pause on any instruction, make preemptive function calls, and pause and serialise the VM, then deserialise and resume it on another host or platform.
What does libriscv not try to do?
Two things are listed as non-goals: wide support for Linux system calls, and higher performance at the cost of call latency. The project also names a secure speculation-safe sandbox as a goal, documented in `SECURITY.md`.
How do I embed libriscv in a project?
The `examples/embed` directory shows direct embedding with CMake, and `examples/package` shows using it as a packaged artefact. The library requires C++17 or later and is built with CMake, and the examples cover game scripting, per-request isolation, web APIs and WebAssembly.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/libriscv-libriscv)Was this useful?