I never completed the Odin / V implementations since their standard libraries didn't have argon2 (a requirement for me).
Of the group, I liked Odin's syntax and feel best. Hare was also very nice. But Zig's optimized binary sizes were unbeatable. 96KB vs 500KB for Hare and 2.5MB for Go.
Zig's standard library and tooling are impressive. Personally, I wish more projects were written in Zig instead of Rust since Zig doesn't seem to have the package explosion problem that Rust has.
HTTP, for example, can go into Zig's standard library, whereas C or Rust cannot do that. This helps control package explosion.
Zig will presumably have the same care about backward compatibility once it becomes stable.
Just like Zig's decision it is a double edged sword: on one side you can avoid compiling code that will not be needed. However on the other side you make incremental compilation worse, since you will have to recompile it more often.
> HTTP, for example, can go into Zig's standard library, whereas C or Rust cannot do that.
Rust _could_ put HTTP in the standard library, the dead code would simply be removed when linking. The reason it's not in the stdlib has more to do with the fact that:
- it would need to be supported by a team that's already overworked - it would need to be supported indefinitely, so it would have to be the right interface on the first try.
This effectively prevents any big and complex feature from making to the Rust stdlib.
> This helps control package explosion.
Arguably it helps controlling the number of "packages", but not the amount of code in those packages. If I split a "package" in 4 crates in Rust to get better compile times it's still mostly the same code, but you now see a number 4 times bigger.
It's not just about the number of bytes.
Zig moves fast with it's BFDL structure, Rust moves slow with its committees, and both are by design. I'm excited to watch the Zig standard library evolve quickly, especially once the language has settled things like I/O.
Yes they can? If you look at old-timey C libraries, for example (standard or otherwise), you’ll see that they have the relatively awkward structure of one public function per file. That’s an adaptation for static linking, which only pulls in the object files that contain symbols required by the program, thus it’s beneficial to make the object (and therefore source) files as small as possible. Yes, the compiler still needs to produce of these object files, but unlike with Zig it only needs to do so once per (separately compiled) library.
An inferior emulation of the same trick, popular in the embedded community, is passing --gc-sections to ld, but unless you’re very careful something will fall off that you weren’t planning on. (Of course C++ makes things more complicated, as always, so you may be forced to use this option.)
Glibc’s (and specifically Drepper’s) aversion to static linking did us all a disservice by making static libraries less popular.
This does not mean that there isn’t some benefit to whole-program compilation. E.g. GCC can derive assumptions about a non-exported function’s arguments and propagate them into the function’s body even if it does not decide to inline it (look for “constprop” symbols in objdump). So that’s also a thing that people do, in particular in gamedev where the somewhat stylized source code structure it requires is less of a problem. (Game developers confusingly call this a “unity” build—personally I prefer the term “amalgamation” used by Lua and SQLite.)
> so Zig has no problems adding richer functionality to its standard library.
That’s orthogonal to both
- whether to compile from source in every compilation unit or to compile once, and use (shared) libraries,
and to
- whether to provide the standard library as a single unit, as is typically done in C, where it is a (shared) library, or as multiple interdependent smaller units as in Zig, where the standard library contains multiple source files.
> HTTP, for example, can go into Zig's standard library,
The claim “you only compile what you need” also is incorrect. Zig’s source files (luckily) aren’t fine-grained enough to support that.
For example, https://github.com/ziglang/zig/blob/master/lib/std/http/Clie... contains stuff that not every user of that module will need, for example connection pools and a function to flush a buffer.
The compiler may not generate code for such unused definitions, but it has to parse them, if only to figure out where the next definition starts.
Zig not even type checking some code when compiling felt a bit off but now I just try to make sure all code is at least being smoke tested, so I don’t get random compilation errors down the line
Most languages I work on (Rust, Python, JavaScript, Haskell), have a huge number of packages.
Boost is a great example of this, since it does a ton of different things, but the boundaries between components are not quite as obvious as having a "dependencies.lock" to look at. Tokio has a ton of different packages but often you only need a few of them.
I was told the std.http.* isn't meant to be used for production servers but its nice that i now have a drop in zig file that contains a very very... bare bones static file server i can add to zig projects that might need it.
Regarding branch profiling, all arm64 (M1+) cpus support these counters: - BRANCH_CALL_INDIR_MISPRED_NONSPEC - BRANCH_COND_MISPRED_NONSPEC - BRANCH_INDIR_MISPRED_NONSPEC - BRANCH_MISPRED_NONSPEC - BRANCH_RET_INDIR_MISPRED_NONSPEC - INST_BRANCH - INST_BRANCH_CALL - INST_BRANCH_COND - INST_BRANCH_INDIR - INST_BRANCH_RET - INST_BRANCH_TAKEN
afaik there is no limitation to implementing the fetching of all these counters based on ibireme’s research on kperf. btw, forked "poop" already can fetch BRANCH_MISPRED_NONSPEC.
turnsout•21h ago
Side note, the CSS is broken for me in Safari—I get this error: