Stream: platform development

Topic: roc_alloc and alignment


view this post on Zulip Oskar Hahn (Nov 13 2024 at 16:00):

Currently, the signature of roc_alloc is (size: usize, alignment: u32) [*]u8 (zig syntax).

The argument alignment is currently not used by most platforms, since most platforms just use malloc. And malloc does not have an alignment argument, but always uses the "fundamental alignment". I am not absolutely sure, what the fundamental alignment is, I think, it is 16 bytes?

In Zig, there is the function allocation.alignedAlloc() that takes an alignment value. But this value has to be comptime. So it can not use a variable alignment from roc. So a zig-platform has to use an alignment of 16 to support all types (for example List U128.

My question is, is it useful for roc_alloc to have the argument alignment if neither malloc nor zig can use it?

view this post on Zulip Oskar Hahn (Nov 13 2024 at 16:20):

My argument is fault. It is possible to use the argument in zig:

export fn roc_alloc(size: usize, alignment: u32) [*]u8 {
    var mem: []u8 = undefined;
    if (alignment <= 8) {
        mem = allocator.alignedAlloc(u8, 8, size) catch std.debug.panic("roc_alloc: OOM", .{});
    } else {
        mem = allocator.alignedAlloc(u8, 16, size) catch std.debug.panic("roc_alloc: OOM", .{});
    }
    return mem.ptr;
}

view this post on Zulip Brendan Hansknecht (Nov 13 2024 at 17:21):

Interesting that it is comptime zig. I guess that is the normal case

view this post on Zulip Brendan Hansknecht (Nov 13 2024 at 17:21):

Also, yeah, for simplicity, one can always fall back on 16 bytes. That said, denser allocations can be done. Saves a lot of space in arenas for example if everything is packed as tight as alignment allows

view this post on Zulip Oskar Hahn (Nov 13 2024 at 17:23):

At the moment, the value of alignment is at least 8 (maybe usize, I am on a 64 system). Even for a type like List U8. Could/Should this be changed?

view this post on Zulip Brendan Hansknecht (Nov 13 2024 at 17:45):

Oh yeah, I always forget that all of our allocations are refcounted so they contain a usize....

view this post on Zulip Brendan Hansknecht (Nov 13 2024 at 17:46):

So savings of at most 8 bytes per allocations in roc if you don't align to 16 all the time

view this post on Zulip Oskar Hahn (Nov 13 2024 at 19:38):

Was there a discussion to put the ref counts to a different place? This would be an argument to do this.

It's like the idea to put attributes in different arrays to get a better memory layout. It seems wrong that every roc object on the heap needs 8 bytes to save a very small number.

view this post on Zulip Brendan Hansknecht (Nov 13 2024 at 19:40):

refcounts need to be on the heap. That said, we could:

  1. allow for 32bit refcounts on 64bit systems
  2. allow for unaligned refounts (not sure if this is a good idea though might hurt perf too much, but if they are accessed in frequently it may not affect perf and would save mem)

view this post on Zulip Brendan Hansknecht (Nov 13 2024 at 19:41):

Also, to be fair, most objects on the heap in roc are dynamically sized and can get quite large (list and str). Everything else tends to be on the stack.

view this post on Zulip Brendan Hansknecht (Nov 13 2024 at 19:41):

boxing is pretty dang rare (and recursive tags are uncommon but definitely used)


Last updated: Jul 05 2025 at 12:14 UTC