45

From what I have found so far it's clear that programs compiled for a 64-bit architecture use twice as much RAM for pointers as their 32-bit alternatives - https://superuser.com/questions/56540/32-bit-vs-64-bit-systems.

Does that mean that code compiled for 64-bit uses on average two times more RAM than the 32-bit version?

I somehow doubt it, but I am wondering what the real overhead is. I suppose that small types, like short, byte and char are same sized in a 64-bit architecture? I am not really sure about byte though. Given that many applications work with large strings (like web browsers, etc.), that consist mostly of char arrays in most implementations, the overhead may not be so large.

So even if numeric types like int and long are larger on 64 bit, would it have a significant effect on usage of RAM or not?

Community
  • 1
  • 1
Petr
  • 13,747
  • 20
  • 89
  • 144
  • 3
    `byte` is *not* a standardized type. With C99 or better, include `` then use `uint8_t` if you need unsigned 8 bits "bytes". – Basile Starynkevitch Mar 19 '15 at 08:42
  • 2
    memory usage will increase, but (almost) never double – phuclv Mar 19 '15 at 08:50
  • 11
    The whole point of creating new CPUs with wider address and data buses is to _increase execution speed at the cost of program size and RAM consumption_. This has been the case from 8 to 16 to 32 to 64. So nothing new here. – Lundin Mar 19 '15 at 09:03
  • 1
    @Lundin I realize that there is overhead caused by that, but what I would like to know is how big that overhead is. Some systems may need to be optimized more for RAM consumption rather than CPU consumption – Petr Mar 19 '15 at 09:25
  • 3
    Of course. RAM doesn't matter, a 64-bit program uses the processor cache much less effectively. Not quite twice as bad, depends what else is going on. An *int* is still 32 bits for this very reason. Credit due to AMD, they did compensate for this loss for perf by adding all the right features to get a comparable outcome. Starting with an extra 8 registers. – Hans Passant Mar 19 '15 at 10:09
  • If the system is 64-bit, it's probably got enough RAM and HDD/SSD space to not have to worry about a few KB of extra memory usage. – Pharap Mar 19 '15 at 10:39
  • (Virtual) memory usage can sometimes increase massively due to new programming techniques that are only possible when a 64bt address space is available, such as allocating *enormous* arrays for everything (or some things), and relying on the OS and processor to lazily map these arrays into physical memory, rather than manually resizing the arrays. – Mankarse Mar 19 '15 at 10:47
  • 1
    @Pharap this is so not true, think of paravirtualized environments or shared hosts. VPS may as well be 64 bit but with very low RAM, or dynamic RAM where you pay for it. It's a common mistake of many programmers to think that RAM is something super cheap that can be wasted as much as they like to. There are many cases where you want to be effective with memory, especially in server applications serving thousands of clients etc. – Petr Mar 19 '15 at 14:39
  • Also "few KB" if the overhead is nearly twice as much, it may be as well be "few GB of extra RAM" in case of application that is consuming large amount of memory – Petr Mar 19 '15 at 14:40
  • BTW one surprising observation: I tried to compile one of my applications in 64 bit. The 32 bit version compiled with MinGW uses 140MB of ram, version compiled with Visual Studio uses 90MB. Same version compiled in Visual Studio with 64bit uses only 10MB of ram. I have no idea why 64bit version actually uses so much less, but I suppose it has something to do with windows WOW64 support. – Petr Mar 19 '15 at 15:27
  • Out of interest, on Visual Studio, compiling with x64 on a 64-bit Intel CPU, `int` and `long` are both 4 bytes. That's just the one example though, there are almost certainly compilers where both `long` and `int` are 8 bytes. Ultimately though, the type sizes can be completely unrelated to whether the CPU is 32bit or 64bit. It's entirely legal and possible to have a C implementation on a 16bit CPU where `int` and `long` are 8 bytes. – Pharap Mar 19 '15 at 15:39
  • @Pharap there are some compilers using [SILP64 and ILP64](http://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models), but extremely rare. The common models nowadays are LLP64 (on Windows) and LP64 (POSIX). – phuclv Mar 20 '15 at 11:19
  • @Petr if the program is compiled as 64 bit, it won't run in WOW64 (which is a compatibility layer for 32-bit programs in 64-bit Windows). Moreover WOW64 only converts things like system calls, paths, registry hives..., not library calls like memory allocation, therefore the problem may lie elsewhere. So if possible you should create a [SSCCE](http://sscce.org/) ([MCVE](http://stackoverflow.com/help/mcve)) and ask another question for that – phuclv Mar 20 '15 at 12:05

3 Answers3

42

It depends on the programming style (and on the language, but you are referring to C).

  • If you work a lot with pointers (or you have a lot of references in some languages), RAM consumption goes up.
  • If you use a lot of data with fixed size, such as double or int32_t, RAM consumption does not go up.
  • For types like int or long, it depends on the architecture; there may be differences between Linux and Windows. Here you see the alternatives you have. In short, Windows uses LLP64, meaning that long long and pointers are 64 bit, while Linux uses LP64, where longis 64 bit as well. Other architectures might make int or even short 64 bit as well, but these are quite uncommon.
  • float and double should remain the same in size in all cases.

So you see it strongly depends on the usage of the data types.

Daniel Kamil Kozar
  • 18,476
  • 5
  • 50
  • 64
glglgl
  • 89,107
  • 13
  • 149
  • 217
  • 1
    x86-64 also has the x32 ABI which uses 32-bit pointers. It has the advantage over using 32-bit x86 of having a more-register-oriented calling convention and being able to use the additional 8 GPRs (and additional 8 SIMD/FP registers). Also, GCC supports ILP32 on AArch64. –  Mar 19 '15 at 11:25
  • So languages like Java/C# are more likely to get this 2x effect than C/C++ (especially if you don't use a ton of pointers), correct? – David says Reinstate Monica Mar 19 '15 at 16:02
  • @DavidGrinberg Here as well, that depends on the data. E. g., a program wich has most of its data in a native array such an `int[]` or `double[]`, not much will change. However, a program dealing with lots of small objects will need more RAM. – glglgl Mar 19 '15 at 20:14
  • 2
    @DavidGrinberg Due to [compressed oops](http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html#compressedOop), Java programs using less than ~4GiB of heap will probably stay the same. – Tavian Barnes Mar 19 '15 at 20:16
  • @TavianBarnes Thanks, that was new to me. Then it shouldn't hurt to work under 64 bit... – glglgl Mar 20 '15 at 05:14
  • 1
    @TavianBarnes actually a JVM can address 64 GB with 32 bit references by using a object alignment of 8 or 26 bytes. – Peter Lawrey Mar 25 '15 at 03:21
27

There are a few reasons for the memory consumption to go up. However the overhead of 64b vs 32b depends from an app to another.

  • Main reason is using a lot of pointers in your code. However, an array allocated dynamically in a code compiled for 64bit and running on a 64bit OS would be the same size as the array allocated on a 32 bit system. Only the address to the array will be larger, the content size will be the same (except when the type size changed - however that should not happen and should be well documented).

  • Another footprint increase would be due to memory alignment. In 64 bit mode the alignment needs to consider a 64bit address so that should add a small overhead.

  • Probably the size of the code will increase. On some architectures the 64bit ISA could be slightly larger. Also, you would now have to make calls to 64bit addresses.

  • When running in 64bit registers are larger (64bit) so if you use many numerical types the compiler might as well place them in registers so that shouldn't necessarily mean that your RAM footprint would go up. Using double variables is likely to produce a memory footprint increase if they are not stored into 64b registers.

  • When using JIT compiled languages like Java, .NET it is likely that the footprint increase of 64b code would be larger as the runtime environment will generate additional overhead through pointer usage, hidden control structures, etc.

However there is no magic number describing the 64bit memory footprint overhead. That needs to be measured from an application to another. From what I've seen, I never got more than 20% increase in footprint for an application running on 64bit, compared to 32bit. However that's purely based on the applications I encountered and I'm using mostly C and C++.

VAndrei
  • 5,420
  • 18
  • 43
  • A jump typically will be relative 32 bit. You can't jump to an absolute 64-bit address with a single jmp instruction – phuclv Mar 19 '15 at 08:50
  • the only instruction that has 64-bit immediate is movabs, so you can't call a function at 64-bit immediate address either – phuclv Mar 19 '15 at 09:05
  • I'm quite sure you can make a call to a 64b absolute address. Check here: http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf – VAndrei Mar 19 '15 at 09:19
  • Also a jump with a 64bit offset is possible according to the same reference. – VAndrei Mar 19 '15 at 09:25
  • you're misreading something. "In 64-bit mode, immediates and displacements are generally only 32 bits wide. NASM will therefore truncate most displacements and immediates to 32 bits. The only instruction which takes a full 64-bit immediate is: MOV reg64,imm64" http://www.nasm.us/doc/nasmdo11.html – phuclv Mar 19 '15 at 13:31
  • "The only instructions which take a full 64-bit displacement is loading or storing, using MOV, AL, AX, EAX or RAX (but no other registers) to an absolute 64-bit address" so you can't call using 64-bit displacement either – phuclv Mar 19 '15 at 13:35
  • I'm not saying you can have a 64b immediate or displacement. I'm saying you can jump or call an address given using a 64b register. FF /4 JMP r/m64. Jump near, absolute indirect, RIP = 64-Bit offset from register or memory (page 506) – VAndrei Mar 19 '15 at 14:11
  • Anecdotal data point: my .NET application uses about 30% more RAM as a 64-bit process when idle, and 50% more while crunching data (peak memory usage). – Roman Starkov Mar 19 '15 at 22:16
0

I think there may be another reason which goes way back in that variables need to be stored in memory on a 64bit boundary at an address that's ...xxxxx000 to be read in one bite, if it's not it needs to read it in a byte at a time.

John
  • 107
  • 1
  • 7