【问题标题】:What is the memory usage overhead for a 64-bit application?64 位应用程序的内存使用开销是多少?
【发布时间】:2015-05-22 06:52:16
【问题描述】:

从我目前发现的情况来看,很明显,为 64 位架构编译的程序使用的指针 RAM 是 32 位替代方案的两倍 - https://superuser.com/questions/56540/32-bit-vs-64-bit-systems

这是否意味着为 64 位编译的代码平均使用的 RAM 是 32 位版本的两倍?

我不知何故对此表示怀疑,但我想知道真正的开销是什么。我想像shortbytechar 这样的小类型在 64 位架构中大小相同?不过,我不太确定byte。鉴于许多应用程序使用大字符串(如 Web 浏览器等),在大多数实现中主要由 char 数组组成,因此开销可能不会那么大。

所以即使像 intlong 这样的数字类型在 64 位上更大,它是否会对 RAM 的使用产生重大影响?

【问题讨论】:

  • byte 不是标准化类型。使用 C99 或更高版本,包括 <stdint.h>,如果需要无符号 8 位“字节”,请使用 uint8_t
  • 内存使用量会增加,但(几乎)不会翻倍
  • 创建具有更宽地址和数据总线的新 CPU 的全部意义在于以程序大小和 RAM 消耗为代价提高执行速度。从 8 到 16 到 32 到 64 都是这种情况。所以这里没有什么新鲜事。
  • @Lundin 我意识到这会导致开销,但我想知道开销有多大。某些系统可能需要针对 RAM 消耗而不是 CPU 消耗进行更多优化
  • 当然。 RAM 无关紧要,64 位程序使用处理器缓存的效率要低得多。不是两倍坏,取决于发生了什么。由于这个原因,int 仍然是 32 位。由于 AMD 的功劳,他们确实通过添加所有正确的功能来补偿这种性能损失,以获得可比较的结果。从额外的 8 个寄存器开始。

标签: c memory memory-management computer-architecture


【解决方案1】:

这取决于编程风格(和语言,但您指的是 C)。

  • 如果您经常使用指针(或者您在某些语言中有很多引用),那么 RAM 消耗就会增加。
  • 如果使用大量固定大小的数据,例如doubleint32_t,RAM 消耗不会增加。
  • 对于intlong 等类型,取决于架构; Linux 和 Windows 之间可能存在差异。 Here 您会看到您拥有的替代方案。简而言之,Windows 使用 LLP64,这意味着 long long 和指针是 64 位的,而 Linux 使用 LP64,其中 long 也是 64 位。其他架构也可能使 int 甚至 short 成为 64 位架构,但这些并不常见。
  • floatdouble 在所有情况下都应保持相同的大小。

所以你看到它很大程度上取决于数据类型的使用。

【讨论】:

  • x86-64 还具有使用 32 位指针的 x32 ABI。与使用 32 位 x86 相比,它具有更多面向寄存器的调用约定和能够使用额外的 8 个 GPR(以及额外的 8 个 SIMD/FP 寄存器)的优势。此外,GCC 在 AArch64 上支持 ILP32。
  • 所以像 Java/C# 这样的语言比 C/C++ 更有可能获得这种 2 倍的效果(尤其是在你不使用大量指针的情况下),对吗?
  • @DavidGrinberg 这也取决于数据。例如,一个程序的大部分数据都在一个原生数组中,比如int[]double[],不会有太大变化。但是,处理大量小对象的程序将需要更多 RAM。
  • @DavidGrinberg 由于compressed oops,使用少于~4GiB 堆的Java 程序可能会保持不变。
  • @TavianBarnes 实际上,JVM 可以通过使用 8 或 26 字节的对象对齐来处理 64 GB 的 32 位引用。
【解决方案2】:

内存消耗增加有几个原因。然而,64b 与 32b 的开销取决于一个应用程序到另一个应用程序。

  • 主要原因是在代码中使用了大量指针。然而,一个 在为 64 位编译并运行的代码中动态分配的数组 在 64 位操作系统上将与在 32 位操作系统上分配的数组大小相同 位系统。只有数组的地址会更大,内容 大小将相同(除非类型大小更改 - 但是 这不应该发生,并且应该有据可查)。

  • 另一个占用空间增加是由于内存对齐。在 64位模式的对齐需要考虑一个64位的地址,这样 应该会增加一点开销。

  • 可能代码的大小会增加。一些 64 位 ISA 的架构可能会稍大一些。另外,你会 现在必须调用 64 位地址。

  • 当运行 64 位寄存器更大(64 位)所以如果你使用 许多数字类型,编译器不妨将它们放入 寄存器,因此不一定意味着您的 RAM 占用空间 会上升。 使用双变量可能会产生记忆 如果它们不存储到 64b 寄存器中,占用空间会增加。

  • 当使用 JIT 编译语言(如 Java、.NET)时,64b 代码的占用空间增加可能会更大,因为运行时环境会通过指针使用、隐藏控制产生额外的开销结构等。

但是,没有描述 64 位内存占用开销的神奇数字。这需要从一个应用程序到另一个应用程序进行衡量。据我所见,与 32 位相比,在 64 位上运行的应用程序的占用空间增加幅度从未超过 20%。然而,这纯粹是基于我遇到的应用程序,我主要使用 C 和 C++。

【讨论】:

  • 跳转通常是相对的 32 位。不能用一条 jmp 指令跳转到绝对 64 位地址
  • 唯一具有 64 位立即数的指令是 movabs,因此您也不能在 64 位立即数地址调用函数
  • 我很确定您可以调用 64b 绝对地址。在这里查看:intel.com/content/dam/www/public/us/en/documents/manuals/…
  • 根据相同的参考,也可以使用 64 位偏移量跳转。
  • 你误读了一些东西。 “在 64 位模式下,立即数和位移通常只有 32 位宽。因此,NASM 会将大多数位移和立即数截断为 32 位。唯一需要完整 64 位立即数的指令是:MOV reg64,imm64”nasm.us/doc/nasmdo11.html
【解决方案3】:

我认为可能还有另一个原因可以追溯到变量需要存储在内存中的 64 位边界上的地址为 ...xxxxx000 以一次性读取,如果不是,则需要读取它一次一个字节。

【讨论】:

    猜你喜欢
    • 2012-09-25
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 2013-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多