example.com/path/to/article
000 points · username · 0 hours ago
example.com544 points · 341 comments · 1 day ago · bobbydigitales
Aardappel
jcmoyer
var words: u8[][>..] = [];
for i in 5 { words.push(str("word", i)); }
In C++ that is a vector<string>: one heap allocation for the vector,
one per string, a pointer and a capacity per element, and a walk over
all of them when it goes out of scope.
The example you've provided uses strings that are eligible for small string optimization, which avoids per-string allocation. All mainstream STL implementations perform this optimization. You can read about several implementations here: https://devblogs.microsoft.com/oldnewthing/20230803-00/?p=10...malisper
For instance, how would you represent a hash table where the values are strings and at random, the program inserts or deletes a random string?
This doesn't seem like something you could easily represent. The only way I can think of is to keep a stack that holds all of your strings, and you periodically compact it.
Edit: Maybe you could also have a separate stack for strings of various sizes. One each for strings less than 8, 16, ... bytes. But at that point you're basically implementing your own malloc by hand.
Edit: Fwiw I do think Goose is very cool! I've had to hand-roll a lot of similar stuff in Rust before to speed up memory management
anigbrowl
I wonder if the name of the language was inspired by the way geese fly in formation, with trailing birds saving energy by flying inside the aerodynamic shadow of the leaders, and swapping in and out as needed. If so, a very nice metaphor for the memory management model.
I was also impressed by the documentation. As we know AI-generted docs tends to be rather mediocre, but the author has clearly invested time in making in readable such that the relevance and rationale of design decisions provide the context that a curious programmer needs to understand why things are implemented in a particular way.
I really appreciated the detailed samples, ranging from simple algorithmic theorems up to a small game. Again, I don't have the experience to rate the language vs others, but I was struck by readable the code was and how easy it was to follow task flow. Not having to think about classes is always a plus!
Anyway, I usually the the offering of a new language with dispassionate interest, as something to be aware of and but not get too invested in or familiar with until it gains enough popularity to have a good shot at longevity. Goose is the first language in a long time where I looked at it and immediately thought that I'd like to use it for its own sake.
pradn
Still, for a large number of programs - like data-oriented applications - it’s probably a good fit. It might work ok with entity-component game systems as long as you reuse old memory…
ebiederm
From what little I read in the literature I seem to recall that there were enough programs with quite a bit more memory usage that they decided this approach was a dead end.
Does anyone know anymore details?
malkia
That reminds me of Dart Isolates - https://dart.dev/language/isolates
bobbydigitalesOP
The relative references and built in binary structure validation also enable direct memory mapping of data structures and immediate use of network data. "Parsing" file and network data is often 100x slower than it needs to be." - John Carmack
jeff_ciesielski
Ported a couple of algorithms from my quite large commercial rust codebase and they were significantly faster in goose. Was wow'd, but the big gain was actually that goose just led the LLM to use more efficient (though admittedly slightly less rust-ideomatic but still safe) data structures, so porting them back kept nearly all of the gain (and in one case, even more).
The obvious 'no shit' comment is 'well your code just wasn't optimized', which is partially true, there was obviously a fair bit left on the table. What I find more interesting is that for darn near zero cost, having an an LLM explore in different languages led to a better outcome than me sitting here running perf and squeezing for cycles.
I'm sure that as I build up a cookbook for my codebase this will be less useful over time, but for now, this is going to be how I approach first order performance optimization.
Nice work, cool tool, plz de-ai the docs :D
pulse7
Aardappel
exaroth
saidnooneever
Either way nice to see more options in this space.
Do you know a bit of an ETA / roadmap for certain features like the dynamically sized moves and struct members?
p.s. love potato and geese so feelin kinda biassed towards being excited about this :D
kadw
Embassy (https://github.com/embassy-rs/embassy) uses this concept of no heap allocation and I find it really solid. Even if you write in C, most of the times you don't use heap. MISRA, the C coding standard for automotives, doesn't allow dynamic allocation!
AnEro
amai
This was my first programming language. Good old times!
weinzierl
Where does Goose sit when classified along these dimensions?
Sure, performance is right there on the packaging but no word about UB in the README. I read "Goose has syntax familiar to C and Rust" as DX in the same ballpark, but is it a performance first or safety first language.
If it is the former it occupies the same crowded niche as C++ and its many cousins and will have a hard time.
If it's the latter it will have much more room to prosper. We don't have enough languages in the niche that Rust and Ada fill right now.
hackrmn
malkia
If the host needs to load several of these .wasm, compiled with goose, then it'll have to run them in separate (browser) instances too (or maybe that's how wasm works by default - not sure).
It just got me thinking - the languge is prepared to translate into javascript workers, because it's really single threaded by nature with communication between threads (or put in the dart languages term "isolates"), which makes them perfect for the browser, now the only question is the memory layout.
malkia
I guess there would be some penalty to be paid here for smaller pages, but being mostly contigous might also help some.
That to be said, such language seems to require 64-bit virtual address space in order to function reasonably, right?
Also a .dll written in it might not be the best suited, for example if loaded in the middle of fragmented virtual address space it may need to find itself hard to allocate N contigious data stacks (do they absolutely have to be contiguous, what if they are simply ropes or deques or connected chunks ... obviously if some data structure requires to be contigous that would be a problem, but maybe this can be expressed somehow.... or maybe I'm overthinking here).
Super excited about this!
twiss
Returns across multiple calls. `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.
Does this mean you have to know the name of the function calling you that's supposed to handle the error? What if you're a library and don't know that?
tonis2
baud9600
I’d love to see 1st class lightweight ‘processes’ and typed comms, like CSP. These light processes would be cheap to spawn in the thousands, with synchronous comms. So it’s possible to quickly use arbitrary networks rather than OS thread worker pools with queues. Maybe like:
fn produce(out: chan<i32>) { for i in 1000 { send(out, i); } }
fn consume(inp: chan<i32>) { for i in 1000 { print(recv(inp)); } }
fn main() { let c = chan<i32>();
par {
produce(c);
consume(c);
}
}[deleted]
swiftcoder
wewewedxfgdf
andsoitis
[deleted]
daoxid
whacko_quacko
[deleted]
stellalo
Edit: I guess one would still miss Goose’s memory layout, which is (if I understand correctly) where it wins in performance.
[deleted]
hbogert
pron
timcobb
One memory model: stacks, and scope exit is the free
What are the ergonomics of this I wonder.
calvinmorrison
sergiotapia
Panzerschrek
Memory is a handful of data stacks that the compiler assigns statically
I doubt this can work well in all cases. Sooner or later one needs proper heap.
cartothug
cardanome
There might be some decent design ideas there but if you can't be arsed to write them down in your own words but instead make me read AI generated slop I am out.
lisp2240
https://www.motherjones.com/politics/2026/10/palmer-luckey-a...
Can't wait find out what terrible crimes against humanity Goose will cause.
alfiedotwtf
skrebbel
groundzeros2015
wegwerper
I find it hard to invest any time in learning about a project if the surface symbols indicate it being a low effort project.
FrankWilhoit
asinglesprinkle
gigatexal
baalimago
rvz
Yet, the author expects YOU to read all of what they didn't write. So I ain't reading all of that.
rfgplk
If anyone is interested, I'm fairly close to finalizing Slang and I'm considering open-sourcing it in the near future. What originally started as a simple register based lang for an embeddable VM turned into an insanely expressive meta?programming language. Full system Fω, expansive whole program reflection (you can reflect on absolutely anything), string memory & logic safety..
You can do stuff like this:
(fn answer () -> i64 0)
(defpass build-answer
(phase source)
(transform (lambda (f)
(fn-with f 'body '(let ((a (arr (42)))) (at a 0)))))
(safety (lambda (goal) (syntax (refl)))))
(run-pass build-answer answer)
(fnmut answer
(transform (lambda (f)
(if (memory-safe? (check-memory (current-program)))
f (syntax-error 'unproved-memory)))))
(defpass inspect-ssa
(phase ssa)
(transform (lambda (f)
(if (memory-safe? (check-memory (ssa-current-program)))
f (syntax-error 'unproved-ssa-memory))))
(proof (lambda (goal) (syntax (refl)))))
(run-pass inspect-ssa answer)
(answer)
or this: (fn next ((i i64)) -> i64 (+ i 1))
(fncontract next
(ensures result (successor (Eq i64 result (+ (old i) 1)) auto)))
(fn read-second ((i i64)) -> i64
(let ((a (arr (0 42)))) (at a i)))
(fncontract read-second (requires (one (Eq i64 i 1))))
(let ((i (next 0)))
(with-proof ((one (Eq i64 i 1) (result-proof i successor)))
(print (read-second i))))
it also supports full inline asm or llvm ir: (var answer 0)
(asm (input rdi 20)
(input rsi 22)
(output rax answer)
(mov rdi rax)
(add rsi rax))
(print answer)
(macroop \ (a) (asm (mov a rax)))
(\ 42)
(print (llvm add 20 22))
(print (->i64 (llvm fused-multiply-add (f64) 6.0 7.0 0.0)))
(llvm fn sum32 ((x i32) (y i32)) -> i32
(block entry
(value answer (llvm add x y (declare (flags nsw))))
(llvm return answer)))
(print (->i64 (sum32 (the i32 20) (the i32 22))))
Even though you can write this by hand, the core idea is to get a very dense and terse language that LLMs can emit while guaranteeing safety and performance.IshKebab
[deleted]
[deleted]
shooshx
FrustratedMonky
Edit Man, two posting about Goose back to back. Carmack alone might be enough to read further.
nnevatie
and scope exit is the free
And doc is the slop.
iacuobos
anonymous908213
mi_lk
geoffbp