Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

To clarify what this means, since things can get confusing with subtle differences in wordings:

* stage1 is when zig is built from C++ code[1] (the "bootstrap" compiler) using system C/C++ compiler toolchain.

* stage2 is when zig is built from Zig code[2] using stage1.

* stage3 is when zig is rebuilt from the same Zig code[2] using stage2.

Before today, zig would give you stage1 by default, and you could opt in to stage2 using `-fno-stage1`. After today, zig gives you stage3 by default, and you can opt in to stage1 using `-fstage1`.

In all three cases, LLVM is being used. Although Zig has started to fully self-host by providing backends that have no dependency on LLVM, none of these fully self-hosted backends are complete.

Why bother self-hosting? Because:

* Zig produces smaller, faster binaries than C++ that use less memory[4]. Case in point: the new self-hosted compiler is 1.5x faster than the C++ implementation and uses 3x less peak RAM.

* Development velocity in Zig is much faster than C++, and debugging is a breeze in comparison due to Zig being much safer than C++ and having better debug tooling. Similarly, comptime features let us add more assertions and debug checks that are not possible in C++.

* Zig compiles much faster than C++.

* Zig cross compiles better than C++ making it easier to create builds of the compiler for every target.

* The self-hosted compiler does not need a softfloat library dependency to support f16 or f128 operations.

* Zig's std lib data structures are incredibly useful, especially compared to the C++ STL.

There are still many known bugs; not every project will be able to upgrade immediately. See the full upgrade guide [3] for help deciding when and how to upgrade.

[1]: https://github.com/ziglang/zig/tree/master/src/stage1

[2]: https://github.com/ziglang/zig/tree/master/src

[3]: https://github.com/ziglang/zig/wiki/Self-Hosted-Compiler-Upg...

[4]: https://media.handmade-seattle.com/practical-data-oriented-d...



> Case in point: the new self-hosted compiler is 1.5x faster than the C++ implementation and uses 3x less peak RAM.

I am not sure it is comparable: the self-hosted compiler uses a different architecture [1].

[1] https://vimeo.com/649009599/7f1fda43ff


This is true, but I don't think your point entirely fair either. Zig's design lends itself to writing this style of code. In contrast the usual way(s) C++ is used encourages code that makes these types of optimizations hard/impossible. In practical terms, if you wanted to write fast software, the ergonomics of the language allowing you to use the desired architecture matter a lot.

(Also, you're replying to the primary author of Zig and presenter of that talk, if you weren't aware.)


While ergonomics matter, I don’t believe the question is settled at all - for very high performance applications C++ is the answer for a long time to come.


Hi Andrew, sorry for the unrelated question but where can we find the financial reports of the Zig Software Foundation for 2022? The Finances spreadsheet hasn't been updated for the past half a year:

https://docs.google.com/spreadsheets/d/14_ljFHGFXY5NhBhlfjgk...


Isn’t it quite common to only do financial reports only every quarter, 6 months, yearly?


> having better debug tooling

What debug tooling are you referring to? It seems like people just use lldb to debug zig programs?

I'm honestly interested, and searching doesn't turn up good tools as far as I can tell.


Here are some features of Zig that make debugging much easier than C++:

* safety checks (equivalent to UBSAN) when triggered, print stack traces that include source code lines and point to the relevant line/column

* one of the safety checks is using the wrong field of an untagged union. This one is so underappreciated. Wrong union field access costs so much time to debug in C++ but it is a breeze in zig, you get a crash explaining the problem with a stack trace immediately, not a corrupt value that causes problems down the road. untagged unions are core part of the strategy that makes zig fast & have a small memory footprint.

* valgrind client request integration[1]. valgrind "just works" better with Zig than C/C++ because zig emits communicates more information about memory regions that are "undefined".

* error return tracing [2]

* segfaults print stack traces

* std.debug has features to collect stack traces in a compact manner and then dump them at a relevant time [3]

* std.heap.GeneralPurposeAllocator detects leaks and prevents memory corruption from Use-After-Free/Double-Free, making debugging easier

[1]: https://valgrind.org/docs/manual/manual-core-adv.html#manual...

[2]: https://ziglang.org/documentation/master/#Error-Return-Trace...

[3]: https://github.com/ziglang/zig/blob/4a98385b0aa3808ab05a1ebf...


Thanks!


Maybe the runtime safety in debug builds? Like for out of bounds, int overflows, etc. In my zig projects those checks have saved me from using a debugger or valgrind in many cases.


I guess I don't call runtime safety features "debug tooling"? But maybe that's the disconnect here


I think it's funny that I got downvoted for this! For full clarity: I wasn't suggesting that they _shouldn't_ be called debug tooling, just that it's not what I would call that class of feature, and it seems that other people do call it that.


I'd call tools like ASAN and friends debug tooling. I'm not sure if zig has tooling that doesn't have an analogue in the c++ world, but having them built in to the compiler by default is a notable feature.


Right, defaults matter. The fact sanitizers exist is much less of a game changer than the default behaviour being sanitized.

Because C++ defaults are notoriously all wrong, in programming language design you could usually do worse than consider, "Is there an alternative to what C++ does here by default?" and if there is one, choose that alternative as your default because it's more likely to be correct.

Sometimes C++ helps you out, it might have a keyword "do_it_right" and you can just default to that, if you feel people might want the C++ default behaviour, feel free to reserve "do_it_wrong" in case people wanted that, but in many cases they will never ask you to implement the C++ behaviour because it's just wrong. Examples: "const" in C++ doesn't mean "constant" it means "immutable", so, make immutable your default and offer "mutable" as the option. "explicit" in C++ makes constructors need an explicit cast to be used for conversion, once again of course you want that by default but feel free to reserve "implicit" in case some people are sure they need the C++ behaviour.


C++ frameworks pre-standard used to have better defaults, unfortunately there a majority of people voting that would rather have the wrong defaults, and so here we are, and given how ISO works it won't change.

Those that care know where the knobs are to re-enable those proper defaults, given that for some domains, C++ is going to stay around for a while, regardless of the alternatives.


> * Zig's std lib data structures are incredibly useful, especially compared to the C++ STL.

I think elaborating on this could make for a very interesting article. :-)

(I have a guess already at one item, which is MultiArrayList, something that kind of blew my mind when I first learned about it, and is in my opinion a very impressive testament to both the power and ease of use of Zig's approach to compile-time computation.)


I didn't even know about it until today, very impressive. Generic SoA in less than 500 lines of userland code...

https://github.com/ziglang/zig/blob/master/lib/std/multi_arr...


SoA in C++ isn't that long, here's my version (which for sure does not have the utility functions defined here though, but is useful enough for me): https://github.com/celtera/ahsohtoa/blob/main/include/ahsoht...


That's pretty sweet, I didn't know C++ could do this now!

Zig's still got it beat handily in simplicity though -- I think what's really cool about Zig's idea of comp-time evaluation is you get something like the power of C++ with something like the simplicity of C.


> Zig produces smaller, faster binaries than C++

This seems fairly significant to me and makes me wonder how this is possible with all the effort that has gone into optimizing C++


Because they can't do breaking changes and must live with legacy baggage.

While zig can work use modern techniques without such issues


This is wrong because you can strip out C++ code you don't need. Green code doesn't need to worry about legacy baggage


And how do you identify the unneeded code in a compiler?

Which is used all over the world?


A smaller binary will not necessarily be faster - specialization can bloat code size, but having a specific version for a given subtype can be much faster. It’s a tradeoff.


right after that sentence there's a link to a talk that explains one way this is true


We can hardly be expected to watch a 46 minute video on "A Practical Guide to Applying Data-Oriented Design" to find our answer. It seems unpromising on the surface.


Data oriented design is why the thing is faster.


I guess I'll wait for the benchmarks comparing C++ and Zig over a variety of problem solutions to see which one is faster


Congratulations. This is an important milestone.


For Andrew it must feel he's now on the home stretch towards 1.0, finally!


In a previous presentation I think he mentions they are still aiming at something like 2025.


Thanks for the context!

What's the difference between the stage2 and stage3 binary? Does stage1 produce different binaries for the same input compared to stage2/stage3?


Ideally there should be no difference and building stage 3 is basically a sanity check to ensure the compiler is working correctly.


Not quite - what you said is true for a hypothetical "stage4" however there is a distinct difference between stage2 and stage3. While they are built from the same source code, and therefore have the same logic, they are lowered by different backends, meaning they will have potentially drastically different performance characteristics depending on the differences between the stage1 and stage2 backend, respectively.

Related: https://github.com/ziglang/zig/issues/12183




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: