46 comments
jgrowl · 6 days ago
I thought a reddit comment on this article had an interesting point:

https://www.reddit.com/r/rust/comments/1d3b356/my_new_favori...

[–]Timzhy0 3 points 7 months ago

Btw I think one can go a step further than the author, there is no need to keep two explicit ExprRef baked in a binary node (lhs, rhs). You can exploit locality, basically the AST, seen it the LISP way, is just an arbitrarily nestable list, where elements are atoms or other lists. Hence all you need to know is where each list ends (and if it's an atom you can assume it spans one node) and actually one bit to know if it is the last entry in the list is quite ergonomic as well (because then you can distinguish whether moving next slot in the AST means there is a sibling). Basically it's easier to keep it sync while constructing and takes up less memory per node. I pay 40 bits per node, stored interleaved for best cache locality (some unaligned accesses but I think it's still worthwhile), 8 bits for the tag, 32 for the data, if data is bigger, 32 is an index into some auxiliary segment (basically a ptr).

Show replies

dmagyari · 6 days ago
"Instead of allocating Expr objects willy-nilly on the heap, we’ll pack them into a single, contiguous array." Zig compiler pipeline (AST, Zir, Air, Sema) does exactly this on all layers. Not only contiguous, but instead of array-of-structs it is struct-of-arrays, so walking the tree is even more cache friendly. For AST see: https://github.com/ziglang/zig/blob/master/lib/std/zig/Ast.z...

Show replies

torginus · 5 days ago
I guess Rust's contribution to high performance programming is that its borrow checker is so loathsome that it pushes people into using ideas like ECS or arenas just to not have to bother with it.
kazinator · 6 days ago
> Instead of allocating Expr objects willy-nilly on the heap, we’ll pack them into a single, contiguous array.

This happens naturally if you bump-allocate them in a garbage-collected run-time, particularly under a copying collector. Free lists also tend to co-locate because they are produced during sweep phases of GC which run through heaps in order of address.

Don't make me bring out the L word for the billionth time.

> A flat array of Exprs can make it fun and easy to implement hash consing

OK, it's not a case of L-ignorance, just willful neglect.

Show replies

Agraillo · 5 days ago
About 10 years ago working with AST trees I (re)invented a flat structure representing trees in a flat array. It reminds me of what is described here but not exactly. In my case I needed only two indices per node: total sub-region length of all the children and sub-children and parent index (so no need to have indices of all children). Total sub-length basically can be interpreted as the index of the next sibling. With such a structure it's easy/cheap to execute FindFirstChild/FindNextSibling.

Later the theory behind such structures was revealed as "Nested set model" [1]. The article seems to not mention the internal representation, but I think that the implementation should use something like my solution, so fixed number of references per node

[1] https://en.wikipedia.org/wiki/Nested_set_model