1. Trace
chromium 在 base 庫中提供了 base::trace_event::TraceLog
類,該類是 TRACE_EVENT*
, TRACE_COUNTER*
等宏的底層實現,關於這些宏定義見 base/trace_event/common/trace_event_common.h
。
使用 TraceLog 的流程:
base::trace_event::TraceLog::GetInstance()->SetEnabled(...)
;TRACE_EVENT*
等宏記錄 Trace: TRACE_EVENT0("test", "main")
;base::trace_event::TraceLog::GetInstance()->Flush(...)
;當使用 TRACE_EVENT(...)
來記錄 Trace 時,預設情況下 Trace 資料會記錄到 TraceLog::logged_events_ 中,流程如下:
TraceLog 只支援將 Trace 輸出到 console 或者返回給到程式中,不支援寫檔案或者多程序,但是它提供了 hook 介面 base::trace_event::TraceLog::SetAddTraceEventOverrides()
, 允許外部 hook trace 的流程,從而實現自己的處理。在 chromium 中就使用了這種方式來支援多程序的 Trace。 如果有註冊 trace hook,則在 TraceLog::AddTraceEventWithThreadIdAndTimestamp
中會將資料發給之前註冊的 hook。
當用戶呼叫 Flush 的時候會將 TraceLog::logged_events_
中的資料轉換為 json, 處理流程如下:
直接使用 TraceLog 的 demo 見 demo_tracing_console.cc
2. TracingService/Perfetto
chromium 使用 TraceLog 的 hook 機制擴充套件了 TraceLog, 如果程式啟動時新增了 --trace-startup=...
引數或者通過 chrome://tracing
來啟動 trace,則會向 TraceLog 註冊 3 個 TraceLog 的回撥, TraceEventDataSource::OnAddTraceEvent, TraceEventDataSource::FlushCurrentThread, TraceEventDataSource::OnUpdateDuration,流程如下:
註冊 hook 後,所有新的 Trace 都會被傳送給 hook 函數,也就是 tracing::TraceEventDataSource
類,這個類由 //services/tracing
服務提供,用來將 TraceLog 對接到 Perfetto
。 Perfetto 是一個跨平臺的 tracing 元件,包括一個可嵌入到其他程式中的 tracing 庫以及用來視覺化展示 trace 的工具 (https://ui.perfetto.dev/和<chrome://tracing>)。 關於 Perfetto 的詳細資訊見 https://perfetto.dev/.
在 chromium 中,Perfetto 被包裝進 TracingService,以便支援多程序的 Trace 追蹤,TracingService 的程式碼在 //services/tracing
目錄中。 直接使用 TracingService 的 demo 見 demo_tracing_perfetto.cc
。
下面的類圖反應了 TracingService 是如何支援多程序的:
本來 Perfetto 也是支援多程序的,但是是使用自己定義的 IPC 通訊,chromium 使用 mojo 替換掉了原本的 IPC 機制,以便讓它更貼近 chromium, 並且可以支援 chromium 的沙箱機制。
3. Trace Viewer
獲取到的 Trace 資料可以使用 TraceViewer 進行視覺化,在 chromium 中使用 --trace-startup=...
或者 chrome://tracing
來獲得 Trace 檔案後可以使用 chrome://tracing
或者 https://ui.perfetto.dev/ 來檢視。 這兩個 Trace Viewer 不僅支援 json 格式的 Trace 檔案也支援 Android systrace 和 ftrace 格式。
如果你想使用 TraceViewer 但是又不想引入 Perfetto 的庫,可以自己將資料生成為 chrome json trace event 格式,在 base 庫中以及 swiftshader 中都採用了這種方式,因為這種 trace 資料格式並不複雜,例如以下格式就是合法的 Trace 格式:
TraceViewer 的一個例子:
4. TracingService 的執行流程追蹤
啟動 TracingService 的時候會同時啟動 TraceLog,如下:
首次收到 Trace,初始化 TraceWriter 用於記錄 Trace:
將 Trace 儲存到 TraceWriter:
結束 TracingSerivce 的時候會將 Trace 的結果轉換為 Json 格式:
5. 參考資料