在Linux上,目标文件比在MacOS或Windows上大2.5倍

时间:2018-06-27 13:44:44

标签: c++ linux windows macos

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

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

该文件(详细信息如下)表示unicode表(的一部分)以及字符属性。编码为utf8。

在我看来,问题可能是libstdc ++无法很好地处理文件,因此我在Gentoo上用clang尝试了libc ++,但是它什么也没做(对象文件的大小保持不变)。

然后我认为这可能是做一些奇怪的优化工作,但是当我从-O3转到-O0时,尺寸再也没有改善。

solution上的

The file包括line 50UnicodeTable.inc包含一个std::array的Unicode代码点。

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

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

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

在这一点上,我没有主意,非常感谢您提供有关找出“膨胀的”目标文件大小来源的帮助。

1 个答案:

答案 0 :(得分:2)

在链接的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;
};

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