如何从C#中的QueryPerformanceCounter获取刻度?

时间:2012-03-20 15:12:27

标签: c# .net-4.0

我需要更换秒表以避免使用getter作为其属性。我将使用QueryPerformanceCounter实现它。 我只需要刻度没有别的。

任何人都可以提供代码snipet,以获得正确的刻度(1/10000毫秒)或任何其他小而稳定的值。

请注意我的服务器将时钟粒度设置为 0.5 ms (不确定它是否会影响QueryPerformanceCounter),但只是为了让您知道。

请注意 - 我不需要计时器。我只需要测量代码部分之间的时间间隔。

编辑:以避免混淆我真的想知道QueryPerformanceCounter中的 lpPerformanceCount (out lpPerformanceCount);

6 个答案:

答案 0 :(得分:10)

http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.gettimestamp.aspx

Stopwatch.GetTimestamp

您不必实例化Stopwatch对象,GetTimestamp应该返回滴答数,而不管其上下文。

答案 1 :(得分: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

旧但它应该仍然有用

编辑:StopWatch的内部实际使用QueryPerformanceCounter,因此使用托管代码应提供相同的结果,并具有更好的兼容性。

答案 2 :(得分:1)

请勿在未经测试的情况下使用StopWatch进行高分辨率计时。我测试它已经有几年了,但当时它给出了默认的窗口时间分辨率。你可以说,因为如果它使用默认的窗口分辨率,真的,非常快的事情将需要0或10-15毫秒(默认分辨率实际上是线程上下文切换的分辨率,可能是在每个上下文中更新默认的Windows时钟开关,大约每10-15毫秒)。

答案 3 :(得分:1)

我使用下面的类将系统上的时间精确到100ns。

public class MStopwatch : Stopwatch
{
    private double _frequencyScaler;

    public MStopwatch()
    {
        _frequencyScaler = 1.0 / Stopwatch.Frequency;
    }

    public double ElapsedSeconds
    {
        get
        {
            return ElapsedTicks * _frequencyScaler;
        }
    }

}

答案 4 :(得分:0)

不是直接的答案(但可能需要支持信息):

一些提供的答案非常适合直接回答您的问题。但是,为了完成你想要做的事情,我想补充一些注意事项。

首先,考虑在运行时发生的实时(jit)编译器的时序开销。获取初始时间戳的任何代码然后执行 stuff ,然后获取最终时间戳以减去delta的t2-t1,对于 stuff 中的任何功能,如果你包括您在当前进程中尚未调用的任何函数,然后在第一次调用它时,您将支付jit开销以将字节码编译为本机代码。在这种情况下,成本并不代表性能关键代码的实际运行时成本,这可能是频繁调用的代码,但其jit成本仅支付一次(在此过程中首次调用它)。因此,多次调用定时代码,抛出第一个时间,然后取平均值。

此外要注意垃圾收集器的运行时成本。如果您只是在玩游戏,那么对可以严格避免分配新对象的代码进行基准测试可能是有趣的。但有时这并不容易,特别是当您调用其实现无法更改的函数时。此外,我必须告诉你,生产代码的实际性能开销无法避免垃圾收集开销,因此获得一个真实的数字应该包括这个开销。也就是说,如果您的 stuff 包含分配新对象的代码,那么它可能会启动垃圾收集器,这将是昂贵的,因此请准备好您可能想要丢弃的一些潜在异常值。

其次,好的答案提供了代码来声明从系统dll调用的外部函数,这很好。在一般情况下获得这些签名是正确的,有时可能会令人讨厌,所以我想提一个很好的资源:pinvoke.net。 搜索QueryPerformanceCounter给了我一些签名,这些签名让我对已经给出的答案进行了剪切和粘贴,对于您想要进行的任何系统调用来说,它都是一个很好的资源。

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

答案 5 :(得分:-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);
    }
}