前进's profile当我不存在PhotosBlogListsMore ![]() | Help |
|
May 09 [Program tip]Field access versus local variable access performanceField access versus local variable access performanceRecently, I was at a customer site and they were comparing the performance of a function that was written in unmanaged C with its C# equivalent. As they expected, the C code was performing much faster than the C# code. However, I didn't expect this. Once managed code is JIT compiled, the code is very similar to that of unmanaged code. The code was being called in a loop in both versios numerous times so the additional time spent by the JIT compiler should be noise and I expect the performance of the C# code to be near identical and even better than the unmanaged C version because the JIT compiler could emit optimizations for the speciifc CPU architecture of the host machine. I was very interested in this problem and I closely examined both functions. Not just the source code, but I also very closely examined the machine code generated by the unmanaged C compiler as well as the machine code generated by the .NET Framework's JIT compiler. Not surprising (to me), the machine code was pratically identical. I did see a place where the C compiler emitted an INCrement instruction where th JIT compiler emitted an ADD instruction to add 1. I assume that this is because the JIT compiler knew the host CPU and determined that an ADD instruction would be faster than an INCrement instruction. This would actually make the managed code version faster. I also noticed a place where the unmanaged version was updating a register directly where the managed version was updating a indirect memory location. This was because the unmanaged source code was updating a local variable while the C# version was turned into an object-oriented equivalent and as updating a field in the class object. This difference alse seemed minor to me and could not possibly accounting for the performance discrepency we were seeing. However, we continued to examine the code and in an effort to get the emitted machine code to be identical between the 2 as possible, we got rid of the field in the object and turned it into a local variable instead. WOW! What a difference this made in performance! Apparently, the JIT compiler is able to enregister local variables but it cannot enregister fields. This makes sense since a field can actually be manipulated by multiple threads simultaneously or via other means behind a method's back and therefore, the JIT compiler takes the safe route of not enregisterring the local and always saves and fetches its value from memory. On the other hand, a local variable cannot be modified behind a method's back and therefor the JIT compiler can put it in a register. I always knew that memory access is slower than CPU register access but I guess I nenver really knew how big a difference it could be. On the machine we were using to test this, the differenece was about 8 times. That is, the method with the field ran 8 times slower than the equivalent method with the local variable! On my notebook computer, the difference was much less: the local variable version ran in ~25 seconds while the field version ran in ~31 seconds. Still a pretty big difference. So, the moral of the story, is that you should avoid field access as much as possible in performance-sensitive code. It might even make sense to copy a field into a loca, use the local in the method and then copy the result back from the local into the field just before the method exits. Below is some simple code (that requires Whidbey because I'm using the Stopwatch class) that you can compile and test on your own machine to see the perf difference: using System; class App { Stopwatch sw = Stopwatch.StartNew(); sw = Stopwatch.StartNew(); private static Int64 j; public static void TestLocalAccess(Int64 numIncrement) { public static void TestFieldAccess(Int64 numIncrement) { for(Int64 i=0; i<numIncrement; i++) j++; Posted Saturday, November 13, 2004 11:09 PM by JeffreyR | 7 Comments Filed under: Jeffrey Richter September 22 思念是一种折磨……当看着自己的思念随风飘去, 当感受着自己的心备受煎熬, 当眼前的灯光都变得模糊, 当站在拥挤的车上,竭力控制哽咽, 当无力地抚慰自己的心口, 思念的痛,可以毁掉一切, 眼见着思念侵袭着爱,慢慢把它变做一种恨, 还剩下什么…… September 01 絮絮写真馆……August 29 流了好长时间的鼻血晚上回到家,居然开始流鼻血了。 其实已经习惯了这个鼻子流血, 可是,这次,它不肯停下来, 感觉自己的体液不断地流失而带来的不安, 满眼都是灰色的, 无助, 我是孤独的, 当流鼻血这件事情成为我这个人的一部分的时候, 便不会有人觉得这是件不好的事情, 有人给我一个大大的问号, 有人调侃我, 有人无语。 所谓人是独立的个体, 就是需要忍受独立带来的孤独, 没人能完全体会自己的感受,只有自己。 人心, 总是经历着从开放向封闭的过程, 而从封闭转向开放,那是个多难的过程啊。 人是不甘寂寞的,因为寂寞总是陪伴左右。 |
当我不存在
|
||||
|
|