I did post previously about 32 bit vs 64 bit through the magnifying glass of .NET – good news is, that it’s now high time to scrap all those results, and revisit the question. The reason behind is one of the changes between .NET 4.5.2 and 4.6 (and therefore 4.6.1) is the introduction of a new JITter (ryujit) which should result each of us carefully revisiting this question.
But, let’s not go that quick; what the problem is we are trying to solve.
32 bit vs 64 bit
“I’m in .NET, why should I be interested in 32 bit vs 64 bit? Isn’t .NET bit agnostic?”
Yes, .NET itself is agnostic; however some of the libraries and technologies you might use might be not. Think about technologies like: P/Invoke, COM Interop, Unsafe Code, Marshaling, Serialization, Managed CPP, … So, yes, if you happen to have 100% type safe managed code, you can just copy your application from a 32 bit system to a 64 bit system, and it would “just run” successfully under the 64 bit CLR. However, likely you are using some of the technologies just mentioned, so you should do your homework to investigate whether your code is depending on the bit length. Be aware, that unlike C++, .NET only changes size of the pointers (IntPtr) and not the builtin value types (e.g. int is going to stay the same). So moving between 32 and 64 bit world either result in no changes or a set of changes related to pointers, changes related to 3rd party libraries, marshaling, serialization, and more; and you can use System.IntPtr.Size and System.Reflection.Module.GetPEKind to determine the current bitlength and/or querying a deployment assembly for platform affinity.
Why 64 bit? Actually, why 32 bit?
What does 64 bit allows you to? Addressing (not necessary accessing) a bigger chunk of memory. 32 bit applications inherently (because of the pointers they use) are limited into a 2Gb section of the memory, 64 bit applications don’t have this limitation.
So, that means I should just specify I want to have 64 bit, and that’s it? I’d have more memory and would be faster? Actually, not necessarily. 64 bit pointers do occupy more memory. Cache lines in the processor gets evicted more likely. Stack becomes bigger. Your application will likely (mileage might vary) occupy more memory, and there is a chance (mileage will vary) it will perform worse – despite the fact that running on 32 bit results involved in the WOW64 subsystem that has its own performance hit.
So should I not update to 64 bit? You should measure; although because what explained above it might be not trivial, you might not want to put effort into it right now.
Why this is a topic now?
With .NET 4.6 a new JITter got introduced that is a significant rewrite of the existing JITter (and caused some uproar when just after .NET 4.6 release a problem in a tail call optimization caused issues). It’s actually optimized to bring 64 bit nirvana for the masses by incorporating more usecases to use SIMD and SSE for. Yes, I’m going to talk about synthetic microbenchmarks here. Synthetic microbenchmarking is evil and you shouldn’t trust any of the results below, rather test your code – mileage will vary.
There are many usecases, like: matrix multiplication, simple floating point arithmetic and more where there is a significant speedup – we speak 4-5x (due to better usage of registers, opcodes, due to better coalescing of arithmetic instructions and use of noeffect code reorder). However, there are many other usecases – just calling a static method, or calling a virtual method might slow down by the same 4-5x factors.
Don’t believe any of the results above – please do measure yourself, and feel free to leave in the comments below whether you did see any performance improvements using .NET 4.6.1 and 64 bit over your 32 bit application. Also, going over 2Gb of memory usage – is it possible your application should be restructured not to hold all the data on the client side? Probably revisit a different pattern for client-server interaction is timely?