Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get statistic of executed tasks in C#

I have following simple code:

var tasks = statements.Select(statement => _session.ExecuteAsync(statement));
var result = Task.WhenAll(tasks).Result;
[...]

How can I calculate min, max, avg, etc. of all executed tasks? The task class doesn't have property like "executedMilliseconds"

like image 646
Piotr Stapp Avatar asked Feb 06 '15 12:02

Piotr Stapp


Video Answer


2 Answers

With the following extension method:

public static class EnumerableExtensions
{
    public static IEnumerable<Task<TimedResult<TReturn>>> TimedSelect<TSource, TReturn>(
        this IEnumerable<TSource> source,
        Func<TSource, Task<TReturn>> func )
    {
        if (source == null) throw new ArgumentNullException("source");
        if (func == null) throw new ArgumentNullException("func");

        return source.Select(x =>
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            Task<TReturn> task = func(x);

            Task<TimedResult<TReturn>> timedResultTask = task
                .ContinueWith(y =>
                {
                    stopwatch.Stop();

                    return new TimedResult<TReturn>(task, stopwatch.Elapsed);
                });

            return timedResultTask;
        });
    }
}

public class TimedResult<T>
{
    internal TimedResult(Task<T> task, TimeSpan duration)
    {
        Task = task;
        Duration = duration;
    }

    public readonly Task<T> Task;
    public readonly TimeSpan Duration;
}

And callsite

var tasks = statements.TimedSelect(statement => _session.ExecuteAsync(statement));

var result = Task.WhenAll(tasks).Result;

You can extract the results that you'll need

// Whatever works (ugly, but just as an example)...
var min = result.Select(x => x.Duration).Min();
var max = result.Select(x => x.Duration).Max();
var avg = new TimeSpan((long)result.Select(x => x.Duration.Ticks).Average());

Note that this includes pool waiting time (time waiting for a task thread to become available), and therefor may not be accurate.

A non-generic variant of this extension is an exercise for the reader.

like image 130
Caramiriel Avatar answered Oct 25 '22 15:10

Caramiriel


You can give tasks a ContinuationTask, which is something that is called after the task has completed. With this you can use a bunch of stopwatches and use the continuation task to individually stop them.

like image 33
Nathan Cooper Avatar answered Oct 25 '22 16:10

Nathan Cooper