Migration to 64-bit Windows

In this blog post, we discuss issues concerning migrating .NET codebase to a 64-bit windows machine, as far as development and production environment is concerned. It contains in fact excerpts from the most important articles, arranged in as logical as possibal way.


Background

Generally:

  • One big limitation of 32-bit is the virtual memory address space – as a user mode process you get 2GB, and if you use large address aware you get 3GB. With 64-bit windows, a 32-bit process gets 4GB, 64-bit process can get roughly several TB of virtual memory space.
  • 64-bit system should be more stable, however in general also slower.

What is different for a .NET developer

These things are specific to 64-bit windows:

  • Base class libraries (System.*)
  • Just-In-Time compiler
  • Debugging support
  • .NET Framework SDK

There are differences, which you will see in your managed memory usage:

  • Your process consumes more memory as the pointer size is bigger – it’s doubled on 64-bit so if you don’t change anything at all, now your managed heap (which undoubtly contains references) is bigger.
  • Allocation speed is slightly higher on 64-bit than on 32-bi (being able to manipulate memory in QWORDs instead of DWORDs).
  • There are other factors that could make your process consume more memory – for example the module size is bigger (mscorwks.dll is about 5MB on x86, 10MB on x64 and 20MB on ia64), instructions are bigger on 64-bit and what have you.
  • If you have looked at the performance counters under .NET CLR Memory you can see that you are now doing a lot fewer GCs on 64-bit than what you used to see on 32-bit.
  • The managed heap segments are much bigger in size on 64-bit. If you do !SOS.eeheap -gc you will now see way bigger segments. From this perspective you should get a performance gain when you move to 64-bit – however in general things tend to run slower on 64-bit. The perf benefit you get because of GC may very well be obscured by other perf degrades. In reality many people are not expecting perf gain when they move to 64-bit but rather they are happy with being able to use more memory to handle more work load.
  • Bigger pointer size/bigger module size are the *main* factors that cause slow down on 64-bit (not the only factors). Of course they apply to both native and managed code.

So what, should I do any changes in my code?

  • That 64-bit process is having its code JIT compiled to use not the x86 instruction set we’re used to, but the AMD64 instruction set. This is important to note: It doesn’t matter if you have an AMD or an Intel processor, if you’re 64-bit you are using the AMD64 instruction set. The short story is – Intel lost. For us, it doesn’t really matter.
  • Remember that our C# compiles to IL, and that IL is basically processor agnostic. It’s the JIT that makes the decision at the last minute.
  • If you have 100% type safe managed code then you really can just copy it to the 64-bit platform and run it successfully under the 64-bit CLR.”
  • In 64-bit Microsoft Windows, this assumption of parity in data type sizes is invalid. Making all data types 64 bits in length would waste space, because most applications do not need the increased size. However, applications do need pointers to 64-bit data, and they need the ability to have 64-bit data types in selected cases. These considerations led the Windows team to select an abstract data model called LLP64 (or P64). In the LLP64 data model, only pointers expand to 64 bits; all other basic data types (integer and long) remain 32 bits in length. The .NET CLR for 64-bit platforms uses the same LLP64 abstract data model. In .NET there is an integral data type, not widely known, that is specifically designated to hold ‘pointer’ information: IntPtr whose size is dependent on the platform (e.g., 32-bit or 64-bit) it is running on.
  • Short version: If you’re using IntPtrs, you care. If you’re aware of what IntPtrs are, you likely know this already.
  • PInvoke: if you declare int instead of IntPtr, you have a problem: The use of int will appear to be fine if you only run the code on a 32-bit machine, but will likely cause your application/component to crash as soon as it gets on a 64-bit machine.
  • It’s possible that when purchasing a vendor’s product in binary form or bringing an Open Source project into your project in binary form, that you might consume an x86 compiled .NET assembly. Then you can get BadImageFormatException.

As mentioned earlier, if you have 100% type safe managed code then you really can just copy it to the 64-bit platform and run it successfully under the 64-bit CLR. But more than likely the managed application will be involved with any or all of the following:

  • Invoking platform APIs via p/invoke
  • Invoking COM objects
  • Making use of unsafe code
  • Using marshaling as a mechanism for sharing information
  • Using serialization as a way of persisting state

Using non-managed code does not mean explicitly that a migration to 64-bit will have issues; rather it should be considered an indicator that additional investigation is required.
Developing can have also some differences:

  • edit-and-continue doesn’t work – see more

Tooling

  • FxCop should be able to detect potential migrating issues

Links

See more at this Maoni’s blog or Hanselman’s blog or ASP.NET on IIS7 or official migration guide or possible problems.

Leave a comment

Your comment