-
Notifications
You must be signed in to change notification settings - Fork 9.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Microoptimise matching #2005
Microoptimise matching #2005
Conversation
580cc3a
to
7d660ce
Compare
rebased |
Can someone have a look please? It is up to 30% speedup on QueryRange benchmark |
It's on my review queue, I'm just totally overloaded, as usual... |
7d660ce
to
9b15a3b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for doing this.
I have mostly just style nits.
@@ -417,11 +417,11 @@ func (s *MemorySeriesStorage) WaitForIndexing() { | |||
func (s *MemorySeriesStorage) LastSampleForLabelMatchers(_ context.Context, cutoff model.Time, matcherSets ...metric.LabelMatchers) (model.Vector, error) { | |||
fps := map[model.Fingerprint]struct{}{} | |||
for _, matchers := range matcherSets { | |||
fpToMetric, err := s.metricsForLabelMatchers(cutoff, model.Latest, matchers...) | |||
fps1, err := s.fpsForLabelMatchers(cutoff, model.Latest, matchers...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use a more descriptive name than fps1
. For example, you could call this fps
, and the original fps
above mergedFPs
or something.
for fp := range fpToMetric { | ||
it := s.preloadChunksForRange(fp, from, through) | ||
iterators := make([]SeriesIterator, 0, len(fpSeriesPairs)) | ||
for _, v := range fpSeriesPairs { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about pair
or p
instead of v
?
for fp := range fpToMetric { | ||
it := s.preloadChunksForInstant(fp, from, through) | ||
iterators := make([]SeriesIterator, 0, len(fpSeriesPairs)) | ||
for _, v := range fpSeriesPairs { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above.
@@ -563,55 +563,55 @@ func (s *MemorySeriesStorage) MetricsForLabelMatchers( | |||
return metrics, nil | |||
} | |||
|
|||
func (s *MemorySeriesStorage) metricsForLabelMatchers( | |||
from, through model.Time, | |||
// returns candidate FPs for given matchers and remaining matchers to be checked |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Start with "candidateFPsForLabelMatchers" and end with a period.
return nil, err | ||
} | ||
|
||
FP_LOOP: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With my comment above, this comment finally makes sense. Use FPLoop:
if series == nil { | ||
return nopIter | ||
} | ||
|
||
s.fpLocker.Lock(fp) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed in the other PR, the performance gain of not going with defer
is probably negligible in this context, and will go away with Go1.8 anyway. Better use the cleaner code here (i.e. unlock with defer as before).
if series == nil { | ||
return nopIter | ||
} | ||
|
||
s.fpLocker.Lock(fp) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, unlock with defer.
@@ -888,40 +963,42 @@ func (s *MemorySeriesStorage) seriesForRange( | |||
} | |||
|
|||
func (s *MemorySeriesStorage) preloadChunksForRange( | |||
fp model.Fingerprint, | |||
fpsPair fingerprintSeriesPair, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fpsPair
is misleading. (Pair of two FPs?). I'd just call it pair
.
return iter | ||
} | ||
|
||
func (s *MemorySeriesStorage) preloadChunksForInstant( | ||
fp model.Fingerprint, | ||
fpsPair fingerprintSeriesPair, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above.
@@ -65,3 +65,7 @@ func NewTestStorage(t testutil.T, encoding chunkEncoding) (*MemorySeriesStorage, | |||
|
|||
return storage, closer | |||
} | |||
|
|||
func mkFpSeriesPair(s *MemorySeriesStorage, fp model.Fingerprint) fingerprintSeriesPair { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Capitalization nit: mkFPSeriesPair
. But given the name of the returned type (where FP is not abbreviated), and given that "make" is rarle abrreviated "mk" in typical Go constructors, why not call it makeFingerprintSeriesPair
after all?
@redbaron Ping? |
@beorn7 will be able to do sometime this week |
Should be marginally faster and somewhat more GC friendly
…chers method No functional changes otherwise
4f50e9b
to
0a16958
Compare
@beorn7 , made suggested changes |
sorry, I didn't know this PR is holding a release back. I'll keep this tab open and expect to be able to make fixes if needed within an hour. |
} | ||
|
||
result := []fingerprintSeriesPair{} | ||
FP_LOOP: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My comment here got lost: Don't use snake case in Go. Use something like FPLoop:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
Thanks. The only missing nit is the one about the loop labels. See comments above. After that, we can merge. |
0a16958
to
fc50365
Compare
Sorry for the nit, but ALLCAPS is also not very Go idiomatic. Please use |
These more specific methods have replaced `metricForLabelMatchers` in cases where its `map[fingerprint]metric` result type was not necessary or was used as an intermediate step Avoids duplicated calls to `seriesForRange` from `QueryRange` and `QueryInstant` methods.
fc50365
to
e6db9f8
Compare
fixed, I wasn't reading careful enough :) |
Thank you. Merging now. |
Do you still keep authors.md up to date? |
In principle, yes. It definitely needs a major update. I had a script for it somewhere… |
Series of patches with minor matching optimizations.
ab65905 - adds BenchmarkQueryRange to measure effect of future changes
e222d40 - avoids extra iteration over possible results, run matchers checks before adding to a result instead
1121364 - extracts logic which prepares candidate FPs into a separate method
9b15a3b - adds
fpsForLabelMatchers
andseriesForLabelMatchers
methods and uses them where appropriateBefore (as of ab65905):
After: