Skip to content

Commit 3373f3b

Browse files
authored
defer array allocation until the first use in CachedOnFirstUseColumnGenerator (#427)
1 parent 6121cf3 commit 3373f3b

File tree

1 file changed

+30
-18
lines changed

1 file changed

+30
-18
lines changed

src/Microsoft.Performance.SDK/Processing/Projection/Projection.cs

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using System;
5+
using System.Collections;
56
using System.Collections.Generic;
67
using System.Diagnostics;
78
using System.Reflection;
@@ -1960,39 +1961,32 @@ private struct CachedOnFirstUseColumnGenerator<T, TGenerator>
19601961
IVisibleDomainSensitiveProjection
19611962
where TGenerator : IProjection<int, T>
19621963
{
1963-
const byte byteTrue = 1;
1964-
const byte byteFalse = 0;
1965-
1966-
private readonly T[] cache;
1967-
private readonly byte[] isCached;
1968-
private TGenerator generator;
1964+
private readonly int rowCount;
1965+
private readonly Lazy<Cache> lazyCache;
1966+
private readonly TGenerator generator;
19691967

19701968
public CachedOnFirstUseColumnGenerator(int rowCount, TGenerator generator)
19711969
{
1972-
this.cache = new T[rowCount];
1973-
this.isCached = new byte[rowCount];
1970+
this.rowCount = rowCount;
19741971
this.generator = generator;
1972+
1973+
// Lazy is thread-safe by default
1974+
this.lazyCache = new Lazy<Cache>(() => new Cache(new T[rowCount], new BitArray(rowCount)));
19751975
}
19761976

19771977
private void ResetCache()
19781978
{
1979-
for (int i = 0; i < this.cache.Length; ++i)
1979+
if (this.lazyCache.IsValueCreated)
19801980
{
1981-
this.isCached[i] = byteFalse;
1981+
this.lazyCache.Value.Reset();
19821982
}
19831983
}
19841984

19851985
public T this[int value]
19861986
{
19871987
get
19881988
{
1989-
if (this.isCached[value] != byteTrue)
1990-
{
1991-
this.cache[value] = this.generator[value];
1992-
this.isCached[value] = byteTrue;
1993-
}
1994-
1995-
return this.cache[value];
1989+
return this.lazyCache.Value.Get(value, this.generator);
19961990
}
19971991
}
19981992

@@ -2017,7 +2011,7 @@ public object Clone()
20172011
if (this.DependsOnVisibleDomain)
20182012
{
20192013
return new CachedOnFirstUseColumnGenerator<T, TGenerator>(
2020-
this.cache.Length,
2014+
this.rowCount,
20212015
this.generator.CloneIfVisibleDomainSensitive());
20222016
}
20232017
else
@@ -2038,6 +2032,24 @@ public bool NotifyVisibleDomainChanged(IVisibleDomainRegion newVisibleDomain)
20382032
}
20392033

20402034
public bool DependsOnVisibleDomain => this.generator.DependsOnVisibleDomain();
2035+
2036+
private readonly record struct Cache(T[] Values, BitArray IsCached)
2037+
{
2038+
public void Reset()
2039+
{
2040+
this.IsCached.SetAll(false);
2041+
}
2042+
2043+
public T Get(int index, TGenerator generator)
2044+
{
2045+
if (!this.IsCached[index])
2046+
{
2047+
this.Values[index] = generator[index];
2048+
this.IsCached[index] = true;
2049+
}
2050+
return this.Values[index];
2051+
}
2052+
}
20412053
}
20422054

20432055
private static class CacheVisibleDomainColumn

0 commit comments

Comments
 (0)