2026/05/21

Newest at the top

2026-05-21 15:15:21 +0000 <jaror> But I definitely also think unboxed arrays deserve a better API
2026-05-21 15:14:47 +0000 <jaror> s/are/should be/
2026-05-21 15:13:36 +0000 <jaror> I think small arrays are very common and it is unwieldy to have to switch between Array and SmallArray
2026-05-21 15:12:24 +0000 <int-e> If you care about the 1.6% wasted memory but are fine with the overhead of having pointers/thunks.
2026-05-21 15:12:10 +0000Lord_of_Life(~Lord@user/lord-of-life/x-2819915) Lord_of_Life
2026-05-21 15:09:39 +0000 <jaror> So if you use an array mostly immutably, you should go for SmallArray# is my conclusion.
2026-05-21 15:09:39 +0000Lord_of_Life(~Lord@user/lord-of-life/x-2819915) (Excess Flood)
2026-05-21 15:08:22 +0000 <jaror> ah that makes sense
2026-05-21 15:07:37 +0000 <int-e> somewhere in the middle of this is https://gitlab.haskell.org/ghc/ghc/-/blob/master/rts/Updates.h#L489
2026-05-21 15:07:00 +0000Lord_of_Life(~Lord@user/lord-of-life/x-2819915) Lord_of_Life
2026-05-21 15:06:52 +0000 <int-e> jaror: The card table is not touched in that case, it's the thunk that's going to be updated. The thunk is replaced by an indirection, and the indirection is recorded in the old generation's mutable list so GC treats it as a root.
2026-05-21 15:05:54 +0000wootehfoot(~wootehfoo@user/wootehfoot) wootehfoot
2026-05-21 15:04:39 +0000humasect(~humasect@dyn-192-249-132-90.nexicom.net) humasect
2026-05-21 15:04:10 +0000Alex_delenda_est(~al_test@5.139.233.99)
2026-05-21 15:02:42 +0000comerijn(~merijn@77.242.116.146) (Ping timeout: 248 seconds)
2026-05-21 15:01:28 +0000Digit(~user@user/digit) (Ping timeout: 256 seconds)
2026-05-21 15:01:18 +0000Digitteknohippie(~user@user/digit) Digit
2026-05-21 14:54:40 +0000 <tomsmeding> (I'm guessing here though)
2026-05-21 14:54:16 +0000 <tomsmeding> the card table being for "the Array# itself occurred in the mut list, now what changed exactly"
2026-05-21 14:54:00 +0000 <tomsmeding> would the resolving of the thunk perhaps itself update the mut list?
2026-05-21 14:53:27 +0000 <jaror> How is the card table updated then, it sounds quite distant
2026-05-21 14:53:06 +0000 <jaror> ah, but then there may be a thunk nested deeply in the Array# which creates such a pointer when it is forced
2026-05-21 14:52:47 +0000Square2(~Square4@user/square) (Ping timeout: 250 seconds)
2026-05-21 14:52:23 +0000 <tomsmeding> that Channable blog post also does mention that
2026-05-21 14:52:00 +0000 <jaror> I think I also read that laziness can cause similar kinds of pointers from the old to new generation though
2026-05-21 14:51:15 +0000 <int-e> jaror: I believe your're right that Array# wouldn't need a card table, but then unsafeThawArray# would have to copy arrays to make room for a card table.
2026-05-21 14:48:32 +0000 <jaror> ah so the card dirty card table entries are taken as roots when checking from pointers from the old to the new generation.
2026-05-21 14:44:42 +0000Lord_of_Life(~Lord@user/lord-of-life/x-2819915) (Excess Flood)
2026-05-21 14:42:51 +0000 <tomsmeding> at least about how exactly mutability is relevant here
2026-05-21 14:42:40 +0000 <tomsmeding> jaror: this sounds relevant https://www.channable.com/tech/lessons-in-managing-haskell-memory#mutability-is-the-root-of-all-ev…
2026-05-21 14:40:43 +0000 <jaror> But that hardly sounds tipical
2026-05-21 14:40:37 +0000 <jaror> Yes if you want to unsafely freeze or thaw it and use it mostly as a large mutable array then there seems to be an advantage to Array#
2026-05-21 14:39:30 +0000 <tomsmeding> well unless it's long and you might want to thaw it at some point
2026-05-21 14:38:41 +0000 <jaror> The documentation seems to imply that it is only mutation that is a problem and thus that SmallArray# should always be preferred over Array#...
2026-05-21 14:37:29 +0000 <jaror> There's some documentation in the primitive package and also some documentation here: https://hackage-content.haskell.org/package/ghc-prim-0.13.0/docs/GHC-Prim.html#g:19
2026-05-21 14:37:26 +0000 <tomsmeding> > This allows the garbage collector to only re-traverse segments of the array that have been marked during certain phases
2026-05-21 14:36:41 +0000 <tomsmeding> sure, I found that one first but there were no docs there whatsoever :)
2026-05-21 14:36:12 +0000 <jaror> Yeah, or the GHC builtin one: https://hackage.haskell.org/package/base-4.21.0.0/docs/GHC-Exts.html#t:SmallArray-35-
2026-05-21 14:35:49 +0000 <tomsmeding> oh primitive:Data.Primitive.SmallArray?
2026-05-21 14:35:25 +0000 <tomsmeding> ok I don't actually know what SmallArray you're talking about :)
2026-05-21 14:34:57 +0000 <jaror> But maybe it is an optimization for the other non-copying strategies that GHC also applies?
2026-05-21 14:34:47 +0000chexum_(~quassel@gateway/tor-sasl/chexum) chexum
2026-05-21 14:34:40 +0000chexum(~quassel@gateway/tor-sasl/chexum) (Ping timeout: 252 seconds)
2026-05-21 14:33:48 +0000 <jaror> I mean all the elements needs to be copied deeply, no?
2026-05-21 14:33:45 +0000danza(~danza@user/danza) danza
2026-05-21 14:33:24 +0000 <tomsmeding> there's memcpy(), and then there's following all the pointers to all the heap nodes referenced from the array cells
2026-05-21 14:27:36 +0000 <jaror> It talks about the GC not having to traverse all elements, but doesn't it need to do that anyway to copy everything over?
2026-05-21 14:26:44 +0000 <jaror> I don't really understand any of the explanations in the docs on SmallArrays
2026-05-21 14:23:35 +0000 <jaror> The immutable Array# I mean
2026-05-21 14:23:13 +0000 <jaror> Do arrays still need a card table if their elements are unlifted?