Как узнать какой метод больше загружает процессор?

206
17 марта 2018, 15:00

Есть несколько реализаций MD5, к примеру. Узнать, какой метод из них выполняется быстрее - не проблема. Как корректно узнать какой из этих методов дает большую нагрузку на процессор?

Answer 1

Для получения процессорного времени, затраченного на выполнение однопоточного метода, необходимо вычесть значения ProcessThread.TotalProcessorTime после и до выполнения метода. Соответственно, загрузку процессора (среднюю), создаваемую в ходе его выполнения, можно найти, разделив полученное значение на Environment.ProcessorCount * ВремяВыполнения. Для повышения точности расчетов произвести измерение несколько раз и найти среднее. Пример:

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

Если DoSomething выполняет только голые вычисления, без обращения к вводу/выводу или ожидания событий, значение загрузки будет близко к 100% / Environment.ProcessorCount. Если он содержит вызов Thread.Sleep, загрузка будет близка к нулю. Все остальное - что-то посередине.

Если метод многопоточный, нужно либо суммировать по всем задействованным потокам, либо просто брать Process.TotalProcessorTime для грубого приближения (в предположении, что ничего другого в данный момент в процессе не происходит).

READ ALSO
Linq возвращает IEnumerable вместо IQueryable

Linq возвращает IEnumerable вместо IQueryable

Заметил что Linq вnet core 2

175
Решить пример записав его условие не используя массивы

Решить пример записав его условие не используя массивы

В начале пытался записать через for( int i = 1; i==256; i*2){} Но что-то пошло не так и я не смог понять,как делить до определенного делителя, не используя...

196
Где хранить временные файлы?

Где хранить временные файлы?

Нужна временная папка для хранения и обработки файловПрочитал на msdn, что можно воспользоваться Path

188