Skip to content

Commit

Permalink
Fix IndexOutOfRangeException when we iterate over all the Generations…
Browse files Browse the repository at this point in the history
… and try to access GenData (#2154)

* Initial work.

* More clean up of accidentally indexing

* Clean up

* Addressed feedback

* Fixed one more IndexOutOfRangeException
  • Loading branch information
mrsharm authored Jan 30, 2025
1 parent e46234e commit 8850b34
Showing 1 changed file with 30 additions and 16 deletions.
46 changes: 30 additions & 16 deletions src/TraceEvent/Computers/TraceManagedProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1979,7 +1979,7 @@ public void EnsureBGCRevisitInfoAlloc()
/// Amount of memory allocated since last GC. Requires GCAllocationTicks enabled. The
/// data is split into small and large heaps
/// </summary>
public double[] AllocedSinceLastGCBasedOnAllocTickMB = { 0.0, 0.0 };// Set in HeapStats
public double[] AllocedSinceLastGCBasedOnAllocTickMB = { 0.0, 0.0, 0.0 };// Set in HeapStats
/// <summary>
/// Number of heaps. -1 is the default
/// </summary>
Expand Down Expand Up @@ -2156,6 +2156,11 @@ public double SurvivalPercent(Gens gen)
{
double retSurvRate = double.NaN;

if (!ValidGenData(PerHeapHistories, gen))
{
return retSurvRate;
}

long SurvRate = 0;

if (gen == Gens.GenLargeObj || gen == Gens.GenPinObj)
Expand All @@ -2170,16 +2175,13 @@ public double SurvivalPercent(Gens gen)
return retSurvRate;
}

if (PerHeapHistories != null && PerHeapHistories.Count > 0)
for (int i = 0; i < PerHeapHistories.Count; i++)
{
for (int i = 0; i < PerHeapHistories.Count; i++)
{
SurvRate += PerHeapHistories[i].GenData[(int)gen].SurvRate;
}

SurvRate /= PerHeapHistories.Count;
SurvRate += PerHeapHistories[i].GenData[(int)gen].SurvRate;
}

SurvRate /= PerHeapHistories.Count;

retSurvRate = SurvRate;

return retSurvRate;
Expand Down Expand Up @@ -2219,14 +2221,16 @@ public double GenSizeAfterMB(Gens gen)
Debug.Assert(false);
return double.NaN;
}


/// <summary>
/// Heap fragmentation by generation (mb)
/// </summary>
/// <param name="gen"></param>
/// <returns></returns>
public double GenFragmentationMB(Gens gen)
{
if (PerHeapHistories == null)
if (!ValidGenData(PerHeapHistories, gen))
{
return double.NaN;
}
Expand Down Expand Up @@ -2255,7 +2259,7 @@ public double GenFragmentationPercent(Gens gen)
/// <returns></returns>
public double GenInMB(Gens gen)
{
if (PerHeapHistories == null)
if (!ValidGenData(PerHeapHistories, gen))
{
return double.NaN;
}
Expand All @@ -2275,7 +2279,7 @@ public double GenInMB(Gens gen)
/// <returns></returns>
public double GenOutMB(Gens gen)
{
if (PerHeapHistories == null)
if (!ValidGenData(PerHeapHistories, gen))
{
return double.NaN;
}
Expand Down Expand Up @@ -2334,7 +2338,7 @@ public double GenPromotedMB(Gens gen)
/// <returns></returns>
public double GenBudgetMB(Gens gen)
{
if (PerHeapHistories == null)
if (!ValidGenData(PerHeapHistories, gen))
{
return double.NaN;
}
Expand All @@ -2354,7 +2358,7 @@ public double GenBudgetMB(Gens gen)
/// <returns></returns>
public double GenObjSizeAfterMB(Gens gen)
{
if (PerHeapHistories == null)
if (!ValidGenData(PerHeapHistories, gen))
{
return double.NaN;
}
Expand Down Expand Up @@ -2414,6 +2418,9 @@ public GCCondemnedReasons[] PerHeapCondemnedReasons
}
}

internal static bool ValidGenData(List<GCPerHeapHistory> perHeapHistories, Gens gen)
=> !(perHeapHistories == null || perHeapHistories.Count == 0 || perHeapHistories[0].GenData.Length <= (int)gen);

public enum TimingType
{
/// <summary>
Expand Down Expand Up @@ -2939,7 +2946,7 @@ internal static double GetHeapSizeBeforeMB(List<TraceGC> GCs, TraceGC gc)
// Per generation stats.
internal static double GetGenSizeBeforeMB(List<TraceGC> GCs, TraceGC gc, Gens gen)
{
if (gc.PerHeapHistories != null && gc.PerHeapHistories.Count > 0)
if (ValidGenData(gc.PerHeapHistories, gen))
{
double ret = 0.0;
for (int HeapIndex = 0; HeapIndex < gc.PerHeapHistories.Count; HeapIndex++)
Expand All @@ -2953,7 +2960,7 @@ internal static double GetGenSizeBeforeMB(List<TraceGC> GCs, TraceGC gc, Gens ge
return ret;
}

// When we don't have perheap history we can only estimate for gen0 and gen3.
// When we don't have perheap history we can only estimate for gen0, gen3 and gen4.
double Gen0SizeBeforeMB = 0;
if (gen == Gens.Gen0)
{
Expand Down Expand Up @@ -3031,6 +3038,12 @@ private static double GetUserAllocatedPerHeap(List<TraceGC> GCs, TraceGC gc, int
{
Debug.Assert(HeapIndex < gc.PerHeapHistories.Count);

// If the gen data isn't available for the specific PerHeapHistory, we can't calculate.
if (!ValidGenData(gc.PerHeapHistories, gen))
{
return 0;
}

long prevObjSize = 0;
if (gc.Index > 0)
{
Expand All @@ -3048,6 +3061,7 @@ private static double GetUserAllocatedPerHeap(List<TraceGC> GCs, TraceGC gc, int
}
}
}

GCPerHeapHistoryGenData currentGenData = gc.PerHeapHistories[HeapIndex].GenData[(int)gen];
double Allocated;

Expand Down Expand Up @@ -3087,7 +3101,7 @@ private static double EstimateAllocSurv0(List<TraceGC> GCs, TraceGC gc, int Heap
{
// If the prevous GC has that heap get its size.
var perHeapGenData = GCs[gc.Index - 1].PerHeapHistories;
if (perHeapGenData?.Count > 0 && HeapIndex < perHeapGenData.Count)
if (ValidGenData(perHeapGenData, gen))
{
return perHeapGenData[HeapIndex].GenData[(int)gen].Budget;
}
Expand Down

0 comments on commit 8850b34

Please sign in to comment.