HighPrecisionTimeStamps 0.1.0

It is well known that DateTime.Now is often used inappropriately.  For example, it may be used together with TimeSpan to produce a task's timeout point or subtracted from another DateTime to calculate a duration.  This can cause subtle bugs because DateTime is not monotonic: the system clock can change, making the result of the subtraction inaccurate -- potentially causing a premature timeout or an infinite loop.  Yet, DateTime is an incredibly convenient and widely used value type in .NET code and is especially useful when printed in ISO-8601 format (with the "O" format specifier).  

With the "O" specifier, you can resolution down to tenths of a microsecond, which is nice.  Until you learn that the resolution of the system clock is usually more coarse than several *milliseconds*, making the additional decimal places misleading garbage values. For calculating durations (time between events), it is better to use a high-resolution and monotonic clock like that provided by System.Diagnostics.Stopwatch: on most computers it is far more **accurate** than DateTime.Now even though, seemingly paradoxically, on a few systems, its *resolution* is lower than that of DateTime.  Also, unsurprisingly, Stopwatch does not provide values that correlate to times of day: while it is appropriate for calculating durations, it is inappropriate for timestamping against a readable date and time.  
 
This library provides timestamps (both as DateTime and as analogous value types it defines) that use the Stopwatch (and your system's high peformance event counter) as its clock, but returns values as DateTimes or an analog thereto so that these values can be used for a mixed purpose of timestamping and providing a meaningful way to calculate time elapsed between events or to calculate how long to perform a programmatic task.

Install-Package HighPrecisionTimeStamps -Version 0.1.0
dotnet add package HighPrecisionTimeStamps --version 0.1.0
<PackageReference Include="HighPrecisionTimeStamps" Version="0.1.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add HighPrecisionTimeStamps --version 0.1.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: HighPrecisionTimeStamps, 0.1.0"
#r directive can be used in F# Interactive, C# scripting and .NET Interactive. Copy this into the interactive tool or source code of the script to reference the package.
// Install HighPrecisionTimeStamps as a Cake Addin
#addin nuget:?package=HighPrecisionTimeStamps&version=0.1.0

// Install HighPrecisionTimeStamps as a Cake Tool
#tool nuget:?package=HighPrecisionTimeStamps&version=0.1.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

High Precision Timestamps

Copyright © 2020, CJM Screws, LLC

A utility providing convenient and appropriate alternatives to DateTime.Now.

It is well known that DateTime.Now is often used inappropriately. For example, it may be used together with TimeSpan to produce a task's timeout point or subtracted from another DateTime to calculate a duration. This can cause subtle bugs because DateTime is not monotonic: the system clock can change, making the result of the subtraction inaccurate -- potentially causing a premature timeout or an infinite loop. Yet, DateTime is an incredibly convenient and widely used value type in .NET code and is especially useful when printed in ISO-8601 format (with the "O" format specifier).

With the "O" specifier, you can resolution down to tenths of a microsecond, which is nice. Until you learn that the resolution of the system clock is usually more coarse than several milliseconds, making the additional decimal places misleading garbage values. For calculating durations (time between events), it is better to use a high-resolution and monotonic clock like that provided by System.Diagnostics.Stopwatch: on most computers it is far more accurate than DateTime.Now even though, seemingly paradoxically, on a few systems, its resolution is lower than that of DateTime. Also, unsurprisingly, Stopwatch does not provide values that correlate to times of day: while it is appropriate for calculating durations, it is inappropriate for timestamping against a readable date and time.

This library provides timestamps (both as DateTime and as analogous value types it defines) that use the Stopwatch (and your system's high peformance event counter) as its clock, but returns values as DateTimes or an analog thereto so that these values can be used for a mixed purpose of timestamping and providing a meaningful way to calculate time elapsed between events.

It provides Monotonic timestamps and High Resolution timestamps.

High Resolution Timestamps

These timestamps are expressed as DateTime values and are derived from Stopwatch. They are calibrated (correlating a reference tick value of the Stopwatch to a reference time value of the system clock) on a per thread basis and have a calibration window that expires. These are suitable for logging times (in a way meaningful to humans) and can be used to measure the time elapsed between events on a single thread within one calibration window. A calibration window by default lasts for fifteen minutes. Eventually, there will be drift between the system clock and the Stopwatch, making recalibration necessary. Nevertheless, for the resolution provided by Stopwatch, fifteen minutes should be a sufficient period for the intended use-case of these timestamps. Also, you can always manually trigger a calibration.

Monotonic Timestamps

These use the same source (Stopwatch) for their clock, but calibration happens exactly once per process and is the same across all threads. Thus, you can accurately log the time of events across multiple threads and have meaningful data to compare when events happen. Also, because calibration happens once these values are safe to use to calculate a timeout period, how long to perform a task, etc without the possibility that a change to the system clock can cause a bug. Like the High Resolution Timestamps, their fractional seconds are meaningful on every system I have tested. These are essentially dual-use values: they can be used to log timestamps and to calculate durations or time that your application should spend doing a task before quitting or timing out, etc. The monotonic clock provided returns a value type provided by this library rather than DateTime, though the value type is conveniently convertible into a DateTime. This choice was made because the Stopwatch's frequency can vary between systems and these stamps are intended to be used for calculating and measuring durations in addition to logging: it was desirable not to need to calculate a conversion to and from DateTime/TimeSpan scale when obtaining a stamp or performing a duration calculation. For a similar reason, there is a Duration value type that is to the monotonic stamp what System.TimeSpan is to DateTime: a duration value with a matching frequency.

Example Code

An example code project (available at ExampleCode) is available and used to provide a tour of the functionality and its recommended use-cases. All of the example code below can be found therein. For more elaboration, please consult the full Readme.md at Readme.md as it is too long to be displayed on NuGet.

Status of Testing / Project

I have used this library to good effect in many projects. It requires more unit tests and there will doubtless remain bugs. It is, however, essentially feature complete and has been unit tested on four different systems:

  1. A Windows 10 System with a Stopwatch frequency of 10,000,000 ticks per second.
  2. An Ubuntu 20.04 system with a Stopwatch frequency of 1,000,000,000 ticks per second.
  3. An Amazon Linux 2 (based on CentOS) system with a Stopwatch frequency of 1,000,000,000 ticks per second.
  4. An Amazon Workspaces Window Server (Windows 10 based Windows server) with (most vexingly) a stopwatch frequency of 2,441,366 ticks per second.

I have decided to make this version a release despite knowing that there remain bugs (but having used the project extensively myself) and a need for additional unit tests because I believe it is in a useful, though imperfect, state. Please inform me of any bugs found on the issues page or via email: I intend to fix bugs. I consider this project more or less feature complete and do not imagine any additional extensive features being added by me. If you would like to add features, I am happy to review any pull-request or issue.

High Precision Timestamps

Copyright © 2020, CJM Screws, LLC

A utility providing convenient and appropriate alternatives to DateTime.Now.

It is well known that DateTime.Now is often used inappropriately. For example, it may be used together with TimeSpan to produce a task's timeout point or subtracted from another DateTime to calculate a duration. This can cause subtle bugs because DateTime is not monotonic: the system clock can change, making the result of the subtraction inaccurate -- potentially causing a premature timeout or an infinite loop. Yet, DateTime is an incredibly convenient and widely used value type in .NET code and is especially useful when printed in ISO-8601 format (with the "O" format specifier).

With the "O" specifier, you can resolution down to tenths of a microsecond, which is nice. Until you learn that the resolution of the system clock is usually more coarse than several milliseconds, making the additional decimal places misleading garbage values. For calculating durations (time between events), it is better to use a high-resolution and monotonic clock like that provided by System.Diagnostics.Stopwatch: on most computers it is far more accurate than DateTime.Now even though, seemingly paradoxically, on a few systems, its resolution is lower than that of DateTime. Also, unsurprisingly, Stopwatch does not provide values that correlate to times of day: while it is appropriate for calculating durations, it is inappropriate for timestamping against a readable date and time.

This library provides timestamps (both as DateTime and as analogous value types it defines) that use the Stopwatch (and your system's high peformance event counter) as its clock, but returns values as DateTimes or an analog thereto so that these values can be used for a mixed purpose of timestamping and providing a meaningful way to calculate time elapsed between events.

It provides Monotonic timestamps and High Resolution timestamps.

High Resolution Timestamps

These timestamps are expressed as DateTime values and are derived from Stopwatch. They are calibrated (correlating a reference tick value of the Stopwatch to a reference time value of the system clock) on a per thread basis and have a calibration window that expires. These are suitable for logging times (in a way meaningful to humans) and can be used to measure the time elapsed between events on a single thread within one calibration window. A calibration window by default lasts for fifteen minutes. Eventually, there will be drift between the system clock and the Stopwatch, making recalibration necessary. Nevertheless, for the resolution provided by Stopwatch, fifteen minutes should be a sufficient period for the intended use-case of these timestamps. Also, you can always manually trigger a calibration.

Monotonic Timestamps

These use the same source (Stopwatch) for their clock, but calibration happens exactly once per process and is the same across all threads. Thus, you can accurately log the time of events across multiple threads and have meaningful data to compare when events happen. Also, because calibration happens once these values are safe to use to calculate a timeout period, how long to perform a task, etc without the possibility that a change to the system clock can cause a bug. Like the High Resolution Timestamps, their fractional seconds are meaningful on every system I have tested. These are essentially dual-use values: they can be used to log timestamps and to calculate durations or time that your application should spend doing a task before quitting or timing out, etc. The monotonic clock provided returns a value type provided by this library rather than DateTime, though the value type is conveniently convertible into a DateTime. This choice was made because the Stopwatch's frequency can vary between systems and these stamps are intended to be used for calculating and measuring durations in addition to logging: it was desirable not to need to calculate a conversion to and from DateTime/TimeSpan scale when obtaining a stamp or performing a duration calculation. For a similar reason, there is a Duration value type that is to the monotonic stamp what System.TimeSpan is to DateTime: a duration value with a matching frequency.

Example Code

An example code project (available at ExampleCode) is available and used to provide a tour of the functionality and its recommended use-cases. All of the example code below can be found therein. For more elaboration, please consult the full Readme.md at Readme.md as it is too long to be displayed on NuGet.

Status of Testing / Project

I have used this library to good effect in many projects. It requires more unit tests and there will doubtless remain bugs. It is, however, essentially feature complete and has been unit tested on four different systems:

  1. A Windows 10 System with a Stopwatch frequency of 10,000,000 ticks per second.
  2. An Ubuntu 20.04 system with a Stopwatch frequency of 1,000,000,000 ticks per second.
  3. An Amazon Linux 2 (based on CentOS) system with a Stopwatch frequency of 1,000,000,000 ticks per second.
  4. An Amazon Workspaces Window Server (Windows 10 based Windows server) with (most vexingly) a stopwatch frequency of 2,441,366 ticks per second.

I have decided to make this version a release despite knowing that there remain bugs (but having used the project extensively myself) and a need for additional unit tests because I believe it is in a useful, though imperfect, state. Please inform me of any bugs found on the issues page or via email: I intend to fix bugs. I consider this project more or less feature complete and do not imagine any additional extensive features being added by me. If you would like to add features, I am happy to review any pull-request or issue.

Release Notes

Initial (non-beta) Release.  
Update Readme.md.
Update Project description.
Create ExampleCode project.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version History

Version Downloads Last updated
0.1.0 186 12/13/2020
0.0.5.4-beta 153 12/6/2020
0.0.5.1-beta 127 11/27/2020
0.0.4-beta 130 11/18/2020
0.0.3-beta 189 11/15/2020
0.0.2-alpha 98 11/14/2020
0.0.1-alpha 205 1/25/2020