1. 程式人生 > >Android 平臺用 Gprof 給 Cocos2d-x 做效能分析

Android 平臺用 Gprof 給 Cocos2d-x 做效能分析

gprof

在 iOS 平臺下我們可以用 Xcode 自帶的 Profile 工具來測試我們程式的效能,那在 Android 平臺下面要怎麼搞呢?答案就是gprof。什麼是 gprof 呢?引用 Wiki 的解釋:

Gprof is a performance analysis tool for Unix applications. It uses a hybrid of instrumentation and sampling[1] and was created as extended version of the older “prof” tool. Unlike prof, gprof is capable of limited call graph collecting and printing.

因為 Android 本來就是基於 Linux 的,所以這裡用 gprof 來做效能測試是沒什麼問題的。不過需要注意的是,這裡所說的效能測試是針對 NDK 編譯的 C++ 程式碼的。就想 Cocos2d-x 這樣的 C++ 實現的遊戲引擎就可以通過 gprof 來分析。下面我們來說說搞法。

環境

我是 Mac OS X 下,這裡要做效能分析的 Cocos2d-x 專案是基於 Cocos2d-x 3.2 引擎,專案本身是基於 Lua 指令碼編寫的。其實這些都無關緊要,只不過是編譯出的 so 檔案有所不同罷了。只要是 NDK 的程式碼都可以用 gprof 來做效能分析的。

android-ndk-profiler

要想生成 gprof 的效能分析報告,我們優先要把一個叫做 android-ndk-profiler 的模組整合到我們的專案中。android-ndk-profiler 模組的原始碼在 GitHub 上面,首先要把模組程式碼 clone 下來

1
git clone [email protected]:richq/android-ndk-profiler.git

android-ndk-profiler 的專案自帶了一篇文件說明教授如何整合和使用,但是寫的比較簡單,我來詳細的說一下。android-ndk-profiler 專案 clone 下來後進到專案目錄可以看到如下結構

1
2 3 4
 |-docs
 |-example
 |-jni
 |-test

而我們需要的就是jni這個目錄下面的檔案。

整合 android-ndk-profiler 到 Cocos2d-x 專案

拷貝檔案

來到我們自己的 Cocos2d-x 專案目錄中,新建一個叫做 android-ndk-profiler 的資料夾,將剛剛克隆的 android-ndk-profile 模組的 jni 目錄中的所有檔案拷貝到我們剛剛建立的資料夾中。

編輯 Android.mk 檔案

開啟 proj.android/jin/Android.mk 檔案,加入如下程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#*注意* YOUR_ANDROID_NDK_PROFILER_PATH 是你 cocos2d-x 專案中 android-ndk-profiler 目錄的位置
$(call import-add-path,$(YOUR_ANDROID_NDK_PROFILER_PATH))
# 加入標頭檔案
LOCAL_C_INCLUDES += $(YOUR_ANDROID_NDK_PROFILER_PATH)
APP_DEBUG := $(strip $(NDK_DEBUG))
# 如果是 Debug 模式,則引入 android-ndk-profiler
ifeq ($(APP_DEBUG),1)
  LOCAL_CFLAGS := -pg
  LOCAL_STATIC_LIBRARIES += android-ndk-profiler
endif
ifeq ($(APP_DEBUG),1)
  $(call import-module,YOUR_ANDROID_NDK_PROFILER_PATH)
endif

這裡只解釋兩點。

LOCAL_CFLAGS := -pg 通過在編譯使用 -pg 編譯和連結選項,gcc 在你應用程式的每個函式中都加入了一個名為mcount ( or “_mcount” , or “__mcount” , 依賴於編譯器或作業系統) 的函式,也就是說你的應用程式裡的每一個函式都會呼叫 mcount, 而 mcount 會在記憶體中儲存一張函式呼叫圖,並通過函式呼叫堆疊的形式查詢子函式和父函式的地址。這張呼叫圖也儲存了所有與函式相關的呼叫時間,呼叫次數等等的所有資訊。

APP_DEBUG 這裡增加了一個判斷,只有當以 NDK_DEBUG=1 的 Debug 模式編譯 NDK 程式碼的時候才開啟 android-ndk-profiler 分析功能,這樣保證我們出 Release 版本的時候不引入效能分析。

使用 android-ndk-profiler

以 Debug 模式重新編譯一下專案程式碼:

1
2
cd proj.android
ndk-build NDK_DEBUG=1

如果編譯成功那麼說明 android-ndk-profiler 已經成功整合到我們的 Cocos2d-x 專案中了,整合的過程非常簡單,同樣,android-ndk-profiler 的使用也非常的方便。

編輯 AppDelegate.cpp 檔案

只需要引入一個頭檔案,新增兩個函式呼叫即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 引入標頭檔案
#if (COCOS2D_DEBUG>0 && CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "prof.h"
#endif
bool AppDelegate::applicationDidFinishLaunching()
{
#if (COCOS2D_DEBUG>0 && CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
  monstartup("libcocos2dlua.so");
#endif
  // 其他已有邏輯程式碼......
}
void AppDelegate::applicationDidEnterBackground()
{
  // 其他已有邏輯程式碼......
#if (COCOS2D_DEBUG>0 && CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    moncleanup();
#endif
}

這裡只需要注意兩點。

AndroidManifest.xml 因為要生成效能分析報告,所以要賦予你的 Android 程式 WRITE_EXTERNAL_STORAGE 許可權,即

1
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

libcocos2dlua.so 這個 so 檔案會根據你的 Cocos2d-x 專案的型別不同名字上會有所不同,比如我們是 Lua 專案,所以 NDK 編譯生成的 so 檔案就叫 libcocos2dlua.so ,具體的檔名請自行到 proj.android/libs/armeabi 目錄下檢視。

再次以 Debug 模式重新編譯一下專案程式碼,如果沒有錯誤,那麼大功就告成了。

生成 gmon.out 效能分析報告

專案編譯完成後生成 apk 檔案,將 apk 檔案安裝到 Android 裝置上。通過上一小節我們對 AppDelegate.cpp 檔案的修改不難看出,當程式在 Android 裝置上執行的時候,呼叫了 monstartup 函式開始效能分析,當程式退到後臺時呼叫了 moncleanup 函式生成效能分析報告。效能分析報告檔案預設儲存到 Android 裝置的 /sdcard/gmon.out 位置,我們用 adb 工具可以把檔案拉到電腦上面。

1
adb pull /sdcard/gmon.out .

當然官方文件裡面也提了,如果想要自定義效能分析報告存放的位置,可以在呼叫 moncleanup 函式前指定要儲存的位置。

1
2
setenv("CPUPROFILE", "/data/data/com.example.application/files/gmon.out", 1);
moncleanup();

解讀效能分析報告 gmon.out

生成的效能分析告報 gmon.out 是不能直接通過文字編輯器開啟來讀的,它是個二進位制檔案,需要專門的工具來生成可讀的文字檔案。這個工具在 NDK 中已經提供了,以我使用的 android-ndk-r10d 為例:

1
2
3
4
5
cd android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/
./arm-linux-androideabi-gprof \
  你的專案路徑/proj.android/obj/local/armeabi/libcocos2dlua.so\
  你的gmon.out存放路徑/gmon.out > gmon.txt

這裡只解釋一點。

libcocos2dlua.so 細心的讀者發現這裡使用的 so 檔案並不是之前的那個放在 proj.android/libs/armeabi/libcocos2dlua.so 下面的那個 so 檔案。這是因為最終隨 apk 一起打包的那個 libcocos2dlua.so 檔案(也就是 proj.android/libs/armeabi 目錄下的)是不包含符號表的,而存放在 proj.android/obj/local/armeabi 目錄下的是帶符號表的版本。而什麼是符號表,這是一個編譯連結中的概念,請自行 Google 一下,或者讀一讀《程式設計師的自我修養》這本書,再次強烈推薦這本書。

gmon.txt 解讀

我節選一下生成的 gmon.txt 的兩處比較重要的部分來看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Flat profile:
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
 19.14      1.16     1.16                             png_read_filter_row_paeth_multibyte_pixel
 15.35      2.09     0.93                             cocos2d::Image::premultipliedAlpha()
 14.36      2.96     0.87                             cocos2d::Texture2D::convertRGBA8888ToRGBA4444(unsigned char const*, int, unsigned char*)
  7.10      3.39     0.43                             profCount
  3.96      3.63     0.24                             png_read_filter_row_up
  3.30      3.83     0.20                             llex
  3.14      4.02     0.19                             png_read_filter_row_sub
  2.81      4.19     0.17                             __gnu_mcount_nc
  ......
           Call graph (explanation follows)
granularity: each sample hit covers 2 byte(s) for 0.17% of 5.99 seconds
index % time    self  children    called     name
                                                 <spontaneous>
[1]     19.4    1.16    0.00                 png_read_filter_row_paeth_multibyte_pixel [1]
-----------------------------------------------
                                                 <spontaneous>
[2]     15.5    0.93    0.00                 cocos2d::Image::premultipliedAlpha() [2]
-----------------------------------------------
                                                 <spontaneous>
[3]     14.5    0.87    0.00                 cocos2d::Texture2D::convertRGBA8888ToRGBA4444(unsigned char const*, int, unsigned char*) [3]
-----------------------------------------------
                                                 <spontaneous>
[4]      7.2    0.43    0.00                 profCount [4]
-----------------------------------------------
                                                 <spontaneous>
[5]      4.0    0.24    0.00                 png_read_filter_row_up [5]
-----------------------------------------------

簡單解釋一下含義

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Flat profile:
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
 函式     程式       函式       函式    函式     函式      函式名
 消耗     累計       本身       呼叫    平均     平均
 時間     執行       執行       次數    執行     執行
 佔程     時間       時間              時間     時間
 序運                                 (      (
 行時                                         
 間的                                         
 百分                                         調
                                     調       
                                             
                                             )
                                      )
           Call graph (explanation follows)
granularity: each sample hit covers 2 byte(s) for 0.17% of 5.99 seconds
index % time    self  children    called     name
 索引    函式     函式   函式的       被呼叫      函式名
       執行     本身   子函式        次數
        時間     執行    執行
        佔程     時間    時間
        序運
        行時
        間百
        分比

相關推薦

Android 平臺 Gprof Cocos2d-x 效能分析

gprof 在 iOS 平臺下我們可以用 Xcode 自帶的 Profile 工具來測試我們程式的效能,那在 Android 平臺下面要怎麼搞呢?答案就是gprof。什麼是 gprof 呢?引用 Wiki 的解釋: Gprof is a performance analysis tool for Unix

怎樣ccache加速cocos2d-x android版本號的編譯

can ins 數據 pro 增加 chang mpi com win 下面步驟在MAC下測試通過: 首先是安裝CCache, 能夠用homebrew brew install --HEAD ccache 也能夠用源代碼安裝 git clone https://g

android ndk 崩潰捕獲(cocos2d-xandroid崩潰捕獲)

ndk 崩潰捕獲 ,我們可以採用 breakpad是一個跨平臺的c++崩潰處理系統。包括:dmp生成模組、 上傳模組、 伺服器儲存模組、解析dmp模組 等。 這裡我只大概說一下dmp生成模組。 1、編譯靜態庫解壓並拷貝breakpad原始碼目錄到專案中,編譯: 指令

cocos2d-x 專案時問題,Assertion failed! Expression: m_pChildren->containsObject(pSprite)

出現以下介面 點選忽略時,會彈出 表示說在這裡中斷 在程式反覆查試之後發現時我運用到已經刪除的一個CCSprite,在它刪除之後還會呼叫到它的位置,即會出現這些錯誤,查了很久,所以發上去給大家分享,希望有幫助!

使用Android Profile效能分析及優化

前言 做Android開發五年,開發工具從最初的eclipse+ADT外掛到AndroidStduio。Google更是在新版的AndroidStudio中集成了Android應用效能分析利器——Profile。 本文基於AndroidStudio 3.2.1 正式版進行分析並定位問題原因。附上下載地址:

Cocos2d-x效能檢測

OpenGL 效能指標 cocos2d-x 中有三個跟 OpenGL 相關的效能指標,遊戲執行時顯示在左下角;cocos2d-x 預設會顯示這些效能指標,可以手動在程式碼在開啟或關閉,C++ 專案在 AppDelegate 的 applicationDidFi

Android平臺藍芽程式設計之藍芽聊天分析(二)

接著上一篇沒有完成的任務,我們繼續分析這個藍芽聊天程式的實現,本文主要包括以下兩個部分的內容:其一,分析掃描裝置部分DeviceListActivity,其二,分析具體的聊天過程的完整通訊方案,包括埠監聽、連結配對、訊息傳送和接收等,如果有對上一篇文章不太熟悉的,可以返回

使用gprof來對程式的效能分析總結

目錄 1.    GPROF介紹    4 2.    使用步驟    4 3.    使用舉例    4 3.1    測試環境    4 3.2    測試程式碼    4 3.3    資料分析    5 3.3.1    flat profile模式    6 3.3.2    call graph

5種方法對python程式程式碼效能分析和計時統計

python程式碼執行時間統計 以下方法分別針對 程式碼塊、程式碼程式檔案、 函式 進行效能計時統計 一、time.time() 或者 datetime.datetime.now() 返回當前時間的時間戳 如 1524302633.980187 兩次時間相減,

Cocos2d-x: 安卓打包問題 “ GoogleAPIs:21 不是一個有效的 Android 目標平臺

一個 androi 發生 cocos2 api clip strong googl color   問題:GoogleAPIs:21 不是一個有效的 Android 目標平臺。   產生原因:這是由於使用Eclipse運行Android項目後, 項目的bulid Targe

Cocos2d-x v3.0正式版嘗鮮體驗【2】 Android平臺移植

生成 ble ack nts 做的 導入 eclipse so文件 腳本 今天沒事又嘗試了下3.0正式版關於Android平臺的移植,把新建的項目移植了下。過程僅用了十分鐘左右,什麽概念?!好吧,事實上我想說,這個版本號真的移植非常輕松啊,只是還沒加上其它東西,只是就眼

一個懶COCOS2D-X程式猿(一)停止手打所有cpp檔案到android.mk[轉]

前言:”懶”在這裡當然不是貶義詞,而是追求高效,拒絕重複勞動的代名詞!做一個懶COCOS2D-X程式猿的系列文章將教會大家在工作中如何偷懶,文章篇幅大多較短,有的甚至只是幾行程式碼,爭取把懶發揮到極致!   一.懶人說書 Android.mk中LOCAL_SRC_FIL

Cocos2d-x 3.x 頭像選擇器,本地相簿與拍照+頭像編輯功能(Android、IOS雙平臺實現)

大連遊戲行業不是太發達,最後選擇在一家應用外包公司工作,在工作和業餘學習過程中積累了一點微不住道的經驗,希望分享給熱愛遊戲的小夥伴們。 在應用開發過程中會常常有使用者上傳頭像的功能,在網上找了N多資料發現沒有人具體介紹過該用cocos2d-x實現。這篇文章就來介紹一下如何在

Windows平臺下Cocos2d-x 打包Android平臺APK

從Cocos2d-x 3.2專案打包成apk安卓應用檔案,搭建安卓環境的步驟有點繁瑣,但搭建一次之後,以後就會非常快捷!(涉及到3.1.1版本的,請自動對應3.2版本,3.x版本的環境搭建都是一樣的) 一、軟體 (1)VS2012(C++11特性在VS2012以上可以

Android studio建立Cocos2d-x 3.X專案

如果你還在用eclipse那你就out了,Android Studio從1.3版開始支援對C++的編輯(雖然從目前來看用Android Studio來編輯C++還比較蛋疼)。而且Cocos2d-x從3.7版開始優化對android studio的支援,相信這一趨勢還會繼續。

cocos2d-x 3.0rc版編譯到android平臺缺少cocos-ext.h標頭檔案的問題解決

問題解決: 修改proj.android/jni/Android.mk 現將需要修改的程式碼貼出: LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes\         $(LOCAL_PATH)/../../cocos2d/extensions \ $

關於cocos2d-x 和安卓之間的相互調

using with font android bject deb 交流 sta log 近期在研究cocos2d遊戲移植安卓須要調用非常多方法。所以在研究之中寫下它們之間相互調用 首先,cocos2d調用安卓 在一個.h文件裏加入頭文件 #include &l

Cocos2d-x 3.0 打造一個全平臺概念文件夾

android cocos2d www 全平臺 -s http 概念 1-1 style Cocos2d-x 3.0 打造一個全平臺概念文件夾http:// www.eoeandroid.com/thread-328055-1-1.html Cocos2d

cocos2d-x 3.0 final 移植 android

filename details blank each 連接 python 頭文件 osd 需求 準備工作 你僅僅要依照上一篇的 cocos2d-x 3.0 final 環境搭建 完畢就能夠了 1.編輯proj.android\jni\Android.mk,更改內

cocos2d-x 2.2.0 怎樣在lua中註冊回調函數C++

s2d 意思 函數 mlu pan build [[]] 進行 ret cocos2d-x內部使用tolua進行lua綁定。可是引擎並沒有提供一個通用的接口讓我們能夠把一個lua函數註冊給C++層面的回調事件。 翻看引擎的lua綁定代碼,我們能夠仿