| Adithya Srinivasan | b9f62d6 | 2020-06-18 11:28:12 -0700 | [diff] [blame] | 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> | 
| Adithya Srinivasan | b9f62d6 | 2020-06-18 11:28:12 -0700 | [diff] [blame] | 26 |  | 
| Adithya Srinivasan | b9f62d6 | 2020-06-18 11:28:12 -0700 | [diff] [blame] | 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 |  | 
 | 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; | 
| Adithya Srinivasan | b9f62d6 | 2020-06-18 11:28:12 -0700 | [diff] [blame] | 45 |     perfetto::Tracing::Initialize(args); | 
 | 46 |     registerDataSource(); | 
| Adithya Srinivasan | f031e97 | 2020-12-12 03:31:50 +0000 | [diff] [blame] | 47 |     std::thread tracerThread(&GpuMemTracer::threadLoop, this, true); | 
| Adithya Srinivasan | b9f62d6 | 2020-06-18 11:28:12 -0700 | [diff] [blame] | 48 |     pthread_setname_np(tracerThread.native_handle(), "GpuMemTracerThread"); | 
 | 49 |     tracerThread.detach(); | 
| Adithya Srinivasan | f031e97 | 2020-12-12 03:31:50 +0000 | [diff] [blame] | 50 |     tracerThreadCount++; | 
 | 51 | } | 
 | 52 |  | 
 | 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 |  | 
| Adithya Srinivasan | f031e97 | 2020-12-12 03:31:50 +0000 | [diff] [blame] | 65 | // Each tracing session can be used for a single block of Start -> Stop. | 
 | 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; | 
| Adithya Srinivasan | b9f62d6 | 2020-06-18 11:28:12 -0700 | [diff] [blame] | 76 | } | 
 | 77 |  | 
 | 78 | void GpuMemTracer::registerDataSource() { | 
 | 79 |     perfetto::DataSourceDescriptor dsd; | 
 | 80 |     dsd.set_name(kGpuMemDataSource); | 
 | 81 |     GpuMemDataSource::Register(dsd); | 
 | 82 | } | 
 | 83 |  | 
| Adithya Srinivasan | f031e97 | 2020-12-12 03:31:50 +0000 | [diff] [blame] | 84 | void GpuMemTracer::threadLoop(bool infiniteLoop) { | 
 | 85 |     do { | 
| Adithya Srinivasan | b9f62d6 | 2020-06-18 11:28:12 -0700 | [diff] [blame] | 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 |         } | 
| Adithya Srinivasan | f031e97 | 2020-12-12 03:31:50 +0000 | [diff] [blame] | 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--; | 
| Adithya Srinivasan | b9f62d6 | 2020-06-18 11:28:12 -0700 | [diff] [blame] | 102 | } | 
 | 103 |  | 
 | 104 | void GpuMemTracer::traceInitialCounters() { | 
 | 105 |     if (!mGpuMem->isInitialized()) { | 
 | 106 |         // This should never happen. | 
 | 107 |         ALOGE("Cannot trace without GpuMem initialization"); | 
 | 108 |         return; | 
 | 109 |     } | 
| Yiwei Zhang | 5cd71a2 | 2020-08-13 17:39:51 -0700 | [diff] [blame] | 110 |     mGpuMem->traverseGpuMemTotals([](int64_t ts, uint32_t gpuId, uint32_t pid, uint64_t size) { | 
| Adithya Srinivasan | b9f62d6 | 2020-06-18 11:28:12 -0700 | [diff] [blame] | 111 |         GpuMemDataSource::Trace([&](GpuMemDataSource::TraceContext ctx) { | 
 | 112 |             auto packet = ctx.NewTracePacket(); | 
| Colin Cross | 0d5e129 | 2020-08-27 04:12:26 +0000 | [diff] [blame] | 113 |             packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC); | 
| Yiwei Zhang | 5cd71a2 | 2020-08-13 17:39:51 -0700 | [diff] [blame] | 114 |             packet->set_timestamp(ts); | 
| Adithya Srinivasan | b9f62d6 | 2020-06-18 11:28:12 -0700 | [diff] [blame] | 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 |