The CLR team is speaking at the Atlanta C# User Group. Tonight just simply rocked.
Kit George opened the show tonight by demonstrating the new GC.MemoryPressure API as well as the newly added TryParse method on value types. And one of my favorite demos... Space Invaders written in managed code, in a console app... then he used a device to connect to a serial port and played the game in front of everyone. Who knew that serial I/O was the #1 requested feature for the .NET FCL?
Brad Abrams then talked about CLR Internals. You have got to love a talk where you start the talk opening notepad.exe and compiling command-line using csc.exe. The next part of his talk was about when verification takes place, how the CLR loads an assembly, and how it fixes up the address for the x86 instruction during JIT compilation so that further evalations jump straight to the x86. Another interesting point...
This routine will optimize out the bounds check because the CLR knows you are not going to walk off the end of the array...
for(i=0;i<myArray.Length;i++) { Console.WriteLine(myArray[0].ToString()); }
This one will not:
for(i=0;i<myArray.Length - 6;i++) { Console.WriteLine(myArray[0].ToString()); }
My personal favorite (largely because it was info I have not seen before in a presentation or haven't presented myself...) was Claudio Caldato's presentation on performance.
Claudio Caldato wrapped up the evening with a discussion on performance. Perf is not something you address once, perf is something you address continually. This should be a mantra for developers.. "I will measure my code... I will measure my code..." There was a great discussion on knowing what GC does and what causes something to be in gen 1 or 2, and why you should avoid gen 2. use perfomon counters to monitor as well as CLRProfiler.
And my favorite... the CLRProfiler!
Had a loop that appends a string with an int 10,000 times. Ran CLRProfiler.
Allocated bytes, it allocates 1.7 Gigs over its lifecycle. It was moving 15 megs of memory, due to GC compacting memory. Gen 0 collections had more than 3,000 gen 0 collections.
Then used a StringBuilder...
21 Megs allocated. 213 K reallocated, and only 40 gen 0 collections. The timeline between them showed much less thrash and memory went to nearly zero.
Ran profiler on 100,000 iterations with a SolidBrush (which includes a finalizer). Allocated, 8 meg, realllocation, 3 meg. TimeLine shows that finalized objects are moved into the finalize queue and memory increases until collection occurs. Changed this to use a C# using statement... 8 meg, 10K reallocated... timeline shows the triangular shape that is desirable rather than the "step" shape that you see without the "using" statement.
Reflection:
P/Invoke, COM interop cost
Deployment
XML
And then the icing on the cake...
In Visual Studio 2005, use Performance Tools wizard and set up a performance session using instrumentation or sampling. It collects data, allows you to see the same type of information that CLRProfiler shows, and you can drill down into the methods to do more investigation.
I'll admit it. I have never liked the "using" keyword in C#. I prefered the try-catch-finally...