开发者

Problem in calculating time taken to execute a function

I am trying to find the time taken to run a function. I am doing it this way:

SomeFunc(input) {
    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();

    //some operation on input          

    stopWatch.Stop();

    long timeTaken = stopWatch.ElapsedMilliseconds;
}

Now the "some operation on input" as mentioned in the comments takes significant time based on the input to SomeFunc.

The problem is when I call SomeFunc multiple times from the main, I get timeTaken correctly only for the first time, and the rest of the time it is being assigned to 0. Is there a problem with the above code?

EDIT: There is a UI with multiple text fields, and when a button is clicked, it is delegated to the SomeFunc. The SomeFunc makes some calc开发者_C百科ulations based on the input (from the text fields) and displays the result on the UI. I am not allowed to share the code in "some operation on input" since I have signed an NDA. I can however answer your questions as to what I am trying to achieve there. Please help.

EDIT 2: As it seems that I am getting weird value when the function is called the first time, and as @Mike Bantegui mentioned, there must be JIT optimization going on, the only solution I can think of now (to not get zero as execution time) is that to display the time in nano seconds. How is it possible to display the time in nano seconds in C#?


Well, you aren't outputing that data anywhere. Ideally you would do it something more like this.

void SomeFunc(input)
{
  Do sstuff
}

main()
{
  List<long> results = new List<long>();
  Stopwatch sw = new Stopwatch();
  for(int i = 0; i < MAX_TRIES; i++)
  {
     sw.Start();
     SomeFunc(arg);
     sw.Stop();
     results.Add(sw.ElapsedMilliseconds);
     sw.Reset();
  }

  //Perform analyses and results
}


In fact you are getting the wrong time at the first start and correct time to the remaining. You can't relay just on the first call to measure the time. However It seams to be that the operation is too fast and so you get the 0 results. To measure the test correctly call the function 1000 times for example to see the average cost time:

Stopwatch watch = StopWatch.StartNew();
for (int index = 0; index < 1000; index++)
{
    SomeFunc(input);
}
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);

Edit:

How is it possible to display the time in nano seconds

You can get watch.ElapsedTicks and then convert it to nanoseconds : (watch.ElapsedTicks / Stopwatch.Frequency) * 1000000000


As a simple example, consider the following (contrived) example:

double Mean(List<double> items)
{
    double mu = 0;
    foreach (double val in items)
        mu += val;
    return mu / items.Length;
}

We can time it like so:

void DoTimings(int n)
{
    Stopwatch sw = new Stopwatch();
    int time = 0;
    double dummy = 0;

    for (int i = 0; i < n; i++)
    {
        List<double> items = new List<double>();
        // populate items with random numbers, excluded for brevity

        sw.Start();
        dummy += Mean(items);
        sw.Stop();
        time += sw.ElapsedMilliseconds;
    }

    Console.WriteLine(dummy);
    Console.WriteLine(time / n);
}

This works if the list of items is actually very large. But if it's too small, we'll have to do multiple runs under one timing:

void DoTimings(int n)
{
    Stopwatch sw = new Stopwatch();
    int time = 0;
    double dummy = 0;

    List<double> items = new List<double>(); // Reuse same list
    // populate items with random numbers, excluded for brevity

    sw.Start();
    for (int i = 0; i < n; i++)
    {
        dummy += Mean(items);
        time += sw.ElapsedMilliseconds;
    }
    sw.Stop();

    Console.WriteLine(dummy);
    Console.WriteLine(time / n);
}

In the second example, if the size of the list is too small, then we can accurately get an idea of how long it takes by simply running this for a large enough n. Each has it's advantages and flaws though.

However, before doing either of these I would do a "warm up" calculation before hand:

// Or something smaller, just enough to let the compiler JIT
double dummy = 0;
for (int i = 0; i < 10000; i++) 
    dummy += Mean(data);
Console.WriteLine(dummy);

// Now do the actual timing

An alternative method of both would be to do what @Rig did in his answer, and build up a list of results to do statistics on. In the first case, you'd simply build up a list of each individual time. In the second case, you would build up a list of the average timing of multiple runs, since the time for a calculation could smaller than finest grained time in your Stopwatch.

With all that said, I would say there is one very large caveat in all of this: Calculating the time it takes for something to run is very hard to do properly. It's admirable to want to do profiling, but you should do some research on SO and see what other people have done to do this properly. It's very easy to write a routine that times something badly, but very hard to do it right.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜