Skip to content

Commit

Permalink
storage: reduce intent interleaving allocations
Browse files Browse the repository at this point in the history
When seeking to a specific version, the intent interleaving iterator may need
to construct the immediate successor next key to serve as a seek key within the
lock table. The roachpb.NextKey method avoids allocations when its receiver's
underlying slice already contains a trailing zero byte after the key. In all
other cases, it must allocate and copy the receiver slice. In the context of
the intent interleaving iterator, this is unnecessary. The intent interleaving
iterator only temporarily needs to compute the next key for the purpose of
constructing a lock-table seek key. Also, the intent interleaving iterator has
a buffer available for constructing intent seek keys.

This commit adds a new keys.LockTableSingleNextKey function that behaves
identically to `keys.LockTableSingleKey(key.Next(), buf)` but avoids
the intermediary step of materializing the next key.

MVCC garbage collection frequently seeks to a specific version, so the removal
of this allocation and key copy is visible on the MVCCGarbageCollect
microbenchmark.

```
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=32/numRangeTs=1/updateStats=true-24          1.070 ±   ∞ ¹    1.070 ±   1%          ~ (p=0.768 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=32/numRangeTs=100/updateStats=false-24       1.097 ±  3%      1.120 ±    ∞ ¹        ~ (p=0.286 n=6+1)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=2/deleteVersions=1/numRangeTs=0/updateStats=false-24               4.974µ ±   ∞ ¹   4.790µ ±   1%     -3.70% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=2/deleteVersions=1/numRangeTs=0/updateStats=true-24                5.377µ ±   ∞ ¹   4.882µ ±   2%     -9.22% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=2/deleteVersions=1/numRangeTs=1/updateStats=false-24               7.648µ ±   ∞ ¹   7.399µ ±   1%     -3.26% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=32/numRangeTs=100/updateStats=true-24        1.090 ±  6%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=2/deleteVersions=1/numRangeTs=1/updateStats=true-24                8.615µ ±   ∞ ¹   8.271µ ±   2%     -4.00% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=2/deleteVersions=1/numRangeTs=2/updateStats=false-24               8.249µ ±   ∞ ¹   7.925µ ±   2%     -3.93% (p=0.008 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=512/numRangeTs=0/updateStats=false-24        1.021 ± 48%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=2/deleteVersions=1/numRangeTs=2/updateStats=true-24                9.208µ ±   ∞ ¹   8.860µ ±   1%     -3.78% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=512/numRangeTs=0/updateStats=true-24         1.023 ± 50%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1/numRangeTs=0/updateStats=false-24            8.699µ ±   ∞ ¹   8.389µ ±   3%     -3.57% (p=0.028 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1/numRangeTs=0/updateStats=true-24             9.266µ ±   ∞ ¹   8.528µ ±   5%     -7.96% (p=0.013 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=512/numRangeTs=1/updateStats=false-24        1.112 ±  3%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1/numRangeTs=1/updateStats=false-24            13.02µ ±   ∞ ¹   12.15µ ±   2%     -6.70% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=512/numRangeTs=1/updateStats=true-24         1.096 ±  2%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1/numRangeTs=1/updateStats=true-24             13.49µ ±   ∞ ¹   12.76µ ±   3%     -5.38% (p=0.019 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1/numRangeTs=100/updateStats=false-24          48.72µ ±   ∞ ¹   47.08µ ±   2%     -3.37% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=512/numRangeTs=100/updateStats=false-24      1.125 ±  7%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1/numRangeTs=100/updateStats=true-24           57.19µ ±   ∞ ¹   54.01µ ±   2%     -5.56% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=16/numRangeTs=0/updateStats=false-24           13.97µ ±   ∞ ¹   13.21µ ±   2%          ~ (p=0.099 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=512/numRangeTs=100/updateStats=true-24       1.124 ±  4%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=16/numRangeTs=0/updateStats=true-24            15.22µ ±   ∞ ¹   14.67µ ±   1%     -3.58% (p=0.005 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=16/numRangeTs=1/updateStats=false-24           18.44µ ±   ∞ ¹   17.91µ ±   2%          ~ (p=0.165 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1015/numRangeTs=0/updateStats=false-24       1.077 ±  9%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=16/numRangeTs=1/updateStats=true-24            21.51µ ±   ∞ ¹   20.70µ ±   1%     -3.76% (p=0.005 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1015/numRangeTs=0/updateStats=true-24        1.058 ±  4%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=16/numRangeTs=100/updateStats=false-24         56.21µ ±   ∞ ¹   53.02µ ±   2%     -5.67% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1015/numRangeTs=1/updateStats=false-24       1.161 ±  7%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=16/numRangeTs=100/updateStats=true-24          66.05µ ±   ∞ ¹   62.73µ ±   2%     -5.04% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1015/numRangeTs=1/updateStats=true-24        1.155 ±  4%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=32/numRangeTs=0/updateStats=false-24           19.37µ ±   ∞ ¹   18.38µ ±   2%     -5.12% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=32/numRangeTs=0/updateStats=true-24            21.58µ ±   ∞ ¹   21.12µ ±   1%     -2.14% (p=0.005 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=32/numRangeTs=1/updateStats=false-24           24.83µ ±   ∞ ¹   23.84µ ±   2%     -3.96% (p=0.005 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1015/numRangeTs=100/updateStats=false-24     1.143 ±  8%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=32/numRangeTs=1/updateStats=true-24            29.28µ ±   ∞ ¹   28.70µ ±   1%     -2.00% (p=0.003 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=32/numRangeTs=100/updateStats=false-24         62.35µ ±   ∞ ¹   58.89µ ±   1%     -5.54% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1015/numRangeTs=100/updateStats=true-24      1.188 ±  8%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1023/numRangeTs=0/updateStats=false-24       1.057 ±  5%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=32/numRangeTs=100/updateStats=true-24          76.47µ ±   ∞ ¹   72.01µ ±   1%     -5.84% (p=0.019 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1023/numRangeTs=0/updateStats=true-24        1.075 ±  4%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=512/numRangeTs=0/updateStats=false-24          172.4µ ±   ∞ ¹   169.8µ ±   1%     -1.51% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1023/numRangeTs=1/updateStats=false-24       1.172 ±  7%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=512/numRangeTs=0/updateStats=true-24           215.9µ ±   ∞ ¹   211.7µ ±   1%     -1.94% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=512/numRangeTs=1/updateStats=false-24          208.5µ ±   ∞ ¹   202.8µ ±   1%     -2.69% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1023/numRangeTs=1/updateStats=true-24        1.148 ±  7%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=512/numRangeTs=1/updateStats=true-24           271.8µ ±   ∞ ¹   266.5µ ±   1%     -1.94% (p=0.008 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=512/numRangeTs=100/updateStats=false-24        249.6µ ±   ∞ ¹   243.7µ ±   1%          ~ (p=0.165 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1023/numRangeTs=100/updateStats=false-24     1.137 ± 11%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=512/numRangeTs=100/updateStats=true-24         331.4µ ±   ∞ ¹   329.1µ ±   0%     -0.69% (p=0.005 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1015/numRangeTs=0/updateStats=false-24         332.7µ ±   ∞ ¹   329.6µ ±   2%          ~ (p=0.055 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1015/numRangeTs=0/updateStats=true-24          417.0µ ±   ∞ ¹   411.7µ ±   1%     -1.26% (p=0.003 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1023/numRangeTs=100/updateStats=true-24      1.098 ± 12%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1015/numRangeTs=1/updateStats=false-24         396.5µ ±   ∞ ¹   393.7µ ±   0%          ~ (p=0.055 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1015/numRangeTs=1/updateStats=true-24          526.4µ ±   ∞ ¹   523.8µ ±   1%          ~ (p=0.099 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1015/numRangeTs=100/updateStats=false-24       439.7µ ±   ∞ ¹   434.0µ ±   2%     -1.29% (p=0.019 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1015/numRangeTs=100/updateStats=true-24        597.9µ ±   ∞ ¹   592.1µ ±   1%     -0.98% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1023/numRangeTs=0/updateStats=false-24         331.7µ ±   ∞ ¹   327.5µ ±   1%     -1.25% (p=0.019 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1023/numRangeTs=0/updateStats=true-24          415.3µ ±   ∞ ¹   413.1µ ±   1%          ~ (p=0.099 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1023/numRangeTs=1/updateStats=false-24         397.1µ ±   ∞ ¹   392.4µ ±   1%     -1.17% (p=0.003 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1023/numRangeTs=1/updateStats=true-24          528.8µ ±   ∞ ¹   520.0µ ±   1%     -1.66% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1023/numRangeTs=100/updateStats=false-24       440.6µ ±   ∞ ¹   433.9µ ±   0%     -1.52% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1023/numRangeTs=100/updateStats=true-24        596.3µ ±   ∞ ¹   593.4µ ±   0%     -0.48% (p=0.008 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=2/deleteVersions=1/numRangeTs=0/updateStats=false-24            1.754m ±   ∞ ¹   1.762m ±   1%          ~ (p=0.254 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=2/deleteVersions=1/numRangeTs=0/updateStats=true-24             1.858m ±   ∞ ¹   1.826m ±   1%          ~ (p=0.099 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=2/deleteVersions=1/numRangeTs=1/updateStats=false-24            2.510m ±   ∞ ¹   2.516m ±   2%          ~ (p=0.513 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=2/deleteVersions=1/numRangeTs=1/updateStats=true-24             2.714m ±   ∞ ¹   2.723m ±   1%          ~ (p=0.371 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=2/deleteVersions=1/numRangeTs=2/updateStats=false-24            2.563m ±   ∞ ¹   2.545m ±   2%          ~ (p=0.679 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=2/deleteVersions=1/numRangeTs=2/updateStats=true-24             2.713m ±   ∞ ¹   2.758m ±   1%     +1.67% (p=0.040 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1/numRangeTs=0/updateStats=false-24         87.58m ±   ∞ ¹   89.34m ± 181%          ~ (p=0.513 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1/numRangeTs=0/updateStats=true-24          503.6m ±   ∞ ¹   333.8m ± 204%          ~ (p=1.000 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1/numRangeTs=1/updateStats=false-24          1.040 ±   ∞ ¹    1.065 ±   2%          ~ (p=0.055 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1/numRangeTs=1/updateStats=true-24           1.049 ±   ∞ ¹    1.064 ±   1%          ~ (p=0.075 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1/numRangeTs=100/updateStats=false-24        1.062 ±   ∞ ¹    1.065 ±   2%          ~ (p=0.371 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1/numRangeTs=100/updateStats=true-24         1.064 ±   ∞ ¹    1.068 ±   4%          ~ (p=1.000 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=16/numRangeTs=0/updateStats=false-24        341.7m ±   ∞ ¹   420.4m ±  40%          ~ (p=0.953 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=16/numRangeTs=0/updateStats=true-24        1003.3m ±   ∞ ¹   257.5m ±  96%    -74.33% (p=0.028 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=16/numRangeTs=1/updateStats=false-24         1.053 ±   ∞ ¹    1.071 ±   3%          ~ (p=0.165 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=16/numRangeTs=1/updateStats=true-24          1.054 ±   ∞ ¹    1.059 ±   1%          ~ (p=0.859 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=16/numRangeTs=100/updateStats=false-24       1.074 ±   ∞ ¹    1.074 ±   1%          ~ (p=0.953 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=16/numRangeTs=100/updateStats=true-24        1.096 ±   ∞ ¹    1.086 ±   4%          ~ (p=0.206 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=32/numRangeTs=0/updateStats=false-24       1011.4m ±   ∞ ¹   506.2m ±  59%    -49.95% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=32/numRangeTs=0/updateStats=true-24         510.0m ±   ∞ ¹   505.9m ±  34%          ~ (p=0.254 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=32/numRangeTs=1/updateStats=false-24         1.082 ±   ∞ ¹    1.066 ±   2%          ~ (p=0.129 n=5+10)

                                                                                                                                        │   allocs/op    │    allocs/op     vs base                    │
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=32/numRangeTs=1/updateStats=true-24        4.662k ±   ∞ ¹   3.618k ±   1%    -22.39% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=32/numRangeTs=100/updateStats=false-24     12.95k ±  7%     11.40k ±    ∞ ¹        ~ (p=0.286 n=6+1)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=2/deleteVersions=1/numRangeTs=0/updateStats=false-24               8.000 ±   ∞ ¹    8.000 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=2/deleteVersions=1/numRangeTs=0/updateStats=true-24                8.000 ±   ∞ ¹    8.000 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=2/deleteVersions=1/numRangeTs=1/updateStats=false-24               10.00 ±   ∞ ¹    10.00 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=32/numRangeTs=100/updateStats=true-24      13.12k ±  5%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=2/deleteVersions=1/numRangeTs=1/updateStats=true-24                14.00 ±   ∞ ¹    14.00 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=2/deleteVersions=1/numRangeTs=2/updateStats=false-24               10.00 ±   ∞ ¹    10.00 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=512/numRangeTs=0/updateStats=false-24      4.421k ± 37%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=2/deleteVersions=1/numRangeTs=2/updateStats=true-24                14.00 ±   ∞ ¹    14.00 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=512/numRangeTs=0/updateStats=true-24       4.427k ± 37%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1/numRangeTs=0/updateStats=false-24            12.00 ±   ∞ ¹    11.00 ±   0%     -8.33% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1/numRangeTs=0/updateStats=true-24             12.00 ±   ∞ ¹    11.00 ±   0%     -8.33% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=512/numRangeTs=1/updateStats=false-24      4.663k ±  1%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1/numRangeTs=1/updateStats=false-24            14.00 ±   ∞ ¹    13.00 ±   0%     -7.14% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=512/numRangeTs=1/updateStats=true-24       4.663k ±  1%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1/numRangeTs=1/updateStats=true-24             18.00 ±   ∞ ¹    17.00 ±   0%     -5.56% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1/numRangeTs=100/updateStats=false-24          23.00 ±   ∞ ¹    22.00 ±   0%     -4.35% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=512/numRangeTs=100/updateStats=false-24    12.97k ±  3%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1/numRangeTs=100/updateStats=true-24           27.00 ±   ∞ ¹    26.00 ±   0%     -3.70% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=16/numRangeTs=0/updateStats=false-24           12.00 ±   ∞ ¹    11.00 ±   0%     -8.33% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=512/numRangeTs=100/updateStats=true-24     12.70k ±  6%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=16/numRangeTs=0/updateStats=true-24            12.00 ±   ∞ ¹    11.00 ±   0%     -8.33% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=16/numRangeTs=1/updateStats=false-24           14.00 ±   ∞ ¹    13.00 ±   0%     -7.14% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1015/numRangeTs=0/updateStats=false-24     4.519k ±  8%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=16/numRangeTs=1/updateStats=true-24            18.00 ±   ∞ ¹    17.00 ±   0%     -5.56% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1015/numRangeTs=0/updateStats=true-24      4.510k ±  2%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=16/numRangeTs=100/updateStats=false-24         23.00 ±   ∞ ¹    22.00 ±   0%     -4.35% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1015/numRangeTs=1/updateStats=false-24     4.738k ±  1%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=16/numRangeTs=100/updateStats=true-24          27.00 ±   ∞ ¹    26.00 ±   0%     -3.70% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1015/numRangeTs=1/updateStats=true-24      4.729k ±  2%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=32/numRangeTs=0/updateStats=false-24           12.00 ±   ∞ ¹    11.00 ±   0%     -8.33% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=32/numRangeTs=0/updateStats=true-24            12.00 ±   ∞ ¹    11.00 ±   0%     -8.33% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=32/numRangeTs=1/updateStats=false-24           14.00 ±   ∞ ¹    13.00 ±   0%     -7.14% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1015/numRangeTs=100/updateStats=false-24   13.00k ±  6%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=32/numRangeTs=1/updateStats=true-24            18.00 ±   ∞ ¹    17.00 ±   0%     -5.56% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=32/numRangeTs=100/updateStats=false-24         23.00 ±   ∞ ¹    22.00 ±   0%     -4.35% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1015/numRangeTs=100/updateStats=true-24    12.92k ±  6%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1023/numRangeTs=0/updateStats=false-24     3.466k ±  2%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=32/numRangeTs=100/updateStats=true-24          27.00 ±   ∞ ¹    26.00 ±   0%     -3.70% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1023/numRangeTs=0/updateStats=true-24      3.514k ±  2%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=512/numRangeTs=0/updateStats=false-24          13.00 ±   ∞ ¹    12.00 ±   0%     -7.69% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1023/numRangeTs=1/updateStats=false-24     3.700k ±  1%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=512/numRangeTs=0/updateStats=true-24           13.00 ±   ∞ ¹    12.00 ±   0%     -7.69% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=512/numRangeTs=1/updateStats=false-24          15.00 ±   ∞ ¹    14.00 ±   0%     -6.67% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1023/numRangeTs=1/updateStats=true-24      3.704k ±  2%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=512/numRangeTs=1/updateStats=true-24           19.00 ±   ∞ ¹    18.00 ±   0%     -5.26% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=512/numRangeTs=100/updateStats=false-24        24.00 ±   ∞ ¹    23.00 ±   0%     -4.17% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1023/numRangeTs=100/updateStats=false-24   11.69k ±  6%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=512/numRangeTs=100/updateStats=true-24         28.00 ±   ∞ ¹    27.00 ±   0%     -3.57% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1015/numRangeTs=0/updateStats=false-24         13.00 ±   ∞ ¹    12.00 ±   0%     -7.69% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1015/numRangeTs=0/updateStats=true-24          13.00 ±   ∞ ¹    12.00 ±   0%     -7.69% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1023/numRangeTs=100/updateStats=true-24    11.78k ±  7%
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1015/numRangeTs=1/updateStats=false-24         15.00 ±   ∞ ¹    14.00 ±   0%     -6.67% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1015/numRangeTs=1/updateStats=true-24          19.00 ±   ∞ ¹    18.00 ±   0%     -5.26% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1015/numRangeTs=100/updateStats=false-24       23.00 ±   ∞ ¹    22.00 ±   0%     -4.35% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1015/numRangeTs=100/updateStats=true-24        28.00 ±   ∞ ¹    27.00 ±   0%     -3.57% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1023/numRangeTs=0/updateStats=false-24         9.000 ±   ∞ ¹    9.000 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1023/numRangeTs=0/updateStats=true-24          9.000 ±   ∞ ¹    9.000 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1023/numRangeTs=1/updateStats=false-24         11.00 ±   ∞ ¹    11.00 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1023/numRangeTs=1/updateStats=true-24          15.00 ±   ∞ ¹    15.00 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1023/numRangeTs=100/updateStats=false-24       19.00 ±   ∞ ¹    19.00 ±   0%          ~ (p=0.527 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1/numVersions=1024/deleteVersions=1023/numRangeTs=100/updateStats=true-24        24.00 ±   ∞ ¹    24.00 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=2/deleteVersions=1/numRangeTs=0/updateStats=false-24            12.00 ±   ∞ ¹    12.00 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=2/deleteVersions=1/numRangeTs=0/updateStats=true-24             12.00 ±   ∞ ¹    12.00 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=2/deleteVersions=1/numRangeTs=1/updateStats=false-24            15.00 ±   ∞ ¹    15.00 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=2/deleteVersions=1/numRangeTs=1/updateStats=true-24             19.00 ±   ∞ ¹    19.00 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=2/deleteVersions=1/numRangeTs=2/updateStats=false-24            16.00 ±   ∞ ¹    16.00 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=2/deleteVersions=1/numRangeTs=2/updateStats=true-24             23.00 ±   ∞ ¹    23.00 ±   0%          ~ (p=1.000 n=5+10) ²
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1/numRangeTs=0/updateStats=false-24        1328.0 ±   ∞ ¹    317.0 ± 174%    -76.13% (p=0.005 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1/numRangeTs=0/updateStats=true-24         2.742k ±   ∞ ¹   1.137k ± 203%          ~ (p=0.055 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1/numRangeTs=1/updateStats=false-24        4.652k ±   ∞ ¹   3.616k ±   1%    -22.27% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1/numRangeTs=1/updateStats=true-24         4.650k ±   ∞ ¹   3.618k ±   1%    -22.19% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1/numRangeTs=100/updateStats=false-24      13.09k ±   ∞ ¹   11.97k ±   6%     -8.62% (p=0.005 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=1/numRangeTs=100/updateStats=true-24       13.22k ±   ∞ ¹   12.09k ±   3%     -8.56% (p=0.003 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=16/numRangeTs=0/updateStats=false-24       2.182k ±   ∞ ¹   1.447k ±  39%    -33.68% (p=0.028 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=16/numRangeTs=0/updateStats=true-24        4422.0 ±   ∞ ¹    872.0 ±  98%    -80.28% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=16/numRangeTs=1/updateStats=false-24       4.630k ±   ∞ ¹   3.611k ±   1%    -22.02% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=16/numRangeTs=1/updateStats=true-24        4.638k ±   ∞ ¹   3.634k ±   1%    -21.66% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=16/numRangeTs=100/updateStats=false-24     12.80k ±   ∞ ¹   11.94k ±   4%     -6.67% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=16/numRangeTs=100/updateStats=true-24      12.75k ±   ∞ ¹   11.97k ±   3%     -6.08% (p=0.013 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=32/numRangeTs=0/updateStats=false-24       4.441k ±   ∞ ¹   1.722k ±  59%    -61.21% (p=0.001 n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=32/numRangeTs=0/updateStats=true-24        2.755k ±   ∞ ¹   1.720k ±  33%    -37.57% (n=5+10)
MVCCGarbageCollect/pebble/keySize=128/valSize=128/numKeys=1024/numVersions=1024/deleteVersions=32/numRangeTs=1/updateStats=false-24       4.663k ±   ∞ ¹   3.616k ±   1%    -22.44% (p=0.001 n=5+10)
```

Informs #97570.
Epic: None
Release note: None
  • Loading branch information
jbowens committed Feb 27, 2023
1 parent e7c2286 commit 0b2c235
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 2 deletions.
18 changes: 18 additions & 0 deletions pkg/keys/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,24 @@ func LockTableSingleKey(key roachpb.Key, buf []byte) (roachpb.Key, []byte) {
return buf, buf
}

// LockTableSingleNextKey is equivalent to LockTableSingleKey(key.Next(), buf)
// but avoids an extra allocation in cases where key.Next() must allocate.
func LockTableSingleNextKey(key roachpb.Key, buf []byte) (roachpb.Key, []byte) {
keyLen := len(LocalRangeLockTablePrefix) + len(LockTableSingleKeyInfix) + encoding.EncodeNextBytesSize(key)
if cap(buf) < keyLen {
buf = make([]byte, 0, keyLen)
} else {
buf = buf[:0]
}
// Don't unwrap any local prefix on key using Addr(key). This allow for
// doubly-local lock table keys. For example, local range descriptor keys can
// be locked during split and merge transactions.
buf = append(buf, LocalRangeLockTablePrefix...)
buf = append(buf, LockTableSingleKeyInfix...)
buf = encoding.EncodeNextBytesAscending(buf, key)
return buf, buf
}

// DecodeLockTableSingleKey decodes the single-key lock table key to return the key
// that was locked.
func DecodeLockTableSingleKey(key roachpb.Key) (lockedKey roachpb.Key, err error) {
Expand Down
25 changes: 25 additions & 0 deletions pkg/keys/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -772,3 +772,28 @@ func TestLockTableKeyEncodeDecode(t *testing.T) {
})
}
}

func TestLockTableSingleKeyNext_Equivalent(t *testing.T) {
testCases := []struct {
key roachpb.Key
}{
{key: roachpb.Key("foo")},
{key: roachpb.Key("a")},
{key: roachpb.Key("")},
// Causes a doubly-local range local key.
{key: RangeDescriptorKey(roachpb.RKey("baz"))},
}
for _, test := range testCases {
t.Run("", func(t *testing.T) {
next := test.key.Next()
want, _ := LockTableSingleKey(next, nil)

got, _ := LockTableSingleNextKey(test.key, nil)
require.Equal(t, want, got)

k, err := DecodeLockTableSingleKey(got)
require.NoError(t, err)
require.Equal(t, next, k)
})
}
}
4 changes: 2 additions & 2 deletions pkg/storage/intent_interleaving_iter.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ func (i *intentInterleavingIter) SeekGE(key MVCCKey) {
intentSeekKey, i.intentKeyBuf = keys.LockTableSingleKey(key.Key, i.intentKeyBuf)
} else if !i.prefix {
// Seeking to a specific version, so go past the intent.
intentSeekKey, i.intentKeyBuf = keys.LockTableSingleKey(key.Key.Next(), i.intentKeyBuf)
intentSeekKey, i.intentKeyBuf = keys.LockTableSingleNextKey(key.Key, i.intentKeyBuf)
} else {
// Else seeking to a particular version and using prefix iteration,
// so don't expect to ever see the intent. NB: intentSeekKey is nil.
Expand Down Expand Up @@ -1103,7 +1103,7 @@ func (i *intentInterleavingIter) SeekLT(key MVCCKey) {
// Seeking to a specific version, so need to see the intent. Since we need
// to see the intent for key.Key, and we don't have SeekLE, call Next() on
// the key before doing SeekLT.
intentSeekKey, i.intentKeyBuf = keys.LockTableSingleKey(key.Key.Next(), i.intentKeyBuf)
intentSeekKey, i.intentKeyBuf = keys.LockTableSingleNextKey(key.Key, i.intentKeyBuf)
}
var limitKey roachpb.Key
if i.iterValid {
Expand Down
33 changes: 33 additions & 0 deletions pkg/util/encoding/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,23 @@ func EncodeBytesAscending(b []byte, data []byte) []byte {
return encodeBytesAscendingWithTerminatorAndPrefix(b, data, ascendingBytesEscapes.escapedTerm, bytesMarker)
}

// EncodeNextBytesAscending encodes the []byte value with an extra 0x00 byte
// appended before encoding. It's equivalent to
//
// EncodeBytesAscending(b, append(data, 0x00))
//
// but may avoid an allocation when the data slice does not have additional
// capacity.
func EncodeNextBytesAscending(b []byte, data []byte) []byte {
b = append(b, bytesMarker)
return encodeNextBytesAscendingWithTerminator(b, data, ascendingBytesEscapes.escapedTerm)
}

func encodeNextBytesAscendingWithTerminator(b []byte, data []byte, terminator byte) []byte {
bs := encodeBytesAscendingWithoutTerminatorOrPrefix(b, data)
return append(bs, escape, escaped00, escape, terminator)
}

// encodeBytesAscendingWithTerminatorAndPrefix encodes the []byte value using an escape-based
// encoding. The encoded value is terminated with the sequence
// "\x00\terminator". The encoded bytes are append to the supplied buffer
Expand Down Expand Up @@ -676,6 +693,22 @@ func EncodeBytesSize(data []byte) int {
return len(data) + 3 + bytes.Count(data, []byte{escape})
}

// EncodeNextBytesSize returns the size of the []byte value when suffixed with a
// zero byte and then encoded using EncodeNextBytes{Ascending,Descending}. The
// function accounts for the encoding marker, escaping, and the terminator.
func EncodeNextBytesSize(data []byte) int {
// Encoding overhead:
// +1 for [bytesMarker] prefix
// +2 for [escape, escapedTerm] suffix
// +1 for each byte that needs to be escaped
// +2 for the appended 0x00 byte, plus its escaping byte
//
// NOTE: bytes.Count is implemented by the go runtime in assembly and is
// much faster than looping over the bytes in the slice, especially when
// given a single-byte separator.
return len(data) + 5 + bytes.Count(data, []byte{escape})
}

// DecodeBytesAscending decodes a []byte value from the input buffer
// which was encoded using EncodeBytesAscending. The decoded bytes
// are appended to r. The remainder of the input buffer and the
Expand Down
50 changes: 50 additions & 0 deletions pkg/util/encoding/encoding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,56 @@ func TestEncodeDecodeBytesAscending(t *testing.T) {
}
}

func TestEncodeNextBytesAscending_Equivalence(t *testing.T) {
for _, b := range [][]byte{
{0, 1, 'a'},
{0, 'a'},
{0, 0xff, 'a'},
{'a'},
{'b'},
{'b', 0},
{'b', 0, 0},
{'b', 0, 0, 'a'},
{'b', 0xff},
{'h', 'e', 'l', 'l', 'o'},
} {
next := append(b, 0x00)

gotSz := EncodeNextBytesSize(b)
wantSz := EncodeBytesSize(next)
if gotSz != wantSz {
t.Errorf("EncodeNextBytesSize(%q) = %d; want %d", b, gotSz, wantSz)
}
gotV := EncodeNextBytesAscending(nil, b)
wantV := EncodeBytesAscending(nil, next)
if !bytes.Equal(gotV, wantV) {
t.Errorf("EncodeNextBytesAscending(%q) = %q; want %q", b, gotV, wantV)
}
}
}

func TestEncodeNextBytesAscending_Equivalence_Randomized(t *testing.T) {
rnd, _ := randutil.NewTestRand()
var buf [10]byte
var nextBuf [10 + 1]byte
for i := 0; i < 1000; i++ {
b := buf[:randutil.RandIntInRange(rnd, 1, cap(buf))]
randutil.ReadTestdataBytes(rnd, b)
next := append(append(nextBuf[:0], b...), 0x00)

gotSz := EncodeNextBytesSize(b)
wantSz := EncodeBytesSize(next)
if gotSz != wantSz {
t.Errorf("EncodeNextBytesSize(%q) = %d; want %d", b, gotSz, wantSz)
}
gotV := EncodeNextBytesAscending(nil, b)
wantV := EncodeBytesAscending(nil, next)
if !bytes.Equal(gotV, wantV) {
t.Errorf("EncodeNextBytesAscending(%q) = %q; want %q", b, gotV, wantV)
}
}
}

func TestEncodeDecodeBytesDescending(t *testing.T) {
testCases := []struct {
value []byte
Expand Down

0 comments on commit 0b2c235

Please sign in to comment.