如何在Windows上安装快速高分辨率计时器?

时间:2014-12-31 00:45:40

标签: windows winapi timing

我正在编写一个探查器,只要函数进入或退出就会查询计时器。因此,它可能每秒查询数千次

最初我使用 QueryPerformanceCounter ,尽管事实上它的分辨率很高,但事实证明非常慢。根据{{​​3}}问题,当我在分析器中使用QPC时,我也有明显的减速,但可能不是那么糟糕的1-2ms数字。如果我用 GetTickCount 替换它,我没有注意到任何减速,但该功能对于分析来说是不准确的。

上述问题提到亲和面具。我尝试使用SetProcessAffinityMask(GetCurrentProcess(), 1)绑定它,但它根本没有提高性能。

我不知道它是否重要,但到目前为止,我在Linux主机上运行VirtualBox的Windows上进行了测试。这可能是问题吗?

2 个答案:

答案 0 :(得分:0)

我在Windows上了解的最高分辨率计时器是winmm.dll

提供的多媒体计时器

这是我为满足自己的性能测试而烦恼的课程 - 给我一个旋转:

public class HighResTimer
{
    private delegate void TimerEventHandler(int id, int msg, IntPtr user, int dw1, int dw2);

    private const int TIME_PERIODIC = 1;
    private const int EVENT_TYPE = TIME_PERIODIC;

    [System.Runtime.InteropServices.DllImport("winmm.dll")]
    private static extern int timeSetEvent( int delay, int resolution, TimerEventHandler handler, IntPtr user, int eventType);  
    [System.Runtime.InteropServices.DllImport("winmm.dll")]
    private static extern int timeKillEvent(int id);
    [System.Runtime.InteropServices.DllImport("winmm.dll")]
    private static extern int timeBeginPeriod(int msec);
    [System.Runtime.InteropServices.DllImport("winmm.dll")]
    private static extern int timeEndPeriod(int msec); 

    private int _timerId;
    private TimerEventHandler _handler = delegate {};

    public event EventHandler OnTick;

    public HighResTimer(int delayInMs)
    {
        timeBeginPeriod(1);
        _handler = new TimerEventHandler(timerElapsed);
        _timerId = timeSetEvent(delayInMs, 0, _handler, IntPtr.Zero, EVENT_TYPE);
    }

    public void Stop()
    {
        int res = timeKillEvent(_timerId);
        timeEndPeriod(1);
        _timerId = 0;
    }

    private void timerElapsed(int id, int msg, IntPtr user, int dw1, int dw2)
    {
        OnTick(this, new EventArgs());
    }   
}

答案 1 :(得分:0)

直接使用RDTSC指令结束。所以我在GCC中为它编写了一个包装器:

static inline unsigned long long rdtsc(void)
{
    unsigned hi, lo;
    asm volatile ("rdtsc" : "=a"(lo), "=d"(hi));
    return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}

没有减速,显然比QueryPerformanceCounter具有更高的分辨率。

代码基于this answer