Over the past few months I've had some interesting debates with folks here (and some customers) about the cost/benefit trade-off of "AnyCPU" (architecture-neutral) managed EXEs. I think we've converged on a consensus that most of the time they're not what you want and so shouldn't be the default in Visual Studio. I suspect this topic may interest (and even shock) some folks, so I thought I'd share the rationale with you here.
Background - .NET and 64-bitWith the introduction of Win64 (64-bit versions of Windows), PE files (EXEs and DLLs) can be marked either as 32-bit OR 64-bit. When a 32-bit EXE is launched on Win64, it runs in "the WOW" (Windows-32 on Windows-64) to present an illusion of a 32-bit operating system to the process. Generally only 32-bit DLLs can be loaded into a 32-bit process, and only 64-bit DLLs can be loaded into a 64-bit process. When the CLR added 64-bit support in version 2.0, we had an interesting decision to make. Should we mark our binaries as 32-bit or 64-bit by default? Techncally managed binaries had no hard CPU dependency, so they could be either (actually there is a small loader thunk, but that's unused on any newer OS including all the 64-bit ones since the OS loader knows about managed EXEs explicitly). Since we wanted people to be able to write .NET libraries that they could re-use from both 32-bit and 64-bit processes, we worked with Windows to extend the OS loader support to enable architecture-neutral ("AnyCPU") PE files.
Managed architecture-neutral DLLs are fairly straight-forward - they can be loaded into either 32-bit or 64-bit processes, and the (32-bit or 64-bit) CLR in the process will do the right thing with them. AnyCPU EXEs are a little more complicated since the OS loader needs to decide how to initialze the process. On 64-bit OSes they are run as 64-bit processes (unless the 'ldr64' master OS switch says otherwise), and on 32-bit OSes they are run as 32-bit processes. In Visual Studio 2008, AnyCPU is the default platform for C# and VB projects. This means that by default, applications you compile will run in 64-bit processes on 64-bit OSes and 32-bit processes on 32-bit OSes. This is fine and does often work alright, but there are a number of minor downsides.
The costs of architecture-neutral EXEsThere are a number of reasons to think that AnyCPU should not be the default for EXEs. Don't get me wrong, 64-bit hardware and OSes are definitely the way to go (in fact all 4 of my development machines have 64-bit OSes on them - I stopped bothering to install 32-bit OSes years ago). But that doesn't necessarily mean that most processes should be 64-bit. Here's the list I've been using in our discussions to justify making x86 the default for EXE projects in Visual Studio:
When do 64-bit processes make sense?The biggest benefit of 64-bit processes is obivously the increased address-space. Many programs are bumping up against the 2GB limit of traditional 32-bit processes (even though they may not be using anywhere near 2GB of RAM). One thing that can be done for such programs is to have them opt-into 4GB mode so that they can get a full 4GB of address space when running in the WOW on a 64-bit OS [Edit: softened wording here due to some guidance to the contrary]. If more address space would be useful, than sometimes the right thing to do is to decide to target JUST x64 and avoid the cost of supporting two platforms (Exchange Server has done this for example). But often the right trade-off is to support both 32-bit and 64-bit processes, so that you can still run on 32-bit OSes, but take advantage of the large address space when running on 64-bit OSes. This is where architecture-neutral assemblies make a lot of sense. If you're a library vendor, then building as AnyCPU and testing on all supported architectures absolutely makes sense. If you are producing an application EXE and have reason to believe your application may need more than 4GB of address space, then switching to AnyCPU may be a good idea. But, as for native, really needing this much address space is still pretty rare and usually only necessary for large complex applications, and so opting-in to AnyCPU should really not be a burden. You've got to think about what you want your testing strategy to be anyway, so making this step explicit seems to make sense.
Another argument for AnyCPU being the default which I think deserves serious thought is the impact on the Windows ecosystem and desire to move to a pure 64-bit world someday. No doubt the WOW adds extra complexity and confusion and it would be great to just kill it as quickly as we can. I definitely agree with that sentiment, and we should work to get to that place. But realistically, we're a long way from being able to seriously consider killing the WOW from Client OSes (it is already optional on Server Core - but how many EXE projects are really server apps?). Here are some things that need to happen before we can seriously consider killing the WOW: Windows needs to stop shipping new 32-bit-only client OSes, most new native applications need to fully support 64-bit, all popular existing apps need to move to 64-bit (including VS), etc. I'm sure we'll get there some day (as we did with the 16-bit to 32-bit transition), but I don't think defaulting to x86 in Visual Studio is going to be a major barrier here. When it starts looking like killing the WOW may be a feasible option in the near-future, then perhaps we should probably just switch the default to be x64-only, and let people opt-in to supporting 'legacy' 32-bit platforms.
So how is Visual Studio 2010 and .NET 4.0 changing?We are not changing anything here in the CLR or compilers - they continue to support both modes. However, after discussing these issues, VS project system team has agreed to make EXE projects default to the x86 platform in VS 2010. Unfortunately there is a bug in Beta1 where ALL managed project types default to x86 (I take the blame for this - I didn't think to check DLL projects when validating the changes were in). AnyCPU is still incredibly valuable for DLLs (you may not always know what processes it will be loaded into), and since it just enables a DLL to be used in more places without actually affecting the bitness of the process, there isn't sufficient justification to disable AnyCPU by default. This bug has been fixed, and so the plan is to ship Beta2 with just the EXE projects defaulting to x86, and all DLL projects remaining as AnyCPU.
That said, there's still time to get customer feedback and so this could change for VS2010 RTM. We've already heard a lot of surprised reactions where people seem to think we're treating x64 as second-class, or otherwise resisting the natural evolution to 64-bit systems. Many people have mentioned that 32-bit hardware and 32-bit OSes are quickly becoming a thing of the past. I agree completely and this is a good trend, but it's completely orthogonal. 64-bit hardware and OSes give us the ability to run processes with 64-bit address spaces, but they by no means make using them a requirement or necessarily even preferable to using the WOW. The Windows folks did such a good job building the WOW, and the CPU designers did a good job supporting 32-bit modes (for x64 at least, ia64 is a different story), so there aren't a lot of downsides to relying on them. Someday I'm sure we'll decide the WOW has outlived it's useful lifetime and Windows should kill it rather than maintain it, but I'm sure that day is a LONG way off (eg. when did Windows finally remove support for 16-bit processes, and did anyone really notice?). When I actually get into debating this issue on it's merrits, almost everyone I've talked to has agreed that making x86 the default seems to be the best choice - at least for the next several years. This, by no means signifies decreased support for 64-bit OSes and frameworks. I can tell you that most CLR developers work almost exclusiviely on x64 OSes, and do much of their testing and development with 64-bit processes. Our testing (like most teams at Microsoft) treats x86 and x64 as first-class and generally equal-priority (except for products like Silverlight of course that are still x86-only). But when we put ourselves in the shoes of our users and study this issue on it's merrits, it just makes practical sense for x86 to be the default for EXE projects.
Let me know if you agree or disagree. Regardless, I hope you enjoy using VS2010 - it's really shaping up to be a great release!
[Edit - added section about helping the ecosystem move to all 64-bit]