I want to start measuring the time it took for a function to run in my program in multiple locations.
Dealing with the StopWatch seemed a bit messy in the code so i decided to wrap it.
These are the things I need:
I want to find a readable and sustainable solution since it will be used in multiple projects.
this is what i did so far:
public class TimeMeasurer
{
private readonly Stopwatch _stopWatch;
public TimeMeasurer()
{
_stopWatch = new Stopwatch();
}
public async Task<Tuple<double, TReturn>> Start<TReturn>(Func<Task<TReturn>> function)
{
try
{
_stopWatch.Start();
var val = await function();
var took = _stopWatch.Elapsed.TotalSeconds;
return Tuple.Create(took, val);
}
finally
{
_stopWatch.Stop();
_stopWatch.Reset();
}
}
public async Task<double> Start(Func<Task> function)
{
try
{
_stopWatch.Start();
await function();
var took = _stopWatch.Elapsed.TotalSeconds;
return took;
}
finally
{
_stopWatch.Stop();
_stopWatch.Reset();
}
}
}
if there isnt a better solution..
edit: calling the class i made also doesnt look good..
var tuple = await _timeMeasurer.Start(async () => await function(param1, param2));
EDIT: I decided to give this idea up. Its too messy. In the end im using StopWatch
For your first point, there is not much more you could do that could combine the functions, there is just not much logic to combine.
For your second point I would make two custom classes to hold the result. You could get fancy and do some inheritance too and return the entire task object instead of just the result in case someone wanted to look at some of the properties of the returned task.
Lastly there is no reason your function should be a instance, the entire class could be made static.
Here is a example that has the changes I suggested.
public class TimeMeasurerResult
{
protected readonly Task _task;
private readonly TimeSpan _duration;
public TimeMeasurerResult(Task task, TimeSpan duration)
{
_task = task;
_duration = duration;
}
public Task Task {get { return _task;}}
public TimeSpan Duration {get {return _duration;}}
}
public class TimeMeasurerResult<T> : TimeMeasurerResult
{
public TimeMeasurerResult(Task<T> task, TimeSpan duration)
:base(task, duration)
{
}
public T Result {get { return ((Task<T>)_task).Result;}}
}
public static class TimeMeasurer
{
public static async Task<TimeMeasurerResult<TReturn>> Start<TReturn>(Func<Task<TReturn>> function)
{
var stopWatch = Stopwatch.StartNew();
var task = function();
await task;
var took = stopWatch.Elapsed;
return new TimeMeasurerResult<TReturn>(task, took);
}
public static async Task<TimeMeasurerResult> Start(Func<Task> function)
{
var stopWatch = Stopwatch.StartNew();
var task = function();
await task;
var took = stopWatch.Elapsed;
return new TimeMeasurerResult(task, took);
}
}
Here is a example of using it, note that I only needed to do var results = await TimeMeasurer.Start(() => Function(a,b)); not var results = await TimeMeasurer.Start(async () => await Function(a,b));
public class Program
{
public static void Main()
{
AsyncMain().Wait();
}
public static async Task AsyncMain()
{
int a = 500;
int b = 10;
var results = await TimeMeasurer.Start(() => Function(a,b));
Console.WriteLine("Waited: {0}", results.Duration.TotalSeconds);
Console.WriteLine("Result: {0}", results.Result);
}
public static async Task<int> Function(int a, int b)
{
var total = a + b;
await Task.Delay(total);
return total;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With