Skip to content
This repository was archived by the owner on Aug 30, 2019. It is now read-only.

{writer,info}: fix races#501

Merged
gbbr merged 5 commits into
masterfrom
gbbr/sampler-races
Oct 23, 2018
Merged

{writer,info}: fix races#501
gbbr merged 5 commits into
masterfrom
gbbr/sampler-races

Conversation

@gbbr

@gbbr gbbr commented Oct 23, 2018

Copy link
Copy Markdown
Contributor

No description provided.

@gbbr gbbr added this to the 6.7.0 milestone Oct 23, 2018
@gbbr
gbbr requested a review from LotharSee October 23, 2018 10:23
Comment thread sampler/score.go
@@ -51,6 +51,8 @@ func (s *Sampler) GetDefaultSampleRate() float64 {
}

func (s *Sampler) backendScoreToSamplerScore(score float64) float64 {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is getting called every time we sample a trace. Is there any way to avoid having this lock in the hotpath? Which variable is subject to a race condition?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'd guess both of them are, right? The issue is calling SetSignatureCoefficients at the same time. AFAIK the performance loss is not really significant when there is not much contention. The read lock is simply an atomic.LoadInt* under the hood.

@LotharSee LotharSee Oct 23, 2018

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Yeah I was curious about how it compares vs using atomic.LoadInt directly on signatureScoreFactor and signatureScoreSlope. I guess it should be very close.

One or the other, what about systematically introduce a benchmark whenever we add a lock somewhere, to illustrate the resulting trace-off? (the same way we introduce a test when we fix a bug).

@gbbr gbbr Oct 23, 2018

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

atomic.LoadInt wouldn't work here, because it's a float. But I'm happy to introduce a benchmark. Although, what would the benchmark do? Run AdjustScoring every 10*time.Second and then in parallel GetCountScore (this is what happens in the agent)? Or were you thinking simply benchmarking calling GetCountScore with and without locks?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I guess the latter probably makes most sense. I will add that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ok, so the results are in:

name                          old time/op  new time/op  delta
BackendScoreToSamplerScore-8  16.3ns ± 0%  48.6ns ± 0%  +198.16%

Using this benchmark:

func BenchmarkBackendScoreToSamplerScore(b *testing.B) {
	s := newSampler(1.0, 10)
	for i := 0; i < b.N; i++ {
		s.backendScoreToSamplerScore(10)
	}
}

It's not looking too good. Do you have any ideas? I'm not sure if it's ok to leave this race here. Or?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Could the cost of a lock be actually much more than an atomic? Maybe that's the defer?

We can try to implement an atomic float (just copy what's in https://github.com/uber-go/atomic/blob/master/atomic.go#L267 ), use it on signatureScoreFactor and signatureScoreSlope and compare?

Also, all of that is to make it "the right way". In absolute that duration might not be that much compared to all the stuff on-going when doing sampling. So I wouldn't worry too too much.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Nice ideas!

With no defer:

name                          old time/op  new time/op  delta
BackendScoreToSamplerScore-8  16.3ns ± 0%  25.1ns ± 0%  +53.99%

With Uber's atomic Float64:

name                          old time/op  new time/op  delta
BackendScoreToSamplerScore-8  16.3ns ± 0%  17.5ns ± 0%  +7.36%

I'll go ahead an add the Uber version.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nice, that's great learnings! defer is big.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Indeed!

@gbbr
gbbr force-pushed the gbbr/sampler-races branch 4 times, most recently from daad8d6 to 220f2d7 Compare October 23, 2018 14:35
gbbr added 3 commits October 23, 2018 16:36
Difference between no lock and lock:

```
name                          old time/op  new time/op  delta
BackendScoreToSamplerScore-8  16.3ns �± 0%  48.6ns �± 0%  +198.16%
```
@gbbr
gbbr force-pushed the gbbr/sampler-races branch from 220f2d7 to c331c38 Compare October 23, 2018 14:36
@gbbr

gbbr commented Oct 23, 2018

Copy link
Copy Markdown
Contributor Author

@LotharSee should be super close to what it was now, without the race:

name                          old time/op  new time/op  delta
BackendScoreToSamplerScore-8  16.3ns ± 0%  17.5ns ± 0%  +7.36%

PTAL

```
name                          old time/op  new time/op  delta
BackendScoreToSamplerScore-8  16.3ns �± 0%  17.4ns �± 0%  +6.75%
```
@gbbr
gbbr force-pushed the gbbr/sampler-races branch from c331c38 to b4deb3c Compare October 23, 2018 14:39
Comment thread sampler/float64.go
@gbbr
gbbr force-pushed the gbbr/sampler-races branch from cb36265 to daa9f1e Compare October 23, 2018 14:51
@gbbr
gbbr merged commit a05b4ea into master Oct 23, 2018
@gbbr
gbbr deleted the gbbr/sampler-races branch October 23, 2018 14:53
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants