Skip to content

Commit 8850b34

Browse files
authored
Fix IndexOutOfRangeException when we iterate over all the Generations and try to access GenData (#2154)
* Initial work. * More clean up of accidentally indexing * Clean up * Addressed feedback * Fixed one more IndexOutOfRangeException
1 parent e46234e commit 8850b34

File tree

1 file changed

+30
-16
lines changed

1 file changed

+30
-16
lines changed

src/TraceEvent/Computers/TraceManagedProcess.cs

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1979,7 +1979,7 @@ public void EnsureBGCRevisitInfoAlloc()
19791979
/// Amount of memory allocated since last GC. Requires GCAllocationTicks enabled. The
19801980
/// data is split into small and large heaps
19811981
/// </summary>
1982-
public double[] AllocedSinceLastGCBasedOnAllocTickMB = { 0.0, 0.0 };// Set in HeapStats
1982+
public double[] AllocedSinceLastGCBasedOnAllocTickMB = { 0.0, 0.0, 0.0 };// Set in HeapStats
19831983
/// <summary>
19841984
/// Number of heaps. -1 is the default
19851985
/// </summary>
@@ -2156,6 +2156,11 @@ public double SurvivalPercent(Gens gen)
21562156
{
21572157
double retSurvRate = double.NaN;
21582158

2159+
if (!ValidGenData(PerHeapHistories, gen))
2160+
{
2161+
return retSurvRate;
2162+
}
2163+
21592164
long SurvRate = 0;
21602165

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

2173-
if (PerHeapHistories != null && PerHeapHistories.Count > 0)
2178+
for (int i = 0; i < PerHeapHistories.Count; i++)
21742179
{
2175-
for (int i = 0; i < PerHeapHistories.Count; i++)
2176-
{
2177-
SurvRate += PerHeapHistories[i].GenData[(int)gen].SurvRate;
2178-
}
2179-
2180-
SurvRate /= PerHeapHistories.Count;
2180+
SurvRate += PerHeapHistories[i].GenData[(int)gen].SurvRate;
21812181
}
21822182

2183+
SurvRate /= PerHeapHistories.Count;
2184+
21832185
retSurvRate = SurvRate;
21842186

21852187
return retSurvRate;
@@ -2219,14 +2221,16 @@ public double GenSizeAfterMB(Gens gen)
22192221
Debug.Assert(false);
22202222
return double.NaN;
22212223
}
2224+
2225+
22222226
/// <summary>
22232227
/// Heap fragmentation by generation (mb)
22242228
/// </summary>
22252229
/// <param name="gen"></param>
22262230
/// <returns></returns>
22272231
public double GenFragmentationMB(Gens gen)
22282232
{
2229-
if (PerHeapHistories == null)
2233+
if (!ValidGenData(PerHeapHistories, gen))
22302234
{
22312235
return double.NaN;
22322236
}
@@ -2255,7 +2259,7 @@ public double GenFragmentationPercent(Gens gen)
22552259
/// <returns></returns>
22562260
public double GenInMB(Gens gen)
22572261
{
2258-
if (PerHeapHistories == null)
2262+
if (!ValidGenData(PerHeapHistories, gen))
22592263
{
22602264
return double.NaN;
22612265
}
@@ -2275,7 +2279,7 @@ public double GenInMB(Gens gen)
22752279
/// <returns></returns>
22762280
public double GenOutMB(Gens gen)
22772281
{
2278-
if (PerHeapHistories == null)
2282+
if (!ValidGenData(PerHeapHistories, gen))
22792283
{
22802284
return double.NaN;
22812285
}
@@ -2334,7 +2338,7 @@ public double GenPromotedMB(Gens gen)
23342338
/// <returns></returns>
23352339
public double GenBudgetMB(Gens gen)
23362340
{
2337-
if (PerHeapHistories == null)
2341+
if (!ValidGenData(PerHeapHistories, gen))
23382342
{
23392343
return double.NaN;
23402344
}
@@ -2354,7 +2358,7 @@ public double GenBudgetMB(Gens gen)
23542358
/// <returns></returns>
23552359
public double GenObjSizeAfterMB(Gens gen)
23562360
{
2357-
if (PerHeapHistories == null)
2361+
if (!ValidGenData(PerHeapHistories, gen))
23582362
{
23592363
return double.NaN;
23602364
}
@@ -2414,6 +2418,9 @@ public GCCondemnedReasons[] PerHeapCondemnedReasons
24142418
}
24152419
}
24162420

2421+
internal static bool ValidGenData(List<GCPerHeapHistory> perHeapHistories, Gens gen)
2422+
=> !(perHeapHistories == null || perHeapHistories.Count == 0 || perHeapHistories[0].GenData.Length <= (int)gen);
2423+
24172424
public enum TimingType
24182425
{
24192426
/// <summary>
@@ -2939,7 +2946,7 @@ internal static double GetHeapSizeBeforeMB(List<TraceGC> GCs, TraceGC gc)
29392946
// Per generation stats.
29402947
internal static double GetGenSizeBeforeMB(List<TraceGC> GCs, TraceGC gc, Gens gen)
29412948
{
2942-
if (gc.PerHeapHistories != null && gc.PerHeapHistories.Count > 0)
2949+
if (ValidGenData(gc.PerHeapHistories, gen))
29432950
{
29442951
double ret = 0.0;
29452952
for (int HeapIndex = 0; HeapIndex < gc.PerHeapHistories.Count; HeapIndex++)
@@ -2953,7 +2960,7 @@ internal static double GetGenSizeBeforeMB(List<TraceGC> GCs, TraceGC gc, Gens ge
29532960
return ret;
29542961
}
29552962

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

3041+
// If the gen data isn't available for the specific PerHeapHistory, we can't calculate.
3042+
if (!ValidGenData(gc.PerHeapHistories, gen))
3043+
{
3044+
return 0;
3045+
}
3046+
30343047
long prevObjSize = 0;
30353048
if (gc.Index > 0)
30363049
{
@@ -3048,6 +3061,7 @@ private static double GetUserAllocatedPerHeap(List<TraceGC> GCs, TraceGC gc, int
30483061
}
30493062
}
30503063
}
3064+
30513065
GCPerHeapHistoryGenData currentGenData = gc.PerHeapHistories[HeapIndex].GenData[(int)gen];
30523066
double Allocated;
30533067

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

0 commit comments

Comments
 (0)