שימוש במעקב כדי לקבל תובנות לגבי ביצועי המערכת

אפשר להשתמש במעקב כדי לתעד אירועים ומונים במערכת, ולהציג כל אחד מהם בתרשים ציר זמן. כלי המעקב הסטנדרטי ב-Android הוא Perfetto. מידע נוסף זמין במאמר הסבר על מעקב.

לבצע אינסטרומנטציה בקוד שלך

כדי לקבל אירועים מהאפליקציה, צריך להוסיף נקודות מעקב לקוד. קטעים שלא הוגדרו לא יופיעו במעקב.

הדוגמה למעקב אחר SDV היא הדגמה של שילוב מעקב, עם הוראות ודוגמה להגדרת מעקב. היא נמצאת בכתובת system/software_defined_vehicle/core_services/samples/tracing/.

חלודה

הגישה המומלצת ל-Rust היא להשתמש בתיבת tracing כדי להפיק אירועי ATrace. מערכת Perfetto תומכת ב-ATrace כמקור נתונים. אנחנו מתכננים לעבור ל-Perfetto SDK כשהקישורים ל-Rust יהיו זמינים, ובהתאם להתפתחות תרחישי השימוש.

מוסיפים את ברירות המחדל של המעקב אל Android.bp:

rust_binary {
...
    defaults: [
        ...
        "sdv_tracing@rust_defaults",
    ],
...
}

מפעילים את המינוי. אפשר לעשות זאת רק פעם אחת בכל תהליך:

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, הקוד הזה יוצר שני פלחים מקוננים וסמן [0x0A] לאירוע המיידי בממשק המשתמש. ערכי הארגומנטים של ניפוי הבאגים מוצגים כשבוחרים אירוע.

איסוף נתונים למעקב

משתמשים בסקריפט של שורת הפקודה record\_android\_trace כדי להקליט עקבות, ובממשק המשתמש האינטרנטי של Perfetto כדי לראות אותם.

הגדרת התיעוד

צריך לספק הגדרות ל-record_android_trace בפורמט textproto. מידע נוסף זמין במאמרי העזרה בנושא Perfetto.

מאגר ה-SDV מכיל הגדרת דוגמה (system/software_defined_vehicle/core_services/samples/tracing/config/trace_cfg.pbtx). הקובץ הזה כולל כמה מקורות נתונים, ואפשר להתאים אותו אישית או להשתמש בו כמו שהוא.

שימוש בממשק המשתמש של Perfetto כדי ליצור הגדרה

כדי להגדיר הגדרה בהתאמה אישית ולבדוק את האפשרויות הזמינות, עוברים אל Record new trace בממשק המשתמש של Perfetto, ומשנים את הגדרות ההקלטה והבדיקות. אחר כך תוכלו לפתוח את התצוגה 'פקודת הקלטה' כדי לראות את הפקודה שנוצרה ולקבל משם את תוכן ההגדרה.

הגדרת הרשאות הגישה למכשיר

הכלי Rust instrumentation משתמש ב-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 על ידי לחיצה על 'פתיחת קובץ מעקב' ובחירת הקובץ.

  • -o <path> כדי להגדיר את נתיב הפלט.

פרטי השימוש

בקטע הזה מפורטים פרטים שיכולים לעזור לכם להשתמש במערכת המעקב.

Trace instrumentation in SDV components

בסוכנים עם כלי מעקב, המעקב זמין כברירת מחדל בגרסאות שניתנות לניפוי באגים (-eng, -userdebug), אלא אם צוין אחרת. כשמבצעים מעקב, אמורים לראות את האירועים של התהליכים בלי צורך בהגדרה נוספת.

בדרך כלל, ספריות לא מאתחלות מעקב באופן אוטומטי. ב-Rust, הקובץ הבינארי שמשתמש בספרייה צריך לאתחל מעקב לתהליך באמצעות sdv_tracing::init_tracing(). מידע נוסף זמין במאמר הוספת כלי מעקב לקוד.

תווכה

ספרייה לפרסום/הרשמה: libsdv_middleware_dt

אירועים:

  • בעל תוכן דיגיטלי: פרסום ורישום של נושאים.
  • מנויים: הרשמה למינוי והשתתפות בסקרים.

הפעלה: שיחה 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. \
  • אירועים: עיבוד ותרגום של הודעות, הרשמה לאירועים.
Lifecycle manager
  • תהליך: sdv_lifecycle_agent. \
  • אירועים: פעולות בשירות – הפעלה, עצירה, רישום, ביטול רישום.
מצב ההפעלה של הרכב
  • תהליך: sdv_vpm_agent. \
  • אירועים: שינויים במצב ההפעלה ומינויים.
מנהרת נתונים

אנחנו מתכננים להוסיף תמיכה בשילוב של מעקב בעתיד.

תקורה של מעקב ביצועים

לגבי מדידות התקורה, חשוב לזכור שהביצועים עשויים להיות שונים במערכות שונות, ובמיוחד בין האמולטור לבין חומרה אמיתית.

חלודה

נתוני השוואה גולמיים זמינים ב-AOSP. הנתונים נאספו במכונה וירטואלית של Cuttlefish.

  • טווח יחיד: tracing::info_span!(), ‏ #[tracing::instrument] וערכים דומים:
    • מעקב אחר אתחול: 1ns.
    • המעקב אותחל והושבת (לא מתבצעת הקלטת מעקב): 30 ננו-שניות.
    • מעקב מופעל: 3 מיקרו-שניות. הערות שדה לניפוי באגים יכולות להוסיף 1-2 מיקרו-שניות, תלוי במורכבות של המרת המחרוזת.
  • אירוע יחיד: tracing::info!() ואירועים דומים:
    • מעקב אחר אתחול: 1ns.
    • המעקב מאותחל ומושבת: 30 ננו-שניות.
    • מעקב מופעל: 1.5 מיקרו-שניות. הערות שדה לניפוי באגים יכולות להוסיף 0.5-1 מיקרו-שניות, בהתאם stringification למורכבות.
C++‎

נתוני הביצועים מגיעים מהקטע 'ביצועים' במסמך Track events (מעקב אחרי אירועים) ב-Perfetto. הזמנים של Pixel 3 בטבלה תואמים לתצפיות שלנו במכונה הווירטואלית Cuttlefish.

פלח יחיד: TRACE_EVENT() ודומים. סקיצה:

  • מושבת: 2ns.
  • מופעל: 300 ננו-שניות. שימוש בהערות של שדות ניפוי באגים יכול להוסיף 50-100 ננו-שניות.