-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Problem: Many BCL components use DateTime.UtcNow to compute timeouts and time deltas. When you run a "Find Usages" on DateTime.UtcNow in .NET Framework assemblies a lot of usage sites come to light. For example, in ADO.NET, transactions, caches, WebRequest, remoting, WCF, SignalR, security.
All of these usages are bugs because the current system time can change significantly forwards and backwards at any time. This means that in case the system clock is changed many .NET components will spuriously fail.
Common symptoms would be timeouts firing to early or too late (possibly never). Perf counters also might show too high or negative values.
Sample scenario:
- The system clock spuriously jumps forward due to misconfiguration by years.
- A cache item is added.
- The clock is fixed.
Then, the cache item will essentially stay around forever if eviction is based on DateTime.UtcNow. I believe this bug exists in the BCL.
User code also has the same problems.
Solution: Add some kind of monotonic clock to the BCL. The main property of such a clock would be that its time advances linearly. It should never jump when the system clock changes. It should not exhibit split second jumps. It should behave reasonably in case the system sleeps or hibernates or in case the VM is paused.
This monotonic clock class should be fast and convenient to use so that it is a no-brainer to switch all DateTime.UtcNow usages over to the new model.
Maybe we can add Environment.TickCount64 as well. Environment.TickCount64 alone would not be good enough because it is awkward to use.
I'm not sure if Stopwatch would cover all these requirements. It is a reference type which might be too heavy for hot code path in the BCL.
Maybe we can add a new value type that is made exactly for this purpose. A sketch:
struct MonotonicTime {
long Ticks;
MonotonicTime operator + (MonotonicTime, TimeSpan);
TimeSpan operator - (MonotonicTime, MonotonicTime);
bool IsNegative;
static MonotonicTime Current;
...
}
To summarize, I request:
- The framework timeouts should be fixed. (The TPL bugs apparently are already fixed. I reported these a while ago.)
- Add
Environment.TickCount64. - Provide a convenient, high-performance monotonic clock.