Use o rastreamento para ter insights sobre a performance do sistema

Use o rastreamento para registrar eventos e contadores no sistema e visualizar cada um em uma linha do tempo. A ferramenta de rastreamento padrão no Android é o Perfetto. Para saber mais, consulte Rastreamento 101.

Instrumentar o código

Para receber eventos do app, é necessário instrumentá-lo adicionando tracepoints ao código. As seções não instrumentadas não aparecem nos rastreamentos.

A amostra de rastreamento do SDV é uma demonstração da integração de rastreamento, com instruções e um exemplo de configuração de rastreamento. Ele está localizado em system/software_defined_vehicle/core_services/samples/tracing/.

Rust

A abordagem recomendada para Rust é usar a crate tracing para emitir eventos ATrace. O Perfetto é compatível com o ATrace como uma fonte de dados. Planejamos mudar para o SDK do Perfetto quando as vinculações do Rust estiverem disponíveis e dependendo da evolução dos casos de uso.

Adicione os padrões de rastreamento a Android.bp:

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

Inicialize o assinante. Isso só pode ser feito uma vez por processo:

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()
    ...
}

Você pode omitir a chamada de inicialização. Isso deixa o rastreamento não inicializado e o Perfetto não coleta eventos de instrumentação do app.

Adicione tracepoints. Encontre mais exemplos em 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++

O rastreamento em C++ usa o SDK do Perfetto para rastrear eventos. Adicione os padrões de rastreamento a Android.bp:

cc_binary {
...
    defaults: [
...
        "sdv_tracing@cc_defaults",
    ],
...
}

Defina as categorias. Se você usar as categorias em vários módulos, mova para uma biblioteca comum. Por exemplo, system/software_defined_vehicle/core_services/samples/tracing/cpp_service/tracing_categories.h.

No cabeçalho:

#include "perfetto/tracing/tracing.h"
#include "perfetto/tracing/track_event.h"

PERFETTO_DEFINE_CATEGORIES(
        perfetto::Category("sample")
                .SetTags("tag")
                .SetDescription("Sample events"));

Coloque a macro de armazenamento estático em um arquivo de origem .cpp, não em um método. Se você estiver compartilhando as categorias entre componentes, use o arquivo de origem que corresponde ao cabeçalho com categorias.

PERFETTO_TRACK_EVENT_STATIC_STORAGE();

int main() {
    ...
}

Para inicializar o Perfetto, inicialize o back-end do sistema e registre os eventos de rastreamento:


#include <sdv/tracing_init.h>

int main() {
  ...
  android::sdv::InitPerfettoWithTrackEvents<perfetto::TrackEvent>();
  ...
}

Adicione instrumentação. Veja mais exemplos em 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;
}

Assim como no exemplo em Rust, esse código produz duas fatias aninhadas e um marcador para o evento instantâneo na interface. Os valores do argumento de depuração são mostrados quando um evento é selecionado.

Coletar um trace

Use o script de linha de comando record\_android\_trace para gravar um rastreamento e a interface da Web do Perfetto para visualizá-lo.

Configurar a captura

Você precisa fornecer uma configuração para record_android_trace no formato textproto. Consulte a documentação do Perfetto para saber mais.

O repositório do SDV contém uma configuração de amostra (system/software_defined_vehicle/core_services/samples/tracing/config/trace_cfg.pbtx). Esse arquivo inclui várias fontes de dados e pode ser personalizado ou usado no estado em que se encontra.

Usar a interface do Perfetto para gerar uma configuração

Para configurar uma configuração personalizada e conferir as opções disponíveis, acesse Registrar novo rastreamento na interface do Perfetto, ajustando as configurações de gravação e as sondagens. Em seguida, abra a visualização "Comando de gravação" para conferir o comando gerado e acessar o conteúdo da configuração.

Configurar a visibilidade da instrumentação no app

A instrumentação do Rust usa o ATrace. Ela é configurada na seção ftrace_config do documento. Os componentes do SDV têm a tag ATRACE_TAG_APP e podem ser ativados por app. A configuração de exemplo ativa todos os apps.

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: "*"
        }
    }
}

Usamos eventos de rastreamento no SDK do Perfetto em C++. Esta é uma fonte de dados track_event (documento).

É possível ativar ou desativar categorias e tags no campo track_event_config. Todas as tags finais de categoria são ativadas por padrão, exceto as tags especiais slow e debug. Se você quiser ativar apenas categorias específicas, desative todas as outras. Por exemplo, com disabled_categories: "*", como aqui:

data_sources: {
    config {
        name: "track_event"
        track_event_config {
            enabled_categories: "the_best_category_in_the_world"
            disabled_categories: "*"
        }
    }
}

Gravar um rastro

Abra um terminal na raiz do repositório Android. Não é necessário fazer envsetup. O script de gravação está em external/perfetto/tools/record_android_trace.

Execute o script com a configuração de exemplo:

external/perfetto/tools/record_android_trace --config system/software_defined_vehicle/core_services/samples/tracing/config/trace_cfg.pbtx

Para interromper a gravação antes, selecione Ctrl + C.

Isso aciona adb shell perfetto para gravar um rastreamento e extrair o rastreamento para o host, geralmente em ~/traces. Quando o trace é coletado, a ferramenta abre uma janela do navegador para mostrar o trace.

Argumentos úteis:

  • -s SERIAL para usar o dispositivo com um determinado número de série. Por exemplo, -s 0.0.0.0:6520

  • --no-open-browser cria um URL para veicular o rastreamento, mas não abre o navegador. É útil para sessões remotas quando você tem o encaminhamento de portas configurado (geralmente 9001).

  • O -n, --no-open não vai abrir o navegador nem criar o URL para veicular o rastreamento depois da sessão de rastreamento. Você ainda pode abrir arquivos na interface do Perfetto clicando em "Abrir arquivo de rastreamento" e selecionando o arquivo.

  • -o <path> para definir o caminho de saída.

Detalhes de uso

Esta seção fornece detalhes que podem ser úteis ao usar o sistema de rastreamento.

Instrumentação de rastreamento em componentes do SDV

Em agentes com instrumentação de rastreamento, o rastreamento está disponível por padrão em builds depuráveis (-eng, -userdebug), a menos que especificado de outra forma. Ao coletar um rastreamento, você vai ver os eventos dos processos sem configuração extra.

Normalmente, as bibliotecas não inicializam o rastreamento automaticamente. Em Rust, o binário que usa a biblioteca precisa inicializar o rastreamento do processo usando sdv_tracing::init_tracing(). Consulte Instrumentar seu código para saber mais.

Middleware

Biblioteca de publicação/assinatura: libsdv_middleware_dt

Eventos:

  • Publisher: publicação e registro de tópicos.
  • Inscrito: inscrição e sondagem.

Ativação: chame sdv_tracing::init_tracing() ou sdv_tracing::try_init_tracing() no binário.

Biblioteca gRPC: libsdvmiddleware_rpc_grpc_transport

Eventos:

  • Cliente RPC: inicialização, conexão com o servidor e chamadas de método RPC.
  • Servidor RPC: iniciando, registrando com a descoberta de serviços, adicionando e chamando métodos RPC.

Ativação: chame sdv_tracing::init_tracing() ou sdv_tracing::try_init_tracing() em binário.

SOME/IP
  • Processo: sdv_someip_broker_agent. \
  • Eventos: processamento e tradução de mensagens, inscrição em eventos.
Gerenciador do ciclo de vida
  • Processo: sdv_lifecycle_agent. \
  • Eventos: operações de serviço (início, interrupção, registro e cancelamento de registro).
Modo de energia do veículo
  • Processo: sdv_vpm_agent. \
  • Eventos: mudanças no estado de energia e assinaturas.
Data Tunnel

Planejamos oferecer suporte à integração de rastreamento no futuro.

Sobrecarga de desempenho do rastreamento

As medições de sobrecarga vêm com a ressalva usual de que o desempenho pode variar entre diferentes sistemas e, principalmente, entre o emulador e o hardware real.

Rust

Os dados brutos de comparativo de mercado estão disponíveis no AOSP. Os dados foram coletados em uma VM do Cuttlefish.

  • Intervalo único: tracing::info_span!(), #[tracing::instrument] e semelhantes:
    • Rastreamento não inicializado: 1 ns.
    • Rastreamento inicializado e desativado (nenhuma gravação de rastreamento em andamento): 30 ns.
    • Rastreamento ativado: 3 µs. Anotações de campo de depuração podem adicionar de 1 a 2 µs, dependendo da complexidade da conversão em string.
  • Evento único: tracing::info!() e semelhantes:
    • Rastreamento não inicializado: 1 ns.
    • Rastreamento inicializado e desativado: 30 ns.
    • Rastreamento ativado: 1,5 µs. As anotações de campo de depuração podem adicionar de 0,5 a 1 µs, dependendo da complexidade de stringification.
C++

Os números de performance são da seção "Performance" do documento "Rastrear eventos" no Perfetto. Os tempos do Pixel 3 na tabela são consistentes com nossas observações na VM do Cuttlefish.

Única fração: TRACE_EVENT() e semelhantes. Rastreamento:

  • Desativado: 2ns.
  • Ativado: 300 ns. O uso de anotações de campo de depuração pode adicionar de 50 a 100 ns.