Stream: beginners

Topic: ✔ Tuples vs records memory usage


view this post on Zulip Michał Łępicki (Oct 16 2022 at 16:38):

I saw that tuples to records desugaring is planned. I'm curious, aren't records always "wrapped", meaning they impose some (minimal, but still) memory usage overhead? Or does Roc optimize records to erase fields information when it's not needed at runtime?

view this post on Zulip Brendan Hansknecht (Oct 16 2022 at 16:58):

What do you mean by wrapped?

view this post on Zulip Michał Łępicki (Oct 16 2022 at 17:04):

I would compare tuples to C structs, in that they only contain the values and nothing else. Because with records I can pattern match on a subset of fields, and this code should work for all kinds of records that have these fields, I would imagine there is some additional memory needed for records (this is what I mean by "wrapped") so that at runtime each field name points to appropriate place in memory. Or is it optimized away when never needed for some particular record value?

view this post on Zulip Brendan Hansknecht (Oct 16 2022 at 17:15):

Oh, that is all compile time

view this post on Zulip Brendan Hansknecht (Oct 16 2022 at 17:15):

They are all compiled to c structs

view this post on Zulip Brendan Hansknecht (Oct 16 2022 at 17:15):

Pattern matching knows byte offsets and expect values at compile time

view this post on Zulip Michał Łępicki (Oct 16 2022 at 17:25):

Then for a row polymorphic function, how does it work for different records that might have the matched fields at different offsets? Are there multiple versions of this function at runtime? Or is there some type-offsets mapping saved somewhere in the program, and at runtime offsets are chosen based on some tag passed from callsite?

view this post on Zulip Brendan Hansknecht (Oct 16 2022 at 17:32):

I believe it is like templated/generic functions where there is a version for each concrete type

view this post on Zulip Brian Carroll (Oct 16 2022 at 17:32):

A single Roc function can compile to many assembly functions, one for each record type

view this post on Zulip Michał Łępicki (Oct 16 2022 at 17:33):

That answers my question and is good to know, thank you!

view this post on Zulip Notification Bot (Oct 16 2022 at 17:33):

Michał Łępicki has marked this topic as resolved.

view this post on Zulip Richard Feldman (Oct 16 2022 at 17:37):

yeah - tuples, records, and single-tag tag unions all have zero memory overhead on top of the values they store

view this post on Zulip Richard Feldman (Oct 16 2022 at 17:37):

also they all compile to the same thing, so there's no runtime performance difference between using one over another

view this post on Zulip Brendan Hansknecht (Oct 16 2022 at 17:38):

*non recursive single tags?

view this post on Zulip Richard Feldman (Oct 16 2022 at 17:38):

oops, yes - good point :big_smile:

view this post on Zulip Richard Feldman (Oct 16 2022 at 17:38):

although I guess in that case it's technically still true :thinking:

view this post on Zulip Brendan Hansknecht (Oct 16 2022 at 17:39):

Not quite. Refcount

view this post on Zulip Richard Feldman (Oct 16 2022 at 17:39):

oh true, fair enough!

view this post on Zulip Martin Stewart (Oct 16 2022 at 17:40):

Richard Feldman said:

yeah - tuples, records, and single-tag tag unions all have zero memory overhead on top of the values they store

Does monomorphization count as memory overhead? You need to generate multiple functions and those functions do need to be stored in memory. I guess this isn't counted because it's a really tiny amount of constant overhead?

view this post on Zulip Ayaz Hafiz (Oct 16 2022 at 17:41):

it does count as overhead. depending on how much you have it can sometimes be a problem (for example, if you have many specialized functions you are calling, the likelihood one’s code is in an instruction cache is much lower)

view this post on Zulip Ayaz Hafiz (Oct 16 2022 at 17:42):

but in general it is reasonable to assume that the overhead is lower than using boxed values and dispatching at runtime based on the boxed type representation

view this post on Zulip Richard Feldman (Oct 16 2022 at 17:43):

yeah, so no memory overhead

view this post on Zulip Richard Feldman (Oct 16 2022 at 17:44):

but there are other performance considerations than that!

view this post on Zulip Ayaz Hafiz (Oct 16 2022 at 17:46):

just to be pedantic there is also memory overhead right. like you have to load the binary, if there is more code there will be more to load

view this post on Zulip Richard Feldman (Oct 16 2022 at 17:55):

ha, also fair

view this post on Zulip Richard Feldman (Oct 16 2022 at 17:55):

so in the sense of like - the function itself has memory overhead

view this post on Zulip Richard Feldman (Oct 16 2022 at 17:55):

even if the data structure itself doesn't

view this post on Zulip Brendan Hansknecht (Oct 16 2022 at 18:02):

If the function doesn't have memory overhead the datastrutures would need to. Also, the function would need to be dynamic at runtime which would make it bigger and have overhead. So umm...i think we are just debating pedantic details.

view this post on Zulip Richard Feldman (Oct 16 2022 at 18:03):

well yes, but that's fun :big_smile:

view this post on Zulip Brendan Hansknecht (Oct 16 2022 at 18:07):

fair


Last updated: Jul 06 2025 at 12:14 UTC