Improve Labels.Compare performance w/stringlabels

I was bored on a train and I spent some amount of time trying to scratch
some nanoseconds off the Labels.Compare when running with stringlabels.

I would be ashamed to admit the real amount of time I spent on it.

The worst thing is, I can't really explain why this is performing so
much better, and someone should re-run the benchmarks on their machine
to confirm that it's not something related to general relativity because
the train is moving. I also added some extra real-life benchmark cases
with longer labelsets (these aren't the longest we have in production,
but kubernetes labelsets are fairly common in Prometheus so I thought it
would be nice to have them).

My benchmarks show this diff:

goos: darwin
goarch: arm64
pkg: github.com/prometheus/prometheus/model/labels
                                       │     old     │                 new                 │
                                       │   sec/op    │   sec/op     vs base                │
Labels_Compare/equal                     5.898n ± 0%   5.875n ± 1%   -0.40% (p=0.037 n=10)
Labels_Compare/not_equal                 11.78n ± 2%   11.01n ± 1%   -6.54% (p=0.000 n=10)
Labels_Compare/different_sizes           4.959n ± 1%   4.906n ± 2%   -1.05% (p=0.050 n=10)
Labels_Compare/lots                      21.32n ± 0%   17.54n ± 5%  -17.75% (p=0.000 n=10)
Labels_Compare/real_long_equal           15.06n ± 1%   14.92n ± 0%   -0.93% (p=0.000 n=10)
Labels_Compare/real_long_different_end   25.20n ± 0%   24.43n ± 0%   -3.04% (p=0.000 n=10)
geomean                                  11.86n        11.25n        -5.16%

Signed-off-by: Oleg Zaytsev <mail@olegzaytsev.com>
This commit is contained in:
Oleg Zaytsev 2024-03-17 16:56:12 +01:00
parent a0e93e403e
commit 9699598952
No known key found for this signature in database
GPG key ID: 7E9FE9FD48F512EF
2 changed files with 12 additions and 6 deletions

View file

@ -363,12 +363,8 @@ func Compare(a, b Labels) int {
// Now we know that there is some difference before the end of a and b.
// Go back through the fields and find which field that difference is in.
firstCharDifferent := i
for i = 0; ; {
size, nextI := decodeSize(a.data, i)
if nextI+size > firstCharDifferent {
break
}
firstCharDifferent, i := i, 0
for size, nextI := decodeSize(a.data, i); nextI+size <= firstCharDifferent; size, nextI = decodeSize(a.data, i) {
i = nextI + size
}
// Difference is inside this entry.

View file

@ -532,6 +532,16 @@ var comparisonBenchmarkScenarios = []struct {
FromStrings("aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo", "ppp", "qqq", "rrz"),
FromStrings("aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo", "ppp", "qqq", "rrr"),
},
{
"real long equal",
FromStrings("__name__", "kube_pod_container_status_last_terminated_exitcode", "cluster", "prod-af-north-0", " container", "prometheus", "instance", "kube-state-metrics-0:kube-state-metrics:ksm", "job", "kube-state-metrics/kube-state-metrics", " namespace", "observability-prometheus", "pod", "observability-prometheus-0", "uid", "d3ec90b2-4975-4607-b45d-b9ad64bb417e"),
FromStrings("__name__", "kube_pod_container_status_last_terminated_exitcode", "cluster", "prod-af-north-0", " container", "prometheus", "instance", "kube-state-metrics-0:kube-state-metrics:ksm", "job", "kube-state-metrics/kube-state-metrics", " namespace", "observability-prometheus", "pod", "observability-prometheus-0", "uid", "d3ec90b2-4975-4607-b45d-b9ad64bb417e"),
},
{
"real long different end",
FromStrings("__name__", "kube_pod_container_status_last_terminated_exitcode", "cluster", "prod-af-north-0", " container", "prometheus", "instance", "kube-state-metrics-0:kube-state-metrics:ksm", "job", "kube-state-metrics/kube-state-metrics", " namespace", "observability-prometheus", "pod", "observability-prometheus-0", "uid", "d3ec90b2-4975-4607-b45d-b9ad64bb417e"),
FromStrings("__name__", "kube_pod_container_status_last_terminated_exitcode", "cluster", "prod-af-north-0", " container", "prometheus", "instance", "kube-state-metrics-0:kube-state-metrics:ksm", "job", "kube-state-metrics/kube-state-metrics", " namespace", "observability-prometheus", "pod", "observability-prometheus-0", "uid", "deadbeef-0000-1111-2222-b9ad64bb417e"),
},
}
func BenchmarkLabels_Equals(b *testing.B) {