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