Following this question - Pass Method as Parameter using C# and some of my personal experience I'd like to know a little more about the performance of calling a delegate vs just calling a method in C#.
Although delegates are extremely convenient, I had an app that did lots of callbacks via delegates and when we rewrote this to use callback interfaces we got an order of magnitude speed improvement. This was with .NET 2.0 so I'm not sure how things have changed with 3 and 4.
How are calls to delegates handled internally in the compiler/CLR and how does this affect performance of method calls?
EDIT - To clarify what I mean by delegates vs callback interfaces.
For asynchronous calls my class could provide an OnComplete event and associated delegate which the caller could subscribe to.
Alternatively I could create an ICallback interface with an OnComplete method that the caller implements and then registers itself with the class that will then call that method on completion (i.e. the way Java handles these things).
I haven't seen that effect - I've certainly never encountered it being a bottleneck.
Here's a very rough-and-ready benchmark which shows (on my box anyway) delegates actually being faster than interfaces:
using System;
using System.Diagnostics;
interface IFoo
{
int Foo(int x);
}
class Program : IFoo
{
const int Iterations = 1000000000;
public int Foo(int x)
{
return x * 3;
}
static void Main(string[] args)
{
int x = 3;
IFoo ifoo = new Program();
Func<int, int> del = ifoo.Foo;
// Make sure everything's JITted:
ifoo.Foo(3);
del(3);
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
x = ifoo.Foo(x);
}
sw.Stop();
Console.WriteLine("Interface: {0}", sw.ElapsedMilliseconds);
x = 3;
sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
x = del(x);
}
sw.Stop();
Console.WriteLine("Delegate: {0}", sw.ElapsedMilliseconds);
}
}
Results (.NET 3.5; .NET 4.0b2 is about the same):
Interface: 5068
Delegate: 4404
Now I don't have particular faith that that means delegates are really faster than interfaces... but it makes me fairly convinced that they're not an order of magnitude slower. Additionally, this is doing almost nothing within the delegate/interface method. Obviously the invocation cost is going to make less and less difference as you do more and more work per call.
One thing to be careful of is that you're not creating a new delegate several times where you'd only use a single interface instance. This could cause an issue as it would provoke garbage collection etc. If you're using an instance method as a delegate within a loop, you will find it more efficient to declare the delegate variable outside the loop, create a single delegate instance and reuse it. For example:
Func<int, int> del = myInstance.MyMethod;
for (int i = 0; i < 100000; i++)
{
MethodTakingFunc(del);
}
is more efficient than:
for (int i = 0; i < 100000; i++)
{
MethodTakingFunc(myInstance.MyMethod);
}
Could this have been the problem you were seeing?
I find it completely implausible that a delegate is substantially faster or slower than a virtual method. If anything the delegate should be negligibly faster. At a lower level, delegates are usually implemented something like (using C-style notation, but please forgive any minor syntax errors as this is just an illustration):
struct Delegate {
void* contextPointer; // What class instance does this reference?
void* functionPointer; // What method does this reference?
}
Calling a delegate works something like:
struct Delegate myDelegate = somethingThatReturnsDelegate();
// Call the delegate in de-sugared C-style notation.
ReturnType returnValue =
(*((FunctionType) *myDelegate.functionPointer))(myDelegate.contextPointer);
A class, translated to C, would be something like:
struct SomeClass {
void** vtable; // Array of pointers to functions.
SomeType someMember; // Member variables.
}
To call a vritual function, you would do the following:
struct SomeClass *myClass = someFunctionThatReturnsMyClassPointer();
// Call the virtual function residing in the second slot of the vtable.
void* funcPtr = (myClass -> vtbl)[1];
ReturnType returnValue = (*((FunctionType) funcPtr))(myClass);
They're basically the same, except that when using virtual functions you go through an extra layer of indirection to get the function pointer. However, this extra indirection layer is often free because modern CPU branch predictors will guess the address of the function pointer and speculatively execute its target in parallel with looking up the address of the function. I've found (albeit in D, not C#) that virtual function calls in a tight loop are not any slower than non-inlined direct calls, provided that for any given run of the loop they're always resolving to the same real function.
Since CLR v 2, the cost of delegate invocation is very close to that of virtual method invocation, which is used for interface methods.
See Joel Pobar's blog.
I did some tests (in .Net 3.5... later I will check at home using .Net 4).
The fact is:
Getting an object as an interface and then executing the method is faster than getting a delegate from a method then calling the delegate.
Considering the variable is already in the right type (interface or delegate) and simple invoking it makes the delegate win.
For some reason, getting a delegate over an interface method (maybe over any virtual method) is MUCH slower.
And, considering there are cases when we simple can't pre-store the delegate (like in Dispatches, for example), that may justify why interfaces are faster.
Here are the results:
To get real results, compile this in Release mode and run it outside Visual Studio.
Checking direct calls twice
00:00:00.5834988
00:00:00.5997071
Checking interface calls, getting the interface at every call
00:00:05.8998212
Checking interface calls, getting the interface once
00:00:05.3163224
Checking Action (delegate) calls, getting the action at every call
00:00:17.1807980
Checking Action (delegate) calls, getting the Action once
00:00:05.3163224
Checking Action (delegate) over an interface method, getting both at
every call
00:03:50.7326056
Checking Action (delegate) over an interface method, getting the
interface once, the delegate at every call
00:03:48.9141438
Checking Action (delegate) over an interface method, getting both once
00:00:04.0036530
As you can see, the direct calls are really fast.
Storing the interface or delegate before, and then only calling it is really fast.
But having to get a delegate is slower than having to get an interface.
Having to get a delegate over an interface method (or virtual method, not sure) is really slow (compare the 5 seconds of getting an object as an interface to the almost 4 minutes of doing the same to get the action).
The code that generated those results is here:
using System;
namespace ActionVersusInterface
{
public interface IRunnable
{
void Run();
}
public sealed class Runnable:
IRunnable
{
public void Run()
{
}
}
class Program
{
private const int COUNT = 1700000000;
static void Main(string[] args)
{
var r = new Runnable();
Console.WriteLine("To get real results, compile this in Release mode and");
Console.WriteLine("run it outside Visual Studio.");
Console.WriteLine();
Console.WriteLine("Checking direct calls twice");
{
DateTime begin = DateTime.Now;
for (int i = 0; i < COUNT; i++)
{
r.Run();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
{
DateTime begin = DateTime.Now;
for (int i = 0; i < COUNT; i++)
{
r.Run();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.WriteLine();
Console.WriteLine("Checking interface calls, getting the interface at every call");
{
DateTime begin = DateTime.Now;
for (int i = 0; i < COUNT; i++)
{
IRunnable interf = r;
interf.Run();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.WriteLine();
Console.WriteLine("Checking interface calls, getting the interface once");
{
DateTime begin = DateTime.Now;
IRunnable interf = r;
for (int i = 0; i < COUNT; i++)
{
interf.Run();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.WriteLine();
Console.WriteLine("Checking Action (delegate) calls, getting the action at every call");
{
DateTime begin = DateTime.Now;
for (int i = 0; i < COUNT; i++)
{
Action a = r.Run;
a();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.WriteLine();
Console.WriteLine("Checking Action (delegate) calls, getting the Action once");
{
DateTime begin = DateTime.Now;
Action a = r.Run;
for (int i = 0; i < COUNT; i++)
{
a();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.WriteLine();
Console.WriteLine("Checking Action (delegate) over an interface method, getting both at every call");
{
DateTime begin = DateTime.Now;
for (int i = 0; i < COUNT; i++)
{
IRunnable interf = r;
Action a = interf.Run;
a();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.WriteLine();
Console.WriteLine("Checking Action (delegate) over an interface method, getting the interface once, the delegate at every call");
{
DateTime begin = DateTime.Now;
IRunnable interf = r;
for (int i = 0; i < COUNT; i++)
{
Action a = interf.Run;
a();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.WriteLine();
Console.WriteLine("Checking Action (delegate) over an interface method, getting both once");
{
DateTime begin = DateTime.Now;
IRunnable interf = r;
Action a = interf.Run;
for (int i = 0; i < COUNT; i++)
{
a();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.ReadLine();
}
}
}
Related
While analyzing an performance hit in our Windows CE based software, I stumbled upon a very
fascinating mystery:
Look at these two methods:
void Method1(List<int> list)
{
foreach (var item in list)
{
if (item == 2000)
break;
}
}
void Method2(List<int> list)
{
foreach (var item in (IEnumerable<int>)list)
{
if (item == 2000)
break;
}
}
void StartTest()
{
var list = new List<int>();
for (var i = 0; i < 3000; i++)
list.Add(i);
StartMeasurement();
Method1(list);
StopMeasurement(); // 1 ms
StartMeasurement();
Method2(list);
StopMeasurement(); // 721 ms
}
void StartMeasurement()
{
_currentStartTime = Environment.TickCount;
}
void StopMeasurement()
{
var time = Environment.TickCount - _currentStartTime;
Debug.WriteLine(time);
}
Method1 takes 1 ms to run. Method2 needs nearly 700 ms !
Don't try to reproduce this performance hit: it won't appear in a normal program on PC.
Unfortunately we can reproduce it in our software on our smart devices very reliably. The program runs on Compact Framework 3.5, Windows Forms, Windows CE 6.0.
The measurement uses Environment.TickCount.
As it is quite clear that there must be a strange bug in our software which slows down the enumerator, I simply can't imagine what kind of error could let the List class slow down, only if the iteration is using the IEnumerable interface of List.
And one more hint: After opening and closing a modal dialog (Windows Forms), suddenly both methods take the same time: 1 ms.
You need to run tests several times, because in a single run the CPU might get suspended, etc. It is for instance possible that while running method2, you are moving with your mouse resulting in the OS temporary letting the mouse driver run, etc. Or a network package arrives, or the timer says it is time to let another application run,... In other words there are a lot of reasons why all of a sudden your program stops running for a few milliseconds.
If I run the following program (note that using DateTime's, etc.) is not recommended:
var list = new List<int>();
for (var i = 0; i < 3000; i++)
list.Add(i);
DateTime t0 = DateTime.Now;
for(int i = 0; i < 50000; i++) {
Method1(list);
}
DateTime t1 = DateTime.Now;
for(int i = 0; i < 50000; i++) {
Method2(list);
}
DateTime t2 = DateTime.Now;
Console.WriteLine(t1-t0);
Console.WriteLine(t2-t1);
I get:
00:00:00.6522770 (method1)
00:00:01.2461630 (method2)
Swapping the order of testing results in:
00:00:01.1278890 (method2)
00:00:00.5473190 (method1)
So it's only 100% slower. Furthermore the performance of the first method (method1) is probably a bit better since for method1, the JIT compiler will first need to translate the code to machine instructions. In other words, the first method calls you do tend to be a bit slower than the ones later in the process..
The delay is probably caused because if you use a List<T>, the compiler can specialize the foreach loop: it already knows the structure of the IEnumerator<T> at compile time and can inline it if necessary.
If you use an IEnumerable<T>, the compiler must use virtual calls and lookup the exact methods using a vtable. This explains the time difference. Especially since you don't do much in your loop. In other words, the runtime must lookup which method to actually use, since the IEnumerable<T> could be anything: a LinkedList<T>, a HashSet<T>, a datastructure you made yourself,...
A general rule is: the higher the type of object in the class hierarchy the less the compiler knows about the real instance, the less it can optimize performance.
Maybe generating the template code the first time for the IEnumerable?
Many thanks for all your comments.
Our development team is analyzing this performance bug for nearly a week now
We run these tests several times in different order and different modules of the program
with and without compiler optimization. #CommuSoft: You are right that JIT needs more time to run code
for the first time. Unfortunately the result is always the same:
Method2 is about 700 times slower than Method1.
Maybe it's worth to mention again, that the performance hit appears untill we open and close any modal dialog in the program. It's not important what modal dialog. The performance hit will be fixed right after the
method Dispose() of the base class Form has been called. (The Dispose method hasn't been
overriden by a derived class)
On my way of analyzing the bug I stepped deeply into the framework and found out now,
that List can't be the reason for the performance hit. Look at this piece of code:
class Test
{
void Test()
{
var myClass = new MyClass();
StartMeasurement();
for (int i = 0; i < 5000; i++)
{
myClass.DoSth();
}
StopMeasurement(); // ==> 46 ms
var a = (IMyInterface)myClass;
StartMeasurement();
for (int i = 0; i < 5000; i++)
{
a.DoSth();
}
StopMeasurement(); // ==> 665 ms
}
}
public interface IMyInterface
{
void DoSth();
}
public class MyClass : IMyInterface
{
public void DoSth()
{
for (int i = 0; i < 10; i++ )
{
double a = 1.2345;
a = a / 19.44;
}
}
}
To call a method via the interface needs much more time than calling it directly.
But of course after closing our dubious dialog we measured between 44 and 45 ms for both loops.
Can you help explain how multiple threads access static methods? Are multiple threads able to access the static method concurrently?
To me it would seem logical that if a method is static that would make it a single resouce that is shared by all the threads. Therefore only one thread would be able to use it at a time. I have created a console app to test this. But from the results of my test it would appear that my assumption is incorrect.
In my test a number of Worker objects are constructed. Each Worker has a number of passwords and keys. Each Worker has an instance method that hashes it's passwords with it's keys. There is also a static method which has exactly the same implementation, the only difference being that it is static. After all the Worker objects have been created the start time is written to the console. Then a DoInstanceWork event is raised and all of the Worker objects queue their useInstanceMethod to the threadpool. When all the methods or all the Worker objects have completed the time it took for them all to complete is calculated from the start time and is written to the console. Then the start time is set to the current time and the DoStaticWork event is raised. This time all the Worker objects queue their useStaticMethod to the threadpool. And when all these method calls have completed the time it took until they had all completed is again calculated and written to the console.
I was expecting the time taken when the objects use their instance method to be 1/8 of the time taken when they use the static method. 1/8 because my machine has 4 cores and 8 virtual threads. But it wasn't. In fact the time taken when using the static method was actually fractionally faster.
How is this so? What is happening under the hood? Does each thread get it's own copy of the static method?
Here is the Console app-
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Threading;
namespace bottleneckTest
{
public delegate void workDelegate();
class Program
{
static int num = 1024;
public static DateTime start;
static int complete = 0;
public static event workDelegate DoInstanceWork;
public static event workDelegate DoStaticWork;
static bool flag = false;
static void Main(string[] args)
{
List<Worker> workers = new List<Worker>();
for( int i = 0; i < num; i++){
workers.Add(new Worker(i, num));
}
start = DateTime.UtcNow;
Console.WriteLine(start.ToString());
DoInstanceWork();
Console.ReadLine();
}
public static void Timer()
{
complete++;
if (complete == num)
{
TimeSpan duration = DateTime.UtcNow - Program.start;
Console.WriteLine("Duration: {0}", duration.ToString());
complete = 0;
if (!flag)
{
flag = true;
Program.start = DateTime.UtcNow;
DoStaticWork();
}
}
}
}
public class Worker
{
int _id;
int _num;
KeyedHashAlgorithm hashAlgorithm;
int keyLength;
Random random;
List<byte[]> _passwords;
List<byte[]> _keys;
List<byte[]> hashes;
public Worker(int id, int num)
{
this._id = id;
this._num = num;
hashAlgorithm = KeyedHashAlgorithm.Create("HMACSHA256");
keyLength = hashAlgorithm.Key.Length;
random = new Random();
_passwords = new List<byte[]>();
_keys = new List<byte[]>();
hashes = new List<byte[]>();
for (int i = 0; i < num; i++)
{
byte[] key = new byte[keyLength];
new RNGCryptoServiceProvider().GetBytes(key);
_keys.Add(key);
int passwordLength = random.Next(8, 20);
byte[] password = new byte[passwordLength * 2];
random.NextBytes(password);
_passwords.Add(password);
}
Program.DoInstanceWork += new workDelegate(doInstanceWork);
Program.DoStaticWork += new workDelegate(doStaticWork);
}
public void doInstanceWork()
{
ThreadPool.QueueUserWorkItem(useInstanceMethod, new WorkerArgs() { num = _num, keys = _keys, passwords = _passwords });
}
public void doStaticWork()
{
ThreadPool.QueueUserWorkItem(useStaticMethod, new WorkerArgs() { num = _num, keys = _keys, passwords = _passwords });
}
public void useInstanceMethod(object args)
{
WorkerArgs workerArgs = (WorkerArgs)args;
for (int i = 0; i < workerArgs.num; i++)
{
KeyedHashAlgorithm hashAlgorithm = KeyedHashAlgorithm.Create("HMACSHA256");
hashAlgorithm.Key = workerArgs.keys[i];
byte[] hash = hashAlgorithm.ComputeHash(workerArgs.passwords[i]);
}
Program.Timer();
}
public static void useStaticMethod(object args)
{
WorkerArgs workerArgs = (WorkerArgs)args;
for (int i = 0; i < workerArgs.num; i++)
{
KeyedHashAlgorithm hashAlgorithm = KeyedHashAlgorithm.Create("HMACSHA256");
hashAlgorithm.Key = workerArgs.keys[i];
byte[] hash = hashAlgorithm.ComputeHash(workerArgs.passwords[i]);
}
Program.Timer();
}
public class WorkerArgs
{
public int num;
public List<byte[]> passwords;
public List<byte[]> keys;
}
}
}
Methods are code - there's no problem with thread accessing that code concurrently since the code isn't modified by running it; it's a read-only resource (jitter aside). What needs to be handled carefully in multi-threaded situations is access to data concurrently (and more specifically, when modifying that data is a possibility). Whether a method is static or an instance method has nothing to do with whether or not it needs to ne serialized in some way to make it threadsafe.
In all cases, whether static or instance, any thread can access any method at any time unless you do explicit work to prevent it.
For example, you can create a lock to ensure only a single thread can access a given method, but C# will not do that for you.
Think of it like watching TV. A TV does nothing to prevent multiple people from watching it at the same time, and as long as everybody watching it wants to see the same show, there's no problem. You certainly wouldn't want a TV to only allow one person to watch it at once just because multiple people might want to watch different shows, right? So if people want to watch different shows, they need some sort of mechanism external to the TV itself (perhaps having a single remote control that the current viewer holds onto for the duration of his show) to make sure that one guy doesn't change the channel to his show while another guy is watching.
C# methods are "reentrant" (As in most languages; the last time I heard of genuinely non-reentrant code was DOS routines) Each thread has its own call stack, and when a method is called, the call stack of that thread is updated to have space for the return address, calling parameters, return value, local values, etc.
Suppose Thread1 and Thread2 calls the method M concurrently and M has a local int variable n. The call stack of Thread1 is seperate from the call stack of Thread2, so n will have two different instantiations in two different stacks. Concurrency would be a problem only if n is stored not in a stack but say in the same register (i.e. in a shared resource) CLR (or is it Windows?) is careful not to let that cause a problem and cleans, stores and restores the registers when switching threads. (What do you do in presence of multiple CPU's, how do you allocate registers, how do you implement locking. These are indeed difficult problems that makes one respect compiler, OS writers when one comes to think of it)
Being reentrant does not prove no bad things happen when two threads call the same method at the same time: it only proves no bad things happen if the method does not access and update other shared resources.
When you access an instance method, you are accessing it through an object reference.
When you access a static method, you are accessing it directly.
So static methods are a tiny bit faster.
When you instanciate a class you dont create a copy of the code. You have a pointer to the definition of the class, and the code is acceded through it. So, instance methods are accessed the sane way than static methods
I have written a log class and a function as in the following code:
Log(System.Reflection.MethodBase methodBase, string message)
Every time I log something I also log the class name from the methodBase.Name and methodBase.DeclaringType.Name.
I read the following post Using Get CurrentMethod and I noticed that this method is slow.
Should I use the this.GetType() instead of System.Reflection.MethodBase or I should manually log the class/method name in my log e.g. Log("ClassName.MethodName", "log message)? What is the best practice?
It really depends.
If you use the this.GetType() approach you will lose the method information, but you will have a big performance gain (apparently a factor of 1200, according to your link).
If you offer an interface that lets the caller supply strings (e.g. Log("ClassName.MethodName", "log message"), you will probably gain even better performance, but this makes your API less friendly (the calling developer has to supply the class name and method name).
I know this is an old question, but I figured I'd throw out a simple solution that seems to perform well and maintains symbols
static void Main(string[] args)
{
int loopCount = 1000000; // 1,000,000 (one million) iterations
var timer = new Timer();
timer.Restart();
for (int i = 0; i < loopCount; i++)
Log(MethodBase.GetCurrentMethod(), "whee");
TimeSpan reflectionRunTime = timer.CalculateTime();
timer.Restart();
for (int i = 0; i < loopCount; i++)
Log((Action<string[]>)Main, "whee");
TimeSpan lookupRunTime = timer.CalculateTime();
Console.WriteLine("Reflection Time: {0}ms", reflectionRunTime.TotalMilliseconds);
Console.WriteLine(" Lookup Time: {0}ms", lookupRunTime.TotalMilliseconds);
Console.WriteLine();
Console.WriteLine("Press Enter to exit");
Console.ReadLine();
}
public static void Log(Delegate info, string message)
{
// do stuff
}
public static void Log(MethodBase info, string message)
{
// do stuff
}
public class Timer
{
private DateTime _startTime;
public void Restart()
{
_startTime = DateTime.Now;
}
public TimeSpan CalculateTime()
{
return DateTime.Now.Subtract(_startTime);
}
}
Running this code gives me the following results:
Reflection Time: 1692.1692ms
Lookup Time: 19.0019ms
Press Enter to exit
For one million iterations, that's not bad at all, especially compared to straight up reflection. The method group is being cast to a Delegate type, you maintain a symbolic link all the way into the logging. No goofy magic strings.
I'm doing practice problems from MCTS Exam 70-536 Microsft .Net Framework Application Dev Foundation, and one of the problems is to create two classes, one generic, one object type that both perform the same thing; in which a loop uses the class and iterated over thousand times. And using the timer, time the performance of both. There was another post at C# generics question that seeks the same questoion but nonone replied.
Basically if in my code I run the generic class first it takes loger to process. If I run the object class first than the object class takes longer to process. The whole idea was to prove that generics perform faster.
I used the original users code to save me some time. I didn't particularly see anything wrong with the code and was puzzled by the outcome. Can some one explain why the unusual results?
Thanks,
Risho
Here is the code:
class Program
{
class Object_Sample
{
public Object_Sample()
{
Console.WriteLine("Object_Sample Class");
}
public long getTicks()
{
return DateTime.Now.Ticks;
}
public void display(Object a)
{
Console.WriteLine("{0}", a);
}
}
class Generics_Samle<T>
{
public Generics_Samle()
{
Console.WriteLine("Generics_Sample Class");
}
public long getTicks()
{
return DateTime.Now.Ticks;
}
public void display(T a)
{
Console.WriteLine("{0}", a);
}
}
static void Main(string[] args)
{
long ticks_initial, ticks_final, diff_generics, diff_object;
Object_Sample OS = new Object_Sample();
Generics_Samle<int> GS = new Generics_Samle<int>();
//Generic Sample
ticks_initial = 0;
ticks_final = 0;
ticks_initial = GS.getTicks();
for (int i = 0; i < 50000; i++)
{
GS.display(i);
}
ticks_final = GS.getTicks();
diff_generics = ticks_final - ticks_initial;
//Object Sample
ticks_initial = 0;
ticks_final = 0;
ticks_initial = OS.getTicks();
for (int j = 0; j < 50000; j++)
{
OS.display(j);
}
ticks_final = OS.getTicks();
diff_object = ticks_final - ticks_initial;
Console.WriteLine("\nPerformance of Generics {0}", diff_generics);
Console.WriteLine("Performance of Object {0}", diff_object);
Console.ReadKey();
}
}
Well, the first problem I can see is that you're using the DateTime object to measure time in your application (for a very small interval).
You should be using the Stopwatch class. It offers better precision when trying to benchmark code.
The second problem is that you're not allowing for JIT (Just-In-Time compilation). The first call to your code is going to take longer simply because it has to be JIT'd. After that, you'll get your results.
I would make a single call in to your code before you start timing things so you can get an accurate idea of what is happening during the loop.
You should run both classes a separate time before timing it to allow the JITter to run.
Your test is incorrect. Here are your methods:
public void display(T a)
{
Console.WriteLine("{0}", a); // Console.WriteLine(string format, params object[] args) <- boxing is performed here
}
public void display(Object a)// <- boxing is performed here
{
Console.WriteLine("{0}", a);
}
So, in both cases you are using boxing. Much better would be if your class, for example, will count total sum of values, like:
public void add(long a)
{
Total += a;
}
public void display(Object a)// <- boxing is performed here
{
Total += (long) a;// <- unboxing is performed here
}
Your timed code includes a Console.WriteLine(). That will take up 99.999999% of the time.
Your assumption that generic will be faster in this situation is wrong. You may have misinterpreted a remark about non-generic collection classes.
This won't be on he exam.
why would it be faster? both ints must be boxed in order to use Console.WriteLine(string, object)
edit: ToString() itself does not seem to cause boxing
http://weblogs.asp.net/ngur/archive/2003/12/16/43856.aspx
so when you use Console.WriteLine(a); which would call Console.WriteLine(Int32) that should work i guess (i would need to look into reflector to confirm this)
This question already has answers here:
Does using delegates slow down my .NET programs?
(4 answers)
Closed 9 years ago.
Consider the following code:
if (IsDebuggingEnabled) {
instance.Log(GetDetailedDebugInfo());
}
GetDetailedDebugInfo() may be an expensive method, so we only want to call it if we're running in debug mode.
Now, the cleaner alternative is to code something like this:
instance.Log(() => GetDetailedDebugInfo());
Where .Log() is defined such as:
public void Log(Func<string> getMessage)
{
if (IsDebuggingEnabled)
{
LogInternal(getMessage.Invoke());
}
}
My concern is with performance, preliminary testing doesn't show the second case to be particularly more expensive, but I don't want to run into any surprises if load increases.
Oh, and please don't suggest conditional compilation because it doesn't apply to this case.
(P.S.: I wrote the code directly in the StackOverflow Ask a Question textarea so don't blame me if there are subtle bugs and it doesn't compile, you get the point :)
No, it shouldn't have a bad performance. After all, you'll be calling it only in debug mode where performance is not at the forefront. Actually, you could remove the lambda and just pass the method name to remove the overhead of an unnecessary intermediate anonymous method.
Note that if you want to do this in Debug builds, you can add a [Conditional("DEBUG")] attribute to the log method.
There is a difference in performance. How significant it is will depend on the rest of your code so I would recommend profiling before embarking on optimisations.
Having said that for your first example:
if (IsDebuggingEnabled)
{
instance.Log(GetDetailedDebugInfo());
}
If IsDebuggingEnabled is static readonly then the check will be jitted away as it knows it can never change. This means that the above sample will have zero performance impact if IsDebuggingEnabled is false, because after the JIT is done the code will be gone.
instance.Log(() => GetDetailedDebugInfo());
public void Log(Func<string> getMessage)
{
if (IsDebuggingEnabled)
{
LogInternal(getMessage.Invoke());
}
}
The method will be called every time instance.Log is called. Which will be slower.
But before expending time with this micro optimization you should profile your application or run some performance tests to make sure this is actually a bottle neck in your application.
I was hoping for some documentation regarding performance in such cases, but it seems that all I got were suggestions on how to improve my code... No one seems to have read my P.S. - no points for you.
So I wrote a simple test case:
public static bool IsDebuggingEnabled { get; set; }
static void Main(string[] args)
{
for (int j = 0; j <= 10; j++)
{
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i <= 15000; i++)
{
Log(GetDebugMessage);
if (i % 1000 == 0) IsDebuggingEnabled = !IsDebuggingEnabled;
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
Console.ReadLine();
for (int j = 0; j <= 10; j++)
{
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i <= 15000; i++)
{
if (IsDebuggingEnabled) GetDebugMessage();
if (i % 1000 == 0) IsDebuggingEnabled = !IsDebuggingEnabled;
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
Console.ReadLine();
}
public static string GetDebugMessage()
{
StringBuilder sb = new StringBuilder(100);
Random rnd = new Random();
for (int i = 0; i < 100; i++)
{
sb.Append(rnd.Next(100, 150));
}
return sb.ToString();
}
public static void Log(Func<string> getMessage)
{
if (IsDebuggingEnabled)
{
getMessage();
}
}
Timings seem to be exactly the same between the two versions.
I get 145 ms in the first case, and 145 ms in the second case
Looks like I answered my own question.
You can also do this:
// no need for a lambda
instance.Log(GetDetailedDebugInfo)
// Using these instance methods on the logger
public void Log(Func<string> detailsProvider)
{
if (!DebuggingEnabled)
return;
this.LogImpl(detailsProvider());
}
public void Log(string message)
{
if (!DebuggingEnabled)
return;
this.LogImpl(message);
}
protected virtual void LogImpl(string message)
{
....
}
Standard answers:
If you gotta do it, you gotta do it.
Loop it 10^9 times, look at a stopwatch, & that tells you how many nanoseconds it takes.
If your program is big, chances are you have bigger problems elsewhere.
Call getMessage delegate directly instead of calling Invoke on it.
if(IsDebuggingEnabled)
{
LogInternal(getMessage());
}
You should also add null check on getMessage.
I believe delegates create a new thread, so you may be right about it increasing performance.
Why not set up a test run like Dav suggested, and keep a close eye on the number of threads spawned by your app, you can use Process Explorer for that.
Hang on! I've been corrected! Delegates only use threads when you use 'BeginInvoke'... so my above comments don't apply to the way you're using them.