How do I find out which method is more CPU-intensive?

There are several implementations of MD5, for example. Finding out which method is faster is not a problem. How to correctly find out which of these methods gives a greater load on the processor?

Author: User101057, 2018-03-16

1 answers

To get the CPU time spent executing a single-threaded method, you need to subtract the values of ProcessThread.TotalProcessorTime after and before executing the method. Accordingly, the CPU load (average) created during its execution can be found by dividing the resulting value by Environment.ProcessorCount * ВремяВыполнения. To improve the accuracy of the calculations, make the measurement several times and find the average. Example:

using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Diagnostics;
using System.Threading;

namespace ConsoleTest1
{    
    class Program
    {
        /* Измеряемый метод */
        public static Int64 DoSomething(Int64 x)
        {
            Int64 res = 1; 
            for (Int64 i = 1; i <= x; i++) res += i;
            return res;
        }

        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        static extern uint GetCurrentThreadId();

        const int N = 50; //число итераций

        static void Main(string[] args)
        {
            Console.WriteLine(DoSomething(5000000).ToString()); //прогрев

            Int64 sum=0;
            Stopwatch sw = new Stopwatch();

            var id = GetCurrentThreadId();//получаем ID текущего потока

            Process pr = Process.GetCurrentProcess();
            ProcessThread thread = null;

            //находим объект ProcessThread для текущего потока
            foreach (ProcessThread th in pr.Threads)
            {
                if (th.Id == (int)id) thread = th;
            }
            if (thread == null) { Console.WriteLine("ProcessThread not found"); return; }

            sw.Start();//начало измерений
            var before = thread.TotalProcessorTime.Ticks;
            for (int i = 0; i < N; i++)
            {
                sum += DoSomething(50000000);//вызов измерямого метода                
            }
            Console.WriteLine(sum.ToString());
            var after = thread.TotalProcessorTime.Ticks;
            sw.Stop();//конец измерений            

            double processor_time = TimeSpan.FromTicks(after - before).TotalMilliseconds / N;
            double total_time = (sw.ElapsedMilliseconds) / (double)N;
            double usage = (processor_time) / (Environment.ProcessorCount * total_time) * 100.0;

            Console.WriteLine("Processor time:" + Math.Round(processor_time,2).ToString());
            Console.WriteLine("Total time:" + total_time.ToString());
            Console.WriteLine("Usage %:" + Math.Round(usage,1).ToString());            

        }
    }
}

If doSomething performs only bare for example, without accessing I / O or waiting for events, the load value will be close to 100% / Environment.ProcessorCount. If it contains a call to Thread.Sleep, the load will be close to zero. Everything else is somewhere in between.

If the method is multithreaded, you either need to sum over all the threads involved, or just take Process. TotalProcessorTime for a rough approximation (assuming that nothing else is currently happening in the process).

 1
Author: MSDN.WhiteKnight, 2018-03-16 16:12:08