-
Notifications
You must be signed in to change notification settings - Fork 775
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
[Trace Exporters] Remove enumeration helper and use new net7 enumeration APIs #3580
[Trace Exporters] Remove enumeration helper and use new net7 enumeration APIs #3580
Conversation
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Api\Internal\Guard.cs" Link="Includes\Guard.cs" /> | ||
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\EnvironmentVariableHelper.cs" Link="Includes\EnvironmentVariableHelper.cs" /> | ||
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\OpenTelemetrySdkEventSource.cs" Link="Includes\OpenTelemetrySdkEventSource.cs" /> | ||
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\PeriodicExportingMetricReaderHelper.cs" Link="Includes\PeriodicExportingMetricReaderHelper.cs" /> | ||
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\PooledList.cs" Link="Includes\PooledList.cs" /> |
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.
@alanwest FYI I removed the pool usage from OtlpExpoter. We were writing to the pool and then copying onto the span DTO thing. Didn't seem to be adding a whole lot of value and taking time to do the copy. What would be much better is to pool the repeated field instances. Not sure if that is possible. TODO 😄
src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs
Outdated
Show resolved
Hide resolved
src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs
Show resolved
Hide resolved
Codecov Report
@@ Coverage Diff @@
## main #3580 +/- ##
==========================================
- Coverage 87.43% 87.37% -0.06%
==========================================
Files 278 277 -1
Lines 10088 9931 -157
==========================================
- Hits 8820 8677 -143
+ Misses 1268 1254 -14
|
@@ -11,6 +11,5 @@ | |||
|
|||
<ItemGroup> | |||
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="$(SystemDiagnosticSourcePkgVer)" /> | |||
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="$(SystemReflectionEmitLightweightPkgVer)" /> |
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.
🥳
src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs
Outdated
Show resolved
Hide resolved
@@ -83,7 +83,7 @@ public void Equality() | |||
Assert.True(link1.Equals(link3)); | |||
} | |||
|
|||
[Fact] | |||
[Fact(Skip = "ActivityLink.Equals is broken in DS7 preview: https://github.com/dotnet/runtime/issues/74026")] |
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.
🙈 🙉 🙊
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.
FYI dotnet/dotnet-api-docs#8316
We discussed it internally and essentially no one is sure what it means for two ActivityLinks to be equal so we're going to leave it broken/undefined.
|
||
PooledList<ZipkinAnnotation>.Add(ref this.Annotations, new ZipkinAnnotation(activityEvent.Timestamp.ToEpochMicroseconds(), activityEvent.Name)); | ||
do |
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.
I love a good do/while... though maybe use goto
s here instead?
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.
The funny thing is goto, while, do/while none of that really exists it is all jumps at the end of the day 🤣 PS: I did it this way to avoid having to check this.Created
each time an item is processed in the inner 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.
It's all just 1s and 0s at the end of the day... And even then 1s and 0s are a fiction. What's the meaning of life? How can we even be sure that this.Created
?
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.
@alanwest I guess we would know it all when this.Disposed
😀
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.
We should start OpenTelemetry Quantum SIG. Stuff doesn't exist until you observe it, right?
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.
We should start OpenTelemetry Quantum SIG.
I'm in, happy to sponsor it 😆
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.
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.
Nice work driving this through both on the OTel side and .NET side of things! 🎉
I assume the benchmarks would be roughly the same before/after this PR?
@alanwest Let me run the benchmarks to make sure no allocations snuck in and I'll post the results. Should also be faster (might not be measurable) just due to tighter loops without a call through the enumeration helper + check for bool result to see if enumeration should break. |
Jaeger benchmarks: (What this benchmark tests is that Jaeger reserves its memory and then reuses it for subsequent calls. Allocations should stay flat no matter the number of export calls.) Before
After
|
Zipkin benchmarks: (I am offended by how greedy Zipkin is with its allocations! 😱 This can be improved, which I will take as a TODO. The important thing is, no change as a result of this PR.) Before
After
|
OTLP benchmarks: (Some nice gains here* but the memory usage is still extremely high. By the way, it is not fair to compare the time of this benchmark against Jaeger or Zipkin above. OtlpExporter is not faster. The OtlpExporter benchmark mocks the whole call into Protobuf which owns the serialization phase. Jaeger and Zipkin benchmarks actually measure the serialization too. Safe to say OtlpExporter is slower and it likely also uses more memory than what the benchmark sees!) Before
After
* The perf gains are due to the removal of public sealed class RepeatedField<T>
{
public void AddRange(IEnumerable<T> values)
{
ProtoPreconditions.CheckNotNull(values, nameof(values));
// Optimization 1: If the collection we're adding is already a RepeatedField<T>,
// we know the values are valid.
var otherRepeatedField = values as RepeatedField<T>;
if (otherRepeatedField != null)
{
EnsureSize(count + otherRepeatedField.count);
Array.Copy(otherRepeatedField.array, 0, array, count, otherRepeatedField.count);
count += otherRepeatedField.count;
return;
}
// Optimization 2: The collection is an ICollection, so we can expand
// just once and ask the collection to copy itself into the array.
var collection = values as ICollection;
if (collection != null)
{
var extraCount = collection.Count;
// For reference types and nullable value types, we need to check that there are no nulls
// present. (This isn't a thread-safe approach, but we don't advertise this is thread-safe.)
// We expect the JITter to optimize this test to true/false, so it's effectively conditional
// specialization.
if (default(T) == null)
{
// TODO: Measure whether iterating once to check and then letting the collection copy
// itself is faster or slower than iterating and adding as we go. For large
// collections this will not be great in terms of cache usage... but the optimized
// copy may be significantly faster than doing it one at a time.
foreach (var item in collection)
{
if (item == null)
{
throw new ArgumentException("Sequence contained null element", nameof(values));
}
}
}
EnsureSize(count + extraCount);
collection.CopyTo(array, count);
count += extraCount;
return;
}
// We *could* check for ICollection<T> as well, but very very few collections implement
// ICollection<T> but not ICollection. (HashSet<T> does, for one...)
// Fall back to a slower path of adding items one at a time.
foreach (T item in values)
{
Add(item);
}
}
} Issues...
|
🥳
Also updated OtlpExporter to send "dropped counts" when attributes limits are being used. CHANGELOG note added for that.