【问题标题】:Object file is 2.5x larger on linux than on macOS or Windows目标文件在 Linux 上比在 macOS 或 Windows 上大 2.5 倍
【发布时间】:2018-12-06 10:43:26
【问题描述】:

我有一个文件,当它编译为目标文件时,其大小如下:

  • 在 Windows 上,使用 MSVC,它是 8MB。
  • 在 macOS 上,使用 clang,它是 8MB。
  • 在 linux(Ubuntu 18.04 或 Gentoo)上,使用 gcc 或 clang,大小为 20MB。

该文件(详述如下)是 Unicode 表(的一部分)以及字符属性的表示。编码为utf8。

我突然想到问题可能是 libstdc++ 不能很好地处理文件,所以我在 Gentoo 上用 clang 尝试了 libc++,但它没有做任何事情(目标文件大小保持不变)。

然后我认为可能是一些优化做了一些奇怪的事情,但是当我从 -O3 转到 -O0 时,我再一次没有大小改进。

The fileline 50 包括 UnicodeTable.incUnicodeTable.inc 包含 unicode 代码点的 std::array

我尝试将 std::array 更改为 C 样式数组,但同样,目标文件大小没有改变。

我有CodePoint.cpp 的预处理版本,可以用$CC -xc++ CodePoint.i -c -o CodePoint.o 编译。 CodePoint.i 包含约 40k 行 STL 代码和约 130k 行 unicode 表。

我尝试将预处理后的 CodePoint.i 上传到 gists.github.com 和 paste.pound-python.org,但都拒绝了 17 万行长的文件。

在这一点上,我没有想法,非常感谢有关找出“臃肿”目标文件大小的来源的任何帮助。

【问题讨论】:

  • 每个平台上的sizeof (RawCodePoint)是什么?
  • 我假设您在某些时候将 .o 文件用作共享库或可执行文件的一部分——该可执行文件在 Linux 下是否也大 12MB?即使在可执行文件上运行strip 之后?
  • 可执行文件有多大?由于目标文件是临时的,大小重要吗?
  • 您使用的完整编译器命令行是什么?
  • 这个问题可能有助于进一步分析结果:stackoverflow.com/questions/11720340/…

标签: c++ linux windows macos


【解决方案1】:

从您链接的size 的输出中,您可以看到elf 对象中有12 MB 的重定位(.rela.dyn 部分)。如果 64 bit relocation 占用 24 个字节,并且您有 132624 个表条目,每个条目有 4 个指向字符串的指针,这几乎可以解释 12 MB 的差异(132624 *4 * 24 = 12731904 ~ 12 MB)。

显然,其他格式要么使用更有效的重定位类型,要么直接链接引用并将整个块与字符串一起重定位为一块内存。

由于您将此链接到共享库,因此动态重定位不会消失。

我不确定您当前使用的代码是否可以避免这种情况。 但是,我认为 unicode 代码点必须具有最大大小。为什么不将代码点按值存储在 RawCodePoint 结构中的 char 数组中?每个码位字符串的大小应该不大于你当前存储的指针,并且查表的引用局部性实际上可能会有所改善。

constexpr size_t MAX_CP_SIZE = 4; // Check if that is correct

struct RawCodePointLocal {
  const std::array<char, MAX_CP_SIZE> original;
  const std::array<char, MAX_CP_SIZE> normal;
  const std::array<char, MAX_CP_SIZE> folded_case;
  const std::array<char, MAX_CP_SIZE> swapped_case;
  bool is_letter;
  bool is_punctuation;
  bool is_uppercase;
  uint8_t break_property;
  uint8_t combining_class;
};

这样您就不需要为条目重新定位。

【讨论】:

  • 感谢您的帮助!这无疑为我指明了正确的方向。用(适当大小的)char[] 替换 char* 使 .rela.dyn 的大小可以忽略不计,但随后 MSVC 花了很长时间才能编译(但是,这是另一个问题)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-07
  • 1970-01-01
  • 2020-08-10
  • 2018-04-24
  • 1970-01-01
相关资源
最近更新 更多