Rpmalloc porting diary



There was a recent thread on reddit (https://www.reddit.com/r/Zig/comments/y8torn/what_is_a_allocator_anyway) where matu3ba suggested porting rpmalloc as a performance optimized allocator for zig. The other day I have found this bug report too: implement a fast general purpose allocator · Issue #12484 · ziglang/zig · GitHub

So I have decided to give it a go. I can not promise, that I will succeed, but I will try to do my best. I am not a programmer, but I was able to port pdqsort and timsort to zig before, and I want to learn, so who knows.

As I will probably struggle sometimes and I would ask here anyway, I though it would be fun to write a progress diary here.

Code is available here: https://git.sr.ht/~voroskoi/rpmalloc.zig

Day 1

I have converted rpmalloc.c to zig with zig tranclate-c -I /usr/include > rpmalloc.zig as a start. There are a couple of problems with it: comments are stripped, atomic does not work to name the biggest issues, but it is nice to see how it handles certain cases as a reference.

I will do a manual porting in an incremental style. That means for the first iteration I just want to have a working version without changing things too much. So it will be in zig, but I will follow the rpmalloc.c line-by-line. After reaching a working state I can make the code more zig-like.
On the other hand I will try to follow zig’s naming conventions and such, so there will be no foo_t here.


I have started with rpmalloc.h. I just skipped the compiler specific part as we only care about the zig compiler. I have defined global values (everything is const for now, but I do not want to think about it), created structs (with some tweak, eg. rpmalloc_global_statistics_tGlobalStatistics).
I just skipped function exports and first class heap support for now.


Adding global variables is simple, so I have done that. Some of them will be unnecessary at the end, but I can remove them later in a cleanup phase. There will be a lots of TODO comments here :slight_smile:

Implemented atomic functions. This was a bit harder: I am not sure if memory_order_relaxed’s zig equivalent is std.builtin.AtomicOrder.Unordered, but that seems to be the best fit.
I use bool for return value with @cmpxchgWeak() calls instead of int in the original code.


Day 2-3

I have implemented pointer_offset and pointer_diff functions. They are probably just wrong as I was unable to figure out what types to use. Consider them placeholders.

I have changed atomic parts to use Atomic_* types as the C version does. It makes my life easier connecting the dots.

Added data types (Heap and Span), global data and thread local heap. There was some assembly in the latter, just copy-pasted it for my current arch as I do not know what to do with that.

While writing the low-level mmap code I had to realize that my original function declarations (copied from the C version) do not play nice with zig, so I moved to []align(std.mem.page_size) u8 from anyopaque. I am a bit afraid of casting that later, we will see how that works out.

There are 20 XXX in my code already, I do not understand a lot of things.



Sorry, I got distracted. Meanwhile there is GitHub - InKryption/rpmalloc-zig-port, so it does not make any sense to continue my work.