Community spotlight: building an efficient and portable programming language with Zig
Building a programming language from scratch is no easy feat. In addition to creating the compiler, defining the standard library, and supporting tools like editors and build systems, you need to design the language — will it be imperative or functional? What systems will the language be used for? Will it have metaprogramming capabilities?
Zig, a member of our Open Source and Nonprofit Program, is a general-purpose programming language and toolchain for maintaining optimal and reusable software. It’s simple yet robust, and has portable SIMD. For the team working on Zig, the decision to build a language that was intentionally designed for their needs wasn’t made lightly. To learn more about what inspired this journey, we sat down with Loris Cro, one of the team members working on the project.
Hannah: How did Zig lang get started and how did you get involved?
Loris: I like to tell a joke version of the origin story where Andrew Kelley (creator of Zig) gets asked at his day job to clean up a C++ codebase so messy that inventing a whole new language is the only way to do it. But even if he really was in charge of a big C++ codebase, the truth is that he started working on Zig for other reasons, mostly related to his interest in real time audio processing. After a few years of working on Zig nights and weekends, he started getting enough donations from the Zig community to leave his job at OkCupid.
In the meantime, I was working as developer advocate at Redis Labs and started getting invested in Zig because it was a beautiful alternative to C for writing Redis extensions. I ended up joining the Zig community, and, in a moment of frustration and boredom at the start of the pandemic, I started Zig SHOWTIME, an experimental take on online events for developers. Soon after, Andrew founded the Zig Software Foundation, a 501(c)(3) non profit corporation, and I joined him as vice president of community.
Hannah: What makes Zig unique?
Loris: Zig has one simple goal: be as efficient and portable as C (or more), and fix all the footguns and the limitations that plague its — and neighboring — ecosystems. We have the advantage of being able to observe what decades of systems programming have produced, and on the path to fix some of these problems, Andrew stumbled upon a few powerful ideas, like compile-time code execution. He does a great job at explaining the essence of Zig in a talk he gave a while ago titled "The Road to Zig 1.0."
Zig is also a truly greenfield project from a social perspective. There is no big company behind Zig, and the non-profit foundation stands on its own legs thanks to a balanced mix of corporate and individual donations. We don't have any big tech company on our board of directors, and frankly, we like it this way. As for where this will take us, only time will tell, but I still remember being awestruck after seeing comptime and how well Andrew was able to direct the development, concluding that the success of Zig would be basically inevitable.
Now we have started to attract some notable names like Frank Denis, a software engineer on Fastly’s OCTO team, author of libsodium, who contributed a full suite of crypto tools for the Zig standard library, and I believe we all share the same impression.
Hannah: How is it possible that Zig applications run faster than C code while also having far better security guarantees?
Loris: Zig is a language with manual memory management and no runtime, like C. This means that Zig and C programs are inherently comparable in terms of performance.
The fight at this point is in the details that guide how the machine code gets generated, and here Zig has a few critical advantages like comptime, which gives to Zig generics and the ability to pre-compute results during compilation. Here you can find an in-depth explanation of how Zig can achieve better performance, but if I had to sum it up in a sentence, I would say that it's often more convenient to write efficient code in Zig than in C.
For safety, Zig features multiple build modes that enable optional runtime checks for undefined behavior (i.e. bugs in the code, like attempting to read past the end of an array), but safety in Zig comes also from a much more expressive type system, especially with regards to pointers. In C, many bugs (and consequently, security flaws) stem from mistakes such as forgetting to check a null pointer, casting a void pointer to the wrong type, forgetting to null-terminate a string or an array, etc. These are all solved problems in Zig by the type system. There is more to say about Zig's safety story but, for the sake of brevity, I'll just say that also in this case it's more convenient to write safe code in Zig than in C.
The convenience argument might sound weak on paper, but when you consider how the global developer community ends up using a tool, convenience is a big factor that has a tangible impact on the quality of the average library out there, which is why Zig tries really hard to make it convenient to do the right thing.
Hannah: What does portability mean for Zig? I read that you can use Zig to develop an application on Windows and instantaneously also get a version that works on Mac, Linux, and even Fastly’s serverless compute environment, Compute@Edge (built on WebAssembly) — all without changing a single line of code?
Loris: Yes! Zig works out of the box as a cross compiler, even for compiling C and C++ code. This is a neat Zig feature that other programming languages like Go can enjoy. Anyway, cross compilation is great but it also needs a bit of planning, since you normally need to interoperate with the target OS: the Zig build system and the standard library are designed to cover most common platforms and they even feature a "bring your own OS" mechanism to let you maximize code reuse from the standard library for platforms not officially supported by Zig.
Zig is a general purpose programming language, meaning that if you have in front of you something that looks like a Von Neumann-ish, Turing-complete machine, you should be able to comfortably program it with Zig. Lately there has been a lot of interest in two such (virtual) machines: BPF and WebAssembly. Needless to say we support both and Jakub Konka, a recent addition to the Zig core development team who is heavily involved in the WebAssembly ecosystem, has added support for WASI to the Zig standard library (he also gave a talk about it).
For Fastly Compute@Edge, you might want to take a look at zigly by Frank Denis, which offers a clean integration with the APIs specific to the platform.
Hannah: How does Zig ensure that applications never crash even with limited memory?
Loris: All dynamic memory allocations in Zig are explicit. There is no global/implicit allocator, like malloc is in C, and every function that wants to allocate dynamic memory is expected to accept an allocator in input. The advantages of this simple practice are astounding: if you want to target a platform where there is no concept of heap or where allocation has special semantics (like WebAssembly, for example), just pass around an appropriate allocator and all code will comply, libraries included! This also means that Zig libraries can cooperate gracefully when you need particular allocations schemes like arenas, for example.
When you encounter an out-of-memory situation, all libraries report the error in a recoverable manner (i.e. instead of panicking), and at that point, if you have an appropriate strategy, the application can recover and continue to function correctly. This is not always easy to achieve but, thanks to this explicit paradigm, it's possible to craft in a webserver an allocation-free path that replies with a 503 error code instead of crashing under load, for example.
Hannah: Should you be interested in Zig if you're not a systems programmer?
Loris: Maybe! I guess it depends on what level of control you want to have over your code. I was mildly interested in learning more about programming, but given my path in life, it never made sense for me to buy into all the accidental complexity of build systems, weird C/C++ footguns, and legacy idiosyncrasies. Zig was for me the simplest way to become a more well-rounded software engineer, and maybe it can be for you too.
Hannah: Is Zig difficult to learn? What are some good resources to get started with Zig?
Loris: Zig is a simple language, and you will be able to become productive in a weekend if you know your way around the basic concepts of systems programming (e.g., pointers and stack vs heap). We're a young project and unfortunately can't yet boast a never-ending list of learning materials, so my recommendation is to follow the “Getting Started” flow on the official website and then move to Zig Learn, which will guide you through the bulk of what you need to know. At that point, you should join one of the existing Zig communities so that other Zig programmers can help you when you get stuck … oh, and if you want to watch Zig talks, check out Zig SHOWTIME of course!