ms813
ms813

Reputation: 251

Wrapper to time generic function

I'm writing some code to generate a procedural map. Some of the steps take much longer than others, and I'm timing each part of the build to see where the bottlenecks are, and to let the user know that the program hasn't stalled on them.

At the moment I have a lot of code that looks like this:

Console.Write("Creating tiles");
var watch = System.Diagnostics.Stopwatch.StartNew();
CreateTiles();    //key mapgen function
watch.Stop();
Console.WriteLine("... finished in: {0} s", watch.ElapsedMilliseconds/1000d);

Console.Write("Calculating tile elevations");
var watch = System.Diagnostics.Stopwatch.StartNew();
CalculateTileElevations();    //key mapgen function
watch.Stop();
Console.WriteLine("... finished in: {0} s", watch.ElapsedMilliseconds/1000d);
//etc

My question is, is there a way of refactoring this to look something more like the following:

ExecuteTimedFunction(CreateTiles(), "Creating tiles");
ExecuteTimedFunction(CalculateTileElevations(), "Calculating tile elevations");

void ExecuteTimedFunction(Func genericFunction, String logMsg)
{
    Console.Write(logMsg);
    var watch = System.Diagnostics.Stopwatch.StartNew();
    genericFunction();    
    watch.Stop();
    Console.WriteLine("... finished in: {0} s", watch.ElapsedMilliseconds/1000d);
}

Caveat: the return type of all of the functions is void as they all manipulate a master list of tiles, but not all of the functions have the same number of input parameters (although the majority have 0 parameters so a solution for that case would still be useful)

Upvotes: 1

Views: 281

Answers (2)

Scott Perham
Scott Perham

Reputation: 2470

Your ExecuteTimedFunction method would look something like this:

public void ExecuteTimedFunction(Action action, string name)
{
    Console.Write(name);
    var watch = Stopwatch.StartNew();
    action();
    watch.Stop();
    Console.WriteLine("... finished in: {0} s", watch.ElapsedMilliseconds/1000d);
}

Then you can call it in either of the following ways:

ExecuteTimedFunction(MyFunctionWithNoParams, "MyFunc");
ExecuteTimedFunction(() => MyFuncWithParams(p1, p2), "MyFunc2");

Upvotes: 9

Dutchdre
Dutchdre

Reputation: 16

You can also access the called method details for logging by changing it into something like:

Console.WriteLine($"{action.Method.Name} finished in: {watch.ElapsedMilliseconds / 1000d} s");

Upvotes: 0

Related Questions