How to get ticks from QueryPerformanceCounter in C#?

后端 未结 6 992
不知归路
不知归路 2020-12-21 01: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 e

相关标签:
6条回答
  • 2020-12-21 01:43
    [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.

    0 讨论(0)
  • 2020-12-21 01:50

    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]

    0 讨论(0)
  • 2020-12-21 01:55
    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);
        }
    }
    
    0 讨论(0)
  • 2020-12-21 01:56

    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.

    0 讨论(0)
  • 2020-12-21 02:02

    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;
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-12-21 02:04

    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).

    0 讨论(0)
提交回复
热议问题