https://github.com/FastVM/minivm Skip to content Sign up * Why GitHub? + Features + Mobile + Actions + Codespaces + Packages + Security + Code review + Issues + Integrations + GitHub Sponsors + Customer stories * Team * Enterprise * Explore + Explore GitHub + Learn and contribute + Topics + Collections + Trending + Learning Lab + Open source guides + Connect with others + The ReadME Project + Events + Community forum + GitHub Education + GitHub Stars program * Marketplace * Pricing + Plans + Compare plans + Contact Sales + Education [ ] * # In this repository All GitHub | Jump to | * No suggested jump to results * # In this repository All GitHub | Jump to | * # In this organization All GitHub | Jump to | * # In this repository All GitHub | Jump to | Sign in Sign up {{ message }} FastVM / minivm Public * Notifications * Fork 17 * Star 496 * A VM That is Dynamic and Fast MIT License 496 stars 17 forks Star Notifications * Code * Issues 2 * Pull requests 1 * Actions * Projects 0 * Wiki * Security * Insights More * Code * Issues * Pull requests * Actions * Projects * Wiki * Security * Insights main Switch branches/tags [ ] Branches Tags Could not load branches Nothing to show {{ refName }} default View all branches Could not load tags Nothing to show {{ refName }} default View all tags 1 branch 0 tags Code Latest commit @ShawSumma ShawSumma Merge pull request #6 from pablogamboa/patch-2 ... 4ea7c95 Jan 8, 2022 Merge pull request #6 from pablogamboa/patch-2 Fix some typos in README.md 4ea7c95 Git stats * 253 commits Files Permalink Failed to load latest commit information. Type Name Latest commit message Commit time .github/workflows actions for macos Jan 6, 2022 main add an wasm api Dec 26, 2021 vm fix spelling mistake in emty to empty Jan 8, 2022 .gitignore rename out Dec 19, 2021 LICENSE add the licence that was deleted Jan 6, 2022 MiniVM.svg Add logo and update readme Oct 2, 2021 README.md Fix some typos in README.md Jan 8, 2022 fib.png add benchmarks update readme Jan 7, 2022 makefile add benchmarks update readme Jan 7, 2022 tree.png add benchmarks update readme Jan 7, 2022 View code [ ] MiniVM History Some Sweet Deets A Register-Based VM On malloc and putchar Types Installation Getting Started Benchmarks Binary Trees: Allocations and GC Recursive Fibonacci: Functions and Math Roadmap README.md The MiniVM Logo, looks like a brick according to some, some catfood according to others MiniVM Link to Discord MiniVM is a small and fast cross-language Virtual Machine (VM) written in good ol' C, meaning it can compile and run just about anywhere. Here are a few reasons why MiniVM is pretty neat: * Built on a register-based ISA that beats luajit--with the JIT on --in some benchmarks. (See the benchmarks section below). * Has an efficient GC that can handle large amounts of allocations and deallocations efficiently. (Again, check the benchmarks). * Supports a flexible data model with a number of optimizations to minimize memory usage. * Leverages Cosmopolitan libc + WebAssembly for easy cross platform portability. * ... check out the details section for more! MiniVM is small and flexible enough to run just about any language under the sun (given you've taken the time to write a compiler for it). Front ends we've experimented with include Lua, Scheme, Paka, and others. You can try out the Paka frontend to MiniVM online! History This project started as an exploration into what it takes to build a fast interpreter. The first version was blocked out during a single Discord call, and ran a small lisp-like language. This original implementation was a plain stack machine, which, for whatever reason, was a tad faster than it should've been. Leveraging this tiny 1,000 LoC base, MiniVM matured into something a bit bigger, but only slightly. It now runs a language close to ASM, and has got quite faster over time. MiniVM's speed is in no small part due to its architecture. It's a register/stack machine with carefully-selected opcodes that are designed to work well with common data-access patterns. Above all else, MiniVM is constantly improving every day. We hope you find the journey to be as interesting as the final destination. If you're interested as to where the project is headed next, ping Shaw (@4984#4984) on the Discord Server. Some Sweet Deets Below is a small discussion of the architecture of MiniVM, and the emergent properties because of these decisions. A Register-Based VM First and foremost, MiniVM is a register-based VM. This means that instructions are larger and operate on registers, as opposed to the stack. Because of this property, register-based VMs play nicely with modern hardware, and result in less instructions per unit of work done. Consider the following: while x < 1000 { x = x + 1 } A stack-based VM would have to emit a single instruction for every single little thing done in the loop above. You'd probably end up with something like: head_of_loop: load_var x push_int 1000 less_than jump_if_false :end_of_loop load_var x increment store_var x end_of_loop: This is all well and good, but compare it to what a register-based machine does: // r0 is where x lives head_of_loop: jump_if_reg_less_than_number r0 1000 :end_of_loop increment_reg r0 1 jump :head_of_loop end_of_loop: Although each instruction is a bit more complex, there are way fewer instructions. And this per-instruction complexity isn't necessarily a bad thing: making instructions more complex offloads work to the host language (C, in this case), which means that the runtime can compile common complex instructions to efficient native code. On malloc and putchar MiniVM's only dependencies are 9 functions in libc: fmod, putchar, malloc, realloc, free, fopen, fclose, fwrite, fread Only malloc and putchar are relied on heavily, though: putchar is the function all IO boils down to eventually. malloc is required for memory allocations as of recent. -- Shaw The entire codebase is highly configurable, allowing users of MiniVM to choose the optimal feature set that supports their application. Types Minivm has a select set of core types. * none + the lack of a value * boolean + true or false * number + configurable to be C's int32_t num: 30; or C's double num; * array + unchanging in length + mutable by default Because MiniVM is a register-based machine, it employs clever instructions to leverage common type layouts for better performance. For instance, to emulate closures arrays can be called as functions if the first item in that array is a function. Installation Building from source is pretty simple: git clone https://github.com/shawsumma/minivm cd minivm make One can also use the artifacts from github actions. MiniVM Binaries for Linux, MacOS and Windows can be found here. Click the text next to a green check mark and download the linux-opt, macos-opt or windows-opt single file binary. Getting Started MiniVM has a growing and fairly unstable API. The best way to get familiar with MiniVM and its opcodes is to read through the headers in the vm/ directory. The top of the bytecode file is the usual entry point. MiniVM can be built as a library with make VM_MAIN=. The most common way to get code running on MiniVM is to use Paka. For those looking to try paka and minivm online use XorI. Benchmarks Taking benchmarks is hard. Benchmarks are fraught with peril and don't always tell the full story: if you want to know how your application will perform in a language, no benchmarks will be a substitute for that. We tried to be fair, methodical, and thorough in our benchmarking; despite this, remember to take these results with a grain of salt. All benchmarks were run in hyperfine on a 2020 MacBook Air M1 with 8GB RAM running Big Sur 11.2.3. The implementations we benchmarked are idiomatic and consistent between target benchmark languages. All benchmarks may be found in the Paka repository if you'd like to run them on your machine. Binary Trees: Allocations and GC Binary Trees Graph As you can see, MiniVM (no JIT) beats luajit with the JIT on in this benchmark. MiniVM has a custom-built allocator and GC, which beats out luajit's slower modified version of malloc. MiniVM also is a hair faster that C for tree sizes above 13 (C is compiled ahead-of time, using clang with the -Ofast flag for best performance). For tree sizes less that 13, beats Node JS due to having a faster startup time. Overall, MiniVM's performance is about on par with JIT'd and compiled languages on this benchmark. The binary tree benchmark measures the time it takes to create a balanced binary tree of a given depth and sum the values in each node to produce a total for the tree. This measures how well the language runtime handles a large number of repeated allocations and deallocations (no memory pooling is used or allowed). Recursive Fibonacci: Functions and Math Fibonacci Runtime As you can see, minivm (no JIT) is a hair slower than Node JS (JIT) but beats luajit --joff by a fair margin (no JIT). The recursive fibonacci benchmark computes fib(35) in a recursive manner (not memoized). This mostly measures the performance of basic mathematical operations and the overhead of function calls. The code for fib in Paka (a minivm frontend) is: def fib(n) { if n < 2 { return n } else { return fib(n - 1) + fib(n - 2) } } We compile this Paka straight to minivm bytecode, there isn't any subsequent optimization of the bytecode by hand. Roadmap * Write assembler for minivm bytecode. * Reducde dependencies to libc functions. * Add types. * Improve performance. Note: MiniVM is wholly developed by Shaw (4984); this README was written by a friend of his who thinks he can be a bit too modest at times. About A VM That is Dynamic and Fast Resources Readme License MIT License Stars 496 stars Watchers 11 watching Forks 17 forks Releases No releases published Packages 0 No packages published Contributors 3 * @ShawSumma ShawSumma Shaw * @slightknack slightknack Isaac Clayton * @pablogamboa pablogamboa Pablo Marti Languages * C 98.5% * Makefile 1.5% * (c) 2022 GitHub, Inc. * Terms * Privacy * Security * Status * Docs * Contact GitHub * Pricing * API * Training * Blog * About You can't perform that action at this time. You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.