What's everybody working on? (September Edition)

Demo thread! Share screenshots, videos, sound clips, stories, asciinema recordings, link a blog post you made, or just explain what hobby project you’ve been working on lately. Ambitious, well-scoped, or anywhere in between, your efforts are welcome in this thread.

If you posted in a previous thread, give us an update! Are you tackling a new challenge? Still wrestling with the same problem space? Have you moved on to something completely new?

Previous threads:

So, what’s everybody working on lately? :slight_smile:

15 Likes

I am having a great time contributing to Cubyz. It may not be the best example of zig code, but it’s nice working on something with so many different areas of code to explore. Next month we can celebrate the 1 year anniversary of the 0.0.0 release.

Currently I am working mostly on the permission system for commands and the core system for accessories (after which you can hopefully finally heal in Cubyz!)

4 Likes

I am working on a lisp! I’ve always been interested in lisps and programming language development but I’ve never gotten past the basic arithmetic tree-walking interpreter stage for some reason. My first project in Zig was Crafting Interpreters so it only seems right that I actually finish something.

I want to learn about intermediate representations, ir optimization, and type systems so I’ve decided to do a bytecode vm. A lisp-like probably isn’t the best language to gather an understanding of static type systems but oh well hopefully I’ll learn something.

As for the vulkan renderer in my previous posts, I implemented a semi-functioning scene system and blinn-phong lighting. Then I got annoyed at attempting to turn the semi-functioning scene system into a functioning scene system and lost motivation. I’m proud of myself though because that’s the farthest along I’ve gotten in a project before and I learned a lot about vulkan. I’ll probably pick it up later again when it piques my interest.

2 Likes

BytePool

I implemented Io.Writer in my project, which seeks to behave similarly to Writer.Allocating.

Each List (a u32 reference to a dynamic array) can be made to implement Io.Writer with a call to BytePool.setSink(), creating an ephemeral allocating writer instance.

The implementation relies on a custom data structure that manages the memory and pools the allocations of many dynamic arrays.

Implementing Io.Writer was just these three functions, which I believe I have defined correctly here:

This is all to make the serializing of self referential structures simple, as nodes can reference each other by u32 and allocations are stored densely.

Is it exactly practical? Maybe. Useful? I think so. Was it fun to mess with? Absolutely.

2 Likes

I’ll chip in with the driest and most boring thing in the thread:

Documenting EU regulatory compliance for the embedded Linux application I develop at work.

(If anybody has resources for SBOM generation in Zig or with the Zig build system, I’m all ears. Working with Yocto is making me want to tear my hair out after more than a year being entirely Zig-native)

2 Likes

For the past few months, I’ve been working full-time on a long-standing frustration of mine: I want a performance/behavior profiler natively designed around non-linear execution flows.

By non-linear, I mean any software that has to detach itself from the strict LIFO order of native threads and callstacks: asynchrony/concurrency, events loops, queues, M:N scheduling, coroutines/fibers/etc, any form of distributed compute, any form of batching… Basically, anything multiplexing compute, I/O, data, or all of the above.

Another way to think about this is in terms of execution spans. In traditional LIFO systems, child spans start and end neatly within the scope of their parents. In heavily multiplexed systems, spans may…:

  • Outlive their parents, or any of their ancestors
  • Share zero temporal overlap with the context that spawned them
  • Arrive out of order
  • End up seemingly orphaned
  • Unintentionally stall or never finish at all
  • Seemingly finish before they even started (yes)
  • Any combination of the above
  • Etc

Inspecting these systems through the lens of a native thread is usually not useful at best, and often actively harmful at worst (i.e. sends you on wild goose chases). What matters is the logical execution flow, not the physical one.
Right now, we have tools like perf and Tracy on one end of the spectrum (legitimately incredible for LIFO, but fall short on multiplexed flows) and high-level observability protocols like OpenTelemetry on the other (great for logical workflows, but designed for enterprise observability rather than profiling, meaning: heavy sampling, bloated SDKs, slow UIs, and generally a focus on aggregated patterns rather than raw data).

I want Tracy-level UX and performance, but built specifically for non-LIFO paradigms.
Crucially, It must also be great at detecting things that are not executing, or stopped doing so halfway through: IME, things that should be running and silently aren’t (a coroutine lost at sea, a queue that doesn’t get popped, purely userspace deadlocks and livelocks, etc) often turn out to be more damaging than active bottlenecks in these kinds of systems.

Here’s a screenshot from an early prototype, where Balamb is observing its own ingestion pipeline:

(This is Dear Imgui, although I do want to give DVUI another try when I get a minute – it seems to have made a lot of progress since I last looked.)

After months of exploring the problem space, wrestling with the core data model, trying many different things for the main data structures, and endlessly suffering through UI/UX design, I believe I finally have an architecture I’m happy with on all fronts. Now I just have to build it all :melting_face:.

Building on Zig has been incredible. Kudos to the team.

6 Likes

I’ve been working on programming an ECU, BMS and various sensors for an electric race motorcycle. I’m in a team of ~20 students builting a motocycle for the MotoStudent competition.

We’re using a few different types of microcontrollers and so far I have used Zig to target STM32 microcontrollers. I’m using ST’s hardware abstraction library directly with no issues. Inspired by TigerBeetle, I’m building a deterministic simulation test for the ECU. It has proven more difficult than I originally thought, but I’m getting there.

One of the few issues I encountered was that the objcopy from the build system produced binaries that were way to large (hundreds of Mos!) to flash onto the microcontroller. This issue is already tracked and I’ve mitigated it by using llvm-objcopy directly.

Most of the source code is private, but I’ve built a CAN database parsing library I can share. CAN is a message-oriented protocol typically used on vehicles that allows different components of that vehicle to exchange data. A CAN database (*.dbc file) is a proprietary file format that describes what are the messages, their “signals” (fields), how signals are encoded, which component sends them and receives them. I got tired of the database getting out of sync with the source code, so I made a library that ingests a *.dbc file in a build.zig and generates all the message definitions as well as encoding/decoding functions. So far it has been working flawlessly.

I also built a package that packages another project required to flash the microcontroller and can be used as a build step. So now, when somebody else wants in the team wants to program and flash an STM32, they have one less system dependency to worry about.

1 Like