Android代碼調試工具 traceview 和 dmtracedump的波折演繹無標題文章

Android代碼調試工具 traceview 和 dmtracedump的波折演繹



?Android 程序調試工具

Google為我們提供的代碼調試工具的亮點:traceviewdmtracedump。有了這兩個工具,我們調試程序分析bug就非常得心應手了。traceview幫助我們分析程序性能,dmtracedump生成函數調用圖。遺憾的是,google提供的dmtracedump是個失敗的工具,并不能繪圖,本文會詳細介紹解決方案,實現繪圖。

?生成.trace文件

android.os.Debug類,其中重要的兩個方法Debug.startMethodTracing()和Debug.stopMethodTracing()。這兩個方法用來創建.trace文件,將從Debug.startMethodTracing()開始,到Debug.stopMethodTracing()結束,期間所有的調用過程保存在.trace文件中,包括調用的函數名稱和執行的時間等信息。

把下面代碼分別在加在調試起始代碼的位置,和終止位置。

Debug.startMethodTracing(“test”);

Debug.stopMethodTracing();

其中參數test是要創建的trace文件的名稱,test.trace。默認路徑是/sdcard/test.trace,也可以自己制定/data/log/test,表示文件在/data/log/test.trace。

?traceview

在SDK中執行 ?:

./traceview test.trace

我們可以得到

1.程序中每個線程調用方法的啟動和停止時間

2.函數執行的信息和效率分析

?dmtracedump

dmtracedump原本的用意是將整個調用過程和時間分析結合,以函數調用圖的形式表現出來。可是google這個項目一直處于broken狀態,遲遲不能得到完善。現在的dmtracdump只有-o選項可以使用,在終端上列出函數調用信息,和traceview功能相似,如果執行./dmtracedump –g test.png test.trace就會卡住不動。

起初我以為是test.trace文件的問題,對文件的結束符稍作修改,畫出了一副雷人的圖片:

后來,搜到了網絡上有牛人提供了dmtracedump的替代(這是原文鏈接),是一個python腳本,借助dot來繪制矢量圖。python腳本一定要注意對齊格式,對齊縮進就是他的邏輯結構。

#!/usr/bin/env?python

"""

turn?the?traceview?data?into?a?jpg?pic,?showing?methods?call?relationship

"""

importsys

importos

importstruct

importre

################################################################################

########################??Global?Variable??#####################################

################################################################################

target_thread=1#the?thread?that?we?want?to?track,?filt?out?other?threads

#all_actions?=?["enter","exit","exception","reserved"]

all_threads?=?{}

all_methods?=?{}

all_records?=?[]

parent_methods?=?{}

child_methods?=?{}

method_calls?=?{}

################################################################################

##############################???Methods???#####################################

################################################################################

defadd_one_thread(line):

fields?=?line.split("/t")

all_threads[int(fields[0],10)]=fields

defadd_one_method(line):

fields?=?line.split("/t")

all_methods[int(fields[0],16)]=fields

defadd_one_record(one):

thread_id,=struct.unpack("B",one[:1])

if(thread_id?==?target_thread):

tmp,=struct.unpack("L",one[1:5])

method_id=?(tmp?/4)?*4;

method_action=?tmp?%4;

time_offset,=struct.unpack("L",one[5:])

all_records.append([thread_id,?method_id,?method_action,?time_offset])

defhandle_one_call(parent_method_id,method_id):

ifnot(parent_methods.has_key(parent_method_id)):

parent_methods[parent_method_id]=1

ifnot(child_methods.has_key(method_id)):

child_methods[method_id]=1

ifmethod_calls.has_key(parent_method_id):

ifmethod_calls[parent_method_id].has_key(method_id):

method_calls[parent_method_id][method_id]+=1

else:

method_calls[parent_method_id][method_id]=1

else:

method_calls[parent_method_id]={}

method_calls[parent_method_id][method_id]=1

defgen_funcname(method_id):

r1=re.compile(r'[/{1}lt;>]')

str1=r1.sub("_",all_methods[method_id][1])

str2=r1.sub("_",all_methods[method_id][2])

returnstr1+"_"+str2

defgen_dot_script_file():

myoutfile?=?open("graph.dot","w")

myoutfile.write("digraph?vanzo?{/n/n");

foroneinall_methods.keys():

ifparent_methods.has_key(one):

myoutfile.write(gen_funcname(one)+"??[shape=rectangle];/n")

else:

ifchild_methods.has_key(one):

myoutfile.write(gen_funcname(one)+"??[shape=ellipse];/n")

foroneinmethod_calls.keys():

fortwoinmethod_calls[one]:

myoutfile.write(gen_funcname(one)?+'?->?'+?gen_funcname(two)?+'?[label="'+?str(method_calls[one][two])?+'"??fontsize="10"];/n')

myoutfile.write("/n}/n");

myoutfile.close

################################################################################

##########################?Script?starts?from?here?#############################

################################################################################

iflen(sys.argv)?<2:

print'No?input?file?specified.'

sys.exit()

ifnot(os.path.exists(sys.argv[1])):

print"input?file?not?exists"

sys.exit()

#Now?handle?the?text?part

current_section=0

forlineinopen(sys.argv[1]):

line2?=?line.strip()

if(line2.startswith("*")):

if(line2.startswith("*version")):

current_section=1

else:

if(line2.startswith("*threads")):

current_section=2

else:

if(line2.startswith("*methods")):

current_section=3

else:

if(line2.startswith("*end")):

current_section=4

break

continue

ifcurrent_section==2:

add_one_thread(line2)

ifcurrent_section==3:

add_one_method(line2)

#Now?handle?the?binary?part

mybinfile?=?open(sys.argv[1],"rb")

alldata?=?mybinfile.read()

mybinfile.close()

pos=alldata.find("SLOW")

offset,=struct.unpack("H",alldata[pos+6:pos+8])

pos2=pos+offset#pos2?is?where?the?record?begin

numofrecords?=?len(alldata)?-?pos2

numofrecords?=?numofrecords?/9

foriinxrange(numofrecords):

add_one_record(alldata[pos2?+?i?*9:pos2?+?i?*9+9])

my_stack=[0]

foronerecordinall_records:

thread_id=onerecord[0];

method_id=onerecord[1];

action=onerecord[2];

time=onerecord[3];

if(action==0):

if(len(my_stack)?>1):

parent_method_id=my_stack[-1]

handle_one_call(parent_method_id,method_id)

my_stack.append(method_id)

else:

if(action==1):

if(len(my_stack)?>1):

my_stack.pop()

gen_dot_script_file()

os.system("dot?-Tjpg?graph.dot?-o?output.jpg;rm?-f?graph.dot");

修改,/t變為\t,/n變為\n。

在計算器的源碼onCreate中添加

Debug.startMethodTracing(“calc”);

Log.v(LOG_TAGS”+++++++++++++++++++++++++test++++++++++++++++”);

Debug.stopMethodTracing();

運行腳本得到calc.trace ,畫出out.jpg

可當得到的trace文件比較復雜時畫圖就會崩潰。修改腳本最后執行dot命令時的參數,jpg格式太大容易崩潰,-Tjpg改為-Tpng:gd,畫大幅png。

我拿camera做了個實驗,得到的png甚大,這是其中一角:

OK累死我了,又快1點了! >_< 晚安!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,578評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,701評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,691評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,974評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,694評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,026評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,015評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,193評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,719評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,442評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,668評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,151評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,846評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,255評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,592評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,394評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,836評論 18 139
  • 轉至元數據結尾創建: 董瀟偉,最新修改于: 十二月 23, 2016 轉至元數據起始第一章:isa和Class一....
    40c0490e5268閱讀 1,757評論 0 9
  • Correctness AdapterViewChildren Summary: AdapterViews can...
    MarcusMa閱讀 8,898評論 0 6
  • ▼ 無窮無盡的愛 都在這里 當你找到暫時的方向 就感覺自己長大了一樣 記得我小學的時候每天都會比其他同學早到教室半...
    三井瘦Soso閱讀 509評論 0 0
  • 初次知曉這本是是看到朋友圈一朋友的推薦,看到封面,作者張嘉佳,微博最會寫故事的博主,睡前故事最佳選擇,...
    Kelly林霞閱讀 610評論 0 2