I have been working again on re-integrating the file reading changes I made to basic cli and I was seeing some errors that really confused me.
One thing I noticed is, if I make a list with capacity 1 in roc, when I log the internal capacity value in rust it's 64. Is this to be expected?
Here's the impl for that function: https://github.com/roc-lang/roc/blob/a58b1013e756749da5c35431efde834a70a29717/crates/compiler/builtins/bitcode/src/list.zig#L353
I think it's not working the way it's supposed to.
It has an arg called capacity
that's passed to a listReserve
function as spare
And then we unconditionally increase our "desired capacity" by spare
So at least that is wrong. There's some casting stuff going on, which might explain how 1 (or 2?) gets to 64, but I'm not seeing
Sam Mohr said:
And then we unconditionally increase our "desired capacity" by spare
That shouldn't matter because later we use a min for the reserve size with the maxint. No issues
Yeah I don't get it either
This tests that withCapacity
reserves correctly
So it sounds like something may be wrong in the FFI interaction for you?
I just did a quick test, any number less than 64 comes out as 64
65 works fine
66?
I'm wondering if this is some small list optimisation trickery
I don't believe we do small list yet, only small str
Sam Mohr said:
66?
66 and 128 is 128
Haha, so 64n + 1
is correct, and anything else is 64(n + 1)
Well 64 is also correct
Yeah
It'd probably be good to get a minimal repro in this channel so we can report a bug
found it.
The calculateCapacity function has a bug
Or, well I guess it has a strange choice to always make it a minimum of 64
But maybe people are smarter than I have good reasons for deciding that 64 bytes is the smallest an array should be.
Anyway, I guess this doesn't matter much, but it's a little confusing for people using small buffers... not that they really should be using a tiny buffer. but still, having it always read 64 bytes when I was only expecting 2, was... unexpected
Should be a minimum of 64 bytes, not 64 items
Also, we should definitely have a way to request a specific size and not over allocate
These numbers where chosen by roughly following what Facebook does for strings that leads to best overall perf/memory use tradeoff for their fleet
That said, that has small string optimization for 0 to 24 bytes
We don't have small list for 0 to 24 bytes. That may shift the tradeoff some.
Though I don't recall if Facebook as small list or not....they may not
Anyway, it is meant to be a reasonable default, but may not be the best choice for all cases.
I'll make sure to double check the original source to see if we mixed something up.
On a really quick skim (so might be off):
Oh actually they still do the 64 byte thing
So I think our core differences are:
So we probably should update our code to do both of those things. Even without knowing the allocator size, we probably know rough bucket sizes based on alignment and blocks.
Last updated: Jul 06 2025 at 12:14 UTC