Сетевой дневник одного программиста

Персональный блог Константина Огородова

Измерение времени на платформе .Net

Периодически возникает необходимость замера промежутка времени в процессе работы приложения или во время тестирования, как уже было описано в статье про BenchmarkDotNet. Платформа .Net позволяет делать замеры различными способами. Я решил разобраться для каких ситуаций какой способ подходит лучше всего.. Для начала набросал приложение для замеров скорости получения текущего времени:

using System.Diagnostics;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

BenchmarkRunner.Run(typeof(MyClass));

public class MyClass
{
    [Benchmark]
    public DateTime DateTime_UtcNow() => DateTime.UtcNow;
    
    [Benchmark]
    public DateTime DateTime_Now() => DateTime.Now;

    [Benchmark]
    public DateTimeOffset DateTimeOffset_UtcNow() => DateTimeOffset.UtcNow;
    
    [Benchmark]
    public DateTimeOffset DateTimeOffset_Now() => DateTimeOffset.Now;

    [Benchmark]
    public int Environment_TickCount() => Environment.TickCount;

    [Benchmark(Baseline = true)]
    public long Environment_TickCount64() => Environment.TickCount64;

    [Benchmark]
    public long Stopwatch_GetTimestamp() => Stopwatch.GetTimestamp();
}

И получил следующие результаты:

MethodMeanErrorStdDevRatioRatioSD
DateTime_UtcNow28.025 ns0.1514 ns0.1416 ns19.400.17
DateTime_Now40.581 ns0.8331 ns0.8555 ns27.810.40
DateTimeOffset_UtcNow34.994 ns0.2892 ns0.2705 ns24.170.32
DateTimeOffset_Now67.920 ns1.3585 ns1.5100 ns46.941.32
Environment_TickCount1.304 ns0.0352 ns0.0294 ns0.900.02
Environment_TickCount641.446 ns0.0137 ns0.0115 ns1.000.00
Stopwatch_GetTimestamp19.771 ns0.0938 ns0.0877 ns13.670.14
  • Environment.TickCount даёт максимальную производительность — всего 1,3 наносекунды. Если учесть, что ядра моего Ryzen 7 4800H в без нагрузки работают на частоте 1,3 GHz, то это выполнение за 1-2 такта процессора в зависимости от частоты. Всё потому, что TickCount выдаёт время прошедшее с момента загрузки системы, т.е. это просто счётчик. А теперь о плохом: время не в Tick’ах, а в миллисекундах. Это означает, что с помощью этого метода можно измерять события длящиеся десятые, сотые и тысячные доли секунды, как например запросы к различным внешним источникам данных, но более скоротечные события измерить не получиться. Отмечу также, что значение метода отсчитывается от 0 до Int32.MaxValue примерно за 24,9 дня, затем значение переключается на Int32.MinValue и увеличивается до нуля ещё за 24,9 дня. Однако разницу в значениях можно считать без плясок с бубном простым hightestValue — lowestValue за счёт переполнения.
  • Environment.TickCount64 аналогично предыдущему, только возвращает Int64 вместо Int32, а значит полного обращения придётся ждать немногим меньше 300-х сот миллионов лет. Минус тот же — миллисекунды. Иногда скоростные показатели почти такие же как и у предыдущего метода.
  • Stopwatch.GetTimestamp возвращает значение счетчика тактов базового механизма таймера, т.е. кол-во «попугаев» от некоторого события (загрузка?). В тактах (Ticks). Напомню, что в одном такте 10 000 миллисекунд. Точность значительно выше, но и отрабатывает метод значительно медленней чем предыдущие два. И хотя в количественном выражении это в 15 раз медленнее — мы говорим о 20 наносекундах, т.е. 20 * 10-9, в то время как один такт(Tick) = 10 * 10-6.
  • DateTime.UtcNow самый быстрой из предоставленных вариантов получения текущего времени.В 20 раз медленнее TickCount, но всего лишь 30 наносекунд в абсолютном выражении.

Выводы: если очень хочется максимального быстродействия при невысокой точности или приходится оперировать методами принимающими миллисекунды — можно заморочиться с Environment.TickCount или Environment.TickCount64. В остальных случаях использование DateTime или DateTimeOffset с методами Now или UtcNow более чем оправдано.

Измерение времени на платформе .Net

Один комментарий к “Измерение времени на платформе .Net

  1. Очень круто всё описано, делайте ещё материалы на эту тему. Мне приходилось очень долго разбираться со всем этим, теперь просто хожу сюда как в домашнюю библиотеку с пометками

Добавить комментарий для Василий Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Пролистать наверх