nanozlog:
Hello! This is my first post in the community. I’m glad to introduce my small zig library: nanozlog. It is basically porting from the famous C++ logging library: fmtlog. It is mainly focusing on the frontend logging speed. It could achieve 6-7ns per message which will cause the smallest blocking on your main working process.
I’m a newbie in Zig, so this is the first project I’m trying to work on after learning Zigling. Through Zig’s greatest comptime machanism, it is so convenient to translate those complicated C++ template code. And to my surprise, nanozlog is even slightly faster than fmtlog (7.3ns->6.8ns), maybe that is just benchmark error.
I’m looking forward to your commits and PRs. And also please no hesitate to criticise any stupid faults.
Supported Zig versions
zig-0-16
small tip for the benchmark; use the .awake Clock instead of .real, to get a monotonic clock that is not subject to potential modifications by your system.
wyzdwdz July 9, 2026, 8:19am 3
thx I got it. So .awake is like Instant in Rust. I ignored this point before.
The thread local buffer you use makes this still incompatible with any std.Io implementation other than std.Io.Threaded.
Sorry, I think it’s safe to use the threadlocal that way.
wyzdwdz July 9, 2026, 9:49am 5
Actually I’m still a little bit confused about that. I want to alloc a SPSC queue for each thread (not each task). In C++, the queue could free itself automatically when the thread is stopped. But in Zig, I have to provide a function called deinitThreadBuffer() to let the user free this queue.
The question is, if the user spawn the thread directly, then he could control when this thread stops and free the queue. But if using std.Io.async, he can’t just free the queue when one task stops, I have no idea how to design the API to solve this. Now the user have to use deinitNanoZlog at the end of the whole program to free all queues unifiedly.
The best option I can see, given that you are not owning the threads, is to have a list of all the queues you allocated and free them all in one single release function. It could be a simple atomic intrusive stack. Then you can allocate them on demand and free once for all the threads.
wyzdwdz July 9, 2026, 10:13am 7
You are right. Actually now I’m using this strategy. There are two ArrayLists to maintain these queues. When calling deinitNanoZlog, it will destroy all resources including the queues. This works well, but the only downside is that it could occupy more memory compare to C++ implementation because in C++ it is possible to free the useless queue in advance.
The only solution I thought is to find a hook function in std.Io which could let me register some codes when the intristic thread is stopped. I don’t know whether it is possible or not. Or maybe we could have something like threaddefer
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.