How to get ticks from QueryPerformanceCounter in C

2020-02-14 03:22发布

问题:

I need to replace Stopwatch to avoid using getters for its properties. I am going to implement it using QueryPerformanceCounter. I only need ticks nothing else.

Can anyone provide a code snipet please, to get correct ticks (1/10000 of ms) or any other small but stable value.

Please note my server sets clock granularity down to 0.5 ms (not sure if it affects QueryPerformanceCounter) but just for you to know.

Please also note - I do not need a timer. I only need to measure time intervals between parts of code.

EDIT: to avoid confusion I really want to know what is lpPerformanceCount in QueryPerformanceCounter(out long lpPerformanceCount);

回答1:

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

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

Taken from http://www.codeproject.com/Articles/2635/High-Performance-Timer-in-C

Old but it should still work

EDIT: The internals of StopWatch actually use QueryPerformanceCounter, so using the managed code should provide identical results, with better compatibility.



回答2:

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

Stopwatch.GetTimestamp

You don't have to instantiate a Stopwatch object, GetTimestamp should return the number of ticks regardless of its context.



回答3:

Do NOT use StopWatch for high resolution timing without testing it. It has been a few years since I have tested it, but at that time it gave the default windows time resolution. You can tell because really, really fast things will take either 0 time or 10-15 milliseconds if it is using the default windows resolution (the default resolution is actually the resolution of thread context switches, presumably the default windows clock is updated at each context switch, which is about every 10-15 milliseconds).



回答4:

I use the following class that gives the time accurate to 100ns on my system.

public class MStopwatch : Stopwatch
{
    private double _frequencyScaler;

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

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

}


回答5:

NOT A DIRECT ANSWER (but Potentially necessary support info follows):

Some of the provided answers are pretty good to directly answer your question. However, to accomplish what you're trying to do, I would like to add a couple notes.

First, take into account the timing overhead of the just-in-time (jit) compiler which happens at runtime. Any code where you grab the initial timestamp then do stuff, and then grab a final timestamp to subtract t2-t1 for the delta, for any functionality inside of stuff, if you include any functions you haven't called yet during the current process then the first time you call it, you will pay for the jit overhead to compile the bytecode into native code. In this case, the cost is not representative of the actual runtime cost of performance critical code which is presumably code that is called frequently and yet whose jit cost is paid just once (on the first call to it in the process). So call the timed code multiple times, throw out the first timing, and take an average.

Furthermore beware of the runtime costs of the garbage collector. If you are just playing around, then it might be possible and interesting to benchmark code that strictly avoids allocating new objects. But sometimes this is not easy particularly when you are calling functions whose implementations you cannot change. Also, I must grant you that the real world performance overhead of production code cannot avoid garbage collection overhead so getting a realistic figure should include this overhead. That said, if your stuff includes code that allocates new objects, then it may kick off the garbage collector which will be expensive so prepare yourself for some potential outliers that you might want to throw out.

Second, the good answers provided the code to declare external functions to call from system dlls and that's great. Getting these signatures correct in the general case can be a nuisance sometimes so I would like to mention a great resource for this: pinvoke.net. A search for QueryPerformanceCounter gave me the signatures that put me a cut-and-paste away from the answer already given and it is a great resource for any system calls you want to make.

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



回答6:

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);
    }
}


标签: c# .net-4.0