Search code examples
.netmultiprocessingclockmulticore

Stopwatch.GetTimestamp() alternative that is safe on multiple processors


I need a clock like Stopwatch.GetTimestamp() that

  1. has little overhead when acquiring the value
  2. is accurate to at least 1 millisecond (without decreasing the os wide timer interval)
  3. does not have to be pegged to the actual time of day (like e.g. DateTime.Now is)
  4. increases monotonically, although not necessarily strictly (calling it multiple times in the same millisecond with 1ms accuracy will produce the same value)
  5. maintains all the above run concurrently on multiple cores and processors

Stopwatch seems to fail to provide the last of these properties:

On a multiprocessor computer, it does not matter which processor the thread runs on. However, because of bugs in the BIOS or the Hardware Abstraction Layer (HAL), you can get different timing results on different processors. To specify processor affinity for a thread, use the ProcessThread.ProcessorAffinity method.

To enable real concurrency, for obvious reasons I cannot pin all threads to a single processor.

Any alternative I can use in .net? Or is the above warning outdated / restricted to some rare models (my production environment is unlikely to house)?

Edit:

Here's my main concern: I don't mind values being off by one (e.g. millisecond) or so on different processors, but they need to be always be more or less the same no matter what processor they are retrieved from.


Solution

  • MS actually has an in-depth article on the counters underlying Stopwatch. Acquiring high-resolution time stamps

    A relevant excerpt:


    In general, the performance counter results are consistent across all processors in multi-core and multi-processor systems, even when measured on different threads or processes. Here are some exceptions to this rule:

    • Pre-Windows Vista operating systems that run on certain processors might violate this consistency because of one of these reasons:
      • The hardware processors have a non-invariant TSC and the BIOS doesn't indicate this condition correctly.
      • The TSC synchronization algorithm that was used wasn't suitable for systems with large numbers of processors.
    • When you compare performance counter results that are acquired from different threads, consider values that differ by ± 1 tick to have an ambiguous ordering. If the time stamps are taken from the same thread, this ± 1 tick uncertainty doesn't apply. In this context, the term tick refers to a period of time equal to 1 ÷ (the frequency of the performance counter obtained from QueryPerformanceFrequency).