测量多线程环境中的执行时间

时间:2011-12-12 14:02:14

标签: c# multithreading time-measurement

我有一个使用Task(TPL)对象进行异步执行的应用程序。

主线程等待触发器(某些TCP数据包),然后执行多个任务。我想要做的是衡量在任务中花费的时间。

看看代码。我有一些冗长的操作(Generator),包含在Stopwatch's开始/停止。

Task.Factory.StartNew((t) => {

    Stopwatch sw = new Stopwatch();
    sw.Start();

    Generator g = new Generator();
    g.GenerateIntervals(); // lengthy operation

    sw.Stop();
    GlobalStopwatch.Add(sw.Elapsed);
});

这是问题所在。秒表在DateTime.UtcNow.Ticks时使用Start(),然后在Stop()时刻再次使用Generator。然后它减去这两个以获得经过的时间。

问题是,一些其他线程(在单线程系统中)可以获得一些处理器时间,而GenerateIntervals()(来自代码)正在执行其Generaor.GenerateIntervals()冗长的操作。这意味着秒表记录的经过时间不仅包含{{1}}时间,还包含其他线程在其间工作的时间。

有没有简单的方法可以确切地知道某些方法花费了多少处理器时间,而不包括由于分时机制而导致其他线程的执行时间?

4 个答案:

答案 0 :(得分:4)

您的问题的答案是“否”......不,您无法衡量特定thread在CPU 上的累积时间。

(旁边咆哮:我真的希望人们在回答之前阅读问题并理解它!)

好的,回到你的问题......你能做的最准确的事情就是为每个任务分离一个单独的process,然后测量进程的CPU时间(可以是在.Net完成......)但这太过分了。

如果您需要有关如何操作的帮助,您应该专门提出另一个问题。

答案 1 :(得分:1)

Here很好。您可以使用它,或者您可以使用VS2010中的内置性能分析器来比较这些时间。

答案 2 :(得分:0)

您可以使用Windows API QueryPerformanceCounter() QueryPerformanceFrequency()方法来检索自计时器启动以来经过的毫秒数。

using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Threading;

namespace Win32
{
    internal class WinTimer
    {
        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceCounter(
            out long lpPerformanceCount);

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

        private long startTime, stopTime;
        private long freq;

        // Constructor
        public HiPerfTimer()
        {
            startTime = 0;
            stopTime  = 0;

            if (QueryPerformanceFrequency(out freq) == false)
            {
                // high-performance counter not supported
                throw new Win32Exception();
            }
        }

        // Start the timer
        public void Start()
        {
            // lets do the waiting threads there work
            Thread.Sleep(0);

            QueryPerformanceCounter(out startTime);
        }

        // Stop the timer
        public void Stop()
        {
            QueryPerformanceCounter(out stopTime);
        }

        // Returns the duration of the timer (in seconds)
        public double Duration
        {
            get
            {
                return (double)(stopTime - startTime) / (double) freq;
            }
        }
    }
}

答案 3 :(得分:0)

实际上答案是肯定的(但你需要使用互操作)。

有一个名为QueryThreadCycleTime的WINAPI函数,它正是这样做的:

“检索指定线程的循环时间。”