7 ms·
Gossamer: a Rust-flavoured language with real goroutines and pause-free memory
- quotemstr 4mo agoGossamer has a cycle collector and eager reference counting. Good luck dropping the last reference to a 10,000-node graph, especially if cyclic. That means it doesn't have "pause free" memory. If you want pause freedom, go use ZGC or another modern GC on a modern VM. I just can't take seriously this spate of languages that ignore the past 30 years of research into automatic memory management. We have multiple open-source pauseless miracles GCs right there before our eyes, yet it's the trendy thing in language design to foist memory management on users. You don't even have to use a big VM if you want good GC. Go use MPS. Lots of options out there, even if you want to implement your own VM.
- platinumrad 4mo ago> We have multiple open-source pauseleses miracles right there before our eyes Is this meaningfully true in a practical sense? I've been writing code with soft real-time requirements and I don't think your notion of "pauseless" suffices. And if these miracles are open-source and right before our eyes, why do languages like Crystal and D still use Boehm?
- quotemstr 4mo agoThe charitable explanation is the authors lack the time to rebase onto something more modern.
- platinumrad 4mo agoYou seem to have a very low opinion of other people. If these miraculous collectors are so generally applicable, why are very smart people putting effort into things like Perseus?
- quotemstr 4mo agoSmart, honest people can have sincere and earnest disagreements. I believe the manual-memory-management people are mistaken. That's not to say they're stupid: it means I believe they're going down the wrong path, as smart people have done since time immemorial. I wish them all the best. That said, I must wonder what other innovations they reject if they insist that GC is unacceptable.
- lstodd 4mo agoWe insist that GC is unacceptable only because we insist that uncontrollable latency is unacceptable.
- LoganDark 4mo agoThe entire concept of a pauseless GC is that you have no uncontrollable latency. The GC can run on a background thread with zero stop-the-world. Of course, this assumes you're in a preemptive environment with access to other threads, etc.
- yunuskusak 4mo ago@LoganDark You're right, as long as there is an object graph to scan, 'uncontrollable' latency is an inherent trade-off in GC-based systems. I’ve taken a different route with a C++20 execution engine that eliminates the object graph scan entirely by using pre-allocated, static memory pools and lock-free SPSC structures. It's essentially moving from 'managing GC pauses' to 'deterministic, zero-allocation execution'. Have you ever benchmarked your systems against a lock-free architecture that bypasses the allocator on the hot path?
- LoganDark 3mo agoThe lock-free architecture that bypasses the allocator on the hot path is called `alloca`. Many mainstream compilers, and nearly every language that is not C, seemingly haven't properly supported it for years.
- gomoboo 4mo agoD uses a homegrown GC not Boehm: - https://dlang.org/spec/garbage.html https://dlang.org/spec/garbage.html - https://dlang.org/blog/2017/03/20/dont-fear-the-reaper/ https://dlang.org/blog/2017/03/20/dont-fear-the-reaper/
- nu11ptr 4mo ago> why do languages like Crystal and D still use Boehm? Languages use Boehm for exactly one reason: it is easy to shim into an otherwise manual memory system (it was designed for use in C/C++). I mean no respect to its authors, but using Boehm in production is the worst of all worlds: slow allocations (free list allocator), poor cache locality, and not precise (so you can expect memory leaks). If you are going to do a GC language you want: 1) precise 2) bump allocator 3) compacting collector 4) generations. Essentially you want to allocate fast, only touch live objects (most objects die young), compact them for locality, and only process objects each cycle of similar age. There is a huge amount of engineering that goes into a state of the art collector, but those are the basics.
- mappu 4mo agoThis is all true but is a somewhat Java-flavoured perspective i.e. generations ties you into a moving collector, which ties you into barriers and complicates FFI, which is not always the right tradeoff. A non-fragmenting allocator goes a long way to alleviating the need for compactions too.
- nu11ptr 3mo agoNot necessarily Java-flavored, but internally vs externally focused, yes. More difficult FFI assuming that is the exception not the rule, and that the language itself takes precedence. Write barriers are also not a given if using segmented heaps. Many ways to do this and no single right way. Memory allocation scheme isn't something that is just bolted on, but needs to be aligned to the rest of the language. For example, Java needs such fast allocations and good GC because it does almost no inline allocation whatsoever, so without the best GC on the planet, it would be a lot slower than it is. Contrast this with Go, which has a solid amount of inline allocations, and hence, can get by with a much slower allocator (~3-4x slower by my measurements) and a more basic mark-sweep allocator since the memory pressure is solidly less.
- iyn 4mo ago> We have multiple open-source pauseless miracles GCs right there in front of us Can you share some links/references?
- quotemstr 4mo agoZGC is extremely good work. https://wiki.openjdk.org/spaces/zgc/pages/34668579/Main https://wiki.openjdk.org/spaces/zgc/pages/34668579/Main > ZGC performs all expensive work concurrently, without stopping the execution of application threads for more than a millisecond. It is suitable for applications which require low latency. Pause times are independent of the heap size that is being used. ZGC works well with heap sizes from a few hundred megabytes to 16TB. Go's GC is also very good: https://go.dev/blog/greenteagc https://go.dev/blog/greenteagc. V8's Orinoco is also pretty good now. It's improved a lot over the past decade and is now mostly-parallel. (A decade is about how long one of these things takes: high-performance GC is hard.) I'm also a fan of MPS: it's a big of dark horse because it's more a GC construction kit than a ready-to-go GC, but it's fast and flexible, and I'd start with it any day over Boehm if I were making a VM from scratch.
- platinumrad 4mo agoIf I were writing this language, I'd probably just compile it to Go, although that means Rust extensions would either incur cgo costs or have to be replaced with Go extensions.
- phplovesong 4mo agoYou just described http://www.lisette.run http://www.lisette.run
- mappu 4mo agoCgo is cheap these days, don't worry about it. It's barely more expensive than a direct function call but, not so you'd notice unless it's in a hot loop. At which point the lack of cross-language inlining is your real problem.
- smj-edison 4mo agoThe one plus I'll give reference counting is it still takes the cake for interoperability with C. Which is only important if you need good interoperability, but when you do, tracing GCs don't play nice.
- poulpy123 4mo agoSorry but the name means bitterkid in french, I can't get over it :D
- ambicapter 4mo agoI'm french and had to think about it for a little bit.
- mkl 3mo agohttps://en.wiktionary.org/wiki/gossamer#Noun https://en.wiktionary.org/wiki/gossamer#Noun
- throwrioawfo 4mo agoThere was once a time when I'd see a page like this and think "wow, must be a great project with such a polished website". Now, it's just a neutral or perhaps even very slightly negative signal (especially the em-dash in the very first line of the page). Anyone able to tell me if this is a project actually worth paying attention to, or just another raindrop in the current monsoon of slop?
- klardotsh 4mo agoSomewhat with you on this. I got slightly excited for a brief moment, but then the site starts to scream "an LLM threw this together super quickly" which doesn't spark joy at all. I then started digging into the code examples and quickly determined that nothing about this project is for me, even as a fan of Rust and some of its influences it has on recent languages. That web routing example is absolutely gross to my eye, for example. Different strokes for different folks - my own thoughts on language design (I'm hacking on one in private over the past several years, maybe one day it'll be shareable) would probably make some folks have a similar reaction, despite taking a wildly different approach than here. But it does suck to see Yet Another Vibe Looking Site hosting a language that feels like Yet Another Flavor Of Similar Stuff. Really looking forward to a language that wildly shakes things up in a usable way, and has a lot of care put into the DX... this one did not check that box for me.
- charlieflowers 4mo agoThe language choices demonstrate excellent taste though.
- mattkrause 4mo agoThe web-routing thing is especially gross because a different example shows off pattern-matching.
- bscphil 4mo agoIt's clearly vibecoded if you look at the commit history.
- 4mo ago
- rohitsriram 4mo ago[flagged]
- samuell 4mo agoGlad to see more languages adopt true goroutines [edit: lightweight threads or fibers] with M:N scheduling. Surprised more haven't. Among compiled language I'm only aware of Go and Crystal off the top of my mind.
- kccqzy 4mo agoHaskell does too. And it predates Go by a large margin, such that calling it goroutine is weird. And within Google, the C++ implementation fiber also predated goroutines. It really shows that this is more of a library feature rather than a language feature.
- Balinares 4mo agoIn fairness, goroutine is far catchier than >>=<%>.
- throwaway17_17 4mo agoI agree with your objection to treating goroutines as the baseline implementation of fibers. However, I would disagree with categorizing the feature as a library feature vs a language level feature. In “low-level” languages (C, Rust, Zig, C++, etc) the ability and option exists for having ‘green threads’ with most of their commonly assumed characteristics be library based constructs (although see [1] for why that’s not true for threads in general ). However, almost all managed/runtime-required/scripting/“high level” languages lack the facilities to implement almost any realistic types of fibers and any FFI based implementations are going to suffer severe syntax integration issues (I am assuming somewhat on this point). TL;DR Green threads are on a library feature for low level languages. 1 - Threads Cannot Be Implemented as Libraries (Boehm 2005), https://dl.acm.org/doi/10.1145/1064978.1065042 https://dl.acm.org/doi/10.1145/1064978.1065042
- ktpsns 3mo agoAnother thing is the stdlib integration of goroutines. We see this in Python where various generations of paradigms kind-of coexist. Golang built their goroutines into the heart of the stdlib which puts it IMHO in a special position.
- lstodd 4mo agoIDK what's the fuss. m:n scheduled by io is .. 2000s-era. The implementation was so obvious in like 2005, that even I patched then Python 2.6 in, so we at my then company could get rid of Twisted. Also let you remind that M:N scheduling was the FreeBSD's pthread implementation for quite a bit too long. No, it didn't play well with MySQL at the time.
- rsyring 4mo agoIf you are interested in Gossamer, you may also be interested in Lis, which is Rust flavored and compiles to go: https://github.com/ivov/lisette https://github.com/ivov/lisette From their readme: Safe and expressive: - Hindley-Milner type system - Algebraic data types, pattern matching - Expression-oriented, immutable by default - Rust-like syntax plus |> operator and try blocks - Go-style interfaces, channels, goroutines Quietly practical: - Interop with Go ecosystem (WIP) - Linter, formatter, 250+ diagnostics - Fast incremental compiler, readable Go - LSP for VSCode, Neovim, Zed, Helix, GoLand
- etaioinshrdlu 4mo agoI would also like to toss my project into the ring, which also allows mixing most real-world Rust & Go packages together, on runtime & syntax compatible level. https://github.com/deepai-org/omnivm https://github.com/deepai-org/omnivm Pardon the sloppy readme - it actually does work :)
- jeremyjh 3mo agoYou were so preoccupied with whether or not you could, you didn't stop to think if you should.
- pantsforbirds 4mo agoI'm fairly sure the code snippets aren't equal in the last python example: ```python names = sorted({name.lower() for name in users if name}) ``` vs. ```gossamer let names = users |> iter::filter(|n: String| n.len() > 0) |> iter::map(|n: String| n.to_lower()) |> iter::sort_by_key(|n: String| n.len()) ``` Python is sorting a set (unique values only), but I'm not seeing a unique or set approach for gossamer.
- mkl 3mo agoAlso the Python sorts by string content and the Gossamer sorts by string length.
- IshKebab 4mo agoIt's only 2 months old. Clearly vibe coded. Still, kind of crazy what you can vibe code now. Also the actual language design seems quite nice. I'd love something like this that was embeddable (and not vibe coded). There are basically no good easily embeddable languages. Everyone used Lua but it sucks.
- cure_42 4mo agoWhy not embedded rust?
- mkj 4mo agoInteresting idea, but wouldn't an embedded language normally be interpreted/runtime editable? I guess you could do it shipping a rust compiler, but it'd be big. A bit like Numba?
- throwaway17_17 4mo agoIf this is a joke, I actually chuckled. But, maybe this is a terminology issue conflating an embeddable language with a language used for embedded programming. I think this is one of those CS issues prevalent for non-native English speakers (especially when those devs are relying on translations of text without LLM style semantic analysis of the source). The first refers to the shipping of a language interpreter within the executable of a program, where that interpreter then processes “scripts”, data files, high level non-programmer editable object attributes or behaviors, etc. The most prevalent example of this is shipping a Lua interpreter inside a video game for interpreting hot reloadable asset scripts. The second usage of embedded is the implication that code is being run on a microcontroller or SoC ‘embedded’ within some other product or device.
- jeremyjh 4mo agoThis is exactly the language I've been yearning for - the exact motivations and intersection of features that would be the sweet spot for me. Kotlin without the Java baggage. Rust but with automated memory management and without async bifurcation. Go with a modern type system. Swift but with green threads and a linux community. Haskell without the hair shirt. Elixir with a full type system and native performance. But yes there are some flags others have mentioned, I won't repeat them. "goroutines" ? Even on the off chance this project is not entirely vibe coded how could it ever build an ecosystem? How can any new language? All the libraries would be suspect for the same reason this repo is. The agents won't know anything about it, no one will believe it can get momentum so it won't.
- veegee 4mo ago[dead]
- Jtsummers 4mo agoI can't figure out the point of having both go and spawn. `spawn` seems to be an ordinary thread spawning mechanism, generating a handle that you can join with (but not cancel? can't find that for certain, it's not actually in the tour but is in the SPEC.md). `go` inherits all the problems of go routines. You can't join with it, you can't cancel it, you have to build other infrastructure on top of it to achieve those effects. As neat as golang was 17 years ago when it came out, this was and still is a major weakness of the language which has resulted in the community developing conventions (now standardized in the go standard library and particular usage patterns) around how to deal with it. I don't get why you'd half fix it (by introducing spawn) but then leave it in anyways. Just let the handle from spawn be ignored and you remove that particular footgun (it becomes a choice to ignore it, which still causes problems but at least the programmer chose to shoot towards their own foot).
- reocha 4mo agoThree things stick out to me on https://gossamer-lang.org/docs/migration/rust/ https://gossamer-lang.org/docs/migration/rust/ * No user macros at all. Six fixed format! / println!-family macros expand at parse time. - Meta programming is incredibly important in rust. * (unsafe is) Forbidden at the language level. No unsafe keyword in Gossamer source. std is safe-Rust too. - No low level programming then. * No move semantics. Non-trivial values are heap-allocated, reference-counted, and shared by reference; primitives are copied the same as Rust. - Again, no low level programming. Calling this rust flavored (or even a systems programming language) seems a bit bold.
- bfung 4mo agoTotally agree, misleading. The syntax looks like rust, but esp w/the memory management model (reference counting), it’s going to have more overhead than rust when it’s running, more like Swift or at worse, Python.
- deleted 4mo ago[deleted]
- charlieflowers 4mo agoOriginally I replied here that I thought you were both missing the point (but I was wrong). I wrote: It has a garbage collector and goroutines, so clearly it is not trying to be a systems programming language. Then ... I saw that it does indeed pitch itself as a systems programming language. So, I guess you both are right. If Gossamer were to drop that claim, then I'd say it looks impressive to me. I have often wanted this particular mix of language features.
- sdicker 4mo agoThis post reminded me of Swift– a modern high-performance language that uses automatic reference counting. Its got a REPL and compiles via LLVM. It does trade goroutines for something with a little more safety built in.
- Zak 4mo agoI'm seeing a big red flag here for what purports to be a systems programming language: it isn't used for its own compiler. The compiler is written in Rust. A systems programming language should be able to self-host its compiler. Writing compilers is one of the canonical systems programming tasks. Making that happen may not even be hard in the LLM and LLVM era as it's a fairly mechanical task for an LLM to execute, and you can output textual LLVM IR to bootstrap on any architecture LLVM supports.
- throw10920 3mo agoDoes it have a REPL? That's been one of the greatest sins of Rust - designing a compiled language after 1990 that doesn't have an interactive REPL.
- valentynkit 3mo ago[dead]