Skip to content

Commit

Permalink
Minor refactoring for AggregatorStore and MetricPoint (#5510)
Browse files Browse the repository at this point in the history
  • Loading branch information
utpilla authored Apr 5, 2024
1 parent 3f4c73a commit 90d9a91
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 35 deletions.
85 changes: 52 additions & 33 deletions src/OpenTelemetry/Metrics/AggregatorStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,39 +270,7 @@ internal void SnapshotDeltaWithMetricPointReclaim()
// the MetricPoint can be reused for other tags.
if (metricPoint.LookupData != null && Interlocked.CompareExchange(ref metricPoint.ReferenceCount, int.MinValue, 0) == 0)
{
var lookupData = metricPoint.LookupData;

metricPoint.Reclaim();

Debug.Assert(this.TagsToMetricPointIndexDictionaryDelta != null, "this.tagsToMetricPointIndexDictionaryDelta was null");

lock (this.TagsToMetricPointIndexDictionaryDelta!)
{
LookupData? dictionaryValue;
if (lookupData.SortedTags != Tags.EmptyTags)
{
// Check if no other thread added a new entry for the same Tags.
// If no, then remove the existing entries.
if (this.TagsToMetricPointIndexDictionaryDelta.TryGetValue(lookupData.SortedTags, out dictionaryValue) &&
dictionaryValue == lookupData)
{
this.TagsToMetricPointIndexDictionaryDelta.TryRemove(lookupData.SortedTags, out var _);
this.TagsToMetricPointIndexDictionaryDelta.TryRemove(lookupData.GivenTags, out var _);
}
}
else
{
if (this.TagsToMetricPointIndexDictionaryDelta.TryGetValue(lookupData.GivenTags, out dictionaryValue) &&
dictionaryValue == lookupData)
{
this.TagsToMetricPointIndexDictionaryDelta.TryRemove(lookupData.GivenTags, out var _);
}
}

Debug.Assert(this.availableMetricPoints != null, "this.availableMetricPoints was null");

this.availableMetricPoints!.Enqueue(i);
}
this.ReclaimMetricPoint(ref metricPoint, i);
}

continue;
Expand Down Expand Up @@ -372,6 +340,57 @@ private void TakeMetricPointSnapshot(ref MetricPoint metricPoint, bool outputDel
}
}

private void ReclaimMetricPoint(ref MetricPoint metricPoint, int metricPointIndex)
{
/*
This method does three things:
1. Set `metricPoint.LookupData` and `metricPoint.mpComponents` to `null` to have them collected faster by GC.
2. Tries to remove the entry for this MetricPoint from the lookup dictionary. An update thread which retrieves this
MetricPoint would realize that the MetricPoint is not valid for use since its reference count would have been set to a negative number.
When that happens, the update thread would also try to remove the entry for this MetricPoint from the lookup dictionary.
We only care about the entry getting removed from the lookup dictionary and not about which thread removes it.
3. Put the array index of this MetricPoint to the queue of available metric points. This makes it available for update threads
to use this MetricPoint to track newer dimension combinations.
*/

var lookupData = metricPoint.LookupData;

// This method is only called after checking that `metricPoint.LookupData` is not `null`.
Debug.Assert(lookupData != null, "LookupData for the provided MetricPoint was null");

metricPoint.NullifyMetricPointState();

Debug.Assert(this.TagsToMetricPointIndexDictionaryDelta != null, "this.tagsToMetricPointIndexDictionaryDelta was null");

lock (this.TagsToMetricPointIndexDictionaryDelta!)
{
LookupData? dictionaryValue;
if (lookupData!.SortedTags != Tags.EmptyTags)
{
// Check if no other thread added a new entry for the same Tags.
// If no, then remove the existing entries.
if (this.TagsToMetricPointIndexDictionaryDelta.TryGetValue(lookupData.SortedTags, out dictionaryValue) &&
dictionaryValue == lookupData)
{
this.TagsToMetricPointIndexDictionaryDelta.TryRemove(lookupData.SortedTags, out var _);
this.TagsToMetricPointIndexDictionaryDelta.TryRemove(lookupData.GivenTags, out var _);
}
}
else
{
if (this.TagsToMetricPointIndexDictionaryDelta.TryGetValue(lookupData.GivenTags, out dictionaryValue) &&
dictionaryValue == lookupData)
{
this.TagsToMetricPointIndexDictionaryDelta.TryRemove(lookupData.GivenTags, out var _);
}
}

Debug.Assert(this.availableMetricPoints != null, "this.availableMetricPoints was null");

this.availableMetricPoints!.Enqueue(metricPointIndex);
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void InitializeZeroTagPointIfNotInitialized()
{
Expand Down
5 changes: 3 additions & 2 deletions src/OpenTelemetry/Metrics/MetricPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1197,9 +1197,10 @@ internal void TakeSnapshotWithExemplar(bool outputDelta)
}

/// <summary>
/// Denote that this MetricPoint is reclaimed.
/// This method sets the member object references of MetricPoint to `null`.
/// This is done to have them collected faster by GC.
/// </summary>
internal void Reclaim()
internal void NullifyMetricPointState()
{
this.LookupData = null;
this.mpComponents = null;
Expand Down

0 comments on commit 90d9a91

Please sign in to comment.