Skip to content

perf: use node cache in insert and remove operations for BTreeMap#426

Open
maksymar wants to merge 21 commits intomainfrom
maksym/insert-remove-cache
Open

perf: use node cache in insert and remove operations for BTreeMap#426
maksymar wants to merge 21 commits intomainfrom
maksym/insert-remove-cache

Conversation

@maksymar
Copy link
Copy Markdown
Contributor

@maksymar maksymar commented Apr 1, 2026

This PR uses node cache for write operations like insert and remove.

Extends the node cache (previously read-only) to insert, remove, pop_first, and pop_last. Nodes are taken from cache instead of stable memory when descending the tree. Unmodified parent nodes are returned to cache on the happy path. Modified nodes go through save_node which invalidates their cache slot. A depth parameter is threaded through recursive helpers to inform the cache eviction policy. Siblings during rebalancing bypass the cache since they are always modified.

131 improvements vs 13 regressions across 252 benchmarks.

  • insert improves 25-30%
  • pop_first/pop_last ~20%
  • compound operations like get_then_insert 25-31%

Regressions are in first/last_key_value (+2-5%) — read-only paths not on changed code paths, caused by write operations filling pinned depth 0-1 cache slots that read traversals also need.

Pop improvements are smaller than insert because single-pass pop (#417) already eliminates redundant traversals — cache only helps by reusing root and near-root nodes across consecutive calls.

chart_by_category

Comparing to base commit 04fe601 before all cache optimizations.
chart_by_category

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

canbench 🏋 (dir: ./benchmarks/nns) 5e27b9d 2026-04-02 16:02:56 UTC

./benchmarks/nns/canbench_results.yml is up to date
📦 canbench_results_nns.csv available in artifacts

---------------------------------------------------

Summary:
  instructions:
    status:   Regressions detected 🔴
    counts:   [total 16 | regressed 1 | improved 0 | new 0 | unchanged 15]
    change:   [max +192.11K | p75 +346 | median 0 | p25 -812.85K | min -107.40M]
    change %: [max +2.16% | p75 0.00% | median 0.00% | p25 -0.21% | min -1.29%]

  heap_increase:
    status:   Regressions detected 🔴
    counts:   [total 16 | regressed 2 | improved 0 | new 0 | unchanged 14]
    change:   [max +1 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max +inf% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

  stable_memory_increase:
    status:   No significant changes 👍
    counts:   [total 16 | regressed 0 | improved 0 | new 0 | unchanged 16]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

---------------------------------------------------

Only significant changes:
| status | name                                 | calls |     ins |  ins Δ% | HI |  HI Δ% | SMI |  SMI Δ% |
|--------|--------------------------------------|-------|---------|---------|----|--------|-----|---------|
|   +    | vote_cascading_stable_single_vote_1k |       |  68.06K |  +2.16% |  0 |  0.00% |   0 |   0.00% |
|   +    | vote_cascading_stable_chain_1k_15    |       | 866.42M |   0.00% |  1 |  +inf% |   0 |   0.00% |
|   +    | vote_cascading_stable_chain_1k_5     |       | 248.62M |  -1.29% |  1 |  +inf% |   0 |   0.00% |

ins = instructions, HI = heap_increase, SMI = stable_memory_increase, Δ% = percent change

---------------------------------------------------
CSV results saved to canbench_results.csv

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

canbench 🏋 (dir: ./benchmarks/btreeset) 5e27b9d 2026-04-02 16:02:56 UTC

./benchmarks/btreeset/canbench_results.yml is up to date
📦 canbench_results_btreeset.csv available in artifacts

---------------------------------------------------

Summary:
  instructions:
    status:   Regressions and improvements 🔴🟢
    counts:   [total 100 | regressed 5 | improved 20 | new 0 | unchanged 75]
    change:   [max +3.60M | p75 +16.14K | median +1.03K | p25 -99.96K | min -3.30B]
    change %: [max +3.03% | p75 +0.58% | median +0.05% | p25 -0.52% | min -43.62%]

  heap_increase:
    status:   Regressions detected 🔴
    counts:   [total 100 | regressed 2 | improved 0 | new 0 | unchanged 98]
    change:   [max +1 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max +inf% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

  stable_memory_increase:
    status:   No significant changes 👍
    counts:   [total 100 | regressed 0 | improved 0 | new 0 | unchanged 100]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

---------------------------------------------------

Only significant changes:
| status | name                          | calls |     ins |  ins Δ% | HI |  HI Δ% | SMI |  SMI Δ% |
|--------|-------------------------------|-------|---------|---------|----|--------|-----|---------|
|   +    | btreeset_is_subset_blob_8     |       |  53.35K |  +3.03% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreeset_iter_blob_256        |       | 129.39M |  +2.86% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreeset_is_subset_u32        |       |  43.61K |  +2.74% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreeset_range_blob_256       |       |  78.42M |  +2.57% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreeset_is_disjoint_blob_256 |       |  13.44M |  +2.09% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_insert_u64           |       | 380.41M | -32.38% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_remove_blob_32       |       | 541.08M | -32.63% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_remove_blob_64       |       | 653.16M | -33.90% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_remove_u32           |       | 349.08M | -34.03% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_insert_u32           |       | 356.07M | -34.21% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_remove_u64           |       | 363.54M | -34.39% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_insert_blob_32       |       | 528.11M | -35.26% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_remove_blob_16       |       | 454.20M | -35.71% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_insert_blob_64       |       | 624.07M | -36.42% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_insert_blob_16       |       | 452.86M | -36.82% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_insert_blob_8        |       | 431.43M | -37.93% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_remove_blob_8        |       | 416.03M | -39.23% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_insert_blob_128      |       | 994.77M | -39.26% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_remove_blob_128      |       |   1.01B | -39.62% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_remove_blob_256      |       |   1.53B | -39.81% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreeset_insert_blob_256      |       |   1.46B | -40.21% |  0 |  0.00% |   0 |   0.00% |
|  +/-   | btreeset_remove_blob_1024     |       |   4.42B | -42.73% |  1 |  +inf% |   0 |   0.00% |
|   -    | btreeset_insert_blob_512      |       |   2.31B | -42.95% |  0 |  0.00% | 128 |   0.00% |
|  +/-   | btreeset_remove_blob_512      |       |   2.40B | -43.59% |  1 |  +inf% |   0 |   0.00% |
|   -    | btreeset_insert_blob_1024     |       |   4.10B | -43.62% |  1 |  0.00% | 256 |   0.00% |

ins = instructions, HI = heap_increase, SMI = stable_memory_increase, Δ% = percent change

---------------------------------------------------
CSV results saved to canbench_results.csv

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

canbench 🏋 (dir: ./benchmarks/vec) 5e27b9d 2026-04-02 16:02:56 UTC

./benchmarks/vec/canbench_results.yml is up to date
📦 canbench_results_vec.csv available in artifacts

---------------------------------------------------

Summary:
  instructions:
    status:   No significant changes 👍
    counts:   [total 16 | regressed 0 | improved 0 | new 0 | unchanged 16]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

  heap_increase:
    status:   No significant changes 👍
    counts:   [total 16 | regressed 0 | improved 0 | new 0 | unchanged 16]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

  stable_memory_increase:
    status:   No significant changes 👍
    counts:   [total 16 | regressed 0 | improved 0 | new 0 | unchanged 16]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

---------------------------------------------------
CSV results saved to canbench_results.csv

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

canbench 🏋 (dir: ./benchmarks/memory_manager) 5e27b9d 2026-04-02 16:02:48 UTC

./benchmarks/memory_manager/canbench_results.yml is up to date
📦 canbench_results_memory-manager.csv available in artifacts

---------------------------------------------------

Summary:
  instructions:
    status:   No significant changes 👍
    counts:   [total 3 | regressed 0 | improved 0 | new 0 | unchanged 3]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

  heap_increase:
    status:   No significant changes 👍
    counts:   [total 3 | regressed 0 | improved 0 | new 0 | unchanged 3]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

  stable_memory_increase:
    status:   No significant changes 👍
    counts:   [total 3 | regressed 0 | improved 0 | new 0 | unchanged 3]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

---------------------------------------------------
CSV results saved to canbench_results.csv

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

canbench 🏋 (dir: ./benchmarks/btreemap) 5e27b9d 2026-04-02 16:04:05 UTC

./benchmarks/btreemap/canbench_results.yml is up to date
📦 canbench_results_btreemap.csv available in artifacts

---------------------------------------------------

Summary:
  instructions:
    status:   Regressions and improvements 🔴🟢
    counts:   [total 252 | regressed 11 | improved 130 | new 0 | unchanged 111]
    change:   [max +105.54M | p75 +2.29K | median -41.76M | p25 -111.85M | min -1.41B]
    change %: [max +139.28% | p75 +0.08% | median -6.16% | p25 -15.67% | min -32.52%]

  heap_increase:
    status:   Regressions detected 🔴
    counts:   [total 252 | regressed 4 | improved 0 | new 0 | unchanged 248]
    change:   [max +2 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max +inf% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

  stable_memory_increase:
    status:   No significant changes 👍
    counts:   [total 252 | regressed 0 | improved 0 | new 0 | unchanged 252]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

---------------------------------------------------

Only significant changes:
| status | name                                          | calls |     ins |   ins Δ% | HI |  HI Δ% | SMI |  SMI Δ% |
|--------|-----------------------------------------------|-------|---------|----------|----|--------|-----|---------|
|   +    | btreemap_v2_last_key_value_principal          |       |  76.71M | +139.28% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_first_key_value_blob_256_128      |       | 458.12M |  +29.93% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_last_key_value_u64_u64            |       |  86.93M |   +7.06% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_last_key_value_vec_32_128         |       |  78.20M |   +6.73% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_last_key_value_vec_32_vec128      |       |  78.20M |   +6.73% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_first_key_value_u64_u64           |       |  90.22M |   +6.27% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_range_key_sum_1k_0b               |       |  17.41K |   +2.81% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_range_count_1k_0b                 |       |  17.44K |   +2.81% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_insert_overwrite_u64_u64_nocache  |       | 371.44M |   +2.77% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_range_value_sum_1k_0b             |       |  17.78K |   +2.75% |  0 |  0.00% |   0 |   0.00% |
|   +    | btreemap_v2_last_key_value_blob_32_128        |       | 125.04M |   +2.19% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_range_key_sum_1k_10kib            |       |   2.47M |   -4.03% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_remove_blob_32_1024               |       | 941.19M |   -4.10% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_range_count_1k_10kib              |       |   2.40M |   -4.13% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_mem_manager_remove_u64_vec512     |       |   1.15B |   -5.82% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_remove_blob_32_512                |       | 800.02M |   -6.51% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_mem_manager_remove_u64_blob512    |       | 822.45M |   -6.54% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_remove_100k_u64_u64               |       |   6.46B |   -6.84% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_remove_u64_blob8                  |       | 524.28M |   -7.63% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_remove_vec_128_128                |       |   1.29B |   -8.16% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_remove_vec_32_1024                |       |   1.55B |   -8.49% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_remove_u64_u64                    |       | 533.95M |   -9.21% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_remove_u64_vec8                   |       | 519.93M |   -9.23% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_insert_blob_32_1024               |       | 640.54M |   -9.26% |  0 |  0.00% | 173 |   0.00% |
|   -    | btreemap_v2_remove_vec_32_512                 |       |   1.27B |   -9.31% |  0 |  0.00% |   0 |   0.00% |
|  ...   | ... 91 rows omitted ...                       |       |         |          |    |        |     |         |
|   -    | btreemap_v2_pop_first_u64_u64                 |       | 404.18M |  -21.25% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_pop_first_blob_32_128             |       | 482.62M |  -21.88% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_insert_blob8_u64                  |       | 342.83M |  -21.89% |  0 |  0.00% |   4 |   0.00% |
|   -    | btreemap_v2_get_then_remove_blob_32_128       |       | 750.75M |  -21.96% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_remove_vec_4_128                  |       | 511.55M |  -22.58% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_insert_blob_256_128               |       |   1.39B |  -22.64% |  0 |  0.00% |  67 |   0.00% |
|   -    | btreemap_v2_pop_first_blob_32_0               |       | 398.69M |  -23.14% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_pop_first_blob_8_128              |       | 337.06M |  -23.22% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_insert_blob_128_128               |       | 898.94M |  -24.03% |  0 |  0.00% |  46 |   0.00% |
|   -    | btreemap_v2_pop_first_principal               |       | 414.63M |  -24.05% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_insert_overwrite_zipf_10k_u64_u64 |       | 265.05M |  -24.63% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_pop_last_blob_32_0                |       | 366.51M |  -24.71% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_pop_last_blob_8_128               |       | 319.26M |  -25.26% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_peek_then_pop_last_u64_u64        |       | 445.25M |  -25.41% |  0 |  0.00% |   0 |   0.00% |
|  +/-   | btreemap_v2_insert_blob_1024_128              |       |   4.09B |  -25.63% |  2 |  +inf% | 196 |   0.00% |
|  +/-   | btreemap_v2_mem_manager_insert_blob512_u64    |       |   2.32B |  -25.86% |  1 |  +inf% |   0 |   0.00% |
|   -    | btreemap_v2_peek_then_pop_first_u64_u64       |       | 451.85M |  -26.22% |  0 |  0.00% |   0 |   0.00% |
|  +/-   | btreemap_v2_insert_blob_512_128               |       |   2.24B |  -26.38% |  1 |  +inf% | 111 |   0.00% |
|   -    | btreemap_v2_pop_last_principal                |       | 387.50M |  -26.52% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_insert_vec8_u64                   |       | 434.94M |  -26.91% |  0 |  0.00% |  16 |   0.00% |
|  +/-   | btreemap_v2_insert_vec_4_128                  |       | 436.37M |  -27.90% |  1 |  +inf% |  16 |   0.00% |
|   -    | btreemap_v2_insert_seq_u64_u64                |       | 333.91M |  -29.81% |  0 |  0.00% |   8 |   0.00% |
|   -    | btreemap_v2_get_then_insert_u64_u64           |       | 375.03M |  -30.87% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_get_then_insert_blob_32_128       |       | 525.77M |  -31.91% |  0 |  0.00% |   0 |   0.00% |
|   -    | btreemap_v2_mixed_get_insert_zipf_10k_u64_u64 |       | 337.37M |  -32.52% |  0 |  0.00% |   0 |   0.00% |

ins = instructions, HI = heap_increase, SMI = stable_memory_increase, Δ% = percent change

---------------------------------------------------
CSV results saved to canbench_results.csv

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

canbench 🏋 (dir: ./benchmarks/io_chunks) 5e27b9d 2026-04-02 16:03:19 UTC

./benchmarks/io_chunks/canbench_results.yml is up to date
📦 canbench_results_io_chunks.csv available in artifacts

---------------------------------------------------

Summary:
  instructions:
    status:   Improvements detected 🟢
    counts:   [total 18 | regressed 0 | improved 2 | new 0 | unchanged 16]
    change:   [max 0 | p75 0 | median 0 | p25 -56 | min -30.09B]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 -0.00% | min -35.93%]

  heap_increase:
    status:   No significant changes 👍
    counts:   [total 18 | regressed 0 | improved 0 | new 0 | unchanged 18]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

  stable_memory_increase:
    status:   No significant changes 👍
    counts:   [total 18 | regressed 0 | improved 0 | new 0 | unchanged 18]
    change:   [max 0 | p75 0 | median 0 | p25 0 | min 0]
    change %: [max 0.00% | p75 0.00% | median 0.00% | p25 0.00% | min 0.00%]

---------------------------------------------------

Only significant changes:
| status | name                     | calls |    ins |  ins Δ% | HI |  HI Δ% |   SMI |  SMI Δ% |
|--------|--------------------------|-------|--------|---------|----|--------|-------|---------|
|   -    | write_chunks_btreemap_1k |       |  3.92B |  -6.35% |  2 |  0.00% | 1.54K |   0.00% |
|   -    | write_chunks_btreemap_1m |       | 53.67B | -35.93% |  0 |  0.00% | 3.07K |   0.00% |

ins = instructions, HI = heap_increase, SMI = stable_memory_increase, Δ% = percent change

---------------------------------------------------
CSV results saved to canbench_results.csv

@maksymar
Copy link
Copy Markdown
Contributor Author

maksymar commented Apr 2, 2026

without using depth on write path:
chart_by_category

with using depth on write path:
chart_by_category

@maksymar
Copy link
Copy Markdown
Contributor Author

maksymar commented Apr 2, 2026

after updated benchmarks
chart_by_category

@maksymar maksymar changed the title perf: make use of node cache in insert & remove perf: use node cache in insert and remove operations for BTreeMap Apr 2, 2026
@maksymar
Copy link
Copy Markdown
Contributor Author

maksymar commented Apr 2, 2026

after split node optimization
chart_by_category

@maksymar maksymar marked this pull request as ready for review April 2, 2026 11:53
@maksymar maksymar requested a review from a team as a code owner April 2, 2026 11:53
@maksymar maksymar requested a review from sasa-tomic April 2, 2026 11:53
Copy link
Copy Markdown
Member

@sasa-tomic sasa-tomic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, LGTM!

@maksymar
Copy link
Copy Markdown
Contributor Author

maksymar commented Apr 2, 2026

chart_by_category

@maksymar
Copy link
Copy Markdown
Contributor Author

maksymar commented Apr 2, 2026

After merging single-pass pop* methods. strangely enough pop* methods got slower from -35...-40% to -20%. but it's actually ok.
The new approach with cache (3 loads) is still faster than the old approach with cache (4 loads). The relative cache benefit just looks smaller because the no-cache baseline is already much better.
There's no fix needed — this is the correct tradeoff. The single-pass approach already eliminated the redundant traversal that the cache was compensating for. The remaining -20% cache benefit comes from inter-operation reuse (root stays cached between pops), which is all that's left to optimize.

chart_by_category

@maksymar
Copy link
Copy Markdown
Contributor Author

maksymar commented Apr 2, 2026

Comparing to base commit 04fe601 before all cache optimizations.
chart_by_category

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants