I want to measure the time that certain function calls take in my application. For this I use the Stopwatch class and it works fine. It looks something like this:
static readonly Stopwatch StopWatch = new Stopwatch();
StopWatch.Restart();
void func();
StopWatch.Stop();
Assert.Blabla
However I am typing this around a lot of functions. Is there a way to make a function that does this for me? I tried but since the signatures of the functions are all different I can't figure it out. I took a look at Func and Action, but they seem to require a fixed signature. I would like something like this:
CallAndMeasureFunction(func)
You can use something like below:
Define a method which takes your actual methods delegate as input:
public static TimeSpan GetTimestampFor(Action action)
{
TimeSpan timestamp = new TimeSpan(0);
Stopwatch stopWatch = new Stopwatch();
if (action != null)
{
stopWatch.Start();
action.Invoke();
stopWatch.Stop();
timestamp = stopWatch.Elapsed;
}
return timestamp;
}
and call it as below:
var timeSpan = GetTimestampFor(() => {var xyz = ActualMethodForWhichTimeHasTobeMeasured()});
With this code, you can measure every method's execution time
Related
I would like to make a custom Assertion for my unit test which would measure the execution time of two c# functions and compare them.
I have written the code below, but there is a better way ?
public static class AssertExtensions
{
public static void MoreSlowThan(Action slowFunction, Action fastFunction)
{
var watch = Stopwatch.StartNew();
slowFunction();
watch.Stop();
var watchBis = Stopwatch.StartNew();
fastFunction();
watchBis.Stop();
Assert.IsTrue(watch.ElapsedMilliseconds >= watchBis.ElapsedMilliseconds);
}
}
called by :
AssertExtensions.MoreSlowThan(() => MyFunction(), () => MyCachedFunction());
(the goal is to compare the execution time of a function with the execution time of the same function in cache)
The best way i found it's refactor it with MSTest-2 like :
public static void IsFaster(this Assert assert, Action expectedFastAction, Action actualSlowAction)
{
var slowStopwatch = Stopwatch.StartNew();
actualSlowAction();
slowStopwatch.Stop();
var fastStopwatch = Stopwatch.StartNew();
expectedFastAction();
fastStopwatch.Stop();
Assert.IsTrue(slowStopwatch.Elapsed >= fastStopwatch.Elapsed, string.Format("First function would be faster than the second. Fast function elapsed time : {0}. Slow function elapsed time : {1}", fastStopwatch.Elapsed, slowStopwatch.Elapsed));
}
And call it with :
Assert.That.IsSlower(() => MyCachedFunction(), () => MyFunction());
If anyone has a better way
I have two actions in mvc and in one I start a global stopwatch and in another I stop it, but the time elapsed is always 0 no matter how long the time elapsed is. Both of these events are triggered by button clicks. My suspition is that the post of the button is messing with my time elapsed maybe? If so is there any way around this?
public Stopwatch stopwatch = new Stopwatch();
public ActionResult Start()
{
stopwatch.Start();
return RedirectToAction("Index");
}
public ActionResult Stop(int workid)
{
stopwatch.Stop();
TimeSpan ts = stopwatch.Elapsed;
int hours = ts.Hours;
int mins = ts.Minutes;
using (ZDevContext db = new ZDevContext())
{
DashboardHelper dashhelper = new DashboardHelper(db);
dashhelper.RecordTimeSpent(workid, hours, mins);
}
return View("Index");
}
It's not the same StopWatch - the controller is created anew for each request. You would need to persist the stopwatch somewhere.
You could persist the start time in a static Dictionary<int,DateTimeOffset> which would map a workId to the started time.
static ConcurrentDictionary<int,DateTimeOffset> starts = new ConcurrentDictionary<int,DateTimeOffset>();
public ActionResult Start(int workId)
{
starts.TryAdd(workId, DateTimeOffset.Now);
return RedirectToAction("Index");
}
public ActionResult Stop(int workId)
{
DateTimeOffset started = DateTimeOffset.MinValue;
if (starts.TryGet(workId, out started))
{
// calculate time difference
}
return View("Index");
}
But this still isn't great as your application may be restarted by IIS in between and you will lose the starts value. It also has no code to clean the table when a value is no longer needed. You could improve the latter by using the .NET Cache but you really need a database to do this right.
if you want to make the same instance shared for all sessions (which you usually don't want) just mark it as static,
private static Stopwatch stopwatch = new Stopwatch();
also, you don't have to define it as public if it will not be accessible from other controllers/assemblies.
as #Ian Mercer suggested, it is not a good way to use for a stopwatch.
have a look at these links:
Access modifiers
static c#
Right now, I have the following code that times the completion time of a method and prints it out:
static void Run()
{
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
GetTableNames().Wait();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedTicks);
}
static async Task GetTableNames() { doesStuff(); }
However, I'll be reusing that timing code a bunch, so I'd like to wrap it inside a method so that I can do something like this:
static void Run()
{
TimeMethod(GetTableNames);
TimeMethod(GetChairNames);
TimeMethod(GetStoolNames);
// etc...
}
I've been trying a few different things (Action, Delegate, Func), but haven't succeeded in finding one that allows me to call .Wait() on the passed function before stopping the timer. Any recommendations?
Declare TimeMethod to take Func<Task>:
TimeMethod(Func<Task> method)
{
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
method().Wait();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedTicks);
}
I need a simple way (and compact if possible) to execute a block of C# while counting time. Something similar to this C++ code:
elapsed = time_call([&]
{
for_each (a.begin(), a.end(), [&](int n) {
results1.push_back(make_tuple(n, fibonacci(n)));
});
});
where time_call is:
// Calls the provided work function and returns the number of milliseconds
// that it takes to call that function.
template <class Function>
__int64 time_call(Function&& f)
{
__int64 begin = GetTickCount();
f();
return GetTickCount() - begin;
}
I know the stopwatch way... anything more compact ?
TimeSpan TimeAction(Action blockingAction)
{
Stopwatch stopWatch = System.Diagnostics.Stopwatch.StartNew();
blockingAction();
stopWatch.Stop();
return stopWatch.Elapsed;
}
Usage:
var elapsed = TimeAction(() =>
{
//Code to time
});
Based on your sample code (and usage of GetTickCount) you might want to return ElapsedTicks instead of Elapsed.
public double TimeCall(Action actionToExecute)
{
double elapsed = 0;
if (actionToExecute != null)
{
var stopwatch = Stopwatch.StartNew();
actionToExecute.Invoke();
elapsed = stopwatch.ElapsedMilliseconds;
}
return elapsed;
}
How-to use:
var elapsed = TimeCall( () => { foreach( ... ) } );
I don't know the stopwatch way, but C# has lambdas too, so it should be easy enough to implement something similar to time_call().
Is there a class in C# that can give me clock ticks, seconds consumed by a method? I guess I have two wrap that functionality around function to time the ticks and seconds taken up.
You could use the System.Diagnostics.Stopwatch class.
Stopwatch sw = new Stopwatch();
sw.Start();
// Your method call here...
sw.Stop();
// Get the elapsed time
TimeSpan elapsed = sw.Elapsed;
From here, you can use the TimeSpan.Ticks or the TimeSpan.TotalSeconds properties to determine the elapsed ticks or elapsed seconds, respectively.
If you wanted to, you could use a method along the following lines to "wrap" that functionality around a function, as you mentioned (just an idea, you'd probably want to tweak this code to suit your specific purposes -- passing in arguments, etc.):
public static T ExecuteWithElapsedTime<T>(Func<T> function, out TimeSpan elapsedTime)
{
T rval;
Stopwatch sw = new Stopwatch();
sw.Start();
rval = function();
sw.Stop();
elapsedTime = sw.Elapsed;
return rval;
}
And you could call it like this (where myFunc is a function that returns an int):
TimeSpan elapsed;
int result = ExecuteWithElapsedTime(myFunc, out elapsed);
Might be simpler though to not even bother with a method like this, and just put the Stopwatch code inline with your method call.
Use:
using System.Diagnostics;
...
var sw = Stopwatch.StartNew();
DoYaThing();
Console.WriteLine("{0} Elapsed", sw.Elapsed);
There's the high resolution timer ...
Also, iirc a TimeSpan can give you a measurement in ticks back.
You can check out the [System.TimeSpan] class and wrap that around your method.