c++ - 目标文件在 Linux 上比在 macOS 或 Windows 上大 2.5 倍
问题描述
我有一个文件,当编译为目标文件时,它具有以下大小:
- 在 Windows 上,使用 MSVC,它是 8MB。
- 在 macOS 上,使用 clang,它是 8MB。
- 在 linux(Ubuntu 18.04 或 Gentoo)上,使用 gcc 或 clang,它是 20MB。
该文件(下文详述)是 Unicode 表(的一部分)以及字符属性的表示。编码为utf8。
我突然想到问题可能是 libstdc++ 不能很好地处理文件,所以我在 Gentoo 上用 clang 尝试了 libc++,但它没有做任何事情(目标文件大小保持不变)。
然后我认为可能是一些优化做了一些奇怪的事情,但是当我从-O3
到-O0
.
该文件在第 50 行包括UnicodeTable.inc
. UnicodeTable.inc
包含一个unicodestd::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,但都拒绝了 170k 行长文件。
在这一点上,我没有想法,非常感谢有关找出“臃肿”目标文件大小来源的任何帮助。
解决方案
从您链接的输出中,您可以看到 elf 对象(部分)size
中有 12 MB 的重定位。.rela.dyn
如果64 位重定位需要 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;
};
这样,您不需要对条目进行重定位。
推荐阅读
- android - 将 listviewBuilder 包装在 Column 内?
- php - 如何在 PHP 7 中从一个页面重定向到另一个页面?
- android - CMake FetchContent 多次下载外部依赖项
- r - BayesFactor anovaBF 语法
- r - keep the returned matrix after indexing as a vector
- python - 使用 pandas_udf 和 Parquet 序列化时内存泄漏?
- sql - 如何唯一显示 SQL
- php - Restrict checkout shipping state in Woocommerce
- flutter - How to convert duration format ( dd HH mm ) to linera minutes in flutter?
- javascript - 使用流将值类型分配给解构对象