Skip to content

Conversation

@codesome
Copy link
Contributor

@codesome codesome commented Jul 1, 2019

In my quest of optimizing query performance, I found that result.append was taking a significant amount of time in mergeStream (2s+ of around 4s of mergeStream).

The query and data in action is described here prometheus/prometheus#5707 (comment)

In this PR I have inlined the appending logic with the merging logic. This saves anywhere from 1s-2.5s for the above data.

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>
@bboreham
Copy link
Contributor

bboreham commented Jul 1, 2019

suggests this comment wasn't true?

// append, reset, hasNext, next, atTime etc are all inlined in go1.11.	

Copy link
Contributor

@bboreham bboreham left a comment

Choose a reason for hiding this comment

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

I'd like some more information on why the repeated code cannot be a function, before approving.

@codesome
Copy link
Contributor Author

codesome commented Jul 1, 2019

Ah yup, then I guess the improvement was by efficient use of result slice I believe. There are fewer accesses to the result slice (only when going to next batch as opposed to accessing it for every sample), and direct assignment of values to the batch.

Also avoiding result = append(result, promchunk.Batch{}) for the first few Batch (till capacity) and just setting Index and Length to 0 also seemed to help.

@codesome
Copy link
Contributor Author

codesome commented Jul 1, 2019

I'd like some more information on why the repeated code cannot be a function, before approving.

I will club repeated code into functions and see if there is any difference in perf. If Go is inlining them, I believe there shouldn't be much difference.

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>
Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>
@bboreham
Copy link
Contributor

bboreham commented Jul 3, 2019

This comment that was there before:

// Caller must guarantee result is big enough.  Return value will always be a	

Can this comment be relied on? Seems the code would be a lot simpler if it were.

@codesome
Copy link
Contributor Author

codesome commented Jul 3, 2019

I considered that, but here are the reasons why I infer result can fall short.

  1. mergeStreams is also called here

    c.batchesBuf = mergeStreams(c.batches, nextBatch, c.batchesBuf, size)
    so the guarantee asked by mergeBatches need not hold true here.

  2. Tests failed if I assume that, because it was thought result length would be taken care of?

@bboreham
Copy link
Contributor

bboreham commented Jul 3, 2019

At least, the comment should be changed.
Right now I feel the code is too complicated for me to approve. Possibly if I spent a few hours poking at it I would understand what is going on.

@codesome
Copy link
Contributor Author

codesome commented Jul 4, 2019

I will try to simplify and add more comments to make it more readable.

At least, the comment should be changed.

I was thinking we can remove mergeBatch totally as we are not using it anywhere.

➜  cortex git:(merge-stream) ✗ grep -rni mergeBatches
Binary file .pkg/linux_amd64/github.com/cortexproject/cortex/pkg/querier/batch.a matches
pkg/querier/batch/stream.go:50:// mergeBatches assumes the contents of batches are overlapping and unsorted.
pkg/querier/batch/stream.go:53:// slice pointing to the same underly array as result, allowing mergeBatches
pkg/querier/batch/stream.go:55:func mergeBatches(batches batchStream, result batchStream, size int) batchStream {
pkg/querier/batch/stream.go:66:		left := mergeBatches(batches[n:], result[n:], size)
pkg/querier/batch/stream.go:67:		right := mergeBatches(batches[:n], result[:n], size)
pkg/querier/batch/stream_test.go:48:			result = mergeBatches(tc.input, result, promchunk.BatchSize)

Ganesh Vernekar added 3 commits July 4, 2019 22:06
After some changes at some other places, this code  suddenly
started taking a lot of allocs (upto 7x) and B/op (and also time)
for query involving a lot of chunks. Reusing the buffer solves it.

Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>
Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>
Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>
@codesome
Copy link
Contributor Author

codesome commented Jul 5, 2019

I have simplified some part of mergeStreams (the initilization at the beginning) and also added some comments. Additionally, removed mergeBatchs as it was not used anywhere.

@tomwilkie tomwilkie self-requested a review July 11, 2019 13:42
Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
Copy link
Contributor

@tomwilkie tomwilkie left a comment

Choose a reason for hiding this comment

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

We're had this running for ~2 weeks now, no problems observed.

@tomwilkie tomwilkie requested a review from gouthamve August 7, 2019 11:03
@tomwilkie tomwilkie merged commit 089acd9 into cortexproject:master Aug 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants