3 ms·
> Technically, everything should be passing a memory allocator if the function might allocate. This is how Zig works. > In practice, this too is too much even
by teknico 4y ago
> Technically, everything should be passing a memory allocator if the function might allocate.
This is how Zig works.
> In practice, this too is too much even though it’s infinitely more practical and useful than failable allocations.
It seems to be working well enough for Zig.
- vlovich123 4y agoZig is still relatively immature so it’s hard to judge just quite what software patterns will look like at scale, especially when it leaves the niche of language enthusiasts using it to build stuff. Anyway, [1] shows the pros of this approach. But notice what’s not being discussed. This acknowledges that you have effectively increased the number of error paths in your program and you have to go through quite a bit of effort to get coverage to get some confidence of the behavior. Think of it in terms of ROI. Testing for malloc failures is comparatively expensive. It’s not logic based so you have to do it probabilistically and hope your test coverage works well and the issue happens infrequently (really never) in production. If it happens never, you’ve wasted all that test effort. If it happens very rarely, you’ve still wasted the effort because the probability that your test coverage accurately simulated the failure path is probably fairly low in a common path. It also sounds like zig’s allocator is actually quite dumb. So while making sure to require explicit allocators, what’s a missed opportunity I think: 1. The default program allocator should be passed into main / dlinit. It’s not. This seems like a bad choice. 2. All malloc code in practice, I suspect, ends up getting propagated with try. That means you’re paying a performance cost for all the error checks that never get executed in practice (mostly in terms of icache pressure). Compare with rust where allocation failures typically panic and an optimized application will have panic set to abort leaving unwinding to a background process responsible for error reporting. That’s means there’s no stack unwinding and no error handling code for malloc failures without any change in safety guarantees. Zig is a neat experiment and I understand why it’s proponents like it. I still would never choose it in production at this time: 1. The safety issues means that it’s not thaaat different in profile from C. It’s significantly easier to write safe code, but it’s not easier to audit / make guarantees. 2. Development speed is higher than some thing like Rust but when performance is a bit less critical higher level GC languages (Kotlin, Go etc) seem to make more sense. So it’s hard to see what niche of professional development Zig can fill. Now being a hobbyist language is fine and it’s doing a lot of interesting things to show the ergonomics of other choices we wouldn’t otherwise see. But I would personally be very careful about making assumptions like “it seems to be working well enough for Zig” until it gets into the hands of a broader community. Things that seem to work OK earlier can shift drastically at scale. [1] https://www.lagerdata.com/articles/testing-memory-allocation-failures-with-zig https://www.lagerdata.com/articles/testing-memory-allocation...