如何确定为什么我的库中的文本大小如此之大?
How to determine why text size in my library is so huge?
我有一个使用 Android NDK for ARM 构建的共享库文件。那里也有一点 JNI。这个 SO 文件链接到许多其他 .a 文件(我们自己构建的静态库作为依赖项)以及一些其他第三方静态库,例如 boost。
我正在使用 GCC 4.8 并利用具有 C++11 功能的 STL。
我对此做了一些自我研究。特别是,我遇到了这个线程:
why my C++ output executable is so big?
这帮助我弄清楚了 运行 的一些命令,例如 size
:
$ size libmine.so
text data bss dec hex filename
13017993 201972 54120 13274085 ca8be5 libmine.so
不幸的是,除了 运行 的命令外,链接的 SO 问题在诊断方面对我没有太大帮助(或者也许我对 linux 的经验不足-风格发展以可靠地使用信息)。我不确定如何分析生成的结果,以帮助我查明导致任何增长的代码区域、特定库或模板 functions/classes/etc。
共享库本身有 13MB,相当大。我确实验证了我的 .SO 文件是 "stripped",我猜这意味着没有调试符号。在这一点上,我不确定这是由于提升还是一些疯狂的模板实例化。我如何确定是什么导致了我的共享库的大量增长?
I have no answers. Yet. Just sharing my quick & dirty oneliners so you don't have to. Disclaimer The performance is abysmal but GoodEnough™. Perl/Python/Haskell/... should have been used pragmatism was the keyword.
You need bc
installed for the summations ¹
从 Andy Brown 的评论开始,我分析了我自己项目的二进制文件:
定义一个辅助函数来列出名字:
function names() { nm -l -S --size-sort --radix=d -C "$@"; }
删除 -l
(行号)以获得更好的性能(我不需要)
以下单行重复显示累积大小:
for a in bin/*; do echo -e "$a\t$(names "$a" | \
cut -d\ -f1-2 | sort | uniq -cd | \
perl -ne '@a=split and print "" . (($a[0]-1) * $a[2]) . "\n"' | \
paste -sd+ | bc)"; done
This tends to show only weak symbols. Because the actual values are duplicates here, I'm not sure this actually means the size in duplicates counts to the stripped binary file-size
符号类型直方图:
for a in bin/*; do names "$a" | awk '{print }'; done | sort | uniq -c | sort -rn
按符号类型划分的符号总大小,按照上一步中直方图的频率降序排列:
for a in bin/*; do names "$a" | awk '{print }'; done | \
sort | uniq -c | sort -rn | \
while read count type
do
total=0
for a in bin/*
do
size=$(names "$a" | awk "$3==\"$type\" {print $2}" | paste -sd+ | bc)
total=$(($total + $size))
echo -e "$type\t$size\t$a"
done
echo -e "total:\t$total\ttotal bytes in $count symbols\n-------"
done
我系统上的示例输出:
bin/tool1 208148
bin/liba.so 204463
bin/libcryptopp.so 166771
bin/tool2 211916
bin/tool3 204733
bin/testrunner 208271
46935 W
16173 V
10442 T
1724 u
574 d
184 R
158 B
94 t
49 r
33 b
13 D
W 1053961 bin/tool1
W 1030888 bin/liba.so
W 784518 bin/libcryptopp.so
W 1097729 bin/tool2
W 1031444 bin/tool3
W 1072752 bin/testrunner
total: 6071292 total bytes in 46935 symbols
-------
V 317146 bin/tool1
V 243869 bin/liba.so
V 368815 bin/libcryptopp.so
V 321841 bin/tool2
V 316629 bin/tool3
V 316947 bin/testrunner
total: 1885247 total bytes in 16173 symbols
-------
T 459075 bin/tool1
T 449020 bin/liba.so
T 610503 bin/libcryptopp.so
T 455224 bin/tool2
T 450630 bin/tool3
T 449234 bin/testrunner
total: 2873686 total bytes in 10442 symbols
-------
u 4912 bin/tool1
u 4136 bin/liba.so
u 448 bin/libcryptopp.so
u 5381 bin/tool2
u 4136 bin/tool3
u 4136 bin/testrunner
total: 23149 total bytes in 1724 symbols
-------
¹ 我知道它可以用纯 bash 来完成,但它要么涉及在评估扩展中扩展整个流,要么编写更多的嵌套循环。我更喜欢这里的 bc
。
我有一个使用 Android NDK for ARM 构建的共享库文件。那里也有一点 JNI。这个 SO 文件链接到许多其他 .a 文件(我们自己构建的静态库作为依赖项)以及一些其他第三方静态库,例如 boost。
我正在使用 GCC 4.8 并利用具有 C++11 功能的 STL。
我对此做了一些自我研究。特别是,我遇到了这个线程:
why my C++ output executable is so big?
这帮助我弄清楚了 运行 的一些命令,例如 size
:
$ size libmine.so
text data bss dec hex filename
13017993 201972 54120 13274085 ca8be5 libmine.so
不幸的是,除了 运行 的命令外,链接的 SO 问题在诊断方面对我没有太大帮助(或者也许我对 linux 的经验不足-风格发展以可靠地使用信息)。我不确定如何分析生成的结果,以帮助我查明导致任何增长的代码区域、特定库或模板 functions/classes/etc。
共享库本身有 13MB,相当大。我确实验证了我的 .SO 文件是 "stripped",我猜这意味着没有调试符号。在这一点上,我不确定这是由于提升还是一些疯狂的模板实例化。我如何确定是什么导致了我的共享库的大量增长?
I have no answers. Yet. Just sharing my quick & dirty oneliners so you don't have to. Disclaimer The performance is abysmal but GoodEnough™.
Perl/Python/Haskell/... should have been usedpragmatism was the keyword.You need
bc
installed for the summations ¹
从 Andy Brown 的评论开始,我分析了我自己项目的二进制文件:
定义一个辅助函数来列出名字:
function names() { nm -l -S --size-sort --radix=d -C "$@"; }
删除
-l
(行号)以获得更好的性能(我不需要)以下单行重复显示累积大小:
for a in bin/*; do echo -e "$a\t$(names "$a" | \ cut -d\ -f1-2 | sort | uniq -cd | \ perl -ne '@a=split and print "" . (($a[0]-1) * $a[2]) . "\n"' | \ paste -sd+ | bc)"; done
This tends to show only weak symbols. Because the actual values are duplicates here, I'm not sure this actually means the size in duplicates counts to the stripped binary file-size
符号类型直方图:
for a in bin/*; do names "$a" | awk '{print }'; done | sort | uniq -c | sort -rn
按符号类型划分的符号总大小,按照上一步中直方图的频率降序排列:
for a in bin/*; do names "$a" | awk '{print }'; done | \ sort | uniq -c | sort -rn | \ while read count type do total=0 for a in bin/* do size=$(names "$a" | awk "$3==\"$type\" {print $2}" | paste -sd+ | bc) total=$(($total + $size)) echo -e "$type\t$size\t$a" done echo -e "total:\t$total\ttotal bytes in $count symbols\n-------" done
我系统上的示例输出:
bin/tool1 208148
bin/liba.so 204463
bin/libcryptopp.so 166771
bin/tool2 211916
bin/tool3 204733
bin/testrunner 208271
46935 W
16173 V
10442 T
1724 u
574 d
184 R
158 B
94 t
49 r
33 b
13 D
W 1053961 bin/tool1
W 1030888 bin/liba.so
W 784518 bin/libcryptopp.so
W 1097729 bin/tool2
W 1031444 bin/tool3
W 1072752 bin/testrunner
total: 6071292 total bytes in 46935 symbols
-------
V 317146 bin/tool1
V 243869 bin/liba.so
V 368815 bin/libcryptopp.so
V 321841 bin/tool2
V 316629 bin/tool3
V 316947 bin/testrunner
total: 1885247 total bytes in 16173 symbols
-------
T 459075 bin/tool1
T 449020 bin/liba.so
T 610503 bin/libcryptopp.so
T 455224 bin/tool2
T 450630 bin/tool3
T 449234 bin/testrunner
total: 2873686 total bytes in 10442 symbols
-------
u 4912 bin/tool1
u 4136 bin/liba.so
u 448 bin/libcryptopp.so
u 5381 bin/tool2
u 4136 bin/tool3
u 4136 bin/testrunner
total: 23149 total bytes in 1724 symbols
-------
¹ 我知道它可以用纯 bash 来完成,但它要么涉及在评估扩展中扩展整个流,要么编写更多的嵌套循环。我更喜欢这里的 bc
。