Zig asserts are not C asserts
I recently came across a piece of code in a Ziggit.dev post that gave me pause: pub fn putOne(q: *@This(), io: Io, item: Elem) Cancelable!void { assert(try q.put(io, &.{item}, 1) == 1); } pub fn getOne(q: *@This(), io: Io) Cancelable!Elem { var buf: [1]Elem = undefined; assert(try q.get(io, &buf, 1) == 1); return buf[0]; } …which led me to ask the following: Just a quick side quest: Doesn’t the assert here risk put and get calls being optimized away?...
Embedding machine code in Zig
Linux and macOS Rosetta notes Assembling Calling from Zig A larger example with fast memcpy and syscalls Using assembly code with Zig is usually done via inline assembly, or by linking to object files produced by assemblers. This post explores a third way: write the assembly in a separate source file, run an assembler, and then embed the resulting machine code using @embedFile Linux and macOS Rosetta notes The code is tested on macOS, but also works with minor modifications on Linux (primarily the syscall number)...
Cache Me If You Can
How come making a struct in Zig less densely packed can give a huge performance increase, with far less variability? This post takes a look at false sharing and how it can be caused by packed data layouts and unintended field reorderings. While packing data closely together can be beneficial due to cache locality, false sharing must be taken into account when designing optimal data layouts for multithreaded programs. False sharing occurs when the data layout is at odds with the memory access pattern, namely threads updating thread-specific data that happens to fall on the same cache line....
Async CPU bound workers in Zig
Zig has async/await support, which is typically used for IO bound operations. In this article, however, we’ll use async/await to simplify writing a simple concurrent worker. Goal: use all the cores on the machine to find a randomly selected 64-bit number whose lower N bits are all cleared. How it works Instead of manually spinning up threads, we’re just going to use async/await, along with pub const io_mode = .evented; which informs the standard library to use a non-blocking event loop....
Bio - All your parentheses are belong to us
In a previous Zig post, we wrote a small postfix notation calculator. This post takes a look at something that take prefix notation to the extreme: a new language in the Lisp family called Bio The goal of this project is to make it easy to play around with Lisp dialect ideas and to make a well-documented and readable Lisp interpreter for others to learn from. This article aims to point out some key areas people stumble on when writing a basic Lisp interpreter....
Some notes on using Zig with Valgrind
Zig has a very nice built-in memory leak detector in its General Purpose Allocator (GPA), but sometimes you have to break out Valgrind to get to the bottom of things. When I first did this, I ran into a couple of problems, which I’m jotting down here along with solutions. Thanks to mikdusan, ifreund and lemonboy for helping me figure out various issues First of all, to get Valgrind going with Zig programs, you’ll have to switch to the C allocator....
Zig scripts?!?
Look at this beauty: //usr/bin/env zig run "$0" -- "$@" ; exit const std = @import("std"); pub fn main() !void { std.log.info("Awesome, it works\n", .{}); } Let’s make it executable and run it: chmod +x myscript.zig ./myscript.zig info: Awesome, it works This works because // is a comment in Zig, and just an empty path component as far as the shell is concerned Thanks to squirl for making the argument passing syntax more robus
A surprisingly capable RPN calculator in about 100 lines of Zig code
Summary: Reverse polish notation is awesome Zig is awesome Before solving quadratic equations and diving into code, let’s see if 2 + 2 is still 4: 2 2 + M0 = 4 Phew! Notice how every answer is placed in the next available memory slot. This will be useful in our next example where we calculate the two solutions to a quadratic equation: First we input the known values so these get memory slots we can reference, rather than repeating the constants....
Running Zig binaries on a KaiOS device
The goal here is to: Cross-compile a Zig program Root a KaiOS device, and then install and run the cross-compiled program on the device We’re not making a GUI app or anything here, just a small “Hello world” program that we’ll cross-compile and run on the device. All sorts of interesting things can be done from this point on. I’m using Android’s adb to push files to the device and to get a shell, so you’ll have to install that first if you wanna follow along....