In my previous post, I showed an example of how to use new C# features to simplify your code. In this post I’ll investigate that technique affects the performance of the code.
Let’s start from the beginning, there’s a function called f_original
static void f_original( int v1, string v2) { /* do something */ }
It takes two parameters. In this scenario I often call it with the first parameter always as 1. Like so…
f_original(1,"foo");
To avoid this repetition I want a way to consistently call with the first parameter being set to 1.
The first approach is to wrap the function.
static void f_with_wrapper(string v2) { f_original(1,v2); }
And clearly we’ll call the wrapped function like this
f_with_wrapper( “foo” )
The second approach is use currying to create a new function
var f_with_currying = MAKE_FUNC(1);
where MAKE_FUNC is defined as …
static Action<string> MAKE_FUNC(int v1) { Action<string> new_func = (string v2) => f_original(v1, v2); return new_func; }
static Action<string> MAKE_FUNC(int v1) { Action<string> new_func = (string v2) => f_original(v1, v2); return new_func;
}
And we call this function like this
f_with_currying("foo");
NOTE: be aware of how often MAKE_FUNC is called. It takes time to create a function. So in the numbers I’m going to show two cases – one in which the curried function is created *every* time it is used, and another when it is statically created once and reused on each call.
using System; using System.Collections.Generic; using System.Linq; using System.Text;
namespace DemoCurrying2 { class Program { static void Main(string[] args) {
int n = 1000 * 1000 * 10; Console.WriteLine("Number of repetitions: {0}",n); time(demo_nothing, n, "demo_nothing"); time(demo_with_direct_call, n, "demo_with_direct_call"); time(demo_with_wrapper_function, n, "demo_with_wrapper_function"); time(demo_with_currying, n, "demo_with_currying"); time(demo_with_currying2, n, "demo_with_currying2");
static void time( Action f , int n,string name) { System.DateTime start = System.DateTime.Now; for (int i = 0; i < n; i++) { f(); } System.DateTime end = System.DateTime.Now; var duration = end - start; Console.WriteLine("{0} \t Duration \t {1}",name,duration.TotalSeconds); }
static void demo_nothing() { }
static void demo_with_direct_call() { f_original(1,"foo"); }
static void demo_with_wrapper_function() { f_with_wrapper("foo"); }
static void demo_with_currying() { var f_with_currying = MAKE_FUNC(1); f_with_currying("foo"); }
static Action<string> pre_defined_f_with_currying = MAKE_FUNC(1);
static void demo_with_currying2() { pre_defined_f_with_currying("foo"); }
static void f_original( int v1, string v2) { /*var sb = new System.Text.StringBuilder(); sb.Append("Hello World: "); sb.AppendFormat(" v1={0} ", v1); sb.AppendFormat(" v2={0} ", v2); string s = sb.ToString();*/ }
} }
The times
What to note:
static void f_original( int v1, string v2) { var sb = new System.Text.StringBuilder(); sb.Append("Hello World: "); sb.AppendFormat(" v1={0} ", v1); sb.AppendFormat(" v2={0} ", v2); string s = sb.ToString(); }