Measuring the execution time in multithreading environment
Asked Answered
P

4

10

I have an application that uses Task (TPL) objects for asynchronous execution.

The main thread waits for a trigger (some TCP packet) and then executes several tasks. What I want to do is to measure the time spent in the tasks.

Take a look at the code. I have some lengthy operation (Generator), enclosed in Stopwatch's start/stop.

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

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

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

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

Here is the problem. Stopwatch uses DateTime.UtcNow.Ticks at the moment of Start() and then again at the moment of Stop(). Then it subtracts those two to get the elapsed time.

The thing is, some other thread (in a single-threaded system) can get some processor time while the Generator (from the code) is doing its GenerateIntervals() lengthy operation. That means that the elapsed time recorded by the stopwatch would contain not only the Generaor.GenerateIntervals() time, but also the time that the other threads did their job inbetween.

Is there any simple way to know exactly how much of processor time did some method take, not including execution time from other threads as a result of timesharing mechanisms?

Paternal answered 12/12, 2011 at 14:2 Comment(4)
possible duplicate of How do you measure code block (thread) execution time with multiple concurrent threads in .NETFlatways
Note: This is not a duplicate... it's a different set of tools, and needs to be specifically answered for .Net TPL utilities.Gramicidin
Why? Are you comparing threading mechanisms? I never quite understood wanting to eliminate environment variables in timing when an environment is always present.Ratiocinate
@Marc, I don't think you understand the question... see my response below for more detail.Gramicidin
G
4

The answer to your question is "No"... No, you cannot measure the accumulated time ON THE CPU for a particular thread.

(Side-rant: I really wish people would read the question and understand it before answering!!!)

Ok, back to your question... the most accurate thing you could do would be to spin off a separate process for each of your tasks, and then measure the CPU time for the process (which can be done in .Net)... but that's overkill.

If you need help on how to do that, you should ask another question specifically for that.

Gramicidin answered 12/12, 2011 at 14:13 Comment(2)
Ah... too bad. It's not all that important for the project. We just wanted to see how much time the process is waiting relative to how much it performs its operation.Paternal
I can appreciate that... it is a bummer, isn't it :P I wish I could get RAM and CPU usage per thread as well.Gramicidin
A
1

Here is nice Article . You can use it or you can compare those times using in-built performance analyzer in VS2010.

Angary answered 12/12, 2011 at 14:18 Comment(0)
S
0

You could use the Windows API QueryPerformanceCounter() and QueryPerformanceFrequency() methodsto retrieves the number of milliseconds that have elapsed since the timer was started.

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;
            }
        }
    }
}
Sachikosachs answered 12/12, 2011 at 14:9 Comment(2)
The System.Diagnostics.Stopwatch class does all of this for you.Tantalus
@BrianGideon: Didnt knew that! Thx for the comment Brian !Sachikosachs
M
0

In fact the answer is YES (but you need to use interop).

There is a WINAPI function which is called QueryThreadCycleTime and does exactly this:

"Retrieves the cycle time for the specified thread."

Menswear answered 20/10, 2012 at 0:8 Comment(1)
Valuable findings - when you control the thread stack. However might not work with the TPL, as the library seems to use thread pooling to do its tasks.Expurgatory

© 2022 - 2024 — McMap. All rights reserved.