鏈接庫文件體積優化工具篇: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.pswp.cn/bicheng/16724.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/16724.shtml
英文地址,請注明出處:http://en.pswp.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%。目的就是盡可…