" />

欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JankMan-極致的卡頓分析系統(tǒng)

 更新時(shí)間:2023年05月06日 08:31:08   作者:Dx  
這篇文章主要為大家介紹了JankMan-極致的卡頓分析系統(tǒng)使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

1.卡頓分析系統(tǒng)介紹

  • 此系統(tǒng)擁有了端上采集兩個(gè)維度數(shù)據(jù)的能力

    • 方法運(yùn)行數(shù)據(jù):系統(tǒng)在編譯期間基于ASM9+AGP7+自定義方法ID映射+自定義字節(jié)碼指令集實(shí)現(xiàn)了方法運(yùn)行數(shù)據(jù)的采集。
    • 幀性能數(shù)據(jù):系統(tǒng)在運(yùn)行期間基于FrameMatrix+自定義數(shù)據(jù)結(jié)構(gòu)體實(shí)現(xiàn)了端上幀數(shù)據(jù)的采集。

當(dāng)APP發(fā)生運(yùn)行卡頓時(shí),系統(tǒng)可自動(dòng)分析堆棧,并且關(guān)聯(lián)卡頓幀的方法調(diào)用鏈,并作出記錄最終導(dǎo)出至文件。整體基于協(xié)程制作,性能損耗僅需1%。

基于Compose KMP獨(dú)創(chuàng)了多端可用的線(xiàn)下還原器,將采集到的數(shù)據(jù)做格式效驗(yàn),并作出二次還原解析,進(jìn)行了perfetto的二次開(kāi)發(fā),實(shí)現(xiàn)了可視化展示整體信息的能力。

2.思路介紹

2.1方法運(yùn)行數(shù)據(jù)采集

2.1.1方法ID映射

由于系統(tǒng)會(huì)在運(yùn)行期間會(huì)采集大量數(shù)據(jù),所以需要將龐大的方法名映射為指定ID的能力,如下

//方法ID`方法具體全路徑和行參
24`com.d.hookplus.HookApplication$onCreate$1.onActivitySaveInstanceState[android.app.Activity,android.os.Bundle,]

此處的方法名包含了全路徑和行參,如果通過(guò)字符串記錄是十分龐大的,所以在編譯期間使用ASM技術(shù)將其對(duì)應(yīng)成ID,降低空間復(fù)雜度

2.2.2函數(shù)記錄能力

在ASM輪訓(xùn)期間,在方法開(kāi)始和結(jié)束位置各插入對(duì)應(yīng)的指令用于實(shí)現(xiàn)標(biāo)記功能

override fun onMethodEnter() {
    //方法進(jìn)入
    methodVisitor?.perfettoVisitMethodDelegate(PerfettoCentre.const.METHOD_ENTER, methodId)
    super.onMethodEnter()
}
?
override fun onMethodExit(opcode: Int) {
    //方法退出
    methodVisitor?.perfettoVisitMethodDelegate(PerfettoCentre.const.METHOD_EXIT, methodId)
    super.onMethodExit(opcode)
}

處理退出指令時(shí),catch和return指令也有對(duì)應(yīng)的記錄

在對(duì)應(yīng)的時(shí)機(jī)插入對(duì)應(yīng)的代碼

this.let { methodVisitor ->
        methodVisitor.visitFieldInsn(
            GETSTATIC,
            "com/d/hookcore/perfetto/PerfettoCore",
            "Companion",
            "Lcom/d/hookcore/perfetto/PerfettoCore$Companion;"
        )
        methodVisitor.visitIntInsn(BIPUSH, enterOrExit)
        methodVisitor.visitIntInsn(SIPUSH, methodId)
        methodVisitor.visitMethodInsn(
            INVOKEVIRTUAL,
            "com/d/hookcore/perfetto/PerfettoCore$Companion",
            "getTraceLine",
            "(II)V",
            false
        )
    }
例:
private fun initRecycler() {
    //方法開(kāi)始,第一個(gè)參數(shù)用于標(biāo)記進(jìn)入或者退出,第二個(gè)參數(shù)用于標(biāo)記映射的方法ID
    PerfettoCore.getTraceLine(0,12)
    var recyclerView: RecyclerView = findViewById(R.id.rec)
    recyclerView.adapter = NodeAdapter(messageList)
    PerfettoCore.getTraceLine(1,12)
}
  • 插入完代碼的例子如下:

2.2.3.運(yùn)行方法記錄內(nèi)容

方法記錄后的結(jié)果如下

如:main-1,942155.120954153,1,39,1

說(shuō)明
當(dāng)前線(xiàn)程Main
當(dāng)前線(xiàn)程ID1
當(dāng)前時(shí)間秒值942155.120954153
當(dāng)前方法標(biāo)記(進(jìn)入或退出)1
當(dāng)前方法ID39
當(dāng)前幀位下標(biāo)1

2.2幀數(shù)據(jù)采集

2.2.1于傳統(tǒng)方式的區(qū)別

區(qū)別于Choreographer Hook的方式,系統(tǒng)采用了FrameMatrix實(shí)現(xiàn)了幀數(shù)據(jù)采集

Choreographer的Hook點(diǎn)是在Looper.loop之中的Printer.println下,

final Printer logging = me.mLogging;
if (logging != null) {
 //Hook點(diǎn)
 logging.println(">>>>> Dispatching to " + msg.target + " " +msg.callback + ": " + msg.what);
}

缺點(diǎn)如下:

每次都需要字符串匹配,性能損耗嚴(yán)重

在API31之中被封掉了

2.2.2FrameMatrix的能力

FrameMatrix通過(guò)addOnFrameMetricsAvailableListener實(shí)現(xiàn)了幀數(shù)據(jù)獲取的能力

window.addOnFrameMetricsAvailableListener({ window, frameMetrics, dropCountSinceLastInvocation ->
//do something
}, frameMetricsHandler)

如果不對(duì)window進(jìn)行addOnFrameMetricsAvailableListener,數(shù)據(jù)也會(huì)保留在平臺(tái)層,所以沒(méi)有性能損耗

FrameMatrix是Android平臺(tái)層提供的幀數(shù)據(jù)采集,包含如下信息

類(lèi)別參數(shù)說(shuō)明
獲取每幀性能數(shù)據(jù)FIRST_DRAW_FRAME表示當(dāng)前幀是否是當(dāng)前 Window 布局中繪制的第一幀
INTENDED_VSYNC_TIMESTAMP當(dāng)前幀的預(yù)期開(kāi)始時(shí)間, 如果此值與 VSYNC_TIMESTAMP 不同,則表示 UI 線(xiàn)程上發(fā)生了阻塞,阻止了 UI 線(xiàn)程及時(shí)響應(yīng)vsync信號(hào)
TOTAL_DURATION表示此幀渲染并發(fā)布給顯示子系統(tǒng)所花費(fèi)的總時(shí)間, 等于所有其他具有時(shí)間價(jià)值的指標(biāo)的值之和
VSYNC_TIMESTAMP在所有 vsync 監(jiān)聽(tīng)器和幀繪制中使用的時(shí)間值(Choreographer 的幀回調(diào), 動(dòng)畫(huà), View#getDrawingTime等)
cpuDurationCOMMAND_ISSUE_DURATION表示向 GPU 發(fā)出繪制命令的耗時(shí)
SWAP_BUFFERS_DURATION表示將此幀的幀緩沖區(qū)發(fā)送給顯示子系統(tǒng)所花的時(shí)間
uiDurationUNKNOWN_DELAY_DURATION表示等待 UI 線(xiàn)程響應(yīng)并處理幀所經(jīng)過(guò)的時(shí)間, 大多數(shù)情況下應(yīng)為0
INPUT_HANDLING_DURATION表示處理輸入事件回調(diào)的耗時(shí)
ANIMATION_DURATION表示執(zhí)行動(dòng)畫(huà)回調(diào)的耗時(shí)
LAYOUT_MEASURE_DURATION表示對(duì) View 樹(shù)進(jìn)行 measure 和 layout 所花的時(shí)間
DRAW_DURATION表示將 View 樹(shù)轉(zhuǎn)換為 DisplayList 的耗時(shí)
SYNC_DURATION表示將 DisplayList 與渲染線(xiàn)程同步所花的時(shí)間

2.3.同步算法

同步算法是將方法運(yùn)行數(shù)據(jù)和幀性能數(shù)據(jù)自動(dòng)分析,裁剪,合并出問(wèn)題堆棧,并保存到指定位置的過(guò)程

在開(kāi)發(fā)者自定義連續(xù)卡頓多少幀后進(jìn)行Dump

如果每卡頓一幀就Dump,信息量太密集,并且意義不大,建議開(kāi)發(fā)者連續(xù)卡頓5幀起步

2.3.1.同步算法細(xì)節(jié)

整個(gè)同步的過(guò)程是在單獨(dú)的一個(gè)HandlerThread中進(jìn)行的,所以面臨了兩個(gè)難題:

由于HandlerThread接受幀數(shù)據(jù)的時(shí)機(jī)是不確定的,即可能方法數(shù)據(jù)已經(jīng)收集到很多幀以后了,但是幀數(shù)據(jù)才剛剛到來(lái)。如何精準(zhǔn)定位到卡頓范圍內(nèi)的全部函數(shù)

如何盡可能減小性能損耗,降低時(shí)間復(fù)雜度和空間復(fù)雜度

所以我們整個(gè)同步的過(guò)程是圍繞著這兩個(gè)問(wèn)題進(jìn)行設(shè)計(jì)的

2.3.2.算法合并過(guò)程

如果卡頓幀連續(xù)個(gè)數(shù)到達(dá)了開(kāi)發(fā)者定義的個(gè)數(shù),那么開(kāi)始還原

將首個(gè)卡頓幀的開(kāi)始時(shí)間和連續(xù)卡頓幀后的第一個(gè)不卡頓幀的開(kāi)始時(shí)間作為時(shí)間范圍,與函數(shù)運(yùn)行數(shù)據(jù)的時(shí)間點(diǎn)進(jìn)行校準(zhǔn)。匹配到函數(shù)運(yùn)行的范圍區(qū)域,并通過(guò)兩個(gè)指針進(jìn)行標(biāo)記

具體匹配的過(guò)程是通過(guò)魔改版的二分查找實(shí)現(xiàn)

將標(biāo)記出的函數(shù)運(yùn)行范圍進(jìn)行導(dǎo)出

導(dǎo)出的能力是基于NIO實(shí)現(xiàn)的

導(dǎo)出完畢后將函數(shù)指針位移到開(kāi)始位置,重復(fù)利用空間

上述過(guò)程均在子線(xiàn)程進(jìn)行,對(duì)主線(xiàn)程無(wú)影響,現(xiàn)階段損耗為3%左右

2.4.可視化展示

  • 將Dump出的數(shù)據(jù)進(jìn)行二次改造,支持可視化展示

2.4.1.線(xiàn)下還原器

  • 基于perfetto的構(gòu)造格式進(jìn)行二次改造,用于支持可視化展示

2.4.2.支持多端的線(xiàn)下還原器

基于Compose KMP實(shí)現(xiàn)了多端的可視化還原器,效果如下:

參數(shù)說(shuō)明如下:

  • MappingFile:函數(shù)ID映射文件
  • SourceFile:后綴為.zy_trace的文件,是系統(tǒng)自動(dòng)采集的格式
  • OutputPath:輸出為perfetto識(shí)別格式的文件目錄

還原格式細(xì)節(jié)

如下:

com.d.hookplus|11116
main-1,942155.105176549,0,29,0
main-1,942155.105229674,1,29,0
main-1,942155.105313008,0,29,0
main-1,942155.105322383,1,29,0
main-1,942155.105492174,0,29,0
main-1,942155.105503112,1,29,0
main-1,942155.105524466,0,30,0
.......
# tracer: nop
#
# entries-in-buffer/entries-written: 30624/30624   #P:4
#
#                                  _-----=> irqs-off
#                                 / _----=> need-resched
#                                | / _---=> hardirq/softirq
#                                || / _--=> preempt-depth
#                                ||| /     delay
#       TASK-PID    TGID   CPU#  ||||    TIMESTAMP  FUNCTION
#          | |        |      |   ||||       |         |
com.d.hookplus-main-1 [000]... 942155.105177: tracing_mark_write: B|11116|0com.d.hookplus.NodeAdapter.getItemCount.[]
com.d.hookplus-main-1 [000]... 942155.105230: tracing_mark_write: E|11116|0com.d.hookplus.NodeAdapter.getItemCount.[]
com.d.hookplus-main-1 [000]... 942155.105313: tracing_mark_write: B|11116|0com.d.hookplus.NodeAdapter.getItemCount.[]
com.d.hookplus-main-1 [000]... 942155.105322: tracing_mark_write: E|11116|0com.d.hookplus.NodeAdapter.getItemCount.[]
com.d.hookplus-main-1 [000]... 942155.105492: tracing_mark_write: B|11116|0com.d.hookplus.NodeAdapter.getItemCount.[]
com.d.hookplus-main-1 [000]... 942155.105503: tracing_mark_write: E|11116|0com.d.hookplus.NodeAdapter.getItemCount.[]
com.d.hookplus-main-1 [000]... 942155.105524: tracing_mark_write: 
.....
  • 改造前:
  • 改造后:

2.4.3.可視化展示

  • 最終將還原器輸出的文件直接導(dǎo)入至perfetto系統(tǒng)中,效果如下

以上就是JankMan-極致的卡頓分析系統(tǒng)的詳細(xì)內(nèi)容,更多關(guān)于JankMan卡頓分析系統(tǒng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論