commit b90acb87add41527b7d76849f4f0f293b5e64bbb
parent f59f4c66c337cb9eee7ba2a3db9c664cad325270
Author: Walther Chen <walther.chen@gmail.com>
Date:   Fri,  1 Nov 2024 14:28:29 -0400

Free temp inside neighbors

bioinformatics on  main [$] > poop "./ba1i-before ba1i-input.txt" "./ba1i ba1i-input.txt"
Benchmark 1 (151 runs): ./ba1i-before ba1i-input.txt
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          33.0ms ± 2.47ms    29.9ms … 40.4ms          2 ( 1%)        0%
  peak_rss           19.1MB ± 53.7KB    19.0MB … 19.2MB          0 ( 0%)        0%
  cpu_cycles         67.1M  ± 1.77M     64.5M  … 75.3M           1 ( 1%)        0%
  instructions        128M  ± 2.42       128M  …  128M           4 ( 3%)        0%
  cache_references   1.06M  ± 8.00K     1.04M  … 1.10M           2 ( 1%)        0%
  cache_misses        337K  ± 35.5K      286K  …  472K           2 ( 1%)        0%
  branch_misses       132K  ± 1.55K      130K  …  139K           6 ( 4%)        0%
Benchmark 2 (200 runs): ./ba1i ba1i-input.txt
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          25.0ms ± 2.26ms    22.3ms … 35.7ms          1 ( 1%)        ⚡- 24.2% ±  1.5%
  peak_rss           7.49MB ± 49.8KB    7.42MB … 7.58MB          0 ( 0%)        ⚡- 60.8% ±  0.1%
  cpu_cycles         58.0M  ± 3.27M     55.0M  … 89.2M           8 ( 4%)        ⚡- 13.6% ±  0.9%
  instructions        118M  ± 3.05       118M  …  118M           2 ( 1%)        ⚡-  8.3% ±  0.0%
  cache_references    768K  ± 23.8K      665K  …  979K           7 ( 4%)        ⚡- 27.4% ±  0.4%
  cache_misses        156K  ± 58.1K     93.5K  …  360K          13 ( 7%)        ⚡- 53.8% ±  3.1%
  branch_misses       121K  ± 1.49K      118K  …  129K           9 ( 5%)        ⚡-  8.5% ±  0.2%

Diffstat:
Mutil-frequency.c3 | 114++++++++++++++++++++++++++++++++++++++++---------------------------------------
1 file changed, 58 insertions(+), 56 deletions(-)

diff --git a/util-frequency.c3 b/util-frequency.c3 @@ -256,68 +256,70 @@ fn String[] neighbors(String pattern, int d, Allocator alloc = allocator::heap() { if (d == 0) return {pattern}; if (pattern.len == 0) return {}; - DynamicArenaAllocator neighborhood_arena; - DynamicArenaAllocator suffix_neighborhood_arena; - neighborhood_arena.init(1024, allocator::temp()); - suffix_neighborhood_arena.init(1024, allocator::temp()); - List(<String>) neighborhood; - List(<String>) suffix_neighborhood; - neighborhood.new_init_with_array({"A", "C", "G", "T"}, &neighborhood_arena); - suffix_neighborhood.new_init(16, &suffix_neighborhood_arena); - for (int i = 1; i < pattern.len; i += 1) { - // swap suffix_neighborhood and neighborhood. The previous - // neighborhood becomes the new suffix_neighborhood to iterate - // over. Now we need a place to collect the next neighborhood into, - // so we reuse the memory from the old suffix_neighborhood, which is - // no longer useful for future calculation, as its results have already - // been moved into the old neighborhood/new suffix_neighborhood as - // calculated during the last iteration. (otherwise we have to keep - // allocating new memory to collect the next neighborhood into). - // - // The memory itself is cleared for reuse by the arena holding the - // List (see next swap) - List(<String>) swap_var; - swap_var = suffix_neighborhood; - suffix_neighborhood = neighborhood; - neighborhood = swap_var; + @pool(alloc) { + DynamicArenaAllocator neighborhood_arena; + DynamicArenaAllocator suffix_neighborhood_arena; + neighborhood_arena.init(1024, allocator::temp()); + suffix_neighborhood_arena.init(1024, allocator::temp()); + List(<String>) neighborhood; + List(<String>) suffix_neighborhood; + neighborhood.new_init_with_array({"A", "C", "G", "T"}, &neighborhood_arena); + suffix_neighborhood.new_init(16, &suffix_neighborhood_arena); + for (int i = 1; i < pattern.len; i += 1) { + // swap suffix_neighborhood and neighborhood. The previous + // neighborhood becomes the new suffix_neighborhood to iterate + // over. Now we need a place to collect the next neighborhood into, + // so we reuse the memory from the old suffix_neighborhood, which is + // no longer useful for future calculation, as its results have already + // been moved into the old neighborhood/new suffix_neighborhood as + // calculated during the last iteration. (otherwise we have to keep + // allocating new memory to collect the next neighborhood into). + // + // The memory itself is cleared for reuse by the arena holding the + // List (see next swap) + List(<String>) swap_var; + swap_var = suffix_neighborhood; + suffix_neighborhood = neighborhood; + neighborhood = swap_var; - // Same swap with the arenas - // Old strings and the List holding them all get cleared - DynamicArenaAllocator swap_arena; - swap_arena = suffix_neighborhood_arena; - suffix_neighborhood_arena = neighborhood_arena; - neighborhood_arena = swap_arena; + // Same swap with the arenas + // Old strings and the List holding them all get cleared + DynamicArenaAllocator swap_arena; + swap_arena = suffix_neighborhood_arena; + suffix_neighborhood_arena = neighborhood_arena; + neighborhood_arena = swap_arena; - // clear out the old neighborhood for use in next iteration - neighborhood_arena.free(); - neighborhood.new_init(suffix_neighborhood.len(), &neighborhood_arena); + // clear out the old neighborhood for use in next iteration + neighborhood_arena.free(); + neighborhood.new_init(suffix_neighborhood.len(), &neighborhood_arena); - int suffix_idx = pattern.len - i; - String suffix = pattern[suffix_idx..]; - //io::printfn("%s, suffix_neighborhood = %s, neighborhood = %s", suffix, suffix_neighborhood, neighborhood); - foreach (suffix_neighbor : suffix_neighborhood) { - //io::printfn("%s, %s, %s, %s", suffix, suffix_neighbor, suffix_neighborhood, neighborhood); - if (hamming_distance(suffix, suffix_neighbor) < d) { - // adding the additional base will be at most hamming dist == d, - neighborhood.push("A".concat(suffix_neighbor, &suffix_neighborhood_arena)); - neighborhood.push("C".concat(suffix_neighbor, &suffix_neighborhood_arena)); - neighborhood.push("G".concat(suffix_neighbor, &suffix_neighborhood_arena)); - neighborhood.push("T".concat(suffix_neighbor, &suffix_neighborhood_arena)); - } else { - // hamming distance == d. It can't be more, because the neighbors are - // generated up to hamming distance d. Adding the first symbol from the - // original pattern cannot increase the hamming distance. - neighborhood.push(pattern[suffix_idx - 1:1].concat(suffix_neighbor, &suffix_neighborhood_arena)); + int suffix_idx = pattern.len - i; + String suffix = pattern[suffix_idx..]; + //io::printfn("%s, suffix_neighborhood = %s, neighborhood = %s", suffix, suffix_neighborhood, neighborhood); + foreach (suffix_neighbor : suffix_neighborhood) { + //io::printfn("%s, %s, %s, %s", suffix, suffix_neighbor, suffix_neighborhood, neighborhood); + if (hamming_distance(suffix, suffix_neighbor) < d) { + // adding the additional base will be at most hamming dist == d, + neighborhood.push("A".concat(suffix_neighbor, &suffix_neighborhood_arena)); + neighborhood.push("C".concat(suffix_neighbor, &suffix_neighborhood_arena)); + neighborhood.push("G".concat(suffix_neighbor, &suffix_neighborhood_arena)); + neighborhood.push("T".concat(suffix_neighbor, &suffix_neighborhood_arena)); + } else { + // hamming distance == d. It can't be more, because the neighbors are + // generated up to hamming distance d. Adding the first symbol from the + // original pattern cannot increase the hamming distance. + neighborhood.push(pattern[suffix_idx - 1:1].concat(suffix_neighbor, &suffix_neighborhood_arena)); + } } } - } - // Copy strings out to final result's allocator - String[] res = allocator::new_array(alloc, String, neighborhood.len()); - foreach (i, neighbor : neighborhood) { - res[i] = neighbor.copy(alloc); - } - return res; + // Copy strings out to final result's allocator + String[] res = allocator::new_array(alloc, String, neighborhood.len()); + foreach (i, neighbor : neighborhood) { + res[i] = neighbor.copy(alloc); + } + return res; + }; } struct NeighborsTest {