patterncsharpMinor
Measure a given method's execution time - follow-up
Viewed 0 times
methodtimefollowmeasuregivenexecution
Problem
A long time ago, I've written a method that would allow me to measure the amount of time a method takes to run. I've decided to tweak this method and make use of TPL since measuring a method may take some time.
```
public static class ComparableUtils
{
public static T Min(this T t1, T t2)where T:IComparable
{
if (t1.CompareTo(t2) (this T t1, T t2) where T : IComparable
{
if (t1.CompareTo(t2) >= 0)
{
return t1;
}
return t2;
}
}
public static class TestUtils
{
private static readonly Stopwatch Watch = new Stopwatch();
//This determines a minimum amount of iterations needed to perform to get a significative time measurment
private static Task GetIterations(Action action)
{
return Task.Run(() =>
{
const int minimumTime = 20;
int iterations = 0;
Watch.Start();
while (Watch.Elapsed.Milliseconds 0)
{
action();
}
Watch.Stop();
return Watch.Elapsed;
}
public static Task Measure(Action action, int? iterations = null, int times = 1)
{
return Task.FromResult(iterations)
.ContinueWith(async t => t.Result.GetValueOrDefault(await GetIterations(action)))
.Unwrap()
.ContinueWith(t =>
{
var iters = t.Result;
TimeSpan timeTaken = TimeSpan.MaxValue;
for (int i = 0; i < times; ++i)
{
timeTaken = MeasureTime(action, iters).Min(timeTaken);
}
return new Time(timeTaken.Ticks*100/iters);
});
}
}
public class Time
{
private readonly long _nanoSeconds;
public Time(long nanoSeconds)
{
_nanoSeconds = nanoSeconds;
}
public override string ToString()
{
if (_nanoSeconds < 9999)
{
return _nanoSeconds.ToString()+"ns";
}
return new Time
```
public static class ComparableUtils
{
public static T Min(this T t1, T t2)where T:IComparable
{
if (t1.CompareTo(t2) (this T t1, T t2) where T : IComparable
{
if (t1.CompareTo(t2) >= 0)
{
return t1;
}
return t2;
}
}
public static class TestUtils
{
private static readonly Stopwatch Watch = new Stopwatch();
//This determines a minimum amount of iterations needed to perform to get a significative time measurment
private static Task GetIterations(Action action)
{
return Task.Run(() =>
{
const int minimumTime = 20;
int iterations = 0;
Watch.Start();
while (Watch.Elapsed.Milliseconds 0)
{
action();
}
Watch.Stop();
return Watch.Elapsed;
}
public static Task Measure(Action action, int? iterations = null, int times = 1)
{
return Task.FromResult(iterations)
.ContinueWith(async t => t.Result.GetValueOrDefault(await GetIterations(action)))
.Unwrap()
.ContinueWith(t =>
{
var iters = t.Result;
TimeSpan timeTaken = TimeSpan.MaxValue;
for (int i = 0; i < times; ++i)
{
timeTaken = MeasureTime(action, iters).Min(timeTaken);
}
return new Time(timeTaken.Ticks*100/iters);
});
}
}
public class Time
{
private readonly long _nanoSeconds;
public Time(long nanoSeconds)
{
_nanoSeconds = nanoSeconds;
}
public override string ToString()
{
if (_nanoSeconds < 9999)
{
return _nanoSeconds.ToString()+"ns";
}
return new Time
Solution
while (Watch.Elapsed.Milliseconds < minimumTime)It probably won't affect this code, but
Milliseconds doesn't do what you probably think it does. I think you want TotalMilliseconds.public static Task Measure(Action action, int? iterations = null, int times = 1)
{
return Task.FromResult(iterations)
.ContinueWith(async t => t.Result.GetValueOrDefault(await GetIterations(action)))
.Unwrap()
.ContinueWith(t =>
{
var iters = t.Result;
TimeSpan timeTaken = TimeSpan.MaxValue;
for (int i = 0; i < times; ++i)
{
timeTaken = MeasureTime(action, iters).Min(timeTaken);
}
return new Time(timeTaken.Ticks*100/iters);
});
}- Generally speaking, if you can use
await, you don't needContinueWith().
- What's the point of using
Task.FromResult().ContinueWith()?Task.Run()would make much more sense here.
- There is actually no reason to use
Taskandasync-awaithere. You should use that only for truly asynchronous IO operations. If the caller wants to run your long-running CPU-bound code on a separate thread, they can easily do it themselves.
- For performance-related code, it feels weird that you're calling
GetIterations()even when it's not needed.
Code Snippets
while (Watch.Elapsed.Milliseconds < minimumTime)public static Task<Time> Measure(Action action, int? iterations = null, int times = 1)
{
return Task.FromResult(iterations)
.ContinueWith(async t => t.Result.GetValueOrDefault(await GetIterations(action)))
.Unwrap()
.ContinueWith(t =>
{
var iters = t.Result;
TimeSpan timeTaken = TimeSpan.MaxValue;
for (int i = 0; i < times; ++i)
{
timeTaken = MeasureTime(action, iters).Min(timeTaken);
}
return new Time(timeTaken.Ticks*100/iters);
});
}Context
StackExchange Code Review Q#79869, answer score: 5
Revisions (0)
No revisions yet.