2012-03-20 5 views
4

Мне нужно заменить секундомер, чтобы избежать использования геттеров для его свойств. Я собираюсь реализовать его с помощью QueryPerformanceCounter. Мне нужны только галочки ничего больше.Как получить тики от QueryPerformanceCounter в C#?

Может ли кто-нибудь предоставить код-снэп, чтобы получить правильные отметки (1/10000 мс) или любое другое небольшое, но стабильное значение.

Обратите внимание: мой сервер устанавливает размерность часов до 0,5 мс (не уверен, влияет ли это на QueryPerformanceCounter), но только для вас.

Также обратите внимание - мне не нужен таймер. Мне нужно только измерить временные интервалы между частями кода.

EDIT:, чтобы избежать путаницы, я действительно хочу знать, что lpPerformanceCount в QueryPerformanceCounter (задолго lpPerformanceCount);

+0

Если вы измерения временных интервалов между частями кода, как это отличается от таймера? В любом случае вы можете использовать interop для вызова QueryPerformanceCounter Kernel32.dll самостоятельно. – Matthew

+0

Не могли бы вы объяснить, почему вы хотите это сделать, «чтобы избежать использования геттеров для его свойств» не вызывает большой причины. Проблема с QueryPerformanceCounter заключается в том, что она возвращает значение в подсчетах, а количество отсчетов в секунду является переменной в зависимости от архитектуры и может быть найдено с помощью QueryPerformanceFrequency. С секундомером вы получаете значение, которое является фактической единицей времени. –

+0

@BenRobinson - это имеет для меня большой смысл, иначе я не буду спрашивать. –

ответ

5
[DllImport("Kernel32.dll")] 
private static extern bool QueryPerformanceCounter(out long lpPerformanceCount); 

[DllImport("Kernel32.dll")] 
private static extern bool QueryPerformanceFrequency(out long lpFrequency); 

Взятые из http://www.codeproject.com/Articles/2635/High-Performance-Timer-in-C

Старые, но оно должно работать

EDIT: Внутренности StopWatch фактически используют QueryPerformanceCounter, поэтому с помощью управляемого кода должны обеспечивать одинаковые результаты, с лучшей совместимостью.

+0

Да, я знаю. из всего, что я нашел в Интернете, включая код, к которому вы обращаетесь - он показывает секунды и требует деления на «частоту» ... Моя точка зрения на самом деле заключается в том, чтобы выяснить, каково значение, которое оно возвращает, и как я могу его использовать без частоты. Я готов сделать его зависимым от одной конкретной установки без переносимости (не заботясь). Просто нужно понять, что такое lpPerformanceCount. –

+0

'lpPerformanceCount' - количество тиков (различно для каждой системы),' lpFrequency' - количество тиков в секунду. Чтобы получить фактическое время, вы разделите 'lpPerformanceCount' на' lpFrequency', чтобы получить сумму в секундах. 'qpc (out time1); ...; qpc (out time2); long diff_in_ms = (time2-time1) * 1000/frequency' – Matthew

+0

Чтобы уточнить, я имею в виду, что частота различна для каждой системы. – Matthew

1

НЕ используйте StopWatch для определения времени высокого разрешения без тестирования. Прошло несколько лет с тех пор, как я протестировал его, но в то время он дал разрешение по умолчанию для окон. Вы можете сказать, потому что действительно, очень быстрые вещи будут занимать 0 или 10-15 миллисекунд, если оно использует разрешение по умолчанию для Windows (разрешение по умолчанию на самом деле является разрешением переключателей контекста потока, по-видимому, часы по умолчанию обновляются по каждому контексту переключатель, который составляет примерно каждые 10-15 миллисекунд).

+2

Лучший способ проверить, что использовать ['Stopwatch.IsHighResolution'] (https://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.ishighresolution% 28v = vs.110% 29.aspx) – torvin

0

НЕ ПРЯМОЙ ОТВЕТ (но потенциально необходимая информация поддержки следующим образом):

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

Во-первых, учтите временные издержки компилятора «точно в срок» (jit), который происходит во время выполнения. Любой код, где вы берете начальную отметку времени, затем делаете , а затем берете окончательную метку времени для вычитания t2-t1 для дельта для любой функции внутри вещей, если вы включаете любые функции, которые вы еще не вызывали во время текущий процесс, то при первом вызове вы заплатите за служебные данные jit, чтобы скомпилировать байт-код в собственный код. В этом случае стоимость не отражает фактическую стоимость критического кода производительности во время исполнения, которая, по-видимому, часто называется кодом, который часто называется, и все же стоимость jit оплачивается только один раз (при первом вызове этого процесса). Поэтому вызовите временный код несколько раз, выбросьте первое время и возьмите среднее.

Кроме того, остерегайтесь затрат времени на сборку мусора. Если вы просто играете, то может быть возможно и интересно провести сравнение кода, который строго избегает выделения новых объектов. Но иногда это непросто, особенно когда вы вызываете функции, реализации которых вы не можете изменить. Кроме того, я должен предоставить вам, что накладные расходы реального мира на производственный код не могут избежать накладных расходов на сборку мусора, поэтому получение реалистичной цифры должно включать в себя эти накладные расходы. Тем не менее, если ваш материал содержит код, который выделяет новые объекты, тогда он может начать сборщик мусора, который будет дорогостоящим, поэтому подготовьтесь к некоторым потенциальным выбросам, которые вы, возможно, захотите выбросить.

Во-вторых, хорошие ответы предоставили код для объявления внешних функций для вызова из системных dll, и это здорово. Правильное использование этих подписи в общем случае может быть неприятностью, поэтому я хотел бы упомянуть о большом ресурсе для этого: pinvoke.net. Поиск QueryPerformanceCounter дал мне подписи, которые вырезали и отклеили от уже предоставленного ответа, и это отличный ресурс для любых системных вызовов, которые вы хотите сделать.

http://pinvoke.net/search.aspx?search=QueryPerformanceCounter&namespace=[All]

+1

, возможно, это полезно для людей, которые не являются профессионалами .net. производительность точки измерения - это только измерение производительности. если ваш код ждет GC - он должен быть отражен в статистике. Это не научный проект. Если на практике ваше приложение попадает в GC, когда оно не должно - это проблема, которая должна быть a) Discoverd (с использованием перформансов I спрашивал) b) обратился к разработчику (разная история). спасибо за идею об использовании объектов ядра. но я не думаю, что это хорошая идея, переход в режим ядра требует времени и бросает вызов сути того, что я спросил –

-1
I don't remember from where I copied it, but this code works well for me: 

     public class QueryPerfCounter 
    { 
     [DllImport("KERNEL32")] 
     private static extern bool QueryPerformanceCounter(out long lpPerformanceCount); 
     [DllImport("Kernel32.dll")] 
     private static extern bool QueryPerformanceFrequency(out long lpFrequency); 
    private long start; 
    private long stop; 
    private long frequency; 
    double multiplier = 1.0e6; // usecs/sec 

    public QueryPerfCounter() 
    { 
     if (QueryPerformanceFrequency(out frequency) == false) 
     { 
      // Frequency not supported 
      throw new Win32Exception(); 
     } 
    } 

    public void Start() 
    { 
     QueryPerformanceCounter(out start); 
    } 

    public void Stop() 
    { 
     QueryPerformanceCounter(out stop); 
    } 

    public double Duration(int iterations) 
    { 
     return ((((stop - start) * multiplier)/frequency)/iterations); 
    } 
} 
Смежные вопросы