• 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     if (size < sizeof(FfrtResultBase)) {
71         PROFILER_LOG_ERROR(LOG_CORE, "%s the size=%d is too small", __FUNCTION__, size);
72         return;
73     }
74     FfrtResultBase* baseData = reinterpret_cast<FfrtResultBase*>(const_cast<int8_t*>(data));
75     if (baseData->type == static_cast<int32_t>(EventType::INVALID)) {
76         PROFILER_LOG_ERROR(LOG_CORE, "%s type is invalid", __FUNCTION__);
77         return;
78     }
79     ReportCommonData(protoData, baseData);
80     if (baseData->type == TRACE_DATA) {
81         SerializeTraceData(protoData, data, size);
82     } else {
83         SerializeRawData(protoData, data, size);
84     }
85 }
86 
87 template <typename T>
ReportCommonData(T & protoData,FfrtResultBase * base)88 void FfrtProfilerHandle::ReportCommonData(T& protoData, FfrtResultBase* base)
89 {
90     if (base == nullptr || strlen(base->threadName) == 0) {
91         return;
92     }
93     FlushData(protoData);
94     auto baseDataProto = protoData.add_ffrt_event();
95     SerializeBaseData(baseDataProto, reinterpret_cast<const int8_t*>(base));
96 
97     if (reportProcessName_) {
98         baseDataProto->set_process_name(processName_.c_str(), processName_.size());
99         reportProcessName_ = false;
100     }
101 
102     baseDataProto->set_thread_name(base->threadName, strlen(base->threadName));
103     FlushData(protoData);
104 }
105 
106 template <typename T>
SerializeBaseData(T & baseDataProto,const int8_t * data)107 void FfrtProfilerHandle::SerializeBaseData(T& baseDataProto, const int8_t* data)
108 {
109     FfrtResultBase* baseData = reinterpret_cast<FfrtResultBase*>(const_cast<int8_t*>(data));
110 
111     baseDataProto->set_tv_sec(baseData->ts.tv_sec);
112     baseDataProto->set_tv_nsec(baseData->ts.tv_nsec);
113     baseDataProto->set_pid(pid_);
114     baseDataProto->set_tid(baseData->tid);
115 }
116 
117 template <typename T>
SerializeTraceData(T & protoData,const int8_t data[],uint32_t size)118 void FfrtProfilerHandle::SerializeTraceData(T& protoData, const int8_t data[], uint32_t size)
119 {
120     FfrtTraceEvent* traceData = reinterpret_cast<FfrtTraceEvent*>(const_cast<int8_t*>(data));
121     auto ffrtEvent = protoData.add_ffrt_event();
122     SerializeBaseData(ffrtEvent, data);
123 
124     auto trace = ffrtEvent->mutable_trace();
125     trace->set_cpu(traceData->cpu);
126     trace->set_trace_type(static_cast<const void*>(&(traceData->traceType)), 1);
127     trace->set_cookie(traceData->cookie);
128 
129     size_t traceDataSize = sizeof(FfrtTraceEvent);
130     if (size > traceDataSize) {
131         trace->set_label(data + traceDataSize, strlen(reinterpret_cast<const char*>(data + traceDataSize)));
132     }
133 }
134 
135 template <typename T>
SerializeRawData(T & protoData,const int8_t data[],uint32_t size)136 void FfrtProfilerHandle::SerializeRawData(T& protoData, const int8_t data[], uint32_t size)
137 {
138     FfrtResultBase* baseData = reinterpret_cast<FfrtResultBase*>(const_cast<int8_t*>(data));
139     auto ffrtEvent = protoData.add_ffrt_event();
140     SerializeBaseData(ffrtEvent, data);
141 
142     size_t baseDataSize = sizeof(FfrtResultBase);
143     if (size > baseDataSize) {
144         auto rawEvent = ffrtEvent->mutable_raw();
145         rawEvent->set_type(baseData->type);
146         rawEvent->set_payload(data + baseDataSize, size - baseDataSize);
147     }
148 }
149 
150 template <typename T>
FlushCheck(T & protoData)151 void FfrtProfilerHandle::FlushCheck(T& protoData)
152 {
153     if ((++flushCount_ & FLUSH_INTERVAL) != 0) {
154         return;
155     }
156     FlushData(protoData);
157 }
158 
FlushData(::FfrtProfilerResult & data)159 void FfrtProfilerHandle::FlushData(::FfrtProfilerResult& data)
160 {
161     size_t length = data.ByteSizeLong();
162     if (length < bufferSize_) {
163         data.SerializeToArray(buffer_.get(), length);
164         if (buffer_.get() == nullptr) {
165             PROFILER_LOG_ERROR(LOG_CORE, "Flush src is nullptr");
166             return;
167         }
168 
169         if (writer_ == nullptr) {
170             PROFILER_LOG_ERROR(LOG_CORE, "Flush writer_ is nullptr");
171             return;
172         }
173         writer_->Write(buffer_.get(), length);
174         writer_->Flush();
175         std::get<::FfrtProfilerResult>(protoData_).clear_ffrt_event();
176     }
177 }
178 
FlushData(ProtoEncoder::FfrtProfilerResult & data)179 void FfrtProfilerHandle::FlushData(ProtoEncoder::FfrtProfilerResult& data)
180 {
181     if (data.Size() == 0) {
182         return;
183     }
184 
185     int messageLen = data.Finish();
186 
187     RandomWriteCtx* ctx = nullptr;
188     writerStruct_->finishReport(writerStruct_, messageLen);
189     writerStruct_->flush(writerStruct_);
190     ctx = writerStruct_->startReport(writerStruct_);
191     if (ctx == nullptr) {
192         PROFILER_LOG_ERROR(LOG_CORE, "%s: get RandomWriteCtx FAILED!", __func__);
193         return;
194     }
195     protoData_ = ProtoEncoder::FfrtProfilerResult(ctx);
196 }
197 }