1 /*
2 * Copyright (C) 2020 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 // This output file is not readable directly. It can be read after converting
21 // it to text, by running the command:
22 // `./tools/traceconv text example.pftrace`
23 // or it can be opened in UI : https://ui.perfetto.dev
24 //
25 // To compile this file, run: `./tools/ninja -C out/default sdk_example`.
26
27 #include "trace_categories.h"
28
29 #include <chrono>
30 #include <fstream>
31 #include <thread>
32
33 namespace {
34
InitializePerfetto()35 void InitializePerfetto() {
36 perfetto::TracingInitArgs args;
37 // The backends determine where trace events are recorded. For this example we
38 // are going to use the in-process tracing service, which only includes in-app
39 // events.
40 args.backends = perfetto::kInProcessBackend;
41
42 perfetto::Tracing::Initialize(args);
43 perfetto::TrackEvent::Register();
44 }
45
StartTracing()46 std::unique_ptr<perfetto::TracingSession> StartTracing() {
47 // The trace config defines which types of data sources are enabled for
48 // recording. In this example we just need the "track_event" data source,
49 // which corresponds to the TRACE_EVENT trace points.
50 perfetto::TraceConfig cfg;
51 cfg.add_buffers()->set_size_kb(1024);
52 auto* ds_cfg = cfg.add_data_sources()->mutable_config();
53 ds_cfg->set_name("track_event");
54
55 auto tracing_session = perfetto::Tracing::NewTrace();
56 tracing_session->Setup(cfg);
57 tracing_session->StartBlocking();
58 return tracing_session;
59 }
60
StopTracing(std::unique_ptr<perfetto::TracingSession> tracing_session)61 void StopTracing(std::unique_ptr<perfetto::TracingSession> tracing_session) {
62 // Make sure the last event is closed for this example.
63 perfetto::TrackEvent::Flush();
64
65 // Stop tracing and read the trace data.
66 tracing_session->StopBlocking();
67 std::vector<char> trace_data(tracing_session->ReadTraceBlocking());
68
69 // Write the result into a file.
70 // Note: To save memory with longer traces, you can tell Perfetto to write
71 // directly into a file by passing a file descriptor into Setup() above.
72 std::ofstream output;
73 output.open("example.pftrace", std::ios::out | std::ios::binary);
74 output.write(&trace_data[0], std::streamsize(trace_data.size()));
75 output.close();
76 PERFETTO_LOG(
77 "Trace written in example.pftrace file. To read this trace in "
78 "text form, run `./tools/traceconv text example.pftrace`");
79 }
80
DrawPlayer(int player_number)81 void DrawPlayer(int player_number) {
82 TRACE_EVENT("rendering", "DrawPlayer", "player_number", player_number);
83 // Sleep to simulate a long computation.
84 std::this_thread::sleep_for(std::chrono::milliseconds(500));
85 }
86
DrawGame()87 void DrawGame() {
88 // This is an example of an unscoped slice, which begins and ends at specific
89 // points (instead of at the end of the current block scope).
90 TRACE_EVENT_BEGIN("rendering", "DrawGame");
91 DrawPlayer(1);
92 DrawPlayer(2);
93 TRACE_EVENT_END("rendering");
94
95 // Record the rendering framerate as a counter sample.
96 TRACE_COUNTER("rendering", "Framerate", 120);
97 }
98
99 } // namespace
100
main(int,const char **)101 int main(int, const char**) {
102 InitializePerfetto();
103 auto tracing_session = StartTracing();
104
105 // Give a custom name for the traced process.
106 perfetto::ProcessTrack process_track = perfetto::ProcessTrack::Current();
107 perfetto::protos::gen::TrackDescriptor desc = process_track.Serialize();
108 desc.mutable_process()->set_process_name("Example");
109 perfetto::TrackEvent::SetTrackDescriptor(process_track, desc);
110
111 // Simulate some work that emits trace events.
112 DrawGame();
113
114 StopTracing(std::move(tracing_session));
115 return 0;
116 }
117