This log describes the commits in branch memorycache-clockquantization-jit-now
.
The first set of 4 commits lays the foundation for the eventual changes. They ensure that new temporal primitives and the new clock quantization primitives get introduced, while ensuring that existing tests leverage these newly introduced temporal primitives. Also, a new net5.0
target is introduced to ensure that we can leverage new features introduced in .NET 5.0.
- Commit
64ec768
- temporal primitives:- Introduction of abstractions for system clock and temporal context, in preparation of clock quantization
- Main interfaces:
Microsoft.Extensions.Internal.ClockQuantization.ISystemClock
,Microsoft.Extensions.Internal.ClockQuantization.ISystemClockTemporalContext
- Implementation of shims around external clocks (incl.
ManualClock
for testing purposes), as well as a built-in TFM-optimizedInternalClock
- Factory method determines most appropriate shim based on traits of the provided
Microsoft.Extensions.Internal.ISystemClock
(may benull
→InternalClock
) - We may drop some specific shims based on insights gained along the way
- Commit
74a49af
-Microsoft.Extensions.Internal.TestClock
reacting to temporal primitives:- Extends the existing
TestClock
withMicrosoft.Extensions.Internal.ClockQuantization.ISystemClockTemporalContext
traits (internal interface) - An internal
ClockAdjusted
event will be raised when the clock is adjusted inTestClock.Add()
- Note: the original public API surface of
TestClock
was left untouched
- Extends the existing
- Commit
66ae3e5
- additional references and unlocking TFM-specific capabilities for .NET 5.0+:- Adding
net5.0
TFM to unlockEnvironment.TickCount64
for .NET 5.0 and .NET 6.0 - TFM-specific references for
net461
:- System.Runtime.CompilerServices.Unsafe (
Interlocked.*
operations acting onuint
) - System.Threading.Tasks.Extensions (
ValueTask
) - Microsoft.Bcl.AsyncInterfaces (
IAsyncDisposable
)
- System.Runtime.CompilerServices.Unsafe (
- TFM-specific references for
netstandard2.0
- System.Threading.Tasks.Extensions (
ValueTask
) - Microsoft.Bcl.AsyncInterfaces (
IAsyncDisposable
)
- System.Threading.Tasks.Extensions (
- TFM-specific references for
net5.0
- System.Runtime
- System.Threading
- System.Threading.ThreadPool
- System.Collections
- System.Collections.Concurrent
- Adding
- Commit
132ac84
- clock quantization primitives:LazyClockOffsetSerialPosition
LazyClockOffsetSerialPosition.Snapshot
Interval
Interval.SnapshotTracker
Expecting worse performance due to additional layers of abstraction and unit conversions. Main purpose is to exercise (most) clock access functions and unit conversion functions:
UtcNow
UtcNowClockOffset
(the option that is faster in .NET 5.0+)DateTimeOffsetToClockOffset()
ClockOffsetToUtcDateTimeOffset()
TimeSpanToClockOffsetUnits()
ClockOffsetUnitsToTimeSpan()
- Commit
9376f4f
-ClockQuantizer
andTemporalContextDriver
:- Adds the heart of clock quantization, as prototyped in repo edevoogd/ClockQuantization
- More details about support class
TemporalContextDriver
are described in PR edevoogd/ClockQuantization#7
- Commit
aafd8b6
- adapt time-relatedCacheEntry
properties and backing storage- Adapt time-related
CacheEntry
properties and backing storage to leverageLazyClockOffsetSerialPosition
(clock offset plus serial position) andlong
(clock offset only)LastAccessed
(also introducing new propertyLastAccessedClockOffsetSerialPosition
)AbsoluteExpration
SlidingExpiration
- Half-hearted approach to leave as much in tact as possible, hopefully making it easier to review commit diffs
- Adapt time-related
- Commit
556a852
- optimize expiration scan trigger checks- Rewriting bookkeeping and checks in terms of clock offset (units)
- If possible, ride the wave of an existing exact
LazyClockOffsetSerialPosition
; if that doesn't exist, fall back to the most inexpensive clock access method:UtcNowClockOffset
- Commit
71fa1b0
- optimizeTryGetValue()
with interval-based expiration checks andLazyClockOffsetSerialPosition
- Introduction of interval-based entry expiration checks
- Most appropriate clock-offset-serial position determined based on entry type and temporal context; applied as late as possible (and only when needed)
- One downside for entries with sliding expiration: if an entry has not yet expired, we incur a so-called "advance operation" (allocating!) to ensure proper expiration tracking, as well as proper LRU ordering of subsequent entry retrievals
- Commit
f8e0a12
- optimizeSetEntry()
with interval-based expiration checks andLazyClockOffsetSerialPosition
- Upfront, obtain an exact clock-offset-serial position only for entries with sliding expiration; we incur a so-called "advance operation" (allocating!)
- Be opportunistic in determining absolute expiration if "relative to now" absolute expiration is at play; if possible, ride the wave of an existing exact
LazyClockOffsetSerialPosition
; if that doesn't exist, fall back to the most inexpensive clock access method:UtcNowClockOffset
- Leverage interval-based expiration checks introduced with commit
71fa1b0
- Commit
b803e28
- additionalLazyClockOffsetSerialPosition
capabilities- Public method
AssignExactClockOffsetSerialPosition()
to (re-)initialize an instance reference with an "exact" clock offset - Implement
IComparable<T>
- Public method
- Commit
5a25899
- rationalizeCacheEntry
time-based properties & expiration checksLastAccessed
property removed (now fully superseded byLastAccessedClockOffsetSerialPosition
)- Implement
AbsoluteExpirationClockOffset
as aninternal
field - Implement
LastAccessedClockOffsetSerialPosition
as aninternal
field - Implement
SlidingExpirationClockOffsetUnits
as aninternal
property (private set
) - Introduction of
CheckExpired(..., bool absoluteExpirationUndecided, bool slidingExpirationUndecided)
- Allowing for more optimal use from places where we already know the values of these flags - e.g., in
MemoryCache.SetEntry()
- Existing
CheckExpired()
method rewired onto new method
- Allowing for more optimal use from places where we already know the values of these flags - e.g., in
DateTimeOffset
-based expiration methods left in place for test purposes, but rewired onto theLazyClockOffsetSerialPosition
-based implementations
- Commit
7b5db3b
- optimizeMemoryCache
- Further optimize
SetEntry()
; amongst others, leverage the newly introducedCacheEntry.CheckExpired(..., bool absoluteExpirationUndecided, bool slidingExpirationUndecided)
method - Rewire
MemoryCache.ScanForExpiredItems()
onto theLazyClockOffsetSerialPosition
-based expiration check - Rewire
MemoryCache.Compact()
onto theLazyClockOffsetSerialPosition
-based expiration check - Rewire
MemoryCache.Compact().ExpirePriorityBucket()
onto theLazyClockOffsetSerialPosition
custom comparer
- Further optimize
- Commit
70d15a2
- add missing#nullable
pragmas