1 /*
2 * Copyright (C) 2025 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 // This example demonstrates in-process tracing with Perfetto.
18 // This program adds trace in a few example functions like DrawPlayer DrawGame
19 // etc. and collect the trace in file `example.pftrace`.
20 //
21 // This file was copied from 'examples/sdk/example.cc' and migrated
22 // to use the 'libperfetto_c' API.
23
24 #include "src/java_sdk/main/cpp/example.h"
25
26 #include "src/java_sdk/main/cpp/utils.h"
27
28 #include "perfetto/public/producer.h"
29 #include "perfetto/public/te_category_macros.h"
30 #include "perfetto/public/te_macros.h"
31 #include "perfetto/public/track_event.h"
32
33 #include <chrono>
34 #include <fstream>
35 #include <string>
36 #include <thread>
37
38 namespace {
39 #define EXAMPLE_CATEGORIES(C) \
40 C(rendering, "rendering", "Rendering and graphics events") \
41 C(network, "network.debug", "Verbose network events", "debug") \
42 C(audio, "audio.latency", "Detailed audio latency metrics", "verbose")
43
PERFETTO_TE_CATEGORIES_DEFINE(EXAMPLE_CATEGORIES)44 PERFETTO_TE_CATEGORIES_DEFINE(EXAMPLE_CATEGORIES)
45
46 void InitializePerfetto() {
47 PerfettoProducerInitArgs args = PERFETTO_PRODUCER_INIT_ARGS_INIT();
48 args.backends = PERFETTO_BACKEND_IN_PROCESS;
49 PerfettoProducerInit(args);
50 PerfettoTeInit();
51 PERFETTO_TE_REGISTER_CATEGORIES(EXAMPLE_CATEGORIES);
52 }
53
StartTracing()54 std::unique_ptr<perfetto::java_sdk::utils::TracingSession> StartTracing() {
55 using perfetto::java_sdk::utils::TracingSession;
56 TracingSession tracing_session = TracingSession::Builder()
57 .set_data_source_name("track_event")
58 .add_enabled_category("*")
59 .Build();
60 return std::make_unique<TracingSession>(std::move(tracing_session));
61 }
62
StopTracing(std::unique_ptr<perfetto::java_sdk::utils::TracingSession> tracing_session,const std::string & output_file_path)63 void StopTracing(
64 std::unique_ptr<perfetto::java_sdk::utils::TracingSession> tracing_session,
65 const std::string& output_file_path) {
66 // Stop tracing and read the trace data.
67 tracing_session->StopBlocking();
68 std::vector<uint8_t> trace_data(tracing_session->ReadBlocking());
69
70 // Write the result into a file.
71 // Note: To save memory with longer traces, you can tell Perfetto to write
72 // directly into a file by passing a file descriptor into Setup() above.
73 std::ofstream output;
74 output.open(output_file_path, std::ios::out | std::ios::binary);
75 output.write(reinterpret_cast<const std::ostream::char_type*>(&trace_data[0]),
76 static_cast<std::streamsize>(trace_data.size()));
77 output.close();
78 printf(
79 "Trace written in %s file. To read this trace in "
80 "text form, run `./tools/traceconv text example.pftrace`\n",
81 output_file_path.c_str());
82 }
83
DrawPlayer(int player_number)84 void DrawPlayer(int player_number) {
85 PERFETTO_TE_SCOPED(rendering, PERFETTO_TE_SLICE("DrawPlayer"),
86 PERFETTO_TE_ARG_INT64("player_number", player_number));
87 // Sleep to simulate a long computation.
88 std::this_thread::sleep_for(std::chrono::milliseconds(500));
89 }
90
DrawGame()91 void DrawGame() {
92 // This is an example of an unscoped slice, which begins and ends at specific
93 // points (instead of at the end of the current block scope).
94 PERFETTO_TE(rendering, PERFETTO_TE_SLICE_BEGIN("DrawGame"));
95 DrawPlayer(1);
96 DrawPlayer(2);
97 PERFETTO_TE(rendering, PERFETTO_TE_SLICE_END());
98
99 // Record the rendering framerate as a counter sample.
100 PERFETTO_TE(
101 rendering, PERFETTO_TE_COUNTER(),
102 PERFETTO_TE_COUNTER_TRACK("Framerate", PerfettoTeProcessTrackUuid()),
103 PERFETTO_TE_INT_COUNTER(120));
104 }
105 } // namespace
106
run_main(const std::string & output_file_path)107 int run_main(const std::string& output_file_path) {
108 InitializePerfetto();
109 auto tracing_session = StartTracing();
110
111 // Simulate some work that emits trace events.
112 DrawGame();
113
114 StopTracing(std::move(tracing_session), output_file_path);
115 return 0;
116 }
117