10

我有一个使用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()时间,还包含其他线程在其间完成工作的时间。

是否有任何简单的方法可以准确地知道某些方法占用了多少处理器时间,不包括由于分时机制而导致的其他线程的执行时间?

4

4 回答 4

4

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

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

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

如果您需要有关如何做到这一点的帮助,您应该专门为此提出另一个问题。

于 2011-12-12T14:13:42.370 回答
1

是一篇不错的文章。您可以使用它,也可以使用 VS2010 中的内置性能分析器来比较这些时间。

于 2011-12-12T14:18:21.153 回答
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;
            }
        }
    }
}
于 2011-12-12T14:09:41.917 回答
0

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

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

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

于 2012-10-20T00:08:39.367 回答