Skip to content

Conversation

@joamaki
Copy link
Contributor

@joamaki joamaki commented Jan 12, 2026

Add txnID to each inner node struct. This allows checking if a node had been cloned during this transaction or not which is more efficient and accurate than with nodeMutated. For iterating queries against the tree the txnID is bumped so that in-placed mutations are not allowed (much faster than cleaning nodeMutated).

The 'NoCache' option was removed as there was no longer any benefit with it (it was used earlier with Set[T] where it was known that there was always just one write per transaction and no point with nodeMutated record keeping).

Deletion now short-circuits if it hits a parent that had already been cloned and we can stop updating the parent pointers.

Benchmarks:

goos: darwin
goarch: arm64
pkg: github.com/cilium/statedb/part
cpu: Apple M1 Pro
                                   │   old.txt    │                new.txt                │
                                   │    sec/op    │    sec/op     vs base                 │
_Uint64Map_Random-8                  608.4µ ± ∞ ¹   589.4µ ± ∞ ¹   -3.12% (p=0.008 n=5)
_Uint64Map_Sequential-8              505.0µ ± ∞ ¹   487.3µ ± ∞ ¹   -3.52% (p=0.008 n=5)
_Uint64Map_Sequential_Insert-8       469.2µ ± ∞ ¹   448.9µ ± ∞ ¹   -4.33% (p=0.008 n=5)
_Uint64Map_Sequential_Txn_Insert-8   70.41µ ± ∞ ¹   69.88µ ± ∞ ¹        ~ (p=0.341 n=5)
_Uint64Map_Random_Insert-8           564.1µ ± ∞ ¹   534.9µ ± ∞ ¹   -5.17% (p=0.008 n=5)
_Uint64Map_Random_Txn_Insert-8       130.5µ ± ∞ ¹   109.1µ ± ∞ ¹  -16.42% (p=0.008 n=5)
_Insert_RootOnlyWatch-8              73.25µ ± ∞ ¹   72.76µ ± ∞ ¹        ~ (p=0.310 n=5)
_Insert-8                            101.5µ ± ∞ ¹   104.6µ ± ∞ ¹   +3.05% (p=0.008 n=5)
_Modify-8                            59.40µ ± ∞ ¹   61.82µ ± ∞ ¹   +4.07% (p=0.008 n=5)
_GetInsert-8                         76.89µ ± ∞ ¹   77.75µ ± ∞ ¹   +1.12% (p=0.032 n=5)
_Replace-8                           19.89n ± ∞ ¹   21.21n ± ∞ ¹   +6.64% (p=0.008 n=5)
_Replace_RootOnlyWatch-8             19.90n ± ∞ ¹   21.20n ± ∞ ¹   +6.53% (p=0.008 n=5)
_txn_1-8                             149.4n ± ∞ ¹   129.0n ± ∞ ¹  -13.65% (p=0.008 n=5)
_txn_10-8                            91.14n ± ∞ ¹   74.24n ± ∞ ¹  -18.54% (p=0.008 n=5)
_txn_100-8                           63.68n ± ∞ ¹   63.86n ± ∞ ¹        ~ (p=1.000 n=5)
_txn_1000-8                          73.85n ± ∞ ¹   72.99n ± ∞ ¹   -1.16% (p=0.048 n=5)
_txn_delete_1-8                      474.9n ± ∞ ¹   180.2n ± ∞ ¹  -62.06% (p=0.008 n=5)
_txn_delete_10-8                     96.95n ± ∞ ¹   69.14n ± ∞ ¹  -28.68% (p=0.008 n=5)
_txn_delete_100-8                    63.34n ± ∞ ¹   60.89n ± ∞ ¹   -3.87% (p=0.008 n=5)
_txn_delete_1000-8                   53.08n ± ∞ ¹   50.18n ± ∞ ¹   -5.46% (p=0.008 n=5)
_Get-8                               16.31µ ± ∞ ¹   16.90µ ± ∞ ¹   +3.63% (p=0.008 n=5)
_All-8                               4.654µ ± ∞ ¹   4.552µ ± ∞ ¹        ~ (p=0.056 n=5)
_Iterator_All-8                      4.578µ ± ∞ ¹   4.562µ ± ∞ ¹        ~ (p=0.841 n=5)
_Iterator_Next-8                     4.846µ ± ∞ ¹   4.935µ ± ∞ ¹   +1.84% (p=0.008 n=5)
_Hashmap_Insert-8                    37.74µ ± ∞ ¹   39.55µ ± ∞ ¹   +4.79% (p=0.008 n=5)
_Hashmap_Get_Uint64-8                5.693µ ± ∞ ¹   5.734µ ± ∞ ¹        ~ (p=1.000 n=5)
_Hashmap_Get_Bytes-8                 6.111µ ± ∞ ¹   6.327µ ± ∞ ¹   +3.53% (p=0.032 n=5)
_Delete_Random-8                     40.14m ± ∞ ¹   11.72m ± ∞ ¹  -70.80% (p=0.008 n=5)
_nodeMutatedClear-8                  7.101n ± ∞ ¹
_nodeMutatedExists-8                 3.870n ± ∞ ¹
_find16-8                            3.492n ± ∞ ¹   3.491n ± ∞ ¹        ~ (p=0.762 n=5)
_findIndex16-8                       8.831n ± ∞ ¹   8.808n ± ∞ ¹        ~ (p=0.095 n=5)
_find4-8                             2.077n ± ∞ ¹   2.079n ± ∞ ¹        ~ (p=0.175 n=5)
_findIndex4-8                        2.837n ± ∞ ¹   2.832n ± ∞ ¹   -0.18% (p=0.024 n=5)
geomean                              1.678µ         2.189µ         -9.04%               ²
¹ need >= 6 samples for confidence interval at level 0.95
² benchmark set differs from baseline; geomeans may not be comparable

                                   │   old.txt    │               new.txt               │
                                   │  items/sec   │  items/sec    vs base               │
_Uint64Map_Random-8                  1.644M ± ∞ ¹   1.697M ± ∞ ¹   +3.22% (p=0.008 n=5)
_Uint64Map_Sequential-8              1.980M ± ∞ ¹   2.052M ± ∞ ¹   +3.64% (p=0.008 n=5)
_Uint64Map_Sequential_Insert-8       2.131M ± ∞ ¹   2.228M ± ∞ ¹   +4.52% (p=0.008 n=5)
_Uint64Map_Sequential_Txn_Insert-8   14.20M ± ∞ ¹   14.31M ± ∞ ¹        ~ (p=0.310 n=5)
_Uint64Map_Random_Insert-8           1.773M ± ∞ ¹   1.870M ± ∞ ¹   +5.45% (p=0.008 n=5)
_Uint64Map_Random_Txn_Insert-8       7.661M ± ∞ ¹   9.165M ± ∞ ¹  +19.64% (p=0.008 n=5)
geomean                              3.320M         3.520M         +6.04%
¹ need >= 6 samples for confidence interval at level 0.95

                                   │    old.txt     │                 new.txt                  │
                                   │      B/op      │     B/op       vs base                   │
_Uint64Map_Random-8                   2.450Mi ± ∞ ¹   2.455Mi ± ∞ ¹   +0.19% (p=0.008 n=5)
_Uint64Map_Sequential-8               2.161Mi ± ∞ ¹   2.160Mi ± ∞ ¹   -0.07% (p=0.008 n=5)
_Uint64Map_Sequential_Insert-8        2.154Mi ± ∞ ¹   2.152Mi ± ∞ ¹   -0.07% (p=0.008 n=5)
_Uint64Map_Sequential_Txn_Insert-8    87.38Ki ± ∞ ¹   84.40Ki ± ∞ ¹   -3.41% (p=0.008 n=5)
_Uint64Map_Random_Insert-8            2.442Mi ± ∞ ¹   2.449Mi ± ∞ ¹   +0.30% (p=0.008 n=5)
_Uint64Map_Random_Txn_Insert-8        173.2Ki ± ∞ ¹   116.1Ki ± ∞ ¹  -32.94% (p=0.008 n=5)
_Insert_RootOnlyWatch-8               73.00Ki ± ∞ ¹   85.60Ki ± ∞ ¹  +17.27% (p=0.008 n=5)
_Insert-8                             187.1Ki ± ∞ ¹   198.3Ki ± ∞ ¹   +6.00% (p=0.008 n=5)
_Modify-8                             58.38Ki ± ∞ ¹   72.53Ki ± ∞ ¹  +24.25% (p=0.008 n=5)
_GetInsert-8                          58.36Ki ± ∞ ¹   72.53Ki ± ∞ ¹  +24.28% (p=0.008 n=5)
_Replace-8                              0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Replace_RootOnlyWatch-8                0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_1-8                                216.0 ± ∞ ¹     232.0 ± ∞ ¹   +7.41% (p=0.008 n=5)
_txn_10-8                               89.00 ± ∞ ¹    107.00 ± ∞ ¹  +20.22% (p=0.008 n=5)
_txn_100-8                              80.00 ± ∞ ¹     96.00 ± ∞ ¹  +20.00% (p=0.008 n=5)
_txn_1000-8                             67.00 ± ∞ ¹     81.00 ± ∞ ¹  +20.90% (p=0.008 n=5)
_txn_delete_1-8                        2952.0 ± ∞ ¹     648.0 ± ∞ ¹  -78.05% (p=0.008 n=5)
_txn_delete_10-8                        333.0 ± ∞ ¹     106.0 ± ∞ ¹  -68.17% (p=0.008 n=5)
_txn_delete_100-8                       70.00 ± ∞ ¹     47.00 ± ∞ ¹  -32.86% (p=0.008 n=5)
_txn_delete_1000-8                      27.00 ± ∞ ¹     24.00 ± ∞ ¹  -11.11% (p=0.008 n=5)
_Get-8                                  0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_All-8                                  0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Iterator_All-8                         0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Iterator_Next-8                        896.0 ± ∞ ¹     896.0 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Hashmap_Insert-8                     72.52Ki ± ∞ ¹   72.52Ki ± ∞ ¹        ~ (p=1.000 n=5) ²
_Hashmap_Get_Uint64-8                   0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Hashmap_Get_Bytes-8                    0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Delete_Random-8                     83.797Mi ± ∞ ¹   2.020Mi ± ∞ ¹  -97.59% (p=0.008 n=5)
_nodeMutatedClear-8                     0.000 ± ∞ ¹
_nodeMutatedExists-8                    0.000 ± ∞ ¹
_find16-8                               0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_findIndex16-8                          0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_find4-8                                0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_findIndex4-8                           0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
geomean                                           ³                  -17.24%               ⁴ ³
¹ need >= 6 samples for confidence interval at level 0.95
² all samples are equal
³ summaries must be >0 to compute geomean
⁴ benchmark set differs from baseline; geomeans may not be comparable

                                   │   old.txt    │                 new.txt                 │
                                   │  allocs/op   │  allocs/op    vs base                   │
_Uint64Map_Random-8                  7.043k ± ∞ ¹   7.037k ± ∞ ¹        ~ (p=0.516 n=5)
_Uint64Map_Sequential-8              6.754k ± ∞ ¹   6.753k ± ∞ ¹   -0.01% (p=0.008 n=5)
_Uint64Map_Sequential_Insert-8       5.753k ± ∞ ¹   5.752k ± ∞ ¹   -0.02% (p=0.008 n=5)
_Uint64Map_Sequential_Txn_Insert-8   2.039k ± ∞ ¹   2.029k ± ∞ ¹   -0.49% (p=0.008 n=5)
_Uint64Map_Random_Insert-8           6.037k ± ∞ ¹   6.038k ± ∞ ¹        ~ (p=0.325 n=5)
_Uint64Map_Random_Txn_Insert-8       2.854k ± ∞ ¹   2.409k ± ∞ ¹  -15.59% (p=0.008 n=5)
_Insert_RootOnlyWatch-8              2.045k ± ∞ ¹   2.034k ± ∞ ¹   -0.54% (p=0.008 n=5)
_Insert-8                            3.082k ± ∞ ¹   3.061k ± ∞ ¹   -0.68% (p=0.008 n=5)
_Modify-8                            1.015k ± ∞ ¹   1.008k ± ∞ ¹   -0.69% (p=0.008 n=5)
_GetInsert-8                         1.015k ± ∞ ¹   1.008k ± ∞ ¹   -0.69% (p=0.008 n=5)
_Replace-8                            0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Replace_RootOnlyWatch-8              0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_1-8                              4.000 ± ∞ ¹    4.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_10-8                             2.000 ± ∞ ¹    2.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_100-8                            2.000 ± ∞ ¹    2.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_1000-8                           2.000 ± ∞ ¹    2.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_delete_1-8                       5.000 ± ∞ ¹    4.000 ± ∞ ¹  -20.00% (p=0.008 n=5)
_txn_delete_10-8                      1.000 ± ∞ ¹    1.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_delete_100-8                     1.000 ± ∞ ¹    1.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_delete_1000-8                    1.000 ± ∞ ¹    1.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Get-8                                0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_All-8                                0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Iterator_All-8                       0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Iterator_Next-8                      1.000 ± ∞ ¹    1.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Hashmap_Insert-8                     20.00 ± ∞ ¹    20.00 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Hashmap_Get_Uint64-8                 0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Hashmap_Get_Bytes-8                  0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Delete_Random-8                     146.5k ± ∞ ¹   102.4k ± ∞ ¹  -30.12% (p=0.008 n=5)
_nodeMutatedClear-8                   0.000 ± ∞ ¹
_nodeMutatedExists-8                  0.000 ± ∞ ¹
_find16-8                             0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_findIndex16-8                        0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_find4-8                              0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_findIndex4-8                         0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
geomean                                         ³                  -2.42%               ⁴ ³
¹ need >= 6 samples for confidence interval at level 0.95
² all samples are equal
³ summaries must be >0 to compute geomean
⁴ benchmark set differs from baseline; geomeans may not be comparable

                         │   old.txt    │               new.txt                │
                         │ objects/sec  │ objects/sec   vs base                │
_Insert_RootOnlyWatch-8    13.65M ± ∞ ¹   13.74M ± ∞ ¹         ~ (p=0.310 n=5)
_Insert-8                  9.854M ± ∞ ¹   9.562M ± ∞ ¹    -2.96% (p=0.008 n=5)
_Modify-8                  16.83M ± ∞ ¹   16.17M ± ∞ ¹    -3.91% (p=0.008 n=5)
_GetInsert-8               13.01M ± ∞ ¹   12.86M ± ∞ ¹    -1.10% (p=0.032 n=5)
_Replace-8                 50.28M ± ∞ ¹   47.16M ± ∞ ¹    -6.21% (p=0.008 n=5)
_Replace_RootOnlyWatch-8   50.26M ± ∞ ¹   47.16M ± ∞ ¹    -6.16% (p=0.008 n=5)
_txn_1-8                   6.695M ± ∞ ¹   7.753M ± ∞ ¹   +15.80% (p=0.008 n=5)
_txn_10-8                  10.97M ± ∞ ¹   13.47M ± ∞ ¹   +22.77% (p=0.008 n=5)
_txn_100-8                 15.70M ± ∞ ¹   15.66M ± ∞ ¹         ~ (p=1.000 n=5)
_txn_1000-8                13.54M ± ∞ ¹   13.70M ± ∞ ¹         ~ (p=0.056 n=5)
_txn_delete_1-8            2.106M ± ∞ ¹   5.550M ± ∞ ¹  +163.52% (p=0.008 n=5)
_txn_delete_10-8           10.31M ± ∞ ¹   14.46M ± ∞ ¹   +40.22% (p=0.008 n=5)
_txn_delete_100-8          15.79M ± ∞ ¹   16.42M ± ∞ ¹    +4.02% (p=0.008 n=5)
_txn_delete_1000-8         18.84M ± ∞ ¹   19.93M ± ∞ ¹    +5.77% (p=0.008 n=5)
_Get-8                     61.32M ± ∞ ¹   59.17M ± ∞ ¹    -3.50% (p=0.008 n=5)
_All-8                     214.9M ± ∞ ¹   219.7M ± ∞ ¹         ~ (p=0.056 n=5)
_Iterator_All-8            218.4M ± ∞ ¹   219.2M ± ∞ ¹         ~ (p=0.841 n=5)
_Iterator_Next-8           206.4M ± ∞ ¹   202.6M ± ∞ ¹    -1.81% (p=0.008 n=5)
_Hashmap_Insert-8          26.50M ± ∞ ¹   25.29M ± ∞ ¹    -4.57% (p=0.008 n=5)
_Hashmap_Get_Uint64-8      175.7M ± ∞ ¹   174.4M ± ∞ ¹         ~ (p=1.000 n=5)
_Hashmap_Get_Bytes-8       163.6M ± ∞ ¹   158.0M ± ∞ ¹    -3.42% (p=0.032 n=5)
_Delete_Random-8           2.491M ± ∞ ¹   8.534M ± ∞ ¹  +242.51% (p=0.008 n=5)
geomean                    25.46M         28.75M         +12.93%
¹ need >= 6 samples for confidence interval at level 0.95

Memory usage actually slightly improved in reconciler benchmark when txnID is only in the inner nodes. Having it also on leafs showed marked increase in memory usage, so decision was to only have it on inner nodes.

jmaeki@JMAEKI-M-0D62 benchmark % go run .
Inserting batch 1000/1000 ...
Waiting for reconciliation to finish ...

1000000 objects reconciled in 1.35 seconds (batch size 1000)
Throughput 740540.27 objects per second
832MB total allocated, 6015207 in-use objects, 339MB bytes in use
jmaeki@JMAEKI-M-0D62 benchmark % stg push
> part-use-txnid-for-node
jmaeki@JMAEKI-M-0D62 benchmark % go run .
Inserting batch 1000/1000 ...
Waiting for reconciliation to finish ...

1000000 objects reconciled in 1.33 seconds (batch size 1000)
Throughput 750269.51 objects per second
817MB total allocated, 6015178 in-use objects, 338MB bytes in use

@github-actions
Copy link

github-actions bot commented Jan 12, 2026

$ make
go build ./...
go: downloading go1.24.0 (linux/amd64)
go: downloading go.yaml.in/yaml/v3 v3.0.3
go: downloading github.com/cilium/hive v0.0.0-20250731144630-28e7a35ed227
go: downloading golang.org/x/time v0.5.0
go: downloading github.com/spf13/cobra v1.8.0
go: downloading github.com/spf13/pflag v1.0.5
go: downloading github.com/cilium/stream v0.0.0-20240209152734-a0792b51812d
go: downloading github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de
go: downloading github.com/spf13/viper v1.18.2
go: downloading go.uber.org/dig v1.17.1
go: downloading golang.org/x/term v0.16.0
go: downloading github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
go: downloading github.com/mitchellh/mapstructure v1.5.0
go: downloading golang.org/x/sys v0.17.0
go: downloading golang.org/x/tools v0.17.0
go: downloading github.com/spf13/cast v1.6.0
go: downloading github.com/fsnotify/fsnotify v1.7.0
go: downloading github.com/sagikazarmark/slog-shim v0.1.0
go: downloading github.com/spf13/afero v1.11.0
go: downloading github.com/subosito/gotenv v1.6.0
go: downloading github.com/hashicorp/hcl v1.0.0
go: downloading gopkg.in/ini.v1 v1.67.0
go: downloading github.com/magiconair/properties v1.8.7
go: downloading github.com/pelletier/go-toml/v2 v2.1.0
go: downloading gopkg.in/yaml.v3 v3.0.1
go: downloading golang.org/x/text v0.14.0
PART_VALIDATE=1 go test ./... -cover -vet=all -test.count 1
go: downloading github.com/stretchr/testify v1.8.4
go: downloading go.uber.org/goleak v1.3.0
go: downloading golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
go: downloading github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
ok  	github.com/cilium/statedb	230.264s	coverage: 78.5% of statements
ok  	github.com/cilium/statedb/index	0.005s	coverage: 28.7% of statements
ok  	github.com/cilium/statedb/internal	0.027s	coverage: 42.9% of statements
ok  	github.com/cilium/statedb/lpm	0.512s	coverage: 75.7% of statements
ok  	github.com/cilium/statedb/part	71.619s	coverage: 87.7% of statements
ok  	github.com/cilium/statedb/reconciler	0.276s	coverage: 89.8% of statements
	github.com/cilium/statedb/reconciler/benchmark		coverage: 0.0% of statements
	github.com/cilium/statedb/reconciler/example		coverage: 0.0% of statements
go test -race ./... -test.count 1
ok  	github.com/cilium/statedb	37.290s
ok  	github.com/cilium/statedb/index	1.014s
ok  	github.com/cilium/statedb/internal	1.024s
ok  	github.com/cilium/statedb/lpm	2.754s
ok  	github.com/cilium/statedb/part	34.525s
ok  	github.com/cilium/statedb/reconciler	1.322s
?   	github.com/cilium/statedb/reconciler/benchmark	[no test files]
?   	github.com/cilium/statedb/reconciler/example	[no test files]
go test ./... -bench . -benchmem -test.run xxx
goos: linux
goarch: amd64
pkg: github.com/cilium/statedb
cpu: AMD EPYC 7763 64-Core Processor                
BenchmarkDB_WriteTxn_1-4                    	  720681	      1759 ns/op	    568480 objects/sec	     976 B/op	      18 allocs/op
BenchmarkDB_WriteTxn_10-4                   	 1727731	       696.9 ns/op	   1435023 objects/sec	     474 B/op	       8 allocs/op
BenchmarkDB_WriteTxn_100-4                  	 2169862	       550.9 ns/op	   1815053 objects/sec	     442 B/op	       7 allocs/op
BenchmarkDB_WriteTxn_1000-4                 	 2008471	       601.5 ns/op	   1662582 objects/sec	     399 B/op	       7 allocs/op
BenchmarkDB_WriteTxn_100_SecondaryIndex-4   	  852943	      1265 ns/op	    790548 objects/sec	     959 B/op	      22 allocs/op
BenchmarkDB_NewWriteTxn-4                   	 1882743	       637.8 ns/op	     192 B/op	       3 allocs/op
BenchmarkDB_WriteTxnCommit100-4             	  457642	      2603 ns/op	    8313 B/op	       4 allocs/op
BenchmarkDB_NewReadTxn-4                    	528078015	         2.199 ns/op	       0 B/op	       0 allocs/op
BenchmarkDB_Modify-4                        	    1744	    673399 ns/op	   1485003 objects/sec	  431666 B/op	    8074 allocs/op
BenchmarkDB_GetInsert-4                     	    1641	    728101 ns/op	   1373437 objects/sec	  407658 B/op	    8074 allocs/op
BenchmarkDB_RandomInsert-4                  	    1963	    613281 ns/op	   1630573 objects/sec	  399645 B/op	    7074 allocs/op
BenchmarkDB_RandomReplace-4                 	     470	   2547994 ns/op	    392466 objects/sec	 1948810 B/op	   32106 allocs/op
BenchmarkDB_SequentialInsert-4              	    1974	    606086 ns/op	   1649930 objects/sec	  399646 B/op	    7074 allocs/op
BenchmarkDB_SequentialInsert_Prefix-4       	     498	   2437844 ns/op	    410199 objects/sec	 3515453 B/op	   45543 allocs/op
BenchmarkDB_Changes_Baseline-4              	    1600	    739669 ns/op	   1351957 objects/sec	  459817 B/op	    9169 allocs/op
BenchmarkDB_Changes-4                       	     950	   1271725 ns/op	    786333 objects/sec	  661336 B/op	   12322 allocs/op
BenchmarkDB_RandomLookup-4                  	   22026	     54409 ns/op	  18379219 objects/sec	       0 B/op	       0 allocs/op
BenchmarkDB_SequentialLookup-4              	   26790	     44817 ns/op	  22312956 objects/sec	       0 B/op	       0 allocs/op
BenchmarkDB_Prefix_SecondaryIndex-4         	    6817	    163984 ns/op	   6098145 objects/sec	  124922 B/op	    1026 allocs/op
BenchmarkDB_FullIteration_All-4             	    1074	   1139867 ns/op	  87729517 objects/sec	     104 B/op	       5 allocs/op
BenchmarkDB_FullIteration_Prefix-4          	    1026	   1164259 ns/op	  85891509 objects/sec	     136 B/op	       6 allocs/op
BenchmarkDB_FullIteration_Get-4             	     202	   5821746 ns/op	  17176978 objects/sec	       0 B/op	       0 allocs/op
BenchmarkDB_FullIteration_Get_Secondary-4   	     103	  11618488 ns/op	   8606972 objects/sec	       0 B/op	       0 allocs/op
BenchmarkDB_FullIteration_ReadTxnGet-4      	     210	   5710008 ns/op	  17513110 objects/sec	       0 B/op	       0 allocs/op
BenchmarkDB_PropagationDelay-4              	  665780	      1665 ns/op	        14.00 50th_µs	        17.00 90th_µs	        40.00 99th_µs	    1040 B/op	      20 allocs/op
BenchmarkDB_WriteTxn_100_LPMIndex-4         	  514174	      2366 ns/op	    422654 objects/sec	    1784 B/op	      37 allocs/op
BenchmarkDB_WriteTxn_1_LPMIndex-4           	  126242	     15132 ns/op	     66087 objects/sec	   15701 B/op	      82 allocs/op
BenchmarkDB_LPMIndex_Get-4                  	     396	   3309181 ns/op	   3021896 objects/sec	       0 B/op	       0 allocs/op
BenchmarkWatchSet_4-4                       	 2258452	       527.2 ns/op	     320 B/op	       5 allocs/op
BenchmarkWatchSet_16-4                      	  712449	      1546 ns/op	    1096 B/op	       5 allocs/op
BenchmarkWatchSet_128-4                     	   89967	     13388 ns/op	    8904 B/op	       5 allocs/op
BenchmarkWatchSet_1024-4                    	    8847	    132570 ns/op	   73744 B/op	       5 allocs/op
PASS
ok  	github.com/cilium/statedb	41.649s
PASS
ok  	github.com/cilium/statedb/index	0.004s
goos: linux
goarch: amd64
pkg: github.com/cilium/statedb/internal
cpu: AMD EPYC 7763 64-Core Processor                
Benchmark_SortableMutex-4   	 6203268	       193.2 ns/op	       0 B/op	       0 allocs/op
PASS
ok  	github.com/cilium/statedb/internal	1.202s
goos: linux
goarch: amd64
pkg: github.com/cilium/statedb/lpm
cpu: AMD EPYC 7763 64-Core Processor                
BenchmarkDB_LPMTxn_100_Insert-4   	 1000000	      1212 ns/op	    825234 objects/sec	     871 B/op	      14 allocs/op
BenchmarkDB_LPMTxn_1_Insert-4     	 1315558	       904.0 ns/op	   1106255 objects/sec	     815 B/op	      13 allocs/op
PASS
ok  	github.com/cilium/statedb/lpm	3.656s
goos: linux
goarch: amd64
pkg: github.com/cilium/statedb/part
cpu: AMD EPYC 7763 64-Core Processor                
Benchmark_Uint64Map_Random-4                  	    1490	    753573 ns/op	   1327011 items/sec	 2574133 B/op	    7033 allocs/op
Benchmark_Uint64Map_Sequential-4              	    1834	    632468 ns/op	   1581108 items/sec	 2264721 B/op	    6754 allocs/op
Benchmark_Uint64Map_Sequential_Insert-4       	    2066	    578832 ns/op	   1727616 items/sec	 2256717 B/op	    5753 allocs/op
Benchmark_Uint64Map_Sequential_Txn_Insert-4   	   10000	    120378 ns/op	   8307191 items/sec	   86425 B/op	    2029 allocs/op
Benchmark_Uint64Map_Random_Insert-4           	    1726	    707113 ns/op	   1414202 items/sec	 2567092 B/op	    6041 allocs/op
Benchmark_Uint64Map_Random_Txn_Insert-4       	    6867	    166734 ns/op	   5997594 items/sec	  118620 B/op	    2406 allocs/op
Benchmark_Insert_RootOnlyWatch-4              	    9753	    118041 ns/op	   8471662 objects/sec	   71577 B/op	    2034 allocs/op
Benchmark_Insert-4                            	    7254	    164375 ns/op	   6083647 objects/sec	  187011 B/op	    3061 allocs/op
Benchmark_Modify-4                            	   12231	     98105 ns/op	  10193182 objects/sec	   58273 B/op	    1008 allocs/op
Benchmark_GetInsert-4                         	    8995	    132020 ns/op	   7574589 objects/sec	   58273 B/op	    1008 allocs/op
Benchmark_Replace-4                           	15666086	        73.33 ns/op	  13637812 objects/sec	      48 B/op	       1 allocs/op
Benchmark_Replace_RootOnlyWatch-4             	 3061888	       392.5 ns/op	   2547739 objects/sec	     209 B/op	       2 allocs/op
Benchmark_txn_1-4                             	 5422605	       212.6 ns/op	   4704342 objects/sec	     216 B/op	       4 allocs/op
Benchmark_txn_10-4                            	 9385948	       126.3 ns/op	   7918998 objects/sec	      91 B/op	       2 allocs/op
Benchmark_txn_100-4                           	11080816	       107.9 ns/op	   9265616 objects/sec	      80 B/op	       2 allocs/op
Benchmark_txn_1000-4                          	 9722644	       122.4 ns/op	   8171352 objects/sec	      65 B/op	       2 allocs/op
Benchmark_txn_delete_1-4                      	 4900638	       243.5 ns/op	   4106651 objects/sec	     648 B/op	       4 allocs/op
Benchmark_txn_delete_10-4                     	11423875	       104.3 ns/op	   9583485 objects/sec	     104 B/op	       1 allocs/op
Benchmark_txn_delete_100-4                    	12037130	        98.30 ns/op	  10172867 objects/sec	      47 B/op	       1 allocs/op
Benchmark_txn_delete_1000-4                   	14828784	        79.93 ns/op	  12510234 objects/sec	      24 B/op	       1 allocs/op
Benchmark_Get-4                               	   45530	     26368 ns/op	  37924520 objects/sec	       0 B/op	       0 allocs/op
Benchmark_All-4                               	  152276	      7876 ns/op	 126962707 objects/sec	       0 B/op	       0 allocs/op
Benchmark_Iterator_All-4                      	  131035	     10061 ns/op	  99392026 objects/sec	       0 B/op	       0 allocs/op
Benchmark_Iterator_Next-4                     	  151618	      7814 ns/op	 127981087 objects/sec	     896 B/op	       1 allocs/op
Benchmark_Hashmap_Insert-4                    	   14852	     80812 ns/op	  12374376 objects/sec	   74265 B/op	      20 allocs/op
Benchmark_Hashmap_Get_Uint64-4                	  138145	      8637 ns/op	 115774928 objects/sec	       0 B/op	       0 allocs/op
Benchmark_Hashmap_Get_Bytes-4                 	  111926	     10695 ns/op	  93502729 objects/sec	       0 B/op	       0 allocs/op
Benchmark_Delete_Random-4                     	      70	  15535741 ns/op	   6436771 objects/sec	 2111839 B/op	  102364 allocs/op
Benchmark_find16-4                            	240443940	         4.986 ns/op	       0 B/op	       0 allocs/op
Benchmark_findIndex16-4                       	100000000	        11.70 ns/op	       0 B/op	       0 allocs/op
Benchmark_find4-4                             	412705228	         2.909 ns/op	       0 B/op	       0 allocs/op
Benchmark_findIndex4-4                        	320690715	         3.739 ns/op	       0 B/op	       0 allocs/op
PASS
ok  	github.com/cilium/statedb/part	39.386s
PASS
ok  	github.com/cilium/statedb/reconciler	0.004s
?   	github.com/cilium/statedb/reconciler/benchmark	[no test files]
?   	github.com/cilium/statedb/reconciler/example	[no test files]
go run ./reconciler/benchmark -quiet
1000000 objects reconciled in 2.04 seconds (batch size 1000)
Throughput 490346.19 objects per second
817MB total allocated, 6015188 in-use objects, 338MB bytes in use

@joamaki joamaki force-pushed the pr/joamaki/part-txnid branch 3 times, most recently from 63e6fc2 to f332e6e Compare January 13, 2026 15:41
@joamaki joamaki marked this pull request as ready for review January 13, 2026 16:11
@joamaki joamaki requested a review from a team as a code owner January 13, 2026 16:11
@joamaki joamaki requested review from bimmlerd and pippolo84 and removed request for a team January 13, 2026 16:11
@joamaki joamaki changed the title part: use txnID for node mutability part: mark inner nodes with a transaction id to detect mutability Jan 13, 2026
Copy link
Member

@pippolo84 pippolo84 left a comment

Choose a reason for hiding this comment

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

Just a couple of minor nits, overall LGTM.

@joamaki joamaki force-pushed the pr/joamaki/part-txnid branch from f332e6e to 7b19b7c Compare January 14, 2026 17:08
@joamaki joamaki requested review from bimmlerd and pippolo84 January 14, 2026 17:10
Copy link
Member

@bimmlerd bimmlerd left a comment

Choose a reason for hiding this comment

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

minor nit, LGTM

txnID marks the generation of the transaction. This allows checking
if a node had been cloned during this transaction or not which is more
efficient and accurate than with nodeMutated. For iterating queries against
the tree the txnID is bumped so that in-placed mutations are not allowed.

The 'NoCache' option was removed as there was no longer any benefit with it
(it was used earlier with Set[T] where it was known that there was always
just one write per transaction and no point with nodeMutated record keeping).

Deletion now short-circuits if it hits a parent that had already been cloned
and we can stop updating the parent pointers.

Benchmarks:

goos: darwin
goarch: arm64
pkg: github.com/cilium/statedb/part
cpu: Apple M1 Pro
                                   │   old.txt    │                new.txt                │
                                   │    sec/op    │    sec/op     vs base                 │
_Uint64Map_Random-8                  608.4µ ± ∞ ¹   589.4µ ± ∞ ¹   -3.12% (p=0.008 n=5)
_Uint64Map_Sequential-8              505.0µ ± ∞ ¹   487.3µ ± ∞ ¹   -3.52% (p=0.008 n=5)
_Uint64Map_Sequential_Insert-8       469.2µ ± ∞ ¹   448.9µ ± ∞ ¹   -4.33% (p=0.008 n=5)
_Uint64Map_Sequential_Txn_Insert-8   70.41µ ± ∞ ¹   69.88µ ± ∞ ¹        ~ (p=0.341 n=5)
_Uint64Map_Random_Insert-8           564.1µ ± ∞ ¹   534.9µ ± ∞ ¹   -5.17% (p=0.008 n=5)
_Uint64Map_Random_Txn_Insert-8       130.5µ ± ∞ ¹   109.1µ ± ∞ ¹  -16.42% (p=0.008 n=5)
_Insert_RootOnlyWatch-8              73.25µ ± ∞ ¹   72.76µ ± ∞ ¹        ~ (p=0.310 n=5)
_Insert-8                            101.5µ ± ∞ ¹   104.6µ ± ∞ ¹   +3.05% (p=0.008 n=5)
_Modify-8                            59.40µ ± ∞ ¹   61.82µ ± ∞ ¹   +4.07% (p=0.008 n=5)
_GetInsert-8                         76.89µ ± ∞ ¹   77.75µ ± ∞ ¹   +1.12% (p=0.032 n=5)
_Replace-8                           19.89n ± ∞ ¹   21.21n ± ∞ ¹   +6.64% (p=0.008 n=5)
_Replace_RootOnlyWatch-8             19.90n ± ∞ ¹   21.20n ± ∞ ¹   +6.53% (p=0.008 n=5)
_txn_1-8                             149.4n ± ∞ ¹   129.0n ± ∞ ¹  -13.65% (p=0.008 n=5)
_txn_10-8                            91.14n ± ∞ ¹   74.24n ± ∞ ¹  -18.54% (p=0.008 n=5)
_txn_100-8                           63.68n ± ∞ ¹   63.86n ± ∞ ¹        ~ (p=1.000 n=5)
_txn_1000-8                          73.85n ± ∞ ¹   72.99n ± ∞ ¹   -1.16% (p=0.048 n=5)
_txn_delete_1-8                      474.9n ± ∞ ¹   180.2n ± ∞ ¹  -62.06% (p=0.008 n=5)
_txn_delete_10-8                     96.95n ± ∞ ¹   69.14n ± ∞ ¹  -28.68% (p=0.008 n=5)
_txn_delete_100-8                    63.34n ± ∞ ¹   60.89n ± ∞ ¹   -3.87% (p=0.008 n=5)
_txn_delete_1000-8                   53.08n ± ∞ ¹   50.18n ± ∞ ¹   -5.46% (p=0.008 n=5)
_Get-8                               16.31µ ± ∞ ¹   16.90µ ± ∞ ¹   +3.63% (p=0.008 n=5)
_All-8                               4.654µ ± ∞ ¹   4.552µ ± ∞ ¹        ~ (p=0.056 n=5)
_Iterator_All-8                      4.578µ ± ∞ ¹   4.562µ ± ∞ ¹        ~ (p=0.841 n=5)
_Iterator_Next-8                     4.846µ ± ∞ ¹   4.935µ ± ∞ ¹   +1.84% (p=0.008 n=5)
_Hashmap_Insert-8                    37.74µ ± ∞ ¹   39.55µ ± ∞ ¹   +4.79% (p=0.008 n=5)
_Hashmap_Get_Uint64-8                5.693µ ± ∞ ¹   5.734µ ± ∞ ¹        ~ (p=1.000 n=5)
_Hashmap_Get_Bytes-8                 6.111µ ± ∞ ¹   6.327µ ± ∞ ¹   +3.53% (p=0.032 n=5)
_Delete_Random-8                     40.14m ± ∞ ¹   11.72m ± ∞ ¹  -70.80% (p=0.008 n=5)
_nodeMutatedClear-8                  7.101n ± ∞ ¹
_nodeMutatedExists-8                 3.870n ± ∞ ¹
_find16-8                            3.492n ± ∞ ¹   3.491n ± ∞ ¹        ~ (p=0.762 n=5)
_findIndex16-8                       8.831n ± ∞ ¹   8.808n ± ∞ ¹        ~ (p=0.095 n=5)
_find4-8                             2.077n ± ∞ ¹   2.079n ± ∞ ¹        ~ (p=0.175 n=5)
_findIndex4-8                        2.837n ± ∞ ¹   2.832n ± ∞ ¹   -0.18% (p=0.024 n=5)
geomean                              1.678µ         2.189µ         -9.04%               ²
¹ need >= 6 samples for confidence interval at level 0.95
² benchmark set differs from baseline; geomeans may not be comparable

                                   │   old.txt    │               new.txt               │
                                   │  items/sec   │  items/sec    vs base               │
_Uint64Map_Random-8                  1.644M ± ∞ ¹   1.697M ± ∞ ¹   +3.22% (p=0.008 n=5)
_Uint64Map_Sequential-8              1.980M ± ∞ ¹   2.052M ± ∞ ¹   +3.64% (p=0.008 n=5)
_Uint64Map_Sequential_Insert-8       2.131M ± ∞ ¹   2.228M ± ∞ ¹   +4.52% (p=0.008 n=5)
_Uint64Map_Sequential_Txn_Insert-8   14.20M ± ∞ ¹   14.31M ± ∞ ¹        ~ (p=0.310 n=5)
_Uint64Map_Random_Insert-8           1.773M ± ∞ ¹   1.870M ± ∞ ¹   +5.45% (p=0.008 n=5)
_Uint64Map_Random_Txn_Insert-8       7.661M ± ∞ ¹   9.165M ± ∞ ¹  +19.64% (p=0.008 n=5)
geomean                              3.320M         3.520M         +6.04%
¹ need >= 6 samples for confidence interval at level 0.95

                                   │    old.txt     │                 new.txt                  │
                                   │      B/op      │     B/op       vs base                   │
_Uint64Map_Random-8                   2.450Mi ± ∞ ¹   2.455Mi ± ∞ ¹   +0.19% (p=0.008 n=5)
_Uint64Map_Sequential-8               2.161Mi ± ∞ ¹   2.160Mi ± ∞ ¹   -0.07% (p=0.008 n=5)
_Uint64Map_Sequential_Insert-8        2.154Mi ± ∞ ¹   2.152Mi ± ∞ ¹   -0.07% (p=0.008 n=5)
_Uint64Map_Sequential_Txn_Insert-8    87.38Ki ± ∞ ¹   84.40Ki ± ∞ ¹   -3.41% (p=0.008 n=5)
_Uint64Map_Random_Insert-8            2.442Mi ± ∞ ¹   2.449Mi ± ∞ ¹   +0.30% (p=0.008 n=5)
_Uint64Map_Random_Txn_Insert-8        173.2Ki ± ∞ ¹   116.1Ki ± ∞ ¹  -32.94% (p=0.008 n=5)
_Insert_RootOnlyWatch-8               73.00Ki ± ∞ ¹   85.60Ki ± ∞ ¹  +17.27% (p=0.008 n=5)
_Insert-8                             187.1Ki ± ∞ ¹   198.3Ki ± ∞ ¹   +6.00% (p=0.008 n=5)
_Modify-8                             58.38Ki ± ∞ ¹   72.53Ki ± ∞ ¹  +24.25% (p=0.008 n=5)
_GetInsert-8                          58.36Ki ± ∞ ¹   72.53Ki ± ∞ ¹  +24.28% (p=0.008 n=5)
_Replace-8                              0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Replace_RootOnlyWatch-8                0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_1-8                                216.0 ± ∞ ¹     232.0 ± ∞ ¹   +7.41% (p=0.008 n=5)
_txn_10-8                               89.00 ± ∞ ¹    107.00 ± ∞ ¹  +20.22% (p=0.008 n=5)
_txn_100-8                              80.00 ± ∞ ¹     96.00 ± ∞ ¹  +20.00% (p=0.008 n=5)
_txn_1000-8                             67.00 ± ∞ ¹     81.00 ± ∞ ¹  +20.90% (p=0.008 n=5)
_txn_delete_1-8                        2952.0 ± ∞ ¹     648.0 ± ∞ ¹  -78.05% (p=0.008 n=5)
_txn_delete_10-8                        333.0 ± ∞ ¹     106.0 ± ∞ ¹  -68.17% (p=0.008 n=5)
_txn_delete_100-8                       70.00 ± ∞ ¹     47.00 ± ∞ ¹  -32.86% (p=0.008 n=5)
_txn_delete_1000-8                      27.00 ± ∞ ¹     24.00 ± ∞ ¹  -11.11% (p=0.008 n=5)
_Get-8                                  0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_All-8                                  0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Iterator_All-8                         0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Iterator_Next-8                        896.0 ± ∞ ¹     896.0 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Hashmap_Insert-8                     72.52Ki ± ∞ ¹   72.52Ki ± ∞ ¹        ~ (p=1.000 n=5) ²
_Hashmap_Get_Uint64-8                   0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Hashmap_Get_Bytes-8                    0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Delete_Random-8                     83.797Mi ± ∞ ¹   2.020Mi ± ∞ ¹  -97.59% (p=0.008 n=5)
_nodeMutatedClear-8                     0.000 ± ∞ ¹
_nodeMutatedExists-8                    0.000 ± ∞ ¹
_find16-8                               0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_findIndex16-8                          0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_find4-8                                0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_findIndex4-8                           0.000 ± ∞ ¹     0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
geomean                                           ³                  -17.24%               ⁴ ³
¹ need >= 6 samples for confidence interval at level 0.95
² all samples are equal
³ summaries must be >0 to compute geomean
⁴ benchmark set differs from baseline; geomeans may not be comparable

                                   │   old.txt    │                 new.txt                 │
                                   │  allocs/op   │  allocs/op    vs base                   │
_Uint64Map_Random-8                  7.043k ± ∞ ¹   7.037k ± ∞ ¹        ~ (p=0.516 n=5)
_Uint64Map_Sequential-8              6.754k ± ∞ ¹   6.753k ± ∞ ¹   -0.01% (p=0.008 n=5)
_Uint64Map_Sequential_Insert-8       5.753k ± ∞ ¹   5.752k ± ∞ ¹   -0.02% (p=0.008 n=5)
_Uint64Map_Sequential_Txn_Insert-8   2.039k ± ∞ ¹   2.029k ± ∞ ¹   -0.49% (p=0.008 n=5)
_Uint64Map_Random_Insert-8           6.037k ± ∞ ¹   6.038k ± ∞ ¹        ~ (p=0.325 n=5)
_Uint64Map_Random_Txn_Insert-8       2.854k ± ∞ ¹   2.409k ± ∞ ¹  -15.59% (p=0.008 n=5)
_Insert_RootOnlyWatch-8              2.045k ± ∞ ¹   2.034k ± ∞ ¹   -0.54% (p=0.008 n=5)
_Insert-8                            3.082k ± ∞ ¹   3.061k ± ∞ ¹   -0.68% (p=0.008 n=5)
_Modify-8                            1.015k ± ∞ ¹   1.008k ± ∞ ¹   -0.69% (p=0.008 n=5)
_GetInsert-8                         1.015k ± ∞ ¹   1.008k ± ∞ ¹   -0.69% (p=0.008 n=5)
_Replace-8                            0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Replace_RootOnlyWatch-8              0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_1-8                              4.000 ± ∞ ¹    4.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_10-8                             2.000 ± ∞ ¹    2.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_100-8                            2.000 ± ∞ ¹    2.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_1000-8                           2.000 ± ∞ ¹    2.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_delete_1-8                       5.000 ± ∞ ¹    4.000 ± ∞ ¹  -20.00% (p=0.008 n=5)
_txn_delete_10-8                      1.000 ± ∞ ¹    1.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_delete_100-8                     1.000 ± ∞ ¹    1.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_txn_delete_1000-8                    1.000 ± ∞ ¹    1.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Get-8                                0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_All-8                                0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Iterator_All-8                       0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Iterator_Next-8                      1.000 ± ∞ ¹    1.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Hashmap_Insert-8                     20.00 ± ∞ ¹    20.00 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Hashmap_Get_Uint64-8                 0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Hashmap_Get_Bytes-8                  0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_Delete_Random-8                     146.5k ± ∞ ¹   102.4k ± ∞ ¹  -30.12% (p=0.008 n=5)
_nodeMutatedClear-8                   0.000 ± ∞ ¹
_nodeMutatedExists-8                  0.000 ± ∞ ¹
_find16-8                             0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_findIndex16-8                        0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_find4-8                              0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
_findIndex4-8                         0.000 ± ∞ ¹    0.000 ± ∞ ¹        ~ (p=1.000 n=5) ²
geomean                                         ³                  -2.42%               ⁴ ³
¹ need >= 6 samples for confidence interval at level 0.95
² all samples are equal
³ summaries must be >0 to compute geomean
⁴ benchmark set differs from baseline; geomeans may not be comparable

                         │   old.txt    │               new.txt                │
                         │ objects/sec  │ objects/sec   vs base                │
_Insert_RootOnlyWatch-8    13.65M ± ∞ ¹   13.74M ± ∞ ¹         ~ (p=0.310 n=5)
_Insert-8                  9.854M ± ∞ ¹   9.562M ± ∞ ¹    -2.96% (p=0.008 n=5)
_Modify-8                  16.83M ± ∞ ¹   16.17M ± ∞ ¹    -3.91% (p=0.008 n=5)
_GetInsert-8               13.01M ± ∞ ¹   12.86M ± ∞ ¹    -1.10% (p=0.032 n=5)
_Replace-8                 50.28M ± ∞ ¹   47.16M ± ∞ ¹    -6.21% (p=0.008 n=5)
_Replace_RootOnlyWatch-8   50.26M ± ∞ ¹   47.16M ± ∞ ¹    -6.16% (p=0.008 n=5)
_txn_1-8                   6.695M ± ∞ ¹   7.753M ± ∞ ¹   +15.80% (p=0.008 n=5)
_txn_10-8                  10.97M ± ∞ ¹   13.47M ± ∞ ¹   +22.77% (p=0.008 n=5)
_txn_100-8                 15.70M ± ∞ ¹   15.66M ± ∞ ¹         ~ (p=1.000 n=5)
_txn_1000-8                13.54M ± ∞ ¹   13.70M ± ∞ ¹         ~ (p=0.056 n=5)
_txn_delete_1-8            2.106M ± ∞ ¹   5.550M ± ∞ ¹  +163.52% (p=0.008 n=5)
_txn_delete_10-8           10.31M ± ∞ ¹   14.46M ± ∞ ¹   +40.22% (p=0.008 n=5)
_txn_delete_100-8          15.79M ± ∞ ¹   16.42M ± ∞ ¹    +4.02% (p=0.008 n=5)
_txn_delete_1000-8         18.84M ± ∞ ¹   19.93M ± ∞ ¹    +5.77% (p=0.008 n=5)
_Get-8                     61.32M ± ∞ ¹   59.17M ± ∞ ¹    -3.50% (p=0.008 n=5)
_All-8                     214.9M ± ∞ ¹   219.7M ± ∞ ¹         ~ (p=0.056 n=5)
_Iterator_All-8            218.4M ± ∞ ¹   219.2M ± ∞ ¹         ~ (p=0.841 n=5)
_Iterator_Next-8           206.4M ± ∞ ¹   202.6M ± ∞ ¹    -1.81% (p=0.008 n=5)
_Hashmap_Insert-8          26.50M ± ∞ ¹   25.29M ± ∞ ¹    -4.57% (p=0.008 n=5)
_Hashmap_Get_Uint64-8      175.7M ± ∞ ¹   174.4M ± ∞ ¹         ~ (p=1.000 n=5)
_Hashmap_Get_Bytes-8       163.6M ± ∞ ¹   158.0M ± ∞ ¹    -3.42% (p=0.032 n=5)
_Delete_Random-8           2.491M ± ∞ ¹   8.534M ± ∞ ¹  +242.51% (p=0.008 n=5)
geomean                    25.46M         28.75M         +12.93%
¹ need >= 6 samples for confidence interval at level 0.95

Signed-off-by: Jussi Maki <jussi.maki@isovalent.com>
@joamaki joamaki force-pushed the pr/joamaki/part-txnid branch from 7b19b7c to 4d4ef5c Compare January 15, 2026 10:05
@joamaki joamaki merged commit 2c43851 into main Jan 15, 2026
1 check passed
@joamaki joamaki deleted the pr/joamaki/part-txnid branch January 15, 2026 10:14
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.

3 participants