1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ffrt_profiler_handle.h"
17
18 namespace {
19 constexpr uint8_t FLUSH_INTERVAL = 10;
20 }
21
22 namespace OHOS::Developtools::Profiler {
FfrtProfilerHandle(uint32_t bufferSize,bool isProtobufSerialize)23 FfrtProfilerHandle::FfrtProfilerHandle(uint32_t bufferSize, bool isProtobufSerialize)
24 : isProtobufSerialize_(isProtobufSerialize), bufferSize_(bufferSize)
25 {
26 if (isProtobufSerialize_) {
27 buffer_ = std::make_unique<uint8_t[]>(bufferSize);
28 }
29 }
30
~FfrtProfilerHandle()31 FfrtProfilerHandle::~FfrtProfilerHandle()
32 {
33 std::visit([&](auto& protoData) {
34 FlushData(protoData);
35 }, protoData_);
36 }
37
SetWriter(const std::shared_ptr<Writer> & writer)38 void FfrtProfilerHandle::SetWriter(const std::shared_ptr<Writer>& writer)
39 {
40 writer_ = writer;
41 protoData_ = ::FfrtProfilerResult();
42 }
43
SetWriter(const WriterStructPtr & writer)44 void FfrtProfilerHandle::SetWriter(const WriterStructPtr& writer)
45 {
46 writerStruct_ = writer;
47 auto ctx = writerStruct_->startReport(writerStruct_);
48 if (ctx == nullptr) {
49 PROFILER_LOG_ERROR(LOG_CORE, "%s: get RandomWriteCtx FAILED!", __func__);
50 return;
51 }
52 protoData_ = ProtoEncoder::FfrtProfilerResult(ctx);
53 }
54
SerializeData(const int8_t data[],uint32_t size)55 void FfrtProfilerHandle::SerializeData(const int8_t data[], uint32_t size)
56 {
57 std::visit([&](auto& protoData) {
58 if (size < sizeof(FfrtResultBase)) {
59 PROFILER_LOG_ERROR(LOG_CORE, "%s the size=%d is too small", __FUNCTION__, size);
60 return;
61 }
62 SerializeDataImpl(protoData, data, size);
63 FlushCheck(protoData);
64 }, protoData_);
65 }
66
67 template <typename T>
SerializeDataImpl(T & protoData,const int8_t data[],uint32_t size)68 void FfrtProfilerHandle::SerializeDataImpl(T& protoData, const int8_t data[], uint32_t size)
69 {
70 FfrtResultBase* baseData = reinterpret_cast<FfrtResultBase*>(const_cast<int8_t*>(data));
71 if (baseData->type == static_cast<int32_t>(EventType::INVALID)) {
72 PROFILER_LOG_ERROR(LOG_CORE, "%s type is invalid", __FUNCTION__);
73 return;
74 }
75 ReportCommonData(protoData, baseData);
76 if (baseData->type == TRACE_DATA) {
77 SerializeTraceData(protoData, data, size);
78 } else {
79 SerializeRawData(protoData, data, size);
80 }
81 }
82
83 template <typename T>
ReportCommonData(T & protoData,FfrtResultBase * base)84 void FfrtProfilerHandle::ReportCommonData(T& protoData, FfrtResultBase* base)
85 {
86 if (base == nullptr || strlen(base->threadName) == 0) {
87 return;
88 }
89 FlushData(protoData);
90 auto baseDataProto = protoData.add_ffrt_event();
91 SerializeBaseData(baseDataProto, reinterpret_cast<const int8_t*>(base));
92
93 if (reportProcessName_) {
94 baseDataProto->set_process_name(processName_.c_str(), processName_.size());
95 reportProcessName_ = false;
96 }
97
98 baseDataProto->set_thread_name(base->threadName, strlen(base->threadName));
99 FlushData(protoData);
100 }
101
102 template <typename T>
SerializeBaseData(T & baseDataProto,const int8_t * data)103 void FfrtProfilerHandle::SerializeBaseData(T& baseDataProto, const int8_t* data)
104 {
105 FfrtResultBase* baseData = reinterpret_cast<FfrtResultBase*>(const_cast<int8_t*>(data));
106
107 baseDataProto->set_tv_sec(baseData->ts.tv_sec);
108 baseDataProto->set_tv_nsec(baseData->ts.tv_nsec);
109 baseDataProto->set_pid(pid_);
110 baseDataProto->set_tid(baseData->tid);
111 }
112
113 template <typename T>
SerializeTraceData(T & protoData,const int8_t data[],uint32_t size)114 void FfrtProfilerHandle::SerializeTraceData(T& protoData, const int8_t data[], uint32_t size)
115 {
116 FfrtTraceEvent* traceData = reinterpret_cast<FfrtTraceEvent*>(const_cast<int8_t*>(data));
117 auto ffrtEvent = protoData.add_ffrt_event();
118 SerializeBaseData(ffrtEvent, data);
119
120 auto trace = ffrtEvent->mutable_trace();
121 trace->set_cpu(traceData->cpu);
122 trace->set_trace_type(static_cast<const void*>(&(traceData->traceType)), 1);
123 trace->set_cookie(traceData->cookie);
124
125 size_t traceDataSize = sizeof(FfrtTraceEvent);
126 if (size > traceDataSize) {
127 trace->set_label(data + traceDataSize, strlen(reinterpret_cast<const char*>(data + traceDataSize)));
128 }
129 }
130
131 template <typename T>
SerializeRawData(T & protoData,const int8_t data[],uint32_t size)132 void FfrtProfilerHandle::SerializeRawData(T& protoData, const int8_t data[], uint32_t size)
133 {
134 FfrtResultBase* baseData = reinterpret_cast<FfrtResultBase*>(const_cast<int8_t*>(data));
135 auto ffrtEvent = protoData.add_ffrt_event();
136 SerializeBaseData(ffrtEvent, data);
137
138 size_t baseDataSize = sizeof(FfrtResultBase);
139 if (size > baseDataSize) {
140 auto rawEvent = ffrtEvent->mutable_raw();
141 rawEvent->set_type(baseData->type);
142 rawEvent->set_payload(data + baseDataSize, size - baseDataSize);
143 }
144 }
145
146 template <typename T>
FlushCheck(T & protoData)147 void FfrtProfilerHandle::FlushCheck(T& protoData)
148 {
149 if ((++flushCount_ & FLUSH_INTERVAL) != 0) {
150 return;
151 }
152 FlushData(protoData);
153 }
154
FlushData(::FfrtProfilerResult & data)155 void FfrtProfilerHandle::FlushData(::FfrtProfilerResult& data)
156 {
157 size_t length = data.ByteSizeLong();
158 if (length < bufferSize_) {
159 data.SerializeToArray(buffer_.get(), length);
160 if (buffer_.get() == nullptr) {
161 PROFILER_LOG_ERROR(LOG_CORE, "Flush src is nullptr");
162 return;
163 }
164
165 if (writer_ == nullptr) {
166 PROFILER_LOG_ERROR(LOG_CORE, "Flush writer_ is nullptr");
167 return;
168 }
169 writer_->Write(buffer_.get(), length);
170 writer_->Flush();
171 std::get<::FfrtProfilerResult>(protoData_).clear_ffrt_event();
172 }
173 }
174
FlushData(ProtoEncoder::FfrtProfilerResult & data)175 void FfrtProfilerHandle::FlushData(ProtoEncoder::FfrtProfilerResult& data)
176 {
177 if (data.Size() == 0) {
178 return;
179 }
180
181 int messageLen = data.Finish();
182
183 RandomWriteCtx* ctx = nullptr;
184 writerStruct_->finishReport(writerStruct_, messageLen);
185 writerStruct_->flush(writerStruct_);
186 ctx = writerStruct_->startReport(writerStruct_);
187 if (ctx == nullptr) {
188 PROFILER_LOG_ERROR(LOG_CORE, "%s: get RandomWriteCtx FAILED!", __func__);
189 return;
190 }
191 protoData_ = ProtoEncoder::FfrtProfilerResult(ctx);
192 }
193 }