Skip to content

tsdb: faster postings sort with generic slices.Sort#11054

Merged
codesome merged 1 commit intoprometheus:mainfrom
bboreham:sort-slice-exp
Sep 30, 2022
Merged

tsdb: faster postings sort with generic slices.Sort#11054
codesome merged 1 commit intoprometheus:mainfrom
bboreham:sort-slice-exp

Conversation

@bboreham
Copy link
Member

@bboreham bboreham commented Jul 23, 2022

Update go.mod to mandate Go 1.18 semantics so we can use generics. This will impact anyone using Prometheus as a library who has not already updated to Go 1.18. Edit: this was done by #11279.

Use new experimental package golang.org/x/exp/slices.

For either of the above reasons you might not want to accept the change, but I thought the difference was striking.

name                                                old time/op    new time/op    delta
MemPostings_ensureOrder/few_values_per_label-8         591ms ± 2%     262ms ±31%  -55.74%  (p=0.008 n=5+5)
MemPostings_ensureOrder/few_refs_per_label_value-8    16.1ms ± 0%    11.9ms ± 0%  -25.93%  (p=0.016 n=4+5)
MemPostings_ensureOrder/many_values_per_label-8        543ms ± 7%      80ms ± 3%  -85.26%  (p=0.008 n=5+5)

name                                                old alloc/op   new alloc/op   delta
MemPostings_ensureOrder/few_values_per_label-8         201kB ± 0%      80kB ± 1%  -60.23%  (p=0.016 n=5+4)
MemPostings_ensureOrder/few_refs_per_label_value-8    6.51kB ± 5%    4.37kB ± 1%  -32.87%  (p=0.008 n=5+5)
MemPostings_ensureOrder/many_values_per_label-8        200kB ± 1%      31kB ± 6%  -84.60%  (p=0.008 n=5+5)

name                                                old allocs/op  new allocs/op  delta
MemPostings_ensureOrder/few_values_per_label-8          53.0 ± 8%      23.0 ±22%  -56.60%  (p=0.008 n=5+5)
MemPostings_ensureOrder/few_refs_per_label_value-8      19.0 ± 5%      10.0 ± 0%  -47.37%  (p=0.008 n=5+5)
MemPostings_ensureOrder/many_values_per_label-8         47.2 ±17%      14.8 ±15%  -68.64%  (p=0.008 n=5+5)

Some of the speedup comes from comparing SeriesRef (which is an int64) directly rather than through an interface .Less() call; some comes from exp/slices using "pattern-defeating quicksort(pdqsort)" which is much better on already-sorted data.

Also we don't need the funky trick from #10500.

Across Prometheus there are many other calls to sort; I think all the sort.Strings and sort.Ints will benefit from the same change, but I don't often see them show up in profiles. Anyway I thought I'd post this one as a start.

@bboreham bboreham requested a review from codesome as a code owner July 23, 2022 14:02
@roidelapluie
Copy link
Member

/prombench main

@prombot
Copy link
Contributor

prombot commented Jul 28, 2022

⏱️ Welcome to Prometheus Benchmarking Tool. ⏱️

Compared versions: PR-11054 and main

After successful deployment, the benchmarking metrics can be viewed at:

Other Commands:
To stop benchmark: /prombench cancel
To restart benchmark: /prombench restart main

@prombot
Copy link
Contributor

prombot commented Jul 31, 2022

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

@roidelapluie
Copy link
Member

/prombench cancel

@prombot
Copy link
Contributor

prombot commented Jul 31, 2022

Benchmark cancel is in progress.

@bboreham
Copy link
Member Author

bboreham commented Sep 8, 2022

CI is failing on Windows with an error I can't believe is connected to this change:

    testing.go:1097: TempDir RemoveAll cleanup: remove C:\Users\RUNNER~1\AppData\Local\Temp\TestReadCheckpointcompress=false1728930424\001\wal\00000030: The process cannot access the file because it is being used by another process.
--- FAIL: TestReadCheckpoint (1.97s)
    --- FAIL: TestReadCheckpoint/compress=false (1.82s)

This appears to the same as described in #10368.

@codesome
Copy link
Member

Hmmm, lint is failing for unrelated change as well. Looks like a simple fix of getting rid of a type. Would you be able to do it in this PR? Thanks!

Use new experimental package `golang.org/x/exp/slices`.

Some of the speedup comes from comparing SeriesRef (which is an int64)
directly rather than through an interface `.Less()` call; some comes
from exp/slices using "pattern-defeating quicksort(pdqsort)".

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
@bboreham
Copy link
Member Author

I fixed the lint error.

@codesome codesome merged commit 7f2374b into prometheus:main Sep 30, 2022
charleskorn added a commit to grafana/mimir that referenced this pull request Dec 12, 2022
#3639 (comment),
prometheus/prometheus#11054, and
prometheus/prometheus#11318 all show
substantial performance improvements when using slices.Sort over
sort.Strings.

I've also added a linting rule to catch usage of sort.Strings and
sort.Ints in the future. (We don't currently use sort.Ints anywhere.)

We could also replace sort.Float64s with slices.Sort, however, this
requires more careful consideration as the documentation for
slices.Sort warns that it may not handle NaN values correctly.
charleskorn added a commit to grafana/mimir that referenced this pull request Dec 15, 2022
#3639 (comment),
prometheus/prometheus#11054, and
prometheus/prometheus#11318 all show
substantial performance improvements when using slices.Sort over
sort.Strings.

I've also added a linting rule to catch usage of sort.Strings and
sort.Ints in the future. (We don't currently use sort.Ints anywhere.)

We could also replace sort.Float64s with slices.Sort, however, this
requires more careful consideration as the documentation for
slices.Sort warns that it may not handle NaN values correctly.
pracucci pushed a commit to grafana/mimir that referenced this pull request Dec 15, 2022
* Use slices.Sort instead of sort.Strings or sort.Ints.

#3639 (comment),
prometheus/prometheus#11054, and
prometheus/prometheus#11318 all show
substantial performance improvements when using slices.Sort over
sort.Strings.

I've also added a linting rule to catch usage of sort.Strings and
sort.Ints in the future. (We don't currently use sort.Ints anywhere.)

We could also replace sort.Float64s with slices.Sort, however, this
requires more careful consideration as the documentation for
slices.Sort warns that it may not handle NaN values correctly.

* Remove unnecessary comment.

* Rename benchmarks file.

* Add benchmark for BinaryReader.LabelNames().

* Add benchmark for LabelValues().

* Modify mergeExemplarQueryResponses benchmark to exercise merging exemplars with different sets of labels.
masonmei pushed a commit to udmire/mimir that referenced this pull request Dec 16, 2022
…fana#3690)

* Use slices.Sort instead of sort.Strings or sort.Ints.

grafana#3639 (comment),
prometheus/prometheus#11054, and
prometheus/prometheus#11318 all show
substantial performance improvements when using slices.Sort over
sort.Strings.

I've also added a linting rule to catch usage of sort.Strings and
sort.Ints in the future. (We don't currently use sort.Ints anywhere.)

We could also replace sort.Float64s with slices.Sort, however, this
requires more careful consideration as the documentation for
slices.Sort warns that it may not handle NaN values correctly.

* Remove unnecessary comment.

* Rename benchmarks file.

* Add benchmark for BinaryReader.LabelNames().

* Add benchmark for LabelValues().

* Modify mergeExemplarQueryResponses benchmark to exercise merging exemplars with different sets of labels.
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.

4 participants