blob: a10f8c448c3c8d6c4c75c1608dc052a117f01b14 [file] [log] [blame]
/*
* 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 <chrono>
#include <fstream>
#include <string>
#include <thread>
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<perfetto::java_sdk::utils::TracingSession> 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<TracingSession>(std::move(tracing_session));
}
void StopTracing(
std::unique_ptr<perfetto::java_sdk::utils::TracingSession> tracing_session,
const std::string& output_file_path) {
// Stop tracing and read the trace data.
tracing_session->StopBlocking();
std::vector<uint8_t> 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<const std::ostream::char_type*>(&trace_data[0]),
static_cast<std::streamsize>(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;
}