トレースを使用して、システム上のイベントとカウンタを記録し、それぞれをタイムライン上に可視化します。Android の標準トレースツールは Perfetto です。詳しくは、トレース入門ガイドをご覧ください。
コードをインストルメント化する
アプリからイベントを取得するには、コードにトレースポイントを追加して計測する必要があります。計測されていないセクションはトレースに表示されません。
SDV トレース サンプルは、トレース統合のデモです。手順とトレース構成の例が示されています。system/software_defined_vehicle/core_services/samples/tracing/ にあります。
Rust
Rust の推奨アプローチは、tracing クレートを使用して ATrace イベントを発行することです。Perfetto は ATrace をデータソースとしてサポートしています。Rust バインディングが利用可能になり、ユースケースの進化に応じて、Perfetto SDK に切り替える予定です。
トレースのデフォルトを Android.bp に追加します。
rust_binary {
...
defaults: [
...
"sdv_tracing@rust_defaults",
],
...
}
サブスクライバーを初期化します。これはプロセスごとに 1 回だけ行うことができます。
fn main() {
// Initialize the subscriber, panic if it fails.
// sdv_tracing::try_init_tracing() is the version that returns a Result.
sdv_tracing::init_tracing()
...
}
初期化呼び出しを省略できます。省略すると、トレースは初期化されず、Perfetto はアプリから計測イベントを収集しません。
トレースポイントを追加します。その他のサンプルについては、system/software_defined_vehicle/core_services/samples/tracing/rust_tracing_api_demo/tracing.rs をご覧ください。
use tracing::{instrument, info_span};
// #[tracing::instrument] wraps the method into a tracing span and records arguments.
// Use #[instrument(skip(num))] if you don't want to record the argument.
#[instrument]
fn mul_by_100(num: i32) -> i32 {
// Create and enter a span with INFO verbosity, name, and a debug field annotation.
// The span will exit when dropped.
let _span = info_span!("This is a span", var=123).entered();
let result = num * 100;
// Emit an instant INFO event that records the result value.
// We recommend to fully qualify the crate when using events to avoid confusion with log records.
tracing::info!(result, "Completed");
result
}
C++
C++ トレースでは、Perfetto SDK を使用してイベントを追跡します。Android.bp にトレースのデフォルトを追加します。
cc_binary {
...
defaults: [
...
"sdv_tracing@cc_defaults",
],
...
}
カテゴリを定義します。複数のモジュールでカテゴリを使用する場合は、共通ライブラリに移動します。例: system/software_defined_vehicle/core_services/samples/tracing/cpp_service/tracing_categories.h
ヘッダー内:
#include "perfetto/tracing/tracing.h"
#include "perfetto/tracing/track_event.h"
PERFETTO_DEFINE_CATEGORIES(
perfetto::Category("sample")
.SetTags("tag")
.SetDescription("Sample events"));
静的ストレージ マクロは、メソッドではなく .cpp ソースファイルに配置します。カテゴリをコンポーネント間で共有する場合は、カテゴリを含むヘッダーに対応するソースファイルを使用します。
PERFETTO_TRACK_EVENT_STATIC_STORAGE();
int main() {
...
}
Perfetto を初期化するには、システム バックエンドを初期化して、トラック イベントを登録します。
#include <sdv/tracing_init.h>
int main() {
...
android::sdv::InitPerfettoWithTrackEvents<perfetto::TrackEvent>();
...
}
計測手法を追加します。system/software_defined_vehicle/core_services/samples/tracing/cpp_service/client.cpp で他のサンプルをご覧ください。
int32_t mulBy100(int32_t num) {
// Start a slice that will get closed at the end of the scope.
TRACE_EVENT("client", "mulBy100", "num", num);
TRACE_EVENT("client", "This is a slice", "var", 123);
int32_t result = num * 100;
// Instant events have zero duration. They are drawn as markers on the track.
TRACE_EVENT_INSTANT("client", "Completed", "result", result);
return result;
}
Rust の例と同様に、このコードは 2 つのネストされたスライスと、UI 内のインスタント イベントのマーカーを生成します。イベントを選択すると、デバッグ引数の値が表示されます。
トレースを収集する
record\_android\_trace コマンドライン スクリプトを使用してトレースを記録し、Perfetto ウェブ UI を使用して表示します。
キャプチャを構成する
record_android_trace の構成を textproto 形式で指定する必要があります。詳細については、Perfetto のドキュメントをご覧ください。
SDV リポジトリには、サンプル構成(system/software_defined_vehicle/core_services/samples/tracing/config/trace_cfg.pbtx)が含まれています。このファイルには複数のデータソースが含まれており、カスタマイズすることも、そのまま使用することもできます。
Perfetto UI を使用して構成を生成する
カスタム構成を設定し、使用可能なオプションを確認するには、Perfetto UI の [新しいトレースを記録] に移動し、記録設定とプローブを調整します。[Recording command] ビューを開いて、生成されたコマンドを確認し、そこから構成内容を取得できます。
アプリ内インストルメンテーションの可視性を構成する
Rust の計測では ATrace が使用されます。これはドキュメントの ftrace_config セクションで構成されます。SDV コンポーネントには ATRACE_TAG_APP タグがあり、アプリごとに有効にできます。サンプル設定では、すべてのアプリが有効になります。
data_sources: {
config {
name: "linux.ftrace"
ftrace_config {
# Setting atrace_apps to "*" enable ATrace events for all apps.
# You can set it to a pattern to match specific processes by name.
# Use multiple atrace_apps entries to enable multiple processes.
atrace_apps: "*"
}
}
}
C++ Perfetto SDK でトラック イベントを使用します。これは track_event データソース(ドキュメント)です。
カテゴリとタグは track_event_config フィールドで有効または無効にできます。特別な slow タグと debug タグを除き、すべてのカテゴリ終了タグはデフォルトで有効になっています。特定のカテゴリのみを有効にする場合は、他のすべてのカテゴリを無効にする必要があります。たとえば、次のように disabled_categories: "*" を使用します。
data_sources: {
config {
name: "track_event"
track_event_config {
enabled_categories: "the_best_category_in_the_world"
disabled_categories: "*"
}
}
}トレースを記録する
Android リポジトリのルートでターミナルを開きます。envsetup を行う必要はありません。録音スクリプトは external/perfetto/tools/record_android_trace にあります。
サンプル構成でスクリプトを実行します。
external/perfetto/tools/record_android_trace --config system/software_defined_vehicle/core_services/samples/tracing/config/trace_cfg.pbtx
録画を途中で停止するには、Ctrl+C キーを押します。
これにより、adb shell perfetto がトリガーされ、トレースが記録されてから、通常は ~/traces でホストにトレースがプルされます。トレースが収集されると、ツールによってブラウザ ウィンドウが開かれ、トレースが表示されます。
便利な引数:
-s SERIAL: 指定されたシリアル番号のデバイスを使用します。例:-s 0.0.0.0:6520--no-open-browserはトレースを提供する URL を作成しますが、ブラウザは開きません。ポート転送(通常は 9001)が設定されているリモート セッションで役立ちます。-n, --no-openは、ブラウザを開いたり、トレース セッション後にトレースを提供する URL を作成したりしません。[トレース ファイルを開く] をクリックしてファイルを選択すれば、Perfetto UI でファイルを開くことはできます。-o <path>を使用して出力パスを設定します。
使用状況の詳細
このセクションでは、トレース システムを使用する際に役立つ詳細について説明します。
SDV コンポーネントのトレース計測
トレース計測機能を持つエージェントでは、特に指定がない限り、デバッグ可能なビルド(-eng、-userdebug)でトレースがデフォルトで利用可能です。トレースを収集すると、追加の構成なしでプロセスのイベントが表示されます。
通常、ライブラリはトレースを自動的に初期化しません。Rust では、ライブラリを使用するバイナリは、sdv_tracing::init_tracing() を使用してプロセスのトレースを初期化する必要があります。詳しくは、コードを計測するをご覧ください。
ミドルウェア
パブリッシュ/サブスクライブ ライブラリ: libsdv_middleware_dt
イベント:
- パブリッシャー: トピックのパブリッシュと登録。
- Subscriber: サブスクライブとポーリング。
有効化: バイナリで sdv_tracing::init_tracing() または sdv_tracing::try_init_tracing() を呼び出します。
gRPC ライブラリ: libsdvmiddleware_rpc_grpc_transport
イベント:
- RPC クライアント: 起動、サーバーへの接続、RPC メソッド呼び出し。
- RPC サーバー: 開始、サービス ディスカバリへの登録、RPC メソッドの追加と呼び出し。
有効化: バイナリで sdv_tracing::init_tracing() または sdv_tracing::try_init_tracing() を呼び出します。
SOME/IP
- プロセス:
sdv_someip_broker_agent。\ - イベント: メッセージ処理と変換、イベント サブスクリプション。
ライフサイクル マネージャー
- プロセス:
sdv_lifecycle_agent。\ - イベント: サービス オペレーション - 起動、停止、登録、登録解除。
車両の電源モード
- プロセス:
sdv_vpm_agent。\ - イベント: 電源状態の変更とサブスクリプション。
データ トンネル
トレース統合は、今後サポートする予定です。
トレースのパフォーマンス オーバーヘッド
オーバーヘッドの測定値には、パフォーマンスがシステムによって、特にエミュレータと実際のハードウェアで異なる可能性があるという通常の注意書きが付きます。
Rust
ベンチマークの元データは AOSP で入手可能です。データは Cuttlefish VM で収集されました。
- 単一スパン:
tracing::info_span!()、#[tracing::instrument]など:- トレースの初期化: 1 ナノ秒。
- トレースが初期化され、無効になっている(トレースの記録が行われていない)場合: 30 ns。
- トレースが有効: 3 µs。デバッグ フィールド アノテーションは、文字列化の複雑さによって 1 ~ 2 マイクロ秒を追加する可能性があります。
- 単一イベント:
tracing::info!()など:- トレースの初期化: 1 ナノ秒。
- トレースが初期化され、無効になっている場合: 30 ナノ秒。
- トレースが有効: 1.5 µs。デバッグ フィールド アノテーションは、
stringificationの複雑さによって 0.5 ~ 1 µs を追加する可能性があります。
C++
パフォーマンスの数値は、Perfetto の「イベントの追跡」ドキュメントのパフォーマンス セクションから取得しています。表の Google Pixel 3 の時間は、Cuttlefish VM での測定結果と一致しています。
単一スライス: TRACE_EVENT() など。トレース:
- 無効: 2ns。
- 有効: 300 ns。デバッグ フィールド アノテーションを使用すると、50 ~ 100 ナノ秒が追加される可能性があります。