# Run: # GC_INITIAL_HEAP_SIZE=$[1024 * 1024] NIX_SHOW_STATS=1 nix eval -f gc-coroutine-test.nix -vvvv let inherit (builtins) foldl' isList ; # Generate a tree of numbers, n deep, such that the numbers add up to (1 + salt) * 10^n. # The salting makes the numbers all different, increasing the likelihood of catching # any memory corruptions that might be caused by the GC or otherwise. garbage = salt: n: if n == 0 then [(1 + salt)] else [ (garbage (10 * salt + 1) (n - 1)) (garbage (10 * salt - 1) (n - 1)) (garbage (10 * salt + 2) (n - 1)) (garbage (10 * salt - 2) (n - 1)) (garbage (10 * salt + 3) (n - 1)) (garbage (10 * salt - 3) (n - 1)) (garbage (10 * salt + 4) (n - 1)) (garbage (10 * salt - 4) (n - 1)) (garbage (10 * salt + 5) (n - 1)) (garbage (10 * salt - 5) (n - 1)) ]; pow = base: n: if n == 0 then 1 else base * (pow base (n - 1)); sumNestedLists = l: if isList l then foldl' (a: b: a + sumNestedLists b) 0 l else l; in assert sumNestedLists (garbage 0 3) == pow 10 3; assert sumNestedLists (garbage 0 6) == pow 10 6; builtins.foldl' (a: b: assert "${ builtins.path { path = ./src; filter = path: type: # We're not doing common subexpression elimination, so this reallocates # the fairly big tree over and over, producing a lot of garbage during # source filtering, whose filter runs in a coroutine. assert sumNestedLists (garbage 0 3) == pow 10 3; true; } }" == "${./src}"; # These asserts don't seem necessary, as the lambda value get corrupted first assert a.okay; assert b.okay; { okay = true; } ) { okay = true; } [ { okay = true; } { okay = true; } { okay = true; } ]