• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }