64 位 dll 的大小比 32 位大 50%

Posted

技术标签:

【中文标题】64 位 dll 的大小比 32 位大 50%【英文标题】:Size of 64-bit dll 50% larger than 32-bit 【发布时间】:2009-10-19 16:33:36 【问题描述】:

我有一个生成 32 位和 64 位 dll 的 VC++ 项目 (2005)。 32 位 dll 为 1044 KB,而 64 位版本为 1620 KB。我很好奇为什么尺寸这么大。仅仅是因为更大的地址大小,还是我缺少编译器选项?

【问题讨论】:

您是否在运行时静态链接?那么肯定是运行时增加了大部分的开销。 没有足够的信息来提供有意义的答案。所提供的任何东西都是纯粹的猜测。 有趣的是,x64 代码大小确实比等效的 x86 代码增加了 50% 到 66%。我认为增加的主要原因是指针的大小(包括函数调用目标地址)。但是,我还没有看到任何严格的研究/分析;我认为这肯定会很有趣 - 我希望有人发布一个指针。 我没有静态链接除 zlib 库以外的任何东西,但这在两个版本的 dll 中都有。顺便说一句,64 位 zlib 库也比 32 位(147KB 与 101KB)大约 50% 【参考方案1】:

也许你的代码包含很多指针。

The Free Lunch Is Over

....

(旁白: 这是一个轶事来证明 最近打击我的“空间就是速度” 编译团队。编译器使用 对于 32 位和 64位编译器;代码只是 编译为 32 位进程或 一个64位的。 64位编译器 获得了大量的基线 通过在 64 位上运行来提高性能 CPU,主要是因为 64 位 CPU 有更多的寄存器可以工作 具有并具有其他代码性能 特征。一切都很好。但是什么 关于数据? 没有转到 64 位 改变大部分数据的大小 内存,当然指针除外 现在特别是两倍 他们以前。碰巧的是,我们的 编译器更多地使用指针 大量使用其内部数据 结构比大多数其他类型的 应用程序永远不会。因为 指针现在是 8 个字节而不是 4 个 字节,纯数据大小增加,我们 看到了显着增加 64 位编译器的工作集。那 更大的工作集导致 性能损失几乎 完全抵消代码执行 我们从中获得的性能提升 使用更快的处理器 更多的寄存器。在撰写本文时, 64位编译器同时运行 速度作为 32 位编译器,甚至 虽然源基础是相同的 和 64 位处理器都提供 更好的原始处理吞吐量。 空间就是速度。)

【讨论】:

请注意,这个 sn-p 是在谈论数据的大小,而不是代码的 sie。但我认为代码和数据的结果和原因将是相似的。【参考方案2】:

x86-64 有更多的寄存器。因此,操作码需要更多位来指定它们。此外,根据 x86 传统,您可以指定寄存器的一部分,现在您有一个 32 位的部分寄存器。不使用寄存器的指令很少见,因此这些更改几乎影响每条指令。由于 x86-64 仍然是 CISC 可变长度 ISA,并不意味着每条指令都从 32 位增长到 64 位,但有一定的增长。

另一个变化是movq,将寄存器设置为常量的操作码需要64位常量(但操作码中的其他常量仍然是32位)

【讨论】:

此外,每条访问扩展寄存器(r8-r15 或 xmm8-xmm15)的指令都需要使用 REX 前缀,这会在每条指令的大小上增加 4 位。它们是否是 64 位操作无关紧要;例如 addl %eax, %ebx 将比 addl %eax, %r8d 短 4 位。 (编译器应该考虑到这一点,并尽可能使用提供更短代码大小的寄存器,但我不知道 Visual C 是否这样做)。【参考方案3】:

您的指针大小增加了一倍,因此如果您的代码中有很多指针,您的可执行文件可以轻松增长 50%。

【讨论】:

以上是关于64 位 dll 的大小比 32 位大 50%的主要内容,如果未能解决你的问题,请参考以下文章

机器大小 64 或 32 位

64 位 Windows 上的 32 位 JVM 最大内存大小没有预期的那么大

32位64位下各种数据类型大小的对比

32 位和 64 位版本的 windows 操作系统的页面大小是多少?

32 位与 64 位 Windows 版本上的进程大小和行为差异

32 位和 64 位 Windows 服务器上 JVM 的最大堆大小