diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj
index 2f1a903683e201..6b79836de8cc60 100644
--- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj
+++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj
@@ -372,6 +372,7 @@ The System.Text.Json library is built-in as part of the shared framework in .NET
+
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.Cache.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.Cache.cs
index dc203854c3d858..c924f7de362e68 100644
--- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.Cache.cs
+++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionEmitCachingMemberAccessor.Cache.cs
@@ -14,16 +14,16 @@ internal sealed partial class ReflectionEmitCachingMemberAccessor
private sealed class Cache where TKey : notnull
{
private int _evictLock;
- private long _lastEvictedTicks; // timestamp of latest eviction operation.
- private readonly long _evictionIntervalTicks; // min timespan needed to trigger a new evict operation.
- private readonly long _slidingExpirationTicks; // max timespan allowed for cache entries to remain inactive.
+ private long _lastEvictedTimestamp; // Stopwatch timestamp of the latest eviction operation.
+ private readonly TimeSpan _evictionInterval; // min duration needed to trigger a new evict operation.
+ private readonly TimeSpan _slidingExpiration; // max duration allowed for cache entries to remain inactive.
private readonly ConcurrentDictionary _cache = new();
public Cache(TimeSpan slidingExpiration, TimeSpan evictionInterval)
{
- _slidingExpirationTicks = slidingExpiration.Ticks;
- _evictionIntervalTicks = evictionInterval.Ticks;
- _lastEvictedTicks = DateTime.UtcNow.Ticks;
+ _slidingExpiration = slidingExpiration;
+ _evictionInterval = evictionInterval;
+ _lastEvictedTimestamp = Stopwatch.GetTimestamp();
}
public TValue GetOrAdd(TKey key, Func valueFactory) where TValue : class?
@@ -36,17 +36,17 @@ public TValue GetOrAdd(TKey key, Func valueFactory) where
#else
key => new(valueFactory(key)));
#endif
- long utcNowTicks = DateTime.UtcNow.Ticks;
- Volatile.Write(ref entry.LastUsedTicks, utcNowTicks);
+ long nowTimestamp = Stopwatch.GetTimestamp();
+ Volatile.Write(ref entry.LastUsedTimestamp, nowTimestamp);
- if (utcNowTicks - Volatile.Read(ref _lastEvictedTicks) >= _evictionIntervalTicks)
+ if (Stopwatch.GetElapsedTime(Volatile.Read(ref _lastEvictedTimestamp), nowTimestamp) >= _evictionInterval)
{
if (Interlocked.CompareExchange(ref _evictLock, 1, 0) == 0)
{
- if (utcNowTicks - _lastEvictedTicks >= _evictionIntervalTicks)
+ if (Stopwatch.GetElapsedTime(_lastEvictedTimestamp, nowTimestamp) >= _evictionInterval)
{
- EvictStaleCacheEntries(utcNowTicks);
- Volatile.Write(ref _lastEvictedTicks, utcNowTicks);
+ EvictStaleCacheEntries(nowTimestamp);
+ Volatile.Write(ref _lastEvictedTimestamp, nowTimestamp);
}
Volatile.Write(ref _evictLock, 0);
@@ -59,14 +59,14 @@ public TValue GetOrAdd(TKey key, Func valueFactory) where
public void Clear()
{
_cache.Clear();
- _lastEvictedTicks = DateTime.UtcNow.Ticks;
+ _lastEvictedTimestamp = Stopwatch.GetTimestamp();
}
- private void EvictStaleCacheEntries(long utcNowTicks)
+ private void EvictStaleCacheEntries(long nowTimestamp)
{
foreach (KeyValuePair kvp in _cache)
{
- if (utcNowTicks - Volatile.Read(ref kvp.Value.LastUsedTicks) >= _slidingExpirationTicks)
+ if (Stopwatch.GetElapsedTime(Volatile.Read(ref kvp.Value.LastUsedTimestamp), nowTimestamp) >= _slidingExpiration)
{
_cache.TryRemove(kvp.Key, out _);
}
@@ -76,7 +76,7 @@ private void EvictStaleCacheEntries(long utcNowTicks)
private sealed class CacheEntry
{
public readonly object? Value;
- public long LastUsedTicks;
+ public long LastUsedTimestamp;
public CacheEntry(object? value)
{