• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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 #undef LOG_TAG
18 #define LOG_TAG "GpuMemTracer"
19 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
20 
21 #include "tracing/GpuMemTracer.h"
22 
23 #include <gpumem/GpuMem.h>
24 #include <perfetto/trace/android/gpu_mem_event.pbzero.h>
25 #include <unistd.h>
26 
27 #include <thread>
28 
29 PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::GpuMemTracer::GpuMemDataSource);
30 
31 namespace android {
32 
33 std::mutex GpuMemTracer::sTraceMutex;
34 std::condition_variable GpuMemTracer::sCondition;
35 bool GpuMemTracer::sTraceStarted;
36 
initialize(std::shared_ptr<GpuMem> gpuMem)37 void GpuMemTracer::initialize(std::shared_ptr<GpuMem> gpuMem) {
38     if (!gpuMem->isInitialized()) {
39         ALOGE("Cannot initialize GpuMemTracer before GpuMem");
40         return;
41     }
42     mGpuMem = gpuMem;
43     perfetto::TracingInitArgs args;
44     args.backends = perfetto::kSystemBackend;
45     perfetto::Tracing::Initialize(args);
46     registerDataSource();
47     std::thread tracerThread(&GpuMemTracer::threadLoop, this, true);
48     pthread_setname_np(tracerThread.native_handle(), "GpuMemTracerThread");
49     tracerThread.detach();
50     tracerThreadCount++;
51 }
52 
initializeForTest(std::shared_ptr<GpuMem> gpuMem)53 void GpuMemTracer::initializeForTest(std::shared_ptr<GpuMem> gpuMem) {
54     mGpuMem = gpuMem;
55     perfetto::TracingInitArgs args;
56     args.backends = perfetto::kInProcessBackend;
57     perfetto::Tracing::Initialize(args);
58     registerDataSource();
59     std::thread tracerThread(&GpuMemTracer::threadLoop, this, false);
60     pthread_setname_np(tracerThread.native_handle(), "GpuMemTracerThreadForTest");
61     tracerThread.detach();
62     tracerThreadCount++;
63 }
64 
65 // Each tracing session can be used for a single block of Start -> Stop.
getTracingSessionForTest()66 std::unique_ptr<perfetto::TracingSession> GpuMemTracer::getTracingSessionForTest() {
67     perfetto::TraceConfig cfg;
68     cfg.set_duration_ms(500);
69     cfg.add_buffers()->set_size_kb(1024);
70     auto* ds_cfg = cfg.add_data_sources()->mutable_config();
71     ds_cfg->set_name(GpuMemTracer::kGpuMemDataSource);
72 
73     auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
74     tracingSession->Setup(cfg);
75     return tracingSession;
76 }
77 
registerDataSource()78 void GpuMemTracer::registerDataSource() {
79     perfetto::DataSourceDescriptor dsd;
80     dsd.set_name(kGpuMemDataSource);
81     GpuMemDataSource::Register(dsd);
82 }
83 
threadLoop(bool infiniteLoop)84 void GpuMemTracer::threadLoop(bool infiniteLoop) {
85     do {
86         {
87             std::unique_lock<std::mutex> lock(GpuMemTracer::sTraceMutex);
88             while (!sTraceStarted) {
89                 sCondition.wait(lock);
90             }
91         }
92         traceInitialCounters();
93         {
94             std::lock_guard<std::mutex> lock(GpuMemTracer::sTraceMutex);
95             sTraceStarted = false;
96         }
97     } while (infiniteLoop);
98 
99     // Thread loop is exiting. Reduce the tracerThreadCount to reflect the number of active threads
100     // in the wait loop.
101     tracerThreadCount--;
102 }
103 
traceInitialCounters()104 void GpuMemTracer::traceInitialCounters() {
105     if (!mGpuMem->isInitialized()) {
106         // This should never happen.
107         ALOGE("Cannot trace without GpuMem initialization");
108         return;
109     }
110     mGpuMem->traverseGpuMemTotals([](int64_t ts, uint32_t gpuId, uint32_t pid, uint64_t size) {
111         GpuMemDataSource::Trace([&](GpuMemDataSource::TraceContext ctx) {
112             auto packet = ctx.NewTracePacket();
113             packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
114             packet->set_timestamp(ts);
115             auto* event = packet->set_gpu_mem_total_event();
116             event->set_gpu_id(gpuId);
117             event->set_pid(pid);
118             event->set_size(size);
119         });
120     });
121     // Flush the TraceContext. The last packet in the above loop will go
122     // missing without this flush.
123     GpuMemDataSource::Trace([](GpuMemDataSource::TraceContext ctx) { ctx.Flush(); });
124 }
125 
126 } // namespace android
127