2
* Copyright (c) 2022-2023 Huawei Device Co., Ltd.
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
7
* http://www.apache.org/licenses/LICENSE-2.0
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.
19
#include <unordered_map>
21
#include "common-interop.h"
22
#include "DeserializerBase.h"
24
CustomDeserializer* DeserializerBase::customDeserializers = nullptr;
26
#if KOALA_INTEROP_PROFILER
29
InteropProfiler* InteropProfiler::_instance = nullptr;
36
static Napi::Reference<Napi::Function> g_koalaNapiCallbackDispatcher;
38
void impl_SetCallbackDispatcher(Napi::Object dispatcher) {
39
g_koalaNapiCallbackDispatcher = Napi::Reference<Napi::Function>::New(dispatcher.As<Napi::Function>(), 1);
41
KOALA_INTEROP_V1(SetCallbackDispatcher, Napi::Object)
43
void impl_CleanCallbackDispatcher() {
44
if (!g_koalaNapiCallbackDispatcher.IsEmpty()) {
45
g_koalaNapiCallbackDispatcher.Reset();
48
KOALA_INTEROP_V0(CleanCallbackDispatcher)
50
napi_value getKoalaNapiCallbackDispatcher() {
51
if (g_koalaNapiCallbackDispatcher.IsEmpty()) {
54
return (napi_value)g_koalaNapiCallbackDispatcher.Value();
58
KInt impl_StringLength(KNativePointer ptr) {
59
string* s = reinterpret_cast<string*>(ptr);
62
KOALA_INTEROP_1(StringLength, KInt, KNativePointer)
64
void impl_StringData(KNativePointer ptr, KByte* bytes, KUInt size) {
65
string* s = reinterpret_cast<string*>(ptr);
66
if (s) memcpy(bytes, s->c_str(), size);
68
KOALA_INTEROP_V3(StringData, KNativePointer, KByte*, KUInt)
70
KNativePointer impl_StringMake(const KStringPtr& str) {
71
return new string(str.c_str());
73
KOALA_INTEROP_1(StringMake, KNativePointer, KStringPtr)
75
// For slow runtimes w/o fast encoders.
76
KInt impl_ManagedStringWrite(const KStringPtr& string, KByte* buffer, KInt offset) {
77
memcpy(buffer + offset, string.c_str(), string.length() + 1);
78
return string.length() + 1;
80
KOALA_INTEROP_3(ManagedStringWrite, KInt, KStringPtr, KByte*, KInt)
82
void stringFinalizer(string* ptr) {
85
KNativePointer impl_GetStringFinalizer() {
86
return fnPtr<string>(stringFinalizer);
88
KOALA_INTEROP_0(GetStringFinalizer, KNativePointer)
90
void impl_InvokeFinalizer(KNativePointer obj, KNativePointer finalizer) {
91
auto finalizer_f = reinterpret_cast<void (*)(KNativePointer)>(finalizer);
94
KOALA_INTEROP_V2(InvokeFinalizer, KNativePointer, KNativePointer)
96
void disposeNodeTmp(KNativePointer* ptr) {
99
KNativePointer impl_GetNodeFinalizer() {
100
return fnPtr<KNativePointer>(disposeNodeTmp);
103
KOALA_INTEROP_0(GetNodeFinalizer, KNativePointer)
105
KInt impl_GetPtrVectorSize(KNativePointer ptr) {
106
return reinterpret_cast<std::vector<void*>*>(ptr)->size();
108
KOALA_INTEROP_1(GetPtrVectorSize, KInt, KNativePointer)
110
KNativePointer impl_GetPtrVectorElement(KNativePointer ptr, KInt index) {
111
auto vector = reinterpret_cast<std::vector<void*>*>(ptr);
112
auto element = vector->at(index);
113
return nativePtr(element);
115
KOALA_INTEROP_2(GetPtrVectorElement, KNativePointer, KNativePointer, KInt)
117
inline KUInt unpackUInt(const KByte* bytes) {
118
return (bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24));
121
std::vector<KStringPtr> makeStringVector(KStringArray strArray) {
122
if (strArray == nullptr) {
123
return std::vector<KStringPtr>(0);
125
KUInt arraySize = unpackUInt(strArray);
126
std::vector<KStringPtr> res(arraySize);
127
size_t offset = sizeof(KUInt);
128
for (KUInt i = 0; i < arraySize; ++i) {
129
int len = unpackUInt(strArray + offset);
130
res[i].assign((const char*)(strArray + offset + sizeof(KUInt)), len);
131
offset += len + sizeof(KUInt);
136
std::vector<KStringPtr> makeStringVector(KNativePointerArray arr, KInt length) {
137
if (arr == nullptr) {
138
return std::vector<KStringPtr>(0);
140
std::vector<KStringPtr> res(length);
141
char** strings = reinterpret_cast<char**>(arr);
142
for (KInt i = 0; i < length; ++i) {
143
const char* str = reinterpret_cast<const char*>(strings[i]);
154
std::vector<Log> groupedLogs;
156
void startGroupedLog(KInt index) {
157
if (index < 0) return;
158
if (index >= (int)groupedLogs.size()) {
159
groupedLogs.resize(index + 1);
161
groupedLogs[index] = Log{std::string(), true};
164
void stopGroupedLog(KInt index) {
165
if (index >=0 && index < (int)groupedLogs.size()) {
166
groupedLogs[index].isActive = false;
170
void appendGroupedLog(KInt index, const std::string& str) {
171
if (index < 0) return;
172
if (index >= (int)groupedLogs.size()) {
173
groupedLogs.resize(index + 1);
174
groupedLogs[index].isActive = true;
176
groupedLogs[index].log.append(str);
179
std::string emptyString;
181
const std::string& getGroupedLog(int32_t index) {
182
if (index >=0 && index < (int)groupedLogs.size()) {
183
return groupedLogs[index].log;
188
const bool needGroupedLog(int32_t index) {
189
if (index >=0 && index < (int)groupedLogs.size()) {
190
return groupedLogs[index].isActive;
195
KNativePointer impl_GetGroupedLog(KInt index) {
196
return new std::string(getGroupedLog(index));
198
KOALA_INTEROP_1(GetGroupedLog, KNativePointer, KInt)
200
void impl_StartGroupedLog(KInt index) {
201
startGroupedLog(index);
203
KOALA_INTEROP_V1(StartGroupedLog, KInt)
205
void impl_StopGroupedLog(KInt index) {
206
stopGroupedLog(index);
208
KOALA_INTEROP_V1(StopGroupedLog, KInt)
210
KInt impl_TestPerfNumber(KInt value) {
213
KOALA_INTEROP_1(TestPerfNumber, KInt, KInt)
215
void impl_TestPerfNumberWithArray(KByte* data, KInt length) {
216
if (needGroupedLog(1)) {
217
string out("TestPerfNumberWithArray(");
218
out.append(std::to_string(data[0]));
220
out.append(std::to_string(length));
222
appendGroupedLog(1, out);
225
KOALA_INTEROP_V2(TestPerfNumberWithArray, KByte*, KInt)
227
Performace* Performace::GetInstance() {
228
static Performace perf;
232
PerfInfo& Performace::GetCurrent() {
236
void Performace::FinishOne() {
237
perfs_[current_.perf_name].emplace_back(current_);
240
void Performace::CalcSelfCost() {
241
float totalCost = 0.0;
242
auto it = perfs_.find("perf_counter_self_cost");
243
if (it == perfs_.end()) {
244
self_cost_ = totalCost;
248
for (const auto& perf : it->second) {
249
totalCost += perf.cost / 1000.0;
251
self_cost_ = totalCost / it->second.size();
254
void Performace::PrintTotals(std::stringstream& result) {
255
for (const auto& [name, perfs] : perfs_) {
257
for (const auto& perf : perfs) {
258
totalCost += perf.cost / 1000.0 - self_cost_;
260
result << "Perf trace_name(" << name << ") " << perfs.size() << " call total cost " << totalCost << " us.";
264
void Performace::PrintAvgs(std::stringstream& result) {
265
for (const auto& [name, perfs] : perfs_) {
266
if (name == "perf_counter_self_cost") continue;
268
for (const auto& perf : perfs) {
269
totalCost += perf.cost / 1000.0 - self_cost_;
271
auto avg = totalCost / perfs.size();
272
result << "Perf trace_name(" << name << ") " << perfs.size() << " call avg cost " << avg << " us.";
276
void Performace::PrintPeak(std::stringstream& result) {
277
for(auto &kv : perfs_) {
278
std::sort(kv.second.begin(), kv.second.end(), [](const PerfInfo &perf1, const PerfInfo &perf2) {
279
return perf1.cost > perf2.cost;
281
auto maxCost = kv.second.front().cost / 1000.0 - self_cost_;
282
auto minCost = kv.second.back().cost / 1000.0 - self_cost_;
283
result << "Perf trace_name(" << kv.first << ") " << " maxCost = " << maxCost << " us, ";
284
result << "minCost = " << minCost << " us.";
288
void Performace::PrintDetails(std::stringstream& result) {
289
for (const auto& [name, perfs] : perfs_) {
290
for (auto perf : perfs) {
296
void Performace::Clean() {
300
void PerfInfo::Print(std::stringstream& result, float counterSelf) {
301
result << "Perf trace_name(" << perf_name << ") cost " << (cost / 1000.0 - counterSelf) << " us.";
304
void impl_StartPerf(const KStringPtr& traceName) {
305
PerfInfo& perf = Performace::GetInstance()->GetCurrent();
306
perf.perf_name = traceName.c_str();
307
auto now = std::chrono::high_resolution_clock::now();
308
perf.start = std::chrono::time_point_cast<std::chrono::nanoseconds>(now).time_since_epoch().count();
310
KOALA_INTEROP_V1(StartPerf, KStringPtr)
312
void impl_EndPerf(const KStringPtr& traceName) {
313
auto now = std::chrono::high_resolution_clock::now();
314
PerfInfo& perf = Performace::GetInstance()->GetCurrent();
315
perf.end = std::chrono::time_point_cast<std::chrono::nanoseconds>(now).time_since_epoch().count();
316
perf.cost = perf.end - perf.start;
317
Performace::GetInstance()->FinishOne();
319
KOALA_INTEROP_V1(EndPerf, KStringPtr)
329
KNativePointer impl_DumpPerf(KInt options) {
330
std::stringstream result;
331
result << std::fixed << std::setprecision(3);
332
Performace::GetInstance()->CalcSelfCost();
335
Performace::GetInstance()->PrintTotals(result);
338
Performace::GetInstance()->PrintAvgs(result);
341
Performace::GetInstance()->PrintPeak(result);
344
Performace::GetInstance()->PrintDetails(result);
347
Performace::GetInstance()->Clean();
352
return new std::string(result.str());
354
KOALA_INTEROP_1(DumpPerf, KNativePointer, KInt)