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
ddtrace/tracer: switch atomics to 32-bit #1443
Conversation
db61ba1
to
fb24699
Compare
fb24699
to
2b1ba99
Compare
I also saw the panic with I think you might have to use |
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.
Removing approval until we can get the tests passing and so we don't accidentally merge
Thanks for the testcase, @nsrip-dd. I assumed that go.uber.org/atomic took care of that based on the documentation. I should've double-checked. I'm wondering if it's worth moving to go.uber.org at all, or if we should wait for Emphasis mine:
We obviously need a solution in the meantime, but maybe we can fix that ourselves. Do we even need 64-bit values for most of these? They're all counters that get reset and I don't think we're sending 2^32 anything. |
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.
IMO, go.uber.atomic is still nice because it enforces atomic access, even if it doesn't solve alignment problems.
Do we even need 64-bit values for most of these? They're all counters that get reset and I don't think we're sending 2^32 anything.
Looking through the PR, I think you cant definitely change most of these to 32-bit. I've left comments where I think you can safely use 32-bit.
For stuff you're not sure about, you can make them *atomic.Int64
, they just need to be initialized with atomic.NewInt64
. From a performance perspective, atomic.Int32
can be used safely without paying the price of a heap allocation. But for things that aren't frequently created, like a tracer
, the performance probably doesn't matter.
Go's (new with go1.19) standard library types do exactly the same thing. They force atomic access, but also solve alignment issues. It looks almost identical to the Uber API, except it works. I double-checked and the alignment is taken care of by the new std lib atomics. It looks like we can move all the 64-bit integers to 32 bits (or bools) so I'm more in favor of doing that at the moment than adding I wouldn't be as hesitant to change to Uber except:
|
Agreed, using the standard library would be my preference as well. Switching everything to 32-bit atomics for now and using the Go 1.19 atomic types as soon as we can makes sense to me. |
sync/atomic has several issues. Among them is that it causes a panic when a 64-bit field isn't correctly aligned. Alignment must be manually ensured and is easy to forget. Instead, we will use 32-bit atomic integers which do not require manual alignment. We can eventually trade them out for Go's new atomics APIs that were introduced in go1.19, but we have to wait until 1.18 falls out of our supported versions. Fixes #1418
855e761
to
bcd6cc1
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.
LGTM! I tested these changes on a Linux VM, using qemu to run with GOARCH=arm
and GOARCH=386
. There aren't any panics due to unaligned atomics, so this should be good to go.
As mentioned previously, I had to temporarily force the tracer to use a no-op statsd client because there are unaligned atomics upstream (see DataDog/datadog-go#260). But as far as I can tell this PR fixes the issues in this repository.
Also, this is a small thing and not worth blocking this PR IMO, but the unit tests in textmap_test.go don't pass on 32-bit architectures. e.g:
--- FAIL: TestTextMapPropagator/InvalidTraceTags (0.00s)
textmap_test.go:322:
Error Trace: textmap_test.go:322
Error: Not equal:
expected: "-478508587"
actual : "1909628612072081877"
Diff:
--- Expected
+++ Actual
@@ -1 +1 @@
--478508587
+1909628612072081877
Test: TestTextMapPropagator/InvalidTraceTags
The failing line is
assert.Equal(t, strconv.Itoa(int(childSpanID)), dst["x-datadog-parent-id"])
But int
is 32 bits on 32-bit platforms and the right hand side comes from a 64-bit integer. I don't think this affects the correctness of the actual code, just the tests, though.
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.
Just one comment, otherwise LGTM
sync/atomic has several issues. Among them is that it causes a panic when a
64-bit field isn't correctly aligned. Alignment must be manually ensured
and is easy to forget.
Instead, we will use 32-bit atomic integers which do not require manual
alignment. We can eventually trade them out for Go's new atomics APIs that
were introduced in go1.19, but we have to wait until 1.18 falls out of our
supported versions.
Fixes #1418