Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store gateway mmap removal: optimise index-header reader and symbol lookups #3742

Merged
merged 13 commits into from
Dec 20, 2022

Conversation

charleskorn
Copy link
Contributor

@charleskorn charleskorn commented Dec 16, 2022

What this PR does

Note to reviewers: this PR is made up of three main commits that build upon each other. I'd suggest reviewing each separately.


de7f5af improves the performance of loading index-headers with the mmap-less reader by 0-23%. This is due to removing an unnecessary allocation for every value of the postings offset table.

Benchmark results
name                                         old time/op    new time/op    delta
NewStreamBinaryReader/1Names1Values-10          122µs ± 8%     122µs ± 5%     ~     (p=0.690 n=5+5)
NewStreamBinaryReader/1Names10Values-10         124µs ± 4%     131µs ± 9%     ~     (p=0.056 n=5+5)
NewStreamBinaryReader/1Names100Values-10        138µs ± 2%     135µs ± 3%     ~     (p=0.056 n=5+5)
NewStreamBinaryReader/1Names500Values-10        187µs ± 4%     177µs ± 2%   -5.31%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       262µs ± 2%     229µs ± 2%  -12.53%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       837µs ± 3%     689µs ± 1%  -17.62%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10         168µs ± 2%     169µs ± 3%     ~     (p=1.000 n=5+5)
NewStreamBinaryReader/20Names10Values-10        199µs ± 2%     194µs ± 2%   -2.56%  (p=0.032 n=5+5)
NewStreamBinaryReader/20Names100Values-10       505µs ± 1%     438µs ± 7%  -13.20%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names500Values-10      1.63ms ± 1%    1.31ms ± 0%  -19.49%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names1000Values-10     2.90ms ± 3%    2.28ms ± 2%  -21.30%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names5000Values-10     12.9ms ± 2%     9.9ms ± 2%  -22.69%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-10         276µs ± 0%     280µs ± 1%   +1.64%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names10Values-10        368µs ± 1%     347µs ± 2%   -5.82%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names100Values-10      1.10ms ± 4%    0.91ms ± 2%  -17.15%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-10      3.73ms ± 3%    2.97ms ± 2%  -20.32%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     6.74ms ± 2%    5.29ms ± 2%  -21.61%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names5000Values-10     32.0ms ± 0%    24.9ms ± 1%  -22.30%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names1Values-10        547µs ± 1%     543µs ± 1%     ~     (p=0.286 n=4+5)
NewStreamBinaryReader/100Names10Values-10       728µs ± 4%     678µs ± 3%   -6.89%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10     2.08ms ± 5%    1.73ms ± 5%  -16.87%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names500Values-10     7.13ms ± 1%    5.63ms ± 2%  -21.06%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    13.3ms ± 2%    10.2ms ± 2%  -23.17%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names5000Values-10    64.9ms ± 2%    49.8ms ± 1%  -23.20%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10       1.17ms ± 0%    1.16ms ± 2%     ~     (p=0.190 n=4+5)
NewStreamBinaryReader/200Names10Values-10      1.49ms ± 0%    1.39ms ± 1%   -6.68%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names100Values-10     4.05ms ± 3%    3.35ms ± 3%  -17.32%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names500Values-10     14.4ms ± 2%    11.5ms ± 1%  -20.30%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1000Values-10    27.3ms ± 2%    21.1ms ± 3%  -22.79%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10     131ms ± 2%     100ms ± 2%  -23.35%  (p=0.008 n=5+5)

name                                         old alloc/op   new alloc/op   delta
NewStreamBinaryReader/1Names1Values-10         3.18MB ± 0%    3.18MB ± 0%   -0.00%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names10Values-10        3.18MB ± 0%    3.18MB ± 0%   -0.01%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10       3.18MB ± 0%    3.18MB ± 0%   -0.10%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-10       3.20MB ± 0%    3.19MB ± 0%   -0.50%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10      3.23MB ± 0%    3.20MB ± 0%   -0.99%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10      3.44MB ± 0%    3.28MB ± 0%   -4.66%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10        3.18MB ± 0%    3.18MB ± 0%   -0.02%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names10Values-10       3.19MB ± 0%    3.19MB ± 0%   -0.20%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10      3.29MB ± 0%    3.22MB ± 0%   -1.95%  (p=0.016 n=5+4)
NewStreamBinaryReader/20Names500Values-10      3.70MB ± 0%    3.38MB ± 0%   -8.65%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names1000Values-10     4.22MB ± 0%    3.58MB ± 0%  -15.17%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names5000Values-10     8.63MB ± 0%    5.43MB ± 0%  -37.09%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names1Values-10        3.19MB ± 0%    3.19MB ± 0%   -0.05%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-10       3.21MB ± 0%    3.20MB ± 0%   -0.50%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names100Values-10      3.45MB ± 0%    3.29MB ± 0%   -4.64%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-10      4.48MB ± 0%    3.68MB ± 0%  -17.85%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     5.78MB ± 0%    4.18MB ± 0%  -27.67%  (p=0.016 n=5+4)
NewStreamBinaryReader/50Names5000Values-10     17.3MB ± 0%     9.3MB ± 0%  -46.28%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1Values-10       3.20MB ± 0%    3.20MB ± 0%   -0.10%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names10Values-10      3.25MB ± 0%    3.22MB ± 0%   -0.99%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10     3.72MB ± 0%    3.40MB ± 0%   -8.60%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names500Values-10     5.79MB ± 0%    4.19MB ± 0%  -27.65%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    8.39MB ± 0%    5.19MB ± 0%  -38.15%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names5000Values-10    31.7MB ± 0%    15.7MB ± 0%  -50.46%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10       3.22MB ± 0%    3.22MB ± 0%   -0.20%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names10Values-10      3.32MB ± 0%    3.26MB ± 0%   -1.93%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names100Values-10     4.27MB ± 0%    3.63MB ± 0%  -15.00%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names500Values-10     8.72MB ± 0%    5.52MB ± 0%  -36.72%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names1000Values-10    14.3MB ± 0%     7.9MB ± 0%  -44.70%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10    61.3MB ± 0%    29.3MB ± 0%  -52.22%  (p=0.008 n=5+5)

name                                         old allocs/op  new allocs/op  delta
NewStreamBinaryReader/1Names1Values-10           78.0 ± 0%      76.0 ± 0%   -2.56%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names10Values-10           106 ± 0%        95 ± 0%  -10.38%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10          379 ± 0%       278 ± 0%  -26.65%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-10        1.58k ± 0%     1.08k ± 0%  -31.69%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       3.08k ± 0%     2.08k ± 0%  -32.48%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       15.1k ± 0%     10.1k ± 0%  -33.15%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10           175 ± 0%       154 ± 0%  -12.00%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names10Values-10          735 ± 0%       534 ± 0%  -27.35%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10       6.20k ± 0%     4.19k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/20Names500Values-10       30.2k ± 0%     20.2k ± 0%  -33.08%  (p=0.000 n=5+4)
NewStreamBinaryReader/20Names1000Values-10      60.3k ± 0%     40.3k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/20Names5000Values-10       300k ± 0%      200k ± 0%  -33.30%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names1Values-10           329 ± 0%       278 ± 0%  -15.50%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-10        1.73k ± 0%     1.23k ± 0%  -28.98%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-10       15.4k ± 0%     10.4k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/50Names500Values-10       75.5k ± 0%     50.5k ± 0%  -33.12%  (p=0.000 n=4+5)
NewStreamBinaryReader/50Names1000Values-10       151k ± 0%      101k ± 0%  -33.22%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names5000Values-10       751k ± 0%      501k ± 0%  -33.31%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names1Values-10          582 ± 0%       481 ± 0%  -17.35%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names10Values-10       3.38k ± 0%     2.38k ± 0%  -29.61%  (p=0.000 n=5+4)
NewStreamBinaryReader/100Names100Values-10      30.7k ± 0%     20.7k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/100Names500Values-10       151k ± 0%      101k ± 0%  -33.14%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names1000Values-10      301k ± 0%      201k ± 0%  -33.23%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names5000Values-10     1.50M ± 0%     1.00M ± 0%  -33.31%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10        1.08k ± 0%     0.88k ± 0%  -18.56%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names10Values-10       6.68k ± 0%     4.68k ± 0%  -29.94%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names100Values-10      61.3k ± 0%     41.3k ± 0%  -32.64%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names500Values-10       302k ± 0%      202k ± 0%  -33.15%  (p=0.000 n=5+4)
NewStreamBinaryReader/200Names1000Values-10      602k ± 0%      402k ± 0%  -33.23%  (p=0.000 n=5+4)
NewStreamBinaryReader/200Names5000Values-10     3.00M ± 0%     2.00M ± 0%  -33.31%  (p=0.000 n=5+4)

40efcae improves the performance of LookupSymbol by skipping over unwanted symbols, saving ~2% in the best case scenario (all value symbol lookups, no name symbol lookups).

Benchmark results
name                                        old time/op    new time/op    delta
LookupSymbol/NameLookups0%-Parallelism1-10    8.57µs ± 0%    8.37µs ± 2%  -2.37%  (p=0.008 n=5+5)

2a119aa uses the same idea while reading the symbol table, resulting in anywhere up to a 2% improvement over 1d98754 for realistic index-headers:

Benchmark results (compared to 1d98754)
name                                         old time/op    new time/op    delta
NewStreamBinaryReader/1Names1Values-10          128µs ± 1%     123µs ± 2%  -4.25%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names10Values-10         128µs ± 1%     122µs ± 1%  -4.95%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10        137µs ± 3%     133µs ± 1%  -2.84%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-10        169µs ± 4%     161µs ± 1%  -4.87%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       201µs ± 3%     192µs ± 3%  -4.47%  (p=0.016 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       541µs ± 5%     494µs ± 2%  -8.64%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10         178µs ± 4%     169µs ± 1%  -4.89%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names10Values-10        216µs ± 4%     200µs ± 0%  -7.14%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10       374µs ± 5%     360µs ± 5%    ~     (p=0.095 n=5+5)
NewStreamBinaryReader/20Names500Values-10       955µs ± 1%     907µs ± 4%  -5.05%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1000Values-10     1.60ms ± 0%    1.54ms ± 3%    ~     (p=0.063 n=4+5)
NewStreamBinaryReader/20Names5000Values-10     6.56ms ± 3%    6.26ms ± 1%  -4.64%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-10         297µs ± 4%     276µs ± 1%  -7.14%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-10        401µs ± 6%     384µs ± 4%  -4.25%  (p=0.032 n=5+5)
NewStreamBinaryReader/50Names100Values-10       738µs ± 3%     716µs ± 2%  -2.97%  (p=0.032 n=5+5)
NewStreamBinaryReader/50Names500Values-10      2.10ms ± 3%    2.06ms ± 3%    ~     (p=0.151 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     3.68ms ± 2%    3.59ms ± 2%    ~     (p=0.056 n=5+5)
NewStreamBinaryReader/50Names5000Values-10     15.8ms ± 2%    15.4ms ± 1%  -2.77%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1Values-10        556µs ± 6%     534µs ± 0%  -4.09%  (p=0.016 n=5+4)
NewStreamBinaryReader/100Names10Values-10       753µs ± 1%     736µs ± 2%  -2.18%  (p=0.032 n=5+5)
NewStreamBinaryReader/100Names100Values-10     1.40ms ± 4%    1.38ms ± 4%    ~     (p=0.222 n=5+5)
NewStreamBinaryReader/100Names500Values-10     3.95ms ± 3%    3.91ms ± 1%    ~     (p=0.310 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    6.92ms ± 1%    6.92ms ± 1%    ~     (p=1.000 n=5+5)
NewStreamBinaryReader/100Names5000Values-10    30.9ms ± 0%    30.8ms ± 1%    ~     (p=0.095 n=5+5)
NewStreamBinaryReader/200Names1Values-10       1.17ms ± 6%    1.14ms ± 0%  -2.33%  (p=0.032 n=5+4)
NewStreamBinaryReader/200Names10Values-10      1.54ms ± 6%    1.84ms ±43%    ~     (p=0.548 n=5+5)
NewStreamBinaryReader/200Names100Values-10     2.73ms ± 3%    2.74ms ± 3%    ~     (p=0.421 n=5+5)
NewStreamBinaryReader/200Names500Values-10     7.62ms ± 1%    7.58ms ± 1%    ~     (p=0.151 n=5+5)
NewStreamBinaryReader/200Names1000Values-10    13.7ms ± 1%    13.7ms ± 1%    ~     (p=0.222 n=5+5)
NewStreamBinaryReader/200Names5000Values-10    62.4ms ± 1%    61.9ms ± 0%  -0.79%  (p=0.029 n=4+4)

1d98754 is the more complex one. It is inspired by prometheus/prometheus#11535.

On my machine (a M1 MacBook Pro with a fast SSD), this results in up to 37% better performance compared to de7f5af, and 52% better performance compared to main. I've also observed similar performance gains on machines with spinning rust disks (up to 62% better performance compared to main).

Explanation of changes

Unfortunately, we can't adopt prometheus/prometheus#11535 as-is, as byte slices returned by our new Decbuf.UvarintBytes() implementation are not valid after subsequent reads because the underlying buffer may have been overwritten.

This means that we must decide whether or not to allocate a string for a label name or value before reading any further in the file. However, we want to store the last value for each name, but won't know if the value is the last one until we've read the next one.

To deal with this limitation, whenever we come to the beginning of a new label name's entries in the table, we seek backwards to read the last entry for the previous name and populate that before resuming with the new name.

This PR previously had a two-pass implementation for this change. Benchmarking of the final single-pass implementation included here showed the single-pass implementation saved another 3-7% (when using a SSD) or 5-12% (when using a spinning rust disk) for index headers with a small number of label names and a large number of values, which is what we'd expect in the real world.

I suspect this implementation could be improved even further: every seek operation requires us to call the bufio.Reader's Reset() method, which discards its buffer and requires it to be refilled from disk. If we used a buffered reader that supported seeking backwards, we could avoid a number of unnecessary disk reads.

I haven't applied this optimisation to the v1 reader yet, but that case should be straightforward given we retain every name and value. This could be a follow-up PR.

Benchmark results: compared to de7f5af with SSD
name                                         old time/op    new time/op    delta
NewStreamBinaryReader/1Names1Values-10          122µs ± 5%     136µs ± 4%  +11.59%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names10Values-10         131µs ± 9%     129µs ± 7%     ~     (p=0.841 n=5+5)
NewStreamBinaryReader/1Names100Values-10        135µs ± 3%     135µs ± 1%     ~     (p=0.841 n=5+5)
NewStreamBinaryReader/1Names500Values-10        177µs ± 2%     164µs ± 2%   -7.43%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       229µs ± 2%     198µs ± 2%  -13.59%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       689µs ± 1%     518µs ± 2%  -24.80%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10         169µs ± 3%     171µs ± 1%     ~     (p=0.310 n=5+5)
NewStreamBinaryReader/20Names10Values-10        194µs ± 2%     208µs ± 2%   +6.99%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10       438µs ± 7%     383µs ± 2%  -12.57%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names500Values-10      1.31ms ± 0%    0.93ms ± 3%  -28.94%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names1000Values-10     2.28ms ± 2%    1.57ms ± 3%  -31.19%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names5000Values-10     9.95ms ± 2%    6.33ms ± 1%  -36.32%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-10         280µs ± 1%     291µs ± 5%   +3.77%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-10        347µs ± 2%     394µs ± 5%  +13.50%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-10       910µs ± 2%     730µs ± 2%  -19.78%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-10      2.97ms ± 2%    2.08ms ± 3%  -30.00%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     5.29ms ± 2%    3.63ms ± 2%  -31.25%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names5000Values-10     24.9ms ± 1%    15.5ms ± 0%  -37.81%  (p=0.016 n=5+4)
NewStreamBinaryReader/100Names1Values-10        543µs ± 1%     542µs ± 3%     ~     (p=0.151 n=5+5)
NewStreamBinaryReader/100Names10Values-10       678µs ± 3%     741µs ± 3%   +9.33%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10     1.73ms ± 5%    1.40ms ± 5%  -19.31%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names500Values-10     5.63ms ± 2%    3.97ms ± 2%  -29.52%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    10.2ms ± 2%     7.0ms ± 1%  -32.03%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names5000Values-10    49.8ms ± 1%    31.1ms ± 0%  -37.54%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10       1.16ms ± 2%    1.16ms ± 3%     ~     (p=0.690 n=5+5)
NewStreamBinaryReader/200Names10Values-10      1.39ms ± 1%    1.57ms ± 4%  +13.04%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names100Values-10     3.35ms ± 3%    2.73ms ± 3%  -18.30%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names500Values-10     11.5ms ± 1%     7.6ms ± 1%  -33.61%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1000Values-10    21.1ms ± 3%    13.7ms ± 1%  -35.02%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10     100ms ± 2%      62ms ± 1%  -37.62%  (p=0.008 n=5+5)

name                                         old alloc/op   new alloc/op   delta
NewStreamBinaryReader/1Names1Values-10         3.18MB ± 0%    3.18MB ± 0%     ~     (p=0.373 n=5+5)
NewStreamBinaryReader/1Names10Values-10        3.18MB ± 0%    3.18MB ± 0%   -0.00%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10       3.18MB ± 0%    3.18MB ± 0%   -0.05%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-10       3.19MB ± 0%    3.18MB ± 0%   -0.24%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10      3.20MB ± 0%    3.18MB ± 0%   -0.48%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10      3.28MB ± 0%    3.20MB ± 0%   -2.37%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10        3.18MB ± 0%    3.18MB ± 0%     ~     (p=0.357 n=5+5)
NewStreamBinaryReader/20Names10Values-10       3.19MB ± 0%    3.18MB ± 0%   -0.09%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10      3.22MB ± 0%    3.19MB ± 0%   -0.96%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names500Values-10      3.38MB ± 0%    3.22MB ± 0%   -4.59%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names1000Values-10     3.58MB ± 0%    3.27MB ± 0%   -8.66%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names5000Values-10     5.43MB ± 0%    3.56MB ± 0%  -34.45%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names1Values-10        3.19MB ± 0%    3.19MB ± 0%     ~     (p=0.921 n=5+5)
NewStreamBinaryReader/50Names10Values-10       3.20MB ± 0%    3.19MB ± 0%   -0.21%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-10      3.29MB ± 0%    3.21MB ± 0%   -2.36%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-10      3.68MB ± 0%    3.29MB ± 0%  -10.54%  (p=0.016 n=5+4)
NewStreamBinaryReader/50Names1000Values-10     4.18MB ± 0%    3.41MB ± 0%  -18.53%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names5000Values-10     9.29MB ± 0%    4.13MB ± 0%  -55.53%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1Values-10       3.20MB ± 0%    3.20MB ± 0%     ~     (p=0.254 n=5+5)
NewStreamBinaryReader/100Names10Values-10      3.22MB ± 0%    3.20MB ± 0%   -0.42%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10     3.40MB ± 0%    3.25MB ± 0%   -4.56%  (p=0.016 n=5+4)
NewStreamBinaryReader/100Names500Values-10     4.19MB ± 0%    3.41MB ± 0%  -18.54%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    5.19MB ± 0%    3.64MB ± 0%  -29.89%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names5000Values-10    15.7MB ± 0%     5.1MB ± 0%  -67.66%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10       3.22MB ± 0%    3.22MB ± 0%     ~     (p=1.000 n=5+5)
NewStreamBinaryReader/200Names10Values-10      3.26MB ± 0%    3.23MB ± 0%   -0.84%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names100Values-10     3.63MB ± 0%    3.32MB ± 0%   -8.56%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names500Values-10     5.52MB ± 0%    3.64MB ± 0%  -33.95%  (p=0.016 n=5+4)
NewStreamBinaryReader/200Names1000Values-10    7.92MB ± 0%    4.10MB ± 0%  -48.23%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10    29.3MB ± 0%     7.0MB ± 0%  -76.16%  (p=0.008 n=5+5)

name                                         old allocs/op  new allocs/op  delta
NewStreamBinaryReader/1Names1Values-10           76.0 ± 0%      76.0 ± 0%     ~     (all equal)
NewStreamBinaryReader/1Names10Values-10          95.0 ± 0%      78.0 ± 0%  -17.89%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10          278 ± 0%        84 ± 0%  -69.78%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-10        1.08k ± 0%     0.10k ± 0%  -90.93%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       2.08k ± 0%     0.12k ± 0%  -94.47%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       10.1k ± 0%      0.2k ± 0%  -97.60%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10           154 ± 0%       154 ± 0%     ~     (all equal)
NewStreamBinaryReader/20Names10Values-10          534 ± 0%       194 ± 0%  -63.67%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10       4.19k ± 0%     0.31k ± 0%  -92.51%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names500Values-10       20.2k ± 0%      0.6k ± 0%  -97.06%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names1000Values-10      40.3k ± 0%      0.9k ± 0%  -97.68%  (p=0.000 n=5+4)
NewStreamBinaryReader/20Names5000Values-10       200k ± 0%        3k ± 0%  -98.27%  (p=0.000 n=4+5)
NewStreamBinaryReader/50Names1Values-10           278 ± 0%       278 ± 0%     ~     (all equal)
NewStreamBinaryReader/50Names10Values-10        1.23k ± 0%     0.38k ± 0%  -69.22%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-10       10.4k ± 0%      0.7k ± 0%  -93.47%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-10       50.5k ± 0%      1.4k ± 0%  -97.27%  (p=0.000 n=5+4)
NewStreamBinaryReader/50Names1000Values-10       101k ± 0%        2k ± 0%  -97.78%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names5000Values-10       501k ± 0%        9k ± 0%  -98.29%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names1Values-10          481 ± 0%       481 ± 0%     ~     (all equal)
NewStreamBinaryReader/100Names10Values-10       2.38k ± 0%     0.68k ± 0%  -71.38%  (p=0.000 n=4+5)
NewStreamBinaryReader/100Names100Values-10      20.7k ± 0%      1.3k ± 0%  -93.80%  (p=0.000 n=5+4)
NewStreamBinaryReader/100Names500Values-10       101k ± 0%        3k ± 0%  -97.34%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-10      201k ± 0%        4k ± 0%  -97.82%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names5000Values-10     1.00M ± 0%     0.02M ± 0%  -98.29%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10          882 ± 0%       882 ± 0%     ~     (all equal)
NewStreamBinaryReader/200Names10Values-10       4.68k ± 0%     1.28k ± 0%  -72.62%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names100Values-10      41.3k ± 0%      2.5k ± 0%  -93.99%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names500Values-10       202k ± 0%        5k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/200Names1000Values-10      402k ± 0%        9k ± 0%  -97.84%  (p=0.000 n=4+5)
NewStreamBinaryReader/200Names5000Values-10     2.00M ± 0%     0.03M ± 0%  -98.30%  (p=0.029 n=4+4)
Benchmark results: compared to main with SSD
name                                         old time/op    new time/op    delta
NewStreamBinaryReader/1Names1Values-10          122µs ± 8%     136µs ± 4%  +11.78%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names10Values-10         124µs ± 4%     129µs ± 7%     ~     (p=0.151 n=5+5)
NewStreamBinaryReader/1Names100Values-10        138µs ± 2%     135µs ± 1%   -2.16%  (p=0.016 n=5+5)
NewStreamBinaryReader/1Names500Values-10        187µs ± 4%     164µs ± 2%  -12.35%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       262µs ± 2%     198µs ± 2%  -24.41%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       837µs ± 3%     518µs ± 2%  -38.05%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10         168µs ± 2%     171µs ± 1%   +1.56%  (p=0.032 n=5+5)
NewStreamBinaryReader/20Names10Values-10        199µs ± 2%     208µs ± 2%   +4.25%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10       505µs ± 1%     383µs ± 2%  -24.11%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names500Values-10      1.63ms ± 1%    0.93ms ± 3%  -42.79%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names1000Values-10     2.90ms ± 3%    1.57ms ± 3%  -45.85%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names5000Values-10     12.9ms ± 2%     6.3ms ± 1%  -50.77%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-10         276µs ± 0%     291µs ± 5%   +5.48%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names10Values-10        368µs ± 1%     394µs ± 5%   +6.89%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names100Values-10      1.10ms ± 4%    0.73ms ± 2%  -33.54%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-10      3.73ms ± 3%    2.08ms ± 3%  -44.22%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     6.74ms ± 2%    3.63ms ± 2%  -46.11%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names5000Values-10     32.0ms ± 0%    15.5ms ± 0%  -51.68%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names1Values-10        547µs ± 1%     542µs ± 3%     ~     (p=0.190 n=4+5)
NewStreamBinaryReader/100Names10Values-10       728µs ± 4%     741µs ± 3%     ~     (p=0.151 n=5+5)
NewStreamBinaryReader/100Names100Values-10     2.08ms ± 5%    1.40ms ± 5%  -32.92%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names500Values-10     7.13ms ± 1%    3.97ms ± 2%  -44.36%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    13.3ms ± 2%     7.0ms ± 1%  -47.78%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names5000Values-10    64.9ms ± 2%    31.1ms ± 0%  -52.04%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10       1.17ms ± 0%    1.16ms ± 3%     ~     (p=0.190 n=4+5)
NewStreamBinaryReader/200Names10Values-10      1.49ms ± 0%    1.57ms ± 4%   +5.49%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names100Values-10     4.05ms ± 3%    2.73ms ± 3%  -32.45%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names500Values-10     14.4ms ± 2%     7.6ms ± 1%  -47.09%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1000Values-10    27.3ms ± 2%    13.7ms ± 1%  -49.83%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10     131ms ± 2%      62ms ± 1%  -52.18%  (p=0.008 n=5+5)

name                                         old alloc/op   new alloc/op   delta
NewStreamBinaryReader/1Names1Values-10         3.18MB ± 0%    3.18MB ± 0%   -0.00%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names10Values-10        3.18MB ± 0%    3.18MB ± 0%   -0.02%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10       3.18MB ± 0%    3.18MB ± 0%   -0.15%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-10       3.20MB ± 0%    3.18MB ± 0%   -0.74%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10      3.23MB ± 0%    3.18MB ± 0%   -1.47%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10      3.44MB ± 0%    3.20MB ± 0%   -6.92%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10        3.18MB ± 0%    3.18MB ± 0%   -0.02%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names10Values-10       3.19MB ± 0%    3.18MB ± 0%   -0.29%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10      3.29MB ± 0%    3.19MB ± 0%   -2.89%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names500Values-10      3.70MB ± 0%    3.22MB ± 0%  -12.85%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names1000Values-10     4.22MB ± 0%    3.27MB ± 0%  -22.52%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names5000Values-10     8.63MB ± 0%    3.56MB ± 0%  -58.76%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names1Values-10        3.19MB ± 0%    3.19MB ± 0%   -0.05%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-10       3.21MB ± 0%    3.19MB ± 0%   -0.71%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names100Values-10      3.45MB ± 0%    3.21MB ± 0%   -6.89%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-10      4.48MB ± 0%    3.29MB ± 0%  -26.51%  (p=0.016 n=5+4)
NewStreamBinaryReader/50Names1000Values-10     5.78MB ± 0%    3.41MB ± 0%  -41.08%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names5000Values-10     17.3MB ± 0%     4.1MB ± 0%  -76.11%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1Values-10       3.20MB ± 0%    3.20MB ± 0%   -0.10%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names10Values-10      3.25MB ± 0%    3.20MB ± 0%   -1.40%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10     3.72MB ± 0%    3.25MB ± 0%  -12.77%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names500Values-10     5.79MB ± 0%    3.41MB ± 0%  -41.06%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    8.39MB ± 0%    3.64MB ± 0%  -56.63%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names5000Values-10    31.7MB ± 0%     5.1MB ± 0%  -83.98%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10       3.22MB ± 0%    3.22MB ± 0%   -0.20%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names10Values-10      3.32MB ± 0%    3.23MB ± 0%   -2.75%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names100Values-10     4.27MB ± 0%    3.32MB ± 0%  -22.27%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names500Values-10     8.72MB ± 0%    3.64MB ± 0%  -58.20%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names1000Values-10    14.3MB ± 0%     4.1MB ± 0%  -71.37%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10    61.3MB ± 0%     7.0MB ± 0%  -88.61%  (p=0.008 n=5+5)

name                                         old allocs/op  new allocs/op  delta
NewStreamBinaryReader/1Names1Values-10           78.0 ± 0%      76.0 ± 0%   -2.56%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names10Values-10           106 ± 0%        78 ± 0%  -26.42%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10          379 ± 0%        84 ± 0%  -77.84%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-10        1.58k ± 0%     0.10k ± 0%  -93.80%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       3.08k ± 0%     0.12k ± 0%  -96.27%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       15.1k ± 0%      0.2k ± 0%  -98.40%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10           175 ± 0%       154 ± 0%  -12.00%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names10Values-10          735 ± 0%       194 ± 0%  -73.61%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10       6.20k ± 0%     0.31k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/20Names500Values-10       30.2k ± 0%      0.6k ± 0%  -98.04%  (p=0.000 n=5+4)
NewStreamBinaryReader/20Names1000Values-10      60.3k ± 0%      0.9k ± 0%  -98.45%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names5000Values-10       300k ± 0%        3k ± 0%  -98.84%  (p=0.000 n=4+5)
NewStreamBinaryReader/50Names1Values-10           329 ± 0%       278 ± 0%  -15.50%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-10        1.73k ± 0%     0.38k ± 0%  -78.14%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-10       15.4k ± 0%      0.7k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/50Names500Values-10       75.5k ± 0%      1.4k ± 0%  -98.17%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names1000Values-10       151k ± 0%        2k ± 0%  -98.52%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names5000Values-10       751k ± 0%        9k ± 0%  -98.86%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names1Values-10          582 ± 0%       481 ± 0%  -17.35%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names10Values-10       3.38k ± 0%     0.68k ± 0%  -79.85%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10      30.7k ± 0%      1.3k ± 0%  -95.82%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names500Values-10       151k ± 0%        3k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/100Names1000Values-10      301k ± 0%        4k ± 0%  -98.54%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names5000Values-10     1.50M ± 0%     0.02M ± 0%  -98.86%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10        1.08k ± 0%     0.88k ± 0%  -18.56%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names10Values-10       6.68k ± 0%     1.28k ± 0%  -80.82%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names100Values-10      61.3k ± 0%      2.5k ± 0%  -95.95%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names500Values-10       302k ± 0%        5k ± 0%  -98.25%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1000Values-10      602k ± 0%        9k ± 0%  -98.56%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10     3.00M ± 0%     0.03M ± 0%  -98.86%  (p=0.000 n=5+4)

Benchmark results: compared to main with spinning rust disk
name                                        old time/op    new time/op    delta
NewStreamBinaryReader/1Names1Values-2         1.56ms ±17%    1.67ms ±10%     ~     (p=0.548 n=5+5)
NewStreamBinaryReader/1Names10Values-2        1.62ms ±19%    1.77ms ±17%     ~     (p=0.690 n=5+5)
NewStreamBinaryReader/1Names100Values-2       1.66ms ±39%    1.62ms ±17%     ~     (p=0.690 n=5+5)
NewStreamBinaryReader/1Names500Values-2       2.30ms ±15%    2.19ms ±40%     ~     (p=0.151 n=5+5)
NewStreamBinaryReader/1Names1000Values-2      1.85ms ± 7%    2.01ms ±14%     ~     (p=0.151 n=5+5)
NewStreamBinaryReader/1Names5000Values-2      4.00ms ±10%    2.64ms ±11%  -33.86%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-2        1.89ms ±18%    2.01ms ± 6%     ~     (p=0.310 n=5+5)
NewStreamBinaryReader/20Names10Values-2       2.07ms ±10%    1.87ms ±18%     ~     (p=0.222 n=5+5)
NewStreamBinaryReader/20Names100Values-2      3.34ms ± 4%    2.47ms ±13%  -25.91%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names500Values-2      6.85ms ±10%    4.28ms ±13%  -37.59%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1000Values-2     10.7ms ± 6%     5.8ms ± 9%  -46.29%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names5000Values-2     42.5ms ± 8%    17.3ms ± 2%  -59.28%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-2        2.05ms ± 1%    2.33ms ±12%  +13.78%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names10Values-2       2.69ms ±16%    2.60ms ± 7%     ~     (p=0.841 n=5+5)
NewStreamBinaryReader/50Names100Values-2      5.06ms ± 9%    3.71ms ±13%  -26.66%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-2      14.2ms ± 6%     7.2ms ±10%  -49.34%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1000Values-2     22.9ms ± 4%    11.4ms ± 7%  -50.06%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names5000Values-2      103ms ± 2%      41ms ± 2%  -60.12%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1Values-2       3.12ms ± 9%    3.36ms ±17%     ~     (p=0.548 n=5+5)
NewStreamBinaryReader/100Names10Values-2      4.05ms ±12%    3.85ms ±17%     ~     (p=0.421 n=5+5)
NewStreamBinaryReader/100Names100Values-2     8.04ms ±10%    5.65ms ± 4%  -29.78%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names500Values-2     23.1ms ± 2%    12.5ms ± 2%  -45.90%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-2    42.7ms ± 5%    20.0ms ± 5%  -53.26%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names5000Values-2     200ms ± 4%      79ms ± 2%  -60.60%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-2       5.10ms ±11%    5.11ms ± 9%     ~     (p=0.841 n=5+5)
NewStreamBinaryReader/200Names10Values-2      6.25ms ± 9%    6.09ms ± 5%     ~     (p=0.690 n=5+5)
NewStreamBinaryReader/200Names100Values-2     14.6ms ± 5%     9.6ms ±10%  -34.02%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names500Values-2     46.1ms ± 5%    21.9ms ± 3%  -52.61%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1000Values-2    85.3ms ± 4%    36.9ms ± 4%  -56.77%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-2     407ms ± 3%     152ms ± 3%  -62.57%  (p=0.008 n=5+5)

name                                        old alloc/op   new alloc/op   delta
NewStreamBinaryReader/1Names1Values-2         3.18MB ± 0%    3.18MB ± 0%   -0.00%  (p=0.032 n=5+5)
NewStreamBinaryReader/1Names10Values-2        3.18MB ± 0%    3.18MB ± 0%   -0.02%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-2       3.18MB ± 0%    3.18MB ± 0%   -0.15%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-2       3.20MB ± 0%    3.18MB ± 0%   -0.74%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-2      3.23MB ± 0%    3.18MB ± 0%   -1.47%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-2      3.44MB ± 0%    3.20MB ± 0%   -6.92%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-2        3.18MB ± 0%    3.18MB ± 0%   -0.02%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names10Values-2       3.19MB ± 0%    3.18MB ± 0%   -0.29%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names100Values-2      3.29MB ± 0%    3.19MB ± 0%   -2.89%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names500Values-2      3.70MB ± 0%    3.22MB ± 0%  -12.85%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names1000Values-2     4.22MB ± 0%    3.27MB ± 0%  -22.52%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names5000Values-2     8.63MB ± 0%    3.56MB ± 0%  -58.76%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-2        3.19MB ± 0%    3.19MB ± 0%   -0.05%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-2       3.21MB ± 0%    3.19MB ± 0%   -0.71%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-2      3.45MB ± 0%    3.21MB ± 0%   -6.89%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-2      4.48MB ± 0%    3.29MB ± 0%  -26.51%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1000Values-2     5.78MB ± 0%    3.41MB ± 0%  -41.08%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names5000Values-2     17.3MB ± 0%     4.1MB ± 0%  -76.11%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1Values-2       3.20MB ± 0%    3.20MB ± 0%   -0.10%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names10Values-2      3.25MB ± 0%    3.20MB ± 0%   -1.41%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-2     3.72MB ± 0%    3.25MB ± 0%  -12.77%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names500Values-2     5.79MB ± 0%    3.41MB ± 0%  -41.07%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-2    8.39MB ± 0%    3.64MB ± 0%  -56.63%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names5000Values-2    31.7MB ± 0%     5.1MB ± 0%  -83.98%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-2       3.22MB ± 0%    3.22MB ± 0%   -0.20%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names10Values-2      3.32MB ± 0%    3.23MB ± 0%   -2.75%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names100Values-2     4.27MB ± 0%    3.32MB ± 0%  -22.27%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names500Values-2     8.72MB ± 0%    3.64MB ± 0%  -58.20%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1000Values-2    14.3MB ± 0%     4.1MB ± 0%  -71.37%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-2    61.3MB ± 0%     7.0MB ± 0%  -88.61%  (p=0.008 n=5+5)

name                                        old allocs/op  new allocs/op  delta
NewStreamBinaryReader/1Names1Values-2           78.0 ± 0%      76.0 ± 0%   -2.56%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names10Values-2           106 ± 0%        78 ± 0%  -26.42%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-2          379 ± 0%        84 ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/1Names500Values-2        1.58k ± 0%     0.10k ± 0%  -93.80%  (p=0.029 n=4+4)
NewStreamBinaryReader/1Names1000Values-2       3.08k ± 0%     0.12k ± 0%  -96.27%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-2       15.1k ± 0%      0.2k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/20Names1Values-2           176 ± 0%       155 ± 0%  -11.93%  (p=0.000 n=5+4)
NewStreamBinaryReader/20Names10Values-2          736 ± 0%       195 ± 0%  -73.49%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-2       6.20k ± 0%     0.32k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/20Names500Values-2       30.2k ± 0%      0.6k ± 0%  -98.03%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names1000Values-2      60.3k ± 0%      0.9k ± 0%  -98.45%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names5000Values-2       300k ± 0%        3k ± 0%  -98.84%  (p=0.000 n=5+4)
NewStreamBinaryReader/50Names1Values-2           330 ± 0%       279 ± 0%  -15.45%  (p=0.000 n=5+4)
NewStreamBinaryReader/50Names10Values-2        1.73k ± 0%     0.38k ± 0%  -78.09%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-2       15.4k ± 0%      0.7k ± 0%  -95.59%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names500Values-2       75.5k ± 0%      1.4k ± 0%  -98.17%  (p=0.000 n=5+4)
NewStreamBinaryReader/50Names1000Values-2       151k ± 0%        2k ± 0%  -98.52%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names5000Values-2       751k ± 0%        9k ± 0%  -98.86%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1Values-2          584 ± 0%       483 ± 0%  -17.24%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names10Values-2       3.38k ± 0%     0.68k ± 0%  -79.82%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names100Values-2      30.7k ± 0%      1.3k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/100Names500Values-2       151k ± 0%        3k ± 0%  -98.22%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names1000Values-2      301k ± 0%        4k ± 0%  -98.54%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names5000Values-2     1.50M ± 0%     0.02M ± 0%  -98.86%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-2        1.09k ± 0%     0.89k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/200Names10Values-2       6.69k ± 0%     1.29k ± 0%  -80.77%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names100Values-2      61.3k ± 0%      2.5k ± 0%  -95.94%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names500Values-2       302k ± 0%        5k ± 0%  -98.25%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names1000Values-2      602k ± 0%        9k ± 0%  -98.56%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-2     3.00M ± 0%     0.03M ± 0%  -98.86%  (p=0.008 n=5+5)


Overall impact: reading the index header from disk is now 50-60% faster for realistic scenarios 🎉

Which issue(s) this PR fixes or relates to

#3465

Checklist

  • [n/a] Tests updated
  • [n/a] Documentation added
  • [n/a] CHANGELOG.md updated - the order of entries should be [CHANGE], [FEATURE], [ENHANCEMENT], [BUGFIX]

We always expect to read exactly one key and value, so there's no need
for the slice. This dramatically improves the performance of reading
an index-header with the mmap-less index-header reader:

name                                         old time/op    new time/op    delta
NewStreamBinaryReader/1Names1Values-10          122µs ± 8%     122µs ± 5%     ~     (p=0.690 n=5+5)
NewStreamBinaryReader/1Names10Values-10         124µs ± 4%     131µs ± 9%     ~     (p=0.056 n=5+5)
NewStreamBinaryReader/1Names100Values-10        138µs ± 2%     135µs ± 3%     ~     (p=0.056 n=5+5)
NewStreamBinaryReader/1Names500Values-10        187µs ± 4%     177µs ± 2%   -5.31%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       262µs ± 2%     229µs ± 2%  -12.53%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       837µs ± 3%     689µs ± 1%  -17.62%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10         168µs ± 2%     169µs ± 3%     ~     (p=1.000 n=5+5)
NewStreamBinaryReader/20Names10Values-10        199µs ± 2%     194µs ± 2%   -2.56%  (p=0.032 n=5+5)
NewStreamBinaryReader/20Names100Values-10       505µs ± 1%     438µs ± 7%  -13.20%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names500Values-10      1.63ms ± 1%    1.31ms ± 0%  -19.49%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names1000Values-10     2.90ms ± 3%    2.28ms ± 2%  -21.30%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names5000Values-10     12.9ms ± 2%     9.9ms ± 2%  -22.69%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-10         276µs ± 0%     280µs ± 1%   +1.64%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names10Values-10        368µs ± 1%     347µs ± 2%   -5.82%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names100Values-10      1.10ms ± 4%    0.91ms ± 2%  -17.15%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-10      3.73ms ± 3%    2.97ms ± 2%  -20.32%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     6.74ms ± 2%    5.29ms ± 2%  -21.61%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names5000Values-10     32.0ms ± 0%    24.9ms ± 1%  -22.30%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names1Values-10        547µs ± 1%     543µs ± 1%     ~     (p=0.286 n=4+5)
NewStreamBinaryReader/100Names10Values-10       728µs ± 4%     678µs ± 3%   -6.89%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10     2.08ms ± 5%    1.73ms ± 5%  -16.87%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names500Values-10     7.13ms ± 1%    5.63ms ± 2%  -21.06%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    13.3ms ± 2%    10.2ms ± 2%  -23.17%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names5000Values-10    64.9ms ± 2%    49.8ms ± 1%  -23.20%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10       1.17ms ± 0%    1.16ms ± 2%     ~     (p=0.190 n=4+5)
NewStreamBinaryReader/200Names10Values-10      1.49ms ± 0%    1.39ms ± 1%   -6.68%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names100Values-10     4.05ms ± 3%    3.35ms ± 3%  -17.32%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names500Values-10     14.4ms ± 2%    11.5ms ± 1%  -20.30%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1000Values-10    27.3ms ± 2%    21.1ms ± 3%  -22.79%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10     131ms ± 2%     100ms ± 2%  -23.35%  (p=0.008 n=5+5)

name                                         old alloc/op   new alloc/op   delta
NewStreamBinaryReader/1Names1Values-10         3.18MB ± 0%    3.18MB ± 0%   -0.00%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names10Values-10        3.18MB ± 0%    3.18MB ± 0%   -0.01%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10       3.18MB ± 0%    3.18MB ± 0%   -0.10%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-10       3.20MB ± 0%    3.19MB ± 0%   -0.50%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10      3.23MB ± 0%    3.20MB ± 0%   -0.99%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10      3.44MB ± 0%    3.28MB ± 0%   -4.66%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10        3.18MB ± 0%    3.18MB ± 0%   -0.02%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names10Values-10       3.19MB ± 0%    3.19MB ± 0%   -0.20%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10      3.29MB ± 0%    3.22MB ± 0%   -1.95%  (p=0.016 n=5+4)
NewStreamBinaryReader/20Names500Values-10      3.70MB ± 0%    3.38MB ± 0%   -8.65%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names1000Values-10     4.22MB ± 0%    3.58MB ± 0%  -15.17%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names5000Values-10     8.63MB ± 0%    5.43MB ± 0%  -37.09%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names1Values-10        3.19MB ± 0%    3.19MB ± 0%   -0.05%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-10       3.21MB ± 0%    3.20MB ± 0%   -0.50%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names100Values-10      3.45MB ± 0%    3.29MB ± 0%   -4.64%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-10      4.48MB ± 0%    3.68MB ± 0%  -17.85%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     5.78MB ± 0%    4.18MB ± 0%  -27.67%  (p=0.016 n=5+4)
NewStreamBinaryReader/50Names5000Values-10     17.3MB ± 0%     9.3MB ± 0%  -46.28%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1Values-10       3.20MB ± 0%    3.20MB ± 0%   -0.10%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names10Values-10      3.25MB ± 0%    3.22MB ± 0%   -0.99%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10     3.72MB ± 0%    3.40MB ± 0%   -8.60%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names500Values-10     5.79MB ± 0%    4.19MB ± 0%  -27.65%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    8.39MB ± 0%    5.19MB ± 0%  -38.15%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names5000Values-10    31.7MB ± 0%    15.7MB ± 0%  -50.46%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10       3.22MB ± 0%    3.22MB ± 0%   -0.20%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names10Values-10      3.32MB ± 0%    3.26MB ± 0%   -1.93%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names100Values-10     4.27MB ± 0%    3.63MB ± 0%  -15.00%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names500Values-10     8.72MB ± 0%    5.52MB ± 0%  -36.72%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names1000Values-10    14.3MB ± 0%     7.9MB ± 0%  -44.70%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10    61.3MB ± 0%    29.3MB ± 0%  -52.22%  (p=0.008 n=5+5)

name                                         old allocs/op  new allocs/op  delta
NewStreamBinaryReader/1Names1Values-10           78.0 ± 0%      76.0 ± 0%   -2.56%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names10Values-10           106 ± 0%        95 ± 0%  -10.38%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10          379 ± 0%       278 ± 0%  -26.65%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-10        1.58k ± 0%     1.08k ± 0%  -31.69%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       3.08k ± 0%     2.08k ± 0%  -32.48%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       15.1k ± 0%     10.1k ± 0%  -33.15%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10           175 ± 0%       154 ± 0%  -12.00%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names10Values-10          735 ± 0%       534 ± 0%  -27.35%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10       6.20k ± 0%     4.19k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/20Names500Values-10       30.2k ± 0%     20.2k ± 0%  -33.08%  (p=0.000 n=5+4)
NewStreamBinaryReader/20Names1000Values-10      60.3k ± 0%     40.3k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/20Names5000Values-10       300k ± 0%      200k ± 0%  -33.30%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names1Values-10           329 ± 0%       278 ± 0%  -15.50%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-10        1.73k ± 0%     1.23k ± 0%  -28.98%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-10       15.4k ± 0%     10.4k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/50Names500Values-10       75.5k ± 0%     50.5k ± 0%  -33.12%  (p=0.000 n=4+5)
NewStreamBinaryReader/50Names1000Values-10       151k ± 0%      101k ± 0%  -33.22%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names5000Values-10       751k ± 0%      501k ± 0%  -33.31%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names1Values-10          582 ± 0%       481 ± 0%  -17.35%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names10Values-10       3.38k ± 0%     2.38k ± 0%  -29.61%  (p=0.000 n=5+4)
NewStreamBinaryReader/100Names100Values-10      30.7k ± 0%     20.7k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/100Names500Values-10       151k ± 0%      101k ± 0%  -33.14%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names1000Values-10      301k ± 0%      201k ± 0%  -33.23%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names5000Values-10     1.50M ± 0%     1.00M ± 0%  -33.31%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10        1.08k ± 0%     0.88k ± 0%  -18.56%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names10Values-10       6.68k ± 0%     4.68k ± 0%  -29.94%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names100Values-10      61.3k ± 0%     41.3k ± 0%  -32.64%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names500Values-10       302k ± 0%      202k ± 0%  -33.15%  (p=0.000 n=5+4)
NewStreamBinaryReader/200Names1000Values-10      602k ± 0%      402k ± 0%  -33.23%  (p=0.000 n=5+4)
NewStreamBinaryReader/200Names5000Values-10     3.00M ± 0%     2.00M ± 0%  -33.31%  (p=0.000 n=5+4)
The exact performance improvement depends on the ratio of name lookups
to value lookups. In the best case (all value lookups, no name
lookups), we save a bit over 2%:

name                                        old time/op    new time/op    delta
LookupSymbol/NameLookups0%-Parallelism1-10    8.57µs ± 0%    8.37µs ± 2%  -2.37%  (p=0.008 n=5+5)
@pracucci
Copy link
Collaborator

pracucci commented Dec 16, 2022

I reviewed all commits except the last one, and they all LGTM. I would suggest to open a PR with them, cause I think we can merge them by EOD.

I'm now going to review the last commit.

@pracucci
Copy link
Collaborator

I haven't applied this optimisation to the v1 reader yet

We don't use v1 indexes in Mimir. They could still be uploaded if an OSS user uploads very old blocks, but I wouldn't optimize for them unless it's trivial (or removes duplicated code).

Copy link
Collaborator

@pracucci pracucci left a comment

Choose a reason for hiding this comment

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

Good job! The optimization in the last commit also makes sense to me. I just left a couple of minor comments and questions.

This optimization may me think about a possible even cooler optimization. What if we add a secondary index (written by the compactor) with already the exact data we want here, so 1/32 of values? Not for now, but something we may want to consider.

pkg/storegateway/indexheader/index/postings.go Outdated Show resolved Hide resolved
pkg/storegateway/indexheader/index/postings.go Outdated Show resolved Hide resolved
off := d.Uvarint64()
t.postings[currentKey].offsets = append(t.postings[currentKey].offsets, postingOffset{value: value, tableOff: offsetInTable})

if lastKey != currentKey {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you explain me this, please? Adding a comment may help. I got lost here (I think I got lost even when I reviewed the initial mmap-less PR).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are you asking about int64(off - crc32.Size)? Or why we need lastValOffset?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm asking about the whole if block:

if lastName != currentName {
    t.postings[lastName].lastValOffset = int64(off - crc32.Size)
}

If we switched to a new symbol name, we update the previous symbol name setting the offset of the last value to off - crc32.Size. But isn't off the offset of the current symbol value? I'm sure I'm missing something...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not 100% sure about this, but this is my understanding:

t.postings[name].lastValOffset is the offset of the last byte of the postings section in the index file for the last value for name name. We use this to calculate what range of the index file we need to download if a query touches this label.

Postings sections are sorted in the same order used to sort the postings offset table. So if we've just read the first postings offset table entry for a new label name, and this first entry of the new label has its postings section at offset off, then the previous postings section (for the last value for the previous name) ends just before off.

Each postings section ends with a CRC32 checksum, and we don't check these at query time, so we can save 4 bytes by skipping the trailing four bytes.

Visually, it looks like this:

offset for "name-1" >┌────────────────────┬────────────────────┐
="value-9" points    │ len <4b>           │ #entries <4b>      │
here                 ├─┬──────────────────┼──────────────────┬─┤
                     │ ├─────────────────────────────────────┤ │
                     │ │ ref(series_1) <4b>                  │ │
                     │ ├─────────────────────────────────────┤ │  Postings
                     │ │ ...                                 │ │  section for
                     │ ├─────────────────────────────────────┤ │  "name-1"="value-9"
                     │ │ ref(series_n) <4b>                  │ │
                     │ ├─────────────────────────────────────┤ │
                     ├─┴─────────────────────────────────────┴─┤
                     │ CRC32 <4b>                              │
offset for "name-2" >├────────────────────┬────────────────────┤
="value-1" points    │ len <4b>           │ #entries <4b>      │
here                 ├─┬──────────────────┼──────────────────┬─┤
                     │ ├─────────────────────────────────────┤ │
                     │ │ ref(series_1) <4b>                  │ │
                     │ ├─────────────────────────────────────┤ │  Postings
                     │ │ ...                                 │ │  section for
                     │ ├─────────────────────────────────────┤ │  "name-2"="value-1"
                     │ │ ref(series_n) <4b>                  │ │
                     │ ├─────────────────────────────────────┤ │
                     ├─┴─────────────────────────────────────┴─┤
                     │ CRC32 <4b>                              │
                     └─────────────────────────────────────────┘

                                          .
                                          .
                                          .
                                          .

@56quarters
Copy link
Contributor

40efcae improves the performance of LookupSymbol by skipping over unwanted symbols, saving ~2% in the best case scenario (all value symbol lookups, no name symbol lookups).

Doesn't need to be done as part of this PR but there a few places that we use UvarintBytes() just to skip over bytes.

@charleskorn
Copy link
Contributor Author

I haven't applied this optimisation to the v1 reader yet

We don't use v1 indexes in Mimir. They could still be uploaded if an OSS user uploads very old blocks, but I wouldn't optimize for them unless it's trivial (or removes duplicated code).

Yeah that's why I didn't bother with v1 just yet - there might be some low-hanging fruit there as well, but my focus is on v2 for now.

@charleskorn
Copy link
Contributor Author

This optimization may me think about a possible even cooler optimization. What if we add a secondary index (written by the compactor) with already the exact data we want here, so 1/32 of values? Not for now, but something we may want to consider.

Interesting idea - I've created #3761 so we don't lose track of this.

…ng unnecessary strings.

This is inspired by prometheus/prometheus#11535.

Unfortunately, we can't adopt that change as-is, as byte slices
returned by our new Decbuf.UvarintBytes() implementation are not valid
after subsequent reads - we can't take advantage of the magic of mmap.

This means that we must decide whether or not to allocate a string
for a key or value before reading any further in the file. However,
we want to store the last value for each key, but won't know if the
value is the last one until we've read the next one.

The trick is to read the table in two passes. On the first pass, we
read every 1-in-postingOffsetsInMemSampling entries, and keep track of
the position of the last value for each key.

On the second pass, we go back and read the last values for each key.

(I've started with two passes to avoid seeking backwards and
discarding the entire file buffer every time we start reading a new
key - it may be interesting to see if discarding the buffer is as
expensive as I expect.)

This involves a trade off: we'll scan the index-header file twice, but
gain massively reduced memory allocations. On my machine (a M1 MacBook
Pro with a fast SSD), the trade off pays off.

Compared to the previous commit:

name                                         old time/op    new time/op    delta
NewStreamBinaryReader/1Names1Values-10          122µs ± 5%     129µs ±13%     ~     (p=0.151 n=5+5)
NewStreamBinaryReader/1Names10Values-10         131µs ± 9%     124µs ± 2%     ~     (p=0.056 n=5+5)
NewStreamBinaryReader/1Names100Values-10        135µs ± 3%     133µs ± 3%     ~     (p=0.548 n=5+5)
NewStreamBinaryReader/1Names500Values-10        177µs ± 2%     162µs ± 1%   -8.29%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       229µs ± 2%     198µs ± 2%  -13.51%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       689µs ± 1%     535µs ± 2%  -22.37%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10         169µs ± 3%     171µs ± 2%     ~     (p=0.310 n=5+5)
NewStreamBinaryReader/20Names10Values-10        194µs ± 2%     188µs ± 4%     ~     (p=0.056 n=5+5)
NewStreamBinaryReader/20Names100Values-10       438µs ± 7%     355µs ± 6%  -19.07%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names500Values-10      1.31ms ± 0%    0.94ms ± 3%  -28.29%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names1000Values-10     2.28ms ± 2%    1.62ms ± 3%  -29.16%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names5000Values-10     9.95ms ± 2%    6.71ms ± 1%  -32.57%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-10         280µs ± 1%     277µs ± 1%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/50Names10Values-10        347µs ± 2%     322µs ± 2%   -7.08%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-10       910µs ± 2%     701µs ± 1%  -22.94%  (p=0.016 n=5+4)
NewStreamBinaryReader/50Names500Values-10      2.97ms ± 2%    2.14ms ± 3%  -28.06%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     5.29ms ± 2%    3.79ms ± 2%  -28.32%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names5000Values-10     24.9ms ± 1%    16.6ms ± 1%  -33.42%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1Values-10        543µs ± 1%     548µs ± 3%     ~     (p=0.548 n=5+5)
NewStreamBinaryReader/100Names10Values-10       678µs ± 3%     632µs ± 4%   -6.77%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10     1.73ms ± 5%    1.37ms ± 5%  -21.00%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names500Values-10     5.63ms ± 2%    4.08ms ± 2%  -27.62%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    10.2ms ± 2%     7.3ms ± 1%  -29.01%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names5000Values-10    49.8ms ± 1%    33.4ms ± 0%  -33.04%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10       1.16ms ± 2%    1.16ms ± 2%     ~     (p=0.548 n=5+5)
NewStreamBinaryReader/200Names10Values-10      1.39ms ± 1%    1.29ms ± 2%   -6.95%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names100Values-10     3.35ms ± 3%    2.68ms ± 4%  -20.01%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names500Values-10     11.5ms ± 1%     8.0ms ± 0%  -30.78%  (p=0.016 n=5+4)
NewStreamBinaryReader/200Names1000Values-10    21.1ms ± 3%    14.5ms ± 1%  -31.39%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10     100ms ± 2%      67ms ± 0%  -32.81%  (p=0.008 n=5+5)

name                                         old alloc/op   new alloc/op   delta
NewStreamBinaryReader/1Names1Values-10         3.18MB ± 0%    3.18MB ± 0%   +0.00%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names10Values-10        3.18MB ± 0%    3.18MB ± 0%   -0.00%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10       3.18MB ± 0%    3.18MB ± 0%   -0.05%  (p=0.016 n=5+4)
NewStreamBinaryReader/1Names500Values-10       3.19MB ± 0%    3.18MB ± 0%   -0.24%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10      3.20MB ± 0%    3.18MB ± 0%   -0.48%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10      3.28MB ± 0%    3.20MB ± 0%   -2.36%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10        3.18MB ± 0%    3.18MB ± 0%   +0.06%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names10Values-10       3.19MB ± 0%    3.18MB ± 0%   -0.02%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10      3.22MB ± 0%    3.19MB ± 0%   -0.90%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names500Values-10      3.38MB ± 0%    3.23MB ± 0%   -4.54%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names1000Values-10     3.58MB ± 0%    3.27MB ± 0%   -8.61%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names5000Values-10     5.43MB ± 0%    3.56MB ± 0%  -34.41%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names1Values-10        3.19MB ± 0%    3.19MB ± 0%   +0.13%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-10       3.20MB ± 0%    3.19MB ± 0%   -0.09%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-10      3.29MB ± 0%    3.22MB ± 0%   -2.24%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-10      3.68MB ± 0%    3.30MB ± 0%  -10.44%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     4.18MB ± 0%    3.41MB ± 0%  -18.44%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names5000Values-10     9.29MB ± 0%    4.13MB ± 0%  -55.48%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1Values-10       3.20MB ± 0%    3.21MB ± 0%   +0.25%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names10Values-10      3.22MB ± 0%    3.21MB ± 0%   -0.17%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10     3.40MB ± 0%    3.26MB ± 0%   -4.32%  (p=0.016 n=5+4)
NewStreamBinaryReader/100Names500Values-10     4.19MB ± 0%    3.42MB ± 0%  -18.36%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    5.19MB ± 0%    3.65MB ± 0%  -29.73%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names5000Values-10    15.7MB ± 0%     5.1MB ± 0%  -67.61%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10       3.22MB ± 0%    3.23MB ± 0%   +0.51%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names10Values-10      3.26MB ± 0%    3.25MB ± 0%   -0.33%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names100Values-10     3.63MB ± 0%    3.33MB ± 0%   -8.11%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names500Values-10     5.52MB ± 0%    3.66MB ± 0%  -33.68%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1000Values-10    7.92MB ± 0%    4.12MB ± 0%  -48.02%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10    29.3MB ± 0%     7.0MB ± 0%  -76.10%  (p=0.016 n=5+4)

name                                         old allocs/op  new allocs/op  delta
NewStreamBinaryReader/1Names1Values-10           76.0 ± 0%      78.0 ± 0%   +2.63%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names10Values-10          95.0 ± 0%      80.0 ± 0%  -15.79%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10          278 ± 0%        86 ± 0%  -69.06%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-10        1.08k ± 0%     0.10k ± 0%  -90.74%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       2.08k ± 0%     0.12k ± 0%  -94.38%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       10.1k ± 0%      0.2k ± 0%  -97.58%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10           154 ± 0%       160 ± 0%   +3.90%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names10Values-10          534 ± 0%       200 ± 0%  -62.55%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10       4.19k ± 0%     0.32k ± 0%  -92.37%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names500Values-10       20.2k ± 0%      0.6k ± 0%  -97.03%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names1000Values-10      40.3k ± 0%      0.9k ± 0%  -97.66%  (p=0.000 n=5+4)
NewStreamBinaryReader/20Names5000Values-10       200k ± 0%        3k ± 0%  -98.26%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names1Values-10           278 ± 0%       285 ± 0%   +2.52%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-10        1.23k ± 0%     0.39k ± 0%  -68.65%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-10       10.4k ± 0%      0.7k ± 0%  -93.40%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-10       50.5k ± 0%      1.4k ± 0%  -97.26%  (p=0.000 n=5+4)
NewStreamBinaryReader/50Names1000Values-10       101k ± 0%        2k ± 0%  -97.78%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names5000Values-10       501k ± 0%        9k ± 0%  -98.28%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names1Values-10          481 ± 0%       489 ± 0%   +1.66%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names10Values-10       2.38k ± 0%     0.69k ± 0%  -71.05%  (p=0.000 n=4+5)
NewStreamBinaryReader/100Names100Values-10      20.7k ± 0%      1.3k ± 0%  -93.76%  (p=0.000 n=5+4)
NewStreamBinaryReader/100Names500Values-10       101k ± 0%        3k ± 0%  -97.33%  (p=0.016 n=5+4)
NewStreamBinaryReader/100Names1000Values-10      201k ± 0%        4k ± 0%  -97.82%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names5000Values-10     1.00M ± 0%     0.02M ± 0%  -98.29%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10          882 ± 0%       891 ± 0%   +1.02%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names10Values-10       4.68k ± 0%     1.29k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/200Names100Values-10      41.3k ± 0%      2.5k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/200Names500Values-10       202k ± 0%        5k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/200Names1000Values-10      402k ± 0%        9k ± 0%  -97.84%  (p=0.000 n=4+5)
NewStreamBinaryReader/200Names5000Values-10     2.00M ± 0%     0.03M ± 0%  -98.30%  (p=0.016 n=4+5)

...and compared to bada69c:

name                                         old time/op    new time/op    delta
NewStreamBinaryReader/1Names1Values-10          122µs ± 8%     129µs ±13%     ~     (p=0.151 n=5+5)
NewStreamBinaryReader/1Names10Values-10         124µs ± 4%     124µs ± 2%     ~     (p=0.421 n=5+5)
NewStreamBinaryReader/1Names100Values-10        138µs ± 2%     133µs ± 3%   -3.45%  (p=0.016 n=5+5)
NewStreamBinaryReader/1Names500Values-10        187µs ± 4%     162µs ± 1%  -13.16%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       262µs ± 2%     198µs ± 2%  -24.35%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       837µs ± 3%     535µs ± 2%  -36.05%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10         168µs ± 2%     171µs ± 2%     ~     (p=0.056 n=5+5)
NewStreamBinaryReader/20Names10Values-10        199µs ± 2%     188µs ± 4%   -5.37%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10       505µs ± 1%     355µs ± 6%  -29.75%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names500Values-10      1.63ms ± 1%    0.94ms ± 3%  -42.27%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names1000Values-10     2.90ms ± 3%    1.62ms ± 3%  -44.24%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names5000Values-10     12.9ms ± 2%     6.7ms ± 1%  -47.87%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-10         276µs ± 0%     277µs ± 1%     ~     (p=0.286 n=4+5)
NewStreamBinaryReader/50Names10Values-10        368µs ± 1%     322µs ± 2%  -12.49%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names100Values-10      1.10ms ± 4%    0.70ms ± 1%  -36.16%  (p=0.016 n=5+4)
NewStreamBinaryReader/50Names500Values-10      3.73ms ± 3%    2.14ms ± 3%  -42.68%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     6.74ms ± 2%    3.79ms ± 2%  -43.81%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names5000Values-10     32.0ms ± 0%    16.6ms ± 1%  -48.27%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names1Values-10        547µs ± 1%     548µs ± 3%     ~     (p=0.413 n=4+5)
NewStreamBinaryReader/100Names10Values-10       728µs ± 4%     632µs ± 4%  -13.19%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10     2.08ms ± 5%    1.37ms ± 5%  -34.32%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names500Values-10     7.13ms ± 1%    4.08ms ± 2%  -42.86%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    13.3ms ± 2%     7.3ms ± 1%  -45.46%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names5000Values-10    64.9ms ± 2%    33.4ms ± 0%  -48.57%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10       1.17ms ± 0%    1.16ms ± 2%     ~     (p=0.190 n=4+5)
NewStreamBinaryReader/200Names10Values-10      1.49ms ± 0%    1.29ms ± 2%  -13.17%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names100Values-10     4.05ms ± 3%    2.68ms ± 4%  -33.87%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names500Values-10     14.4ms ± 2%     8.0ms ± 0%  -44.83%  (p=0.016 n=5+4)
NewStreamBinaryReader/200Names1000Values-10    27.3ms ± 2%    14.5ms ± 1%  -47.02%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10     131ms ± 2%      67ms ± 0%  -48.50%  (p=0.008 n=5+5)

name                                         old alloc/op   new alloc/op   delta
NewStreamBinaryReader/1Names1Values-10         3.18MB ± 0%    3.18MB ± 0%   +0.00%  (p=0.032 n=5+5)
NewStreamBinaryReader/1Names10Values-10        3.18MB ± 0%    3.18MB ± 0%   -0.01%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10       3.18MB ± 0%    3.18MB ± 0%   -0.15%  (p=0.016 n=5+4)
NewStreamBinaryReader/1Names500Values-10       3.20MB ± 0%    3.18MB ± 0%   -0.74%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10      3.23MB ± 0%    3.18MB ± 0%   -1.47%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10      3.44MB ± 0%    3.20MB ± 0%   -6.91%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10        3.18MB ± 0%    3.18MB ± 0%   +0.04%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names10Values-10       3.19MB ± 0%    3.18MB ± 0%   -0.22%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10      3.29MB ± 0%    3.19MB ± 0%   -2.83%  (p=0.016 n=5+4)
NewStreamBinaryReader/20Names500Values-10      3.70MB ± 0%    3.23MB ± 0%  -12.80%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names1000Values-10     4.22MB ± 0%    3.27MB ± 0%  -22.47%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names5000Values-10     8.63MB ± 0%    3.56MB ± 0%  -58.73%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names1Values-10        3.19MB ± 0%    3.19MB ± 0%   +0.08%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-10       3.21MB ± 0%    3.19MB ± 0%   -0.58%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names100Values-10      3.45MB ± 0%    3.22MB ± 0%   -6.77%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-10      4.48MB ± 0%    3.30MB ± 0%  -26.43%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     5.78MB ± 0%    3.41MB ± 0%  -41.01%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names5000Values-10     17.3MB ± 0%     4.1MB ± 0%  -76.09%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1Values-10       3.20MB ± 0%    3.21MB ± 0%   +0.15%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names10Values-10      3.25MB ± 0%    3.21MB ± 0%   -1.15%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10     3.72MB ± 0%    3.26MB ± 0%  -12.55%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names500Values-10     5.79MB ± 0%    3.42MB ± 0%  -40.94%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    8.39MB ± 0%    3.65MB ± 0%  -56.54%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names5000Values-10    31.7MB ± 0%     5.1MB ± 0%  -83.95%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10       3.22MB ± 0%    3.23MB ± 0%   +0.31%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names10Values-10      3.32MB ± 0%    3.25MB ± 0%   -2.26%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names100Values-10     4.27MB ± 0%    3.33MB ± 0%  -21.89%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names500Values-10     8.72MB ± 0%    3.66MB ± 0%  -58.03%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names1000Values-10    14.3MB ± 0%     4.1MB ± 0%  -71.26%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10    61.3MB ± 0%     7.0MB ± 0%  -88.58%  (p=0.016 n=5+4)

name                                         old allocs/op  new allocs/op  delta
NewStreamBinaryReader/1Names1Values-10           78.0 ± 0%      78.0 ± 0%     ~     (all equal)
NewStreamBinaryReader/1Names10Values-10           106 ± 0%        80 ± 0%  -24.53%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10          379 ± 0%        86 ± 0%  -77.31%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-10        1.58k ± 0%     0.10k ± 0%  -93.67%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       3.08k ± 0%     0.12k ± 0%  -96.20%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       15.1k ± 0%      0.2k ± 0%  -98.38%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10           175 ± 0%       160 ± 0%   -8.57%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names10Values-10          735 ± 0%       200 ± 0%  -72.79%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10       6.20k ± 0%     0.32k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/20Names500Values-10       30.2k ± 0%      0.6k ± 0%  -98.02%  (p=0.000 n=5+4)
NewStreamBinaryReader/20Names1000Values-10      60.3k ± 0%      0.9k ± 0%  -98.44%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names5000Values-10       300k ± 0%        3k ± 0%  -98.84%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names1Values-10           329 ± 0%       285 ± 0%  -13.37%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-10        1.73k ± 0%     0.39k ± 0%  -77.73%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-10       15.4k ± 0%      0.7k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/50Names500Values-10       75.5k ± 0%      1.4k ± 0%  -98.17%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names1000Values-10       151k ± 0%        2k ± 0%  -98.52%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names5000Values-10       751k ± 0%        9k ± 0%  -98.86%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names1Values-10          582 ± 0%       489 ± 0%  -15.98%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names10Values-10       3.38k ± 0%     0.69k ± 0%  -79.62%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10      30.7k ± 0%      1.3k ± 0%  -95.80%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names500Values-10       151k ± 0%        3k ± 0%  -98.22%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names1000Values-10      301k ± 0%        4k ± 0%  -98.54%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names5000Values-10     1.50M ± 0%     0.02M ± 0%  -98.86%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10        1.08k ± 0%     0.89k ± 0%  -17.73%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names10Values-10       6.68k ± 0%     1.29k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/200Names100Values-10      61.3k ± 0%      2.5k ± 0%     ~     (p=0.079 n=4+5)
NewStreamBinaryReader/200Names500Values-10       302k ± 0%        5k ± 0%  -98.25%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1000Values-10      602k ± 0%        9k ± 0%  -98.56%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10     3.00M ± 0%     0.03M ± 0%  -98.86%  (p=0.008 n=5+5)

Read postings offset table in one pass by seeking back to previous values when required.

On my machine with a SSD, this produces mixed results, but seems to
improve things for index-headers with a high number of values and
relatively few names:

name                                         old time/op    new time/op    delta
NewStreamBinaryReader/1Names1Values-10          129µs ±13%     136µs ± 4%     ~     (p=0.151 n=5+5)
NewStreamBinaryReader/1Names10Values-10         124µs ± 2%     129µs ± 7%   +3.75%  (p=0.032 n=5+5)
NewStreamBinaryReader/1Names100Values-10        133µs ± 3%     135µs ± 1%     ~     (p=0.421 n=5+5)
NewStreamBinaryReader/1Names500Values-10        162µs ± 1%     164µs ± 2%     ~     (p=0.421 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       198µs ± 2%     198µs ± 2%     ~     (p=1.000 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       535µs ± 2%     518µs ± 2%   -3.13%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10         171µs ± 2%     171µs ± 1%     ~     (p=0.841 n=5+5)
NewStreamBinaryReader/20Names10Values-10        188µs ± 4%     208µs ± 2%  +10.17%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10       355µs ± 6%     383µs ± 2%   +8.03%  (p=0.016 n=5+5)
NewStreamBinaryReader/20Names500Values-10       941µs ± 3%     932µs ± 3%     ~     (p=0.421 n=5+5)
NewStreamBinaryReader/20Names1000Values-10     1.62ms ± 3%    1.57ms ± 3%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/20Names5000Values-10     6.71ms ± 1%    6.33ms ± 1%   -5.57%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-10         277µs ± 1%     291µs ± 5%   +5.10%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-10        322µs ± 2%     394µs ± 5%  +22.15%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-10       701µs ± 1%     730µs ± 2%   +4.11%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names500Values-10      2.14ms ± 3%    2.08ms ± 3%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     3.79ms ± 2%    3.63ms ± 2%   -4.09%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names5000Values-10     16.6ms ± 1%    15.5ms ± 0%   -6.59%  (p=0.016 n=5+4)
NewStreamBinaryReader/100Names1Values-10        548µs ± 3%     542µs ± 3%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/100Names10Values-10       632µs ± 4%     741µs ± 3%  +17.27%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10     1.37ms ± 5%    1.40ms ± 5%     ~     (p=0.222 n=5+5)
NewStreamBinaryReader/100Names500Values-10     4.08ms ± 2%    3.97ms ± 2%   -2.62%  (p=0.016 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    7.27ms ± 1%    6.96ms ± 1%   -4.25%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names5000Values-10    33.4ms ± 0%    31.1ms ± 0%   -6.73%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10       1.16ms ± 2%    1.16ms ± 3%     ~     (p=1.000 n=5+5)
NewStreamBinaryReader/200Names10Values-10      1.29ms ± 2%    1.57ms ± 4%  +21.49%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names100Values-10     2.68ms ± 4%    2.73ms ± 3%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/200Names500Values-10     7.97ms ± 0%    7.64ms ± 1%   -4.09%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names1000Values-10    14.5ms ± 1%    13.7ms ± 1%   -5.30%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10    67.3ms ± 0%    62.5ms ± 1%   -7.15%  (p=0.008 n=5+5)
@charleskorn charleskorn force-pushed the charleskorn/mmap-less-index-header-reader-optimisation branch from dc6ff92 to 7e2b4a3 Compare December 19, 2022 02:05
This reduces the time taken to load an index-header by up to 2-4% for
realistic scenarios:

name                                         old time/op    new time/op    delta
NewStreamBinaryReader/1Names1Values-10          128µs ± 1%     123µs ± 2%  -4.25%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names10Values-10         128µs ± 1%     122µs ± 1%  -4.95%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10        137µs ± 3%     133µs ± 1%  -2.84%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-10        169µs ± 4%     161µs ± 1%  -4.87%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       201µs ± 3%     192µs ± 3%  -4.47%  (p=0.016 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       541µs ± 5%     494µs ± 2%  -8.64%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10         178µs ± 4%     169µs ± 1%  -4.89%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names10Values-10        216µs ± 4%     200µs ± 0%  -7.14%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10       374µs ± 5%     360µs ± 5%    ~     (p=0.095 n=5+5)
NewStreamBinaryReader/20Names500Values-10       955µs ± 1%     907µs ± 4%  -5.05%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1000Values-10     1.60ms ± 0%    1.54ms ± 3%    ~     (p=0.063 n=4+5)
NewStreamBinaryReader/20Names5000Values-10     6.56ms ± 3%    6.26ms ± 1%  -4.64%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-10         297µs ± 4%     276µs ± 1%  -7.14%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names10Values-10        401µs ± 6%     384µs ± 4%  -4.25%  (p=0.032 n=5+5)
NewStreamBinaryReader/50Names100Values-10       738µs ± 3%     716µs ± 2%  -2.97%  (p=0.032 n=5+5)
NewStreamBinaryReader/50Names500Values-10      2.10ms ± 3%    2.06ms ± 3%    ~     (p=0.151 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     3.68ms ± 2%    3.59ms ± 2%    ~     (p=0.056 n=5+5)
NewStreamBinaryReader/50Names5000Values-10     15.8ms ± 2%    15.4ms ± 1%  -2.77%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1Values-10        556µs ± 6%     534µs ± 0%  -4.09%  (p=0.016 n=5+4)
NewStreamBinaryReader/100Names10Values-10       753µs ± 1%     736µs ± 2%  -2.18%  (p=0.032 n=5+5)
NewStreamBinaryReader/100Names100Values-10     1.40ms ± 4%    1.38ms ± 4%    ~     (p=0.222 n=5+5)
NewStreamBinaryReader/100Names500Values-10     3.95ms ± 3%    3.91ms ± 1%    ~     (p=0.310 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    6.92ms ± 1%    6.92ms ± 1%    ~     (p=1.000 n=5+5)
NewStreamBinaryReader/100Names5000Values-10    30.9ms ± 0%    30.8ms ± 1%    ~     (p=0.095 n=5+5)
NewStreamBinaryReader/200Names1Values-10       1.17ms ± 6%    1.14ms ± 0%  -2.33%  (p=0.032 n=5+4)
NewStreamBinaryReader/200Names10Values-10      1.54ms ± 6%    1.84ms ±43%    ~     (p=0.548 n=5+5)
NewStreamBinaryReader/200Names100Values-10     2.73ms ± 3%    2.74ms ± 3%    ~     (p=0.421 n=5+5)
NewStreamBinaryReader/200Names500Values-10     7.62ms ± 1%    7.58ms ± 1%    ~     (p=0.151 n=5+5)
NewStreamBinaryReader/200Names1000Values-10    13.7ms ± 1%    13.7ms ± 1%    ~     (p=0.222 n=5+5)
NewStreamBinaryReader/200Names5000Values-10    62.4ms ± 1%    61.9ms ± 0%  -0.79%  (p=0.029 n=4+4)
@charleskorn charleskorn changed the title Store gateway mmap removal: optimise postings offset table reader Store gateway mmap removal: optimise index-header reader and symbol lookups Dec 19, 2022
@charleskorn
Copy link
Contributor Author

charleskorn commented Dec 19, 2022

40efcae improves the performance of LookupSymbol by skipping over unwanted symbols, saving ~2% in the best case scenario (all value symbol lookups, no name symbol lookups).

Doesn't need to be done as part of this PR but there a few places that we use UvarintBytes() just to skip over bytes.

I'm trying to keep this PR as small as possible, but I agree.

I think there are a couple of follow up changes after this PR:

  • using SkipUvarintBytes() where possible (LabelValues(), PostingsOffset() and skipNAndName() in postings.go are the three instances that I can see), as you suggest
  • replacing bufio.Reader with something similar that supports seeking backwards without discarding the buffer
  • applying similar ideas to the v1 postings offset table reader
  • adding a Position() method (or something similar) to Decbuf to remove the need for the confusing maths with Len() - then we could call Position() to get a value we can pass to ResetAt()

@charleskorn charleskorn marked this pull request as ready for review December 19, 2022 03:14
@charleskorn charleskorn requested a review from a team as a code owner December 19, 2022 03:14
// We haven't recorded the last offset for the last value of the previous name.
// Go back and read the last value for the previous name.
newValueOffset := d.Len()
d.ResetAt(lastEntryOffsetInTable + 4) // 4 bytes for entry count
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: I would define a const entryCountLength = 4 and use it here and below as:

Suggested change
d.ResetAt(lastEntryOffsetInTable + 4) // 4 bytes for entry count
d.ResetAt(entryCountLength + lastEntryOffsetInTable)

So you wouldn't need the comment.

// We haven't recorded the last offset for the last value of the previous name.
// Go back and read the last value for the previous name.
newValueOffset := d.Len()
d.ResetAt(lastEntryOffsetInTable + 4) // 4 bytes for entry count
Copy link
Collaborator

Choose a reason for hiding this comment

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

Don't we waste the buffer in the buffered reader, doing it for each new symbol name?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes - this is where my idea of replacing bufio.Reader with something that supports seeking backwards without discarding the buffer came from. However, your idea to copy the value into a []byte buffer in this method would remove the need for any kind of seeking.

Copy link
Contributor

@colega colega left a comment

Choose a reason for hiding this comment

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

Thank you for splitting an explaining the commits, it was much easier to review them that way.

LGTM, left some nitpicks but feel free to disagree with them.

@56quarters
Copy link
Contributor

56quarters commented Dec 19, 2022

I think there are a couple of follow up changes after this PR:

  • using SkipUvarintBytes() where possible (LabelValues(), PostingsOffset() and skipNAndName() in postings.go are the three instances that I can see), as you suggest

👍

  • replacing bufio.Reader with something similar that supports seeking backwards without discarding the buffer

I guess let's test it but I'm wary of:

  • Implementing something so low-level ourselves
  • Moving backwards in a file. I'd guess that there's a lot of things optimized around reading a file sequentially. If we do go this course, maybe it makes sense to look into fadvise via the unix package
  • applying similar ideas to the v1 postings offset table reader

  • adding a Position() method (or something similar) to Decbuf to remove the need for the confusing maths with Len() - then we could call Position() to get a value we can pass to ResetAt()

👍

@pracucci
Copy link
Collaborator

replacing bufio.Reader with something similar that supports seeking backwards without discarding the buffer

Is that actually required? What if we keep a []byte buffer with the previous symbol value, which is read with unsafe and then copy(). It wouldn't trigger any new allocation for each symbol we discard because we would always overwrite the same buffer. This should avoid having to call .ResetAt() at all. Am I missing anything obvious?

@56quarters
Copy link
Contributor

replacing bufio.Reader with something similar that supports seeking backwards without discarding the buffer

Is that actually required? What if we keep a []byte buffer with the previous symbol value, which is read with unsafe and then copy(). It wouldn't trigger any new allocation for each symbol we discard because we would always overwrite the same buffer. This should avoid having to call .ResetAt() at all. Am I missing anything obvious?

I think you're right. We only need to .ResetAt() to move backwards and grab the value which unfortunately means we have to discard any buffered portion of file. If we just stored it every iteration in the same []byte buffer we could avoid that.

Co-authored-by: Oleg Zaytsev <mail@olegzaytsev.com>
@charleskorn
Copy link
Contributor Author

replacing bufio.Reader with something similar that supports seeking backwards without discarding the buffer

Is that actually required? What if we keep a []byte buffer with the previous symbol value, which is read with unsafe and then copy(). It wouldn't trigger any new allocation for each symbol we discard because we would always overwrite the same buffer. This should avoid having to call .ResetAt() at all. Am I missing anything obvious?

I think you're right. We only need to .ResetAt() to move backwards and grab the value which unfortunately means we have to discard any buffered portion of file. If we just stored it every iteration in the same []byte buffer we could avoid that.

Great idea, I'll give this a go - it would not only remove the need to seek backwards, but also remove some of the confusing maths both Marco and Oleg have commented on.

@charleskorn
Copy link
Contributor Author

I've had a go at implementing Marco's suggestion of always copying the label value into a buffer in 0b279fd. This removes the need to seek backwards to read the last label value at the cost of more CPU time spent copying bytes from one buffer to another.

The benchmarking results are mixed, and depend greatly on the size of the index-header and the ratio of unique names to total number of values - more unique names meant more seeking in the old implementation, more values means more copying in the new implementation. All of these results are relative to 1066f9c:

Benchmark results: with SSD
name                                         old time/op    new time/op    delta
NewStreamBinaryReader/1Names1Values-10          127µs ± 3%     131µs ± 9%     ~     (p=0.690 n=5+5)
NewStreamBinaryReader/1Names10Values-10         128µs ± 4%     122µs ± 2%     ~     (p=0.056 n=5+5)
NewStreamBinaryReader/1Names100Values-10        139µs ± 3%     132µs ± 1%   -5.32%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-10        163µs ± 4%     161µs ± 1%     ~     (p=0.421 n=5+5)
NewStreamBinaryReader/1Names1000Values-10       196µs ± 3%     197µs ± 3%     ~     (p=0.690 n=5+5)
NewStreamBinaryReader/1Names5000Values-10       503µs ± 4%     524µs ± 2%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/20Names1Values-10         168µs ± 2%     168µs ± 3%     ~     (p=1.000 n=5+5)
NewStreamBinaryReader/20Names10Values-10        207µs ± 4%     184µs ± 2%  -11.38%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10       368µs ± 4%     355µs ± 5%     ~     (p=0.056 n=5+5)
NewStreamBinaryReader/20Names500Values-10       915µs ± 2%     946µs ± 1%   +3.34%  (p=0.016 n=5+4)
NewStreamBinaryReader/20Names1000Values-10     1.55ms ± 4%    1.65ms ± 3%   +6.51%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names5000Values-10     6.19ms ± 1%    6.84ms ± 1%  +10.41%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-10         271µs ± 2%     281µs ± 5%   +3.73%  (p=0.032 n=5+5)
NewStreamBinaryReader/50Names10Values-10        375µs ± 1%     322µs ± 2%  -14.28%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-10       720µs ± 4%     709µs ± 3%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/50Names500Values-10      2.05ms ± 3%    2.19ms ± 3%   +6.78%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     3.58ms ± 2%    3.84ms ± 0%   +7.11%  (p=0.016 n=5+4)
NewStreamBinaryReader/50Names5000Values-10     15.3ms ± 1%    16.9ms ± 2%  +10.31%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1Values-10        539µs ± 5%     532µs ± 0%     ~     (p=0.730 n=5+4)
NewStreamBinaryReader/100Names10Values-10       730µs ± 3%     626µs ± 2%  -14.34%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names100Values-10     1.36ms ± 0%    1.37ms ± 6%     ~     (p=0.190 n=4+5)
NewStreamBinaryReader/100Names500Values-10     3.89ms ± 2%    4.14ms ± 2%   +6.43%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1000Values-10    6.87ms ± 1%    7.41ms ± 1%   +7.95%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names5000Values-10    30.8ms ± 1%    33.9ms ± 1%  +10.24%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-10       1.15ms ± 3%    1.18ms ± 3%     ~     (p=0.056 n=5+5)
NewStreamBinaryReader/200Names10Values-10      1.53ms ± 5%    1.31ms ± 7%  -14.41%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names100Values-10     2.72ms ± 0%    2.69ms ± 3%     ~     (p=0.190 n=4+5)
NewStreamBinaryReader/200Names500Values-10     7.57ms ± 0%    8.09ms ± 1%   +6.79%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names1000Values-10    13.6ms ± 2%    14.6ms ± 1%   +7.45%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-10    61.9ms ± 0%    67.3ms ± 1%   +8.67%  (p=0.008 n=5+5)

name                                         old alloc/op   new alloc/op   delta
NewStreamBinaryReader/1Names1Values-10         3.18MB ± 0%    3.18MB ± 0%     ~     (p=0.952 n=5+5)
NewStreamBinaryReader/1Names10Values-10        3.18MB ± 0%    3.18MB ± 0%     ~     (p=0.151 n=5+5)
NewStreamBinaryReader/1Names100Values-10       3.18MB ± 0%    3.18MB ± 0%   +0.00%  (p=0.016 n=5+5)
NewStreamBinaryReader/1Names500Values-10       3.18MB ± 0%    3.18MB ± 0%   +0.00%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10      3.18MB ± 0%    3.18MB ± 0%   +0.00%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10      3.20MB ± 0%    3.20MB ± 0%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/20Names1Values-10        3.18MB ± 0%    3.18MB ± 0%     ~     (p=0.087 n=5+5)
NewStreamBinaryReader/20Names10Values-10       3.18MB ± 0%    3.18MB ± 0%     ~     (p=0.516 n=5+5)
NewStreamBinaryReader/20Names100Values-10      3.19MB ± 0%    3.19MB ± 0%     ~     (p=0.135 n=5+5)
NewStreamBinaryReader/20Names500Values-10      3.22MB ± 0%    3.22MB ± 0%     ~     (p=0.111 n=5+4)
NewStreamBinaryReader/20Names1000Values-10     3.27MB ± 0%    3.27MB ± 0%   +0.00%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names5000Values-10     3.56MB ± 0%    3.56MB ± 0%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/50Names1Values-10        3.19MB ± 0%    3.19MB ± 0%     ~     (p=0.349 n=5+5)
NewStreamBinaryReader/50Names10Values-10       3.19MB ± 0%    3.19MB ± 0%     ~     (p=0.317 n=5+5)
NewStreamBinaryReader/50Names100Values-10      3.21MB ± 0%    3.21MB ± 0%     ~     (p=0.222 n=5+5)
NewStreamBinaryReader/50Names500Values-10      3.29MB ± 0%    3.29MB ± 0%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/50Names1000Values-10     3.41MB ± 0%    3.41MB ± 0%     ~     (p=0.190 n=5+4)
NewStreamBinaryReader/50Names5000Values-10     4.13MB ± 0%    4.13MB ± 0%     ~     (p=0.238 n=5+5)
NewStreamBinaryReader/100Names1Values-10       3.20MB ± 0%    3.20MB ± 0%     ~     (p=0.897 n=5+5)
NewStreamBinaryReader/100Names10Values-10      3.20MB ± 0%    3.20MB ± 0%     ~     (p=0.841 n=5+5)
NewStreamBinaryReader/100Names100Values-10     3.25MB ± 0%    3.25MB ± 0%     ~     (p=0.286 n=4+5)
NewStreamBinaryReader/100Names500Values-10     3.41MB ± 0%    3.41MB ± 0%     ~     (p=0.190 n=4+5)
NewStreamBinaryReader/100Names1000Values-10    3.64MB ± 0%    3.64MB ± 0%     ~     (p=0.841 n=5+5)
NewStreamBinaryReader/100Names5000Values-10    5.08MB ± 0%    5.08MB ± 0%   +0.00%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names1Values-10       3.22MB ± 0%    3.22MB ± 0%     ~     (p=0.452 n=5+5)
NewStreamBinaryReader/200Names10Values-10      3.23MB ± 0%    3.23MB ± 0%     ~     (p=1.000 n=4+4)
NewStreamBinaryReader/200Names100Values-10     3.32MB ± 0%    3.32MB ± 0%     ~     (p=0.548 n=5+5)
NewStreamBinaryReader/200Names500Values-10     3.64MB ± 0%    3.64MB ± 0%     ~     (p=0.222 n=5+5)
NewStreamBinaryReader/200Names1000Values-10    4.10MB ± 0%    4.10MB ± 0%     ~     (p=0.841 n=5+5)
NewStreamBinaryReader/200Names5000Values-10    6.98MB ± 0%    6.98MB ± 0%     ~     (p=0.690 n=5+5)

name                                         old allocs/op  new allocs/op  delta
NewStreamBinaryReader/1Names1Values-10           76.0 ± 0%      76.0 ± 0%     ~     (all equal)
NewStreamBinaryReader/1Names10Values-10          78.0 ± 0%      79.0 ± 0%   +1.28%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names100Values-10         84.0 ± 0%      86.0 ± 0%   +2.38%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-10         98.0 ± 0%     101.0 ± 0%   +3.06%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names1000Values-10         115 ± 0%       118 ± 0%   +2.61%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-10         242 ± 0%       246 ± 0%   +1.65%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names1Values-10           154 ± 0%       154 ± 0%     ~     (all equal)
NewStreamBinaryReader/20Names10Values-10          194 ± 0%       195 ± 0%   +0.52%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names100Values-10         314 ± 0%       316 ± 0%   +0.64%  (p=0.008 n=5+5)
NewStreamBinaryReader/20Names500Values-10         594 ± 0%       597 ± 0%   +0.51%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names1000Values-10        934 ± 0%       937 ± 0%   +0.32%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names5000Values-10      3.47k ± 0%     3.48k ± 0%   +0.12%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-10           278 ± 0%       278 ± 0%     ~     (all equal)
NewStreamBinaryReader/50Names10Values-10          378 ± 0%       379 ± 0%   +0.26%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-10         678 ± 0%       680 ± 0%   +0.29%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names500Values-10       1.38k ± 0%     1.38k ± 0%   +0.22%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names1000Values-10      2.23k ± 0%     2.23k ± 0%   +0.15%  (p=0.016 n=4+5)
NewStreamBinaryReader/50Names5000Values-10      8.58k ± 0%     8.58k ± 0%   +0.05%  (p=0.016 n=5+4)
NewStreamBinaryReader/100Names1Values-10          481 ± 0%       481 ± 0%     ~     (all equal)
NewStreamBinaryReader/100Names10Values-10         682 ± 0%       683 ± 0%     ~     (p=0.079 n=5+5)
NewStreamBinaryReader/100Names100Values-10      1.28k ± 0%     1.28k ± 0%   +0.16%  (p=0.016 n=5+4)
NewStreamBinaryReader/100Names500Values-10      2.68k ± 0%     2.69k ± 0%   +0.11%  (p=0.016 n=5+4)
NewStreamBinaryReader/100Names1000Values-10     4.38k ± 0%     4.38k ± 0%   +0.07%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names5000Values-10     17.1k ± 0%     17.1k ± 0%   +0.02%  (p=0.016 n=5+4)
NewStreamBinaryReader/200Names1Values-10          882 ± 0%       882 ± 0%     ~     (all equal)
NewStreamBinaryReader/200Names10Values-10       1.28k ± 0%     1.28k ± 0%   +0.08%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names100Values-10      2.48k ± 0%     2.48k ± 0%   +0.08%  (p=0.016 n=5+4)
NewStreamBinaryReader/200Names500Values-10      5.28k ± 0%     5.29k ± 0%   +0.06%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1000Values-10     8.68k ± 0%     8.69k ± 0%   +0.03%  (p=0.016 n=5+4)
NewStreamBinaryReader/200Names5000Values-10     34.1k ± 0%     34.1k ± 0%   +0.01%  (p=0.008 n=5+5)
Benchmark results: with spinning rust disk
name                                        old time/op    new time/op    delta
NewStreamBinaryReader/1Names1Values-2         1.62ms ±19%    1.56ms ±31%     ~     (p=0.841 n=5+5)
NewStreamBinaryReader/1Names10Values-2        1.69ms ±26%    1.49ms ±26%     ~     (p=0.548 n=5+5)
NewStreamBinaryReader/1Names100Values-2       1.51ms ±21%    1.46ms ±25%     ~     (p=1.000 n=5+5)
NewStreamBinaryReader/1Names500Values-2       1.58ms ±20%    1.82ms ±25%     ~     (p=0.310 n=5+5)
NewStreamBinaryReader/1Names1000Values-2      1.90ms ±18%    1.57ms ± 5%  -17.70%  (p=0.032 n=5+5)
NewStreamBinaryReader/1Names5000Values-2      2.80ms ±16%    2.85ms ±10%     ~     (p=0.690 n=5+5)
NewStreamBinaryReader/20Names1Values-2        1.75ms ±14%    1.85ms ±20%     ~     (p=0.421 n=5+5)
NewStreamBinaryReader/20Names10Values-2       1.69ms ±15%    1.75ms ±17%     ~     (p=0.841 n=5+5)
NewStreamBinaryReader/20Names100Values-2      2.49ms ± 7%    2.46ms ±13%     ~     (p=0.841 n=5+5)
NewStreamBinaryReader/20Names500Values-2      3.83ms ± 8%    3.79ms ± 7%     ~     (p=0.841 n=5+5)
NewStreamBinaryReader/20Names1000Values-2     5.39ms ± 5%    5.68ms ± 7%     ~     (p=0.222 n=5+5)
NewStreamBinaryReader/20Names5000Values-2     17.8ms ± 1%    18.5ms ± 4%   +3.71%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-2        2.23ms ±11%    2.02ms ± 2%     ~     (p=0.421 n=5+5)
NewStreamBinaryReader/50Names10Values-2       2.58ms ±13%    2.22ms ± 3%  -14.22%  (p=0.016 n=5+5)
NewStreamBinaryReader/50Names100Values-2      3.36ms ± 5%    3.14ms ± 9%     ~     (p=0.056 n=5+5)
NewStreamBinaryReader/50Names500Values-2      6.84ms ± 8%    6.85ms ± 2%     ~     (p=0.690 n=5+5)
NewStreamBinaryReader/50Names1000Values-2     10.9ms ± 4%    11.3ms ± 3%     ~     (p=0.056 n=5+5)
NewStreamBinaryReader/50Names5000Values-2     39.7ms ± 2%    41.7ms ± 1%   +5.17%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names1Values-2       3.05ms ±10%    2.83ms ± 8%     ~     (p=0.421 n=5+5)
NewStreamBinaryReader/100Names10Values-2      3.59ms ±15%    3.04ms ± 1%  -15.33%  (p=0.016 n=5+4)
NewStreamBinaryReader/100Names100Values-2     5.36ms ± 5%    4.95ms ± 3%   -7.66%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names500Values-2     12.1ms ± 2%    12.1ms ± 3%     ~     (p=1.000 n=5+5)
NewStreamBinaryReader/100Names1000Values-2    19.8ms ± 2%    20.2ms ± 3%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/100Names5000Values-2    76.2ms ± 2%    81.0ms ± 2%   +6.38%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-2       4.98ms ± 8%    4.63ms ± 5%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/200Names10Values-2      5.63ms ± 7%    5.11ms ± 4%   -9.35%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names100Values-2     9.00ms ± 5%    8.45ms ± 1%   -6.14%  (p=0.032 n=5+5)
NewStreamBinaryReader/200Names500Values-2     21.5ms ± 1%    21.9ms ± 2%   +2.12%  (p=0.016 n=5+5)
NewStreamBinaryReader/200Names1000Values-2    35.5ms ± 2%    37.5ms ± 2%   +5.58%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names5000Values-2     148ms ± 2%     159ms ± 2%   +7.18%  (p=0.016 n=5+4)

name                                        old alloc/op   new alloc/op   delta
NewStreamBinaryReader/1Names1Values-2         3.18MB ± 0%    3.18MB ± 0%     ~     (p=0.548 n=5+5)
NewStreamBinaryReader/1Names10Values-2        3.18MB ± 0%    3.18MB ± 0%     ~     (p=0.302 n=5+4)
NewStreamBinaryReader/1Names100Values-2       3.18MB ± 0%    3.18MB ± 0%     ~     (p=0.524 n=5+5)
NewStreamBinaryReader/1Names500Values-2       3.18MB ± 0%    3.18MB ± 0%   +0.00%  (p=0.016 n=5+5)
NewStreamBinaryReader/1Names1000Values-2      3.18MB ± 0%    3.18MB ± 0%   +0.00%  (p=0.016 n=5+5)
NewStreamBinaryReader/1Names5000Values-2      3.20MB ± 0%    3.20MB ± 0%   +0.00%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names1Values-2        3.18MB ± 0%    3.18MB ± 0%     ~     (p=0.175 n=5+5)
NewStreamBinaryReader/20Names10Values-2       3.18MB ± 0%    3.18MB ± 0%     ~     (p=1.000 n=5+5)
NewStreamBinaryReader/20Names100Values-2      3.19MB ± 0%    3.19MB ± 0%     ~     (p=0.921 n=4+5)
NewStreamBinaryReader/20Names500Values-2      3.22MB ± 0%    3.22MB ± 0%   +0.00%  (p=0.016 n=4+5)
NewStreamBinaryReader/20Names1000Values-2     3.27MB ± 0%    3.27MB ± 0%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/20Names5000Values-2     3.56MB ± 0%    3.56MB ± 0%   +0.00%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names1Values-2        3.19MB ± 0%    3.19MB ± 0%     ~     (p=0.159 n=5+5)
NewStreamBinaryReader/50Names10Values-2       3.19MB ± 0%    3.19MB ± 0%     ~     (p=0.111 n=5+5)
NewStreamBinaryReader/50Names100Values-2      3.21MB ± 0%    3.21MB ± 0%     ~     (p=0.333 n=5+5)
NewStreamBinaryReader/50Names500Values-2      3.29MB ± 0%    3.29MB ± 0%     ~     (p=0.690 n=5+5)
NewStreamBinaryReader/50Names1000Values-2     3.41MB ± 0%    3.41MB ± 0%     ~     (p=0.690 n=5+5)
NewStreamBinaryReader/50Names5000Values-2     4.13MB ± 0%    4.13MB ± 0%     ~     (p=0.310 n=5+5)
NewStreamBinaryReader/100Names1Values-2       3.20MB ± 0%    3.20MB ± 0%     ~     (p=0.548 n=5+5)
NewStreamBinaryReader/100Names10Values-2      3.20MB ± 0%    3.20MB ± 0%     ~     (p=1.000 n=5+5)
NewStreamBinaryReader/100Names100Values-2     3.25MB ± 0%    3.25MB ± 0%     ~     (p=1.000 n=5+5)
NewStreamBinaryReader/100Names500Values-2     3.41MB ± 0%    3.41MB ± 0%     ~     (p=0.548 n=5+5)
NewStreamBinaryReader/100Names1000Values-2    3.64MB ± 0%    3.64MB ± 0%     ~     (p=0.151 n=5+5)
NewStreamBinaryReader/100Names5000Values-2    5.08MB ± 0%    5.08MB ± 0%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/200Names1Values-2       3.22MB ± 0%    3.22MB ± 0%     ~     (p=0.198 n=5+5)
NewStreamBinaryReader/200Names10Values-2      3.23MB ± 0%    3.23MB ± 0%     ~     (p=0.095 n=5+5)
NewStreamBinaryReader/200Names100Values-2     3.32MB ± 0%    3.32MB ± 0%     ~     (p=0.421 n=5+5)
NewStreamBinaryReader/200Names500Values-2     3.64MB ± 0%    3.64MB ± 0%     ~     (p=0.222 n=5+5)
NewStreamBinaryReader/200Names1000Values-2    4.10MB ± 0%    4.10MB ± 0%     ~     (p=0.222 n=5+5)
NewStreamBinaryReader/200Names5000Values-2    6.98MB ± 0%    6.98MB ± 0%     ~     (p=0.310 n=5+5)

name                                        old allocs/op  new allocs/op  delta
NewStreamBinaryReader/1Names1Values-2           76.0 ± 0%      76.0 ± 0%     ~     (all equal)
NewStreamBinaryReader/1Names10Values-2          78.0 ± 0%      79.0 ± 0%   +1.28%  (p=0.016 n=4+5)
NewStreamBinaryReader/1Names100Values-2         84.0 ± 0%      86.0 ± 0%   +2.38%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names500Values-2         98.0 ± 0%     101.0 ± 0%   +3.06%  (p=0.016 n=5+4)
NewStreamBinaryReader/1Names1000Values-2         115 ± 0%       118 ± 0%   +2.61%  (p=0.008 n=5+5)
NewStreamBinaryReader/1Names5000Values-2         242 ± 0%       246 ± 0%   +1.65%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names1Values-2           155 ± 0%       155 ± 0%     ~     (all equal)
NewStreamBinaryReader/20Names10Values-2          195 ± 0%       195 ± 0%     ~     (p=0.556 n=4+5)
NewStreamBinaryReader/20Names100Values-2         315 ± 0%       317 ± 0%   +0.63%  (p=0.016 n=5+4)
NewStreamBinaryReader/20Names500Values-2         595 ± 0%       598 ± 0%   +0.50%  (p=0.029 n=4+4)
NewStreamBinaryReader/20Names1000Values-2        935 ± 0%       938 ± 0%   +0.32%  (p=0.016 n=5+4)
NewStreamBinaryReader/20Names5000Values-2      3.48k ± 0%     3.48k ± 0%   +0.12%  (p=0.016 n=5+4)
NewStreamBinaryReader/50Names1Values-2           279 ± 0%       279 ± 0%     ~     (all equal)
NewStreamBinaryReader/50Names10Values-2          379 ± 0%       380 ± 0%   +0.26%  (p=0.008 n=5+5)
NewStreamBinaryReader/50Names100Values-2         679 ± 0%       681 ± 0%   +0.29%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names500Values-2       1.38k ± 0%     1.38k ± 0%   +0.22%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names1000Values-2      2.23k ± 0%     2.23k ± 0%   +0.13%  (p=0.029 n=4+4)
NewStreamBinaryReader/50Names5000Values-2      8.58k ± 0%     8.58k ± 0%   +0.05%  (p=0.029 n=4+4)
NewStreamBinaryReader/100Names1Values-2          483 ± 0%       483 ± 0%     ~     (all equal)
NewStreamBinaryReader/100Names10Values-2         683 ± 0%       684 ± 0%     ~     (p=0.079 n=5+4)
NewStreamBinaryReader/100Names100Values-2      1.28k ± 0%     1.28k ± 0%   +0.16%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names500Values-2      2.68k ± 0%     2.69k ± 0%   +0.13%  (p=0.016 n=4+5)
NewStreamBinaryReader/100Names1000Values-2     4.38k ± 0%     4.39k ± 0%   +0.07%  (p=0.008 n=5+5)
NewStreamBinaryReader/100Names5000Values-2     17.1k ± 0%     17.1k ± 0%   +0.03%  (p=0.008 n=5+5)
NewStreamBinaryReader/200Names1Values-2          886 ± 0%       886 ± 0%     ~     (all equal)
NewStreamBinaryReader/200Names10Values-2       1.29k ± 0%     1.29k ± 0%   +0.08%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names100Values-2      2.49k ± 0%     2.49k ± 0%   +0.08%  (p=0.029 n=4+4)
NewStreamBinaryReader/200Names500Values-2      5.29k ± 0%     5.29k ± 0%   +0.06%  (p=0.016 n=5+4)
NewStreamBinaryReader/200Names1000Values-2     8.69k ± 0%     8.69k ± 0%   +0.04%  (p=0.016 n=4+5)
NewStreamBinaryReader/200Names5000Values-2     34.1k ± 0%     34.1k ± 0%   +0.01%  (p=0.008 n=5+5)

This doesn't seem worthwhile to me, but I'm happy either way - what do you think @pracucci @56quarters @colega? Or can you see a way to improve this further?

@pracucci
Copy link
Collaborator

Thanks a lot @charleskorn for trying it. I agree doesn't look worth. I'm happy to move on and merge this PR with the ResetAt(). Is there anything else you want to do on this PR?

@charleskorn
Copy link
Contributor Author

Thanks a lot @charleskorn for trying it. I agree doesn't look worth. I'm happy to move on and merge this PR with the ResetAt(). Is there anything else you want to do on this PR?

If you're happy to merge this as-is, I'll follow up with a PR to introduce a Position() method to simplify some of the position calculation maths, then take a look at the other improvements I mentioned earlier.

Copy link
Collaborator

@pracucci pracucci left a comment

Choose a reason for hiding this comment

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

I don't see anything blocking the merge, so I'm happy to merge it as is and follow up with the other minor comments in another PR.

@pracucci pracucci merged commit b777f85 into main Dec 20, 2022
@pracucci pracucci deleted the charleskorn/mmap-less-index-header-reader-optimisation branch December 20, 2022 12:19
charleskorn added a commit that referenced this pull request Dec 21, 2022
@charleskorn charleskorn mentioned this pull request Dec 21, 2022
1 task
charleskorn added a commit that referenced this pull request Dec 21, 2022
pracucci pushed a commit that referenced this pull request Dec 22, 2022
pracucci added a commit that referenced this pull request Dec 22, 2022
…3797)

* Address last remaining feedback on #3742.

* Add changelog entry.

Co-authored-by: Marco Pracucci <marco@pracucci.com>
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.

4 participants