in x86 processors, 64-bit code helps two ways:
- bigger addresses let you access more memory directly (only relevant for processes that manage huge datasets)
- more registers might let a compiler reduce memory accesses for tight variables (slight extra optimization, unnoticeable except in tight loops of highly optimized code).
and has the following cons:
- more and bigger registers means more state to save/restore on every context switch.
- bigger pointers means more RAM use and bigger structures, more data to read/write.
therefore, in a lot of cases, the best of both worlds is a 64-bit OS and 32-bit processes:
- a 64-bit OS can handle lots of RAM, both to hold many processes and for big caches
- 32-bit apps are limited to 2 or 3 GB RAM for each process, but it's enough for the vast majority of tasks.
- no matter where in the 64-bit space a 32-bit task's RAM is located, it will only need 32-bit pointers to access its memory, so all pointers and data structures are still the smaller 32-bit variety.
- a 32-bit task (process or thread) only have to save/restore the few and small registers available in 32-bit x86, the 64-bit Linux scheduler handles this case well.
but, in all, the advantage is seldom noticeable (just guessing it would be far less than 5%), so just go with 64-bit everywhere and get it all simpler.
the only case where i would definitely go with 32-on-64 is when doing OpenVZ-kind of isolation. That way each partition owner would make the most of the limited RAM he can access.
still, i don't know of any advantage of PAE over 64-bit (not even small pointers, since each PAE pointer has a 32-bit offset and an extra (up to 32-bit) 'start' (remember the segmented memory of 8086? what a load of bloat!)