.NET 2 x64 slow compared to 32 bit?
When running a natively compiled 64 bit managed C# app on .NET 2.0 Beta 2 x64 and 64 bit hardware, it is consistently slower than when compiled for 32 bit and running on 32 bit hardware.
On compiling, a warning in VS 2005 tells me thatReferenced assembly 'mscorlib.dll' targets a different processor.
I've rungacutil -L mscorlib fromProgram Files\Microsoft.NET\SDK\v2.0 64bit\Bin and it shows that there is a 64 bit version of mscorlib:
mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, P
rocessorArchitecture=AMD64
mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, P
rocessorArchitecture=x86
Is there a way for 64 bit .NET 2.0 applications to target the 64 bit mscorlib? The code does a lot of number crunching and I was expecting this to be faster on 64 bit hardware, but the profiler shows that a lot of time is spent in mscorlib so I was hoping that the 64 bit version would run faster.
Any advice would be much appreciated.
[1147 byte] By [
Nandor] at [2008-1-13]
Nandor --
If your process starts up as 64-bit then you're using the 64-bit version of mscorlib, no matter which one you compiled against (the binding doesn't happen until JIT/NGEN time). You can tell this on your 64-bit machine by looking at task manager and seeing whether your process has a "*32" next to it, if it does then it's a 32-bit process.
That said, performance of apps on 64-bit as compared to 32-bit can vary quite a bit depending on what you're doing. Sometimes you can see very large wins, in other cases you will see some degrade in performance; it is unfortunately not a automatic win.
I would agree that given your statement that your app does a lot of number crunching there is potentially some opportunity for 64-bit to win, however it depends on a whole lot of factors. To make any more intelligent statements about your specific performance we'd have to know what it is you're trying to do as well as see profiles.
-josh
Thank you for the info, I have since seen an MS blog which states what you are both saying, that the correct 64 bit mscorlib will automatically be referenced.
Here is some info on the hardware and a (very basic) sample of code which I expected to execute faster on 64 bit:
32 bit machine:
Dell Precision Workstation 650
Dual Xeon 3.0GHz
512kb cache
2 GB RAM
Windows Server 2003 Standard SP1
64 bit machine
Dell 2850 rack server
Dual Xeon 3.2GHz (EM64T)
2MB cache
6 GB RAM
Windows Server 2003 Standard x64 SP1
Both systems run VS 2005 Beta 2.
// 32 bit copy
...
int intCount = bitCount >> 5;
fixed (byte* pbSrc = &data[byteIx + sizeof(ushort)], pbDst = b.Data) {
int* piSrc = (int*) pbSrc;
int* piDst = (int*) pbDst;
for (int i = 0; i < intCount; ++i)
*piDst++ = *piSrc++;
...
// 64 bit copy
...
int longCount = bitCount >> 6;
fixed (byte* pbSrc = &data[byteIx + sizeof(ushort)], pbDst = b.Data) {
long* plSrc = (long*) pbSrc;
long* plDst = (long*) pbDst;
for (int i = 0; i < longCount; ++i)
*plDst++ = *plSrc++;
...
These are actual snippets from our application (unsafe copying data between byte[]'s). All pointers on 64 bit .NET are 64 bits wide so one can expect a slight performance hit when running the 32 bit code on 64 bit hardware, but the 64 bit code should execute faster (at least that's what I thought). With 64 bit (long) being native and there being only half as many iterations through the loop, shouldn't the 64 bit code in this specific example execute at twice the speed? Here are the results from two low level bit-op tests similar to the code shown above:
32 bit code (int*), built on 32 bit hardware, run on 32 bit hardware
Test 1: 22,860 ms
Test 2: 22,765 ms
32 bit code (int*), built on 64 bit hardware, run on 64 bit hardware
Test 1: 20,859 ms
Test 2: 20,719 ms
The 64 bit hardware runs the 32 bit code (int*) about 10% faster than on the 32 bit machine. However, if I run the build from the 32 bit machine on 64 bit hardware it runs even faster, i.e. building and running the same code on 64 bit is fractionally slower than building it on 32 bit and running it on 64 bit:
32 bit code (int*), built on 32 bit hardware, run on 64 bit hardware
Test 1: 20,484 ms
Test 2: 20,485 ms
And now for the 64 bit code (long*):
64 bit code (long*), built on 32 bit hardware, run on 32 bit hardware
Test 1: 23,453 ms
Test 2: 22,969 ms
64 bit code (long*), built on 64 bit hardware, run on 64 bit hardware
Test 1: 21,500 ms
Test 2: 21,281 ms
Here the 64 bit hardware is slightly faster, while the 32 bit hardware takes a slight performance hit from processing long* vs. int*. But again, the greatest gain is achieved by building the 64 bit code (long*) on a 32 bit machine, and then executing the resulting assemblies on 64 bit hardware:
64 bit code (long*), built on 32 bit hardware, run on 64 bit hardware
Test 1: 20,375 ms
Test 2: 20,282 ms
So it appears that:
1) VS 2005 Beta 2 on 32 bit hardware builds assemblies which run faster on 64 bit hardware than if the assemblies were built using VS 2005 Beta 2 on 64 bit hardware.
2) Using long* vs. int* provides virtually no benefit on current EM64T hardware.
We have a fairly large test suite (around 220 classes, 1500 methods) which tests various aspects of our software. On some tests there are slight gains (up to approx. 10%) and on others there are slight losses, but overall the 64 bit tests lag by approx. 3% despite the fact that the 64 bit hardware is slightly faster than 32 bit. We are not seeing large wins anywhere.
We have been developing this project with 64 bit hardware in mind (for more than two years now) and the code is littered with #define's and #if's which split various methods between 32 bit and 64 bit specific implementations. To now find that there is virtually no performance benefit is a little disappointing. Is this scenario likely to change in future with newer processors and memory architectures or is there a different way to code for optimal 64 bit performance in .NET?
Nandor.