链接库文件体积优化工具篇:bloaty

笔者之前参与过一个嵌入式智能手表项目,曾经碰到过这样一个问题:手表的flash大小只有2M,这意味着只能在上面烧录2M大小的代码。随着开发不断进行,代码越写越多,编译出来的bin也越来越大。最后bin大小超过了2M, 就没法烧写了,很尴尬。最后只能想办法精简代码,当然这是在不影响功能的前提下精简代码。那如何精简代码呢?我们自然会想到先看看哪里的代码最多,比如使用的各个so的大小,so里边哪个源文件最大,源文件里边哪一个函数最耗空间等等,先做一个统计分析,然后再看一下怎么优化。那这个统计如何进行呢?这个就需要用到一些工具。

本文介绍的工具:bloaty就用来干这个活的,这是谷歌公司开源的一个项目,在GitHub上有源码,主要是用来查看可执行文件,链接库内存分布的。Bloaty对二进制文件进行深入分析,使用自定义的ELF、DWARF和Mach-O解析器,旨在将二进制文件的每个字节准确地定位到是属于哪个符号或编译单元。它甚至会反汇编二进制文件,寻找对匿名数据的引用。
下面是一个例子,用bloaty工具来分析bloaty二进制文件,看一下各个编译单元(源文件)所占的内存大小和占总大小的百分比:

./bloaty bloaty -d compileunitsFILE SIZE        VM SIZE    --------------  -------------- 34.8%  10.2Mi  43.4%  2.91Mi    [163 Others]17.2%  5.08Mi   4.3%   295Ki    third_party/protobuf/src/google/protobuf/descriptor.cc7.3%  2.14Mi   2.6%   179Ki    third_party/protobuf/src/google/protobuf/descriptor.pb.cc4.6%  1.36Mi   1.1%  78.4Ki    third_party/protobuf/src/google/protobuf/text_format.cc3.7%  1.10Mi   4.5%   311Ki    third_party/capstone/arch/ARM/ARMDisassembler.c1.3%   399Ki  15.9%  1.07Mi    third_party/capstone/arch/M68K/M68KDisassembler.c3.2%   980Ki   1.1%  75.3Ki    third_party/protobuf/src/google/protobuf/generated_message_reflection.cc3.2%   965Ki   0.6%  40.7Ki    third_party/protobuf/src/google/protobuf/descriptor_database.cc2.8%   854Ki  12.0%   819Ki    third_party/capstone/arch/X86/X86Mapping.c2.8%   846Ki   1.0%  66.4Ki    third_party/protobuf/src/google/protobuf/extension_set.cc2.7%   800Ki   0.6%  41.2Ki    third_party/protobuf/src/google/protobuf/generated_message_util.cc2.3%   709Ki   0.7%  50.7Ki    third_party/protobuf/src/google/protobuf/wire_format.cc2.1%   637Ki   1.7%   117Ki    third_party/demumble/third_party/libcxxabi/cxa_demangle.cpp1.8%   549Ki   1.7%   114Ki    src/bloaty.cc1.7%   503Ki   0.7%  48.1Ki    third_party/protobuf/src/google/protobuf/repeated_field.cc1.6%   469Ki   6.2%   427Ki    third_party/capstone/arch/X86/X86DisassemblerDecoder.c1.4%   434Ki   0.2%  15.9Ki    third_party/protobuf/src/google/protobuf/message.cc1.4%   422Ki   0.3%  23.4Ki    third_party/re2/re2/dfa.cc1.3%   407Ki   0.4%  24.9Ki    third_party/re2/re2/regexp.cc1.3%   407Ki   0.4%  29.9Ki    third_party/protobuf/src/google/protobuf/map_field.cc1.3%   397Ki   0.4%  24.8Ki    third_party/re2/re2/re2.cc100.0%  29.5Mi 100.0%  6.69Mi    TOTAL

Bloaty支持许多功能:

  1. 文件格式:ELF、Mach-O、PE/COFF(实验)、WebAssembly(实验)
  2. 数据来源:compilenit(如上所示)、符号、节、段等。
  3. 分层解析:将多个数据源合并为一个报告
  4. size diffs:查看二进制文件的增长位置,非常适合CI测试
  5. 单独的调试文件:剥离测试中的二进制文件,同时使调试数据可用于分析
  6. 灵活的解映射:解映射C++符号,可选择丢弃函数/模板参数
  7. 自定义数据源:regex重写内置数据源,用于自定义munging/bucketing
  8. 正则表达式过滤:过滤掉二进制文件中与给定正则表达式匹配或不匹配的部分

使用说明

$ ./bloaty bloatyFILE SIZE        VM SIZE    --------------  -------------- 30.0%  8.85Mi   0.0%       0    .debug_info24.7%  7.29Mi   0.0%       0    .debug_loc12.8%  3.79Mi   0.0%       0    .debug_str9.7%  2.86Mi  42.8%  2.86Mi    .rodata6.9%  2.03Mi  30.3%  2.03Mi    .text6.3%  1.85Mi   0.0%       0    .debug_line4.0%  1.19Mi   0.0%       0    .debug_ranges0.0%       0  15.0%  1.01Mi    .bss1.6%   473Ki   0.0%       0    .strtab1.4%   435Ki   6.3%   435Ki    .data0.8%   254Ki   3.7%   254Ki    .eh_frame0.8%   231Ki   0.0%       0    .symtab0.5%   142Ki   0.0%       0    .debug_abbrev0.2%  56.8Ki   0.8%  56.8Ki    .gcc_except_table0.1%  41.4Ki   0.6%  41.4Ki    .eh_frame_hdr0.0%  11.4Ki   0.1%  9.45Ki    [26 Others]0.0%  7.20Ki   0.1%  7.14Ki    .dynstr0.0%  6.09Ki   0.1%  6.02Ki    .dynsym0.0%  4.89Ki   0.1%  4.83Ki    .rela.plt0.0%  4.59Ki   0.0%       0    [Unmapped]0.0%  3.30Ki   0.0%  3.23Ki    .plt100.0%  29.5Mi 100.0%  6.69Mi    TOTAL

“VM SIZE”列告诉二进制文件加载到内存时将占用多少空间。“文件大小”列告诉二进制文件在磁盘上占用的空间。这两者可能彼此非常不同:

  • 有些数据存在于文件中,但没有加载到内存中,例如调试信息。
  • 某些数据已映射到内存中,但文件中不存在。这主要适用于.bss部分(零初始化数据)。

Bloaty中的默认细分是分段的,但支持许多其他对二进制文件进行切片的方式,如符号和分段。如果使用调试信息进行编译,甚至可以按编译单元和内联进行分解!效果见第一个例子。

Size Diffs

可以使用Bloaty来查看二进制文件的大小是如何变化的。
例如,这里有几个不同版本的Bloaty之间的大小差异,显示了当我添加一些功能时它是如何增长的。

$ ./bloaty bloaty -- oldbloatyVM SIZE                     FILE SIZE--------------               --------------[ = ]       0 .debug_loc     +688Ki  +9.9%+19%  +349Ki .text          +349Ki   +19%[ = ]       0 .debug_ranges  +180Ki   +11%[ = ]       0 .debug_info    +120Ki  +0.9%+23% +73.5Ki .rela.dyn     +73.5Ki   +23%+3.5% +57.1Ki .rodata       +57.1Ki  +3.5%+28e3% +53.9Ki .data         +53.9Ki +28e3%[ = ]       0 .debug_line   +40.2Ki  +4.8%+2.3% +5.35Ki .eh_frame     +5.35Ki  +2.3%-6.0%      -5 [Unmapped]    +2.65Ki  +215%+0.5% +1.70Ki .dynstr       +1.70Ki  +0.5%[ = ]       0 .symtab       +1.59Ki  +0.9%[ = ]       0 .debug_abbrev +1.29Ki  +0.5%[ = ]       0 .strtab       +1.26Ki  +0.3%+16%    +992 .bss                0  [ = ]+0.2%    +642 [13 Others]      +849  +0.2%+0.6%    +792 .dynsym          +792  +0.6%+16%    +696 .rela.plt        +696   +16%+16%    +464 .plt             +464   +16%+0.8%    +312 .eh_frame_hdr    +312  +0.8%[ = ]       0 .debug_str    -19.6Ki  -0.4%+11%  +544Ki TOTAL         +1.52Mi  +4.6%

分层解析

Bloaty支持以多种不同的方式分解二进制文件。您可以将多个数据源组合到一个层次配置文件中。例如,我们可以在单个报告中使用分段和分段数据源:

$ ./bloaty -d segments,sections bloatyFILE SIZE        VM SIZE    --------------  -------------- 80.7%  23.8Mi   0.0%       0    [Unmapped]37.2%  8.85Mi   NAN%       0    .debug_info30.6%  7.29Mi   NAN%       0    .debug_loc15.9%  3.79Mi   NAN%       0    .debug_str7.8%  1.85Mi   NAN%       0    .debug_line5.0%  1.19Mi   NAN%       0    .debug_ranges1.9%   473Ki   NAN%       0    .strtab1.0%   231Ki   NAN%       0    .symtab0.6%   142Ki   NAN%       0    .debug_abbrev0.0%  4.59Ki   NAN%       0    [Unmapped]0.0%     392   NAN%       0    .shstrtab0.0%     139   NAN%       0    .debug_macinfo0.0%      68   NAN%       0    .comment10.9%  3.21Mi  47.9%  3.21Mi    LOAD #4 [R]89.3%  2.86Mi  89.3%  2.86Mi    .rodata7.7%   254Ki   7.7%   254Ki    .eh_frame1.7%  56.8Ki   1.7%  56.8Ki    .gcc_except_table1.3%  41.4Ki   1.3%  41.4Ki    .eh_frame_hdr0.0%       1   0.0%       1    [LOAD #4 [R]]6.9%  2.03Mi  30.3%  2.03Mi    LOAD #3 [RX]99.8%  2.03Mi  99.8%  2.03Mi    .text0.2%  3.23Ki   0.2%  3.23Ki    .plt0.0%      28   0.0%      28    [LOAD #3 [RX]]0.0%      23   0.0%      23    .init0.0%       9   0.0%       9    .fini1.5%   439Ki  21.4%  1.44Mi    LOAD #5 [RW]0.0%       0  70.1%  1.01Mi    .bss99.1%   435Ki  29.6%   435Ki    .data0.4%  1.63Ki   0.1%  1.63Ki    .got.plt0.3%  1.46Ki   0.1%  1.46Ki    .data.rel.ro0.1%     560   0.0%     560    .dynamic0.1%     384   0.0%     376    .init_array0.0%      32   0.0%      56    [LOAD #5 [RW]]0.0%      32   0.0%      32    .got0.0%      16   0.0%      16    .tdata0.0%       8   0.0%       8    .fini_array0.0%       0   0.0%       8    .tbss0.1%  23.3Ki   0.3%  23.3Ki    LOAD #2 [R]30.7%  7.14Ki  30.7%  7.14Ki    .dynstr25.9%  6.02Ki  25.9%  6.02Ki    .dynsym20.8%  4.83Ki  20.8%  4.83Ki    .rela.plt7.7%  1.78Ki   7.7%  1.78Ki    .hash5.0%  1.17Ki   5.0%  1.17Ki    .rela.dyn3.1%     741   3.1%     741    [LOAD #2 [R]]2.7%     632   2.7%     632    .gnu.hash2.2%     514   2.2%     514    .gnu.version1.6%     384   1.6%     384    .gnu.version_r0.2%      36   0.2%      36    .note.gnu.build-id0.1%      32   0.1%      32    .note.ABI-tag0.1%      28   0.1%      28    .interp0.0%  2.56Ki   0.0%       0    [ELF Headers]46.3%  1.19Ki   NAN%       0    [19 Others]7.3%     192   NAN%       0    [ELF Headers]2.4%      64   NAN%       0    .comment2.4%      64   NAN%       0    .data2.4%      64   NAN%       0    .data.rel.ro2.4%      64   NAN%       0    .debug_abbrev2.4%      64   NAN%       0    .debug_info2.4%      64   NAN%       0    .debug_line2.4%      64   NAN%       0    .debug_loc2.4%      64   NAN%       0    .debug_macinfo2.4%      64   NAN%       0    .debug_ranges2.4%      64   NAN%       0    .debug_str2.4%      64   NAN%       0    .dynamic2.4%      64   NAN%       0    .dynstr2.4%      64   NAN%       0    .dynsym2.4%      64   NAN%       0    .eh_frame2.4%      64   NAN%       0    .eh_frame_hdr2.4%      64   NAN%       0    .fini2.4%      64   NAN%       0    .fini_array2.4%      64   NAN%       0    .gcc_except_table2.4%      64   NAN%       0    .gnu.hash100.0%  29.5Mi 100.0%  6.69Mi    TOTAL

Bloaty为每个级别显示最多20行;其他值被分组到[other]bin中。使用-n<num>可覆盖此设置。如果传递-n 0,所有数据都将被输出,而不会将任何内容折叠到[Other]中

调试剥离的二进制文件

Bloaty支持从单独的二进制文件中读取调试信息/符号。这使您可以对剥离的二进制文件进行配置,即使是对于像“compilenits”或“symbol”这样需要这些额外信息的数据源也是如此。
Bloaty使用构建ID来验证二进制文件和调试文件是否匹配。否则,结果将是无稽之谈(这种不匹配听起来可能不太可能,但这是一个很容易犯的错误)。
如果您的二进制文件有一个生成ID,那么使用单独的调试文件非常简单,如下所示:

$ cp bloaty bloaty.stripped
$ strip bloaty.stripped
$ ./bloaty -d symbols --debug-file=bloaty bloaty.stripped

数据源

Bloaty有许多内置的数据源。这些都提供了不同的方法来查看二进制文件。您还可以通过将正则表达式应用于内置数据源来创建自己的数据源(请参阅下面的“自定义数据源”)。
虽然Bloaty处理二进制文件、共享对象、对象文件和静态库(.a文件),但有些数据源不处理对象文件。这尤其适用于读取调试信息的数据源。

Segments段

段是运行时加载程序用来确定二进制文件的哪些部分需要加载/映射到内存中的内容。通常只有几个部分:每组mmap()权限需要一个:

$ ./bloaty -d segments bloatyFILE SIZE        VM SIZE    --------------  -------------- 80.7%  23.8Mi   0.0%       0    [Unmapped]10.9%  3.21Mi  47.9%  3.21Mi    LOAD #4 [R]6.9%  2.03Mi  30.3%  2.03Mi    LOAD #3 [RX]1.5%   439Ki  21.4%  1.44Mi    LOAD #5 [RW]0.1%  23.3Ki   0.3%  23.3Ki    LOAD #2 [R]0.0%  2.56Ki   0.0%       0    [ELF Headers]100.0%  29.5Mi 100.0%  6.69Mi    TOTAL

在这里,我们看到一个段被映射[RX](读/执行)和一个段映射[RW](读取/写入)。二进制文件的很大一部分没有加载到内存中,我们将其视为[未映射]。
对象文件和静态库没有段。然而,我们通过将部分按其标志分组来伪造它。这给了我们一个分解,有点像真实的片段。

$ ./bloaty -d segments CMakeFiles/libbloaty.dir/src/bloaty.cc.oFILE SIZE        VM SIZE    --------------  -------------- 87.5%   972Ki   0.0%       0    Section []8.2%  90.9Ki  78.3%  90.9Ki    Section [AX]2.3%  25.2Ki  21.7%  25.2Ki    Section [A]2.0%  22.6Ki   0.0%       0    [ELF Headers]0.1%     844   0.0%       0    [Unmapped]0.0%      24   0.1%      72    Section [AW]100.0%  1.09Mi 100.0%   116Ki    TOTAL

未完待续

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/16724.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3+Ant design 实现Select下拉框一键全选/清空

最近在做后台管理系统项目的时候,产品增加了一个让人非常苦恼的需求,让在Select选择器中添加一键全选和清空的功能,刚开始听到的时候真是很懵,他又不让在外部增加按钮,其实如果说在外部增加按钮实现全选或者清空的话&a…

3、python安装-linux系统下

安装前置依赖软件,安装完成后,打开官网,下载linux系统下的python安装包: 选择最新的版本 点击最新版本,进入版本对应的界面, 选择第一个进行源码的编译,右键选择复制连接地址, 回到终…

HTML+CSS+JS(web前端大作业)~致敬鸟山明简略版

HTMLCSSJS【动漫网站】网页设计期末课程大作业 web前端开发技术 web课程设计 文章目录 一、网站题目 二、网站描述 三、网站介绍 四、网站效果 五、 网站代码 文章目录 一、 网站题目 动漫网站-鸟山明-龙珠超 二、 网站描述 页面分为页头、菜单导航栏(最好可下拉&…

CDC 数据实时同步入湖的技术、架构和方案(截至2024年5月的现状调研)

近期,对 “实时摄取 CDC 数据同步到数据湖” 这一技术主题作了一系列深入的研究和验证,目前这部分工作已经告一段落,本文把截止目前(2024年5月)的研究结果和重要结论做一下梳理和汇总。为了能给出针对性的技术方案&…

Redis和MySQL的结合方式

Redis和MySQL的结合方式可以多样化,以满足不同的应用需求。以下是几种常见的结合方式,以及它们的特点和适用场景: 缓存数据库查询结果: 应用程序首先尝试从Redis中查询数据。如果Redis中没有所需数据,则从MySQL数据库中…

ESP32-C6接入巴法云,Arduino方式

ESP32-C6接入巴法云,Arduino方式 第一、ESP32-C6开发环境搭建第一步:安装arduino IDE 软件第二步:安装esp32库第三:arduino 软件设置 第二:简单AP配网程序第一步:程序下载第二步:程序使用第三步…

电脑微信群发 500 1000人以上怎么群发,微信营销群发助手软件,本人亲测,增加十倍业绩!!!

今天给大家推荐一款我们目前在使用的电脑群发工具掘金小蜜,不仅可以无限多开,方便你同时管理多个账号,群发功能更是十分强大,轻松释放你的双手。 掘金小蜜(只支持Win7及以上操作系统,没有推Mac版和手机客户…

[码蹄集新手训练营]MT1016-MT1020

目录 题号MT1016 宽度与对齐MT1017 左右对齐MT1018 输入宽度MT1020 %s格式符 题号 MT1016 宽度与对齐 #include<stdio.h> int main() { printf("%-5d %5d\n%-5d %5d\n%-5d %5d",455,455,-123,-123,987654,987654);return 0; }MT1017 左右对齐 #include<s…

Mac | macOs系统安装Monuty解决外接u盘ntfs读写问题

问题 mac电脑的macOs系统无法将文件读写入外接u盘或硬盘中&#xff1b; 解决方案 安装Monuty 官网&#xff1a;mounty官网 下载软件 安装其他配置 macbook:~ uwe$ brew install --cask macfuse macbook:~ uwe$ brew install gromgit/fuse/ntfs-3g-mac macbook:~ uwe$ brew…

【Vue】组件用法

【前言】 … 【目标】 1 了解组件间传参 2 组件间自定义事件绑定与解绑 3 组件的事件总线,消息订阅与发布的用法 4 组件插槽 一 组件间传参 #mermaid-svg-CAQFgxRrMK5KRFOr {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#merma…

机顶盒也可以跑量--上机指南

一、背景介绍 随着科技的进步和智能设备的普及&#xff0c;机顶盒已不再是单纯的电视接收器&#xff0c;而是逐渐演变成为家庭娱乐中心。越来越多的机顶盒支持各种应用、游戏和功能&#xff0c;使得用户可以在大屏幕上享受更多样化的内容。本指南将带你深入了解如何让你的机顶…

Spring中如何配置和使用Properties文件?

在Spring框架中&#xff0c;.properties 文件通常用于存储配置信息&#xff0c;如数据库连接、服务地址、应用参数等。以下是配置和使用 Properties 文件的详细步骤&#xff1a; 1. 创建 Properties 文件 在项目的 src/main/resources 目录下创建一个 .properties 文件&#…

价格预言机领导者 Pyth 与 Eclipse 平台集成,为高频 DeFi 应用提供支持

本篇文章将对这一战略合作伙伴关系&#xff0c;以及 Pyth 网络在 Eclipse 生态系统中扮演的关键角色进行深入探讨。 目前&#xff0c;Pyth 价格数据已正式上线于 Eclipse 测试网。Eclipse 是首个结合了以太坊安全性、Solana 性能和 Celestia DA 的 Solana虚拟机(SVM) Layer2 方…

Key Chain has stopped 是什么

Key Chain has stopped 是一个特定的错误消息&#xff0c;通常出现在Android设备上。这个错误提示意味着设备上的“Key Chain”服务出现了问题&#xff0c;Key Chain服务在Android中负责管理设备的安全密钥和证书&#xff0c;包括用户的隐私密钥、应用签名密钥等。当这个服务意…

无线麦克风哪个牌子性价比高?揭秘领夹麦克风性价比最高品牌

随着自媒体行业的兴起&#xff0c;现在视频直播或者是个人Vlog都越来越受欢迎了&#xff0c;要想做好内容&#xff0c;除了画面之外&#xff0c;声音效果同样重要。而我们手机上自带的麦克风&#xff0c;容易受环境影响&#xff0c;特别是在户外或者拍摄距离较远时&#xff0c;…

微软改进WSL子系统 新版将支持镜像宿主机网络接口及使用外部DNS

Windows SubSystem for Linux (即 WSL) 是微软在 Windows 10/11 中开发的子系统功能&#xff0c;该功能允许用户在 Windows 上安装 Linux 系统和相关环境&#xff0c;对开发者来说可以构建 Linux 开发环境进行工作。不过 WSL 系统在功能上也有不少缺点&#xff0c;典型的就是默…

【Docker实战】进入四大数据库的命令行模式

上一篇我们讲了docker exec命令&#xff0c;这一次我们使用docker exec命令来进入四大数据库的命令行模式。 我们进行游戏开发或软件开发是离不开四大数据库的&#xff0c;这四大数据库分别是关系型数据库mysql、postgres&#xff0c;nosql数据库redis、mongodb。将它们容器化…

TopK问题

前言&#xff1a;本篇对TopK问题的解答是介于堆的基础上讲的 TopK问题&#xff1a; 就是在许多数据中找到前K个最大的数据或者最小的数据 比如&#xff1a;专业前10、世界五百强、富豪榜、以及游戏排行榜等等 对于TopK问题&#xff1a;能想到的最简单直接的方式就是排序解决,…

fastadmin二次开发 修改默认的前端弹出样式

需要修改fastadmin后台默认的弹出提示样式效果&#xff1a; 在项目里搜索这个关键词&#xff1a;Toastr 首先这个文件&#xff0c;里面的success和error就是弹出提示的方法。 public/assets/js/fast.js 然后是下面这个文件&#xff1a; public/assets/js/require-form.js 你…

对于高速信号完整性,一块聊聊啊(13)

前面一篇说了有源仿真和无源仿真的区别&#xff0c;今天介绍一下前仿真和后仿真。 一个完整的电路设计中必然包含前仿真和后仿真两个部分&#xff0c;它们都属于验证的必要环节。 尤其是在复杂的芯片设计中&#xff0c;验证要占用整个芯片设计流程时间的60%-70%。目的就是尽可…