9 ms·
Congratulations with the milestone! Does using Zig over C++ lead to "less memory, and represents a modest performance"? Or was the C++ implementation a bit slo
by erwincoumans 5y ago
Congratulations with the milestone!
Does using Zig over C++ lead to "less memory, and represents a modest performance"? Or was the C++ implementation a bit sloppy? (lacking data oriented design for instance)
Also, what specifically are you most excited using Zig for?
- AndyKelley 5y agoThanks :) The new Zig implementation is certainly more well designed than the C++ implementation, for several reasons: * It's the second implementation of the language * It did not have to survive as much evolution and language churn * I leveled up as a programmer over the last 7 years * The Zig language safety and debugging features make it possible to do things I would never dream of attempting in C++ for fear of footguns. A lot of the data-oriented design stuff, for example, makes use of untagged unions, which are nightmarish to debug in C++ but trivial in Zig. In C++, accessing the wrong union field means you later end up trying to figure out where your memory became corrupted; in Zig it immediately crashes with a stack trace. This is just one example. * Zig makes certain data structures comfortable and ergonomic such as MultiArrayList. In C++ it's too hard, you end up making performance compromises to keep your sanity. Generally, I would say that C++ and Zig are in the same performance ballbark, but my (obviously biased) position is that the Zig language guides you away from bad habits where as C++ encourages them (such as smart pointers and reference counting). As for less memory, I think this is simply a clear win for Zig. No other modern languages compete with the tiny memory footprints of Zig software. Some of the projects I am exited to use Zig for: * rewriting Groove Basin (a music player server) in zig and adding more features * a local multiplayer arcade game that runs bare metal on a raspberry pi * a Digital Audio Workstation
- maleldil 5y agoThanks for the detailed answer! I have more questions, if you'll indulge me: If I understood it correctly, you think smart pointers and reference counting are bad habits. Why? Especially the smart pointers bit. Why does Zig use less memory than other languages? Is it inherent to Zig, or can it be reproduced in other languages?
- lupire 5y agoI think Zig prefers explicit memory management, because allocations may fail and should be handled explicitly, and because automatic deallocations lead to hard-to-predict lifetimes (excess memory usage, and bugs for resource handles that are destructed at hard to predict moments). These are things that a "systems language" programmer should put in the work to do correctly/near-optimally, and not ask the compiler to just do something "good enough", like Python would.
- coder543 5y ago> because automatic deallocations lead to hard-to-predict lifetimes (excess memory usage, and bugs for resource handles that are destructed at hard to predict moments). I don't really feel this is the case in Rust.
- throwawayzr 5y ago
- varajelle 5y agoBut it is. If you have a String on the stack, it's memory is only reclaimed at the end of the scope, while it often could be free'd before. This is especially bad in async code around await point since it means the memory need to be kept alive more than needed.
- coder543 5y agoI disagree. It is substantially and unequivocally better to hold onto memory until the end of scope than to leak memory by default. How can anyone argue that leaking memory is a better default? That’s a ticking time bomb. Maybe someone is so optimistic as to believe they’ll catch every leak before shipping new code? You can easily add a manual “drop” call in Rust at any point if you want to force an allocation to be freed sooner, but I speak from years of experience using Rust for work when I say that Rust’s RAII model is not problematic in practice. I’m not simply speculating or theorizing, and I have professional experience with a variety of languages at all levels of the stack. I personally don’t mind garbage collectors most of the time, but Rust is great when you need more control. In C++, RAII can absolutely be problematic because you are able to easily do things that cause undefined behavior by accident, which is arguably worse than either leaking by default or the mere act of holding onto memory for the duration of a scope. If you can propose a system which cannot be contrived to have any downside, that would be fantastic! In the real world, Rust’s approach to memory management is extremely pragmatic and beneficial. I’m sure someone will eventually improve on Rust’s approach, but “leak by default” isn’t it. I honestly do enjoy following Zig… it is a fascinating language taking a really interesting approach to solving many problems, but its memory safety story is not where I want it to be yet. Leaking memory by default is technically safe, but it's not exactly endearing.
- erwincoumans 5y agoGreat, thanks for those details! I primarily develop using C++ and avoiding pitfalls (smart pointers, exceptions, unintended memory allocations) takes a lot of effort. I enjoy synthesizers (including Eurorack) and looking forward playing with a Zig DAW!
- jcpst 5y agoThanks for all the context. Curious to know more about the concept/design of the DAW.
- aaaaaaaaata 5y agoSeconded.
- Karliss 5y agoCan you clarify about the union part? Did you meant that zig allowed you replacing what would be untagged union in C++ with tagged union in zig? Or does the zig compiler has some kind of debug sanitizer mode which automatically turns untagged unions into tagged unions with checks?
- dralley 5y agoIn the past they've talked about the speed and memory improvements they've gotten from using MultiArrayList in the compiler, storing tags separately from the unions themselves. If you have a union with a size of 16 bytes and you add a tag to that which is 1 byte, a lot of space is wasted due to padding. If you keep the tags in a separate array, both arrays are individually densely packed. Less memory wasted due to padding == less memory use overall and better utilization of cache. But in terms of the implementation, this means working with untagged unions, because the tags are maintained externally.
- tristan957 5y agoIn debug builds, untagged unions become tagged behind the scenes as you described.
- abbeyj 5y agoIf the union is untagged, how can it be determined (at runtime) that you've accessed the wrong field?
- jchw 5y ago> * a Digital Audio Workstation Woah. A little bit ago I went to write a little tool that mucked with the FL Studio FLP format. It was easy enough to guess out the bits that I cared about, so I pretty much just did that using a couple quick projects with specific things in them. However, I did check to see if anyone else had mucked around with the FLP format, and couldn’t help but notice your name. Was pretty surprised as a very curious onlooker to the Zig programming language. You certainly seem to get around :) That’s a little tangential, but I guess I mention it because I was actually wondering if this was ever something you planned on doing given the fact that it was clear you had dabbled with DAW stuff (forgive me for not knowing if you have a more rich connection to music production than just that; I never bothered to check.) A DAW in Zig sounds like a kick-ass idea. I tried to write a sort-of DAW toy with friends in Rust and it was a lot of fun even if it mostly made me realize how challenging it could be. (And also how bad at math I am. It took me so much effort to feel like I could understand FFTs enough to actually implement them.) It makes me wonder if your Zig DAW would be open source? It would be a fun project to attempt to contribute to, if or when it ever came to fruition. Exciting stuff. Congrats on the Zig milestone.
- PaulDavisThe1st 5y ago> It took me so much effort to feel like I could understand FFTs enough to actually implement them.) Do you understand how little DSP is involved in writing a DAW? It has almost nothing to do with DSP and everything to do with application architecture, data management, threading and more.
- jchw 5y agoI think you may be reading too much into what I said; I was working on a DAW-like toy, not a full DAW that uses VST plugins, and because I chose to write DSP code, I had to understand it. I don’t know what a real DAW looks like because I am not a subject expert. That said, Rust seemed pretty promising for writing the audio engine of a DAW due to the memory ownership model. It was relatively easy to come up with a way to architect a very basic lock-free audio thread and feel sure that it was at least memory correct. I have no idea how a real DAW avoids certain pitfalls in the audio thread; lock-free isn’t too hard, but avoiding allocations in all circumstances seems tricky.
- elcritch 5y agoImpressive work getting Zig self-hosting. However: > As for less memory, I think this is simply a clear win for Zig. No other modern languages compete with the tiny memory footprints of Zig software. Is not true at all. There are several other modern languages that compete with Zig for small memory footprints.
- geodel 5y agoWould you tell about those languages or they are left as an exercise to readers?
- elcritch 5y agoSort of left it to the readers and hopefully encourage people to investigate for themselves. It's far too easy to get into "this benchmark vs this benchmark", etc. Memory usage is overall a complicated topic, which I think Andrew's comment doesn't do justice to. Granted the Zig team has done some impressive work, much of the memory usage & bloat in the C++ world comes from real world programs and libraries and the inevitable drift in program architecture over time. However, I could believe Zig's stdlib and culture encourages low memory footprints, but there isn't anything novel in the language that makes it inherently lower memory footprint. Though to name a few languages I'd say that can be directly comparable are Rust, D (esp. BetterC mode), and Nim. Even Julia & Go in the right context. Though honestly I often prefer wasting a few hundred bytes of RAM here and there, even on a microcontroller, for pure convenience. edit: forgot Odin. Another comment mentioned it, though I've never used it. It looks like it's used in production.
- dralley 5y agoZig has a few extra tricks up their sleeves compared to most languages. The ones that come to mind are * MultiArrayList * arbitrary size-integers that make it easy to pack data very tightly * easy access to several special purpose allocators which reduce the need for strategies like reference counting
- 5y ago
- PaulDavisThe1st 5y ago> * a Digital Audio Workstation ORLY? Maybe you can put together a better, faster team (like Presonus managed to do for Studio One), but most current DAWs have been in existence for 20 years or more. Catching up with that is a challenge, and if you don't catch up then it's an interesting toy or half-a-DAW. So why? ps. obviously I am biased.
- reitzensteinm 5y agoThis argument applies equally to programming languages, and Zig seemed to go OK?
- PaulDavisThe1st 5y agoOh yes, it absolutely applies to all programming languages.