Live data from Hacker News

Zig and Rust

matklad.github.io

141–150 of 247 posts

Re: Zig and Rust

#141

Earlier quoted context omitted.

> I think unless you have some precise needs about memory allocation, and want to control exactly where when and how memory is allocated, it is hard to argue in favour of Zig. I do have a hard time to think of use cases other than embedded microcontroller work where that matters nowadays. That said, I suspect that while they could have written TigerBeetle in Rust (no_std does not assume the existence of an allocator)…

> I do have a hard time to think of use cases other than embedded microcontroller work where that matters nowadays. People keep saying things like this and software keeps getting more bloated and shittier. It is difficult to believe there isn't a correlation.

The issue is not always garbage collection. The issue is, as others have pointed out, not having to think about it (memory & cycles.) But this also ties very much into another thing about many modern applications: excessive reliance on third-party packages, many of which are written with (or without) constraints and features that aren't always a match for the core application. It's very easy to blow out your memory use and runtime costs this way.

And in this respect Rust could be vulnerable, because Cargo.toml makes it way-easy to pull in a huge tree of transitive third party dependencies without even thinking about it.

Re: Zig and Rust

#142

I tried zig after reading so many HN articles and I am not impressed. You have to remember to free after each allocation. The language is supposed to be simple, yet there exist try, catch, defer, errdefer. Rust enums make defining errors so simple with arbitrary payload. Using data structures in rust is much nicer. I think unless you have some precise needs about memory allocation, and want to control exactly where w…

"(Zig's) collections are not parametrized by an allocator, like in C++ or (future) Rust. Rather, an allocator is passed in explicitly to every method which actually needs to allocate. This is Call Site Dependency Injection, and it is more flexible.' I'd once considered the idea of having "space" as a type. Space is an array of bytes, and it cannot be read or written. Constructors take in "space" and turn it into an o…

This is exactly how C++ work.

   union {  MyObject space; }; // just a bunch of bytes
   MyObject * myObject = new(&space) MyObject(); // invoke the constructor
   myObject->~MyObject(); // invoke the destructor
   
If you want RAII use some wrapper like Optional.

Re: Zig and Rust

#144

I tried zig after reading so many HN articles and I am not impressed. You have to remember to free after each allocation. The language is supposed to be simple, yet there exist try, catch, defer, errdefer. Rust enums make defining errors so simple with arbitrary payload. Using data structures in rust is much nicer. I think unless you have some precise needs about memory allocation, and want to control exactly where w…

> ...and want to control exactly where when and how memory is allocated... Isn't this the whole point and the reason why manual memory management is still a thing - and actually getting more important with the ever widening CPU/memory latency gap? There simply is no silver bullet for memory management, you can either have high performance or automatic memory management, but not both. (vastly simplified of course - bu…

Reference Counting (including a secondary counter for internal cycles) is your silver bullet.

The only hairy issue then becomes multiple processors needing to update the reference counter, where the count has to go in an out of the various processor's cache. One possible way to resolve that is to have a per-thread reference count, and only change the globally shared reference count when a per-thread's reference count would reach 0.

Re: Zig and Rust

#145

Earlier quoted context omitted.

There's the third option, which is what Rust and C++ do by default, where types have destructors that are run when the value goes out of scope, but also have mechanisms to be activated manually at a precise moment if you know what you're doing and have specific needs.

RAII is not a silver bullet. RAII wants to have neat recursive ownership and cleanup of everything, which is undoubtedly a nice model, but sometimes in low-level code you have to choose between nice recursive ownership and performance. For example, Protocol Buffers are trees of objects. Originally they were simple and had recursively-owned, heap-allocated nodes. But it turns out that traversing and deleting a big gra…

There is no incompatibility between RAII and arenas. RAII doesn't require heap allocation.

Re: Zig and Rust

#146
post #91

Earlier quoted context omitted.

> There simply is no silver bullet for memory management, you can either have high performance or automatic memory management, but not both. RAII is the way.

RAII for memory management implies that destructors free owned memory, which can quickly cascade out of control for complex objects (e.g. you still need to think very carefully about memory management).

You are right in the sense that for high performance applications you still need to explicitly take into consideration memory allocations, allocators, indirection, into consideration. RAII helps you implement your preferred design, but it doesn't make you ignore the details.

Re: Zig and Rust

#147

Earlier quoted context omitted.

This is a good comment that I hope can help other readers manage their expectations. Zig is verbose and low-level and, to like it, you have to appreciate simplicity and what it means to have control over tiny details. If you don't like either thing, then Zig will not bring anything particularly interesting to the table for you.

Yes to the appreciating simplicity bit, but if you go to Rust expecting to not sweat over having to control tiny details you are in for a ride.

To be honest I just clone and unwrap everywhere when writing the first iteration. If I care more, then I'll refactor to remove unnecessary clones. I really haven't felt the pain of the borrow checker like some people say.

Re: Zig and Rust

#148

Earlier quoted context omitted.

Which is why low level languages like C++ and Rust make RAII the default in their standard library (easy, simple), but it's still completely possible to manage the memory on your own if that's necessary for the task at hand. Having easy defaults with the capacity to do everything by hand if you need to is the most flexible system.

The last time I looked (which has been a while, I admit), that meant that you had a very hard time using any of the standard library types with an arena or whatever form of management you used for your specialized code. What does that look like now?

If you're willing to write Nightly Rust, you can use the allocator_api feature to have the types which allocate take an allocator parameter so e.g.

Vec::with_capacity_in(10, arena_allocator)

... obviously user-defined types don't know these allocators exist and so may not provide a way to pick which allocator is used, whereas in Zig this is "always" how it worked.

For stable Rust, until/ unless allocator_api is stabilized, you will need to replace the global allocator for your code with one that has the desired behaviour. That applies to everything using an allocator, but on the other hand you lose considerable flexibility.

Re: Zig and Rust

#149

Earlier quoted context omitted.

It's still bizarre though that Rust is capturing such ridiculous mindshare. I suspect it has a lot to do with web developers being plugged into Mozilla, and Mozilla spending quite a lot on Rust development and marketing. And Zig may be being roped into it. It seems to be a temporary low-level programming zeitgeist driven by YouTube and Reddit recommendation algorithms to an audience that has never done it and probabl…

> It's still bizarre though that Rust is capturing such ridiculous mindshare. I don't think it's that bizarre. The two big headline features that bring Rust such popularity are: #1 "70% of bugs are memory-safety bugs" [1] and Rust can help solve those, and #2 C/C++ have a couple of package manager solutions - none of which have critical mass and Rust "comes with" cargo. Those two make me really eager to continue expe…

> This is some weird gatekeep-y kinda thing. Most of us didn't start out with low-level programming. Wouldn't it have been odd and frustrating for someone to tell your younger self that you have "never written C and probably never will"?

I'm not making any sorts of demands about who should be able to program at a low level, but I'm being realistic about who will. I have an intuition that I do not think is unreasonable that the vast majority of the 20- to 30-something crowd that recently learned JavaScript in a boot camp would bounce off of systems programming hard, while a handful might discover it's what they should've been doing all along.

The young are not who I'm thinking of at all. Someone with time and neuroplasticity can and should be spending that time toying around with C, Haskell, and Lisp to expand their understanding as much as possible.

Re: Zig and Rust

#150

Still not convinced that memory semantics are critical in the vast majority of domains. Incredibly fast speeds can be achieved with simple GC and RC for short-running programs, and programs with sustained runtimes can rely on generational GC. These methods have the advantage of nearly eliminating the need for memory semantics, leaving only business logic behind. The best example might be Nim, which drastically reduce…

You can get the idea that a GC has minimal impact on performance when you just look at things like how fast the GC runs, or what % of time is spent in GC, but that only represents a portion of performance implications, there are lots of indirect effects: 1. More memory is used, which means more CPU cache evictions happen 2. There will be things the language won't let you do, because it is garbage collected 3. There w…

> More memory is used, which means more CPU cache evictions happen

The first part is true, and the second part is sort of true, but it may or may not matter. The order of magnitude speedups that good cache usage can cause only happens when you are having a small hot loop working over a huge amount of data that has an easy to guess access pattern (e.g. serial). I am not convinced that your ordinary program would have too many such loops and thus that it would have a huge speed up were it rewritten in C from a managed language.

> There will be things the language won't let you do, because it is garbage collected

There are always escape hatches

> There will be extra FFI costs, like when making OS calls or calling into other languages

Do you mean like GC barriers and such?

But we do agree on your last paragraph, and sure low-level languages will always be needed. But the niche where they are irreplaceable are very small, if we are pedantic OS and games are also not necessarily to be written in them (see Microsoft’s singularity, the latter has plenty of examples)

Post reply on HN