Archive for April, 2008

Performance impact of the readonly keyword

Julien on Apr 22nd 2008

I've heard from a co-worker that the readonly keyword was optimizing memory access and therefore quicker than a normal field access. I must admit that I found this assertion a bit surprising. My first bet would have been that the performance are identical with or without it (it's just a compiler check, but it doesn't result in any change at execution). If wrong, I then would have bet on a slower access (I would expect the CLR to do some checks when accessing the field). Let's see if I'm mistaken :).

Unfortunately for me, I didn't find anything to confirm or not my theories, so I decided to do my own micro-benchmark.

I measured the time spent for 3 main scenarios, with a read only field and without it:
- Scenario 1: Creating an object
- Scenario 2: Accessing the field
- Scenario 3: Creating an object and accessing the field

I executed this code 1,000,000,000 times for each scenario and ran each scenario 10 times on 4 different PC to get a meaningful average. For each test, I excluded the top and bottom result.
The code (in C#, .NET 2.0) is available here (It is duplicated for each test, I know it's horrible, my apologies :)), and the results here.

Each test looks like that (with sligh modifications of course):

  1. _streamWriter.WriteLine();
  2. _streamWriter.WriteLine("Obj creation & access in loop");
  3. for (int j = 0; j < _numberOfTestExecutions; j++)
  4. {
  5. Poco poco = new Poco();
  6.  
  7. Stopwatch watch = new Stopwatch();
  8. watch.Start();
  9. for (int i = 0; i < _numberOfIterationPerTest; i++)
  10. {
  11. ReadOnlyField objReadOnlyField = new ReadOnlyField(poco);
  12. Poco myCopyOfPoco = objReadOnlyField.Poco;
  13. }
  14. watch.Stop();
  15. _streamWriter.Write(watch.ElapsedMilliseconds + ";");
  16.  
  17. watch.Reset();
  18. watch.Start();
  19. for (int i = 0; i < _numberOfIterationPerTest; i++)
  20. {
  21. ReadWriteField objReadWriteField = new ReadWriteField(poco);
  22. Poco myCopyOfPoco = objReadOnlyField.Poco;
  23. }
  24. watch.Stop();
  25. _streamWriter.WriteLine(watch.ElapsedMilliseconds);
  26. }

Here are the raw numbers:

Scenario 1: Creating an object
- read only: 25172ms
- read write: 24983ms
Read only is in average 0.76% slower than read write.

Scenario 2: Accessing the field
- read only: 6437ms
- read write: 6449ms
Read only is in average 0.19% quicker than read write.

Scenario 3: Creating an object and accessing the field
- read only: 19929ms
- read write: 19761ms
Read only is in average 0.85% slower than read write.

However, you can see greater differences by looking at the results for each computer. For instance, on the first PC I used (a core 2 duo, 2,8Ghz, DDR2 800Mhz), I have the following results:

- Scenario 1: Creating an object
Read only is in average 5.72% quicker than read write.
- Scenario 2: Accessing the field
Read only is in average 0.94% quicker than read write.
- Scenario 3: Creating an object and accessing the field
Read only is in average 2.28% quicker than read write.

And on a laptop (centrino 1,7ghz, DDR):
- Scenario 1: Creating an object
Read only is in average 6.34% slower than read write.
- Scenario 2: Accessing the field
Read only is in average 0.21% quicker than read write.
- Scenario 3: Creating an object and accessing the field
Read only is in average 3.01% slower than read write.

My (own) conclusions:
There seem to be a difference of performance involved by using the readonly keyword. The problem is that the impact is highly dependant on the hardware. On a PC with decent hardware, accessing a read only field is between 1% and 2.5% quicker than accessing a normal field. Object creation can be as much as 6% quicker. On lower-end hardware, the results are the opposite.
However, the tests have been made with very simple class, so keep in mind that in reality, the speed difference in object creation would have been smaller with classes that have more members.

As far as I'm concerned, I would not used the readonly keyword just for optimization purposes except for very demanding situations, and only after checking that it's actually quicker on the specifics machines where the software is going to run. So unless your application is:
- running on a very controlled environment with a very limited set of installations
- pseudo real-time or extremely sensible to performances
I don't think you should even wonder about the performance impact of readonly. There's probably hundreds of optimization that will be more effective before this one!

Finally, if you have any clue showing a different behaviour, please tell me about it and I will edit this post in consequence :). I'm specially interested in having benchmark with Xeon processors (unfortunately, I don't have access to one)

Filed in .NET | 6 responses so far

Keep your objects in a consistent state

Julien on Apr 12th 2008

Part of a good object oriented design is to keep the objects in a correct state.

For instance, in the financial world, we have financial instruments called "derivatives". According to Wikipedia:

Derivatives are financial instruments whose value changes in response to the changes in underlying variables. The main types of derivatives are futures, forwards, options, and swaps.

In the real world, a derivative can't exist if there isn't an underlying financial instrument associated. A future on the dow jones could not have been created without the dow jones in the first place. If we want to represent a derivative in a software, we must make sure that we follow the same rule.

So let's assume that I have the following class:

  1. class Derivative
  2. {
  3. private string _name;
  4. private Instrument _underlyingInstrument ;
  5.  
  6. public string Name
  7. {
  8. get { return _name; }
  9. }
  10.  
  11. public Instrument UnderlyingInstrument
  12. {
  13. get { return _underlyingInstrument; }
  14. }
  15.  
  16. public Derivative(string name, Instrument underlyingInstrument)
  17. {
  18. _name = name;
  19. _underlyingInstrument = underlyingInstrument;
  20. }
  21. }

Any new developer on a project that uses this Derivative class will mentally map the Derivative class to the corresponding financial concept. He will expect the UnderlyingInstrument property to return a non-null object. However, this is not guaranteed in the current implementation. As a matter of fact, this class can currently be used to only convey the name of a Derivative. If we wanted to do that, we would need to create a new class for that purpose only. So in the mean time, if we want our code to stay in a maintainable state, we need to make sure that each Derivative object will be constructed correctly. If not, different people will make different usage of the class.

In that case, ensuring the correctness of the object can be done very easily. We just need to do a bit of Design By Contract. So our constructor will become:

  1. public Derivative(string name, Instrument underlyingInstrument)
  2. {
  3. if(name == null || name.Length == 0)
  4. {
  5. throw new Exception("The name of the derivative can't be null or empty");
  6. }
  7. else if(underlyingInstrument == null)
  8. {
  9. throw new Exception("A derivative must have an underlying instrument");
  10. }
  11.  
  12. _name = name;
  13. _underlyingInstrument = underlyingInstrument ;
  14. }

Now you're sure that a fellow developer won't use your object to do a weird thing :).

Of course, you can improve the clarity of this piece of code significantly by using various techniques and frameworks(including Debug.Assert or your own Assert class). For instance, I would write something like that:

  1. public Derivative(string name, Instrument underlyingInstrument )
  2. {
  3. Guard.Against(name == null, "The name of the derivative can't be null");
  4. Guard.Against(name.Length == 0, "The name of the derivative can't be empty");
  5. Guard.Against(underlyingInstrument == null, "The underlying instrument of the derivative can't be null");
  6.  
  7. _name = name;
  8. _underlyingInstrument = underlyingInstrument;
  9. }

But that's a topic for another day!

Filed in .NET, General development | 2 responses so far

AutoResetEvent vs ManualResetEvent: beware!

Julien on Apr 7th 2008

I did load testing last week on the component I am developing and found out that the performances were just miserable... It was barely capable of handling 60 messages per seconds which was: 1) bad and 2) surprising! (Basically it's doing some kind of real-time caching/transformation/redirection of messages).

I then spent 5mins in dotrace trying to get a picture of what was going on. I found that in the thread that is monitoring the queue and sending messages, I had used an instance of ManualResetEvent instead of AutoResetEvent.

If you never used them, these 2 classes allow you to send signals between 2 threads. That way, the "monitor" thread is not wasting any resources until it's notified by the other thread that there is something in the queue. For instance, Thread 1 will wait for a queue to be filled with something like that:

  1.  
  2. private AutoResetEvent _mySignal = new AutoResetEvent(false);
  3.  
  4. private void MonitorQueue()
  5. {
  6. while(!monitorQueue)
  7. {
  8. _mySignal.WaitOne();
  9. GetItemsInTheQueueAndDoStuff();
  10. }
  11. }

And thread 2 will inject data in the queue:

  1.  
  2. public void EnqueueItem(Item myItem)
  3. {
  4. InsertInQueue(myItem);
  5. _mySignal.Set();
  6. }
  7.  

As I said, my problem is that I used a ManualResetEvent instead of an AutoResetEvent. These 2 classes are almost the same except that when you use ManualResetEvent, you need to reset the signal manually with mySignal.Reset();. In my case, instead of blocking on mySignal.WaitOne(); the code was constantly looping and using a lot of CPU!

I fixed it and reran the load testing: now I'm at 5000 messages per seconds at 40% CPU. Much better!

Filed in .NET | One response so far

lock(this): don’t!

Julien on Apr 4th 2008

I've seen that kind of things in several codebases recently:

  1. lock(this)
  2. {
  3. // Do stuff...
  4. }

Even if it perfectly works, this is a bad idea. You should never (or at least I can't think of a good reason!) lock on a public type, therefore including "this". There is a simple reason: you don't know what expectations the caller is doing.

Let's take a simple example. In the following code, we have a class that uses a lock on this (ClassThatLocksItself) and another class that is going to call it (CallerClass). When CallerClass calls ClassThatLocksItself, it's going to lock on the instance of ClassThatLocksItself.

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. ClassThatLocksItself myObj = new ClassThatLocksItself();
  6.  
  7. CallerClass caller = new CallerClass(myObj);
  8. caller.LockTheObjectInAThread();
  9. Thread.Sleep(500);
  10.  
  11. myObj.LockMe();
  12. }
  13. }
  14.  
  15. class CallerClass
  16. {
  17. private ClassThatLocksItself _myObj;
  18. public CallerClass(ClassThatLocksItself myObj)
  19. {
  20. _myObj = myObj;
  21. }
  22.  
  23. public void LockTheObjectInAThread()
  24. {
  25. ThreadPool.QueueUserWorkItem(LockTheObject);
  26. }
  27.  
  28. public void LockTheObject(object state)
  29. {
  30. Console.WriteLine("Acquiring lock on the object");
  31. lock (_myObj)
  32. {
  33. Thread.Sleep(100000); // Do a long computation
  34. }
  35. Console.WriteLine("Releasing lock on the object");
  36. }
  37. }
  38.  
  39. public class ClassThatLocksItself
  40. {
  41. public void LockMe()
  42. {
  43. Console.WriteLine("ClassThatLocksItself -- Trying to acquire lock on this");
  44. lock (this)
  45. {
  46. Console.WriteLine("ClassThatLocksItself -- lock on this acquired");
  47. }
  48. Console.WriteLine("ClassThatLocksItself -- lock on this released");
  49. }

If you try to execute this code, you'll notice that Console.WriteLine("ClassThatLocksItself -- lock on this acquired"); is only executed when LockTheObject() returns (here it takes 100 seconds). By using lock(this), you became dependant on externals and unknowns factors (in that case, the caller of your code decided to lock on your class). The situation is even a lot worse for developers who want to reuse your ClassThatLocksItself: they have no way of knowing that there can be a synchronisation problem unless they read the code of your class!

Now, try to guess what is going to happen if you change the implementation of LockTheObject with the following:

  1. public void LockTheObject(object state)
  2. {
  3. Console.WriteLine("Acquiring lock on the object");
  4. lock (_myObj)
  5. {
  6. _myObj.LockMe(); // will not lock!
  7. }
  8. Console.WriteLine("Releasing lock on the object");
  9. }

Most of you will bet on a deadlock I guess. However, the CLR is intelligent enough to detect that when LockMe executes lock(this), the lock was already acquired by the caller. Therefore, it doesn't block on it. It makes the whole lock(this) thing very subtile: you'll only see a problem in some specific cases.

Continue Reading »

Filed in .NET | One response so far

Yet another blogger on earth!

Julien on Apr 4th 2008

Hi guys, welcome on this new blog!

Like many people, I learned a lot by reading posts from various very good writers (Think Jeremy Miller, JP Boodhoo, Martin Fowler, and dozens of others!). Since I discovered their blogs, their knowledge has always been useful to me. Even if I don't know them personally, they helped me a lot in improving my skills as a developer. In a few words, I owe them a lot!

Starting this blog is a way to try repaying my debt to the community as a whole at my humble level. As a matter of fact, I feel that there's still a lot to do to improve the way we do software development. Even if there are some excellent books and articles available on internet, most people I've been working with have always been foreigners to topics such as design patterns, testing, agiles methodologies, etc. Even if I don't have the expertise of all the people above (and I also don't claim to master any of these topics myself!), hopefully, I'll be able to convey good practices and ideas too. Who knows, maybe I'll even make a small difference around me! :)

Let me also give you a quick background about myself. I'm a French guy working as a .NET developer in the financial industry. I spent the last year in London working for a hedge-fund, and I moved back to Paris in February where I started a new job in a consulting company. Before that, I was studying computer science in a French engineering school which also lead me to do several internships. I also started a company during that time but it's an old story! Bottom line: I'm still very young and I still have a lot to learn!

Finally, while I'm here, I also apologize in advance for all the spelling mistakes that I'll do in my posts. Please feel free to correct me whenever you spot one (that is probably every 5 words!).

See you!

By the way, I'm also opening a french version of this blog here: www.thedotnetfrog.fr

Filed in various stuff | One response so far