Как Измерить Прошедшее Время без Аллокаций
Есть много случаев, когда вам нужно вычислить время выполнения метода. Классический способ - использовать класс Stopwatch. Это ссылочный тип, поэтому его создание может увеличить нагрузку на сборщик мусора. В случае однопоточного приложения вы можете повторно использовать экземпляр, чтобы избежать создания большого количества экземпляров. Однако в многопоточном приложении может быть сложнее повторно использовать экземпляры. Вы можете использовать поле
[ThreadStatic] или ObjectPool<Stopwatch>, но и за это придется заплатить производительностью.Если вам не нужны все функции
Stopwatch, такие как остановка и перезапуск секундомера, вы можете создать структуру, которая предоставляет только минимум функционала. Таким образом, можно легко замерить время без каких-либо аллокаций. Идея состоит в том, чтобы использовать значение Stopwatch.GetTimestamp() при инициализации структуры и при вычислении прошедшего времени. Затем вычислить разницу, чтобы получить искомое время.// За основу взят код отсюда: https://github.com/dotnet/runtime/blob/26b6e4ea97a627ab800362b2c10f32ebecea041d/src/libraries/Common/src/Extensions/ValueStopwatch/ValueStopwatch.csИспользование:
using System.Diagnostics;
public readonly struct ValueStopwatch
{
private static readonly double _timeToTicks =
TimeSpan.TicksPerSecond / (double)Stopwatch.Frequency;
private readonly long _startTimestamp;
private ValueStopwatch(long startTimestamp)
=> _startTimestamp = startTimestamp;
public static ValueStopwatch StartNew()
=> new ValueStopwatch(GetTimestamp());
public static long GetTimestamp()
=> Stopwatch.GetTimestamp();
public static TimeSpan
GetElapsedTime(long start, long end) {
var delta = end - start;
var ticks = (long)(_timeToTicks * delta);
return new TimeSpan(ticks);
}
public TimeSpan GetElapsedTime()
=> GetElapsedTime(_startTimestamp, GetTimestamp());
}
var stopwatch = ValueStopwatch.StartNew();Источник: https://www.meziantou.net/how-to-measure-elapsed-time-without-allocating-a-stopwatch.htm
// измеряемый код
Console.WriteLine(stopwatch.GetElapsedTime());