嘗試在Mac/iOS上使用tcmalloc庫


概述

       TCMalloc 是 Google 開發的內存分配器,在不少項目中都有使用,例如在 Golang 中就使用了類似的算法進行內存分配。它具有現代化內存分配器的基本特征:對抗內存碎片、在多核處理器能夠 scale。據稱,它的內存分配速度是 glibc2.3(glibc是GNU發布的libc庫,即c運行庫。glibc是linux系統中最底層的api,幾乎其它任何運行庫都會依賴於glibc。glibc除了封裝linux操作系統所提供的系統服務外,它本身也提供了許多其它一些必要功能服務的實現)中實現的 malloc的數倍。

  TCMalloc全稱Thread-Caching Malloc,即線程緩存的malloc,實現了高效的多線程內存管理,用於替代系統的內存分配相關的函數(malloc、free,new,new[]等)。

  TCMalloc是gperftools的一部分,除TCMalloc外,gperftools還包括heap-checker、heap-profiler和cpu-profiler。本文只討論gperftools的TCMalloc部分。

  git倉庫:https://github.com/gperftools/gperftools.git

  官方介紹:https://gperftools.github.io/gperftools/TCMalloc.html

安裝

       從git倉庫clone版本的gperftools的安裝依賴autoconf、automake、libtool,以Mac為例:

  $ brew install autoconf automake libtool

  Autoconf實際上是一個工具集,其中包含aclocal、autoheader和autoconf等可執行文件。Libtool軟件包是第三個重要的GNU工具,它的作用是確定共享庫在特定平台上的特性。

  $ ./autogen.sh

  生成Makefile

  $ ./configure

  編譯

  $ make

  安裝

  $ make install

  默認安裝在/usr/local/下的相關路徑(bin、lib、share),可在configure時以--prefix=PATH指定其他路徑。

       TCMalloc是如何生效的

  為什么指定-ltcmalloc或者與libtcmalloc_and_profiler.a連接之后,對malloc、free、new、delete等的調用就由默認的libc中的函數調用變為TCMalloc中相應的函數調用了呢?答案在libc_override.h中

  Qt工程中使用tcmalloc,新建工程qtTCmallocTest,pro文件中鏈接靜態庫libtcmalloc.a或者動態庫libtcmalloc.dylib,我使用Mac平台的clang構建正常,運行也正常,Demo運行截圖如下圖所示,一切都好!

  

  我使用iOS Simulator構建出現警告錯誤:

  :-1: warning: URGENT:building for iOS Simulator simulator, but linking against dylib (/usr/local/lib/libtcmalloc.dylib) built for macOS. Note: This will be an error in the future.

       實際運行也會有運行時的類似提示導致最終無法在iOS模擬器上運行:

   

  解決辦法:重新編譯配置

       $make uninstall                          // 刪除/usr/local/lib下的tcmalloc庫

       $make clean                              // 清除make產生的臨時文件

       // 重新configure來配置,只生成minimal的靜態庫(.a)

       $./configure --disable-cpu-profiler --disable-heap-profiler --disable-heap-checker --enable-minimal --enable-static --disable-shared

       $make & make install

       編譯安裝成后后

       $cd /usr/local/lib

       $ls

      

       可見只生成了libtcmalloc_minimal.a和libtcmalloc_minimal_debug.a

       查看靜態庫的架構:

       $lipo –info libtcmalloc_minimal.a

      

       可見是x86_64架構的靜態庫,我們的iOS模擬器是64位處理器,測試需要x86_64架構庫,看起來可以使用的。

  現在重新在Qt Creator中使用iOS Simulator構建我們上面的qtTCmallocTest Demo,在pro文件中添加靜態庫libtcmalloc_minimal.a,編譯鏈接,結果成功構建,運行時卻出錯了~

  

  錯誤提示在tcmalloc的源碼中,嘗試free了已經失效的指針導致出錯。可能的原因是程序啟動后會調用glibc內存分配的malloc、free等函數,而tcmalloc庫就已經將glibc中的內存分配替換成了自己的,此時有點過早調用導致出錯。

  解決:注釋修改tcmalloc源碼相關部分,然后再重新make以及make install

  找到libc_override_osx.h,注釋部分代碼

  

   

  重新make過程中還會出現如下錯誤:

  

  可以看到是cfree和pvalloc引用錯誤,找到tcmalloc_unittest.cc可以看到如下代碼:

       #if defined(_WIN32)

  # define cfree free         // don't bother to try to test these obsolete fns

  # define valloc malloc

  # define pvalloc malloc

  將該文件中用到cfree的地方用free替代,用到valloc和pvalloc的地方用malloc替代,保存后,再重新make,沒啥錯誤,緊接着make install。

  再次構建Demo,並運行:

  

  注意:手機等嵌入式內存等較小,程序中不宜不斷申請內存,可能造成內存不夠用導致程序崩潰退出。

  到此為止,使用tcmalloc靜態庫嘗試可以在iOS模擬器上運行了~

  但是我在iOS真機上編譯時卻提示找不到arm64架構符號的錯誤:

  

  可見在Mac OS的終端中執行的./configure & make & make install等操作編譯出來的靜態庫和動態庫是針對Mac平台的,iOS平台不兼容導致無法使用。

  該文章指出:iOS用不了谷歌的tcmalloc,無語了~

  Compile tcmalloc for iOS,but getting errors進行了Compile tcmalloc for iOS的嘗試,但是遇到了錯誤,看底下評論,這一部分在官網文檔中並沒有涉及,也希望借此機會來完善tcmalloc對iOS的支持。

  我努力嘗試Clang交叉編譯iOS真機版本的tcmalloc,最終沒有編譯出可以正常使用的arm64架構的靜態庫,目前是個難題,煩請哪位大神給予指導!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM