Goose: 1.16x faster than C++ and 1.12x than safe Rust, while memory safe aardappel / goose Public Notifications You must be signed in to change notification settings Fork 0 Star 26 masterBranchesTags
By Coderz Club · 2026-09-18 · Tags: git, rust, go
Goose: 1.16x faster than C++ and 1.12x than safe Rust, while memory safe
aardappel / goose Public Notifications You must be signed in to change notification settings Fork 0 Star 26 masterBranchesTagsGo to fileCodeOpen more actions menuLatest commit History201 Commits201 CommitsFolders and filesNameNameLast commit messageLast commit date.github/workflows.github/workflows benchbench cmakecmake docsdocs samplessamples scriptsscripts srcsrc stdlibstdlib testtest third_partythird_party vscodevscode .gitattributes.gitattributes .gitignore.gitignore .gitmodules.gitmodules CMakeLists.txtCMakeLists.txt LICENSELICENSE README.mdREADME.md View all filesRepository files navigation The Goose Programming Language A memory-safe systems language that is faster than C++ and Rust, on less memory, with no allocator/GC and no lifetime annotations. Tutorial · Specification · Samples · Benchmarks · Standard library Goose looks familiar like C or Rust, and is built on one idea: there is no heap. Every dynamic value lives inline on a data stack the compiler manages, growth is a pointer bump, and scope exit is the only free. The rest of the language is what it takes to make that work for real programs, and what it buys is measurable. Why Goose Faster than C++ and than safe Rust, while memory safe. Over sixteen benchmarks Goose runs at 3.3x the speed of idiomatic C++, 1.16x hand-optimized C++ and 1.12x the best safe Rust, on 1.9x, 1.3x and 1.2x less memory (summary, full results). The wins are structural: they come from things the other languages cannot express. No allocator, no GC, no reference counting, no destructors. Memory is a handful of data stacks that the compiler assigns statically. Freeing a million-element structure is one store, however deeply it nests. Nothing ever moves. A reference into a growing array stays valid for as long as the array does. You keep typed references where C++ must reserve and safe Rust retreats to u32 indices. Memory safe with zero annotations. No lifetime syntax, no aliasing or exclusivity rules, no unsafe. The compiler infers what every reference is rooted in and objects to exactly one thing: outliving the owner. Flat all the way down. A string, an array of strings, a record with variable-size fields and an array of those records are each one contiguous block with no pointer in it. A record that is 160 bytes and an allocation in C++ is 29 bytes and none in Goose. Enums that cost what they hold. Variable-mode ADTs give each value its own variant's size rather than the largest one's: 4x less memory and 2x the speed of a Rust enum on the benchmark that exercises it. Links narrower than pointers. A relative reference stores a typed, checked link as a 1, 2 or 4-byte offset. Structures built from them are position independent, so your data structure is already its file format: saving is a write, loading is a read plus a verification pass that rejects hostile bytes. Everything is built in place, guaranteed. A value is constructed at its final destination through any depth of calls. items.push(parse(line)) writes the parsed record straight into the array, and returning a growable array by value costs nothing. Errors without plumbing. return err from load returns from a function any number of frames up, statically checked, with no unwinder, no Result type and no ? on every call. Threads that share nothing. A worker is compiled as a separate program with its own memory, and flat values cross typed queues as a memcpy. Data races, locks, atomics and memory orderings do not exist in the language. Generics and higher-order functions with no overhead. An untyped parameter is generic. Function values are compile-time entities, so xs.filter() { it > 0 } compiles to the loop it looks like and builds its result straight into its destination. Plain C in, plain C out. Goose compiles to one C file, so it runs wherever a C compiler does and calls C directly through extern fn. The bundled TinyCC backend compiles and runs a program in-process, with no build step. The tutorial walks through all of this by example, the specification has the exact rules, and the benchmarks have the numbers, losses included. Features Only what is different about Goose is shown here. The tutorial covers the same ground properly, and the samples are twenty-six complete programs doing it for real. One memory model: stacks, and scope exit is the free A program has the native call stack, static data and N data stacks, where the compiler works out N. A data stack is a large address-space reservation with a bump pointer, and there is no other memory. At most one resizable value is live per stack and it is always on top, so growth never moves anything and never checks a capacity. All of this is proved at compile time; the runtime keeps nothing but the bump pointers. for round in 3 { var scratch: u8[>..] = []; // grow-only: growth is a pointer bump for i in 100000 { scratch.push((i % 256) as! u8); } print("round ", round, ": ", scratch.len, " bytes
aardappel / goose Public Notifications You must be signed in to change notification settings Fork 0 Star 26 masterBranchesTagsGo to fileCodeOpen more actions menuLatest commit History201 Commits201 CommitsFolders and filesNameNameLast commit messageLast commit date.github/workflows.github/workflows benchbench cmakecmake docsdocs samplessamples scriptsscripts srcsrc stdlibstdlib testtest third_partythird_party vscodevscode .gitattributes.gitattributes .gitignore.gitignore .gitmodules.gitmodules CMakeLists.txtCMakeLists.txt LICENSELICENSE README.mdREADME.md View all filesRepository files navigation The Goose Programming Language A memory-safe systems language that is faster than C++ and Rust, on less memory, with no allocator/GC and no lifetime annotations. Tutorial · Specification · Samples · Benchmarks · Standard library Goose looks familiar like C or Rust, and is built on one idea: there is no heap. Every dynamic value lives inline on a data stack the compiler manages, growth is a pointer bump, and scope exit is the only free. The rest of the language is what it takes to make that work for real programs, and what it buys is measurable. Why Goose Faster than C++ and than safe Rust, while memory safe. Over sixteen benchmarks Goose runs at 3.3x the speed of idiomatic C++, 1.16x hand-optimized C++ and 1.12x the best safe Rust, on 1.9x, 1.3x and 1.2x less memory (summary, full results). The wins are structural: they come from things the other languages cannot express. No allocator, no GC, no reference counting, no destructors. Memory is a handful of data stacks that the compiler assigns statically. Freeing a million-element structure is one store, however deeply it nests. Nothing ever moves. A reference into a growing array stays valid for as long as the array does. You keep typed references where C++ must reserve and safe Rust retreats to u32 indices. Memory safe with zero annotations. No lifetime syntax, no aliasing or exclusivity rules, no unsafe. The compiler infers what every reference is rooted in and objects to exactly one thing: outliving the owner. Flat all the way down. A string, an array of strings, a record with variable-size fields and an array of those records are each one contiguous block with no pointer in it. A record that is 160 bytes and an allocation in C++ is 29 bytes and none in Goose. Enums that cost what they hold. Variable-mode ADTs give each value its own variant's size rather than the largest one's: 4x less memory and 2x the speed of a Rust enum on the benchmark that exercises it. Links narrower than pointers. A relative reference stores a typed, checked link as a 1, 2 or 4-byte offset. Structures built from them are position independent, so your data structure is already its file format: saving is a write, loading is a read plus a verification pass that rejects hostile bytes. Everything is built in place, guaranteed. A value is constructed at its final destination through any depth of calls. items.push(parse(line)) writes the parsed record straight into the array, and returning a growable array by value costs nothing. Errors without plumbing. return err from load returns from a function any number of frames up, statically checked, with no unwinder, no Result type and no ? on every call. Threads that share nothing. A worker is compiled as a separate program with its own memory, and flat values cross typed queues as a memcpy. Data races, locks, atomics and memory orderings do not exist in the language. Generics and higher-order functions with no overhead. An untyped parameter is generic. Function values are compile-time entities, so xs.filter() { it > 0 } compiles to the loop it looks like and builds its result straight into its destination. Plain C in, plain C out. Goose compiles to one C file, so it runs wherever a C compiler does and calls C directly through extern fn. The bundled TinyCC backend compiles and runs a program in-process, with no build step. The tutorial walks through all of this by example, the specification has the exact rules, and the benchmarks have the numbers, losses included. Features Only what is different about Goose is shown here. The tutorial covers the same ground properly, and the samples are twenty-six complete programs doing it for real. One memory model: stacks, and scope exit is the free A program has the native call stack, static data and N data stacks, where the compiler works out N. A data stack is a large address-space reservation with a bump pointer, and there is no other memory. At most one resizable value is live per stack and it is always on top, so growth never moves anything and never checks a capacity. All of this is proved at compile time; the runtime keeps nothing but the bump pointers. for round in 3 { var scratch: u8[>..] = []; // grow-only: growth is a pointer bump for i in 100000 { scratch.push((i % 256) as! u8); } print("round ", round, ": ", scratch.len, " bytes