Skip to content

Conversation

prymitive
Copy link
Contributor

@prymitive prymitive commented Feb 6, 2025

stringlabels stores all time series labels as a single string using this format:

<length><name><length><value>[<length><name><length><value> ...]

So a label set for my_metric{job=foo, instance="bar", env="prod", blank=""} would be encoded as:

[8]__name__[9]my_metric[3]job[3]foo[8]instance[3]bar[3]env[4]prod[5]blank[0]

This is a huge improvement over 'classic' labels implementation that stores all label names & values as seperate strings. There is some room for improvement though since some string are present more often than others. For example __name__ will be present for all label sets of every time series we store in HEAD, eating 1+8=9 bytes. Since __name__ is well known string we can try to use a single byte to store it in our encoded string, rather than repeat it in full each time. To be able to store strings that are short cut into a single byte we need to somehow signal that to the reader of the encoded string, for that we use the fact that zero length strings are rare and generaly not stored on time series. If we have an encoded string with zero length then this will now signal that it represents a mapped value - to learn the true value of this string we need to read the next byte which gives us index in a static mapping. That mapping must include empty string, so that we can still encode empty strings using this scheme.

Example of our mapping (minimal version):

0: ""
1: "__name__"
2: "instance"
3: "job"

With that mapping our example label set would be encoded as:

[0]1[9]my_metric[0]3[3]foo[0]2[3]bar[3]env[4]prod[5]blank[0]0

Which would mean 40 bytes instead of 56.

Given that we have more possible mapping slots we could and should map more strings, but the tricky bit is how to populate this mapping with useful strings that will result in measurable memory savings. This is further complicated by the fact that the mapping must remain static and cannot be modified during Prometheus lifetime. We can use all the 255 slots we have inside our mapping byte with well known generic strings and that will provide some measurable savings for all Prometheus users, and is essentially a slightly more compact stringlabels variant. We could also allow users to pass in a list of well know strings via flags, which will allow Prometheus operators to reduce memory usage for any labels if they know those are popular. Third option is to discover most popular strings from TSDB or WAL on startup, but that's more complicated and we might pick a list that would be the best set of mapped strings on startup, but after some time is no longer the best set.

Benchmark results:
goos: linux
goarch: amd64
pkg: github.com/prometheus/prometheus/model/labels cpu: 13th Gen Intel(R) Core(TM) i7-13800H
                                                 │   main.txt   │                new1.txt                │
                                                 │    sec/op    │    sec/op      vs base                 │
String-20                                           863.8n ± 4%    873.0n ±  4%         ~ (p=0.353 n=10)
Labels_Get/with_5_labels/first_label/get-20         4.763n ± 1%    5.035n ±  0%    +5.72% (p=0.000 n=10)
Labels_Get/with_5_labels/first_label/has-20         3.439n ± 0%    3.967n ±  0%   +15.37% (p=0.000 n=10)
Labels_Get/with_5_labels/middle_label/get-20        7.077n ± 1%    9.588n ±  1%   +35.47% (p=0.000 n=10)
Labels_Get/with_5_labels/middle_label/has-20        5.166n ± 0%    6.990n ±  1%   +35.30% (p=0.000 n=10)
Labels_Get/with_5_labels/last_label/get-20          9.181n ± 1%   12.970n ±  1%   +41.26% (p=0.000 n=10)
Labels_Get/with_5_labels/last_label/has-20          8.101n ± 1%   11.640n ±  1%   +43.69% (p=0.000 n=10)
Labels_Get/with_5_labels/not-found_label/get-20     3.974n ± 0%    4.768n ±  0%   +19.98% (p=0.000 n=10)
Labels_Get/with_5_labels/not-found_label/has-20     3.974n ± 0%    5.033n ±  0%   +26.65% (p=0.000 n=10)
Labels_Get/with_10_labels/first_label/get-20        4.761n ± 0%    5.042n ±  0%    +5.90% (p=0.000 n=10)
Labels_Get/with_10_labels/first_label/has-20        3.442n ± 0%    3.972n ±  0%   +15.40% (p=0.000 n=10)
Labels_Get/with_10_labels/middle_label/get-20       10.62n ± 1%    14.85n ±  1%   +39.83% (p=0.000 n=10)
Labels_Get/with_10_labels/middle_label/has-20       9.360n ± 1%   13.375n ±  0%   +42.90% (p=0.000 n=10)
Labels_Get/with_10_labels/last_label/get-20         18.19n ± 1%    22.00n ±  0%   +20.97% (p=0.000 n=10)
Labels_Get/with_10_labels/last_label/has-20         16.51n ± 0%    20.50n ±  1%   +24.14% (p=0.000 n=10)
Labels_Get/with_10_labels/not-found_label/get-20    3.985n ± 0%    4.768n ±  0%   +19.62% (p=0.000 n=10)
Labels_Get/with_10_labels/not-found_label/has-20    3.973n ± 0%    5.045n ±  0%   +26.97% (p=0.000 n=10)
Labels_Get/with_30_labels/first_label/get-20        4.773n ± 0%    5.050n ±  1%    +5.80% (p=0.000 n=10)
Labels_Get/with_30_labels/first_label/has-20        3.443n ± 1%    3.976n ±  2%   +15.50% (p=0.000 n=10)
Labels_Get/with_30_labels/middle_label/get-20       31.93n ± 0%    43.50n ±  1%   +36.21% (p=0.000 n=10)
Labels_Get/with_30_labels/middle_label/has-20       30.53n ± 0%    41.75n ±  1%   +36.75% (p=0.000 n=10)
Labels_Get/with_30_labels/last_label/get-20        106.55n ± 0%    71.17n ±  0%   -33.21% (p=0.000 n=10)
Labels_Get/with_30_labels/last_label/has-20        104.70n ± 0%    69.21n ±  1%   -33.90% (p=0.000 n=10)
Labels_Get/with_30_labels/not-found_label/get-20    3.976n ± 1%    4.772n ±  0%   +20.03% (p=0.000 n=10)
Labels_Get/with_30_labels/not-found_label/has-20    3.974n ± 0%    5.032n ±  0%   +26.64% (p=0.000 n=10)
Labels_Equals/equal-20                              2.382n ± 0%    2.446n ±  0%    +2.67% (p=0.000 n=10)
Labels_Equals/not_equal-20                         0.2741n ± 2%   0.2662n ±  2%    -2.88% (p=0.001 n=10)
Labels_Equals/different_sizes-20                   0.2762n ± 3%   0.2652n ±  0%    -3.95% (p=0.000 n=10)
Labels_Equals/lots-20                               2.381n ± 0%    2.386n ±  1%    +0.23% (p=0.011 n=10)
Labels_Equals/real_long_equal-20                    6.087n ± 1%    5.558n ±  1%    -8.70% (p=0.000 n=10)
Labels_Equals/real_long_different_end-20            5.030n ± 0%    4.699n ±  0%    -6.57% (p=0.000 n=10)
Labels_Compare/equal-20                             4.814n ± 1%    4.777n ±  0%    -0.77% (p=0.000 n=10)
Labels_Compare/not_equal-20                         17.55n ± 8%    20.92n ±  1%   +19.24% (p=0.000 n=10)
Labels_Compare/different_sizes-20                   3.711n ± 1%    3.707n ±  0%         ~ (p=0.224 n=10)
Labels_Compare/lots-20                              27.09n ± 3%    28.73n ±  2%    +6.05% (p=0.000 n=10)
Labels_Compare/real_long_equal-20                   27.91n ± 3%    15.67n ±  1%   -43.86% (p=0.000 n=10)
Labels_Compare/real_long_different_end-20           33.92n ± 1%    35.35n ±  1%    +4.22% (p=0.000 n=10)
Labels_Hash/typical_labels_under_1KB-20             59.63n ± 0%    59.67n ±  0%         ~ (p=0.897 n=10)
Labels_Hash/bigger_labels_over_1KB-20               73.42n ± 1%    73.81n ±  1%         ~ (p=0.342 n=10)
Labels_Hash/extremely_large_label_value_10MB-20     720.3µ ± 2%    715.2µ ±  3%         ~ (p=0.971 n=10)
Builder-20                                          371.6n ± 4%   1191.0n ±  3%  +220.46% (p=0.000 n=10)
Labels_Copy-20                                      85.52n ± 4%    53.90n ± 48%   -36.97% (p=0.000 n=10)
geomean                                             13.26n         14.68n         +10.71%

                                                 │   main.txt   │               new1.txt               │
                                                 │     B/op     │    B/op     vs base                  │
String-20                                          240.0 ± 0%     240.0 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/first_label/get-20        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/first_label/has-20        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/middle_label/get-20       0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/middle_label/has-20       0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/last_label/get-20         0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/last_label/has-20         0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/not-found_label/get-20    0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/not-found_label/has-20    0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/first_label/get-20       0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/first_label/has-20       0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/middle_label/get-20      0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/middle_label/has-20      0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/last_label/get-20        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/last_label/has-20        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/not-found_label/get-20   0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/not-found_label/has-20   0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/first_label/get-20       0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/first_label/has-20       0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/middle_label/get-20      0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/middle_label/has-20      0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/last_label/get-20        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/last_label/has-20        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/not-found_label/get-20   0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/not-found_label/has-20   0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Equals/equal-20                             0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Equals/not_equal-20                         0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Equals/different_sizes-20                   0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Equals/lots-20                              0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Equals/real_long_equal-20                   0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Equals/real_long_different_end-20           0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Compare/equal-20                            0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Compare/not_equal-20                        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Compare/different_sizes-20                  0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Compare/lots-20                             0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Compare/real_long_equal-20                  0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Compare/real_long_different_end-20          0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Hash/typical_labels_under_1KB-20            0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Hash/bigger_labels_over_1KB-20              0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Hash/extremely_large_label_value_10MB-20    0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Builder-20                                         224.0 ± 0%     192.0 ± 0%  -14.29% (p=0.000 n=10)
Labels_Copy-20                                     224.0 ± 0%     192.0 ± 0%  -14.29% (p=0.000 n=10)
geomean                                                       ²                -0.73%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                                 │   main.txt   │              new1.txt               │
                                                 │  allocs/op   │ allocs/op   vs base                 │
String-20                                          1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/first_label/get-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/first_label/has-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/middle_label/get-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/middle_label/has-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/last_label/get-20         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/last_label/has-20         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/not-found_label/get-20    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/not-found_label/has-20    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/first_label/get-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/first_label/has-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/middle_label/get-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/middle_label/has-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/last_label/get-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/last_label/has-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/not-found_label/get-20   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/not-found_label/has-20   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/first_label/get-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/first_label/has-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/middle_label/get-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/middle_label/has-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/last_label/get-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/last_label/has-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/not-found_label/get-20   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/not-found_label/has-20   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/equal-20                             0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/not_equal-20                         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/different_sizes-20                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/lots-20                              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/real_long_equal-20                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/real_long_different_end-20           0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/equal-20                            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/not_equal-20                        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/different_sizes-20                  0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/lots-20                             0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/real_long_equal-20                  0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/real_long_different_end-20          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Hash/typical_labels_under_1KB-20            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Hash/bigger_labels_over_1KB-20              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Hash/extremely_large_label_value_10MB-20    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Builder-20                                         1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Copy-20                                     1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
geomean                                                       ²               +0.00%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

@prymitive
Copy link
Contributor Author

@bboreham I was hoping to get your thoughts on this approach
I know that there's the deduplabels that is suppose to be the "ultimate" dictionary solution but because the memory usage of it fluctuates a lot I don't feel super optimistic that I can use it - #12304 (comment).
So I'm looking into way to make stringlabels even cheaper.

@prymitive
Copy link
Contributor Author

prymitive commented Feb 7, 2025

Testing a variant of this patch on two servers with ~32M time series each, both scraping same set of targets and using a custom list of strings to map I see:

(vanilla 2.55.1)

    7.32GB 12.42% 12.42%     7.32GB 12.42%  github.com/prometheus/prometheus/model/labels.(*ScratchBuilder).Labels
    6.37GB 10.82% 23.24%     6.37GB 10.82%  github.com/prometheus/prometheus/model/labels.(*Builder).Labels

vs (2.55.1 + patch)

    5.32GB  9.64% 29.67%     5.32GB  9.64%  github.com/prometheus/prometheus/model/labels.(*ScratchBuilder).Labels
    4.57GB  8.29% 37.96%     4.57GB  8.29%  github.com/prometheus/prometheus/model/labels.(*Builder).Labels

And I'm seeing ~4-5GB reduction in go heap, so it does seem worth the effort.

@prymitive prymitive marked this pull request as ready for review February 7, 2025 17:57
@bboreham
Copy link
Member

bboreham commented Feb 7, 2025

Sorry I haven’t read the code yet but fine with the idea. Probably just the hard-coded list of strings.

@prymitive prymitive marked this pull request as draft February 10, 2025 20:20
@prymitive prymitive marked this pull request as ready for review February 11, 2025 09:55
@prymitive
Copy link
Contributor Author

Probably just the hard-coded list of strings.

Hardcoded list works well as a starting point IMHO, so we can start with that.

When I generated a list of most common strings from last TSDB block I've managed to reduce heap from ~70GB to ~61GB, so there's potential to make this a lot more efficient.
If this change gets merged then we could follow up with a feature flag that makes Prometheus read the last TSDB block on startup and build a mapping from that? That's what I will end up doing anyway for our deployments.

@bboreham
Copy link
Member

Can you run the labels package benchmarks please?

@prymitive
Copy link
Contributor Author

Can you run the labels package benchmarks please?

They are attached to my first comment, but might be outdated with latest changes so let me re-run there. Takes a while and it's late so might be ready tomorrow.

@bboreham
Copy link
Member

Regarding the hard-coded strings, I don't want this to descend into bike-shedding, but I do think as Kubernetes users we have quite a different profile from you.
From the TSDB Status page on a couple of Prometheus at work I got:

Label Names

instance
__name__
job
pod
name
cluster
image
namespace
uid
status_code
method
container
address
container_id
name
cidr
pod_ip
node_id

Label Values:

false
200
GET
kube-system/cadvisor
kube-system/kubelet
kube-state-metrics/kube-state-metrics
node-exporter/node-exporter
node-exporter
kube-system

Metric names

(excluding ones from home-grown software)
kafka_writer_write_wait_seconds_bucket
kafka_writer_write_time_seconds_bucket
storage_operation_duration_seconds_bucket
kube_pod_status_phase
kube_pod_status_ready
container_spec_cpu_period
container_spec_memory_limit_bytes
container_memory_working_set_bytes
container_memory_usage_bytes
container_memory_max_usage_bytes
container_cpu_usage_seconds_total
kube_pod_container_resource_requests
kube_pod_container_status_restarts_total

@bboreham
Copy link
Member

read the last TSDB block on startup and build a mapping from that

Isn't that quite an intensive operation, involving reading the whole index?
Another thought would be to have the WAL checkpoint process emit the table we need. But maybe it comes out the same.

@prymitive
Copy link
Contributor Author

Latest benchmark results (folded)
goos: linux
goarch: amd64
pkg: github.com/prometheus/prometheus/model/labels
cpu: 13th Gen Intel(R) Core(TM) i7-13800H
                                                                                                                                                   │   main.txt    │                  new.txt                  │
                                                                                                                                                   │    sec/op     │    sec/op      vs base                    │
String-20                                                                                                                                             852.1n ±  2%    879.3n ±  3%     +3.19% (p=0.000 n=10)
Labels_Get/with_5_labels/first_label/get-20                                                                                                           4.770n ±  1%    5.042n ±  2%     +5.68% (p=0.000 n=10)
Labels_Get/with_5_labels/first_label/has-20                                                                                                           3.447n ±  0%    3.971n ±  0%    +15.22% (p=0.000 n=10)
Labels_Get/with_5_labels/middle_label/get-20                                                                                                          9.147n ±  1%    9.257n ±  1%     +1.21% (p=0.014 n=10)
Labels_Get/with_5_labels/middle_label/has-20                                                                                                          5.191n ±  1%    7.146n ±  1%    +37.66% (p=0.000 n=10)
Labels_Get/with_5_labels/last_label/get-20                                                                                                            11.88n ±  2%    12.70n ±  1%     +6.82% (p=0.000 n=10)
Labels_Get/with_5_labels/last_label/has-20                                                                                                            9.918n ±  3%   12.050n ±  1%    +21.50% (p=0.000 n=10)
Labels_Get/with_5_labels/not-found_label/get-20                                                                                                       3.984n ±  2%    4.773n ±  0%    +19.82% (p=0.000 n=10)
Labels_Get/with_5_labels/not-found_label/has-20                                                                                                       4.022n ±  2%    5.044n ±  0%    +25.39% (p=0.000 n=10)
Labels_Get/with_10_labels/first_label/get-20                                                                                                          4.769n ±  1%    5.041n ±  1%     +5.70% (p=0.000 n=10)
Labels_Get/with_10_labels/first_label/has-20                                                                                                          3.446n ±  0%    3.972n ±  0%    +15.28% (p=0.000 n=10)
Labels_Get/with_10_labels/middle_label/get-20                                                                                                         12.61n ±  1%    14.55n ±  0%    +15.38% (p=0.000 n=10)
Labels_Get/with_10_labels/middle_label/has-20                                                                                                         10.61n ±  1%    13.66n ±  1%    +28.75% (p=0.000 n=10)
Labels_Get/with_10_labels/last_label/get-20                                                                                                           17.99n ±  0%    21.72n ±  1%    +20.73% (p=0.000 n=10)
Labels_Get/with_10_labels/last_label/has-20                                                                                                           16.45n ±  0%    20.65n ±  1%    +25.57% (p=0.000 n=10)
Labels_Get/with_10_labels/not-found_label/get-20                                                                                                      3.984n ±  1%    4.771n ±  0%    +19.75% (p=0.000 n=10)
Labels_Get/with_10_labels/not-found_label/has-20                                                                                                      4.052n ±  2%    5.040n ±  0%    +24.37% (p=0.000 n=10)
Labels_Get/with_30_labels/first_label/get-20                                                                                                          4.771n ±  1%    5.041n ±  1%     +5.66% (p=0.000 n=10)
Labels_Get/with_30_labels/first_label/has-20                                                                                                          3.447n ±  0%    3.971n ±  1%    +15.20% (p=0.000 n=10)
Labels_Get/with_30_labels/middle_label/get-20                                                                                                         51.38n ±  2%    43.08n ±  0%    -16.15% (p=0.000 n=10)
Labels_Get/with_30_labels/middle_label/has-20                                                                                                         53.02n ±  1%    41.96n ±  0%    -20.85% (p=0.000 n=10)
Labels_Get/with_30_labels/last_label/get-20                                                                                                          106.25n ±  1%    71.05n ±  0%    -33.13% (p=0.000 n=10)
Labels_Get/with_30_labels/last_label/has-20                                                                                                          104.35n ±  1%    70.35n ±  1%    -32.59% (p=0.000 n=10)
Labels_Get/with_30_labels/not-found_label/get-20                                                                                                      3.986n ±  1%    4.769n ±  0%    +19.63% (p=0.000 n=10)
Labels_Get/with_30_labels/not-found_label/has-20                                                                                                      4.021n ±  1%    5.048n ±  1%    +25.55% (p=0.000 n=10)
Labels_Equals/equal-20                                                                                                                                2.386n ±  0%    2.383n ±  0%     -0.13% (p=0.002 n=10)
Labels_Equals/not_equal-20                                                                                                                           0.2662n ±  2%   0.4163n ± 20%    +56.39% (p=0.000 n=10)
Labels_Equals/different_sizes-20                                                                                                                     0.2657n ±  0%   0.4400n ± 26%    +65.58% (p=0.000 n=10)
Labels_Equals/lots-20                                                                                                                                 2.385n ±  1%    2.384n ±  1%          ~ (p=0.223 n=10)
Labels_Equals/real_long_equal-20                                                                                                                      6.094n ±  0%    5.564n ±  0%     -8.69% (p=0.000 n=10)
Labels_Equals/real_long_different_end-20                                                                                                              5.134n ±  0%    4.710n ±  1%     -8.25% (p=0.000 n=10)
Labels_Compare/equal-20                                                                                                                               4.768n ±  0%    4.778n ±  0%          ~ (p=0.065 n=10)
Labels_Compare/not_equal-20                                                                                                                           18.34n ±  1%    18.96n ±  2%     +3.35% (p=0.000 n=10)
Labels_Compare/different_sizes-20                                                                                                                     3.715n ±  0%    3.724n ±  1%          ~ (p=0.093 n=10)
Labels_Compare/lots-20                                                                                                                                26.12n ±  1%    27.55n ±  1%     +5.47% (p=0.000 n=10)
Labels_Compare/real_long_equal-20                                                                                                                     16.82n ±  2%    15.67n ±  2%     -6.86% (p=0.000 n=10)
Labels_Compare/real_long_different_end-20                                                                                                             29.61n ±  1%    35.19n ±  0%    +18.87% (p=0.000 n=10)
Labels_Hash/typical_labels_under_1KB-20                                                                                                               59.55n ±  1%    59.59n ±  0%          ~ (p=0.895 n=10)
Labels_Hash/bigger_labels_over_1KB-20                                                                                                                 73.16n ±  0%    73.45n ±  1%     +0.40% (p=0.041 n=10)
Labels_Hash/extremely_large_label_value_10MB-20                                                                                                       699.7µ ±  3%    707.8µ ±  2%          ~ (p=0.315 n=10)
Builder-20                                                                                                                                            358.6n ±  5%   7328.5n ±  1%  +1943.64% (p=0.000 n=10)
Labels_Copy-20                                                                                                                                        92.91n ±  4%    51.42n ± 39%    -44.65% (p=0.000 n=10)
MatchType_String-20                                                                                                                                  0.6626n ±  0%   0.6614n ±  1%          ~ (p=0.424 n=10)
NewMatcher/regex_matcher_with_literal-20                                                                                                              219.9n ±  2%    151.4n ± 31%    -31.13% (p=0.000 n=10)
Matcher_String/short_name_equal-20                                                                                                                    53.30n ±  3%    51.66n ±  7%          ~ (p=0.190 n=10)
Matcher_String/short_quoted_name_not_equal-20                                                                                                         63.81n ±  2%    63.67n ±  4%          ~ (p=0.542 n=10)
Matcher_String/short_quoted_name_with_quotes_not_equal-20                                                                                             67.62n ±  2%    68.52n ±  6%          ~ (p=0.315 n=10)
Matcher_String/short_name_value_with_quotes_equal-20                                                                                                  57.99n ±  2%    59.32n ±  7%          ~ (p=0.403 n=10)
Matcher_String/short_name_and_long_value_regexp-20                                                                                                    243.9n ±  4%    238.8n ±  2%          ~ (p=0.089 n=10)
Matcher_String/short_name_and_long_value_with_quotes_equal-20                                                                                         260.4n ±  3%    266.4n ±  3%          ~ (p=0.184 n=10)
Matcher_String/long_name_regexp-20                                                                                                                    119.2n ±  8%    124.3n ±  6%          ~ (p=0.060 n=10)
Matcher_String/long_quoted_name_regexp-20                                                                                                             265.4n ±  3%    266.4n ±  3%          ~ (p=0.529 n=10)
Matcher_String/long_name_and_long_value_regexp-20                                                                                                     334.9n ±  3%    337.2n ±  5%          ~ (p=0.315 n=10)
Matcher_String/long_quoted_name_and_long_value_regexp-20                                                                                              447.3n ±  3%    458.6n ±  5%          ~ (p=0.105 n=10)
Matcher_String/mixed-20                                                                                                                               196.8n ±  6%    197.2n ±  4%          ~ (p=0.404 n=10)
FastRegexMatcher/#00-20                                                                                                                               44.22n ± 11%    42.21n ±  1%     -4.57% (p=0.000 n=10)
FastRegexMatcher/foo-20                                                                                                                               54.74n ±  1%    42.79n ±  0%    -21.83% (p=0.000 n=10)
FastRegexMatcher/^foo-20                                                                                                                              40.00n ±  1%    46.07n ±  1%    +15.16% (p=0.000 n=10)
FastRegexMatcher/(foo|bar)-20                                                                                                                         53.14n ±  0%    57.61n ±  1%     +8.41% (p=0.000 n=10)
FastRegexMatcher/foo.*-20                                                                                                                             109.2n ±  4%    112.8n ±  1%     +3.30% (p=0.001 n=10)
FastRegexMatcher/.*foo-20                                                                                                                             142.3n ±  4%    128.0n ±  2%    -10.08% (p=0.000 n=10)
FastRegexMatcher/^.*foo$-20                                                                                                                           141.1n ±  5%    127.6n ±  2%     -9.57% (p=0.000 n=10)
FastRegexMatcher/^.+foo$-20                                                                                                                           140.5n ±  2%    129.5n ±  1%     -7.83% (p=0.000 n=10)
FastRegexMatcher/.?-20                                                                                                                                65.91n ±  1%    61.45n ±  0%     -6.75% (p=0.000 n=10)
FastRegexMatcher/.*-20                                                                                                                                44.07n ±  1%    40.14n ±  0%     -8.92% (p=0.000 n=10)
FastRegexMatcher/.+-20                                                                                                                                48.78n ±  0%    44.04n ±  0%     -9.72% (p=0.000 n=10)
FastRegexMatcher/foo.+-20                                                                                                                             109.9n ±  3%    111.3n ±  2%          ~ (p=0.425 n=10)
FastRegexMatcher/.+foo-20                                                                                                                             140.8n ±  9%    128.0n ± 10%     -9.12% (p=0.001 n=10)
FastRegexMatcher/foo_.+-20                                                                                                                            103.8n ±  3%    101.5n ±  3%          ~ (p=0.190 n=10)
FastRegexMatcher/foo_.*-20                                                                                                                            104.4n ± 10%    104.3n ±  4%          ~ (p=0.927 n=10)
FastRegexMatcher/.*foo.*-20                                                                                                                           194.8n ±  0%    199.1n ±  0%     +2.18% (p=0.000 n=10)
FastRegexMatcher/.+foo.+-20                                                                                                                           211.9n ±  1%    210.8n ±  0%     -0.54% (p=0.002 n=10)
FastRegexMatcher/(?s:.*)-20                                                                                                                           44.02n ±  0%    40.07n ±  0%     -8.97% (p=0.000 n=10)
FastRegexMatcher/(?s:.+)-20                                                                                                                           48.88n ±  1%    44.02n ±  0%     -9.94% (p=0.000 n=10)
FastRegexMatcher/(?s:^.*foo$)-20                                                                                                                      140.9n ±  2%    128.2n ±  2%     -9.01% (p=0.000 n=10)
FastRegexMatcher/(?i:foo)-20                                                                                                                          78.61n ±  0%    78.00n ±  0%     -0.78% (p=0.000 n=10)
FastRegexMatcher/(?i:(foo|bar))-20                                                                                                                    179.8n ±  0%    169.8n ±  1%     -5.56% (p=0.000 n=10)
FastRegexMatcher/(?i:(foo1|foo2|bar))-20                                                                                                              308.1n ±  0%    302.2n ±  1%     -1.91% (p=0.000 n=10)
FastRegexMatcher/^(?i:foo|oo)|(bar)$-20                                                                                                               838.3n ±  1%    827.5n ±  1%     -1.29% (p=0.000 n=10)
FastRegexMatcher/(?i:(foo1|foo2|aaa|bbb|ccc|ddd|e-20                                                                                                  848.1n ±  5%    799.4n ±  5%     -5.74% (p=0.029 n=10)
FastRegexMatcher/((.*)(bar|b|buzz)(.+)|foo)$-20                                                                                                       479.6n ±  1%    461.1n ±  1%     -3.86% (p=0.000 n=10)
FastRegexMatcher/^$-20                                                                                                                                44.01n ±  0%    42.27n ±  0%     -3.95% (p=0.000 n=10)
FastRegexMatcher/(prometheus|api_prom)_api_v1_.+-20                                                                                                   165.5n ±  0%    169.2n ±  1%     +2.21% (p=0.000 n=10)
FastRegexMatcher/10\.0\.(1|2)\.+-20                                                                                                                   105.2n ±  3%    101.6n ±  7%     -3.37% (p=0.000 n=10)
FastRegexMatcher/10\.0\.(1|2).+-20                                                                                                                    104.4n ±  2%    101.0n ±  6%     -3.26% (p=0.004 n=10)
FastRegexMatcher/((fo(bar))|.+foo)-20                                                                                                                 266.2n ±  1%    258.0n ±  1%     -3.10% (p=0.000 n=10)
FastRegexMatcher/zQPbMkNO|NNSPdvMi|iWuuSoAl|qbvKM-20                                                                                                  249.2n ±  6%    239.4n ±  5%     -3.91% (p=0.004 n=10)
FastRegexMatcher/jyyfj00j0061|jyyfj00j0062|jyyfj9-20                                                                                                  243.6n ±  3%    240.2n ±  3%          ~ (p=0.247 n=10)
FastRegexMatcher/(?i:(zQPbMkNO|NNSPdvMi|iWuuSoAl|-20                                                                                                  875.2n ±  4%    800.1n ±  3%     -8.59% (p=0.000 n=10)
FastRegexMatcher/(?i:(AAAAAAAAAAAAAAAAAAAAAAAA|BB-20                                                                                                  353.1n ±  0%    351.9n ±  0%     -0.33% (p=0.000 n=10)
FastRegexMatcher/(?i:(zQPbMkNO.*|NNSPdvMi.*|iWuuS-20                                                                                                  254.4n ±  0%    225.5n ±  0%    -11.36% (p=0.000 n=10)
FastRegexMatcher/(?i:(zQPbMkNO.*|NNSPdvMi.*|iWuuS#01-20                                                                                               475.8n ±  1%    492.3n ±  2%     +3.48% (p=0.000 n=10)
FastRegexMatcher/(?i:(.*zQPbMkNO|.*NNSPdvMi|.*iWu-20                                                                                                  8.123µ ±  1%    7.529µ ±  0%     -7.31% (p=0.000 n=10)
FastRegexMatcher/fo.?-20                                                                                                                              109.8n ±  2%    114.4n ±  4%     +4.19% (p=0.002 n=10)
FastRegexMatcher/foo.?-20                                                                                                                             110.2n ±  1%    115.5n ±  3%     +4.76% (p=0.000 n=10)
FastRegexMatcher/f.?o-20                                                                                                                              113.0n ±  3%    112.7n ±  3%          ~ (p=0.424 n=10)
FastRegexMatcher/.*foo.?-20                                                                                                                           207.7n ±  0%    209.4n ±  2%     +0.84% (p=0.000 n=10)
FastRegexMatcher/.?foo.+-20                                                                                                                           202.5n ±  0%    206.2n ±  0%     +1.83% (p=0.000 n=10)
FastRegexMatcher/foo.?|bar-20                                                                                                                         201.1n ±  1%    186.2n ±  0%     -7.43% (p=0.000 n=10)
FastRegexMatcher/ſſs-20                                                                                                                               54.27n ±  1%    42.99n ±  1%    -20.78% (p=0.000 n=10)
FastRegexMatcher/.*-.*-.*-.*-.*-20                                                                                                                    196.1n ±  1%    194.6n ±  1%     -0.74% (p=0.005 n=10)
FastRegexMatcher/(.+)-(.+)-(.+)-(.+)-(.+)-20                                                                                                          196.7n ±  0%    194.6n ±  1%     -1.04% (p=0.007 n=10)
FastRegexMatcher/((.*))(?i:f)((.*))o((.*))o((.*))-20                                                                                                  4.250µ ±  0%    4.243µ ±  1%          ~ (p=0.382 n=10)
FastRegexMatcher/((.*))f((.*))(?i:o)((.*))o((.*))-20                                                                                                  3.330µ ±  1%    3.318µ ±  0%          ~ (p=0.445 n=10)
ToNormalizedLower/length=10/uppercase=none/ascii=true-20                                                                                              6.987n ±  1%    7.293n ±  1%     +4.37% (p=0.000 n=10)
ToNormalizedLower/length=10/uppercase=none/ascii=false-20                                                                                             167.4n ±  1%    167.2n ±  1%          ~ (p=0.753 n=10)
ToNormalizedLower/length=10/uppercase=first/ascii=true-20                                                                                             11.20n ±  0%    11.48n ±  0%     +2.50% (p=0.000 n=10)
ToNormalizedLower/length=10/uppercase=first/ascii=false-20                                                                                            189.7n ±  1%    191.6n ±  1%          ~ (p=0.079 n=10)
ToNormalizedLower/length=10/uppercase=last/ascii=true-20                                                                                              11.12n ±  0%    10.29n ±  1%     -7.46% (p=0.000 n=10)
ToNormalizedLower/length=10/uppercase=last/ascii=false-20                                                                                             185.0n ±  2%    184.6n ±  2%          ~ (p=0.446 n=10)
ToNormalizedLower/length=10/uppercase=all/ascii=true-20                                                                                               13.77n ±  0%    13.86n ±  0%     +0.62% (p=0.000 n=10)
ToNormalizedLower/length=10/uppercase=all/ascii=false-20                                                                                              179.4n ±  1%    178.0n ±  3%          ~ (p=0.565 n=10)
ToNormalizedLower/length=100/uppercase=none/ascii=true-20                                                                                             55.76n ±  0%    55.63n ±  0%     -0.23% (p=0.041 n=10)
ToNormalizedLower/length=100/uppercase=none/ascii=false-20                                                                                            2.929µ ±  3%    2.974µ ±  5%          ~ (p=0.542 n=10)
ToNormalizedLower/length=100/uppercase=first/ascii=true-20                                                                                            60.59n ±  0%    69.93n ±  1%    +15.43% (p=0.000 n=10)
ToNormalizedLower/length=100/uppercase=first/ascii=false-20                                                                                           3.014µ ±  3%    3.174µ ±  4%     +5.31% (p=0.009 n=10)
ToNormalizedLower/length=100/uppercase=last/ascii=true-20                                                                                             59.31n ±  0%    55.53n ±  1%     -6.36% (p=0.000 n=10)
ToNormalizedLower/length=100/uppercase=last/ascii=false-20                                                                                            3.039µ ±  4%    3.106µ ±  3%          ~ (p=0.123 n=10)
ToNormalizedLower/length=100/uppercase=all/ascii=true-20                                                                                              86.13n ±  1%    90.61n ±  1%     +5.21% (p=0.000 n=10)
ToNormalizedLower/length=100/uppercase=all/ascii=false-20                                                                                             2.782µ ± 10%    3.093µ ±  6%    +11.20% (p=0.003 n=10)
ToNormalizedLower/length=1000/uppercase=none/ascii=true-20                                                                                            529.0n ±  1%    413.0n ±  0%    -21.92% (p=0.000 n=10)
ToNormalizedLower/length=1000/uppercase=none/ascii=false-20                                                                                           22.57µ ±  2%    22.30µ ±  2%          ~ (p=0.393 n=10)
ToNormalizedLower/length=1000/uppercase=first/ascii=true-20                                                                                           855.1n ± 15%   1075.5n ±  3%    +25.78% (p=0.000 n=10)
ToNormalizedLower/length=1000/uppercase=first/ascii=false-20                                                                                          23.69µ ±  5%    23.37µ ±  3%          ~ (p=0.448 n=10)
ToNormalizedLower/length=1000/uppercase=last/ascii=true-20                                                                                           1011.5n ± 32%    925.1n ±  4%          ~ (p=0.143 n=10)
ToNormalizedLower/length=1000/uppercase=last/ascii=false-20                                                                                           22.43µ ±  6%    22.50µ ±  2%          ~ (p=0.631 n=10)
ToNormalizedLower/length=1000/uppercase=all/ascii=true-20                                                                                             1.334µ ±  5%    1.303µ ±  3%          ~ (p=0.363 n=10)
ToNormalizedLower/length=1000/uppercase=all/ascii=false-20                                                                                            22.51µ ±  2%    23.01µ ±  4%          ~ (p=0.143 n=10)
ToNormalizedLower/length=4000/uppercase=none/ascii=true-20                                                                                            2.073µ ±  1%    1.607µ ±  0%    -22.50% (p=0.000 n=10)
ToNormalizedLower/length=4000/uppercase=none/ascii=false-20                                                                                           85.87µ ±  2%    87.02µ ±  2%          ~ (p=0.218 n=10)
ToNormalizedLower/length=4000/uppercase=first/ascii=true-20                                                                                           4.293µ ±  2%    4.275µ ±  4%          ~ (p=0.565 n=10)
ToNormalizedLower/length=4000/uppercase=first/ascii=false-20                                                                                          90.60µ ±  3%    90.36µ ±  2%          ~ (p=1.000 n=10)
ToNormalizedLower/length=4000/uppercase=last/ascii=true-20                                                                                            3.945µ ±  5%    3.718µ ±  3%     -5.74% (p=0.009 n=10)
ToNormalizedLower/length=4000/uppercase=last/ascii=false-20                                                                                           87.08µ ±  2%    88.07µ ±  2%          ~ (p=0.063 n=10)
ToNormalizedLower/length=4000/uppercase=all/ascii=true-20                                                                                             5.470µ ±  7%    5.338µ ±  6%          ~ (p=0.315 n=10)
ToNormalizedLower/length=4000/uppercase=all/ascii=false-20                                                                                            85.93µ ±  2%    86.98µ ±  3%          ~ (p=0.436 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20        160.4n ±  1%    154.6n ±  0%     -3.58% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20           178.5n ±  1%    182.5n ±  2%     +2.27% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20       154.3n ±  1%    132.6n ±  0%    -14.12% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20          83.66n ±  1%    86.48n ±  0%     +3.36% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20       149.4n ±  1%
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20          366.1n ±  2%
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20      144.2n ±  0%    146.9n ±  1%     +1.84% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20         107.5n ±  0%    115.2n ±  0%     +7.11% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20        265.3n ±  1%    260.6n ±  1%     -1.77% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20           251.3n ±  2%    262.4n ±  2%     +4.42% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20       251.9n ±  2%    218.3n ±  0%    -13.32% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20          146.5n ±  1%    145.5n ±  1%          ~ (p=0.078 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20       256.2n ±  1%    271.7n ±  3%     +6.07% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20          451.0n ±  1%    419.5n ±  3%     -6.99% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20      239.5n ±  0%    242.2n ±  0%     +1.11% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20         172.0n ±  1%    190.7n ±  1%    +10.84% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20        483.9n ±  1%    497.4n ±  1%     +2.79% (p=0.001 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20           496.5n ±  1%    493.2n ±  1%          ~ (p=0.060 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20       443.2n ±  1%    376.4n ±  2%    -15.05% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20          226.0n ±  1%    224.5n ±  0%     -0.64% (p=0.006 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20       448.8n ±  1%    507.0n ±  1%    +12.96% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20          487.6n ±  2%    569.6n ±  5%    +16.83% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20      504.2n ±  0%    561.6n ±  1%    +11.40% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20         311.4n ±  1%    337.9n ±  1%     +8.51% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20       883.3n ±  2%    874.2n ±  1%     -1.03% (p=0.009 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20          234.8n ±  0%    215.8n ±  1%     -8.07% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20      797.0n ±  1%    680.5n ±  1%    -14.61% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20         216.1n ±  1%    195.9n ±  1%     -9.39% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20      958.4n ±  0%    920.9n ±  4%     -3.91% (p=0.022 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20         274.4n ±  1%    299.4n ±  1%     +9.09% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20     887.9n ±  0%    891.5n ±  0%     +0.41% (p=0.025 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20        603.4n ±  3%    539.6n ±  3%    -10.58% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20       1.740µ ±  0%    1.909µ ±  0%     +9.74% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20          224.3n ±  1%    211.9n ±  0%     -5.55% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20      1.507µ ±  0%    1.386µ ±  1%     -8.03% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20         204.2n ±  1%    196.0n ±  0%     -3.99% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20      1.721µ ±  0%    1.910µ ±  0%    +11.01% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20         277.2n ±  0%    374.0n ±  1%    +34.92% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20     1.707µ ±  1%    1.812µ ±  0%     +6.18% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20        608.2n ±  2%    527.4n ±  2%    -13.30% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20       3.534µ ±  1%    3.667µ ±  1%     +3.78% (p=0.001 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20          264.4n ±  1%    247.7n ±  0%     -6.32% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20      3.093µ ±  1%    2.773µ ±  1%    -10.35% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20         204.4n ±  1%    201.6n ±  0%     -1.39% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20      3.712µ ±  0%    3.528µ ±  1%     -4.96% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20         378.2n ±  1%    365.8n ±  0%     -3.28% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20     3.533µ ±  1%    3.511µ ±  2%          ~ (p=0.101 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20        599.4n ±  2%    541.9n ±  2%     -9.59% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20      6.862µ ±  0%    6.801µ ±  2%          ~ (p=0.078 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20         290.5n ±  1%    301.8n ±  1%     +3.89% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20     5.695µ ±  0%    5.190µ ±  0%     -8.88% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20        207.9n ±  1%    209.9n ±  1%     +0.99% (p=0.001 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20     7.228µ ±  1%    7.271µ ±  0%     +0.59% (p=0.023 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20        476.3n ±  0%    537.2n ±  1%    +12.79% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20    6.971µ ±  1%    6.917µ ±  0%     -0.77% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20       599.6n ±  1%    533.3n ±  2%    -11.06% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20      13.65µ ±  1%    13.70µ ±  0%          ~ (p=0.143 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20         412.1n ±  0%    352.6n ±  0%    -14.44% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20     11.98µ ±  1%    10.63µ ±  3%    -11.27% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20        212.8n ±  1%    209.9n ±  1%     -1.39% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20     14.71µ ±  1%    14.05µ ±  1%     -4.52% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20        757.2n ±  0%    699.2n ±  1%     -7.67% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20    14.39µ ±  0%    13.84µ ±  0%     -3.83% (p=0.000 n=10)
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20       597.9n ±  3%    537.6n ±  1%    -10.08% (p=0.000 n=10)
ZeroOrOneCharacterStringMatcher-20                                                                                                                    3.547n ±  2%    3.592n ±  1%     +1.27% (p=0.009 n=10)
geomean                                                                                                                                               195.9n          197.8n           +1.18%                ¹
¹ benchmark set differs from baseline; geomeans may not be comparable

                                                                                                                                                   │    main.txt    │                 new.txt                 │
                                                                                                                                                   │      B/op      │     B/op      vs base                   │
String-20                                                                                                                                              240.0 ± 0%       240.0 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/first_label/get-20                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/first_label/has-20                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/middle_label/get-20                                                                                                           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/middle_label/has-20                                                                                                           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/last_label/get-20                                                                                                             0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/last_label/has-20                                                                                                             0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/not-found_label/get-20                                                                                                        0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/not-found_label/has-20                                                                                                        0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/first_label/get-20                                                                                                           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/first_label/has-20                                                                                                           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/middle_label/get-20                                                                                                          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/middle_label/has-20                                                                                                          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/last_label/get-20                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/last_label/has-20                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/not-found_label/get-20                                                                                                       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/not-found_label/has-20                                                                                                       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/first_label/get-20                                                                                                           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/first_label/has-20                                                                                                           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/middle_label/get-20                                                                                                          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/middle_label/has-20                                                                                                          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/last_label/get-20                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/last_label/has-20                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/not-found_label/get-20                                                                                                       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/not-found_label/has-20                                                                                                       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/equal-20                                                                                                                                 0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/not_equal-20                                                                                                                             0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/different_sizes-20                                                                                                                       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/lots-20                                                                                                                                  0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/real_long_equal-20                                                                                                                       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/real_long_different_end-20                                                                                                               0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/equal-20                                                                                                                                0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/not_equal-20                                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/different_sizes-20                                                                                                                      0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/lots-20                                                                                                                                 0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/real_long_equal-20                                                                                                                      0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/real_long_different_end-20                                                                                                              0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Hash/typical_labels_under_1KB-20                                                                                                                0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Hash/bigger_labels_over_1KB-20                                                                                                                  0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Hash/extremely_large_label_value_10MB-20                                                                                                        0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
Builder-20                                                                                                                                             224.0 ± 0%       208.0 ± 0%  -7.14% (p=0.000 n=10)
Labels_Copy-20                                                                                                                                         224.0 ± 0%       208.0 ± 0%  -7.14% (p=0.000 n=10)
MatchType_String-20                                                                                                                                    0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
NewMatcher/regex_matcher_with_literal-20                                                                                                               240.0 ± 0%       240.0 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/short_name_equal-20                                                                                                                     16.00 ± 0%       16.00 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/short_quoted_name_not_equal-20                                                                                                          16.00 ± 0%       16.00 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/short_quoted_name_with_quotes_not_equal-20                                                                                              16.00 ± 0%       16.00 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/short_name_value_with_quotes_equal-20                                                                                                   16.00 ± 0%       16.00 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/short_name_and_long_value_regexp-20                                                                                                     64.00 ± 0%       64.00 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/short_name_and_long_value_with_quotes_equal-20                                                                                          64.00 ± 0%       64.00 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/long_name_regexp-20                                                                                                                     64.00 ± 0%       64.00 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/long_quoted_name_regexp-20                                                                                                              64.00 ± 0%       64.00 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/long_name_and_long_value_regexp-20                                                                                                      112.0 ± 0%       112.0 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/long_quoted_name_and_long_value_regexp-20                                                                                               112.0 ± 0%       112.0 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/mixed-20                                                                                                                                54.00 ± 0%       54.00 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/#00-20                                                                                                                                0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/foo-20                                                                                                                                0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/^foo-20                                                                                                                               0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(foo|bar)-20                                                                                                                          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/foo.*-20                                                                                                                              0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.*foo-20                                                                                                                              0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/^.*foo$-20                                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/^.+foo$-20                                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.?-20                                                                                                                                 0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.*-20                                                                                                                                 0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.+-20                                                                                                                                 0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/foo.+-20                                                                                                                              0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.+foo-20                                                                                                                              0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/foo_.+-20                                                                                                                             0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/foo_.*-20                                                                                                                             0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.*foo.*-20                                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.+foo.+-20                                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?s:.*)-20                                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?s:.+)-20                                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?s:^.*foo$)-20                                                                                                                       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:foo)-20                                                                                                                           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(foo|bar))-20                                                                                                                     0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(foo1|foo2|bar))-20                                                                                                               0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/^(?i:foo|oo)|(bar)$-20                                                                                                                0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(foo1|foo2|aaa|bbb|ccc|ddd|e-20                                                                                                   240.0 ± 0%       240.0 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/((.*)(bar|b|buzz)(.+)|foo)$-20                                                                                                        0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/^$-20                                                                                                                                 0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(prometheus|api_prom)_api_v1_.+-20                                                                                                    0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/10\.0\.(1|2)\.+-20                                                                                                                    0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/10\.0\.(1|2).+-20                                                                                                                     0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/((fo(bar))|.+foo)-20                                                                                                                  0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/zQPbMkNO|NNSPdvMi|iWuuSoAl|qbvKM-20                                                                                                   0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/jyyfj00j0061|jyyfj00j0062|jyyfj9-20                                                                                                   0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(zQPbMkNO|NNSPdvMi|iWuuSoAl|-20                                                                                                   240.0 ± 0%       240.0 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(AAAAAAAAAAAAAAAAAAAAAAAA|BB-20                                                                                                   0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(zQPbMkNO.*|NNSPdvMi.*|iWuuS-20                                                                                                   0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(zQPbMkNO.*|NNSPdvMi.*|iWuuS#01-20                                                                                                0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(.*zQPbMkNO|.*NNSPdvMi|.*iWu-20                                                                                                   0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/fo.?-20                                                                                                                               0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/foo.?-20                                                                                                                              0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/f.?o-20                                                                                                                               0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.*foo.?-20                                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.?foo.+-20                                                                                                                            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/foo.?|bar-20                                                                                                                          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/ſſs-20                                                                                                                                0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.*-.*-.*-.*-.*-20                                                                                                                     0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(.+)-(.+)-(.+)-(.+)-(.+)-20                                                                                                           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/((.*))(?i:f)((.*))o((.*))o((.*))-20                                                                                                   0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/((.*))f((.*))(?i:o)((.*))o((.*))-20                                                                                                   0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=none/ascii=true-20                                                                                               0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=none/ascii=false-20                                                                                              9.000 ± 0%       9.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=first/ascii=true-20                                                                                              0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=first/ascii=false-20                                                                                             11.00 ± 0%       11.00 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=last/ascii=true-20                                                                                               0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=last/ascii=false-20                                                                                              11.00 ± 0%       11.00 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=all/ascii=true-20                                                                                                0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=all/ascii=false-20                                                                                               16.00 ± 0%       16.00 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=none/ascii=true-20                                                                                              0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=none/ascii=false-20                                                                                           1.050Ki ± 0%     1.050Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=first/ascii=true-20                                                                                             0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=first/ascii=false-20                                                                                          1.061Ki ± 0%     1.061Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=last/ascii=true-20                                                                                              0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=last/ascii=false-20                                                                                           1.061Ki ± 0%     1.061Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=all/ascii=true-20                                                                                               0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=all/ascii=false-20                                                                                            1.094Ki ± 0%     1.094Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=none/ascii=true-20                                                                                             0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=none/ascii=false-20                                                                                          4.862Ki ± 0%     4.862Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=first/ascii=true-20                                                                                          1.000Ki ± 0%     1.000Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=first/ascii=false-20                                                                                         5.375Ki ± 0%     5.375Ki ± 0%       ~ (p=1.000 n=10)
ToNormalizedLower/length=1000/uppercase=last/ascii=true-20                                                                                           1.000Ki ± 0%     1.000Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=last/ascii=false-20                                                                                          4.975Ki ± 0%     4.975Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=all/ascii=true-20                                                                                            1.000Ki ± 0%     1.000Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=all/ascii=false-20                                                                                           5.712Ki ± 0%     5.712Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=none/ascii=true-20                                                                                             0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=none/ascii=false-20                                                                                          17.41Ki ± 0%     17.41Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=first/ascii=true-20                                                                                          4.000Ki ± 0%     4.000Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=first/ascii=false-20                                                                                         19.49Ki ± 0%     19.49Ki ± 0%       ~ (p=0.211 n=10)
ToNormalizedLower/length=4000/uppercase=last/ascii=true-20                                                                                           4.000Ki ± 0%     4.000Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=last/ascii=false-20                                                                                          17.89Ki ± 0%     17.89Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=all/ascii=true-20                                                                                            4.000Ki ± 0%     4.000Ki ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=all/ascii=false-20                                                                                           20.91Ki ± 0%     20.91Ki ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20           0.000 ± 0%
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20            0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20         112.0 ± 0%       112.0 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20         112.0 ± 0%       112.0 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20           0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20         112.0 ± 0%       112.0 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20     0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20        112.0 ± 0%       112.0 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20     0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20        112.0 ± 0%       112.0 ± 0%       ~ (p=1.000 n=10) ¹
ZeroOrOneCharacterStringMatcher-20                                                                                                                     0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=10) ¹
geomean                                                                                                                                                           ²                 -0.07%                ³ ²
¹ all samples are equal
² summaries must be >0 to compute geomean
³ benchmark set differs from baseline; geomeans may not be comparable

                                                                                                                                                   │   main.txt   │                new.txt                │
                                                                                                                                                   │  allocs/op   │ allocs/op   vs base                   │
String-20                                                                                                                                            1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/first_label/get-20                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/first_label/has-20                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/middle_label/get-20                                                                                                         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/middle_label/has-20                                                                                                         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/last_label/get-20                                                                                                           0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/last_label/has-20                                                                                                           0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/not-found_label/get-20                                                                                                      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/not-found_label/has-20                                                                                                      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/first_label/get-20                                                                                                         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/first_label/has-20                                                                                                         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/middle_label/get-20                                                                                                        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/middle_label/has-20                                                                                                        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/last_label/get-20                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/last_label/has-20                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/not-found_label/get-20                                                                                                     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/not-found_label/has-20                                                                                                     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/first_label/get-20                                                                                                         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/first_label/has-20                                                                                                         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/middle_label/get-20                                                                                                        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/middle_label/has-20                                                                                                        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/last_label/get-20                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/last_label/has-20                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/not-found_label/get-20                                                                                                     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/not-found_label/has-20                                                                                                     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/equal-20                                                                                                                               0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/not_equal-20                                                                                                                           0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/different_sizes-20                                                                                                                     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/lots-20                                                                                                                                0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/real_long_equal-20                                                                                                                     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/real_long_different_end-20                                                                                                             0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/equal-20                                                                                                                              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/not_equal-20                                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/different_sizes-20                                                                                                                    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/lots-20                                                                                                                               0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/real_long_equal-20                                                                                                                    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/real_long_different_end-20                                                                                                            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Hash/typical_labels_under_1KB-20                                                                                                              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Hash/bigger_labels_over_1KB-20                                                                                                                0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Hash/extremely_large_label_value_10MB-20                                                                                                      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Builder-20                                                                                                                                           1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Copy-20                                                                                                                                       1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
MatchType_String-20                                                                                                                                  0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
NewMatcher/regex_matcher_with_literal-20                                                                                                             5.000 ± 0%     5.000 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/short_name_equal-20                                                                                                                   1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/short_quoted_name_not_equal-20                                                                                                        1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/short_quoted_name_with_quotes_not_equal-20                                                                                            1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/short_name_value_with_quotes_equal-20                                                                                                 1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/short_name_and_long_value_regexp-20                                                                                                   1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/short_name_and_long_value_with_quotes_equal-20                                                                                        1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/long_name_regexp-20                                                                                                                   1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/long_quoted_name_regexp-20                                                                                                            1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/long_name_and_long_value_regexp-20                                                                                                    1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/long_quoted_name_and_long_value_regexp-20                                                                                             1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Matcher_String/mixed-20                                                                                                                              1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/#00-20                                                                                                                              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/foo-20                                                                                                                              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/^foo-20                                                                                                                             0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(foo|bar)-20                                                                                                                        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/foo.*-20                                                                                                                            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.*foo-20                                                                                                                            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/^.*foo$-20                                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/^.+foo$-20                                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.?-20                                                                                                                               0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.*-20                                                                                                                               0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.+-20                                                                                                                               0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/foo.+-20                                                                                                                            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.+foo-20                                                                                                                            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/foo_.+-20                                                                                                                           0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/foo_.*-20                                                                                                                           0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.*foo.*-20                                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.+foo.+-20                                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?s:.*)-20                                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?s:.+)-20                                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?s:^.*foo$)-20                                                                                                                     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:foo)-20                                                                                                                         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(foo|bar))-20                                                                                                                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(foo1|foo2|bar))-20                                                                                                             0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/^(?i:foo|oo)|(bar)$-20                                                                                                              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(foo1|foo2|aaa|bbb|ccc|ddd|e-20                                                                                                 3.000 ± 0%     3.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/((.*)(bar|b|buzz)(.+)|foo)$-20                                                                                                      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/^$-20                                                                                                                               0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(prometheus|api_prom)_api_v1_.+-20                                                                                                  0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/10\.0\.(1|2)\.+-20                                                                                                                  0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/10\.0\.(1|2).+-20                                                                                                                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/((fo(bar))|.+foo)-20                                                                                                                0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/zQPbMkNO|NNSPdvMi|iWuuSoAl|qbvKM-20                                                                                                 0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/jyyfj00j0061|jyyfj00j0062|jyyfj9-20                                                                                                 0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(zQPbMkNO|NNSPdvMi|iWuuSoAl|-20                                                                                                 3.000 ± 0%     3.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(AAAAAAAAAAAAAAAAAAAAAAAA|BB-20                                                                                                 0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(zQPbMkNO.*|NNSPdvMi.*|iWuuS-20                                                                                                 0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(zQPbMkNO.*|NNSPdvMi.*|iWuuS#01-20                                                                                              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(?i:(.*zQPbMkNO|.*NNSPdvMi|.*iWu-20                                                                                                 0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/fo.?-20                                                                                                                             0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/foo.?-20                                                                                                                            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/f.?o-20                                                                                                                             0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.*foo.?-20                                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.?foo.+-20                                                                                                                          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/foo.?|bar-20                                                                                                                        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/ſſs-20                                                                                                                              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/.*-.*-.*-.*-.*-20                                                                                                                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/(.+)-(.+)-(.+)-(.+)-(.+)-20                                                                                                         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/((.*))(?i:f)((.*))o((.*))o((.*))-20                                                                                                 0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
FastRegexMatcher/((.*))f((.*))(?i:o)((.*))o((.*))-20                                                                                                 0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=none/ascii=true-20                                                                                             0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=none/ascii=false-20                                                                                            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=first/ascii=true-20                                                                                            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=first/ascii=false-20                                                                                           0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=last/ascii=true-20                                                                                             0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=last/ascii=false-20                                                                                            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=all/ascii=true-20                                                                                              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=10/uppercase=all/ascii=false-20                                                                                             1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=none/ascii=true-20                                                                                            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=none/ascii=false-20                                                                                           4.000 ± 0%     4.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=first/ascii=true-20                                                                                           0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=first/ascii=false-20                                                                                          4.000 ± 0%     4.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=last/ascii=true-20                                                                                            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=last/ascii=false-20                                                                                           4.000 ± 0%     4.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=all/ascii=true-20                                                                                             0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=100/uppercase=all/ascii=false-20                                                                                            5.000 ± 0%     5.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=none/ascii=true-20                                                                                           0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=none/ascii=false-20                                                                                          4.000 ± 0%     4.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=first/ascii=true-20                                                                                          1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=first/ascii=false-20                                                                                         5.000 ± 0%     5.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=last/ascii=true-20                                                                                           1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=last/ascii=false-20                                                                                          4.000 ± 0%     4.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=all/ascii=true-20                                                                                            1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=1000/uppercase=all/ascii=false-20                                                                                           5.000 ± 0%     5.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=none/ascii=true-20                                                                                           0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=none/ascii=false-20                                                                                          4.000 ± 0%     4.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=first/ascii=true-20                                                                                          1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=first/ascii=false-20                                                                                         5.000 ± 0%     5.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=last/ascii=true-20                                                                                           1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=last/ascii=false-20                                                                                          4.000 ± 0%     4.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=all/ascii=true-20                                                                                            1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
ToNormalizedLower/length=4000/uppercase=all/ascii=false-20                                                                                           5.000 ± 0%     5.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_2_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_4_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_8_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_16_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20       1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_32_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20       1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_64_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20       1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_128_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20      1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_true_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_true_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_true_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_true_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_false_prefix_matcher:_true/without_optimizeEqualOrPrefixStringMatchers()-20    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_false_prefix_matcher:_true/with_optimizeEqualOrPrefixStringMatchers()-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_false_prefix_matcher:_false/without_optimizeEqualOrPrefixStringMatchers()-20   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
OptimizeEqualOrPrefixStringMatchers/alternations:_256_case_sensitive:_false_prefix_matcher:_false/with_optimizeEqualOrPrefixStringMatchers()-20      1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
ZeroOrOneCharacterStringMatcher-20                                                                                                                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
geomean                                                                                                                                                         ²               +0.00%                ³ ²
¹ all samples are equal
² summaries must be >0 to compute geomean
³ benchmark set differs from baseline; geomeans may not be comparable

@prymitive
Copy link
Contributor Author

Regarding the hard-coded strings, I don't want this to descend into bike-shedding, but I do think as Kubernetes users we have quite a different profile from you.

That's right, and this is why ideally this list gets populated from actual usage.
That being said even if we hardcode __name__, job, instance labels it's already a win, just a smaller one then we could get if we use all possible slots from our mapping byte.

Isn't that quite an intensive operation, involving reading the whole index?

Possibly, didn't look into that much yet, but Prometheus will open recent blocks anyway so it might be not that bad, needs benchmarking. Any option that gives use list from actual usage is worth following IMHO.

@bboreham
Copy link
Member

Benchmarks: there are a number of slow-downs, including a couple at +50% and one at +1943%, which deserve attention. Maybe we can code-golf them back a bit. I'll fire up PromBench so we get an idea whether this is microbenchmark exaggeration or not.
If it's a general slow-down I think we'd have to put this change behind a build tag.

(next time you can skip the regex ones - they don't touch Labels)

@bboreham
Copy link
Member

/prombench main

@prombot
Copy link
Contributor

prombot commented Feb 12, 2025

⏱️ Welcome to Prometheus Benchmarking Tool. ⏱️

Compared versions: PR-15988 and main

After the successful deployment (check status here), the benchmarking results can be viewed at:

Available Commands:

  • To restart benchmark: /prombench restart main
  • To stop benchmark: /prombench cancel
  • To print help: /prombench help

@prymitive
Copy link
Contributor Author

read the last TSDB block on startup and build a mapping from that

Isn't that quite an intensive operation, involving reading the whole index? Another thought would be to have the WAL checkpoint process emit the table we need. But maybe it comes out the same.

Running this code below:

labels.go (folded)
package main

import (
	"cmp"
	"context"
	"flag"
	"fmt"
	"log"
	"os"
	"runtime/pprof"
	"slices"

	"github.com/prometheus/prometheus/model/labels"
	"github.com/prometheus/prometheus/tsdb"
	"github.com/prometheus/prometheus/tsdb/chunks"
)

var dbPath, blockID string

func openBlock(path, blockID string) (*tsdb.DBReadOnly, tsdb.BlockReader, error) {
	db, err := tsdb.OpenDBReadOnly(path, "", nil)
	if err != nil {
		return nil, nil, err
	}

	if blockID == "" {
		blockID, err = db.LastBlockID()
		if err != nil {
			return nil, nil, err
		}
	}

	b, err := db.Block(blockID, tsdb.DefaultPostingsDecoderFactory)
	if err != nil {
		return nil, nil, err
	}

	return db, b, nil
}

func countLabels(dbPath, blockID string) (map[string]int, error) {
	ctx := context.Background()
	names := map[string]int{}

	db, block, err := openBlock(dbPath, blockID)
	if err != nil {
		return names, err
	}

	ir, err := block.Index()
	if err != nil {
		return names, err
	}

	p, err := ir.Postings(ctx, "", "")
	if err != nil {
		return names, err
	}

	chks := []chunks.Meta{}
	builder := labels.ScratchBuilder{}
	for p.Next() {
		if err = ir.Series(p.At(), &builder, &chks); err != nil {
			return names, err
		}
		builder.Labels().Range(func(l labels.Label) {
			if _, ok := names[l.Name]; !ok {
				names[l.Name] = 0
			}
			names[l.Name]++

			if _, ok := names[l.Value]; !ok {
				names[l.Value] = 0
			}
			names[l.Value]++
		})
	}
	if err = p.Err(); err != nil {
		return names, err
	}
	if err = ir.Close(); err != nil {
		return names, err
	}
	if err = db.Close(); err != nil {
		return names, err
	}

	return names, nil
}

type labelCost struct {
	name  string
	count int
	cost  int
}

func main() {
	flag.StringVar(&dbPath, "dbpath", "", "Path to the DB")
	flag.StringVar(&blockID, "blockid", "", "ID of the block to open")
	flag.Parse()

	f, err := os.Create("profile.prof")
	if err != nil {
		log.Fatalf("Can't create profile: %s", err)
	}
	defer f.Close()

	if err := pprof.StartCPUProfile(f); err != nil {
		log.Fatalf("Can't start to profile: %s", err)
	}
	defer pprof.StopCPUProfile()

	names, err := countLabels(dbPath, blockID)
	if err != nil {
		log.Fatalf("Failed to open block: %s", err)
	}

	costs := make([]labelCost, 0, len(names))
	for name, count := range names {
		costs = append(costs, labelCost{name: name, count: count, cost: (len(name) - 1) * count})
	}

	slices.SortFunc(costs, func(a, b labelCost) int {
		return cmp.Compare(b.cost, a.cost)
	})

	for i, c := range costs {
		fmt.Println(c.name)
		if i > 256 {
			break
		}
	}
}

Takes little over 2 minutes on the ~32M time series instance I was testing it on:

real	1m47.972s
user	2m7.263s
sys	0m9.278s

with most time spent decoding TSDB data:

File: labels
Type: cpu
Time: Feb 12, 2025 at 10:56am (UTC)
Duration: 107.09s, Total samples = 132.19s (123.44%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 80.61s, 60.98% of 132.19s total
Dropped 276 nodes (cum <= 0.66s)
Showing top 10 nodes out of 79
      flat  flat%   sum%        cum   cum%
    20.85s 15.77% 15.77%     29.40s 22.24%  github.com/prometheus/prometheus/tsdb/encoding.(*Decbuf).Uvarint64
    16.85s 12.75% 28.52%     42.65s 32.26%  github.com/prometheus/prometheus/tsdb/encoding.(*Decbuf).UvarintBytes
     7.91s  5.98% 34.50%      7.92s  5.99%  github.com/dennwc/varint.Uvarint
     7.54s  5.70% 40.21%     12.37s  9.36%  runtime.mapaccess2_faststr
     6.81s  5.15% 45.36%      9.64s  7.29%  runtime.mapaccess2_fast32
     5.12s  3.87% 49.23%      8.18s  6.19%  runtime.mapassign_faststr
     4.63s  3.50% 52.73%      4.63s  3.50%  aeshashbody
     3.94s  2.98% 55.72%     55.39s 41.90%  github.com/prometheus/prometheus/tsdb/index.Symbols.Lookup
     3.74s  2.83% 58.54%     77.04s 58.28%  github.com/prometheus/prometheus/tsdb/index.(*Decoder).Series
     3.22s  2.44% 60.98%      8.82s  6.67%  runtime.mallocgc

2m extra startup time does seem excessive so it doesn't seem like an acceptable solution.
Not sure if there's any faster way to read the index from a TSDB block.

@bboreham
Copy link
Member

Just looked at the "Top 10 label names with high memory usage" section in
http://prombench.prometheus.io/15988/prometheus-pr/tsdb-status and http://prombench.prometheus.io/15988/prometheus-release/tsdb-status

We see an improvement on the hard-coded strings. The overall number is still large because the size of the value is included.

Quoting here so the info is available after prombench is canceled:

release

Name Bytes
__name__ 163682433
nodeName 162238010
instance 84573660
job 74249041

pr

Name Bytes
nodeName 162238010
__name__ 137938564
job 67725287
instance 61740521

Copy link
Contributor

@GiedriusS GiedriusS left a comment

Choose a reason for hiding this comment

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

Some downstream users might want to transfer this data over the wire so it would be cool to expose the mapped labels and version this somehow i.e. create a const MappedLabelsVersion =

@bboreham
Copy link
Member

Some downstream users might want to transfer this data over the wire

How would you do that? I can see how you would do it inside the Labels package, but then you don't need an export.

@prymitive
Copy link
Contributor Author

Benchmarks: there are a number of slow-downs, including a couple at +50% and one at +1943%, which deserve attention. Maybe we can code-golf them back a bit. I'll fire up PromBench so we get an idea whether this is microbenchmark exaggeration or not. If it's a general slow-down I think we'd have to put this change behind a build tag.

(next time you can skip the regex ones - they don't touch Labels)

I think most of the slowdown comes from the extra check for zero value in decodeSize():

https://github.com/prometheus/prometheus/pull/15988/files#diff-04b1f8c3637395325a4d3a696c6ecbb7b65cf9bc66831912b2a2b6b7bbc006bfR120-R122

What happens is that if a string is mapped to our static mapping (b == 0) then we return there and there's no extra cost as the number of checks is the same.
But for strings that are not in our mapping this check is an extra cost and so it's added to the cpu cost of decodeSize() for majority of strings and the more labels on a label set the more it adds up to.

This simple benchmark demonstrates that:

var benchmarkLabels = []Label{
	{"__name__", "prometheus_build_info"},
	{"job", "node"},
	{"instance", "123.123.1.211:9090"},
	{"path", "/api/v1/namespaces/<namespace>/deployments/<name>"},
	{"method", http.MethodGet},
	{"namespace", "system"},
	{"status", "500"},
	{"prometheus", "prometheus-core-1"},
	{"datacenter", "eu-west-1"},
	{"pod_name", "abcdef-99999-defee"},
}

func BenchmarkLabels_decodeSize(b *testing.B) {
	for _, l := range benchmarkLabels {
		ls := NewForBenchmark(l)
		b.Run(ls.String(), func(b *testing.B) {
			for i := 0; i < b.N; i++ {
				decodeSize(ls.data, 0)
			}
		})
	}
}
goos: linux
goarch: amd64
pkg: github.com/prometheus/prometheus/model/labels
cpu: 13th Gen Intel(R) Core(TM) i7-13800H
                                                                                │   main.txt    │               new.txt                │
                                                                                │    sec/op     │    sec/op      vs base               │
Labels_decodeSize/{__name__="prometheus_build_info"}-20                           0.6737n ± ∞ ¹   0.6589n ± ∞ ¹        ~ (p=0.151 n=5)
Labels_decodeSize/{job="node"}-20                                                 0.6792n ± ∞ ¹   0.6657n ± ∞ ¹        ~ (p=0.151 n=5)
Labels_decodeSize/{instance="123.123.1.211:9090"}-20                              0.6528n ± ∞ ¹   0.6617n ± ∞ ¹        ~ (p=0.238 n=5)
Labels_decodeSize/{path="/api/v1/namespaces/<namespace>/deployments/<name>"}-20   0.6529n ± ∞ ¹   0.8740n ± ∞ ¹  +33.86% (p=0.008 n=5)
Labels_decodeSize/{method="GET"}-20                                               0.6528n ± ∞ ¹   0.8650n ± ∞ ¹  +32.51% (p=0.008 n=5)
Labels_decodeSize/{namespace="system"}-20                                         0.6518n ± ∞ ¹   0.8633n ± ∞ ¹  +32.45% (p=0.008 n=5)
Labels_decodeSize/{status="500"}-20                                               0.6651n ± ∞ ¹   0.8684n ± ∞ ¹  +30.57% (p=0.008 n=5)
Labels_decodeSize/{prometheus="prometheus-core-1"}-20                             0.6606n ± ∞ ¹   0.8704n ± ∞ ¹  +31.76% (p=0.008 n=5)
Labels_decodeSize/{datacenter="eu-west-1"}-20                                     0.6624n ± ∞ ¹   0.8746n ± ∞ ¹  +32.04% (p=0.008 n=5)
Labels_decodeSize/{pod_name="abcdef-99999-defee"}-20                              0.6588n ± ∞ ¹   0.8698n ± ∞ ¹  +32.03% (p=0.008 n=5)
geomean                                                                           0.6609n         0.8011n        +21.21%
¹ need >= 6 samples for confidence interval at level 0.95

@prymitive
Copy link
Contributor Author

Updated benchmarks (just the ones that matter):

goos: linux
goarch: amd64
pkg: github.com/prometheus/prometheus/model/labels
cpu: 13th Gen Intel(R) Core(TM) i7-13800H
                                                 │   main.txt    │                new.txt                │
                                                 │    sec/op     │    sec/op      vs base                │
String-20                                           1.372µ ± ∞ ¹    1.385µ ± ∞ ¹         ~ (p=0.421 n=5)
Labels_Get/with_5_labels/first_label/get-20         7.918n ± ∞ ¹    8.394n ± ∞ ¹    +6.01% (p=0.008 n=5)
Labels_Get/with_5_labels/first_label/has-20         5.712n ± ∞ ¹    6.582n ± ∞ ¹   +15.23% (p=0.008 n=5)
Labels_Get/with_5_labels/middle_label/get-20        11.90n ± ∞ ¹    15.62n ± ∞ ¹   +31.26% (p=0.008 n=5)
Labels_Get/with_5_labels/middle_label/has-20        8.709n ± ∞ ¹   11.420n ± ∞ ¹   +31.13% (p=0.008 n=5)
Labels_Get/with_5_labels/last_label/get-20          15.86n ± ∞ ¹    21.71n ± ∞ ¹   +36.89% (p=0.008 n=5)
Labels_Get/with_5_labels/last_label/has-20          13.30n ± ∞ ¹    20.49n ± ∞ ¹   +54.06% (p=0.008 n=5)
Labels_Get/with_5_labels/not-found_label/get-20     6.621n ± ∞ ¹    8.204n ± ∞ ¹   +23.91% (p=0.008 n=5)
Labels_Get/with_5_labels/not-found_label/has-20     6.592n ± ∞ ¹    8.413n ± ∞ ¹   +27.62% (p=0.008 n=5)
Labels_Get/with_10_labels/first_label/get-20        7.987n ± ∞ ¹    8.297n ± ∞ ¹    +3.88% (p=0.008 n=5)
Labels_Get/with_10_labels/first_label/has-20        5.770n ± ∞ ¹    6.565n ± ∞ ¹   +13.78% (p=0.008 n=5)
Labels_Get/with_10_labels/middle_label/get-20       18.02n ± ∞ ¹    24.68n ± ∞ ¹   +36.96% (p=0.008 n=5)
Labels_Get/with_10_labels/middle_label/has-20       15.60n ± ∞ ¹    23.09n ± ∞ ¹   +48.01% (p=0.008 n=5)
Labels_Get/with_10_labels/last_label/get-20         29.92n ± ∞ ¹    36.37n ± ∞ ¹   +21.56% (p=0.008 n=5)
Labels_Get/with_10_labels/last_label/has-20         27.52n ± ∞ ¹    34.81n ± ∞ ¹   +26.49% (p=0.008 n=5)
Labels_Get/with_10_labels/not-found_label/get-20    6.689n ± ∞ ¹    7.919n ± ∞ ¹         ~ (p=0.056 n=5)
Labels_Get/with_10_labels/not-found_label/has-20    6.965n ± ∞ ¹    8.368n ± ∞ ¹   +20.14% (p=0.008 n=5)
Labels_Get/with_30_labels/first_label/get-20        7.831n ± ∞ ¹    8.348n ± ∞ ¹    +6.60% (p=0.008 n=5)
Labels_Get/with_30_labels/first_label/has-20        5.981n ± ∞ ¹    6.566n ± ∞ ¹    +9.78% (p=0.008 n=5)
Labels_Get/with_30_labels/middle_label/get-20       54.93n ± ∞ ¹    70.48n ± ∞ ¹   +28.31% (p=0.008 n=5)
Labels_Get/with_30_labels/middle_label/has-20       53.76n ± ∞ ¹    65.27n ± ∞ ¹   +21.41% (p=0.008 n=5)
Labels_Get/with_30_labels/last_label/get-20         184.9n ± ∞ ¹    118.4n ± ∞ ¹   -35.97% (p=0.008 n=5)
Labels_Get/with_30_labels/last_label/has-20         180.9n ± ∞ ¹    114.5n ± ∞ ¹   -36.71% (p=0.008 n=5)
Labels_Get/with_30_labels/not-found_label/get-20    6.952n ± ∞ ¹    7.989n ± ∞ ¹   +14.92% (p=0.008 n=5)
Labels_Get/with_30_labels/not-found_label/has-20    6.907n ± ∞ ¹    8.398n ± ∞ ¹   +21.59% (p=0.008 n=5)
Labels_Equals/equal-20                              4.122n ± ∞ ¹    4.119n ± ∞ ¹         ~ (p=0.690 n=5)
Labels_Equals/not_equal-20                         0.8336n ± ∞ ¹   0.4450n ± ∞ ¹   -46.62% (p=0.008 n=5)
Labels_Equals/different_sizes-20                   0.8669n ± ∞ ¹   0.4460n ± ∞ ¹   -48.55% (p=0.008 n=5)
Labels_Equals/lots-20                               4.003n ± ∞ ¹    3.960n ± ∞ ¹         ~ (p=0.310 n=5)
Labels_Equals/real_long_equal-20                   10.060n ± ∞ ¹    9.249n ± ∞ ¹    -8.06% (p=0.008 n=5)
Labels_Equals/real_long_different_end-20            8.536n ± ∞ ¹    7.810n ± ∞ ¹    -8.51% (p=0.008 n=5)
Labels_Compare/equal-20                             8.286n ± ∞ ¹    8.429n ± ∞ ¹         ~ (p=1.000 n=5)
Labels_Compare/not_equal-20                         31.19n ± ∞ ¹    35.46n ± ∞ ¹   +13.69% (p=0.008 n=5)
Labels_Compare/different_sizes-20                   6.631n ± ∞ ¹    6.158n ± ∞ ¹    -7.13% (p=0.008 n=5)
Labels_Compare/lots-20                              46.54n ± ∞ ¹    49.72n ± ∞ ¹    +6.83% (p=0.008 n=5)
Labels_Compare/real_long_equal-20                   29.73n ± ∞ ¹    46.80n ± ∞ ¹   +57.42% (p=0.008 n=5)
Labels_Compare/real_long_different_end-20           49.35n ± ∞ ¹    61.95n ± ∞ ¹   +25.53% (p=0.008 n=5)
Labels_Hash/typical_labels_under_1KB-20             98.98n ± ∞ ¹    99.02n ± ∞ ¹         ~ (p=0.794 n=5)
Labels_Hash/bigger_labels_over_1KB-20               121.1n ± ∞ ¹    122.4n ± ∞ ¹         ~ (p=0.460 n=5)
Labels_Hash/extremely_large_label_value_10MB-20     1.202m ± ∞ ¹    1.166m ± ∞ ¹         ~ (p=0.222 n=5)
Builder-20                                          423.9n ± ∞ ¹   4235.0n ± ∞ ¹  +899.06% (p=0.008 n=5)
Labels_Copy-20                                     105.10n ± ∞ ¹    97.75n ± ∞ ¹    -6.99% (p=0.008 n=5)
geomean                                             22.39n          25.34n         +13.17%
¹ need >= 6 samples for confidence interval at level 0.95

@prombot
Copy link
Contributor

prombot commented Feb 15, 2025

Benchmark tests are running for 3 days! If this is intended ignore this message otherwise you can cancel it by commenting: /prombench cancel

@prymitive
Copy link
Contributor Author

I've added another commit that populates the mapping from last tsdb block, this should show better results in benchmarks but I suspect that the benchmark suite run here always starts with an empty instance, so won't really show any improvement.

@GiedriusS
Copy link
Contributor

Some downstream users might want to transfer this data over the wire

How would you do that? I can see how you would do it inside the Labels package, but then you don't need an export.

Through the Bytes() method https://github.com/prometheus/prometheus/blob/main/model/labels/labels_stringlabels.go#L62. Without exporting this new mapping, it's unclear what the bytes mean.

@bboreham
Copy link
Member

Bytes is opaque; it is not supposed to be a serialization/deserialization mechanism.

I’ve done a whole symbol-table implementation, under -tags dedupelabels. I think it’s better to improve that (or write a 4th implementation) rather than slowly turn stringlabels into that.

@prymitive
Copy link
Contributor Author

I’ve done a whole symbol-table implementation, under -tags dedupelabels. I think it’s better to improve that (or write a 4th implementation) rather than slowly turn stringlabels into that.

Is there a line where this PR is acceptable or stops being acceptable? Does removing the last commit make it more acceptable?

@bboreham
Copy link
Member

I was responding to @GiedriusS, not on the changes in this PR.

Building a list from the last TSDB block is acceptable, though I might still do it as an add-on PR.

However, we can use PromBench to check the impact. I think I can restart the process so it will see a block.

@bboreham
Copy link
Member

However the (micro) benchmarks are still worrying.

stringlabels stores all time series labels as a single string using this format:

<length><name><length><value>[<length><name><length><value> ...]

So a label set for my_metric{job=foo, instance="bar", env="prod", blank=""} would be encoded as:

[8]__name__[9]my_metric[3]job[3]foo[8]instance[3]bar[3]env[4]prod[5]blank[0]

This is a huge improvement over 'classic' labels implementation that stores all label names & values as seperate strings.
There is some room for improvement though since some string are present more often than others.
For example __name__ will be present for all label sets of every time series we store in HEAD, eating 1+8=9 bytes.
Since __name__ is well known string we can try to use a single byte to store it in our encoded string, rather than repeat it in full each time.
To be able to store strings that are short cut into a single byte we need to somehow signal that to the reader of the encoded string, for that
we use the fact that zero length strings are rare and generaly not stored on time series. If we have an encoded string with zero length
then this will now signal that it represents a mapped value - to learn the true value of this string we need to read the next byte
which gives us index in a static mapping. That mapping must include empty string, so that we can still encode empty strings using this scheme.

Example of our mapping (minimal version):

0: ""
1: "__name__"
2: "instance"
3: "job"

With that mapping our example label set would be encoded as:

[0]1[9]mymetric[0]3[3]foo[0]2[3]bar[3]env[4]prod[5]blank[0]0

The tricky bit is how to populate this mapping with useful strings that will result in measurable memory savings.
This is further complicated by the fact that the mapping must remain static and cannot be modified during Prometheus lifetime.
We can use all the 255 slots we have inside our mapping byte with well known generic strings and that will
provide some measurable savings for all Prometheus users, and is essentially a slightly more compact stringlabels variant.
We could also allow users to pass in a list of well know strings via flags, which will allow Prometheus operators
to reduce memory usage for any labels if they know those are popular.
Third option is to discover most popular strings from TSDB or WAL on startup, but that's more complicated and
we might pick a list that would be the best set of mapped strings on startup, but after some time is no longer
the best set.

Benchmark results:

goos: linux
goarch: amd64
pkg: github.com/prometheus/prometheus/model/labels
cpu: 13th Gen Intel(R) Core(TM) i7-13800H
                                                 │   main.txt   │                new1.txt                │
                                                 │    sec/op    │    sec/op      vs base                 │
String-20                                           863.8n ± 4%    873.0n ±  4%         ~ (p=0.353 n=10)
Labels_Get/with_5_labels/first_label/get-20         4.763n ± 1%    5.035n ±  0%    +5.72% (p=0.000 n=10)
Labels_Get/with_5_labels/first_label/has-20         3.439n ± 0%    3.967n ±  0%   +15.37% (p=0.000 n=10)
Labels_Get/with_5_labels/middle_label/get-20        7.077n ± 1%    9.588n ±  1%   +35.47% (p=0.000 n=10)
Labels_Get/with_5_labels/middle_label/has-20        5.166n ± 0%    6.990n ±  1%   +35.30% (p=0.000 n=10)
Labels_Get/with_5_labels/last_label/get-20          9.181n ± 1%   12.970n ±  1%   +41.26% (p=0.000 n=10)
Labels_Get/with_5_labels/last_label/has-20          8.101n ± 1%   11.640n ±  1%   +43.69% (p=0.000 n=10)
Labels_Get/with_5_labels/not-found_label/get-20     3.974n ± 0%    4.768n ±  0%   +19.98% (p=0.000 n=10)
Labels_Get/with_5_labels/not-found_label/has-20     3.974n ± 0%    5.033n ±  0%   +26.65% (p=0.000 n=10)
Labels_Get/with_10_labels/first_label/get-20        4.761n ± 0%    5.042n ±  0%    +5.90% (p=0.000 n=10)
Labels_Get/with_10_labels/first_label/has-20        3.442n ± 0%    3.972n ±  0%   +15.40% (p=0.000 n=10)
Labels_Get/with_10_labels/middle_label/get-20       10.62n ± 1%    14.85n ±  1%   +39.83% (p=0.000 n=10)
Labels_Get/with_10_labels/middle_label/has-20       9.360n ± 1%   13.375n ±  0%   +42.90% (p=0.000 n=10)
Labels_Get/with_10_labels/last_label/get-20         18.19n ± 1%    22.00n ±  0%   +20.97% (p=0.000 n=10)
Labels_Get/with_10_labels/last_label/has-20         16.51n ± 0%    20.50n ±  1%   +24.14% (p=0.000 n=10)
Labels_Get/with_10_labels/not-found_label/get-20    3.985n ± 0%    4.768n ±  0%   +19.62% (p=0.000 n=10)
Labels_Get/with_10_labels/not-found_label/has-20    3.973n ± 0%    5.045n ±  0%   +26.97% (p=0.000 n=10)
Labels_Get/with_30_labels/first_label/get-20        4.773n ± 0%    5.050n ±  1%    +5.80% (p=0.000 n=10)
Labels_Get/with_30_labels/first_label/has-20        3.443n ± 1%    3.976n ±  2%   +15.50% (p=0.000 n=10)
Labels_Get/with_30_labels/middle_label/get-20       31.93n ± 0%    43.50n ±  1%   +36.21% (p=0.000 n=10)
Labels_Get/with_30_labels/middle_label/has-20       30.53n ± 0%    41.75n ±  1%   +36.75% (p=0.000 n=10)
Labels_Get/with_30_labels/last_label/get-20        106.55n ± 0%    71.17n ±  0%   -33.21% (p=0.000 n=10)
Labels_Get/with_30_labels/last_label/has-20        104.70n ± 0%    69.21n ±  1%   -33.90% (p=0.000 n=10)
Labels_Get/with_30_labels/not-found_label/get-20    3.976n ± 1%    4.772n ±  0%   +20.03% (p=0.000 n=10)
Labels_Get/with_30_labels/not-found_label/has-20    3.974n ± 0%    5.032n ±  0%   +26.64% (p=0.000 n=10)
Labels_Equals/equal-20                              2.382n ± 0%    2.446n ±  0%    +2.67% (p=0.000 n=10)
Labels_Equals/not_equal-20                         0.2741n ± 2%   0.2662n ±  2%    -2.88% (p=0.001 n=10)
Labels_Equals/different_sizes-20                   0.2762n ± 3%   0.2652n ±  0%    -3.95% (p=0.000 n=10)
Labels_Equals/lots-20                               2.381n ± 0%    2.386n ±  1%    +0.23% (p=0.011 n=10)
Labels_Equals/real_long_equal-20                    6.087n ± 1%    5.558n ±  1%    -8.70% (p=0.000 n=10)
Labels_Equals/real_long_different_end-20            5.030n ± 0%    4.699n ±  0%    -6.57% (p=0.000 n=10)
Labels_Compare/equal-20                             4.814n ± 1%    4.777n ±  0%    -0.77% (p=0.000 n=10)
Labels_Compare/not_equal-20                         17.55n ± 8%    20.92n ±  1%   +19.24% (p=0.000 n=10)
Labels_Compare/different_sizes-20                   3.711n ± 1%    3.707n ±  0%         ~ (p=0.224 n=10)
Labels_Compare/lots-20                              27.09n ± 3%    28.73n ±  2%    +6.05% (p=0.000 n=10)
Labels_Compare/real_long_equal-20                   27.91n ± 3%    15.67n ±  1%   -43.86% (p=0.000 n=10)
Labels_Compare/real_long_different_end-20           33.92n ± 1%    35.35n ±  1%    +4.22% (p=0.000 n=10)
Labels_Hash/typical_labels_under_1KB-20             59.63n ± 0%    59.67n ±  0%         ~ (p=0.897 n=10)
Labels_Hash/bigger_labels_over_1KB-20               73.42n ± 1%    73.81n ±  1%         ~ (p=0.342 n=10)
Labels_Hash/extremely_large_label_value_10MB-20     720.3µ ± 2%    715.2µ ±  3%         ~ (p=0.971 n=10)
Builder-20                                          371.6n ± 4%   1191.0n ±  3%  +220.46% (p=0.000 n=10)
Labels_Copy-20                                      85.52n ± 4%    53.90n ± 48%   -36.97% (p=0.000 n=10)
geomean                                             13.26n         14.68n         +10.71%

                                                 │   main.txt   │               new1.txt               │
                                                 │     B/op     │    B/op     vs base                  │
String-20                                          240.0 ± 0%     240.0 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/first_label/get-20        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/first_label/has-20        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/middle_label/get-20       0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/middle_label/has-20       0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/last_label/get-20         0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/last_label/has-20         0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/not-found_label/get-20    0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/not-found_label/has-20    0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/first_label/get-20       0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/first_label/has-20       0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/middle_label/get-20      0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/middle_label/has-20      0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/last_label/get-20        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/last_label/has-20        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/not-found_label/get-20   0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/not-found_label/has-20   0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/first_label/get-20       0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/first_label/has-20       0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/middle_label/get-20      0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/middle_label/has-20      0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/last_label/get-20        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/last_label/has-20        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/not-found_label/get-20   0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/not-found_label/has-20   0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Equals/equal-20                             0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Equals/not_equal-20                         0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Equals/different_sizes-20                   0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Equals/lots-20                              0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Equals/real_long_equal-20                   0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Equals/real_long_different_end-20           0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Compare/equal-20                            0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Compare/not_equal-20                        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Compare/different_sizes-20                  0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Compare/lots-20                             0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Compare/real_long_equal-20                  0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Compare/real_long_different_end-20          0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Hash/typical_labels_under_1KB-20            0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Hash/bigger_labels_over_1KB-20              0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Labels_Hash/extremely_large_label_value_10MB-20    0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
Builder-20                                         224.0 ± 0%     192.0 ± 0%  -14.29% (p=0.000 n=10)
Labels_Copy-20                                     224.0 ± 0%     192.0 ± 0%  -14.29% (p=0.000 n=10)
geomean                                                       ²                -0.73%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                                 │   main.txt   │              new1.txt               │
                                                 │  allocs/op   │ allocs/op   vs base                 │
String-20                                          1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/first_label/get-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/first_label/has-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/middle_label/get-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/middle_label/has-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/last_label/get-20         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/last_label/has-20         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/not-found_label/get-20    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_5_labels/not-found_label/has-20    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/first_label/get-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/first_label/has-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/middle_label/get-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/middle_label/has-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/last_label/get-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/last_label/has-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/not-found_label/get-20   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_10_labels/not-found_label/has-20   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/first_label/get-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/first_label/has-20       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/middle_label/get-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/middle_label/has-20      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/last_label/get-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/last_label/has-20        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/not-found_label/get-20   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Get/with_30_labels/not-found_label/has-20   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/equal-20                             0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/not_equal-20                         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/different_sizes-20                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/lots-20                              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/real_long_equal-20                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Equals/real_long_different_end-20           0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/equal-20                            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/not_equal-20                        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/different_sizes-20                  0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/lots-20                             0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/real_long_equal-20                  0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Compare/real_long_different_end-20          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Hash/typical_labels_under_1KB-20            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Hash/bigger_labels_over_1KB-20              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Hash/extremely_large_label_value_10MB-20    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
Builder-20                                         1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
Labels_Copy-20                                     1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=10) ¹
geomean                                                       ²               +0.00%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

Signed-off-by: Lukasz Mierzwa <l.mierzwa@gmail.com>
Signed-off-by: Lukasz Mierzwa <l.mierzwa@gmail.com>
Signed-off-by: Lukasz Mierzwa <l.mierzwa@gmail.com>
Signed-off-by: Lukasz Mierzwa <l.mierzwa@gmail.com>
This will populate the static mapping of strings to store as a single byte on startup.
We use the last TSDB block as the source of data, iterate the index for each label and count how many time series given label pair is referencing.

Signed-off-by: Lukasz Mierzwa <l.mierzwa@gmail.com>
@prymitive
Copy link
Contributor Author

prymitive commented Feb 20, 2025

image

There is definitely an increase in CPU usage as per screenshot from the previous benchmark run (I've changed the rate to be 2h so it's easier to read).

I can put this behind a dedicated build tag but since this is modifying stringlabels tag my worry is that we end up with a tag on top of a tag, which will be hard to follow. Or alternatively create a duplicate of stringlabels implementation with just a small part of the code modified (which is also not ideal).

I'm not sure what the long term plans are but maybe now is a good time to declare stringlabels code as the default labels implementation and get rid of the old slice based code? Or at least make the stringlabels default code without any build tag restrictions and put slice based code behind some build tag (like legacylabels) ?

@bboreham
Copy link
Member

The reason to leave tags as-is was to avoid inconvenience for downstream users such as Thanos.
Probably best to open a separate issue to propose changing the default.

This makes building labels faster by having a fast lookup for string->index path via a map.
Since we now need to populate both the slice that maps index->string and a map that gives us string->index.
For that we add labels.MapLabels() function which handles updating the static mapping.

Signed-off-by: Lukasz Mierzwa <l.mierzwa@gmail.com>
@bboreham
Copy link
Member

I took some time to look at the performance of this PR over the weekend, and tried to speed it up.

However I think this kind of thing is a blocker:

Builder-20 423.9n ± ∞ ¹ 4235.0n ± ∞ ¹ +899.06% (p=0.008 n=5)

It doesn't show up most of the time when scraping, as the initial construction of labels is cached. But when reading the WAL or creating a large set of new series, this overhead will be painful.
Also when receiving data via remote-write or OTLP, every series is constructed fresh - those users will pay the overhead continuously.

So, I don't think we could have this on by default.

Do you find that this version is better than -tags dedupelabels ? On what dimension(s) ?
Maybe the idea works better as a modification to that, rather than a modification to stringlabels ?

@prymitive
Copy link
Contributor Author

I took some time to look at the performance of this PR over the weekend, and tried to speed it up.

However I think this kind of thing is a blocker:

Builder-20 423.9n ± ∞ ¹ 4235.0n ± ∞ ¹ +899.06% (p=0.008 n=5)

It doesn't show up most of the time when scraping, as the initial construction of labels is cached. But when reading the WAL or creating a large set of new series, this overhead will be painful. Also when receiving data via remote-write or OTLP, every series is constructed fresh - those users will pay the overhead continuously.

So, I don't think we could have this on by default.

I did push a change that helps a bit with that, just didn't re-run all benchmarks yet.
Just running builder ones give me:

goos: linux
goarch: amd64
pkg: github.com/prometheus/prometheus/model/labels
cpu: 13th Gen Intel(R) Core(TM) i7-13800H
           │   main.txt   │               new.txt               │
           │    sec/op    │    sec/op     vs base               │
Builder-20   411.0n ± ∞ ¹   701.2n ± ∞ ¹  +70.61% (p=0.008 n=5)
¹ need >= 6 samples for confidence interval at level 0.95

Do you find that this version is better than -tags dedupelabels ? On what dimension(s) ? Maybe the idea works better as a modification to that, rather than a modification to stringlabels ?

I did leave a comment a while ago about dedupelabels and all of it still stands - #12304 (comment).
This PR gives me a consistent memory reduction of ~70GiB -> 61GiB, dedupelabels is a lot more unpredictable.
That being said we do have a fair number of "common" labels that are a great target for optimisation implemented here, not everyone will, but that is also true for dedupelabels - it mostly benefits from a large number of repeated labels.

We need to call mapCommonLabelSymbols() once TSDB opens all blocks, but before we start to reply the WAL and populate the HEAD.
There doesn't seem to be a way to do this right now, so add a hook we can use for it.

Signed-off-by: Lukasz Mierzwa <l.mierzwa@gmail.com>
@bboreham
Copy link
Member

Hello from the bug-scrub!

I'm personally still unable to accept a benchmark result going 70% slower. In our cloud bills CPU is about 4x the price of RAM.

Discussed at the bug-scrub: we could add this variant under another build tag, letting people in similar situations to yourself get the benefit.

@prymitive
Copy link
Contributor Author

Hello from the bug-scrub!

I'm personally still unable to accept a benchmark result going 70% slower. In our cloud bills CPU is about 4x the price of RAM.

Discussed at the bug-scrub: we could add this variant under another build tag, letting people in similar situations to yourself get the benefit.

Happy to put it behind a build tag, raised #16064 to make stringlabels the default and if that gets merged I can add it as a new tag. Don't really want to add a new tag that's behind another tag.

@prymitive
Copy link
Contributor Author

Thanks for merging #16436 @bboreham
I'll refactor this PR to make all the changes behind a new build tag.
I'll try to deploy both dedupelabels and this change here to some test environments in the next few weeks, so I can compare both and to gather some debug info for deduplabels

@bboreham
Copy link
Member

bboreham commented May 2, 2025

Still thinking whether doesn't work better as a mod to dedupelabels. Basically you have one symbol-table which you never change, plus a fall-back to store strings that aren't in the table.

@prymitive
Copy link
Contributor Author

Raised #16588 with a version that's behind a new build tag

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

Successfully merging this pull request may close these issues.

5 participants