Skip to content

Commit

Permalink
Modify MetricPoint to avoid copy (#2321)
Browse files Browse the repository at this point in the history
  • Loading branch information
cijothomas authored Sep 10, 2021
1 parent 4afa474 commit cb8f686
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 24 deletions.
30 changes: 16 additions & 14 deletions src/OpenTelemetry/Metrics/BatchMetricPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,20 @@ public struct Enumerator : IEnumerator

internal Enumerator(MetricPoint[] metricsPoints, long targetCount, DateTimeOffset start, DateTimeOffset end)
{
this.Current = default;
this.metricsPoints = metricsPoints;
this.targetCount = targetCount;
this.index = 0;
this.index = -1;
this.start = start;
this.end = end;
}

public MetricPoint Current { get; private set; }
public ref MetricPoint Current
{
get
{
return ref this.metricsPoints[this.index];
}
}

/// <inheritdoc/>
object IEnumerator.Current => this.Current;
Expand All @@ -84,22 +89,19 @@ public void Dispose()
/// <inheritdoc/>
public bool MoveNext()
{
var metricPoints = this.metricsPoints;
if (this.index < this.targetCount && metricPoints[this.index].StartTime == default)
while (++this.index < this.targetCount)
{
this.index++;
}
ref var metricPoint = ref this.metricsPoints[this.index];
if (metricPoint.StartTime == default)
{
continue;
}

if (this.index < this.targetCount)
{
metricPoints[this.index].StartTime = this.start;
metricPoints[this.index].EndTime = this.end;
this.Current = metricPoints[this.index];
this.index++;
metricPoint.StartTime = this.start;
metricPoint.EndTime = this.end;
return true;
}

this.Current = default;
return false;
}

Expand Down
35 changes: 25 additions & 10 deletions test/Benchmarks/Metrics/MetricCollectBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,18 @@
DefaultJob : .NET Core 3.1.18 (CoreCLR 4.700.21.35901, CoreFX 4.700.21.36305), X64 RyuJIT
| Method | ExportDelta | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|-------- |------------ |----------:|---------:|---------:|------:|------:|------:|----------:|
| Collect | False | 100.59 us | 1.970 us | 5.490 us | - | - | - | 136 B |
| Collect | True | 98.41 us | 1.861 us | 4.670 us | - | - | - | 136 B |
| Method | UseWithRef | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|-------- |----------- |---------:|---------:|---------:|------:|------:|------:|----------:|
| Collect | False | 51.38 us | 1.027 us | 1.261 us | - | - | - | 136 B |
| Collect | True | 33.86 us | 0.716 us | 2.088 us | - | - | - | 136 B |
*/

namespace Benchmarks.Metrics
{
[MemoryDiagnoser]
public class MetricCollectBenchmarks
{
private Counter<long> counter;
private Counter<double> counter;
private MeterProvider provider;
private Meter meter;
private CancellationTokenSource token;
Expand All @@ -55,18 +55,33 @@ public class MetricCollectBenchmarks
private Random random = new Random();

[Params(false, true)]
public bool ExportDelta { get; set; }
public bool UseWithRef { get; set; }

[GlobalSetup]
public void Setup()
{
var metricExporter = new TestMetricExporter(ProcessExport, this.ExportDelta ? AggregationTemporality.Delta : AggregationTemporality.Cumulative);
var metricExporter = new TestMetricExporter(ProcessExport);
void ProcessExport(IEnumerable<Metric> batch)
{
double sum = 0;
foreach (var metric in batch)
{
foreach (var metricPoint in metric.GetMetricPoints())
if (this.UseWithRef)
{
// The performant way of iterating.
foreach (ref var metricPoint in metric.GetMetricPoints())
{
sum += metricPoint.LongValue;
}
}
else
{
// The non-performant way of iterating.
// This is still "correct", but less performant.
foreach (var metricPoint in metric.GetMetricPoints())
{
sum += metricPoint.LongValue;
}
}
}
}
Expand All @@ -78,7 +93,7 @@ void ProcessExport(IEnumerable<Metric> batch)
.Build();

this.meter = new Meter("TestMeter");
this.counter = this.meter.CreateCounter<long>("counter");
this.counter = this.meter.CreateCounter<double>("counter");
this.token = new CancellationTokenSource();
this.writeMetricTask = new Task(() =>
{
Expand All @@ -87,7 +102,7 @@ void ProcessExport(IEnumerable<Metric> batch)
var tag1 = new KeyValuePair<string, object>("DimName1", this.dimensionValues[this.random.Next(0, 10)]);
var tag2 = new KeyValuePair<string, object>("DimName2", this.dimensionValues[this.random.Next(0, 10)]);
var tag3 = new KeyValuePair<string, object>("DimName3", this.dimensionValues[this.random.Next(0, 10)]);
this.counter.Add(100, tag1, tag2, tag3);
this.counter.Add(100.00, tag1, tag2, tag3);
}
});
this.writeMetricTask.Start();
Expand Down

0 comments on commit cb8f686

Please sign in to comment.