/* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // This example demonstrates in-process tracing with Perfetto. // This program adds trace in a few example functions like DrawPlayer DrawGame // etc. and collect the trace in file `example.pftrace`. // // This file was copied from 'examples/sdk/example.cc' and migrated // to use the 'libperfetto_c' API. #include "src/java_sdk/main/cpp/example.h" #include "src/java_sdk/main/cpp/utils.h" #include "perfetto/public/producer.h" #include "perfetto/public/te_category_macros.h" #include "perfetto/public/te_macros.h" #include "perfetto/public/track_event.h" #include #include #include #include namespace { #define EXAMPLE_CATEGORIES(C) \ C(rendering, "rendering", "Rendering and graphics events") \ C(network, "network.debug", "Verbose network events", "debug") \ C(audio, "audio.latency", "Detailed audio latency metrics", "verbose") PERFETTO_TE_CATEGORIES_DEFINE(EXAMPLE_CATEGORIES) void InitializePerfetto() { PerfettoProducerInitArgs args = PERFETTO_PRODUCER_INIT_ARGS_INIT(); args.backends = PERFETTO_BACKEND_IN_PROCESS; PerfettoProducerInit(args); PerfettoTeInit(); PERFETTO_TE_REGISTER_CATEGORIES(EXAMPLE_CATEGORIES); } std::unique_ptr StartTracing() { using perfetto::java_sdk::utils::TracingSession; TracingSession tracing_session = TracingSession::Builder() .set_data_source_name("track_event") .add_enabled_category("*") .Build(); return std::make_unique(std::move(tracing_session)); } void StopTracing( std::unique_ptr tracing_session, const std::string& output_file_path) { // Stop tracing and read the trace data. tracing_session->StopBlocking(); std::vector trace_data(tracing_session->ReadBlocking()); // Write the result into a file. // Note: To save memory with longer traces, you can tell Perfetto to write // directly into a file by passing a file descriptor into Setup() above. std::ofstream output; output.open(output_file_path, std::ios::out | std::ios::binary); output.write(reinterpret_cast(&trace_data[0]), static_cast(trace_data.size())); output.close(); printf( "Trace written in %s file. To read this trace in " "text form, run `./tools/traceconv text example.pftrace`\n", output_file_path.c_str()); } void DrawPlayer(int player_number) { PERFETTO_TE_SCOPED(rendering, PERFETTO_TE_SLICE("DrawPlayer"), PERFETTO_TE_ARG_INT64("player_number", player_number)); // Sleep to simulate a long computation. std::this_thread::sleep_for(std::chrono::milliseconds(500)); } void DrawGame() { // This is an example of an unscoped slice, which begins and ends at specific // points (instead of at the end of the current block scope). PERFETTO_TE(rendering, PERFETTO_TE_SLICE_BEGIN("DrawGame")); DrawPlayer(1); DrawPlayer(2); PERFETTO_TE(rendering, PERFETTO_TE_SLICE_END()); // Record the rendering framerate as a counter sample. PERFETTO_TE( rendering, PERFETTO_TE_COUNTER(), PERFETTO_TE_COUNTER_TRACK("Framerate", PerfettoTeProcessTrackUuid()), PERFETTO_TE_INT_COUNTER(120)); } } // namespace int run_main(const std::string& output_file_path) { InitializePerfetto(); auto tracing_session = StartTracing(); // Simulate some work that emits trace events. DrawGame(); StopTracing(std::move(tracing_session), output_file_path); return 0; }