如何确定为什么我的库中的文本大小如此之大

How to determine why text size in my library is so huge?

本文关键字:文本 如此之 何确定 为什么 我的      更新时间:2023-10-16

我有一个使用 Android NDK for ARM 构建的共享库文件。里面还有一点JNI。这个SO文件链接到许多其他.a文件(我们自己的静态库,我们作为依赖项构建)以及其他一些第三方静态库,如boost。

我正在使用GCC 4.8并使用具有C++11功能的STL。

我对此做了一些自我研究。特别是,我遇到了这个线程:
为什么我的C++输出可执行文件这么大?

这帮助我想出了一些要运行的命令,例如size

$ size libmine.so
   text    data     bss     dec     hex filename
13017993         201972   54120 13274085         ca8be5 libmine.so

不幸的是,除了要运行的命令之外,链接的 SO 问题在诊断方面对我没有多大帮助(或者也许我只是在 Linux 风格的开发方面没有足够的经验来可靠地使用这些信息)。我不确定如何分析产生的结果,以帮助我查明导致任何增长的代码、特定库或模板函数/类/等区域。

共享库本身是13MB,这是相当巨大的。我确实验证了我的.SO文件被"剥离",我想这意味着没有调试符号。在这一点上,我不确定这是由于提升还是一些疯狂的模板实例化。如何确定是什么促成了共享图书馆的大规模增长?

我没有答案。还。只是分享我的快速和肮脏的单行本,所以你不必这样做。免責聲明性能很糟糕,但足够™好。Perl/Python/Haskell/...应该使用的实用主义是关键词。

您需要安装bc才能进行求和¹

从 Andy Brown 的评论开始,我分析了我自己项目的二进制文件:

  • 定义一个帮助程序函数来列出名称:

    function names() { nm -l -S --size-sort --radix=d -C "$@"; }
    

    删除-l(行号)以提高性能(我不需要)

  • 以下单行显示重复的累积大小:

    for a in bin/*; do echo -e "$at$(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
    

    这往往只显示弱符号。因为这里的实际值是重复的,我不确定这是否意味着重复的大小计入剥离的二进制文件大小

  • 符号类型的直方图:

    for a in bin/*; do names "$a" | awk '{print $3}'; done | sort | uniq -c | sort -rn
    
  • 按符号
  • 类型划分的符号总大小,按上一步直方图频率降序排列:

    for a in bin/*; do names "$a" | awk '{print $3}'; 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 "$typet$sizet$a"
            done
            echo -e "total:t$totalttotal bytes in $count symbolsn-------"
        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这里。