-
Notifications
You must be signed in to change notification settings - Fork 404
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
Make GetSpan return a statically allocated invalid span #3037
base: main
Are you sure you want to change the base?
Make GetSpan return a statically allocated invalid span #3037
Conversation
By initializing the invalid span at process start time, I mean setting it up like this: void main() {
std::shared_ptr<Span> invalid_span =
std::make_shared<DefaultSpan>(SpanContext::GetInvalid());
opentelemetry::trace::SetSpan(invalid_span);
// ...
} |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #3037 +/- ##
==========================================
+ Coverage 87.12% 87.63% +0.52%
==========================================
Files 200 190 -10
Lines 6109 5869 -240
==========================================
- Hits 5322 5143 -179
+ Misses 787 726 -61
|
Just curious, where are you getting issue in usage of
Just couple of thoughts came to my mind as the potential solution/workarounds to avoid any changes in |
I wouldn't necessarily call it an "issue," but it seems suboptimal for GetSpan to allocate a new span each time a default span is needed. Ideally, it would return a statically allocated span when no active span is found in the current context. Are there any potential downsides to returning a statically allocated span as the default? I'm currently working on integrating OpenTelemetry into parts of Gecko (Firefox), and depending on the level of instrumentation, this could potentially impact performance. |
I believe not. It should be fine to return static allocation for an invalid span. I just don't understand how can the flow possibly reach there. Feel free to make it ready for review. |
If you don't have a root span in main, then this will happen (since we primarily use contexts to control when tracing is active). void main() {
for (int i = 0; i < 100,000; i++) {
foo(); // Will result in 100,000 allocations
}
auto provider = opentelemetry::trace::Provider::GetTracerProvider();
auto tracer = provider->GetTracer("foo_library", "1.0.0");
auto span = tracer->StartSpan("foo");
auto scope = tracer->WithActiveSpan(span);
for (int i = 0; i < 100,000; i++) {
foo(); // Will result in 0 allocations
}
};
void foo() {
auto active_span = opentelemetry::trace::GetSpan(
opentelemetry::context::RuntimeContext::GetCurrent());
active_span.AddEvent("something in foo");
} |
Sorry for the confusion, my college mentioned some potential raise conditions which turned out to be not applicable here. |
Just to clarify, should we continue with this PR, or should it be closed (because of the race found) ? As a side note, if the main concern is performances, the best course of action could be to avoid reaching this case in the first place (i.e., provide a root span in main), instead of optimizing non nominal use cases. |
Yes, I've marked the PR as a draft for the time being where the race was unclear, but it does not apply here. So please continue. The reason for this PR is that for users not familiar with the lib this might not be obvious. If this change is too invasive, we can close this PR and add a note in the docs. |
I’ve observed that the current implementation of
GetSpan
performs a new allocation each time it is called if no active span is found. SinceDefaultSpan
is immutable (or at least intended to be), it seems reasonable to return a statically allocated invalid span instead.This approach could reduce unnecessary heap allocations and improve performance. However, it also introduces the possibility of someone inadvertently replacing the default invalid span with a valid one.
I’m not certain whether this change aligns with the intended design or if the allocation was deliberately chosen to provide more isolation for the default span. An alternative could be to initialize an invalid span at the start of the program if the goal is to eliminate the allocation overhead in production. Nonetheless, there might be other implications to consider.
Please consider this PR as a suggestion and an opportunity for discussion.