Вот вид обновленного & обновленного резюме какие могут быть самые полезные ответы & комментариев в этой теме + дополнительные контрольные отметки и варианты:
Первое, что f irst: Как отмечали другие в комментариях, в последние годы все изменилось, и с «современными» Windows (Win XP ++) и .NET, а в современном оборудовании нет или мало причин не использовать секундомер(). Для получения более подробной информации см. MSDN. Котировки:?
«Является ли точность QPC влияние изменения частоты процессора, вызванным управлением питанием или технологией Turbo Boost
No. Если процессора имеет инвариантную TSC, то QPC не влияют на этих сортах изменений. Если процессор не имеет инвариантного TSC, QPC вернется к аппаратным таймерам платформы, на которые не будут влиять изменения частоты процессора или технология Turbo Boost.
QPC надежно работает на многопроцессорных системах , многоядерная система и системы с гиперпотоком?
Да
Как определить и подтвердить, что QPC работает на моей машине?
Вам не нужно выполнять такие проверки.
Какие процессоры имеют неинвариантные TSC? [..Read дальше ..] "
Но если вам не нужна точность Секундомер() или, по крайней мере, хотят точно знать о производительности Секундомер (статический vs. основе экземпляров) и другие возможные варианты, продолжайте читать:
Я взял на себя эталон выше из cskwg и расширил код для большего количества вариантов. Я измерил несколько лет i7 4700 MQ и C# 7 с VS 2017 (чтобы быть более точный, скомпилированный с .NET 4.5.2, несмотря на бинарные литералы, это C# 6 (используется для этого: строковые литералы и «использование статического»). Особенно производительность секундомера() кажется улучшенной по сравнению с упомянутым эталоном.
Это пример результатов 10 миллионов повторений в цикле, как всегда, абсолютные значения не важны, но даже относительные значения могут отличаться от других аппаратных средств:
32 бит, режима выпуска без оптимизации :
Измеренные: GetTickCount64() [мс]: 275
Измерено: Environment.TickCount [мс]: 45
Измеренные: DateTime.UtcNow.Ticks [мс]:
Измеренный: Секундомер: .ElapsedTicks [мс]: 277
Измеренные: Секундомер: .ElapsedMilliseconds [мс]: 548
Измеренные: статическое Stopwatch.GetTimestamp [мс]: 193
Измерены: Секундомер + преобразование в DateTime [мс ]: 551
Сравните с DateTime.Now.Ticks [мс]:
32 битных, режим выпуска, оптимизированная:
Измеренные: GetTickCount64() [мс]: 198
Измерено: Environment.TickCount [мс]: 39
Измеренные: DateTime.UtcNow.Ticks [мс]: 66
Измеренный (!): Секундомер: .ElapsedTicks [мс]: 175
Измеренные: секундомер: .ElapsedMilliseconds [мс]:
Измеренные: статические Stopwatch.GetTimestamp [мс]: 175
Измеренные: секундомер + преобразование в DateTime [мс]:
Com Parè, что с DateTime.Now.Ticks [мс]:
64 бит, режим выпуска без оптимизации:
Измеренные: GetTickCount64() [мс]: 205
Измеренный : Environment.TickCount [мс]: 39
Измеренные: DateTime.UtcNow.Ticks [мс]:
Измеренные: секундомер: .ElapsedTicks [мс]: 209
Измеренные: Секундомер: .ElapsedMilliseconds [мс]: 285
Измеренные: статическое Stopwatch.GetTimestamp [мс]: 187
Измерены: Секундомер + преобразование в DateTime [мс]: 319
Сравните с DateTime.Now.Ticks [мс]: 3040
64 бит, режим выпуска, оптимизирован:
Измерено: GetTickCount64() [мс]: 148
Измерено: окружающая среда.TickCount [мс]: 31 (он все еще стоит?)
Измеренные: DateTime.UtcNow.Ticks [мс]: 76
Измеренные (!): Секундомер: .ElapsedTicks [мс]: 178
Измеренные: секундомер: .ElapsedMilliseconds [мс]: 226
Измерено: статические Stopwatch.GetTimestamp [мс]: 175
Измерено: секундомер + преобразование в DateTime [мс]: 246
Сравните с DateTime.Now.Ticks [мс ]: 3020
Может быть очень интересно, что , создавая значение DateTime для печати времени секундомера, похоже, почти не стоит. Интересным в более академичном, чем практический образом, является то, что статический секундомер немного быстрее (как и ожидалось). Некоторые точки оптимизации весьма интересны. Например, я не могу объяснить, почему Stopwatch.ElapsedMilliseconds только с 32-битным настолько медленным, по сравнению с другими вариантами, например, статическим. Это и DateTime.Now более чем удваивают их скорость с 64 бит.
Вы можете видеть: Только для миллионов исполнений время Секундомера начинает иметь значение. Если это действительно так (но будьте осторожны с микро-оптимизацией слишком рано), может быть интересно, что с GetTickCount64(), но особенно с DateTime.UtcNow, у вас есть 64-разрядный (длинный) таймер с меньшей точностью, чем секундомер, но быстрее, так что вам не нужно возиться с 32-разрядной «уродливой» средой Environment.TickCount.
Как и ожидалось, DateTime.Now на сегодняшний день является самым медленным из всех.
Если вы запустите его, код получит также текущую точность секундомера и многое другое.
Вот полный тест-код:
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using static System.Environment;
[...]
[DllImport("kernel32.dll") ]
public static extern UInt64 GetTickCount64(); // Retrieves a 64bit value containing ticks since system start
static void Main(string[] args)
{
const int max = 10_000_000;
const int n = 3;
Stopwatch sw;
// Following Process&Thread lines according to tips by Thomas Maierhofer: https://codeproject.com/KB/testing/stopwatch-measure-precise.aspx
// But this somewhat contradicts to assertions by MS in: https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396#Does_QPC_reliably_work_on_multi-processor_systems__multi-core_system__and_________systems_with_hyper-threading
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1); // Use only the first core
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
Thread.CurrentThread.Priority = ThreadPriority.Highest;
Thread.Sleep(2); // warmup
Console.WriteLine($"Repeating measurement {n} times in loop of {max:N0}:{NewLine}");
for (int j = 0; j < n; j++)
{
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < max; i++)
{
var tickCount = GetTickCount64();
}
sw.Stop();
Console.WriteLine($"Measured: GetTickCount64() [ms]: {sw.ElapsedMilliseconds}");
//
//
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < max; i++)
{
var tickCount = Environment.TickCount; // only int capacity, enough for a bit more than 24 days
}
sw.Stop();
Console.WriteLine($"Measured: Environment.TickCount [ms]: {sw.ElapsedMilliseconds}");
//
//
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < max; i++)
{
var a = DateTime.UtcNow.Ticks;
}
sw.Stop();
Console.WriteLine($"Measured: DateTime.UtcNow.Ticks [ms]: {sw.ElapsedMilliseconds}");
//
//
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < max; i++)
{
var a = sw.ElapsedMilliseconds;
}
sw.Stop();
Console.WriteLine($"Measured: Stopwatch: .ElapsedMilliseconds [ms]: {sw.ElapsedMilliseconds}");
//
//
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < max; i++)
{
var a = Stopwatch.GetTimestamp();
}
sw.Stop();
Console.WriteLine($"Measured: static Stopwatch.GetTimestamp [ms]: {sw.ElapsedMilliseconds}");
//
//
DateTime dt=DateTime.MinValue; // just init
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < max; i++)
{
var a = new DateTime(sw.Elapsed.Ticks); // using variable dt here seems to make nearly no difference
}
sw.Stop();
//Console.WriteLine($"Measured: Stopwatch+conversion to DateTime [s] with millisecs: {dt:s.fff}");
Console.WriteLine($"Measured: Stopwatch+conversion to DateTime [ms]: {sw.ElapsedMilliseconds}");
Console.WriteLine();
}
//
//
sw = new Stopwatch();
var tickCounterStart = Environment.TickCount;
sw.Start();
for (int i = 0; i < max/10; i++)
{
var a = DateTime.Now.Ticks;
}
sw.Stop();
var tickCounter = Environment.TickCount - tickCounterStart;
Console.WriteLine($"Compare that with DateTime.Now.Ticks [ms]: {sw.ElapsedMilliseconds*10}");
Console.WriteLine($"{NewLine}General Stopwatch information:");
if (Stopwatch.IsHighResolution)
Console.WriteLine("- Using high-resolution performance counter for Stopwatch class.");
else
Console.WriteLine("- Using high-resolution performance counter for Stopwatch class.");
double freq = (double)Stopwatch.Frequency;
double ticksPerMicroSec = freq/(1000d*1000d) ; // microsecond resolution: 1 million ticks per sec
Console.WriteLine($"- Stopwatch accuracy- ticks per microsecond (1000 ms): {ticksPerMicroSec:N1}");
Console.WriteLine(" (Max. tick resolution normally is 100 nanoseconds, this is 10 ticks/microsecond.)");
DateTime maxTimeForTickCountInteger= new DateTime(Int32.MaxValue*10_000L); // tickCount means millisec -> there are 10.000 milliseconds in 100 nanoseconds, which is the tick resolution in .NET, e.g. used for TimeSpan
Console.WriteLine($"- Approximated capacity (maxtime) of TickCount [dd:hh:mm:ss] {maxTimeForTickCountInteger:dd:HH:mm:ss}");
// this conversion from seems not really accurate, it will be between 24-25 days.
Console.WriteLine($"{NewLine}Done.");
while (Console.KeyAvailable)
Console.ReadKey(false);
Console.ReadKey();
}
Как неродственного в сторону, если вы используете DateTime для Дата, связанные с расчетами по математике, всегда использовать DateTime. UtcNow as DateTime.Now восприимчив к летнему времени ... ваши расчеты могут быть отключены на час или, что еще хуже, отрицательные числа. – 2009-07-03 07:04:51
@Scott: Думаю, стоит упомянуть: даже с помощью `UtcNow` существует проблема запланированных синхронизаций NTP: не так редко, системное время изменяется на 10 секунд после этих обновлений (на моем ПК). – Groo 2011-09-30 12:13:29
Математика на самом деле не такая сложная ... `int duration = unchecked ((int) ((uint) start.tickCount - (uint));` ... даст вам правильный ответ независимо от опрокидывания. (Вы можете в идеале пропустить бросок до «int», если он вам не нужен.) – AnorZaken 2015-10-11 02:18:15