diff --git a/README.en.md b/README.en.md deleted file mode 100644 index 5ceb97dc2668a3fb157e1f5da8c5d022e45bf810..0000000000000000000000000000000000000000 --- a/README.en.md +++ /dev/null @@ -1,36 +0,0 @@ -# smartperf - -#### Description -{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**} - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md deleted file mode 100644 index 278241571f6290f4fbd1fbf96881117a538e31f3..0000000000000000000000000000000000000000 --- a/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# smartperf - -#### 介绍 -{**以下是 Gitee 平台说明,您可以替换此简介** -Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台 -无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)} - -#### 软件架构 -软件架构说明 - - -#### 安装教程 - -1. xxxx -2. xxxx -3. xxxx - -#### 使用说明 - -1. xxxx -2. xxxx -3. xxxx - -#### 参与贡献 - -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request - - -#### 特技 - -1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md -2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) -3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 -4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 -5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) -6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README_zh.md b/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..38e2cebaeb239a565687682defad1e7cb7f6742b --- /dev/null +++ b/README_zh.md @@ -0,0 +1,65 @@ +# SmartPerf + +- [简介](#简介) +- [目录](#目录) +- [约束](#约束) +- [相关文档](#相关文档) + +## 简介 + +- **SmartPerf** 是一款基于OpenHarmony系统开发的性能功耗测试分析工具,支持两个组成部分: SP-Device端和SP-Host端。 +- **SP-Device端:** 是一款初级的,粗粒度的数据采集分析的性能功耗测试工具。支持FPS、功耗、热、Soc信息的实时采集、实时展示、数据报告生成。 +- **SP-Host端:** 是一款深入挖掘数据、细粒度的展示数据的性能功耗测试工具。支持CPU调度、频点、进程线程时间片、堆内存、FPS数据采集和展示。支持在泳道图中展示非实时的采集数据,支持GUI操作数据分析。 + +其主要的结构如下图所示: + +![系统架构图](http://image.huawei.com/tiny-lts/v1/images/cc51c24a361d47dd1d10b23f089a0faa_877x491.png) + + +## 目录 +``` +/developtools/smartperf +├── device # device端 相关代码 +│   ├── device_command # device端 命令行方式采集代码 +│ ├── device_ui # device端 GUI方式采集代码 +├── host # host端 相关代码 +│ ├── doc # host端 相关使用文档 +│ ├── ide # host端 IDE 模块目录 +│   │ └── src # 主机测调优模块代码 +│ │ │ ├── base-ui # 基础组件目录 +│ │ │ └── Trace # 业务逻辑目录 +│ ├── trace_streamer # 解析模块代码目录 +│   │ ├── base # 基础功能 +│ │ ├── cfg # 配置目录 +│ │ ├── filter # Filter功能 +│ │ ├── include # Include头文件 +│ │ ├── multi_platform # 平台适配 +│ │ ├── parser # 解析业务逻辑 +│ │ │ ├── bytrace_parser # byTrace解析业务逻辑 +│ │ │ └── htrace_parser # hTrace 解析业务逻辑 +│ │ ├── table # 表结构 +│ │ ├── trace_data # trace 结构 +│ │ ├── trace_streamer # traceStreamer 结构 +│ │ │   └── kits # js/napi接口存放目录 +``` + + + +## 约束 +host端构建约束 +- 语言版本 + - C++11或以上 + - TypeScript 4.2.3 + + +## 相关文档 +- [device_command_line_collection](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/quickstart_trace_streamer.md) +- [device_ui_collection](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/quickstart_trace_streamer.md) +- [quickstart_trace_streamer](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/quickstart_trace_streamer.md) +- [quickstart_smartperf](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/quickstart_smartperf.md) +- [quickstart_hiprofiler_cmd](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/quickstart_hiprofiler_cmd.md) +- [compile_smartperf](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/compile_smartperf.md) +- [compile_trace_streamer](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/compile_trace_streamer.md) +- [des_stat](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/des_stat.md) +- [des_support_event](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/des_support_event.md) +- [des_tables](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/des_tables.md) \ No newline at end of file diff --git a/device/device_command/BUILD.gn b/device/device_command/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..2975184bee41ca26abb81c30cb37cfbfc09324ad --- /dev/null +++ b/device/device_command/BUILD.gn @@ -0,0 +1,59 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../../build/config.gni") + +## Build so {{{ +config("config") { + visibility = [ ":*" ] + + cflags = [ + "-Wall", + "-Werror", + "-g3", + "-Wunused-variable", + ] +} + +config("public_config") { +} + +ohos_executable("SP_daemon") { + sources = [ + "ByTrace.cpp", + "CPU.cpp", + "DDR.cpp", + "FPS.cpp", + "GPU.cpp", + "Power.cpp", + "RAM.cpp", + "Temperature.cpp", + "gp_utils.cpp", + "profiler.cpp", + "smartperf_command.cpp", + "smartperf_main.cpp", + "socket_profiler.cpp", + ] + include_dirs = [ + "//developtools/profiler/host/smartperf/client/client_command/include", + "//utils/native/base/include", + ] + configs = [ ":config" ] + + deps = [ "//utils/native/base:utils" ] + + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" +} +## Build so }}} diff --git a/device/device_command/ByTrace.cpp b/device/device_command/ByTrace.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4458842f3a8f2628dc34357f6d4836db3e566dd --- /dev/null +++ b/device/device_command/ByTrace.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include "include/ByTrace.h" + +namespace OHOS { +namespace SmartPerf { +void ByTrace::thread_get_trace() +{ + std::stringstream sstream; + sstream << "bytrace --trace_begin --overwrite"; + std::string cmd_trace = sstream.str(); + GPUtils::readFile(cmd_trace); +} +void ByTrace::thread_finish_trace(std::string &pathName) +{ + std::stringstream sstream; + sstream << "bytrace --trace_finish"; + const std::string &cmd_trace_finish = sstream.str(); + GPUtils::readFile(cmd_trace_finish); + sstream.str(""); + sstream << "bytrace --overwrite sched ace app disk ohos graphic sync workq ability > /data/mynewtrace"; + sstream << pathName; + sstream << "s.ftrace"; + const std::string &cmd_trace_overwrite = sstream.str(); + GPUtils::readFile(cmd_trace_overwrite); +} + +TraceStatus ByTrace::init_trace(bool isStart) +{ + if (isStart) { + return TraceStatus::TRACE_START; + } else { + return TraceStatus::TRACE_NO; + } +} + +TraceStatus ByTrace::check_fps_jitters(std::vector jitters, int curProfilerNum) +{ + if (curNum <= sum) { + for (size_t i = 0; i < jitters.size(); i++) { + long long normalJitter = jitters[i] / 1e6; + if (normalJitter > threshold) { + if ((flagProfilerNum != -1) && curProfilerNum < (flagProfilerNum + interval)) { + // 如果不是第一次抓取 并且 小于抓取周期间隔 则放弃抓取 + return TraceStatus::TRACE_NO; + } + curNum++; + flagProfilerNum = curProfilerNum; + std::cout << "***************************************************************************" << std::endl; + std::cout << "***************************************************************************" << std::endl; + std::cout << "************* ByTrace::getTrace:curJitter:" << normalJitter << "*******************" << + std::endl; + std::cout << "***************************************************************************" << std::endl; + std::cout << "***************************************************************************" << std::endl; + return TraceStatus::TRACE_FINISH; + } + } + } + return TraceStatus::TRACE_NO; +} +} +} diff --git a/device/device_command/CPU.cpp b/device/device_command/CPU.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f8d556f8f689fdfb81b528d0a48edab5af4aad2 --- /dev/null +++ b/device/device_command/CPU.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "securec.h" +#include "include/CPU.h" +namespace OHOS { +namespace SmartPerf { +int CPU::get_cpu_num() +{ + char cpu_node[128]; + int cpu_num = 0; + while (true) { + if (snprintf_s(cpu_node, sizeof(cpu_node), sizeof(cpu_node), "%s/cpu%d", CPU_BASE_PATH.c_str(), cpu_num) > 0) { + if (access(cpu_node, F_OK) == -1) { + break; + } + } + ++cpu_num; + } + return m_cpu_num = cpu_num; +} +int CPU::get_cpu_freq(int cpu_id) +{ + char buffer[128]; + if (access(CPU_SCALING_CUR_FREQ(cpu_id).c_str(), F_OK) == -1) { + return -1; + } + FILE *fp = fopen(CPU_SCALING_CUR_FREQ(cpu_id).c_str(), "r"); + if (fp == nullptr) { + return -1; + } + buffer[0] = '\0'; + while (fgets(buffer, sizeof(buffer), fp) == nullptr) { + std::cout << "fgets fail"; + } + if (fclose(fp) == EOF) { + return EOF; + } + return atoi(buffer); +} +std::vector CPU::get_cpu_load() +{ + if (m_cpu_num <= 0) { + std::vector workload; + return workload; + } + std::vector workload; + + static char pre_buffer[10][256] = { + "\0", + "\0", + "\0", + "\0", + "\0", + "\0", + "\0", + "\0", + "\0", + "\0", + }; + if (access(PROC_STAT.c_str(), F_OK) == -1) { + return workload; + } + FILE *fp = fopen(PROC_STAT.c_str(), "r"); + if (fp == nullptr) { + for (int i = 0; i <= m_cpu_num; ++i) { + workload.push_back(-1.0f); + } + return workload; + } + char buffer[1024]; + buffer[0] = '\0'; + int line = 0; + while (fgets(buffer, sizeof(buffer), fp) != nullptr) { + const int zeroPos = 0; + const int firstPos = 1; + const int secondPos = 2; + const int length = 3; + if (strlen(buffer) >= length && buffer[zeroPos] == 'c' && buffer[firstPos] == 'p' && buffer[secondPos] == 'u') { + float b = cac_workload(buffer, pre_buffer[line]); + workload.push_back(b); + if (snprintf_s(pre_buffer[line], sizeof(pre_buffer[line]), sizeof(pre_buffer[line]), "%s", buffer) < 0) { + std::cout << "snprintf_s fail"; + } + } + ++line; + + if (line >= m_cpu_num + 1) { + break; + } + } + if (fclose(fp) == EOF) { + return workload; + } + + return workload; +} + +float CPU::cac_workload(const char *buffer, const char *pre_buffer) +{ + const size_t default_index = 4; + const size_t default_shift = 10; + const char default_start = '0'; + const char default_end = '9'; + + size_t pre_len = strlen(pre_buffer); + size_t len = strlen(buffer); + if (pre_len == 0 || len == 0) { + return -1.0f; + } + size_t time[10]; + size_t pre_time[10]; + size_t cnt = 0; + + for (size_t i = default_index; i < len; ++i) { + size_t tmp = 0; + if (buffer[i] < default_start || buffer[i] > default_end) { + continue; + } + while (buffer[i] >= default_start && buffer[i] <= default_end) { + tmp = tmp * default_shift + (buffer[i] - default_start); + i++; + } + time[cnt++] = tmp; + } + + size_t pre_cnt = 0; + for (size_t i = default_index; i < pre_len; ++i) { + size_t tmp = 0; + if (pre_buffer[i] < default_start || pre_buffer[i] > default_end) { + continue; + } + while (pre_buffer[i] >= default_start && pre_buffer[i] <= default_end) { + tmp = tmp * default_shift + (pre_buffer[i] - default_start); + i++; + } + pre_time[pre_cnt++] = tmp; + } + + size_t user = time[0] + time[1] - pre_time[0] - pre_time[1]; + size_t sys = time[2] - pre_time[2]; + size_t idle = time[3] - pre_time[3]; + size_t iowait = time[4] - pre_time[4]; + size_t irq = time[5] + time[6] - pre_time[5] - pre_time[6]; + size_t total = user + sys + idle + iowait + irq; + + if (user < 0 || sys < 0 || idle < 0 || iowait < 0 || irq < 0) { + return 0.0f; + } + + double per_user = std::atof(std::to_string(user * 100.0 / total).c_str()); + double per_sys = std::atof(std::to_string(sys * 100.0 / total).c_str()); + double per_iowait = std::atof(std::to_string(iowait * 100.0 / total).c_str()); + double per_irq = std::atof(std::to_string(irq * 100.0 / total).c_str()); + + double workload = per_user + per_sys + per_iowait + per_irq; + + return static_cast(workload); +} +} +} diff --git a/device/device_command/DDR.cpp b/device/device_command/DDR.cpp new file mode 100644 index 0000000000000000000000000000000000000000..80997f9397474f9c0060efe8c54bfd4b4bbb78d2 --- /dev/null +++ b/device/device_command/DDR.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "include/DDR.h" +namespace OHOS { +namespace SmartPerf { +long long DDR::get_ddr_freq() +{ + long long curFreq; + std::string ddr_freq = GPUtils::freadFile(std::string(ddr_cur_freq_path.c_str())); + curFreq = std::atoll(ddr_freq.c_str()); + return curFreq; +} +} +} diff --git a/device/device_command/FPS.cpp b/device/device_command/FPS.cpp new file mode 100644 index 0000000000000000000000000000000000000000..93f1236d3b8fd2cc4d29816c4210f2781af015b3 --- /dev/null +++ b/device/device_command/FPS.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include "securec.h" +#include "include/gp_utils.h" +#include "include/FPS.h" +namespace OHOS { + namespace SmartPerf { + void FPS::setPackageName(std::string pkgName) + { + pkg_name = std::move(pkgName); + std::vector sps; + GPUtils::mSplit(pkg_name, ".", sps); + if (sps.size() > 0) { + cur_layer_name = std::string(""); + std::string cur_layer = sps[2]; + char cmd[100]; + if (snprintf_s(cmd, sizeof(cmd), sizeof(cmd), + "hidumper -s 10 |grep surface |grep %s", cur_layer.c_str()) < 0) { + std::cout << "snprintf fail"; + } + std::string layer_line = GPUtils::readFile(cmd); + int flag = 0; + for (size_t i = 0; i < layer_line.size(); i++) { + if (layer_line[i] == ']') { + flag = 0; + break; + } + if (flag) { + cur_layer_name += layer_line[i]; + } + if (layer_line[i] == '[') { + flag = 1; + } + } + } + } + FpsInfo FPS::getFpsInfo(int is_video, int is_camera) + { + FpsInfo fpsInfoMax; + fpsInfoMax.fps = -1; + + std::string layerName; + if (is_video) { + layerName = std::string("RosenRenderTexture"); + } else if (is_camera) { + layerName = std::string("RosenRenderXComponent"); + } else { + std::vector sps; + GPUtils::mSplit(this->pkg_name, ".", sps); + std::string addEndChar = "0"; + const int pNameLastPos = 2; + layerName = std::string(sps[pNameLastPos].c_str() + addEndChar); + } + FpsInfo fpsInfo = GetSurfaceFrame(layerName); + if (fpsInfo.fps > fpsInfoMax.fps) { + fpsInfoMax = fpsInfo; + } + return fpsInfoMax; + } + FpsInfo FPS::GetSurfaceFrame(std::string name) + { + if (name == "") { + return FpsInfo(); + } + static std::map fps_map; + if (fps_map.count(name) == 0) { + FpsInfo tmp; + tmp.fps = 0; + tmp.pre_fps = 0; + fps_map[name] = tmp; + } + FpsInfo &fpsInfo = fps_map[name]; + fpsInfo.fps = 0; + FILE *fp; + static char tmp[1024]; + std::string cmd = "hidumper -s 10 -a \"fps " + name + "\""; + fp = popen(cmd.c_str(), "r"); + if (fp == nullptr) { + return fpsInfo; + } + long long MOD = 1e9; + long long lastReadyTime = -1; + int fps_gb = 0; + if (!(fpsInfo.time_stamp_q).empty()) { + lastReadyTime = (fpsInfo.time_stamp_q).back(); + } + bool jump = false; + bool refresh = false; + + int cnt = 0; + int zeroNum = 0; + while (fgets(tmp, sizeof(tmp), fp) != nullptr) { + long long frameReadyTime = 0; + std::stringstream sstream; + sstream << tmp; + sstream >> frameReadyTime; + cnt++; + if (frameReadyTime == 0) { + zeroNum++; + continue; + } + if (lastReadyTime >= frameReadyTime) { + lastReadyTime = -1; + continue; + } + refresh = true; + long long t_frameReadyTime = frameReadyTime / MOD; + long long t_lastReadyTime = lastReadyTime / MOD; + long long lastFrame = -1; + if (t_frameReadyTime == t_lastReadyTime) { + (fpsInfo.time_stamp_q).push(frameReadyTime); + } else if (t_frameReadyTime == t_lastReadyTime + 1) { + jump = true; + lastFrame = fpsInfo.last_frame_ready_time; + lastReadyTime = frameReadyTime; + int fps_tmp = 0; + fpsInfo.jitters.clear(); + while (!(fpsInfo.time_stamp_q).empty()) { + fps_tmp++; + long long currFrame = (fpsInfo.time_stamp_q.front()); + if (lastFrame != -1) { + long long jitter = currFrame - lastFrame; + fpsInfo.jitters.push_back(jitter); + } + lastFrame = currFrame; + (fpsInfo.time_stamp_q).pop(); + } + + fps_gb = fps_tmp; + + (fpsInfo.time_stamp_q).push(frameReadyTime); + + fpsInfo.last_frame_ready_time = lastFrame; + } else if (t_frameReadyTime > t_lastReadyTime + 1) { + jump = true; + lastReadyTime = frameReadyTime; + + while (!(fpsInfo.time_stamp_q).empty()) { + (fpsInfo.time_stamp_q).pop(); + } + + (fpsInfo.time_stamp_q).push(frameReadyTime); + } + } + + pclose(fp); + const int maxZeroNum = 120; + if (zeroNum >= maxZeroNum) { + while (!(fpsInfo.time_stamp_q.empty())) { + fpsInfo.time_stamp_q.pop(); + } + fpsInfo.fps = 0; + return fpsInfo; + } + const int minPrintLine = 5; + if (cnt < minPrintLine) { + fpsInfo.fps = fpsInfo.pre_fps; + return fpsInfo; + } + + if (fps_gb > 0) { + fpsInfo.fps = fps_gb; + fpsInfo.pre_fps = fps_gb; + return fpsInfo; + } else if (refresh && !jump) { + fpsInfo.fps = fpsInfo.pre_fps; + return fpsInfo; + } else { + fpsInfo.fps = 0; + return fpsInfo; + } + } + } +} diff --git a/device/device_command/GPU.cpp b/device/device_command/GPU.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c13a7bfd5058ef833491a11fa8300f874ce2679 --- /dev/null +++ b/device/device_command/GPU.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "include/GPU.h" + +namespace OHOS { + namespace SmartPerf { + void GPU::init_gpu_node() + { + for (int i = 0; i < sizeof(GPU_CUR_FREQ_PATH) / sizeof(const char *); ++i) { + if (GPUtils::canOpen(GPU_CUR_FREQ_PATH[i])) { + gpu_cur_freq_path = std::string(GPU_CUR_FREQ_PATH[i]); + } + } + + for (int i = 0; i < sizeof(GPU_CUR_WORKLOAD_PATH) / sizeof(const char *); ++i) { + if (GPUtils::canOpen(GPU_CUR_WORKLOAD_PATH[i])) { + gpu_cur_load_path = std::string(GPU_CUR_WORKLOAD_PATH[i]); + } + } + } + int GPU::get_gpu_freq() + { + std::string gpu_freq = GPUtils::readFile(std::string(gpu_cur_freq_path.c_str())); + return atoi(gpu_freq.c_str()); + } + float GPU::calc_workload(const char *buffer) const + { + std::vector sps; + std::string buffer_line = buffer; + GPUtils::mSplit(buffer, "@", sps); + if (sps.size() > 0) { + // rk3568 + float loadRk = std::stof(sps[0]); + return loadRk; + } else { + // wgr + float loadWgr = std::stof(buffer); + return loadWgr; + } + return -1.0; + } + float GPU::get_gpu_load() + { + static char buffer[128]; + if (access(gpu_cur_load_path.c_str(), F_OK) == -1) { + return -1.0; + } + FILE *fp = fopen(gpu_cur_load_path.c_str(), "r"); + if (fp == nullptr) { + return EOF; + } + buffer[0] = '\0'; + while (fgets(buffer, sizeof(buffer), fp) == nullptr) { + std::cout << "fgets fail"; + } + if (fclose(fp) == EOF) { + return -1.0; + } + return calc_workload(buffer); + } + } +} diff --git a/device/device_command/Power.cpp b/device/device_command/Power.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c10b6ccbd991cc965fbfff1a00142908423a15d --- /dev/null +++ b/device/device_command/Power.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include "securec.h" +#include "include/gp_utils.h" +#include "include/Power.h" + +namespace OHOS { +namespace SmartPerf { +void Power::init_power() +{ + for (int i = 0; i < sizeof(power_path) / sizeof(const char *); ++i) { + if (GPUtils::canOpen(std::string(power_path[i]))) { + power_base_path = std::string(power_path[i]); + } + } + + char powerNode[256]; + for (int j = 0; j < sizeof(default_collect_power_info) / sizeof(const char *); ++j) { + if (snprintf_s(powerNode, sizeof(powerNode), sizeof(powerNode), "%s/%s", power_base_path.c_str(), + default_collect_power_info[j]) < 0) { + std::cout << "snprintf fail"; + } + // file exists + std::string type = std::string(default_collect_power_info[j]); + if (power_node_path_map.count(type) > 0) { + continue; + } + power_node_path_map[type] = std::string(powerNode); + } +} + +std::map Power::getPowerMap() +{ + std::map power_map; + FILE *fp = nullptr; + char buffer[256]; + std::map::iterator iter; + int charging = 1; + for (iter = power_node_path_map.begin(); iter != power_node_path_map.end(); ++iter) { + std::string type = iter->first; + std::string powerNode = power_node_path_map[type]; + if (access(powerNode.c_str(), F_OK) == -1) { + continue; + } + fp = fopen(powerNode.c_str(), "r"); + if (fp == nullptr) { + power_map[type] = "-1.0"; + continue; + } + buffer[0] = '\0'; + while (fgets(buffer, sizeof(buffer), fp) == nullptr) { + std::cout << "fgets fail"; + } + if (fclose(fp) == EOF) { + std::cout << "fclose fail"; + } + std::string power_value = std::string(buffer); + if (iter->first == "status") { + if (power_value.find("Charging") == std::string::npos && power_value.find("Full") == std::string::npos) { + charging = 0; + } + if (power_value.find("Discharging") != std::string::npos) { + charging = 0; + } + } else if (iter->first == "enable_hiz") { + if (strcmp(buffer, "1") == 0) { + charging = 0; + } + if (std::stoi(power_value) == 1) { + charging = 0; + } + } else if (iter->first == "current_now") { + // 若current now 大于 100000 单位归一化为 1000,大于10000 单位归一化为100,大于3000 单位归一化为10 + double tmp = fabs(std::stof(power_value)); + power_value = std::to_string(tmp); + } else if (iter->first == "voltage_now") { + // 若voltage now 大于100 单位归一化为100 + double tmp = std::stof(power_value); + power_value = std::to_string(tmp); + } + power_map[type] = power_value; + } + if (power_map.count("voltage_now") == 0 && power_map.count("bat_id_0") > 0 && power_map.count("bat_id_1") > 0) { + power_map["voltage_now"] = std::to_string(std::stof(power_map["bat_id_0"]) + std::stof(power_map["bat_id_1"])); + } + if (power_map.count("current_now") > 0 && charging) { + power_map["current_now"] = "-" + power_map["current_now"]; + } + if (power_map.count("status") > 0 && charging == 0) { + power_map["status"] = "Discharging"; + } + return power_map; +} +} +} \ No newline at end of file diff --git a/device/device_command/RAM.cpp b/device/device_command/RAM.cpp new file mode 100644 index 0000000000000000000000000000000000000000..653182a247bfe61e196830eb40b59145a4a032b7 --- /dev/null +++ b/device/device_command/RAM.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include "securec.h" +#include "include/gp_utils.h" +#include "include/RAM.h" + +namespace OHOS { +namespace SmartPerf { +void RAM::setPkgName(std::string ss) +{ + pkgName = std::move(ss); +} + +std::map RAM::getRamInfo(std::string pkg_name, int pid) +{ + std::map ramInfo; + ramInfo["pss"] = "-1"; + std::string pid_value = ""; + if (pid > 0) { + pid_value = std::to_string(pid); + } else { + char pidStr[100]; + if (snprintf_s(pidStr, sizeof(pidStr), sizeof(pidStr), + "ps -ef |grep -w %s", pkg_name.c_str()) < 0) { + std::cout << "snprintf_s fail"; + } + std::string pidLine = GPUtils::readFile(pidStr); + std::vector sps; + GPUtils::mSplit(pidLine, " ", sps); + if (sps.size() > 0) { + pid_value = sps[1]; + } + } + + std::string tmp = "-1"; + if (atoi(pid_value.c_str()) > 0) { + char ram[50]; + if (snprintf_s(ram, sizeof(ram), sizeof(ram), "/proc/%s/smaps_rollup", pid_value.c_str()) < 0) { + std::cout << "snprintf fail"; + } + std::string path = ram; + FILE *fp; + if (access(path.c_str(), F_OK) == -1) { + return ramInfo; + } + if ((fp = fopen(path.c_str(), "r")) != nullptr) { + char s[1024]; + s[0] = '\0'; + while (fgets(s, sizeof(s), fp) != nullptr) { + const int zeroPos = 0; + const int firstPos = 1; + const int secondPos = 2; + const int thirdPos = 3; + if (s[zeroPos] == 'P' && s[firstPos] == 's' && s[secondPos] == 's' && s[thirdPos] == ':') { + tmp += std::string(s); + } + } + } + if (fp != nullptr) { + pclose(fp); + } + } + ramInfo["pss"] = GPUtils::getNumber(tmp); + return ramInfo; +} +} +} diff --git a/device/device_command/README_zh.md b/device/device_command/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..255edabca04f36add27641a77547fbf6e8f79b82 --- /dev/null +++ b/device/device_command/README_zh.md @@ -0,0 +1,102 @@ +## 工具介绍 + +> OpenHarmony性能测试工具,通过采集设备性能指标,对采集数据进行实时展示、导出csv。 + +## 支持功能 + +> 当前版本支持如下功能 + +- 支持RK3568、Hi3516; +- 支持Shell启动; +- 支持采集整机CPU、GPU、POWER、TEMPERATURE、应用的FPS、RAM; + +## 使用方式 +>1、首先检查系统是否默认预制了SP_daemon,如打印如下日志,系统已内置SP_daemon + +```bash +C:\>hdc_std shell +SP_daemon --help +usage: SP_daemon +-------------------------------------------------------------------- +These are common commands list: + -N set num of profiler + -PKG set pkgname of profiler + -PID set process id of profiler + -OUT set output path of CSV + -c get cpuFreq and cpuLoad + -g get gpuFreq and gpuLoad + -f get fps and fps jitters + -t get soc-temp gpu-temp .. + -p get current_now and voltage_now + -r get ram(pss) + -snapshot get screen capture +-------------------------------------------------------------------- +Example: SP_daemon -N 20 -PKG ohos.samples.ecg -c -g -t -p -f +-------------------------------------------------------------------- +command exec finished! +``` +>2、执行示例命令:SP_daemon -N 20 -PKG ohos.samples.ecg -c -g -t -p -f +``` +----------------------------------Print START------------------------------------ +order:0 cpu0freq=1992000 +order:1 cpu0load=23.469387 +order:2 cpu1freq=1992000 +order:3 cpu1load=26.262627 +order:4 cpu2freq=1992000 +order:5 cpu2load=19.000000 +order:6 cpu3freq=1992000 +order:7 cpu3load=74.747475 +order:8 current_now=-1000.000000 +order:9 gpu-thermal=48333.000000 +order:10 gpufreq=200000000 +order:11 gpuload=0.000000 +order:12 soc-thermal=48888.000000 +order:13 timestamp=1501925596847 +order:14 voltage_now=4123456.000000 +----------------------------------Print END-------------------------------------- +----------------------------------Print START------------------------------------ +order:0 cpu0freq=1992000 +order:1 cpu0load=33.673470 +order:2 cpu1freq=1992000 +order:3 cpu1load=19.801979 +order:4 cpu2freq=1992000 +order:5 cpu2load=37.755100 +order:6 cpu3freq=1992000 +order:7 cpu3load=55.555553 +order:8 current_now=-1000.000000 +order:9 gpu-thermal=48333.000000 +order:10 gpufreq=200000000 +order:11 gpuload=0.000000 +order:12 soc-thermal=48888.000000 +order:13 timestamp=1501925597848 +order:14 voltage_now=4123456.000000 +----------------------------------Print END-------------------------------------- +``` +>3、执行完毕后会在data/local/tmp生成data.csv文件,每次执行命令覆盖写入 +```bash +# cat /data/local/tmp/data.csv +cpu0freq,cpu0load,cpu1freq,cpu1load,cpu2freq,cpu2load,cpu3freq,cpu3load,current_now,gpu-thermal,gpufreq,gpuload,soc-thermal,timestamp,voltage_now +1992000,-1.000000,1992000,-1.000000,1992000,-1.000000,1992000,-1.000000,-1000.000000,48333.000000,200000000,0.000000,49444.000000,1501925677010,4123456.000000 +1992000,16.326530,1992000,22.680412,1992000,62.626263,1992000,41.836735,-1000.000000,48333.000000,200000000,0.000000,48888.000000,1501925678011,4123456.000000 +1992000,16.326530,1992000,35.353535,1992000,50.505051,1992000,42.857143,-1000.000000,48333.000000,200000000,0.000000,49444.000000,1501925679013,4123456.000000 +``` +--- + +## 参数说明 + +| 命令 | 功能 |是否必选| +| :-----| :--------------------- |:-----| +| -N | 设置采集次数 |是| +| -PKG | 设置包名 |否| +| -PID | 设置进程pid(对于ram适用) |否| +| -c | 是否采集cpu |否| +| -g | 是否采集gpu |否| +| -f | 是否采集fps |否| +| -t | 是否采集温度 |否| +| -p | 是否采集电流 |否| +| -r | 是否采集内存(需指定进程pid) |否| +| -snapshot | 是否截图 |否| + +--- +## 构建方式 +>1、在OpenHarmony系统根目录执行全量编译命令(RK3568为例): ./build.sh --product-name rk3568 --ccache
diff --git a/device/device_command/Temperature.cpp b/device/device_command/Temperature.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f7149b69e20b9eb5eecd506d8ddfaac4abdacb19 --- /dev/null +++ b/device/device_command/Temperature.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include "securec.h" +#include "include/Temperature.h" +namespace OHOS { +namespace SmartPerf { +void Temperature::init_temperature() +{ + int cnt = sizeof(thermal_path) / sizeof(const char *); + for (int i = 0; i < cnt; ++i) { + if (GPUtils::canOpen(std::string(thermal_path[i]) + "/thermal_zone1/temp")) { + thermal_base_path = std::string(thermal_path[i]); + init_thermal_node(); + } + } +} + +void Temperature::init_thermal_node() +{ + char typeNode[256]; + char tempNode[256]; + char buffer[256]; + FILE *fp = nullptr; + const int zoneTravelNum = 100; + for (int zone = 0; zone < zoneTravelNum; ++zone) { + if (snprintf_s(typeNode, sizeof(typeNode), sizeof(typeNode), "%s/thermal_zone%d/type", + thermal_base_path.c_str(), zone) < 0) { + std::cout << "snprintf_s fail"; + } + if (access(typeNode, F_OK) == -1) { + continue; + } + fp = fopen(typeNode, "r"); + if (fp == nullptr) { + continue; + } + buffer[0] = '\0'; + while (fgets(buffer, sizeof(buffer), fp) == nullptr) { + std::cout << "fgets fail"; + } + if (fclose(fp) == EOF) { + std::cout << "fclose fail"; + } + + if (strlen(buffer) == 0) { + continue; + } + + std::string type = std::string(buffer); + if (collect_nodes.count(type) == 0) { + continue; + } + if (snprintf_s(tempNode, sizeof(tempNode), sizeof(tempNode), "%s/thermal_zone%d/temp", + thermal_base_path.c_str(), zone) < 0) { + std::cout << "snprintf_s fail"; + } + thermal_node_path_map[type] = std::string(tempNode); + } +} + +std::map Temperature::getThermalMap() +{ + std::map thermal_map; + + FILE *fp = nullptr; + char buffer[256]; + std::map::iterator iter; + for (iter = thermal_node_path_map.begin(); iter != thermal_node_path_map.end(); ++iter) { + std::string type = iter->first; + std::string tempNode = thermal_node_path_map[type]; + fp = fopen(tempNode.c_str(), "r"); + if (fp == nullptr) { + thermal_map[type] = -1.0f; + continue; + } + buffer[0] = '\0'; + while (fgets(buffer, sizeof(buffer), fp) == nullptr) { + std::cout << "fgets fail"; + } + float temp = std::fabs(atof(buffer)); + if (fclose(fp) == EOF) { + std::cout << "fclose fail"; + } + if (strlen(buffer) == 0) { + thermal_map[type] = -1.0f; + continue; + } + thermal_map[type] = temp; + } + return thermal_map; +} +} +} diff --git a/device/device_command/gp_utils.cpp b/device/device_command/gp_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e2954eecb97db6600e0058601a4c598bc991a8df --- /dev/null +++ b/device/device_command/gp_utils.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include "include/gp_utils.h" + +namespace OHOS { + namespace SmartPerf { + void GPUtils::mSplit(const std::string &content, const std::string &sp, std::vector &out) + { + size_t index = 0; + while (index != std::string::npos) { + size_t t_end = content.find_first_of(sp, index); + std::string tmp = content.substr(index, t_end - index); + if (tmp != "" && tmp != " ") { + out.push_back(tmp); + } + if (t_end == std::string::npos) { + break; + } + index = t_end + 1; + } + } + + bool GPUtils::canOpen(const std::string &path) + { + if (access(path.c_str(), F_OK) == -1) { + return false; + } + FILE *fp = fopen(path.c_str(), "r"); + if (fp == nullptr) { + return false; + } + if (fclose(fp) == EOF) { + return false; + } + return true; + } + + // popen + std::string GPUtils::readFile(const std::string &cmd) + { + const int buffLengh = 1024; + std::string res = "NA"; + FILE *fp = popen(cmd.c_str(), "r"); + char line[buffLengh]; + line[0] = '\0'; + while (fgets(line, buffLengh, fp) != nullptr) { + res = std::string(line); + } + + if (pclose(fp) == EOF) { + return ""; + } + return res; + } + + // fopen + std::string GPUtils::freadFile(const std::string &path) + { + std::string res = "NA"; + const int buffLengh = 1024; + if (access(path.c_str(), F_OK) == -1) { + return res; + } + FILE *fp; + if ((fp = fopen(path.c_str(), "r")) != nullptr) { + char s[buffLengh]; + s[0] = '\0'; + while (fgets(s, sizeof(s), fp) != nullptr) { + res += std::string(s); + } + } + if (fp != nullptr) { + fclose(fp); + } + return res; + } + + // get number_str from str + std::string GPUtils::getNumber(const std::string &str) + { + int cntInt = 0; + const int shift = 10; + + for (int i = 0; str[i] != '\0'; ++i) { + if (str[i] >= '0' && str[i] <= '9') { + cntInt *= shift; + cntInt += str[i] - '0'; + } + } + return std::to_string(cntInt); + } + + // wirte to csv by path + void GPUtils::writeCsv(const std::string &path, std::vector &vmap) + { + std::ofstream outFile; + char realPath[PATH_MAX + 1] = {0x00}; + if (strlen(path.c_str()) > PATH_MAX || realpath(path.c_str(), realPath) == NULL) { + return; + } + + outFile.open(path.c_str(), std::ios::out); + int i = 0; + std::string title = ""; + for (GPData gpdata : vmap) { + std::map::iterator iter; + std::string line_content = ""; + for (iter = gpdata.values.begin(); iter != gpdata.values.end(); ++iter) { + if (i == 0) { + title += iter->first + ","; + } + line_content += iter->second + ","; + } + if (i == 0) { + title.pop_back(); + outFile << title << std::endl; + } + line_content.pop_back(); + outFile << line_content << std::endl; + ++i; + } + outFile.close(); + } + } +} diff --git a/device/device_command/include/ByTrace.h b/device/device_command/include/ByTrace.h new file mode 100644 index 0000000000000000000000000000000000000000..1a451f9f21bf7eb6372f19dc3b4bedb6bd181efd --- /dev/null +++ b/device/device_command/include/ByTrace.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef BY_TRACE_H +#define BY_TRACE_H +#include "gp_utils.h" +#include "singleton.h" +namespace OHOS { +namespace SmartPerf { +enum class TraceStatus { + TRACE_START, + TRACE_FINISH, + TRACE_NO +}; +class ByTrace : public DelayedSingleton { +public: + // 开始抓trace线程 + void thread_get_trace(); + // 结束抓trace线程 + void thread_finish_trace(std::string &pathName); + // 初始化抓取 + TraceStatus init_trace(bool isStart); + // 校验fps-jitters + TraceStatus check_fps_jitters(std::vector jitters, int curProfilerNum); + // 抓trace总次数 默认2次 + int sum = 2; + // 当前触发的次数 + int curNum = 0; + +private: + // 抓trace间隔 默认60s + int interval = 60; + // 当前触发标记次数 + int flagProfilerNum = -1; + // 抓trace触发条件:默认 某一帧的某个jitter>100 ms触发 + long long threshold = 100; +}; +} +} +#endif \ No newline at end of file diff --git a/device/device_command/include/CPU.h b/device/device_command/include/CPU.h new file mode 100644 index 0000000000000000000000000000000000000000..e6172a3790a2b3019ba8550b8e84579cea50ae90 --- /dev/null +++ b/device/device_command/include/CPU.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef CPU_H +#define CPU_H +#include +#include +#include +#include "gp_utils.h" +#include "singleton.h" + + +namespace OHOS { +namespace SmartPerf { +class CPU : public DelayedSingleton { +public: + int get_cpu_num(); + int get_cpu_freq(int cpu_id); + std::vector get_cpu_load(); + +private: + + const std::string CPU_BASE_PATH = "/sys/devices/system/cpu"; + const std::string PROC_STAT = "/proc/stat"; + inline const std::string CPU_SCALING_CUR_FREQ(int CPUID) + { + return CPU_BASE_PATH + "/cpu" + std::to_string(CPUID) + "/cpufreq/scaling_cur_freq"; + } + inline const std::string CPU_SCALING_MAX_FREQ(int CPUID) + { + return CPU_BASE_PATH + "/cpu" + std::to_string(CPUID) + "/cpufreq/scaling_max_freq"; + } + inline const std::string CPU_SCALING_MIN_FREQ(int CPUID) + { + return CPU_BASE_PATH + "/cpu" + std::to_string(CPUID) + "/cpufreq/scaling_min_freq"; + } + inline const std::string CPUINFO_MAX_FREQ(int CPUID) + { + return CPU_BASE_PATH + "/cpu" + std::to_string(CPUID) + "/cpufreq/cpuinfo_max_freq"; + } + inline const std::string CPUINFO_MIN_FREQ(int CPUID) + { + return CPU_BASE_PATH + "/cpu" + std::to_string(CPUID) + "/cpufreq/cpuinfo_min_freq"; + } + + int m_cpu_num; + float cac_workload(const char *buffer, const char *pre_buffer); +}; +} +} +#endif \ No newline at end of file diff --git a/device/device_command/include/DDR.h b/device/device_command/include/DDR.h new file mode 100644 index 0000000000000000000000000000000000000000..434b67bcc9adabc552ffb87c649578a53ed023e0 --- /dev/null +++ b/device/device_command/include/DDR.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef DDR_H +#define DDR_H + +#include +#include +#include +#include "gp_utils.h" +#include "singleton.h" +namespace OHOS { +namespace SmartPerf { +class DDR : public DelayedSingleton { +public: + static constexpr const char *DDR_CUR_FREQ_PATH[] = { + "/sys/class/devfreq/ddrfreq/cur_freq", + }; + static constexpr const char *DDR_AVAILABLE_FREQ_PATH[] = { + "/sys/class/devfreq/ddrfreq/available_frequencies", + }; + long long get_ddr_freq(); + +private: + std::string ddr_cur_freq_path; +}; +}; +} +#endif diff --git a/device/device_command/include/FPS.h b/device/device_command/include/FPS.h new file mode 100644 index 0000000000000000000000000000000000000000..38cdd08e93d37bbb6523f77bcc913f4c41a16c37 --- /dev/null +++ b/device/device_command/include/FPS.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FPS_H +#define FPS_H + +#include +#include +#include +#include +#include "gp_utils.h" +#include "singleton.h" +namespace OHOS { +namespace SmartPerf { +struct FpsInfo { + int fps; + int pre_fps; + std::vector jitters; + std::queue time_stamp_q; + long long last_frame_ready_time; + long long current_fps_time; + FpsInfo() + { + fps = 0; + pre_fps = 0; + last_frame_ready_time = 0; + current_fps_time = 0; + } +}; +class FPS : public DelayedSingleton { +public: + void setPackageName(std::string pkgName); + FpsInfo getFpsInfo(int is_video, int is_camera); + FpsInfo m_fpsInfo; +private: + std::string pkg_name; + std::string cur_layer_name; + FpsInfo GetSurfaceFrame(std::string name); +}; +} +} +#endif diff --git a/device/device_command/include/GPU.h b/device/device_command/include/GPU.h new file mode 100644 index 0000000000000000000000000000000000000000..aedcb970d8466074cb64e4e81985fcf92c9c5c57 --- /dev/null +++ b/device/device_command/include/GPU.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GPU_H +#define GPU_H +#include +#include +#include +#include "gp_utils.h" +#include "singleton.h" + +namespace OHOS { +namespace SmartPerf { +class GPU : public DelayedSingleton { +public: + static constexpr const char *GPU_CUR_FREQ_PATH[] = { + "/sys/class/devfreq/fde60000.gpu/cur_freq", // rk3568 + "/sys/class/devfreq/gpufreq/cur_freq", // wgr + }; + static constexpr const char *GPU_CUR_WORKLOAD_PATH[] = { + "/sys/class/devfreq/gpufreq/gpu_scene_aware/utilisation", // wgr + "/sys/class/devfreq/fde60000.gpu/load", // rk3568 + }; + int get_gpu_freq(); + float get_gpu_load(); + void init_gpu_node(); +private: + std::string gpu_cur_freq_path; + std::string gpu_cur_load_path; + float calc_workload(const char *buffer) const; +}; +} +} +#endif // GPU_H diff --git a/device/device_command/include/Power.h b/device/device_command/include/Power.h new file mode 100644 index 0000000000000000000000000000000000000000..286f4ba63f641948c0f05132c52d63c5139f42c9 --- /dev/null +++ b/device/device_command/include/Power.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef POWER_H +#define POWER_H + +#include +#include +#include +#include "singleton.h" +namespace OHOS { +namespace SmartPerf { +class Power : public DelayedSingleton { +public: + static constexpr const char *power_path[] = { + "/sys/class/power_supply/battery", + "/sys/class/power_supply/Battery", + "/data/local/tmp/battery" + }; + + static constexpr const char *default_collect_power_info[] = { + "current_now", + "voltage_now", + }; + std::map getPowerMap(); + void init_power(); +private: + std::string power_base_path; + std::map power_node_path_map; +}; +} +} +#endif diff --git a/device/device_command/include/RAM.h b/device/device_command/include/RAM.h new file mode 100644 index 0000000000000000000000000000000000000000..f880185b856efc902a6fe60dc270888a5c05e40a --- /dev/null +++ b/device/device_command/include/RAM.h @@ -0,0 +1,32 @@ +/* +* Copyright (C) 2021 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef RAM_H +#define RAM_H +#include +#include +#include "singleton.h" + +namespace OHOS { + namespace SmartPerf { + class RAM : public DelayedSingleton { + public: + void setPkgName(std::string ss); + std::map getRamInfo(std::string pkg_name, int pid); + private: + std::string pkgName; + }; + } +} +#endif diff --git a/device/device_command/include/Temperature.h b/device/device_command/include/Temperature.h new file mode 100644 index 0000000000000000000000000000000000000000..df5935a26ac72e6d6be75f14c5231ac1847f6214 --- /dev/null +++ b/device/device_command/include/Temperature.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef TEMPERATURE_H +#define TEMPERATURE_H + +#include +#include +#include +#include +#include "gp_utils.h" +#include "singleton.h" +namespace OHOS { +namespace SmartPerf { +class Temperature : public DelayedSingleton { +public: + static constexpr const char *thermal_path[] = { + "/sys/devices/virtual/thermal", + "/sys/class/thermal" + }; + const std::map collect_nodes = { + { "soc_thermal", "soc_thermal" }, { "system_h", "system_h" }, { "soc-thermal", "soc-thermal" }, + { "gpu-thermal", "gpu-thermal" }, { "shell_frame", "shell_frame" }, { "shell_front", "shell_front" }, + { "shell_back", "shell_back" } + }; + std::map getThermalMap(); + void init_thermal_node(); + void init_temperature(); +private: + std::string thermal_base_path; + std::map thermal_node_path_map; +}; +} +} +#endif \ No newline at end of file diff --git a/device/device_command/include/gp_constant.h b/device/device_command/include/gp_constant.h new file mode 100644 index 0000000000000000000000000000000000000000..ca085571336dd8a7066607a2cd617b14f9c6d145 --- /dev/null +++ b/device/device_command/include/gp_constant.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef GP_CONSTANT_H +#define GP_CONSTANT_H +enum NumberConstant { + ZERO = 0X00, + ONE = 0X01, + TWO = 0X02, + THREE = 0X03 +}; +enum FunConstant { + SUCCESS_ONE = 0X01, + SUCCESS_ZERO = 0X00, + ERROR_ZERO = 0X00, + ERROR_MINUX = 0xFFFFFFFF +}; +#endif \ No newline at end of file diff --git a/device/device_command/include/gp_data.h b/device/device_command/include/gp_data.h new file mode 100644 index 0000000000000000000000000000000000000000..05c939bfe63cacdf68dac7b9813d88cfac2ca375 --- /dev/null +++ b/device/device_command/include/gp_data.h @@ -0,0 +1,23 @@ +/* +* Copyright (C) 2021 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef GPDATA_H +#define GPDATA_H +#include + +class GPData { +public: + std::map values; +}; +#endif \ No newline at end of file diff --git a/device/device_command/include/gp_utils.h b/device/device_command/include/gp_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..37b06507a7f6a7515ada47dab619bd35d31e38af --- /dev/null +++ b/device/device_command/include/gp_utils.h @@ -0,0 +1,38 @@ +/* +* Copyright (C) 2021 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef GP_UTILS_H +#define GP_UTILS_H +#include +#include +#include "gp_data.h" +namespace OHOS { + namespace SmartPerf { + namespace GPUtils { + void mSplit(const std::string &content, const std::string &sp, std::vector &out); + + bool canOpen(const std::string &path); + + std::string readFile(const std::string &cmd); + + std::string freadFile(const std::string &path); + + std::string getNumber(const std::string &str); + + void writeCsv(const std::string &path, std::vector &vmap); + }; + } +} + +#endif // GP_UTILS_H diff --git a/device/device_command/include/profiler.h b/device/device_command/include/profiler.h new file mode 100644 index 0000000000000000000000000000000000000000..c5db299be537608cf5f3f1dcca80c6615c012c6a --- /dev/null +++ b/device/device_command/include/profiler.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef PROFILER_H +#define PROFILER_H +#include +#include +#include "CPU.h" +#include "GPU.h" +#include "DDR.h" +#include "FPS.h" +#include "RAM.h" +#include "Temperature.h" +#include "Power.h" +#include "ByTrace.h" +#include "gp_data.h" + +namespace OHOS { +namespace SmartPerf { +class Profiler : public DelayedSingleton{ +public: + void initProfiler(); + void createCpu(std::map &gpMap); + void createGpu(std::map &gpMap); + void createDdr(std::map &gpMap); + void createFps(int isVideo, int isCamera, int isCatchTrace, int curProfilerNum, + std::map &gpMap); + void createTemp(std::map &gpMap); + void createPower(std::map &gpMap); + void createRam(const std::string &pkg_name, std::map &gpMap, int pid); + void createSnapshot(std::map &gpMap, long long timestamp); + std::shared_ptr mCpu = nullptr; + std::shared_ptr mGpu = nullptr; + std::shared_ptr mDdr = nullptr; + std::shared_ptr mFps = nullptr; + std::shared_ptr mRam = nullptr; + std::shared_ptr mTemperature = nullptr; + std::shared_ptr mPower = nullptr; + std::shared_ptr mByTrace = nullptr; +}; +} +} +#endif \ No newline at end of file diff --git a/device/device_command/include/smartperf_command.h b/device/device_command/include/smartperf_command.h new file mode 100644 index 0000000000000000000000000000000000000000..f8453ff1002e4fc8793a2d4520bcd01645e42dc1 --- /dev/null +++ b/device/device_command/include/smartperf_command.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SMARTPERF_COMMAND_H +#define SMARTPERF_COMMAND_H + +#include +#include +#include "profiler.h" +#include "socket_profiler.h" +namespace OHOS { + namespace SmartPerf { + class SmartPerfCommand { + public: + const std::string SmartPerf_EXE_NAME = "SP_daemon"; + const std::string SmartPerf_VERSION = "1.0.1\n"; + const std::string SmartPerf_MSG_ERR = "error input!\n use command '--help' get more information\n"; + const std::string SmartPerf_MSG = "usage: SP_daemon \n" + "--------------------------------------------------------------------\n" + "These are common commands list:\n" + " -N set num of profiler \n" + " -PKG set pkgname of profiler \n" + " -PID set process id of profiler \n" + " -OUT set output path of CSV\n" + " -c get cpuFreq and cpuLoad \n" + " -g get gpuFreq and gpuLoad \n" + " -f get fps and fps jitters \n" + " -t get soc-temp gpu-temp .. \n" + " -p get current_now and voltage_now \n" + " -r get ram(pss) \n" + " -snapshot get screen capture\n" + "--------------------------------------------------------------------\n" + "Example: SP_daemon -N 20 -PKG ohos.samples.ecg -c -g -t -p -f \n" + "--------------------------------------------------------------------\n"; + const int ONE_PARAM = 1; + const int TWO_PARAM = 2; + const int THREE_PARAM_MORE = 3; + SmartPerfCommand(int argc, char *argv[]); + ~SmartPerfCommand() {}; + void initSomething(); + std::string ExecCommand(); + // 采集次数 + int num = 0; + // 包名 + std::string pkgName = ""; + // 是否开启trace 抓取 + int trace = 0; + // csv输出路径 + std::string outPath = "/data/local/tmp/data.csv"; + std::string outPathParam = ""; + // 指定进程pid + int pid = 0; + // 采集配置项 + std::vector configs; + // 命令式采集 + std::shared_ptr profiler = nullptr; + // Socket采集 + std::shared_ptr socketProfiler = nullptr; + }; + } +} +#endif // SMARTPERF_COMMAND_H \ No newline at end of file diff --git a/device/device_command/include/socket_profiler.h b/device/device_command/include/socket_profiler.h new file mode 100644 index 0000000000000000000000000000000000000000..84a91f5986f12b3e66297f8c4fe10082555c1b66 --- /dev/null +++ b/device/device_command/include/socket_profiler.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SOCKET_PROFILER_H +#define SOCKET_PROFILER_H +#include +#include +#include "CPU.h" +#include "GPU.h" +#include "DDR.h" +#include "FPS.h" +#include "RAM.h" +#include "Temperature.h" +#include "Power.h" +#include "ByTrace.h" +namespace OHOS { +namespace SmartPerf { +class SocketProfiler : public DelayedSingleton { +public: + void initSocketProfiler(); + void bufsendto(int sockLocal, const char *bufsend, int length, struct sockaddr *clientLocal, socklen_t len); + void callSend(std::stringstream &sstream, std::string &str1, std::string &str2); + void thread_udp_server(); + void initSocket(); + + std::shared_ptr mCpu = nullptr; + std::shared_ptr mGpu = nullptr; + std::shared_ptr mDdr = nullptr; + std::shared_ptr mFps = nullptr; + std::shared_ptr mRam = nullptr; + std::shared_ptr mTemperature = nullptr; + std::shared_ptr mPower = nullptr; + std::shared_ptr mByTrace = nullptr; + + int sock; + struct sockaddr_in local; + struct sockaddr_in client; + const size_t SOCK_PORT = 8283; + const size_t BUFF_SIZE_RECV = 256; + const size_t BUFF_SIZE_SEND = 2048; + +}; +} +} +#endif \ No newline at end of file diff --git a/device/device_command/profiler.cpp b/device/device_command/profiler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..62cf658f281abc283f32748e9659ce0c1f3bc660 --- /dev/null +++ b/device/device_command/profiler.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include "securec.h" +#include "include/profiler.h" +namespace OHOS { +namespace SmartPerf { +void Profiler::initProfiler() +{ + // get singleton instance + mCpu = CPU::GetInstance(); + mGpu = GPU::GetInstance(); + mDdr = DDR::GetInstance(); + mFps = FPS::GetInstance(); + mRam = RAM::GetInstance(); + mTemperature = Temperature::GetInstance(); + mPower = Power::GetInstance(); + mByTrace = ByTrace::GetInstance(); + + // some init methods + mTemperature->init_temperature(); + mGpu->init_gpu_node(); + mPower->init_power(); + if (mByTrace->init_trace(true) == TraceStatus::TRACE_START) { + std::thread pInitTrace(&ByTrace::thread_get_trace, mByTrace); + } +} + +void Profiler::createCpu(std::map &gpMap) +{ + int cpuCoreNum = mCpu->get_cpu_num(); + for (int i = 0; i < cpuCoreNum; i++) { + int curFreq = mCpu->get_cpu_freq(i); + char desc[10]; + if (snprintf_s(desc, sizeof(desc), sizeof(desc), "cpu%dfreq", i) > 0) { + gpMap.insert(std::pair(std::string(desc), std::to_string(curFreq))); + } + } + + std::vector workloads = mCpu->get_cpu_load(); + + for (size_t i = 1; i < workloads.size(); ++i) { + char desc[10]; + if (snprintf_s(desc, sizeof(desc), sizeof(desc), "cpu%dload", i - 1) > 0) { + gpMap.insert(std::pair(std::string(desc), std::to_string(workloads[i]))); + } + } +} +void Profiler::createGpu(std::map &gpMap) +{ + int ret = mGpu->get_gpu_freq(); + float workload = mGpu->get_gpu_load(); + char desc[10]; + if (snprintf_s(desc, sizeof(desc), sizeof(desc), "gpufreq") > 0) { + gpMap.insert(std::pair(std::string(desc), std::to_string(ret))); + } + if (snprintf_s(desc, sizeof(desc), sizeof(desc), "gpuload") > 0) { + gpMap.insert(std::pair(std::string(desc), std::to_string(workload))); + } +} +void Profiler::createDdr(std::map &gpMap) +{ + long long ret = mDdr->get_ddr_freq(); + char desc[10]; + if (snprintf_s(desc, sizeof(desc), sizeof(desc), "ddrfreq") > 0) { + gpMap.insert(std::pair(std::string(desc), std::to_string(ret))); + } +} +void Profiler::createFps(int isVideo, int isCamera, int isCatchTrace, int curProfilerNum, + std::map &gpMap) +{ + FpsInfo gfpsInfo = mFps->getFpsInfo(isVideo, isCamera); + char desc[10]; + if (snprintf_s(desc, sizeof(desc), sizeof(desc), "fps") > 0) { + gpMap.insert(std::pair(std::string(desc), std::to_string(gfpsInfo.fps))); + } + if (isCatchTrace > 0) { + if (mByTrace->check_fps_jitters(gfpsInfo.jitters, curProfilerNum) == TraceStatus::TRACE_FINISH) { + std::string profilerNum = std::to_string(curProfilerNum); + std::thread pFinishTrace(&ByTrace::thread_finish_trace, mByTrace, std::ref(profilerNum)); + } + } +} +void Profiler::createTemp(std::map &gpMap) +{ + std::map tempInfo = mTemperature->getThermalMap(); + std::map::iterator iter; + for (iter = tempInfo.begin(); iter != tempInfo.end(); ++iter) { + float value = iter->second; + gpMap.insert(std::pair(iter->first, std::to_string(value))); + } +} +void Profiler::createPower(std::map &gpMap) +{ + std::map powerInfo; + powerInfo = mPower->getPowerMap(); + std::map::iterator iter; + for (iter = powerInfo.begin(); iter != powerInfo.end(); ++iter) { + gpMap.insert(std::pair(iter->first, iter->second)); + } +} +void Profiler::createRam(const std::string &pkg_name, std::map &gpMap, int pid) +{ + std::map gramInfo; + gramInfo = mRam->getRamInfo(pkg_name, pid); + std::map::iterator iter; + for (iter = gramInfo.begin(); iter != gramInfo.end(); ++iter) { + gpMap.insert(std::pair(iter->first, iter->second)); + } +} +void Profiler::createSnapshot(std::map &gpMap, long long timestamp) +{ + char pathstr[50]; + std::string path; + if (snprintf_s(pathstr, sizeof(pathstr), sizeof(pathstr), "/data/local/tmp/capture/%lld", timestamp) > 0) { + path = pathstr; + } + char cmdCapture[100]; + if (snprintf_s(cmdCapture, sizeof(cmdCapture), sizeof(cmdCapture), + "snapshot_display -f /data/local/tmp/capture/%lld.png", timestamp) > 0) { + GPUtils::readFile(cmdCapture); + } + gpMap.insert(std::pair(std::string("snapshotPath"), path)); +} +} +} \ No newline at end of file diff --git a/device/device_command/smartperf_command.cpp b/device/device_command/smartperf_command.cpp new file mode 100644 index 0000000000000000000000000000000000000000..20cc47975a97b577398ef7e68e2f3e532c42cee2 --- /dev/null +++ b/device/device_command/smartperf_command.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include "sys/time.h" +#include "unistd.h" +#include "include/gp_data.h" +#include "include/gp_utils.h" +#include "include/smartperf_command.h" + +namespace OHOS { +namespace SmartPerf { +SmartPerfCommand::SmartPerfCommand(int argc, char *argv[]) +{ + if (argc == ONE_PARAM) { + socketProfiler = SocketProfiler::GetInstance(); + socketProfiler->initSocketProfiler(); + daemon(0, 0); + std::thread t_udp(&SocketProfiler::thread_udp_server, socketProfiler); + t_udp.join(); + } + if (argc == TWO_PARAM) { + char *cmd = argv[1]; + if (strcmp(cmd, "--help") == 0 || strcmp(cmd, "-h") == 0) { + std::cout << SmartPerf_MSG; + } else if (strcmp(cmd, "--version") == 0) { + std::cout << SmartPerf_VERSION; + } else { + std::cout << SmartPerf_MSG_ERR; + } + } + if (argc >= THREE_PARAM_MORE) { + profiler = Profiler::GetInstance(); + profiler->initProfiler(); + for (int i = 1; i <= argc - 1; i++) { + if ((strcmp(argv[i], "-N") == 0) || (strcmp(argv[i], "--num") == 0)) { + num = atoi(argv[i + 1]); + if (num > 0) { + std::cout << "set num:" << num << std::endl; + } else { + std::cout << "error input args: -N" << std::endl; + } + } + if ((strcmp(argv[i], "-PKG") == 0) || (strcmp(argv[i], "--pkgname") == 0)) { + pkgName = argv[i + 1]; + if (strcmp(pkgName.c_str(), "") != 0) { + profiler->mFps->setPackageName(pkgName); + std::cout << "set pkg name:" << pkgName << std::endl; + } else { + std::cout << "empty input args: -PKG" << std::endl; + } + } + if ((strcmp(argv[i], "-PID") == 0) || (strcmp(argv[i], "--processid") == 0)) { + pid = atoi(argv[i + 1]); + if (pid > 0) { + std::cout << "set test pid:" << pid << std::endl; + } else { + std::cout << "error input args: -PID " << std::endl; + } + } + + if ((strcmp(argv[i], "-OUT") == 0) || (strcmp(argv[i], "--output") == 0)) { + outPathParam = argv[i + 1]; + if (strcmp(outPathParam.c_str(), "") != 0) { + outPath = outPathParam + std::string(".csv"); + } + } + + if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "-d") == 0 || + strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "-f1") == 0 || strcmp(argv[i], "-f2") == 0 || + strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "-r") == 0 || + strcmp(argv[i], "-trace") == 0 || strcmp(argv[i], "-snapshot") == 0) { + configs.push_back(argv[i]); + } + } + } +} +std::string SmartPerfCommand::ExecCommand() +{ + int index = 0; + std::vector vmap; + while (index < num) { + std::map gpMap; + struct timeval tv; + gettimeofday(&tv, nullptr); + long long timestamp = tv.tv_sec * 1000 + tv.tv_usec / 1000; + gpMap.insert(std::pair(std::string("timestamp"), std::to_string(timestamp))); + + for (size_t j = 0; j < configs.size(); j++) { + std::string curParam = configs[j]; + if (strcmp(curParam.c_str(), "-trace") == 0) { + trace = 1; + } + if (strcmp(curParam.c_str(), "-c") == 0) { + profiler->createCpu(gpMap); + } + if (strcmp(curParam.c_str(), "-g") == 0) { + profiler->createGpu(gpMap); + } + if (strcmp(curParam.c_str(), "-d") == 0) { + profiler->createDdr(gpMap); + } + if (strcmp(curParam.c_str(), "-f") == 0) { + profiler->createFps(0, 0, trace, index, gpMap); + } + if (strcmp(curParam.c_str(), "-f1") == 0) { + profiler->createFps(1, 0, trace, index, gpMap); + } + if (strcmp(curParam.c_str(), "-f2") == 0) { + profiler->createFps(0, 1, trace, index, gpMap); + } + if (strcmp(curParam.c_str(), "-t") == 0) { + profiler->createTemp(gpMap); + } + if (strcmp(curParam.c_str(), "-p") == 0) { + profiler->createPower(gpMap); + } + if (strcmp(curParam.c_str(), "-r") == 0) { + if (strcmp(pkgName.c_str(), "") != 0 || pid > 0) { + profiler->createRam(pkgName, gpMap, pid); + } + } + if (strcmp(curParam.c_str(), "-snapshot") == 0) { + profiler->createSnapshot(gpMap, timestamp); + } + } + + printf("----------------------------------Print START------------------------------------\n"); + std::map::iterator iter; + int i = 0; + for (iter = gpMap.begin(); iter != gpMap.end(); ++iter) { + printf("order:%d %s=%s\n", i, iter->first.c_str(), iter->second.c_str()); + i++; + } + printf("----------------------------------Print END--------------------------------------\n"); + + GPData gpdata; + gpdata.values = gpMap; + vmap.push_back(gpdata); + sleep(1); + index++; + } + + GPUtils::writeCsv(std::string(outPath.c_str()), vmap); + + return std::string("command exec finished!"); +} +void SmartPerfCommand::initSomething() +{ + GPUtils::readFile("chmod a+w /proc/stat"); +} +} +} diff --git a/device/device_command/smartperf_main.cpp b/device/device_command/smartperf_main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fcca632c1367101820c8c81248619a6ba0714ca0 --- /dev/null +++ b/device/device_command/smartperf_main.cpp @@ -0,0 +1,24 @@ +/* +* Copyright (C) 2021 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "include/smartperf_command.h" + +int main(int argc, char *argv[]) +{ + OHOS::SmartPerf::SmartPerfCommand cmd(argc, argv); + cmd.initSomething(); + std::cout << cmd.ExecCommand() << std::endl; + return 0; +} diff --git a/device/device_command/socket_profiler.cpp b/device/device_command/socket_profiler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..08cb87c02566a3f119806341af0d498b5bdcea71 --- /dev/null +++ b/device/device_command/socket_profiler.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include "include/gp_utils.h" +#include "include/socket_profiler.h" +namespace OHOS { +namespace SmartPerf { +void SocketProfiler::initSocketProfiler() +{ + mCpu = CPU::GetInstance(); + mGpu = GPU::GetInstance(); + mDdr = DDR::GetInstance(); + mFps = FPS::GetInstance(); + mRam = RAM::GetInstance(); + mTemperature = Temperature::GetInstance(); + mPower = Power::GetInstance(); + mByTrace = ByTrace::GetInstance(); + + mTemperature->init_temperature(); + mGpu->init_gpu_node(); + mPower->init_power(); +} + +void SocketProfiler::bufsendto(int sockLocal, const char *bufsend, int length, + struct sockaddr *clientLocal, socklen_t len) +{ + ssize_t echo_size = sendto(sockLocal, bufsend, length, 0, clientLocal, len); + if (echo_size < 0) { + printf("sendto error, buf is %s\n", bufsend); + } +} + +void SocketProfiler::callSend(std::stringstream &sstream, std::string &str1, std::string &str2) +{ + sstream.str(""); + sstream.clear(); + sstream << str1 << "::" << str2; + std::string streamSend = sstream.str(); + bufsendto(sock, streamSend.c_str(), streamSend.size(), + reinterpret_cast(&client), sizeof(sockaddr_in)); +} + +void SocketProfiler::initSocket() +{ + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + perror("socket error"); + } + local.sin_family = AF_INET; + local.sin_port = htons(SOCK_PORT); + local.sin_addr.s_addr = htonl(INADDR_ANY); + if (::bind(sock, reinterpret_cast(&local), sizeof(local)) < 0) { + perror("bind error"); + } +} + +void SocketProfiler::thread_udp_server() +{ + std::shared_ptr SP = SocketProfiler::GetInstance(); + SP->initSocket(); + socklen_t len = sizeof(sockaddr_in); + std::stringstream sstream; + const int loopforever = 1; + printf("enter while loop forever\n"); + while (loopforever) { + char recvbuf[BUFF_SIZE_RECV]; + recvbuf[0] = '\0'; + ssize_t _size = recvfrom(sock, recvbuf, sizeof(recvbuf) - 1, 0, + reinterpret_cast(&client), &len); + if (_size > 0) { + recvbuf[_size] = '\0'; + printf("server recvbuf:%s\n", recvbuf); + } + sstream.str(""); + sstream.clear(); + std::string recv = std::string(recvbuf); + if (recv.find("get_cpu_num") != std::string::npos) { + std::string recvStr = "get_cpu_num"; + int ret = SP->mCpu->get_cpu_num(); + std::string str2 = std::to_string(ret); + SP->callSend(sstream, recvStr, str2); + } else if (recv.find("get_cpu_freq") != std::string::npos) { + std::vector sps; + GPUtils::mSplit(recv, "_", sps); + int cpu_id = std::stoi(sps[sps.size() - 1]); + int ret = SP->mCpu->get_cpu_freq(cpu_id); + std::string str2 = std::to_string(ret); + SP->callSend(sstream, recv, str2); + } else if (recv.find("get_cpu_load") != std::string::npos) { + std::vector workloads = SP->mCpu->get_cpu_load(); + std::string res = ""; + for (size_t i = 0; i < workloads.size(); ++i) { + if (i != 0) { + res += "=="; + } + res += std::to_string(workloads[i]); + } + SP->callSend(sstream, recv, res); + } else if (recv.find("set_pkgName") != std::string::npos) { + std::vector sps; + GPUtils::mSplit(recv, "::", sps); + if (sps.size() > 1) { + SP->mFps->setPackageName(sps[1]); + SP->mRam->setPkgName(sps[1]); + } + } else if (recv.find("get_fps_and_jitters") != std::string::npos) { + std::vector sps; + GPUtils::mSplit(recv, "::", sps); + if (sps.size() > 2) { + int is_video = atoi(sps[1].c_str()); + int is_camera = atoi(sps[2].c_str()); + + FpsInfo gfpsInfo = SP->mFps->getFpsInfo(is_video, is_camera); + std::string res = ""; + res += "timestamp|"; + res += std::to_string(gfpsInfo.current_fps_time); + res += ";"; + res += "fps|"; + res += std::to_string(gfpsInfo.fps); + res += ";"; + res += "jitter|"; + for (size_t i = 0; i < gfpsInfo.jitters.size(); ++i) { + res += std::to_string(gfpsInfo.jitters[i]); + res += "=="; + } + std::string recvStr = "get_fps_and_jitters"; + SP->callSend(sstream, recvStr, res); + } + } else if (recv.find("get_gpu_freq") != std::string::npos) { + int ret = SP->mGpu->get_gpu_freq(); + std::string str2 = std::to_string(ret); + SP->callSend(sstream, recv, str2); + } else if (recv.find("get_gpu_load") != std::string::npos) { + float workload = SP->mGpu->get_gpu_load(); + std::string str2 = std::to_string(workload); + SP->callSend(sstream, recv, str2); + } else if (recv.find("get_ddr_freq") != std::string::npos) { + long long ret = SP->mDdr->get_ddr_freq(); + std::string str2 = std::to_string(ret); + SP->callSend(sstream, recv, str2); + } else if (recv.find("get_ram_info") != std::string::npos) { + std::vector sps; + GPUtils::mSplit(recv, "::", sps); + if (sps.size() > 1) { + std::map gramInfo = SP->mRam->getRamInfo(sps[1], 0); + std::string res = "Pss"; + std::map::iterator iter; + int i = 0; + for (iter = gramInfo.begin(); iter != gramInfo.end(); ++iter) { + if (i != 0) + res += "=="; + res += iter->second; + ++i; + } + SP->callSend(sstream, sps[0], res); + } + } else if (recv.find("get_temperature") != std::string::npos) { + std::map tempInfo = SP->mTemperature->getThermalMap(); + std::string res = ""; + std::map::iterator iter; + int i = 0; + for (iter = tempInfo.begin(); iter != tempInfo.end(); ++iter) { + if (i != 0) { + res += "=="; + } + res += (iter->first + ",," + std::to_string(iter->second)); + ++i; + } + SP->callSend(sstream, recv, res); + } else if (recv.find("get_power") != std::string::npos) { + std::map powerInfo; + powerInfo = SP->mPower->getPowerMap(); + std::string res = ""; + std::map::iterator iter; + int i = 0; + for (iter = powerInfo.begin(); iter != powerInfo.end(); ++iter) { + if (i != 0) { + res += "=="; + } + res += (iter->first + ",," + iter->second); + ++i; + } + SP->callSend(sstream, recv, res); + } else if (recv.find("get_capture") != std::string::npos) { + sstream << "snapshot_display"; + std::string cmd_capture = sstream.str(); + GPUtils::readFile(cmd_capture); + } else if (recv.find("catch_trace_start") != std::string::npos) { + std::thread tStart(&ByTrace::thread_get_trace, SP->mByTrace); + } else if (recv.find("catch_trace_finish") != std::string::npos) { + std::vector traces; + GPUtils::mSplit(recv, "::", traces); + std::thread tFinish(&ByTrace::thread_finish_trace, SP->mByTrace, std::ref(traces[1])); + } + } +} +} +} diff --git a/device/device_ui/.gitignore b/device/device_ui/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..ce9e170a7715615dbafb9b2595b55017e7d6696c --- /dev/null +++ b/device/device_ui/.gitignore @@ -0,0 +1,13 @@ +*/build +/build/* +/entry/build/* +/gp_daemon_for_hap/libs/* +/gp_daemon_for_hap/obj/* +/gp_daemon_for_hap/push_x64.bat +/.idea +/local.properties +/node_modules/* +/.deveco/* +/entry/.preview +/entry/.preview/* + diff --git a/device/device_ui/AppScope/app.json5 b/device/device_ui/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..f1c18a3fb59df9fa4853abd93a5e94b7cb3fedc9 --- /dev/null +++ b/device/device_ui/AppScope/app.json5 @@ -0,0 +1,13 @@ +{ + "app": { + "bundleName": "com.ohos.gameperceptio", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name", + "distributedNotificationEnabled": true, + "minAPIVersion": 8, + "targetAPIVersion": 9 + } +} diff --git a/device/device_ui/AppScope/resources/base/element/string.json b/device/device_ui/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..a14439a083c6e3304242fb1e458e8634ac8dd04b --- /dev/null +++ b/device/device_ui/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "OpenHarmony_SP" + } + ] +} diff --git a/device/device_ui/AppScope/resources/base/media/app_icon.png b/device/device_ui/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/device/device_ui/AppScope/resources/base/media/app_icon.png differ diff --git a/device/device_ui/README_zh.md b/device/device_ui/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..0772ae0c66cbe4c35c25f8181a468f509a090f9a --- /dev/null +++ b/device/device_ui/README_zh.md @@ -0,0 +1,73 @@ +## 一、简介 +- OpenHarmony性能测试工具 SmartPerf UI版本,可采集CPU、GPU、Temperature、Power、应用RAM、FPS等指标,可使用悬浮窗口实时展示测试数据并支持本地测试报告图表展示。 + +## 二、如何使用 + +- 步骤1:打开桌面预制的Smartperf工具;
+- 步骤2:点击登录,进入首页,点击开始测试页,选择被测应用,配置采集项(目前支持CPU、GPU、FPS、POWER、TEMP、RAM、截图能力、trace);
+- 步骤3:选择应用后根据应用类型选择是否是视频应用、是否是相机应用,点击开始测试、启动悬浮窗(左上角展示),会自动拉起应用,左上角悬浮窗展示start后点击即可开始,展示会变为计时状态,显示当前采集计时;(双击展开、关闭详情悬浮窗;长按结束任务保存数据;单击暂停、继续任务;点击详情悬浮窗后任意采集项会展开相应采集折线图)
+- 步骤4:长按计时器,可以保存采集项数据,悬浮框消失;
+- 步骤5:报告列表页查看报告,原始数据可在概览页对应路径自行使用hdc命令pull出来
+ +## 三、功能介绍 +**1、采集指标说明**
+ +| 采集项 | 说明 | +| :----- | :--------------------- | +| FPS | 1秒内游戏画面或者应用界面真实刷新次数 | +| CPU频率 | 每1秒读取一次设备节点下各CPU的频点信息 | +| CPU负载 | 每1秒读取一次设备节点下各CPU的负载信息 | +| GPU频率 | 每1秒读取一次设备节点下GPU的频点信息 | +| GPU负载 | 每1秒读取一次设备节点下GPU的负载信息 | +| DDR频点 |每1秒读取一次设备节点下DDR的频点信息 | +| RAM |每1秒读取一次设备节点下DDR的频点信息 | +| 温度 | 每1秒读取一次读取一次设备节点下的soc温度等信息 | +| 电流 | 每1秒读取一次设备节点下的电流信息 | +| 电压 | 每1秒读取一次设备节点下电池的电压信息 | +| 截图 |每1秒截取一张截图 | +|trace采集|当帧绘制时间超过100ms以上会自动抓取trace,1min内只抓取1次 | + + +**2、计算指标说明**
+ +| 计算指标 | 说明 | +| :----- | :--------------------- | +| 归一化电流 | 归一化电流=电压 * 电流 / 3.8。 | +| 平均帧率 | 有效时间内的帧率之和除以时间 | +| 最高帧率 | 测试数据中帧率的最大值 | +| 低帧率 | 根据测试数据帧率数据最大数据计算满帧,然后满帧对应的的低帧基线,计算低于基线数量除以总的帧率个数 | +| 抖动率 | 根据测试数据帧率数据的最大数据计算满帧,按照满帧对应抖动率基线,然后计算得到抖动率 | +| 卡顿次数 | 目前卡顿次数依赖于每帧的绘制时间,帧绘制时间>100ms的计算为卡顿 | + +**3、原始数据说明**
+ +| 原始数据 | 说明 | +| :----- | :--------------------- | +| timestamp | 当前时间戳,对应于采集时间 | +| taskId | 任务Id,对应于网站端报告的任务ID| +| cpu0Frequency | cpu0核心的频率 单位一般是HZ| +| cpu0Load | cpu0核心的负载占比,计算得出 单位%| +| gpuFrequency | gpu频率| +| gpuLoad | gpu负载占比 单位%| +| ddrFrequency | ddr频率 | +| socThermalTemp | soc温度| +| gpuTemp | gpu温度| +| batteryTemp |电池温度| +| currentNow | 当前读到的电流值,单位一般是mA| +| voltageNow | 当前读到的电压值,单位一般是uV(微伏)| +| pss | 应用实际使用的物理内存, 单位一般是KB| +| fps | 帧率| +| fpsJitters | 每一帧绘制间隔,单位ns| + + +## 四、其他一些说明 +**1、关于截图、FPS、RAM、trace采集能力**
+- 截图目录默认在/data/local/tmp/capture下。
+ - **Trace抓取:当帧绘制时间超过100ms以上会自动抓取trace,1min内只抓取1次,目录在/data目录下,trace文件较大,建议定期清除。** + **文件名称为:mynewtrace + 当前采集s数 + s:mynewtrace950s.ftrace** + + +**2、fps采集不到如何解决**
+- 方法一:后台必须只能存在一个被测试应用,同应用不能挂许多后台(如果有多个,需清除所有应用,重新启动测试);
+- 方法二:执行hidumper -s 10是否出现connect error等error错误,有error报错的话(尝试kill 掉 hidumper_servic进程,系统会自动再次拉起)
+ diff --git a/device/device_ui/build-profile.json5 b/device/device_ui/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..8da18f847156da22373da0be29ba8c112ca8001c --- /dev/null +++ b/device/device_ui/build-profile.json5 @@ -0,0 +1,26 @@ +{ + "app": { + "signingConfigs": [], + "compileSdkVersion": 9, + "compatibleSdkVersion": 9, + "products": [ + { + "name": "default", + }, + ], + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default", + ], + }, + ], + }, + ], +} \ No newline at end of file diff --git a/device/device_ui/entry/build-profile.json5 b/device/device_ui/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..eeeb460a6f5e502c3ee1b71fa356beab6bf2f37a --- /dev/null +++ b/device/device_ui/entry/build-profile.json5 @@ -0,0 +1,22 @@ +{ + "apiType": 'stageMode', + "buildOption": { + arkEnable: true, + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "-v -DOHOS_STL=c++_shared", + "abiFilters": [ + "armeabi-v7a", + ], + "cppFlags": "", + } + }, + "targets": [ + { + "name": "default", + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/device/device_ui/entry/hvigorfile.js b/device/device_ui/entry/hvigorfile.js new file mode 100644 index 0000000000000000000000000000000000000000..d7720ee6a7aad5c617d1fd2f6fc8c87067bfa32c --- /dev/null +++ b/device/device_ui/entry/hvigorfile.js @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +module.exports = require('@ohos/hvigor-ohos-plugin').hapTasks diff --git a/device/device_ui/entry/package-lock.json b/device/device_ui/entry/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..3064c2ef1c4f50806e52119bf5c276cf07b17bfb --- /dev/null +++ b/device/device_ui/entry/package-lock.json @@ -0,0 +1,5 @@ +{ + "name": "entry", + "version": "1.0.0", + "lockfileVersion": 1 +} diff --git a/device/device_ui/entry/package.json b/device/device_ui/entry/package.json new file mode 100644 index 0000000000000000000000000000000000000000..7651155354ad537960d238ba4b48820678ec0efb --- /dev/null +++ b/device/device_ui/entry/package.json @@ -0,0 +1,14 @@ +{ + "license": "ISC", + "devDependencies": {}, + "name": "entry", + "ohos": { + "org": "ohos", + "directoryLevel": "module", + "buildTool": "hvigor" + }, + "description": "example description", + "repository": {}, + "version": "1.0.0", + "dependencies": {} +} diff --git a/device/device_ui/entry/src/main/cpp/CMakeLists.txt b/device/device_ui/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..96ab5381f4520e2e491dc50053d2cb9058a1c0c2 --- /dev/null +++ b/device/device_ui/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.4.1) +project(XComponent) + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +include_directories(${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/include + ) +add_library(smartperf SHARED profiler.cpp gp_utils.cpp FPS.cpp RAM.cpp) +target_link_libraries(smartperf PUBLIC libace_napi.z.so libc++.a libhilog_ndk.z.so) \ No newline at end of file diff --git a/device/device_ui/entry/src/main/cpp/FPS.cpp b/device/device_ui/entry/src/main/cpp/FPS.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4fda886dcd60ed63255fe71cb6a63d9a26908637 --- /dev/null +++ b/device/device_ui/entry/src/main/cpp/FPS.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include +#include +#include +#include +#include "gp_utils.h" +#include "FPS.h" + +pthread_mutex_t FPS::mutex; +FPS *FPS::instance = nullptr; +FPS *FPS::getInstance() +{ + if (instance == nullptr) { + pthread_mutex_lock(&mutex); + if (instance == nullptr) { + instance = new FPS(); + } + pthread_mutex_unlock(&mutex); + } + return instance; +} +FPS::FPS() +{ + pthread_mutex_init(&mutex, nullptr); +} +void FPS::setPackageName(std::string pkgName) +{ + pkg_name = std::move(pkgName); +} +FpsInfo FPS::getFpsInfo() +{ + FpsInfo fpsInfoMax; + fpsInfoMax.fps = -1; + + std::string layerName; + + std::vector sps; + gpUtils::mSplit(this->pkg_name, ".", sps); + std::string addEndChar = "0"; + const int pNameLastPos = 2; + std::string pkgSuffix = sps[pNameLastPos]; + layerName = std::string( pkgSuffix.c_str()+ addEndChar); + if (pkgSuffix.find("camera")!=std::string::npos) { + layerName = std::string("RosenRenderXComponent"); + } + + FpsInfo fpsInfo = GetSurfaceFrameDataGB(layerName); + if (fpsInfo.fps > fpsInfoMax.fps) { + fpsInfoMax = fpsInfo; + } + return fpsInfoMax; +} +FpsInfo FPS::GetSurfaceFrameDataGB(std::string name) +{ + if (name == "") { + return FpsInfo(); + } + static std::map fps_map; + if (fps_map.count(name) == 0) { + FpsInfo tmp; + tmp.fps = 0; + tmp.pre_fps = 0; + fps_map[name] = tmp; + } + FpsInfo &fpsInfo = fps_map[name]; + fpsInfo.fps = 0; + FILE *fp; + char tmp[1024]; + tmp[0] = '\0'; + std::string cmd = "hidumper -s 10 -a \"fps " + name + "\""; + fp = popen(cmd.c_str(), "r"); + if (fp == nullptr) { + return fpsInfo; + } + long long MOD = 1e9; + long long lastReadyTime = -1; + int fps_gb = 0; + if (!(fpsInfo.time_stamp_q).empty()) { + lastReadyTime = (fpsInfo.time_stamp_q).back(); + } + bool jump = false; + bool refresh = false; + int cnt = 0; + int zeroNum = 0; + while (fgets(tmp, sizeof(tmp), fp) != nullptr) { + long long frameReadyTime = 0; + sscanf(tmp, "%lld", &frameReadyTime); + cnt++; + if (frameReadyTime == 0) { + zeroNum++; + continue; + } + if (lastReadyTime >= frameReadyTime) { + lastReadyTime = -1; + continue; + } + refresh = true; + long long t_frameReadyTime = frameReadyTime / MOD; + long long t_lastReadyTime = lastReadyTime / MOD; + long long lastFrame = -1; + if (t_frameReadyTime == t_lastReadyTime) { + (fpsInfo.time_stamp_q).push(frameReadyTime); + } else if (t_frameReadyTime == t_lastReadyTime + 1) { + jump = true; + lastFrame = fpsInfo.last_frame_ready_time; + lastReadyTime = frameReadyTime; + int fps_tmp = 0; + fpsInfo.jitters.clear(); + while (!(fpsInfo.time_stamp_q).empty()) { + fps_tmp++; + long long currFrame = (fpsInfo.time_stamp_q.front()); + if (lastFrame != -1) { + long long jitter = currFrame - lastFrame; + fpsInfo.jitters.push_back(jitter); + } + lastFrame = currFrame; + (fpsInfo.time_stamp_q).pop(); + } + fps_gb = fps_tmp; + (fpsInfo.time_stamp_q).push(frameReadyTime); + fpsInfo.last_frame_ready_time = lastFrame; + } else if (t_frameReadyTime > t_lastReadyTime + 1) { + jump = true; + lastReadyTime = frameReadyTime; + while (!(fpsInfo.time_stamp_q).empty()) { + (fpsInfo.time_stamp_q).pop(); + } + (fpsInfo.time_stamp_q).push(frameReadyTime); + } + } + pclose(fp); + const int maxZeroNum = 120; + if (zeroNum >= maxZeroNum) { + while (!(fpsInfo.time_stamp_q.empty())) { + fpsInfo.time_stamp_q.pop(); + } + fpsInfo.fps = 0; + return fpsInfo; + } + const int minPrintLine = 5; + if (cnt < minPrintLine) { + fpsInfo.fps = fpsInfo.pre_fps; + return fpsInfo; + } + if (fps_gb > 0) { + fpsInfo.fps = fps_gb; + fpsInfo.pre_fps = fps_gb; + return fpsInfo; + } else if (refresh && !jump) { + fpsInfo.fps = fpsInfo.pre_fps; + return fpsInfo; + } else { + fpsInfo.fps = 0; + return fpsInfo; + } +} + + diff --git a/device/device_ui/entry/src/main/cpp/FPS.h b/device/device_ui/entry/src/main/cpp/FPS.h new file mode 100644 index 0000000000000000000000000000000000000000..d0e3fb0513d9667cf2cdf2aaa97e660e3027c3ba --- /dev/null +++ b/device/device_ui/entry/src/main/cpp/FPS.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +#ifndef FPS_H +#define FPS_H + +#include +#include +#include +#include +#include "pthread.h" +#include "gp_utils.h" + +struct FpsInfo { + int fps; + int pre_fps; + std::vector jitters; + std::queue time_stamp_q; + long long last_frame_ready_time; + long long current_fps_time; + FpsInfo() + { + fps = 0; + pre_fps = 0; + last_frame_ready_time = 0; + current_fps_time = 0; + } +}; +class FPS{ +public: + static FPS* getInstance(); + FpsInfo getFpsInfo(); + FpsInfo GetSurfaceFrameDataGB(std::string name); + void setPackageName(std::string pkgName); + std::string pkg_name; + static pthread_mutex_t mutex; +private: + FPS(); + ~FPS(){}; + static FPS* instance; +}; + +#endif //FPS_H diff --git a/device/device_ui/entry/src/main/cpp/RAM.cpp b/device/device_ui/entry/src/main/cpp/RAM.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a5f3b4234d2618ba000cdbfb5d6686e88d6a81f9 --- /dev/null +++ b/device/device_ui/entry/src/main/cpp/RAM.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include "gp_utils.h" +#include "RAM.h" + +pthread_mutex_t RAM::mutex; +RAM *RAM::instance = nullptr; +RAM *RAM::getInstance() +{ + if (instance == nullptr) + { + pthread_mutex_lock(&mutex); + if (instance == nullptr) + { + instance = new RAM(); + } + pthread_mutex_unlock(&mutex); + } + return instance; +} +RAM::RAM() +{ + pthread_mutex_init(&mutex, nullptr); +} + +std::map RAM::getRamInfo(std::string pid) +{ + std::map ramInfo; + std::string pss_value = ""; + ramInfo["pss"] = "-1"; + if (pid.size() > 0) { + std::ostringstream cmd_grep; + cmd_grep << "hidumper --mem "; + cmd_grep << pid; + std::string cmd = cmd_grep.str(); + std::string pidLine = gpUtils::readCmd(cmd); + std::vector sps; + gpUtils::mSplit(pidLine, " ", sps); + if (sps.size() > 0) { + pss_value = sps[1]; + } + } + if (atoi(pss_value.c_str()) > 0) { + ramInfo["pss"] = gpUtils::extractNumber(pss_value.c_str()); + } + return ramInfo; +} diff --git a/device/device_ui/entry/src/main/cpp/RAM.h b/device/device_ui/entry/src/main/cpp/RAM.h new file mode 100644 index 0000000000000000000000000000000000000000..997119f8fb8479d21d7192a141ffe1454ca71198 --- /dev/null +++ b/device/device_ui/entry/src/main/cpp/RAM.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef RAM_H +#define RAM_H +#include +#include + +class RAM { +public: + static pthread_mutex_t mutex; + static RAM* getInstance(); + std::map getRamInfo(std::string pid); +private: + RAM(); + ~RAM(){}; + static RAM* instance; +}; + +#endif diff --git a/device/device_ui/entry/src/main/cpp/gp_utils.cpp b/device/device_ui/entry/src/main/cpp/gp_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3845f21635249852007e8956cb432eaf4a6fa288 --- /dev/null +++ b/device/device_ui/entry/src/main/cpp/gp_utils.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +#include +#include +#include +#include +#include "gp_utils.h" + +#define LOG_DOMAIN 0x200 // 标识业务领域,范围0x0~0xFFFFF +#define LOG_TAG "gpUtils" + +namespace gpUtils { + void mSplit(const std::string &content, const std::string &sp, std::vector &out) { + int index = 0; + while (index != std ::string::npos) { + int t_end = content.find_first_of(sp, index); + std::string tmp = content.substr(index, t_end - index); + if (tmp != "" && tmp != " ") + out.push_back(tmp); + if (t_end == std::string::npos) + break; + index = t_end + 1; + } + } + + bool canOpen(const std::string &path) { + FILE* fp; + fp = fopen(path.c_str(), "r"); + if(fp == nullptr){ + return false; + } + fclose(fp); + return true; + } + + bool canCmd(const std::string &cmd) { + FILE* pp; + pp = popen(cmd.c_str(), "r"); + if(pp == nullptr){ + return false; + } + pclose(pp); + return true; + } +} +// popen +std::string gpUtils::readCmd(const std::string &cmd) +{ + const int buffLength = 1024; + std::string res = "NA"; + FILE *pp = popen(cmd.c_str(), "r"); + if (pp == nullptr) { + return res; + } else { + char line[buffLength]; + line[0] = '\0'; + while (fgets(line, buffLength, pp) != nullptr) { + res = std::string(line); + } + } + pclose(pp); + return res; +} + +// fopen +std::string gpUtils::readFile(const std::string &path) +{ + std::string res = "NA"; + const int buffLengh = 1024; + FILE *fp; + if ((fp = fopen(path.c_str(), "r")) != nullptr) { + char s[buffLengh]; + s[0] = '\0'; + while (fgets(s, sizeof(s), fp) != nullptr) { + res += std::string(s); + } + } + if (fp != nullptr) { + fclose(fp); + } + return res; +} +// get number_str from str +std::string gpUtils::extractNumber(const std::string &str) +{ + int cntInt = 0; + const int shift = 10; + + for (int i = 0; str[i] != '\0'; ++i) { + if (str[i] >= '0' && str[i] <= '9') { + cntInt *= shift; + cntInt += str[i] - '0'; + } + } + return std::to_string(cntInt); +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/cpp/gp_utils.h b/device/device_ui/entry/src/main/cpp/gp_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..6e44d46c25c5b89e32db5ed146fae66027bdc76a --- /dev/null +++ b/device/device_ui/entry/src/main/cpp/gp_utils.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +#ifndef GP_UTILS_H +#define GP_UTILS_H +#include +#include + +namespace gpUtils { + + void mSplit(const std::string &content, const std::string &sp, std::vector& out); + + bool canOpen(const std::string &path); + + bool canCmd(const std::string &cmd); + + std::string extractNumber(const std::string &str); + + std::string readFile(const std::string &path); + + std::string readCmd(const std::string &cmd); +}; + +#endif //GP_UTILS_H diff --git a/device/device_ui/entry/src/main/cpp/profiler.cpp b/device/device_ui/entry/src/main/cpp/profiler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f96aba319c6937a62bb7ff2c007aaf72af462fd2 --- /dev/null +++ b/device/device_ui/entry/src/main/cpp/profiler.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "napi/native_api.h" +#include "gp_utils.h" + +#define LOG_DOMAIN 0x200 // 标识业务领域,范围0x0~0xFFFFF +#define LOG_TAG "PROFILER" + +namespace { + void collectFpsThread(std::promise &promiseObj){ + FpsInfo fpsInfo = FPS::getInstance()->getFpsInfo(); + promiseObj.set_value(fpsInfo); + } +} + + +static napi_value getFpsData(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = { nullptr }; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + napi_valuetype valuetype0; + napi_typeof(env, args[0], &valuetype0); + char pkgName[64] = {0}; + size_t typeLen = 0; + napi_get_value_string_utf8(env, args[0], pkgName, 63, &typeLen); + FPS::getInstance()->setPackageName(pkgName); + + std::promise promiseObj; + std::future futureObj = promiseObj.get_future(); + std::thread tFps(collectFpsThread, ref(promiseObj)); + tFps.join(); + + FpsInfo fpsInfo = futureObj.get(); + std::string fps = std::to_string(fpsInfo.fps); + std::vector fpsJitters = fpsInfo.jitters; + std::string fps_str = fps + "|"; + for (int i = 0; i < fpsJitters.size(); ++i) { + fps_str += std::to_string(fpsJitters[i]); + fps_str += "=="; + } + napi_value fps_result; + napi_create_string_utf8(env, fps_str.c_str(), fps_str.size(), &fps_result); + return fps_result; +} + +static napi_value getRamData(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = { nullptr }; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + napi_valuetype valuetype0; + napi_typeof(env, args[0], &valuetype0); + char pidNumber[64] = {0}; + size_t typeLen = 0; + napi_get_value_string_utf8(env, args[0], pidNumber, 63, &typeLen); + std::map gramInfo = RAM::getInstance()->getRamInfo(pidNumber); + std::string ram_pss = gramInfo["pss"]; + napi_value ram_result; + napi_create_string_utf8(env, ram_pss.c_str(), ram_pss.size(), &ram_result); + return ram_result; +} + +static napi_value checkDaemon(napi_env env, napi_callback_info info) +{ + std::string status = "Dead"; + std::string spRunning = gpUtils::readCmd(std::string("ps -ef |grep SP_daemon |grep -v grep")); + if (spRunning.find("NA")!= std::string::npos) { + gpUtils::canCmd(std::string("SP_daemon")); + } else { + status = "Running"; + } + napi_value result; + napi_create_string_utf8(env, status.c_str(), status.size(), &result); + return result; +} + +static napi_value checkAccess(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = { nullptr }; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + napi_valuetype valuetype0; + napi_typeof(env, args[0], &valuetype0); + char pathName[64] = {0}; + size_t typeLen = 0; + napi_get_value_string_utf8(env, args[0], pathName, 63, &typeLen); + std::string pathNameStr = pathName; + std::string status = "PermissionDenied"; + bool isAccess = gpUtils::canOpen(pathNameStr); + if (isAccess) { + status = "PermissionAccessed"; + } + napi_value result; + napi_create_string_utf8(env, status.c_str(), status.size(), &result); + return result; +} + +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + { "getFpsData", nullptr, getFpsData, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "getRamData", nullptr, getRamData, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "checkDaemon", nullptr, checkDaemon, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "checkAccess", nullptr, checkAccess, nullptr, nullptr, nullptr, napi_default, nullptr }, + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +} +EXTERN_C_END + +static napi_module demoModule = { +.nm_version = 1, +.nm_flags = 0, +.nm_filename = nullptr, +.nm_register_func = Init, +.nm_modname = "libsmartperf", +.nm_priv = ((void *)0), +.reserved = { 0 }, +}; + +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ +napi_module_register(&demoModule); +} diff --git a/device/device_ui/entry/src/main/cpp/types/libsmartperf/index.d.ts b/device/device_ui/entry/src/main/cpp/types/libsmartperf/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..c678fb88d789f48b0907ba50d5ddf36c59d8d8c1 --- /dev/null +++ b/device/device_ui/entry/src/main/cpp/types/libsmartperf/index.d.ts @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const getFpsData: (pkg: string) => string + +export const getRamData: (pid: string) => string + +export const checkDaemon: () => string + +export const checkAccess: (path: string) => string + diff --git a/device/device_ui/entry/src/main/cpp/types/libsmartperf/package.json b/device/device_ui/entry/src/main/cpp/types/libsmartperf/package.json new file mode 100644 index 0000000000000000000000000000000000000000..3af17c2761c46413f7976c43a51fed3c3108925b --- /dev/null +++ b/device/device_ui/entry/src/main/cpp/types/libsmartperf/package.json @@ -0,0 +1,4 @@ +{ + "name": "libsmartperf.so", + "types": "./index.d.ts" +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/Application/AbilityStage.ts b/device/device_ui/entry/src/main/ets/Application/AbilityStage.ts new file mode 100644 index 0000000000000000000000000000000000000000..d0a61158c23b847792936ee40db21268a0fee5f0 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/Application/AbilityStage.ts @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbilityStage from "@ohos.application.AbilityStage" + +export default class MyAbilityStage extends AbilityStage { + onCreate() { + console.log("MyApplication MyAbilityStage onCreate") + globalThis.hapModuleName = "entry" + } +} diff --git a/device/device_ui/entry/src/main/ets/MainAbility/MainAbility.ts b/device/device_ui/entry/src/main/ets/MainAbility/MainAbility.ts new file mode 100644 index 0000000000000000000000000000000000000000..b085e608173943eb6f3c267b06d7531cff139ae8 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/MainAbility/MainAbility.ts @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ability from '@ohos.application.Ability' +import { initDb } from '../common/database/LocalRepository' +import { FloatWindowFun } from '../common/ui/floatwindow/FloatWindowFun' +import { NativeTaskFun } from "../common/profiler/NativeTaskFun" +import { NetWork } from '../common/profiler/item/NetWork'; +import BundleManager from '../common/utils/BundleMangerUtils'; +import SPLogger from '../common/utils/SPLogger' + + +var abilityWindowStage +const TAG = "MainAbility" + +export default class MainAbility extends Ability { + + + onCreate(want, launchParam) { + globalThis.showFloatingWindow=false + // Ability is creating, initialize resources for this ability + BundleManager.getAppList().then(appList => { + globalThis.appList = appList + + }) + SPLogger.DEBUG(TAG,"getReportListDb" + "--> MainAbility createDd 1") + } + + onDestroy() { + // Ability is destroying, release resources for this ability + SPLogger.DEBUG(TAG,"[MyApplication] MainAbility onDestroy") + } + + onWindowStageCreate(windowStage) { + globalThis.abilityContext = this.context + + // Main window is created, set main page for this ability + SPLogger.DEBUG(TAG,"[MyApplication] MainAbility onWindowStageCreate") + abilityWindowStage = windowStage; + abilityWindowStage.setUIContent(this.context, "pages/LoginPage", null) + } + + onWindowStageDestroy() { + // Main window is destroyed, release UI related resources + SPLogger.DEBUG(TAG,"[MyApplication] MainAbility onWindowStageDestroy") + } + + onForeground() { + initDb() + // Ability has brought to foreground + FloatWindowFun.initAllFun() + NativeTaskFun.initAllFun() + //check netWork + NetWork.getInstance().init() + } + + onBackground() { + // Ability has back to background + SPLogger.DEBUG(TAG,"[MyApplication] MainAbility onBackground") + } +}; + +export function initTest() { + +} + + + diff --git a/device/device_ui/entry/src/main/ets/common/FloatWindowComponent.ets b/device/device_ui/entry/src/main/ets/common/FloatWindowComponent.ets new file mode 100644 index 0000000000000000000000000000000000000000..09e24e6fce21d8114cba2c148ee9b783d2ed544d --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/FloatWindowComponent.ets @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {moveFloatWindow,setFloatWindow} from './ui/floatwindow/utils/floatwindowutils' + + + + + +@Component +export struct FloatWindowComponent { + private settings: RenderingContextSettings = new RenderingContextSettings(true) + private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings) + @State title: string = "SmartPerf" + private XPoint: number = 5 //x起始坐标 + private YPoint: number = 73 //Y起始坐标 + private XScale: number = 5 //刻度 + private YScale: number = 15 //刻度 + private XLength: number = 110 //X轴长度 + private YLength: number = 70 //Y轴长度 + @State data: number[]= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] //数据集合 + private MaxDataSize: number= this.XLength / this.XScale //数据集合的最大长度 + @State NumericalValue: number= 0 //数值 + offsetX: number = -1 //悬浮框移动触摸点 X + offsetY: number = -1 //悬浮框移动触摸点 X + + MoveWindow(offsetX: number, offsetY: number) { + moveFloatWindow(this.title,offsetX, offsetY) + } + + SetWindowPosition(offsetX: number, offsetY: number) { + setFloatWindow(offsetX, offsetY) + } + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Center }) { + Canvas(this.context) + .width('100%') + .height('100%') + .onReady(() => { + //Y轴 + this.context.clearRect(this.XPoint + 0.5, this.YPoint - this.YLength, this.XLength, this.YLength) + this.context.beginPath() + this.context.moveTo(this.XPoint, this.YPoint - this.YLength) + this.context.lineTo(this.XPoint, this.YPoint) + this.context.stroke() + //X轴 + this.context.beginPath() + this.context.moveTo(this.XPoint, this.YPoint) + this.context.lineTo(this.XPoint + this.XLength, this.YPoint) + this.context.stroke() + //K线绘制 + if (this.data.length > 1) { + for (let i = 1; i < this.data.length; i++) { + this.context.beginPath() + console.log("GestureEvent--------------beginPath:" + this.data[i-1]); + this.context.moveTo(this.XPoint + (i - 1) * this.XScale, this.YPoint - this.data[i-1]) + this.context.lineTo(this.XPoint + i * this.XScale, this.YPoint - this.data[i]) + this.context.stroke() + } + } + }) + } + .width('100%') + .height('100%').margin({ top: 14 }).gesture( + GestureGroup(GestureMode.Exclusive, + PanGesture({}) + .onActionStart((event: GestureEvent) => { + + }) + .onActionUpdate((event: GestureEvent) => { + this.offsetX = event.offsetX + this.offsetY = event.offsetY + + }) + .onActionEnd(() => { + this.MoveWindow(this.offsetX, this.offsetY) + this.SetWindowPosition(this.offsetX, this.offsetY) + + + }) + )) + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/constant/ConstantSQL.ts b/device/device_ui/entry/src/main/ets/common/constant/ConstantSQL.ts new file mode 100644 index 0000000000000000000000000000000000000000..913f2859f81e20de56ea75a41b70932a6f049543 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/constant/ConstantSQL.ts @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export const dbName = "gp.db" + +export const dbVersion = 1 + +export const sql_t_general_info = + "CREATE TABLE IF NOT EXISTS " + "t_general_info" + "(" + + "sessionId TEXT PRIMARY KEY, " + + "taskId TEXT NOT NULL," + + "appName TEXT," + + "appVersion TEXT," + + "packageName TEXT," + + "startTime TEXT," + + "endTime TEXT," + + "testDuration TEXT," + + "taskName TEXT," + + "testCase TEXT," + + "testType TEXT," + + "user TEXT," + + "userId TEXT," + + "projectId TEXT," + + "dataSource TEXT," + + "spVersion TEXT," + + "deviceTypeName TEXT," + + "brand TEXT," + + "deviceName TEXT," + + "board TEXT," + + "version TEXT," + + "plat TEXT," + + "cpuCluster TEXT," + + "sn TEXT," + + "resolution TEXT," + + "screenBrightness TEXT," + + "volume TEXT," + + "batteryVolume TEXT," + + "isOnline TEXT," + + "deviceNum TEXT," + + "roomNumber TEXT," + + "taskType TEXT" + + ")" + +export const sql_t_index_info = "CREATE TABLE IF NOT EXISTS " + "t_index_info" + "(" + +"timestamp TEXT PRIMARY KEY, " + +"taskId TEXT NOT NULL, " + +"flag TEXT, " + +"shellBackTemp TEXT," + +"shellFrameTemp TEXT," + +"shellFrontTemp TEXT," + +"socThermalTemp TEXT," + +"systemHTemp TEXT," + +"gpuTemp TEXT," + +"ambientTemp TEXT," + +"batteryTemp TEXT," + +"ddrFrequency TEXT," + +"fps TEXT," + +"fpsJitters TEXT," + +"cpu0Frequency TEXT," + +"cpu0Load TEXT," + +"cpu1Frequency TEXT," + +"cpu1Load TEXT," + +"cpu2Frequency TEXT," + +"cpu2Load TEXT," + +"cpu3Frequency TEXT," + +"cpu3Load TEXT," + +"cpu4Frequency TEXT," + +"cpu4Load TEXT," + +"cpu5Frequency TEXT," + +"cpu5Load TEXT," + +"cpu6Frequency TEXT," + +"cpu6Load TEXT," + +"cpu7Frequency TEXT," + +"cpu7Load TEXT," + +"cpuLoad TEXT," + +"gpuFrequency TEXT," + +"gpuLoad TEXT," + +"currentNow TEXT," + +"capacity TEXT," + +"enableHiz TEXT," + +"status TEXT," + +"voltageNow TEXT," + +"pss TEXT," + +"networkUpSpeed TEXT," + +"networkDownSpeed TEXT" + +")" diff --git a/device/device_ui/entry/src/main/ets/common/constant/ConstantsPath.ts b/device/device_ui/entry/src/main/ets/common/constant/ConstantsPath.ts new file mode 100644 index 0000000000000000000000000000000000000000..11d246d47dbb55b73d9b12c9ab35c07ae124c85f --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/constant/ConstantsPath.ts @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//实际存储路径 对应 沙箱路径 globalThis.abilityContext.getApplicationContext().filesDir 即/data/storage/base/files +export const AppFileRealDir = "/data/app/el2/100/base/com.ohos.gameperceptio/files/" + + diff --git a/device/device_ui/entry/src/main/ets/common/database/DatabaseUtils.ts b/device/device_ui/entry/src/main/ets/common/database/DatabaseUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..1881f30158c2f5339c6cad27fb8416bbbae2a50a --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/database/DatabaseUtils.ts @@ -0,0 +1,366 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import dataRdb from '@ohos.data.rdb' +import { GPData,TIndexInfo,TGeneralInfo } from '../entity/DatabaseEntity'; +import { sql_t_index_info, dbVersion, dbName } from '../constant/ConstantSQL' +import SPLogger from '../utils/SPLogger' + +const TAG = "DatabaseUtils" + +export default { + + //创建表(T_INDEX_INFO T_GENERAL_INFO) + async createTable(pathSuffix: number): Promise { + const STORE_CONFIG_Index = { + name: pathSuffix + ".db" + } + dataRdb.getRdbStore(globalThis.abilityContext, STORE_CONFIG_Index, dbVersion) + .then(rdbStore => { + rdbStore.executeSql(sql_t_index_info, null).catch(err => { + SPLogger.DEBUG(TAG,"--> createTable t_index_info err:" + err) + }) + SPLogger.DEBUG(TAG,"--> createTable start execute sql_t_index_info:" + sql_t_index_info) + return rdbStore + }) + }, + + //插入表( T_GENERAL_INFO) + insertGeneraData(tableName: string, tGeneralInfo: TGeneralInfo) { + var strMap = new Map; + for (let k of Object.keys(tGeneralInfo)) { + strMap.set(k, tGeneralInfo[k]) + } + const valueInsert = { + "sessionId": strMap.get("sessionId"), + "taskId": strMap.get("taskId"), + "appName": strMap.get("appName"), + "appVersion": strMap.get("appVersion"), + "packageName": strMap.get("packageName"), + "startTime": strMap.get("startTime"), + "endTime": strMap.get("endTime"), + "testDuration": strMap.get("testDuration"), + "taskName": strMap.get("taskName") + // "testCase":strMap.get("testCase"), + // "testType":strMap.get("testType"), + // "user":strMap.get("user"), + // "userId":strMap.get("userId"), + // "projectId":strMap.get("projectId"), + // "dataSource":strMap.get("dataSource"), + // "spVersion":strMap.get("spVersion"), + // "deviceTypeName":strMap.get("deviceTypeName"), + // "brand":strMap.get("brand"), + // "deviceName":strMap.get("deviceName"), + // "board":strMap.get("board"), + // "version":strMap.get("version"), + // "plat":strMap.get("plat"), + // "cpuCluster":strMap.get("cpuCluster"), + // "sn":strMap.get("sn"), + // "resolution":strMap.get("resolution"), + // "screenBrightness":strMap.get("screenBrightness"), + // "volume":strMap.get("volume"), + // "batteryVolume":strMap.get("batteryVolume") + } + const STORE_CONFIG = { + name: dbName + } + dataRdb.getRdbStore(globalThis.abilityContext, STORE_CONFIG, dbVersion, (err, rdbStore) => { + SPLogger.DEBUG(TAG,"--> insert into insertGeneraData :tableName:" + tableName + "| valueInsert:" + JSON.stringify(valueInsert)) + rdbStore.insert(tableName, valueInsert).catch(err => { + SPLogger.DEBUG(TAG,"--> insert into insertGeneraData err:" + err) + }).then(() => { + SPLogger.DEBUG(TAG,"--> insert into insertGeneraData success:") + }) + }) + }, + + //插入表(T_INDEX_INFO) + insertData(tableName: string, pathSuffix: number, tIndexInfo: TIndexInfo) { + + var strMap = new Map; + for (let k of Object.keys(tIndexInfo)) { + strMap.set(k, tIndexInfo[k]); + } + const valueInsert = { + "timestamp": strMap.get("timestamp"), + "taskId": strMap.get("taskId"), + "ddrFrequency": strMap.get("ddrFrequency"), + "cpu0Frequency": strMap.get("cpu0Frequency"), + "cpu1Frequency": strMap.get("cpu1Frequency"), + "cpu2Frequency": strMap.get("cpu2Frequency"), + "cpu3Frequency": strMap.get("cpu3Frequency"), + "cpu4Frequency": strMap.get("cpu4Frequency"), + "cpu5Frequency": strMap.get("cpu5Frequency"), + "cpu6Frequency": strMap.get("cpu6Frequency"), + "cpu7Frequency": strMap.get("cpu7Frequency"), + "cpu0Load": strMap.get("cpu0Load"), + "cpu1Load": strMap.get("cpu1Load"), + "cpu2Load": strMap.get("cpu2Load"), + "cpu3Load": strMap.get("cpu3Load"), + "cpu4Load": strMap.get("cpu4Load"), + "cpu5Load": strMap.get("cpu5Load"), + "cpu6Load": strMap.get("cpu6Load"), + "cpu7Load": strMap.get("cpu7Load"), + "gpuFrequency": strMap.get("gpuFrequency"), + "gpuLoad": strMap.get("gpuLoad"), + "currentNow": strMap.get("currentNow"), + "voltageNow": strMap.get("voltageNow"), + "shellFrameTemp": strMap.get("shellFrameTemp"), + "shellFrontTemp": strMap.get("shellFrontTemp"), + "shellBackTemp": strMap.get("shellBackTemp"), + "socThermalTemp": strMap.get("socThermalTemp"), + "systemHTemp": strMap.get("systemHTemp"), + "gpuTemp": strMap.get("gpuTemp"), + "ambientTemp": strMap.get("ambientTemp"), + "batteryTemp": strMap.get("batteryTemp"), + "pss": strMap.get("pss"), + "fps": strMap.get("fps"), + "fpsJitters": strMap.get("fpsJitters"), + "networkUpSpeed": strMap.get("networkUpSpeed"), + "networkDownSpeed": strMap.get("networkDownSpeed") + } + const STORE_CONFIG = { + name: pathSuffix + ".db" + } + dataRdb.getRdbStore(globalThis.abilityContext, STORE_CONFIG, dbVersion, (err, rdbStore) => { + rdbStore.insert(tableName, valueInsert) + }) + }, + + //查询表( T_GENERAL_INFO) + async queryGeneralData(): Promise> { + const STORE_CONFIG = { + name: dbName + } + let results = Array() + try { + return await dataRdb.getRdbStore(globalThis.abilityContext, STORE_CONFIG, 1) + .then(rdbStore => { + let predicates = new dataRdb.RdbPredicates('t_general_info') + predicates.orderByDesc("startTime") + return rdbStore.query(predicates, ["sessionId", + "startTime", "taskId", "appName", "appVersion", "packageName", "endTime", "testDuration", "taskName" + ]) + }) + .then(resultSet => { + while (resultSet.goToNextRow()) { + let sessionId = resultSet.getString(resultSet.getColumnIndex("sessionId")) + let taskId = resultSet.getString(resultSet.getColumnIndex("taskId")) + let appName = resultSet.getString(resultSet.getColumnIndex("appName")) + let appVersion = resultSet.getString(resultSet.getColumnIndex("appVersion")) + let packageName = resultSet.getString(resultSet.getColumnIndex("packageName")) + let startTime = resultSet.getString(resultSet.getColumnIndex("startTime")) + let endTime = resultSet.getString(resultSet.getColumnIndex("endTime")) + let testDuration = resultSet.getLong(resultSet.getColumnIndex("testDuration")) + let taskName = resultSet.getString(resultSet.getColumnIndex("taskName")) + let board = resultSet.getString(resultSet.getColumnIndex("board")) + let deviceTypeName = resultSet.getString(resultSet.getColumnIndex("deviceTypeName")) + let brand = resultSet.getString(resultSet.getColumnIndex("brand")) + let version = resultSet.getString(resultSet.getColumnIndex("version")) + let sn = resultSet.getString(resultSet.getColumnIndex("sn")) + + let tGeneralInfo = new TGeneralInfo( + sessionId, taskId, appName, appVersion, packageName, Number(startTime).valueOf(), Number(endTime).valueOf(), testDuration, taskName + ) + tGeneralInfo.board = board + tGeneralInfo.deviceTypeName = deviceTypeName + tGeneralInfo.brand = brand + tGeneralInfo.version = version + tGeneralInfo.sn = sn + results.push(tGeneralInfo) + } + return results + }) + + } catch (err) { + SPLogger.ERROR(TAG,"resultSet queryGeneralData:err" + err) + } + }, + + //查询表( T_INDEX_INFO) 2022-02-23 改为传时间戳 + async queryData(dbPath: string): Promise> { + const STORE_CONFIG = { + name: dbPath + } + let results = Array() + try { + return await dataRdb.getRdbStore(globalThis.abilityContext, STORE_CONFIG, 1) + .then(rdbStore => { + let predicates = new dataRdb.RdbPredicates('t_index_info') + predicates.orderByDesc("timestamp") + return rdbStore.query(predicates, [ + "timestamp", + "taskId", + "shellBackTemp", "shellFrameTemp", "shellFrontTemp", "socThermalTemp", "systemHTemp", "gpuTemp", "ambientTemp", "batteryTemp", + "ddrFrequency", + "cpu0Frequency", "cpu1Frequency", "cpu2Frequency", "cpu3Frequency", "cpu4Frequency", "cpu5Frequency", "cpu6Frequency", "cpu7Frequency", + "cpu0Load", "cpu1Load", "cpu2Load", "cpu3Load", "cpu4Load", "cpu5Load", "cpu6Load", "cpu7Load", + "gpuLoad", "gpuFrequency", + "currentNow", "voltageNow", + "pss", + "fps", "fpsJitters", + "networkUpSpeed","networkDownSpeed" + ]) + }) + .then(resultSet => { + while (resultSet.goToNextRow()) { + let timestamp = resultSet.getString(resultSet.getColumnIndex("timestamp")) + let shellBackTemp = resultSet.getString(resultSet.getColumnIndex("shellBackTemp")) + let shellFrameTemp = resultSet.getString(resultSet.getColumnIndex("shellFrameTemp")) + let shellFrontTemp = resultSet.getString(resultSet.getColumnIndex("shellFrontTemp")) + let socThermalTemp = resultSet.getString(resultSet.getColumnIndex("socThermalTemp")) + let systemHTemp = resultSet.getString(resultSet.getColumnIndex("systemHTemp")) + let gpuTemp = resultSet.getString(resultSet.getColumnIndex("gpuTemp")) + let ambientTemp = resultSet.getString(resultSet.getColumnIndex("ambientTemp")) + let batteryTemp = resultSet.getString(resultSet.getColumnIndex("batteryTemp")) + let ddrFrequency = resultSet.getString(resultSet.getColumnIndex("ddrFrequency")) + let cpu0Frequency = resultSet.getString(resultSet.getColumnIndex("cpu0Frequency")) + let cpu1Frequency = resultSet.getString(resultSet.getColumnIndex("cpu1Frequency")) + let cpu2Frequency = resultSet.getString(resultSet.getColumnIndex("cpu2Frequency")) + let cpu3Frequency = resultSet.getString(resultSet.getColumnIndex("cpu3Frequency")) + let cpu4Frequency = resultSet.getString(resultSet.getColumnIndex("cpu4Frequency")) + let cpu5Frequency = resultSet.getString(resultSet.getColumnIndex("cpu5Frequency")) + let cpu6Frequency = resultSet.getString(resultSet.getColumnIndex("cpu6Frequency")) + let cpu7Frequency = resultSet.getString(resultSet.getColumnIndex("cpu7Frequency")) + + let cpu0Load = resultSet.getString(resultSet.getColumnIndex("cpu0Load")) + let cpu1Load = resultSet.getString(resultSet.getColumnIndex("cpu1Load")) + let cpu2Load = resultSet.getString(resultSet.getColumnIndex("cpu2Load")) + let cpu3Load = resultSet.getString(resultSet.getColumnIndex("cpu3Load")) + let cpu4Load = resultSet.getString(resultSet.getColumnIndex("cpu4Load")) + let cpu5Load = resultSet.getString(resultSet.getColumnIndex("cpu5Load")) + let cpu6Load = resultSet.getString(resultSet.getColumnIndex("cpu6Load")) + let cpu7Load = resultSet.getString(resultSet.getColumnIndex("cpu7Load")) + + let gpuLoad = resultSet.getString(resultSet.getColumnIndex("gpuLoad")) + let gpuFrequency = resultSet.getString(resultSet.getColumnIndex("gpuFrequency")) + let currentNow = resultSet.getString(resultSet.getColumnIndex("currentNow")) + let voltageNow = resultSet.getString(resultSet.getColumnIndex("voltageNow")) + + let pss = resultSet.getString(resultSet.getColumnIndex("pss")) + let fps = resultSet.getString(resultSet.getColumnIndex("fps")) + let fpsJitters = resultSet.getString(resultSet.getColumnIndex("fpsJitters")) + + let networkUpSpeed = resultSet.getString(resultSet.getColumnIndex("networkUpSpeed")) + let networkDownSpeed = resultSet.getString(resultSet.getColumnIndex("networkDownSpeed")) + + results.push(new TIndexInfo( + timestamp, + "18", + cpu0Frequency, cpu1Frequency, cpu2Frequency, cpu3Frequency, cpu4Frequency, cpu5Frequency, cpu6Frequency, cpu7Frequency, + cpu0Load, cpu1Load, cpu2Load, cpu3Load, cpu4Load, cpu5Load, cpu6Load, cpu7Load, + gpuFrequency, gpuLoad, + ddrFrequency, + shellFrameTemp, shellFrontTemp, shellBackTemp, socThermalTemp, systemHTemp, gpuTemp, ambientTemp, batteryTemp, + currentNow, voltageNow, + pss, + fps,fpsJitters, + networkUpSpeed,networkDownSpeed + )) + console.log("resultSet column names:results:index:" + resultSet.rowIndex) + } + console.log("resultSet column names:results length:" + results.length) + console.log("resultSet column names:results:" + JSON.stringify(results)) + return results + }) + } catch (err) { + SPLogger.ERROR(TAG,"resultSet queryIndexInfo Data:err" + err) + } + }, + /** + * Array 封装为TIndexInfo + * @param gpDatas + */ + gpArray2Index(gpDatas: Array): TIndexInfo{ + var tIndexInfo: TIndexInfo = new TIndexInfo() + tIndexInfo.setTaskId("18") + tIndexInfo.setTimeStamp(new Date().getTime().toString()) + if (gpDatas != null) { + for (var index = 0; index < gpDatas.length; index++) { + let curGPData: GPData = gpDatas[index] + let map = curGPData.values + switch (curGPData.moduleType) { + case "CPU": + tIndexInfo.setCPUData( + map.get("cpu0Freq"), + map.get("cpu1Freq"), + map.get("cpu2Freq"), + map.get("cpu3Freq"), + map.get("cpu4Freq"), + map.get("cpu5Freq"), + map.get("cpu6Freq"), + map.get("cpu7Freq") + ) + break; + case "CPULoad": + tIndexInfo.setCPULoadData( + map.get("cpu0Load"), + map.get("cpu1Load"), + map.get("cpu2Load"), + map.get("cpu3Load"), + map.get("cpu4Load"), + map.get("cpu5Load"), + map.get("cpu6Load"), + map.get("cpu7Load") + ) + break; + case "GPU": + tIndexInfo.setGPUData( + map.get("gpuFreq"), + map.get("gpuLoad") + ) + break; + case "DDR": + tIndexInfo.setDDRData( + map.get("ddrFreq") + ) + break; + case "Temp": + tIndexInfo.setTempData( + map.get("shell_frame"), + map.get("shell_front"), + map.get("shell_back"), + map.get("soc-thermal"), + map.get("system_h"), + map.get("gpu-thermal"), + map.get("ambient"), + map.get("Battery") + ) + break; + case "Power": + tIndexInfo.setPowerData( + map.get("current_now"), + map.get("voltage_now") + ) + break; + case "RAM": + tIndexInfo.setRamData( + map.get("pss") + ) + break; + case "FPS": + tIndexInfo.setFpsData( + map.get("fps"), map.get("fpsJitters")) + break; + case "NetWork": + tIndexInfo.setNetWorkData( + map.get("netSpeedUp"), map.get("netSpeedDown")) + break; + } + } + } + return tIndexInfo + } +} diff --git a/device/device_ui/entry/src/main/ets/common/database/LocalRepository.ts b/device/device_ui/entry/src/main/ets/common/database/LocalRepository.ts new file mode 100644 index 0000000000000000000000000000000000000000..c349f9441d97152302d9f2935a11812cf8174313 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/database/LocalRepository.ts @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import dataRdb from '@ohos.data.rdb' +import database from './DatabaseUtils' +import BundleManager from '../utils/BundleMangerUtils'; +import { dateFormat } from '../utils/TimeUtils' +import { ReportItem } from '../entity/LocalConfigEntity' +import { sql_t_general_info, dbVersion, dbName } from '../constant/ConstantSQL'; +import { AppFileRealDir } from '../constant/ConstantsPath' +import SPLogger from '../utils/SPLogger' + + +const TAG = "LocalRepository" + + +export function initDb(): void { + + const STORE_CONFIG = { + name: dbName + } + + dataRdb.getRdbStore(globalThis.abilityContext, STORE_CONFIG, dbVersion) + .then(rdbStore => { + rdbStore.executeSql(sql_t_general_info, null).catch(err => { + SPLogger.DEBUG(TAG, "--> createTable t_genneral_info err:" + err) + }) + SPLogger.DEBUG(TAG, "--> createTable start execute sql_t_genneral_info:" + sql_t_general_info) + return rdbStore + }) + + getReportListDb().then(res => { + globalThis.reportList = res + let bundleNameArr = [] + for (let reportItemKey in globalThis.reportList) { + bundleNameArr.push(globalThis.reportList[reportItemKey].packageName) + } + + BundleManager.getIconByBundleName(bundleNameArr).then(map => { + globalThis.iconMap = map + }) + + let resReport: Array = res + + globalThis.sumTest = resReport.length + globalThis.sumTestTime = 0 + + let sumTestAppMap = new Map + for (let resReportKey in resReport) { + sumTestAppMap.set(resReport[resReportKey].appName, "") + globalThis.sumTestTime += Number(resReport[resReportKey].testDuration).valueOf() + } + globalThis.sumTestApp = sumTestAppMap.size + }).catch(err => { + SPLogger.DEBUG(TAG, "getReportListDb ERR:" + err); + }) +} + + +export async function getReportListDb(): Promise> { + var result = Array() + await database.queryGeneralData().then(generals => { + for (var i = 0; i < generals.length; i++) { + var curGeneralInfo = generals[i] + result.push( + new ReportItem( + curGeneralInfo.taskId.toString(), + AppFileRealDir + "/" + curGeneralInfo.sessionId.toString(), + curGeneralInfo.packageName, + "", + curGeneralInfo.taskName, + curGeneralInfo.appName, + dateFormat(curGeneralInfo.startTime), + curGeneralInfo.testDuration.toString(), + false + )) + } + }) + return result +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/entity/DatabaseEntity.ets b/device/device_ui/entry/src/main/ets/common/entity/DatabaseEntity.ets new file mode 100644 index 0000000000000000000000000000000000000000..8ccc49696626fb28579fe5d1d4937490e8ffaed7 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/entity/DatabaseEntity.ets @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * GPData实体类 + */ +export class GPData { + public moduleType: String + public timeStamp: number + public values: Map + + constructor(moduleType: String, timeStamp: number, values: Map) { + this.moduleType = moduleType; + this.timeStamp = timeStamp; + this.values = values; + } + + toString() { + var obj = Object.create(null); + var iterator = this.values.keys(); + for (var i = 0; i < this.values.size; i++) { + var key = iterator.next().value; + obj[key] = this.values.get(key); + } + return "GPData{" + + "module='" + this.moduleType + '\'' + + ", timeStamp=" + this.timeStamp + + ", values=" + JSON.stringify(obj) + + '}'; + } +} + +/** + * 任务列表页 任务概览页实体类 + */ +export class TGeneralInfo { + //目录生成的UUID 作为主键 + public sessionId: String + //任务Id + public taskId: String + //测试游戏名称 + public appName: String + //测试游戏版本 + public appVersion: String + //游戏包名 + public packageName: String + //开始时间 + public startTime: number + //结束时间 + public endTime: number + //测试时长 + public testDuration: number + //任务名称 + public taskName: String + //测试方式 middle + public testCase: String + //测试类型 smartPerf beta + public testType: String + //用户名 + public user: String + //用户id + public userId: String + //项目Id + public projectId: String + //报告来源 + public dataSource: String + //sp版本 + public spVersion: String + //设备类型 + public deviceTypeName: String + //设备品牌 + public brand: String + //设备名称 XX-XXX(****00018) + public deviceName: String + //设备型号 + public board: String + //手机版本 + public version: String + //芯片平台 + public plat: String + //大中小核心 + public cpuCluster: String + //设备sn号 + public sn: String + //分辨类 + public resolution: String + //当前亮度 + public screenBrightness: String + //设备当前音量 + public volume: String + //当前电池电量 + public batteryVolume: String + //是否是多路测试 + public isOnline: boolean + //设备号 + public deviceNum: number + //房间号 + public roomNumber: String + //任务类型 主控、被控 + public taskType: number + + constructor(sessionId ?: String, taskId ?: String, appName ?: String, appVersion ?: String, packageName ?: String, startTime ?: number, endTime ?: number, testDuration ?: number, taskName ?: String) { + this.sessionId = sessionId + this.taskId = taskId + this.appName = appName + this.appVersion = appVersion + this.packageName = packageName + this.startTime = startTime + this.endTime = endTime + this.testDuration = testDuration + this.taskName = taskName + } +} + +/** + * 任务详情实体类 + */ +export class TIndexInfo { + //时间戳 主键 + public timestamp: String; + //任务ID + public taskId: String; + //场景标识 + public flag: String; + //温度 + public shellBackTemp: String; + public shellFrameTemp: String; + public shellFrontTemp: String; + public socThermalTemp: String; + public systemHTemp: String; + public gpuTemp: String; + public ambientTemp: String; + public batteryTemp: String; + + //ddr + public ddrFrequency: String; + //fps + public fps: String; + public fpsJitters: String; + //cpu + public cpu0Frequency: String; + public cpu0Load: String; + public cpu1Frequency: String; + public cpu1Load: String; + public cpu2Frequency: String; + public cpu2Load: String; + public cpu3Frequency: String; + public cpu3Load: String; + public cpu4Frequency: String; + public cpu4Load: String; + public cpu5Frequency: String; + public cpu5Load: String; + public cpu6Frequency: String; + public cpu6Load: String; + public cpu7Frequency: String; + public cpu7Load: String; + public cpuLoad: String; + //gpu + public gpuFrequency: String; + public gpuLoad: String; + //power + public currentNow: String; + public capacity: String; + public enableHiz: String; + public status: String; + public voltageNow: String; + //ram + public pss: String; + //HWCPipeGPU + public cacheMisses: String; + public instructions: String; + //HWCPipeGPU + public gpuCycles: String; + public vertexComputeCycles: String; + public fragmentCycles: String; + public tilerCycles: String; + public vertexComputeJobs: String; + public fragmentJobs: String; + public pixels: String; + public earlyZTests: String; + public earlyZKilled: String; + public externalMemoryReadAccesses: String; + public externalMemoryWriteAccesses: String; + public externalMemoryReadBytes: String; + public externalMemoryWriteBytes: String; + public cacheWriteLookups: String; + public cacheReadLookups: String; + public externalMemoryWriteStalls: String; + public externalMemoryReadStalls: String; + public shaderCycles: String; + public shaderArithmeticCycles: String; + public shaderLoadStoreCycles: String; + public shaderTextureCycles: String; + + //QPCounters + public clocksSecond: String; + public gpuUtilization: String; + public gpuBusBusy: String; + public verticesShadedSecond: String; + public fragmentsShadedSecond: String; + public texturesVertex: String; + public texturesFragment: String; + public aluVertex: String; + public aluFragment: String; + public timeShadingFragments: String; + public timeShadingVertices: String; + public timeCompute: String; + public readTotal: String; + public writeTotal: String; + public textureMemoryReadBW: String; + public vertexMemoryRead: String; + public spMemoryRead: String; + public qpGPUFrequency: String; + //network + public currNetworkType: String; + public networkUpSpeed: String; + public networkDownSpeed: String; + public wlanSingleIntensity: String; + public radioSingleIntensity: String; + public networkDelay_SDK: String; + constructor( + timestamp?: String, + taskId?: String, + cpu0Freq?: String, cpu1Freq?: String, cpu2Freq?: String, cpu3Freq?: String, cpu4Freq?: String, cpu5Freq?: String, cpu6Freq?: String, cpu7Freq?: String, + cpu0Load?: string, cpu1Load?: string, cpu2Load?: string, cpu3Load?: string, cpu4Load?: string, cpu5Load?: string, cpu6Load?: string, cpu7Load?: string, + gpuFreq?: String, gpuLoad?: String, + ddrFreq?: String, + shellFrame?: String, shellFront?: String, shellBack?: String, socThermal?: String, systemH?: String, gpu?: String, ambient?: String, battery?: String, + currentNow?: String, voltageNow?: String, + pss?: String, + fps?: String, + fpsJitters?: String, + networkUpSpeed?: String, networkDownSpeed?: String + ) { + this.timestamp = timestamp + this.taskId = taskId + this.cpu0Frequency = cpu0Freq + this.cpu1Frequency = cpu1Freq + this.cpu2Frequency = cpu2Freq + this.cpu3Frequency = cpu3Freq + this.cpu4Frequency = cpu4Freq + this.cpu5Frequency = cpu5Freq + this.cpu6Frequency = cpu6Freq + this.cpu7Frequency = cpu7Freq + this.cpu0Load = cpu0Load + this.cpu1Load = cpu1Load + this.cpu2Load = cpu2Load + this.cpu3Load = cpu3Load + this.cpu4Load = cpu4Load + this.cpu5Load = cpu5Load + this.cpu6Load = cpu6Load + this.cpu7Load = cpu7Load + this.gpuFrequency = gpuFreq + this.gpuLoad = gpuLoad + this.ddrFrequency = ddrFreq + this.shellFrameTemp = shellFrame + this.shellFrontTemp = shellFront + this.shellBackTemp = shellBack + this.socThermalTemp = socThermal + this.systemHTemp = systemH + this.gpuTemp = gpu + this.ambientTemp = ambient + this.batteryTemp = battery + this.currentNow = currentNow + this.voltageNow = voltageNow + this.pss = pss + this.fps = fps + this.fpsJitters = fpsJitters + this.networkUpSpeed = networkUpSpeed + this.networkDownSpeed = networkDownSpeed + } + + setTimeStamp(timestamp: String) { + this.timestamp = timestamp + } + + setTaskId(taskId: String) { + this.taskId = taskId + } + + setCPUData(cpu0Freq: String, cpu1Freq: String, cpu2Freq: String, cpu3Freq: String, cpu4Freq: String, cpu5Freq: String, cpu6Freq: String, cpu7Freq: String) { + this.cpu0Frequency = cpu0Freq + this.cpu1Frequency = cpu1Freq + this.cpu2Frequency = cpu2Freq + this.cpu3Frequency = cpu3Freq + this.cpu4Frequency = cpu4Freq + this.cpu5Frequency = cpu5Freq + this.cpu6Frequency = cpu6Freq + this.cpu7Frequency = cpu7Freq + } + + setCPULoadData(cpu0Load: String, cpu1Load: String, cpu2Load: String, cpu3Load: String, cpu4Load: String, cpu5Load: String, cpu6Load: String, cpu7Load: String) { + this.cpu0Load = cpu0Load + this.cpu1Load = cpu1Load + this.cpu2Load = cpu2Load + this.cpu3Load = cpu3Load + this.cpu4Load = cpu4Load + this.cpu5Load = cpu5Load + this.cpu6Load = cpu6Load + this.cpu7Load = cpu7Load + } + + setGPUData(gpuFreq: String, gpuLoad: String) { + this.gpuFrequency = gpuFreq + this.gpuLoad = gpuLoad + } + + setDDRData(ddrFreq: String) { + this.ddrFrequency = ddrFreq + } + + setTempData(shellFrame: String, shellFront: String, shellBack: String, soc_thermal: String, system_h: String, gpu: String, ambient: String, battery: String) { + this.shellFrameTemp = shellFrame + this.shellFrontTemp = shellFront + this.shellBackTemp = shellBack + this.socThermalTemp = soc_thermal + this.systemHTemp = system_h + this.gpuTemp = gpu + this.ambientTemp = ambient + this.batteryTemp = battery + } + + setPowerData(currentNow: String, voltageNow: String) { + this.currentNow = currentNow + this.voltageNow = voltageNow + } + + setFpsData(fps: String, fpsJitter: String) { + this.fps = fps + this.fpsJitters = fpsJitter + } + + setRamData(pss: String) { + this.pss = pss + } + + setNetWorkData(networkUpSpeed:String, networkDownSpeed:String){ + this.networkDownSpeed = networkDownSpeed + this.networkUpSpeed = networkUpSpeed + } + + setDefaultValue() { + let properties: any[] = Object.keys(this) + properties.forEach(property => { + this[property] = "-1" + }) + } +} + +//dubai app功耗 +export class TPowerAppInfo { + //主键 自增 + public id: String; + public taskId: String; + public application: String; + public power: String; + public current: String; + public percent: String; +} + +//dubai 器件功耗 +export class TPowerSensorInfo { + //主键 自增 + public id: String; + public taskId: String; + public sensor: String; + public power: String; + public current: String; + public percent: String; +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/entity/LocalConfigEntity.ts b/device/device_ui/entry/src/main/ets/common/entity/LocalConfigEntity.ts new file mode 100644 index 0000000000000000000000000000000000000000..55bb4bbf0ae778e2d6861df2c7855ab4d86739f6 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/entity/LocalConfigEntity.ts @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export enum TestMode { + ONLINE, + BRIGHTNESS, + STARTUP +} + +export class OtherSupport { + public testName: string + public testSrc: string + public testMode: TestMode + public resource: Resource + + constructor(testName: string, testSrc: string, testMode: TestMode, resource: Resource) { + this.testName = testName + this.testSrc = testSrc + this.testMode = testMode + this.resource = resource + } +} + +export class SwitchItem { + public id: string + public switchName: string + public switchSrc: Resource + public isOpen: boolean + public enable: boolean + + constructor(id: string, switchName: string, switchSrc: Resource, isOpen: boolean, enable: boolean) { + this.id = id + this.switchName = switchName + this.switchSrc = switchSrc + this.isOpen = isOpen + this.enable = enable + } +} + +export class CollectItem { + public name: string + public isSupport: boolean + public isSelect: boolean + + constructor(name: string, isSupport: boolean, isSelect: boolean) { + this.name = name + this.isSupport = isSupport + this.isSelect = isSelect + } +} + +export class TaskInfoConfig { + public testName: string + public collectItem: Array + public switchItem: Array + + constructor(testName?: string, collectItem?: Array, switchItem?: Array) { + this.testName = testName + this.collectItem = collectItem + this.switchItem = switchItem + } +} + +export class AppInfoItem { + public id: number + public packageName: string + public appName: string + public appVersion: String + public appIcon: string + public abilityName: string + + constructor(packageName: string, appName: string, appVersion: String, appIcon: string, abilityName: string) { + this.packageName = packageName + this.appName = appName + this.appVersion = appVersion + this.appIcon = appIcon + this.abilityName = abilityName + } +} + +export class ReportItem { + public sessionId: String; + public dbPath: String; + public packageName: String; + public iconId: String; + public name: String; + public appName: String; + public startTime: String; + public testDuration: String; + public upStatus: boolean; + + constructor(sessionId: String, dbPath: String, packageName: String, iconId: String, name: String, appName: String, startTime: String, testDuration: String, upStatus: boolean) { + this.sessionId = sessionId + this.dbPath = dbPath + this.packageName = packageName + this.iconId = iconId + this.name = name + this.appName = appName + this.startTime = startTime + this.testDuration = testDuration + this.upStatus = upStatus + } + + public getStartTime(): string{ + return this.startTime.valueOf() + } + + public getTestDuration(): string{ + return this.testDuration.valueOf() + } + + public getDbPath(): string{ + return this.dbPath.valueOf() + } +} + +export const otherSupportList = new Array( + new OtherSupport('亮度调节', '调节屏幕亮度', TestMode.BRIGHTNESS, $r("app.media.icon_brightness_plus")), +) + +export let switchList = new Array( + new SwitchItem("trace", '是否抓取trace', $r("app.media.icon_average_frame_b"), false, true), + new SwitchItem("is_camera", '是否为相机应用', $r("app.media.icon_camera"), false, true), + new SwitchItem("is_video", '是否为视频应用', $r("app.media.icon_video"), false, true), + new SwitchItem("screen_capture", '是否开启截图', $r("app.media.icon_screencap"), false, true) +) + +export class QuestionItem { + public question: string + public answer: string + + constructor(question: string, answer: string) { + this.answer = answer + this.question = question + } +} + +export const questionList = new Array( + new QuestionItem('1.SP工具支持FPS采集吗?', '可以,fps依赖Hidumper能力..'), + new QuestionItem('2.SP工具支持RAM采集吗?', 'ram采集目前是 读取进程节点内存信息中的PSS值...'), + new QuestionItem('3.FPS采集不到?', '可能是视频应用,需要联系开发添加对应的图层,做采集适配'), + new QuestionItem('4.SP采集原理?', '目前除fps外,其他采集均是通过cat 系统节点获取'), + new QuestionItem('5.报告页的值是怎么算的?', '最终以一场测试结果的平均值为准'), + new QuestionItem('6.SP后续规划?', '集成更多采集能力,如trace采集,counter采集,网络采集等等;优化数据展示方式,报告上传网站端,在线分析性能功耗问题') +) + +export class SummaryItem { + public icon: Resource + public content: string + public value: string + + constructor(icon: Resource, content: string, value: string) { + this.icon = icon + this.content = content + this.value = value + } +} + diff --git a/device/device_ui/entry/src/main/ets/common/entity/SystemEntity.ets b/device/device_ui/entry/src/main/ets/common/entity/SystemEntity.ets new file mode 100644 index 0000000000000000000000000000000000000000..94f0dc230bc3b30e7a866e963a1d2247b6f12e35 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/entity/SystemEntity.ets @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface ProcessRunningInfo { + /** + * @default process id + * @since 8 + * @syscap SystemCapability.Ability.AbilityRuntime.Mission + */ + pid: number; + + /** + * @default user id + * @since 8 + * @syscap SystemCapability.Ability.AbilityRuntime.Mission + */ + uid: number; + + /** + * @default the name of the process + * @since 8 + * @syscap SystemCapability.Ability.AbilityRuntime.Mission + */ + processName: string; + + /** + * @default an array of the bundleNames running in the process + * @since 8 + * @syscap SystemCapability.Ability.AbilityRuntime.Mission + */ + bundleNames: Array; +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/entity/UserEntity.ets b/device/device_ui/entry/src/main/ets/common/entity/UserEntity.ets new file mode 100644 index 0000000000000000000000000000000000000000..1b38d3f3aaff3122ea0fd9b2d52a6576b0b27429 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/entity/UserEntity.ets @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class User { + public token: String; + public expires_in: String; //过期时间 + public refresh_token: String; //刷新token + public expires_at: String; //时间 + public token_type: String; //token类型 + + constructor(token?: String, expires_in?: String, refresh_token?: String, expires_at?: String, token_type?: String) { + this.token = token + this.expires_in = expires_in + this.refresh_token = refresh_token + this.expires_at = expires_at + this.token_type = token_type + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/profiler/MainWorkTask.ets b/device/device_ui/entry/src/main/ets/common/profiler/MainWorkTask.ets new file mode 100644 index 0000000000000000000000000000000000000000..94ab554b6bd44ed0909dab4c54a8ca97aa1f6fc3 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/MainWorkTask.ets @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import worker from '@ohos.worker'; // 导入worker模块 +import { CatchTraceStatus } from '../profiler/base/ProfilerConstant'; +import SPLogger from '../utils/SPLogger' +export let MainWorker = new worker.Worker("workers/worker.js") + +MainWorker.onmessage = function (e) { + SPLogger.DEBUG("MainWorker","MainWorker recv:" + e.data); + let arr = e.data.split("$") + if (arr[0] == "RAM ") { + globalThis.ramArr.push(arr[1]) + } + if (arr[0] == "FPS") { + globalThis.fpsArr.push(arr[1]) + globalThis.fpsJitterArr.push(arr[2]) + globalThis.timerFps=arr[1] + if (globalThis.catchTraceState == CatchTraceStatus.catch_trace_start + || globalThis.catchTraceState == CatchTraceStatus.catch_trace_finish + || globalThis.catchTraceState == CatchTraceStatus.catch_trace_first_running + ) { + if (globalThis.fpsJitterArr != undefined && globalThis.fpsJitterArr != null && globalThis.fpsJitterArr != "") { + let tempQueue: Array = globalThis.fpsJitterArr + let curJitter = tempQueue.pop() + let tempJitterArr = curJitter.split("==") + for (var i = 0; i < tempJitterArr.length; i++) { + let tmp = tempJitterArr[i] + let jitter = parseInt(tmp) / 1e6 + if (jitter > 100) { + globalThis.jitterTrace = true + return + } + } + } + } + } +} + diff --git a/device/device_ui/entry/src/main/ets/common/profiler/NativeTaskFun.ts b/device/device_ui/entry/src/main/ets/common/profiler/NativeTaskFun.ts new file mode 100644 index 0000000000000000000000000000000000000000..6ee272ff6290308d22bfd9ae9293b46985d03916 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/NativeTaskFun.ts @@ -0,0 +1,49 @@ + +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { getPidOfAbility } from '../utils/SystemUtils'; +import SPLogger from '../utils/SPLogger' +import nativeProfiler from "libsmartperf.so" + + +const TAG = "NativeTaskFun" + +export class NativeTaskFun { + static initAllFun() { + globalThis.CreateNativeFps = ((pkgName: string) => { + let fpsStr: string = nativeProfiler.getFpsData(pkgName) + SPLogger.DEBUG(TAG, "nativeProfiler" + "--> fpsStr:" + fpsStr) + return fpsStr + }) + globalThis.CreateNativeRam = (() => { + let ramStr: string = nativeProfiler.getRamData(globalThis.processPid) + SPLogger.DEBUG(TAG, "nativeProfiler" + "--> ramStr :" + ramStr) + globalThis.ramArr.push(ramStr) + return ramStr + }) + + globalThis.CheckDaemon = (() => { + let status: string = nativeProfiler.checkDaemon() + SPLogger.DEBUG(TAG, "nativeProfiler" + "--> daemon status :" + status) + return status + }) + + globalThis.checkAccess = ((path: string) => { + let status: string = nativeProfiler.checkAccess(path) + SPLogger.DEBUG(TAG, "nativeProfiler --> "+ path + " status :" + status) + return status + }) + } +} diff --git a/device/device_ui/entry/src/main/ets/common/profiler/ProfilerTask.ets b/device/device_ui/entry/src/main/ets/common/profiler/ProfilerTask.ets new file mode 100644 index 0000000000000000000000000000000000000000..6aaa9a712a8f681253e977cf1f8d71d88a04405f --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/ProfilerTask.ets @@ -0,0 +1,203 @@ + +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import deviceInfo from '@ohos.deviceInfo' +import CommonEvent from '@ohos.commonevent' +import database from '../database/databaseutils' +import { getPidOfAbility } from '../utils/SystemUtils'; +import { CPU } from './item/CPU'; +import { csvGeneralInfo, csvTIndexInfo } from '../utils/csvutils' +import { createFilePath } from '../utils/ioutils' +import { GPData, TIndexInfo, TGeneralInfo } from '../entity/databaseentity' +import { ProfilerFactory } from './base/ProfilerFactory' +import SPLogger from '../../common/utils/SPLogger' + +export class ProfilerTask { + private collectItems:Array = [] + private static instance: ProfilerTask + + public static getInstance(): ProfilerTask { + if (this.instance == null) { + this.instance = new ProfilerTask + } + return ProfilerTask.instance + } + + initModule() { + SPLogger.DEBUG(ProfilerTask.name,'ProfilerTask initModule configs: ' + JSON.stringify(globalThis.collectConfigs)) + const keys: any[] = Object.keys(globalThis.collectConfigs) + for (var key of keys) { + if (globalThis.collectConfigs[key]) { + let typeCollect = ProfilerFactory.getProfilerByConfig(key.toString()) + SPLogger.DEBUG(ProfilerTask.name,'ProfilerTask initModule: ' + typeCollect) + if (typeCollect == null) { + continue + }else{ + this.collectItems.push(typeCollect.init()) + } + } + } + //默认不使用daemon + globalThis.useDaemon = false + let status = globalThis.CheckDaemon() + if (status == "Running") { + globalThis.useDaemon = true + } + SPLogger.DEBUG(ProfilerTask.name,'ProfilerTask initModule:Daemon status ' + status) + } + + getSupports(keys:string[]){ + let supports = new Map + for (var key of keys) { + let typeCollect = ProfilerFactory.getProfilerByConfig(key) + supports.set(key.toString(),typeCollect.isSupport()) + } + return supports + } + + taskInit() { + SPLogger.DEBUG(ProfilerTask.name,'ProfilerUtils taskInit call'); + var now = new Date() + //数据库时间戳标记 + globalThis.dbTime = now.getTime() + //开始时间 + globalThis.startTime = now.getTime() + //结束时间 + globalThis.endTime = -1 + //时间计数器 + globalThis.collectIntervalNum = -1 + //入库数据 + globalThis.tTndexs = new Array() + //实时数据 + globalThis.tTndex = new TIndexInfo() + // ram队列 + globalThis.ramArr = new Array() + // fps队列 + globalThis.fpsArr = new Array() + // fpsJitter队列 + globalThis.fpsJitterArr = new Array() + //初始化采集目标进程pid + getPidOfAbility(globalThis.collectPkg).then(pid=>{ + globalThis.processPid = pid + }) + //初始化数据库 2022-02-23 dbName改为时间戳 + database.createTable(globalThis.dbTime) + SPLogger.DEBUG(ProfilerTask.name,'ProfilerUtils taskInit called'); + } + + taskStart() { + SPLogger.DEBUG(ProfilerTask.name,'ProfilerTask taskStart call'); + var gpDataArr: Array = new Array() + this.collectItems.forEach( + (moduleName)=>{ + let typeCollect = ProfilerFactory.getProfilerByConfig(moduleName.toString()) + if (typeCollect != null) { + let gpData:GPData =typeCollect.readData() + if(typeCollect instanceof CPU){ + typeCollect.readCPULoad() + } + gpDataArr.push(gpData) + SPLogger.DEBUG(ProfilerTask.name,"profiler ProfilerTask:curData:"+gpData); + } + } + ) + + //防止cpuLoad -1 + if (globalThis.collectIntervalNum > 0) { + let tTndex = database.gpArray2Index(gpDataArr) + globalThis.tTndexs.push(tTndex) + globalThis.tTndex = tTndex; + CommonEvent.publish("event", { code: 0, data: tTndex.fps + "", }, (err)=>{}); + } + globalThis.collectIntervalNum++ + SPLogger.DEBUG(ProfilerTask.name,"profiler globalThis.collectIntervalNum " + globalThis.collectIntervalNum) + + SPLogger.DEBUG(ProfilerTask.name,'ProfilerTask taskStart called'); + } + + taskStop() { + SPLogger.DEBUG(ProfilerTask.name,'ProfilerTask taskStop call'); + // t_index_info 入库 + if (globalThis.tTndexs.length > 2) { + for (var index = 2; index < globalThis.tTndexs.length; index++) { + const tTndex = globalThis.tTndexs[index]; + database.insertData("t_index_info", globalThis.dbTime, tTndex) + } + } + createFilePath(globalThis.abilityContext.getApplicationContext().filesDir + "/" + globalThis.dbTime + "/t_index_info.csv", csvTIndexInfo(globalThis.tTndexs)) + // t_general_info 入库 + globalThis.endTime = new Date().getTime() + let tGeneralInfo = new TGeneralInfo( + globalThis.dbTime.toString(), + "NA", + globalThis.appName, + globalThis.appVersion, + globalThis.packageName, + globalThis.startTime, + globalThis.endTime, + globalThis.collectIntervalNum, + globalThis.testTaskName + ) + tGeneralInfo.board = deviceInfo.brand + tGeneralInfo.deviceTypeName = deviceInfo.deviceType + tGeneralInfo.brand = deviceInfo.brand + tGeneralInfo.version = deviceInfo.displayVersion + tGeneralInfo.sn = deviceInfo.serial + database.insertGeneraData("t_general_info", tGeneralInfo) + createFilePath(globalThis.abilityContext.getApplicationContext().filesDir + "/" + globalThis.dbTime + "/t_general_info.csv", csvGeneralInfo(tGeneralInfo)) + + SPLogger.DEBUG(ProfilerTask.name,'ProfilerTask taskStop called'); + } + + taskDestroy() { + //数据库时间戳标记 + globalThis.dbTime = -1 + //开始时间 + globalThis.startTime = -1 + //结束时间 + globalThis.endTime = -1 + //入库数据 + globalThis.tTndexs = new Array() + + //采集配置恢复fileOpen + globalThis.collectConfigs = -1 + globalThis.collectPkg = -1 + + //采集定时器 配置 + globalThis.collectInterval = -1 + globalThis.collectIntervalCollect = -1 + globalThis.collectIntervalNum = -1 + + //socket采集队列 fps ram + globalThis.fpsArr = new Array() + globalThis.fpsJitterArr = new Array() + globalThis.ramArr = new Array() + } +} + + + + + + + + + + + + + + + diff --git a/device/device_ui/entry/src/main/ets/common/profiler/base/BaseProfiler.ets b/device/device_ui/entry/src/main/ets/common/profiler/base/BaseProfiler.ets new file mode 100644 index 0000000000000000000000000000000000000000..78fcd09961de6088ffa5065dfc15c88a7e5f81cb --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/base/BaseProfiler.ets @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { GPData } from '../../entity/databaseentity'; +import { CollectorType } from './ProfilerConstant' + +export abstract class BaseProfiler { + abstract init(): CollectorType + abstract isSupport(): Boolean + abstract readData(): GPData +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/profiler/base/BaseProfilerUtils.ets b/device/device_ui/entry/src/main/ets/common/profiler/base/BaseProfilerUtils.ets new file mode 100644 index 0000000000000000000000000000000000000000..8077764c9d18b42bbdc0b0c0806f2bd0f2010632 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/base/BaseProfilerUtils.ets @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import fileio from '@ohos.fileio'; +import util from '@ohos.util'; +import { GPData } from '../../entity/databaseentity'; +import SPLogger from '../../../common/utils/SPLogger' + +const BUFF_SIZE = 1024 +const TAG="BaseProfilerUtils" +/** + * 构造GPData + */ +export function createGPData(moduleType: string, values: Map): GPData { + var now = new Date(); + return new GPData(moduleType, now.getTime(), values) +} + + +export function isAccess(path: string):boolean{ + var isAccess = false + try { + fileio.accessSync(path); + isAccess = true + } catch(err) { + SPLogger.DEBUG(TAG,"accessSync failed with error:"+ err + "path:" + path); + } + return isAccess +} + +/** + * 通用文件节点打开 + * @param path + */ +export function fileOpen(path: string): String { + + if (!isAccess(path)) { + return "null" + } + + try { + var fd = -1 + fd = fileio.openSync(path, 0o0) + let buf = new ArrayBuffer(BUFF_SIZE); + fileio.readSync(fd, buf); + var result: String = String.fromCharCode.apply(null, new Uint8Array(buf)) + SPLogger.DEBUG(TAG,"fileOpen path data:"+result); + return util.printf("%s", result.substring(0, lastIndex(result))).toString() + } catch (err) { + SPLogger.ERROR(TAG,"fileOpen path:" + path + " error:" + err); + } finally { + fileio.closeSync(fd) + } + return "null" +} + +/** + * 通用遍历目录节点 + * @param path + * @param regexp + */ +export function travelFile(path: string, regexp: string): Array { + let dir + let fileNames = [] + + if (!isAccess(path)) { + return [] + } + + try { + dir = fileio.opendirSync(path); + do { + var dirent = dir.readSync() + if (dirent == null) { + break + } + let name: String = dirent.name + if (name.match(regexp)) { + SPLogger.DEBUG(TAG, "travelFile get name:" + dirent.name) + fileNames.push(name) + } + if (regexp == "") { + fileNames.push(name) + } + } while (dirent != null) + } catch (err) { + SPLogger.ERROR(TAG, "travelFile get err:" + err); + SPLogger.ERROR(TAG, "travelFile err path:" + path); + } finally { + dir.closeSync(); + } + return fileNames +} + + + +/** + * 返回字符结尾符坐标 + * @param str + */ +function lastIndex(str) { + var index = -1; + for (var i = 0; i < str.length; i++) { + var temp = str.charCodeAt(i).toString(16); + if (temp == 'a') { + return i; + } + } + return index; +} + +/** + * 睡眠函数 + * @param numberMillis + */ +export function sleep(numberMillis) { + var now = new Date(); + var exitTime = now.getTime() + numberMillis; + while (true) { + now = new Date(); + if (now.getTime() > exitTime) + return; + } +} +/** + * 提取字符串数字 + */ +export function extractNumber(originStr) { + let result = "" + for (var index = 0; index < originStr.length; index++) { + const element: string = originStr[index]; + if (element.match("^[0-9]*$")) { + result += element + } + } + return result +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/profiler/base/ProfilerConstant.ts b/device/device_ui/entry/src/main/ets/common/profiler/base/ProfilerConstant.ts new file mode 100644 index 0000000000000000000000000000000000000000..142b14e0207517602d7d03f13ff419fbf2192d90 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/base/ProfilerConstant.ts @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//trace 状态 +export enum CatchTraceStatus { + catch_trace_start = 1, + // trace采集结束 + catch_trace_finish = 2, + // trace采集第一次运行中 + catch_trace_first_running = 3, + // trace采集运行中 + catch_trace_running = 4, + // trace 采集 停止后间隔60次 + catch_trace_times = 60 +} + +//采集状态 +export enum TaskStatus { + //采集初始化 + task_init = 1, + //采集运行中 + task_running = 2, + //采集暂停 + task_pause = 3, + //采集结束 + task_stop = 4 +} + +//采集项 +export enum CollectorType { + TYPE_CPU = "CPU", + TYPE_GPU = "GPU", + TYPE_DDR = "DDR", + TYPE_FPS = "FPS", + TYPE_HW_COUNTER = "HW_COUNTER", + TYPE_POWER = "POWER", + TYPE_TEMPERATURE = "TEMP", + TYPE_RAM = "RAM", + TYPE_NET = "NETWORK", + TYPE_UNKNOWN = "UNKNOWN" +}; + + + diff --git a/device/device_ui/entry/src/main/ets/common/profiler/base/ProfilerFactory.ets b/device/device_ui/entry/src/main/ets/common/profiler/base/ProfilerFactory.ets new file mode 100644 index 0000000000000000000000000000000000000000..dbe7d78dc36a082dffc8dcc3af719627dea6ea60 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/base/ProfilerFactory.ets @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { CPU } from '../item/CPU' +import { GPU } from '../item/GPU' +import { FPS } from '../item/FPS' +import { Power } from '../item/Power' +import { RAM } from '../item/RAM' +import { Thermal } from '../item/Thermal' +import { DDR } from '../item/DDR' +import { NetWork } from '../item/NetWork'; +import { CollectorType } from './ProfilerConstant' +import { BaseProfiler } from './BaseProfiler' +import SPLogger from '../../../common/utils/SPLogger' + +export class ProfilerFactory { + static getProfilerByConfig(moduleName: string): BaseProfiler{ + if (moduleName == CollectorType.TYPE_FPS) { + SPLogger.DEBUG(ProfilerFactory.name,"getProfilerByConfig:TYPE_FPS" ); + return FPS.getInstance() + } else if (moduleName == CollectorType.TYPE_CPU) { + SPLogger.DEBUG(ProfilerFactory.name,"getProfilerByConfig:TYPE_CPU"); + return CPU.getInstance() + } else if (moduleName == CollectorType.TYPE_GPU) { + SPLogger.DEBUG(ProfilerFactory.name,"getProfilerByConfig:TYPE_GPU" ); + return GPU.getInstance() + } else if (moduleName == CollectorType.TYPE_POWER) { + SPLogger.DEBUG(ProfilerFactory.name,"getProfilerByConfig:TYPE_POWER" ); + return Power.getInstance() + } else if (moduleName == CollectorType.TYPE_RAM) { + SPLogger.DEBUG(ProfilerFactory.name,"getProfilerByConfig:TYPE_RAM" ); + return RAM.getInstance() + } else if (moduleName == CollectorType.TYPE_TEMPERATURE) { + SPLogger.DEBUG(ProfilerFactory.name,"getProfilerByConfig:TYPE_TEMPERATURE" ); + return Thermal.getInstance() + } else if (moduleName == CollectorType.TYPE_DDR) { + SPLogger.DEBUG(ProfilerFactory.name,"getProfilerByConfig:TYPE_DDR"); + return DDR.getInstance() + }else if (moduleName == CollectorType.TYPE_NET) { + SPLogger.DEBUG(ProfilerFactory.name,"getProfilerByConfig:TYPE_NET"); + return NetWork.getInstance() + } + return null + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/profiler/base/SocketProfiler.ets b/device/device_ui/entry/src/main/ets/common/profiler/base/SocketProfiler.ets new file mode 100644 index 0000000000000000000000000000000000000000..98200ab4f8cda04edbb1b9802950ff0fa65ec999 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/base/SocketProfiler.ets @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface SocketProfiler{ + readMessageQueue():void +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/profiler/item/CPU.ets b/device/device_ui/entry/src/main/ets/common/profiler/item/CPU.ets new file mode 100644 index 0000000000000000000000000000000000000000..e47536049909fea4d22dc5a5fd5e5cd781d7798c --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/item/CPU.ets @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import fileio from '@ohos.fileio'; +import { fileOpen, travelFile, createGPData, isAccess} from '../base/BaseProfilerUtils'; +import { BaseProfiler } from '../base/BaseProfiler' +import { CollectorType } from '../base/ProfilerConstant' +import { GPData } from '../../entity/databaseentity'; +import SPLogger from '../../../common/utils/SPLogger' +enum CPU_CONFIG { + CPU_BASE = "/sys/devices/system/cpu", + CPU_CUR_FREQ = "/cpufreq/scaling_cur_freq", + CPU_LOAD = "/proc/stat" +} + +export class CPU extends BaseProfiler { + private cpuMap: Map = new Map + private cpuCoreNum: number + private prebufferArr = ["", "", "", "", "", "", "", "", ""] + + public static instance: CPU = null + public static getInstance() { + if (this.instance == null) { + this.instance = new CPU() + } + return this.instance + } + + init() { + //初始化CPU 核心数 节点路径 + this.cpuCoreNum = travelFile(CPU_CONFIG.CPU_BASE,"cpu[0-9]").length + return CollectorType.TYPE_CPU + } + + isSupport(){ + if(isAccess(CPU_CONFIG.CPU_BASE)&&isAccess(CPU_CONFIG.CPU_LOAD)){ + if (globalThis.checkAccess(CPU_CONFIG.CPU_LOAD) == "PermissionAccessed") { + return true + } + } + return false + } + + readData() { + for (var i = 0;i < this.cpuCoreNum; i++) { + const path = CPU_CONFIG.CPU_BASE + "/cpu" + i + CPU_CONFIG.CPU_CUR_FREQ + var cpu = fileOpen(path) + this.cpuMap.set("cpu" + i + "Freq", cpu) + SPLogger.DEBUG(CPU.name,"profile_readCpu cpu" + i + "freq:" + cpu); + } + return createGPData("CPU", this.cpuMap) + } + + readCPULoad(): GPData { + const path = CPU_CONFIG.CPU_LOAD + var workLoadArr = [] + try { + var fd = -1 + fd = fileio.openSync(path, 0o0) + SPLogger.DEBUG(CPU.name,"readCPULoad fd:" + fd); + let buf = new ArrayBuffer(2048); + fileio.readSync(fd, buf); + let cpuStr: String = String.fromCharCode.apply(null, new Uint8Array(buf)) + SPLogger.DEBUG(CPU.name,"readCPULoad cpuStr:" + cpuStr); + let cpuStrArr = [] + cpuStr = cpuStr.substring(0, cpuStr.indexOf("intr")) + let nextj = 0; + let j + for (var i = 1;i < cpuStr.length; i++) { + if (cpuStr.charAt(i) == 'c') { + j = nextj + nextj = i + cpuStrArr.push(cpuStr.substring(j, nextj)) + } + } + cpuStrArr.push(cpuStr.substring(nextj, nextj + 50)) + let buffer = "" + for (let index = 1;index < cpuStrArr.length; index++) { + buffer = cpuStrArr[index] + let load = this.calCPULoad(buffer, this.prebufferArr[index]) + workLoadArr.push(load) + this.prebufferArr[index] = buffer + } + } catch (err) { + SPLogger.ERROR(CPU.name,"readCPULoad path:" + path + " error:" + err); + } finally { + fileio.closeSync(fd) + } + + let map = new Map + for (let index = 0; index < workLoadArr.length; index++) { + const element = workLoadArr[index]; + map.set("cpu" + index + "Load", element) + } + return createGPData("CPULoad", map) + } + + calCPULoad(buffer: string, pre_buffer: string): number { + + if (pre_buffer.length == 0) { + return -1 + } + let timeArr: string[] = buffer.split(" "); + let pre_timeArr: string[] = pre_buffer.split(" "); + + timeArr.reverse().pop() + pre_timeArr.reverse().pop() + timeArr.reverse() + pre_timeArr.reverse() + + let time = this.ArrStr2Number(timeArr) + let pre_time = this.ArrStr2Number(pre_timeArr) + + let user = time[0] + time[1] - pre_time[0] - pre_time[1]; + let sys = time[2] - pre_time[2]; + let idle = time[3] - pre_time[3]; + let iowait = time[4] - pre_time[4]; + let irq = time[5] + time[6] - pre_time[5] - pre_time[6]; + let total = user + sys + idle + iowait + irq; + if (user < 0 || sys < 0 || idle < 0 || iowait < 0 || irq < 0) { + return 0; + } + let per_user = user * 100.0 / total; + let per_sys = sys * 100.0 / total; + let per_iowait = iowait * 100.0 / total; + let per_irq = irq * 100.0 / total; + let workload = per_user + per_sys + per_iowait + per_irq; + return Number(workload.toFixed(2)).valueOf() + } + + ArrStr2Number(arr: Array): Array { + let result = new Array() + for (var index = 0; index < arr.length; index++) { + const element = arr[index].replace("\n", ""); + result.push(new Number(element).valueOf()) + } + return result + } +} diff --git a/device/device_ui/entry/src/main/ets/common/profiler/item/DDR.ets b/device/device_ui/entry/src/main/ets/common/profiler/item/DDR.ets new file mode 100644 index 0000000000000000000000000000000000000000..d118badcb50575138001d72c6fd575016861c4dd --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/item/DDR.ets @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { fileOpen, createGPData, isAccess} from '../base/BaseProfilerUtils'; +import { BaseProfiler } from '../base/BaseProfiler' +import { CollectorType } from '../base/ProfilerConstant' +import SPLogger from '../../../common/utils/SPLogger' + +enum DDR_CONFIG { + DDR_BASE = "/sys/class/devfreq/ddrfreq/cur_freq" +} + +export class DDR extends BaseProfiler { + private ddrMap: Map = new Map + + public static instance: DDR = null + public static getInstance() { + if (this.instance == null) { + this.instance = new DDR() + } + return this.instance + } + + init() { + //初始化DDR 节点 + return CollectorType.TYPE_DDR + } + + isSupport(){ + if(isAccess(DDR_CONFIG.DDR_BASE)){ + return true + } + return false + } + + readData() { + const path = DDR_CONFIG.DDR_BASE + let ddr = fileOpen(path) + this.ddrMap.set("ddrFreq", ddr) + SPLogger.DEBUG(DDR.name, "profile_readDDR" + ddr); + return createGPData("DDR", this.ddrMap) + } +} diff --git a/device/device_ui/entry/src/main/ets/common/profiler/item/FPS.ets b/device/device_ui/entry/src/main/ets/common/profiler/item/FPS.ets new file mode 100644 index 0000000000000000000000000000000000000000..1fa4443a3b1a6ec1897e810abf0d6d57b1a702a3 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/item/FPS.ets @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createGPData, extractNumber , isAccess} from '../base/BaseProfilerUtils'; +import { BaseProfiler } from '../base/BaseProfiler' +import { CollectorType } from '../base/ProfilerConstant' +import { SocketProfiler } from '../base/SocketProfiler' +import SPLogger from '../../../common/utils/SPLogger' + +export class FPS extends BaseProfiler implements SocketProfiler { + private fpsMap: Map = new Map + + public static instance: FPS = null + public static getInstance() { + if (this.instance == null) { + this.instance = new FPS() + } + return this.instance + } + + init() { + //初始化FPS + return CollectorType.TYPE_FPS + } + + isSupport(){ + return true + } + + readData() { + if (globalThis.useDaemon) { + this.readMessageQueue() + } else { + let fpsStr: string = globalThis.CreateNativeFps(globalThis.collectPkg) + if (fpsStr.length > 0) { + let fpsArr = fpsStr.split("|") + this.fpsMap.set("fps", extractNumber(fpsArr[0])) + let fpsJitters = "\"" + fpsArr[1].split("==").join(",") + "\"" + this.fpsMap.set("fpsJitters", fpsJitters) + globalThis.fpsArr.push(fpsArr[0]) + globalThis.fpsJitterArr.push(fpsArr[1]) + globalThis.timerFps = fpsArr[0] + } + } + return createGPData("FPS", this.fpsMap) + } + + readMessageQueue() { + SPLogger.DEBUG(FPS.name, "messageQueue for fps" + globalThis.fpsArr.length) + if (globalThis.fpsArr.length > 0) { + let fpsQueue: Array = globalThis.fpsArr + let fpsJitterQueue: Array = globalThis.fpsJitterArr + let curFPS = fpsQueue.pop() + let curFPSJitter = fpsJitterQueue.pop() + let fpsJitters = "\"" + curFPSJitter.split("==").join(",") + "\"" + this.fpsMap.set("fpsJitters", fpsJitters) + this.fpsMap.set("fps", extractNumber(curFPS)) + } + } +} diff --git a/device/device_ui/entry/src/main/ets/common/profiler/item/GPU.ets b/device/device_ui/entry/src/main/ets/common/profiler/item/GPU.ets new file mode 100644 index 0000000000000000000000000000000000000000..1ebd21ffad5940c3ee95dca51143e00c64363a12 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/item/GPU.ets @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { fileOpen, createGPData, isAccess} from '../base/BaseProfilerUtils'; +import { BaseProfiler } from '../base/BaseProfiler' +import { CollectorType } from '../base/ProfilerConstant' + +enum GPU_CONFIG { + GPU_FREQ_PATH = "/sys/class/devfreq/fde60000.gpu/cur_freq", //RK + GPU_LOAD_PATH = "/sys/class/devfreq/fde60000.gpu/load", //RK +// GPU_FREQ_PATH = "/sys/class/devfreq/gpufreq/cur_freq", // wgr +// GPU_LOAD_PATH = "/sys/class/devfreq/gpufreq/gpu_scene_aware/utilisation", // wgr +} + +export class GPU extends BaseProfiler { + private gpuMap: Map = new Map + + public static instance: GPU = null + public static getInstance() { + if (this.instance == null) { + this.instance = new GPU() + } + return this.instance + } + + init() { + //初始化GPU + return CollectorType.TYPE_GPU + } + isSupport(){ + if(isAccess(GPU_CONFIG.GPU_FREQ_PATH)&&isAccess(GPU_CONFIG.GPU_LOAD_PATH)){ + return true + } + return false + } + readData() { + console.log("GPU:BaseProfiler called") + let gpuFreq = fileOpen(GPU_CONFIG.GPU_FREQ_PATH) + let gpuLoad = fileOpen(GPU_CONFIG.GPU_LOAD_PATH) + console.log("GPU:BaseProfiler called1111") + let loadStr: string[] = gpuLoad.split("@") + let load = "-1" + if (loadStr.length > 0) { + load = loadStr[0].toString() + }else{ + load = gpuLoad.toString() + } + this.gpuMap.set("gpuFreq", gpuFreq) + this.gpuMap.set("gpuLoad", load) + console.log("GPU:BaseProfiler called2222") + return createGPData("GPU", this.gpuMap) + } +} diff --git a/device/device_ui/entry/src/main/ets/common/profiler/item/NetWork.ets b/device/device_ui/entry/src/main/ets/common/profiler/item/NetWork.ets new file mode 100644 index 0000000000000000000000000000000000000000..33d19170eea6d0aed7fa61caf95bf205c687298b --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/item/NetWork.ets @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createGPData } from '../base/BaseProfilerUtils'; +import { BaseProfiler } from '../base/BaseProfiler' +import { CollectorType } from '../base/ProfilerConstant' +import connection from '@ohos.net.connection' +import SPLogger from '../../../common/utils/SPLogger' + +export class NetWork extends BaseProfiler{ + private netMap: Map = new Map + private catchNetUp = "-1" + private catchNetDown = "-1" + public static instance: NetWork = null + public static getInstance() { + if (this.instance == null) { + this.instance = new NetWork() + } + return this.instance + } + + init() { + //初始化NET + connection.getDefaultNet().then(function (netHandle) { + connection.getNetCapabilities(netHandle).then(function (info) { + if(info != undefined){ + globalThis.isNetAlive = true + }else{ + globalThis.isNetAlive = false + } + }) + }) + return CollectorType.TYPE_NET + } + + isSupport() { + SPLogger.DEBUG(NetWork.name, "networkInfo support:" + globalThis.isNetAlive) + return globalThis.isNetAlive + } + + readData() { + this.handleMessage() + this.netMap.set("netSpeedUp",this.catchNetUp) + this.netMap.set("netSpeedDown",this.catchNetDown) + return createGPData("NetWork", this.netMap) + } + + handleMessage(){ + var that = this + connection.getDefaultNet().then(function (netHandle) { + connection.getNetCapabilities(netHandle).then(function (info) { + SPLogger.DEBUG(NetWork.name,"networkInfo up:" + info["linkUpBandwidthKbps"] ) + SPLogger.DEBUG(NetWork.name,"networkInfo down:" + info["linkDownBandwidthKbps"]) + that.catchNetDown = info["linkDownBandwidthKbps"].toString() + that.catchNetUp = info["linkUpBandwidthKbps"].toString() + }) + }) + } + +} diff --git a/device/device_ui/entry/src/main/ets/common/profiler/item/Power.ets b/device/device_ui/entry/src/main/ets/common/profiler/item/Power.ets new file mode 100644 index 0000000000000000000000000000000000000000..35d69f702e30806acd87960a197084f1d360472c --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/item/Power.ets @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { fileOpen, travelFile, createGPData, isAccess} from '../base/BaseProfilerUtils'; +import { BaseProfiler } from '../base/BaseProfiler' +import { CollectorType } from '../base/ProfilerConstant' +import SPLogger from '../../../common/utils/SPLogger' +enum POWER_CONFIG { + //此目录 fileio 无法读取 需自行适配 +// POWER_PATH = "/data/local/tmp/battery" + POWER_PATH = "/sys/class/power_supply/Battery" // wgr +} + +export class Power extends BaseProfiler { + private powerMap: Map = new Map + private enableSupportItem = ["current_now", "voltage_now", "charge_now", "temp", "status"] + private supportItemKey = [] + + public static instance: Power = null + public static getInstance() { + if (this.instance == null) { + this.instance = new Power() + } + return this.instance + } + + init() { + //初始化Power节点 + let pathNodes = travelFile(POWER_CONFIG.POWER_PATH,"") + pathNodes.forEach(path=>{ + this.enableSupportItem.forEach(item=>{ + if(path == item ){ + this.supportItemKey.push(item) + } + }) + }) + SPLogger.DEBUG(Power.name,"pathNodes init length:"+ pathNodes.length + "support items:" + JSON.stringify(this.supportItemKey)) + return CollectorType.TYPE_POWER + } + + isSupport(){ + if(isAccess(POWER_CONFIG.POWER_PATH)){ + return true + } + return false + } + + readData() { + if (this.supportItemKey.length > 0) { + for (let powerKey of this.supportItemKey) { + let powerValue = fileOpen(POWER_CONFIG.POWER_PATH + "/" + powerKey) + this.powerMap.set(powerKey, powerValue) + } + } + return createGPData("Power", this.powerMap) + } +} diff --git a/device/device_ui/entry/src/main/ets/common/profiler/item/RAM.ets b/device/device_ui/entry/src/main/ets/common/profiler/item/RAM.ets new file mode 100644 index 0000000000000000000000000000000000000000..a7f9a31c45002d13ea33cfdb9da64cbb1d09d066 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/item/RAM.ets @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createGPData, extractNumber } from '../base/BaseProfilerUtils'; +import { BaseProfiler } from '../base/BaseProfiler' +import { CollectorType } from '../base/ProfilerConstant' +import { SocketProfiler} from '../base/SocketProfiler' + +export class RAM extends BaseProfiler implements SocketProfiler{ + private ramMap: Map = new Map + + public static instance: RAM = null + public static getInstance() { + if (this.instance == null) { + this.instance = new RAM() + } + return this.instance + } + + init() { + //初始化RAM节点 + return CollectorType.TYPE_RAM + } + + isSupport(){ + return true + } + + readData() { + if (globalThis.useDaemon) { + this.readMessageQueue() + }else{ + let ramStr:string = globalThis.CreateNativeRam(globalThis.collectPkg) + if (ramStr.length > 0) { + this.ramMap.set("pss", ramStr) + } + } + return createGPData("RAM", this.ramMap) + } + readMessageQueue(){ + if (globalThis.ramArr.length > 0) { + let ramQueue: Array = globalThis.ramArr + let curRAM = ramQueue.pop() + this.ramMap.set("pss", extractNumber(curRAM)) + } + } +} diff --git a/device/device_ui/entry/src/main/ets/common/profiler/item/Thermal.ets b/device/device_ui/entry/src/main/ets/common/profiler/item/Thermal.ets new file mode 100644 index 0000000000000000000000000000000000000000..4c85ebecaa0956687d29447a69a7e1509dda01b1 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/profiler/item/Thermal.ets @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import fileio from '@ohos.fileio'; +import { fileOpen, createGPData, isAccess} from '../base/BaseProfilerUtils'; +import { BaseProfiler } from '../base/BaseProfiler' +import { CollectorType } from '../base/ProfilerConstant' +import SPLogger from '../../../common/utils/SPLogger' +enum THERMAL_CONFIG{ + THERMAL_BASE = "/sys/devices/virtual/thermal" +} + +export class Thermal extends BaseProfiler { + private thermalMap: Map = new Map + private enableSupportItem = [ + "gpu-thermal", + "soc-thermal", + "shell_back", + "shell_front", + "shell_frame", + ] + private supportItemMap = new Map + + public static instance: Thermal = null + public static getInstance() { + if (this.instance == null) { + this.instance = new Thermal() + } + return this.instance + } + + init() { + //初始化Thermal node + var dir + dir = fileio.opendirSync(THERMAL_CONFIG.THERMAL_BASE); + do { + var dirent = dir.readSync() + if (dirent == null ) { + break + } + let name: String = dirent.name + SPLogger.DEBUG(Thermal.name,"thermal_zone name:" + name) + if (name.match("thermal_zone")) { + let typeName = fileOpen(THERMAL_CONFIG.THERMAL_BASE + "/" + dirent.name + "/type") + if (this.enableSupportItem.length > 0) { + this.enableSupportItem.find((item: String) => { + if (typeName.match(item.toString())) { + SPLogger.DEBUG(Thermal.name,"thermal_zone match name:" + typeName) + this.supportItemMap.set(name, item) + SPLogger.DEBUG(Thermal.name,"thermal_zone match name this.supportItemMap:" + this.supportItemMap.size) + } + }) + } + } + } while (dirent != null) + return CollectorType.TYPE_TEMPERATURE + } + + isSupport(){ + if(isAccess(THERMAL_CONFIG.THERMAL_BASE)){ + return true + } + return false + } + + readData() { + if (this.supportItemMap.size > 0) { + let timeZones = this.supportItemMap.keys() + for (let timeZone of timeZones) { + let tempValue = fileOpen(THERMAL_CONFIG.THERMAL_BASE + "/" + timeZone + "/temp") + this.thermalMap.set(this.supportItemMap.get(timeZone),tempValue) + } + } + return createGPData("Temp", this.thermalMap) + } +} + + + diff --git a/device/device_ui/entry/src/main/ets/common/ui/StartTestTitleComponent.ets b/device/device_ui/entry/src/main/ets/common/ui/StartTestTitleComponent.ets new file mode 100644 index 0000000000000000000000000000000000000000..8d83a75b9f5835807fc0cbb228b869a55c3eeb62 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/ui/StartTestTitleComponent.ets @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import router from '@system.router'; + +@Component +export struct StartTestTitleComponent { + private title: string = "开始测试" + + build() { + //开始测试title + Row({ space: '15vp' }) { + Image($r('app.media.icon_back')) + .width('25vp') + .height('15%') + .margin({ left: '5%', top: '30vp' }) + .alignSelf(ItemAlign.Center) + .onClick(() => { + router.back() + }) + + Text(this.title) + .fontSize('20fp') + .fontWeight(FontWeight.Bold) + .fontColor($r("app.color.color_fff")) + .margin({ top: '30vp' }) + }.backgroundColor($r("app.color.colorPrimary")).width('100%').height('12%') + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/ui/detail/Summary.ets b/device/device_ui/entry/src/main/ets/common/ui/detail/Summary.ets new file mode 100644 index 0000000000000000000000000000000000000000..fee3ba383797ff4f1e2dc2b28183f434cc4d8a2f --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/ui/detail/Summary.ets @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { TIndexInfo } from '../../entity/DatabaseEntity'; +import { SummaryItem } from '../../entity/LocalConfigEntity' +import { getCpuCoreInfo, } from '../../utils/SystemUtils'; +import CalculationUtils from '../../utils/CalculationUtils'; +import SPLogger from "../../utils/SPLogger" + +const TAG = "SummaryTAG" +/* + * 报告详情概览页 + */ +@Component +@Preview +export struct Summary { + @State private gpData: Array = new Array() + @State private summaryItems: Array = new Array() + + aboutToAppear() { + SPLogger.DEBUG(TAG,"Summary: aboutToAppear"); + var cpuCoreArr = getCpuCoreInfo() + SPLogger.DEBUG(TAG,"Summary:aboutToAppear: cpuCoreArr:" + cpuCoreArr); + + var cpu0FreqSum: number = 0 + var cpu1FreqSum: number = 0 + var cpu2FreqSum: number = 0 + var cpu3FreqSum: number = 0 + var cpu4FreqSum: number = 0 + var cpu5FreqSum: number = 0 + var cpu6FreqSum: number = 0 + var cpu7FreqSum: number = 0 + var cpuFreqMap = new Map + + var cpuMin: number = 0 + var cpuMid: number = 0 + var cpuMax: number = 0 + + var currentNowSum: number = 0 + var curVoltageSum: number = 0 + var normalCurrentNow: number = 0 + + + var socThermalTemp: number = 0 + var gpuLoadSum: number = 0 + var ddrFreqSum: number = 0 + + // fps和ram 为空时 过滤掉脏数据 0和空 + var fpsNullSum = 0 + var ramNullSum = 0 + + var pssSum: number = 0 + var fpsSum: number = 0 + let fpsMax: number = 0 + let fpsList = [] + let fpsJitters = [] + + for (var index = 0; index < this.gpData.length; index++) { + const gpDataCur = this.gpData[index]; + SPLogger.DEBUG(TAG,"Summary s:" + JSON.stringify(gpDataCur)); + let currentNow = Number(gpDataCur.currentNow).valueOf() + currentNowSum += Math.abs(currentNow) + + let curVoltage = Number(gpDataCur.voltageNow).valueOf() / 1e6 + curVoltageSum += Math.abs(curVoltage) + normalCurrentNow += Math.abs(currentNow) * Math.abs(curVoltage) / 3.8 + + socThermalTemp += Number(gpDataCur.socThermalTemp).valueOf() + gpuLoadSum += Number(gpDataCur.gpuLoad).valueOf() + ddrFreqSum += Number(gpDataCur.ddrFrequency).valueOf() + cpu0FreqSum += Number(gpDataCur.cpu0Frequency).valueOf() + cpu1FreqSum += Number(gpDataCur.cpu1Frequency).valueOf() + cpu2FreqSum += Number(gpDataCur.cpu2Frequency).valueOf() + cpu3FreqSum += Number(gpDataCur.cpu3Frequency).valueOf() + cpu4FreqSum += Number(gpDataCur.cpu4Frequency).valueOf() + cpu5FreqSum += Number(gpDataCur.cpu5Frequency).valueOf() + cpu6FreqSum += Number(gpDataCur.cpu6Frequency).valueOf() + cpu7FreqSum += Number(gpDataCur.cpu7Frequency).valueOf() + + if (gpDataCur.pss == "") { + ramNullSum++ + } + if (gpDataCur.fps == "" || gpDataCur.fps == "0") { + fpsNullSum++ + } + + pssSum += Number(gpDataCur.pss).valueOf() + let fpxCur = Number(gpDataCur.fps).valueOf() + fpsSum += fpxCur + if (fpsMax < fpxCur) { + fpsMax = fpxCur + } + fpsList.push(Number(gpDataCur.fps).valueOf()) + fpsJitters.push(gpDataCur.fpsJitters.toString().replace("\"", "")) + } + + cpuFreqMap.set("cpu0FreqSum", cpu0FreqSum) + cpuFreqMap.set("cpu1FreqSum", cpu1FreqSum) + cpuFreqMap.set("cpu2FreqSum", cpu2FreqSum) + cpuFreqMap.set("cpu3FreqSum", cpu3FreqSum) + cpuFreqMap.set("cpu4FreqSum", cpu4FreqSum) + cpuFreqMap.set("cpu5FreqSum", cpu5FreqSum) + cpuFreqMap.set("cpu6FreqSum", cpu6FreqSum) + cpuFreqMap.set("cpu7FreqSum", cpu7FreqSum) + + SPLogger.DEBUG(TAG,"Summary cpu0FreqSum" + cpu0FreqSum); + SPLogger.DEBUG(TAG,"Summary cpu1FreqSum" + cpu1FreqSum); + SPLogger.DEBUG(TAG,"Summary cpu2FreqSum" + cpu2FreqSum); + SPLogger.DEBUG(TAG,"Summary cpu3FreqSum" + cpu3FreqSum); + SPLogger.DEBUG(TAG,"Summary cpu4FreqSum" + cpu4FreqSum); + SPLogger.DEBUG(TAG,"Summary cpu5FreqSum" + cpu5FreqSum); + SPLogger.DEBUG(TAG,"Summary cpu6FreqSum" + cpu6FreqSum); + SPLogger.DEBUG(TAG,"Summary cpu7FreqSum" + cpu7FreqSum); + SPLogger.DEBUG(TAG,"Summary FpsJitters" + JSON.stringify(fpsJitters)); + + SPLogger.DEBUG(TAG,"Summary:aboutToAppear currentNowSum:" + currentNowSum); + SPLogger.DEBUG(TAG,"Summary:aboutToAppear socThermalTemp:" + socThermalTemp); + SPLogger.DEBUG(TAG,"Summary:aboutToAppear gpuLoadSum:" + gpuLoadSum); + SPLogger.DEBUG(TAG,"Summary:aboutToAppear ddrFreqSum:" + ddrFreqSum); + SPLogger.DEBUG(TAG,"Summary:aboutToAppear cpuFreqMap:" + JSON.stringify(cpuFreqMap)); + + + cpuMin = cpuFreqMap.get("cpu" + 0 + "FreqSum") / 1e3 + cpuMid = cpuFreqMap.get("cpu" +1 + "FreqSum") / 1e3 + cpuMax = cpuFreqMap.get("cpu" + 2 + "FreqSum") / 1e3 + + let calculationTest = new CalculationUtils(fpsList, CalculationUtils.calculateFPSNew(fpsList)) + this.summaryItems.push( + new SummaryItem($r("app.media.icon_normalized_current"), "归一化电流", (normalCurrentNow / this.gpData.length).toFixed(0) + "mA"), + new SummaryItem($r("app.media.icon_max_temperature"), "soc温度", (socThermalTemp / this.gpData.length / 1000 ).toFixed(0) + "℃"), + new SummaryItem($r("app.media.icon_jank_score"), "平均帧率/最高帧率", (fpsSum / (this.gpData.length - fpsNullSum)).toFixed(0) + "Hz" + "/" + (fpsMax).toFixed(0) + "HZ"), + new SummaryItem($r("app.media.icon_jank_score"), "低帧率", (calculationTest.Low_Frame_Rate()).toFixed(2) + "%"), + new SummaryItem($r("app.media.icon_jank_score"), "抖动率", (calculationTest.Jitter_rate()).toFixed(2) + "%"), + new SummaryItem($r("app.media.icon_jank_score"), "卡顿次数", (calculationTest.calculateCaton(fpsJitters)).toFixed(0) + "次"), + new SummaryItem($r("app.media.icon_frame_score"), "GPU负载", (gpuLoadSum / this.gpData.length).toFixed(0) + "%"), + new SummaryItem($r("app.media.icon_frame_score"), "DDR频率", (ddrFreqSum / this.gpData.length / 1e6).toFixed(0) + "MHZ"), + new SummaryItem($r("app.media.icon_average_frame_b"), "CPU0频率", (cpuMin / this.gpData.length).toFixed(0) + "MHZ"), + new SummaryItem($r("app.media.icon_average_frame_b"), "CPU1频率", (cpuMid / this.gpData.length).toFixed(0) + "MHZ"), + new SummaryItem($r("app.media.icon_average_frame_b"), "CPU2频率", (cpuMax / this.gpData.length).toFixed(0) + "MHZ"), + new SummaryItem($r("app.media.icon_jank_each_hour"), "RAM", (pssSum / (this.gpData.length - ramNullSum)).toFixed(0) + "KB") + ) + } + + build() { + Scroll() { + Column() { + Grid() { + ForEach(this.summaryItems, item => { + GridItem() { + Flex({ alignItems: ItemAlign.Center, alignContent: FlexAlign.Start }) { + Row({ space: "8vp" }) { + Image(item.icon).width('50vp').height('50vp') + Text(item.content).fontSize('14fp').textAlign(TextAlign.Start) + Text(item.value).fontSize('11fp').textAlign(TextAlign.Start) + }.alignItems(VerticalAlign.Center) + }.margin({ left: '10' }).borderStyle(BorderStyle.Solid).borderStyle(1).borderColor(Color.Gray) + }.margin({ left: "6%" }) + }, item => item.content) + }.margin({ bottom: "20%" }) + .columnsTemplate('1fr 1fr') + .rowsGap(20) + } + }.height('100%').width('100%') + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/ui/detail/data/DetailCommon.ets b/device/device_ui/entry/src/main/ets/common/ui/detail/data/DetailCommon.ets new file mode 100644 index 0000000000000000000000000000000000000000..c715500991e4389b15531a2cfd161f7a8a1134f6 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/ui/detail/data/DetailCommon.ets @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * FPS丢帧占比类 + * @param key + * @param value + * @param percent + */ +export class FpsLostFrame { + public key: string + public value: string + public percent: string + public color: Resource + + constructor(key: string, value: string, percent: string, color: Resource) { + this.key = key + this.value = value + this.percent = percent + this.color = color + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/ui/detail/utils/HandleLostFrame.ts b/device/device_ui/entry/src/main/ets/common/ui/detail/utils/HandleLostFrame.ts new file mode 100644 index 0000000000000000000000000000000000000000..606a779b2305e1fc43fddd4e6b7ad3db0da887dd --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/ui/detail/utils/HandleLostFrame.ts @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import StringUtils from '../../../utils/StringUtils' +/** + * 处理丢帧 + * @param fullFps + */ +let TAG = "HandleLostFrame" + +export default class HandleLostFrame { + private mFullFps: number; + private mJankArray: Array = Array(21); + + constructor(fullFps: number) { + this.mFullFps = fullFps + let frameTime = 1000 / this.mFullFps + + for (let i = 1; i < 22; i++) { + this.mJankArray[i - 1] = (frameTime * i + frameTime * (i + 1)) / 2 + } + } + + getJankMap(jankSrcStr: String): Map { + if (jankSrcStr == "" || jankSrcStr === undefined) { + return new Map + } + let allDrawFrame: string[] = jankSrcStr.split(",") + let jitters = Array(allDrawFrame.length) + + for (let i = 0; i < allDrawFrame.length; i++) { + console.log(TAG + "allDrawFrame[i]" + i+ allDrawFrame[i]) + if (!isNaN(StringUtils.s2L(allDrawFrame[i]))) { + jitters[i] = StringUtils.s2L(allDrawFrame[i]) + } + } + let jankCountMap: Map = new Map + + for (let i of jitters.keys()) { + + let doubleJank = jitters[i] / 1e6 + console.log(TAG + "for jitters[" + i + "]" + doubleJank) + var jankRange = 0 + jankRange = this.getJankRange(2, doubleJank) + console.log(TAG + "for jankRange" + jankRange) + if (jankRange != 0) { + console.log(TAG + "for jitters[" + jankRange + "]" + jankCountMap.get(jankRange)) + if (jankCountMap.get(jankRange) == null) { + jankCountMap.set(jankRange, 1) + } else { + jankCountMap.set(jankRange, jankCountMap.get(jankRange) + 1) + } + } + } + for (let i = 2; i < 22; i++) { + if (!jankCountMap.has(i)) { + jankCountMap.set(i, 0) + } + } + return jankCountMap + } + + private getJankRange(currRange: number, jank: number): number { + if (currRange > 22) { + return 0 + } + if (currRange == 2) { + if (jank < this.mJankArray[currRange - 2]) { + return 0 + } + } + if (currRange == 22) { + if (jank >= this.mJankArray[currRange - 2]) { + return currRange + } else { + return 0 + } + } + if (jank >= this.mJankArray[currRange - 2] && jank < this.mJankArray[currRange - 1] + ) { + return currRange + } else { + return this.getJankRange(currRange + 1, jank) + } + } +} diff --git a/device/device_ui/entry/src/main/ets/common/ui/floatwindow/FloatWindowConstant.ets b/device/device_ui/entry/src/main/ets/common/ui/floatwindow/FloatWindowConstant.ets new file mode 100644 index 0000000000000000000000000000000000000000..fa3741df7e2e407be2267cfc48a0217fb22ac61a --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/ui/floatwindow/FloatWindowConstant.ets @@ -0,0 +1,31 @@ + /* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export const CURRENTNOW = 0 + +export const SHELLBACKTEMP = 1 + +export const DDRFREQUENCY = 2 + +export const GPUFREQUENCY = 3 + +export const CPU0FREQUENCY = 4 + +export const CPU1FREQUENCY = 5 + +export const CPU2FREQUENCY = 6 + +export const RAM = 6 + +export const FPS = 7 \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/ui/floatwindow/FloatWindowFun.ts b/device/device_ui/entry/src/main/ets/common/ui/floatwindow/FloatWindowFun.ts new file mode 100644 index 0000000000000000000000000000000000000000..b5f22986bbf855a84f80fc14a9c16b77efcc101f --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/ui/floatwindow/FloatWindowFun.ts @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import wm from '@ohos.window' +import SPLogger from '../../utils/SPLogger' + +const TAG = "FloatWindowFun" + +export class FloatWindowFun { + static floatingWindowOffsetX: number = 50 + static floatingWindowOffsetY: number = 200 + static titleWindowOffsetX: number = 300 + static titleWindowOffsetY: number = 200 + static lineChartWindowOffsetX: number= 700 + static lineChartWindowOffsetY: number= 200 + static windowWidth: number = 2560 + static windowHeight: number = 1600 + + + static initAllFun() { + globalThis.CreateFloatingWindow = (() => { + //5.5SP2 2106 改成 8 + wm.create(globalThis.abilityContext, 'floatingWindow', 2106).then((floatWin) => { + floatWin.setWindowMode(102).then(() => { + floatWin.moveTo(this.floatingWindowOffsetX, this.floatingWindowOffsetY).then(() => { + floatWin.resetSize(95, 95).then(() => { + floatWin.getProperties().then((property) => { + property.isTransparent = false + }) + floatWin.loadContent('pages/FloatBall').then(() => { + floatWin.setTransparent(true).then(() => { //透明 + floatWin.show().then(() => { + globalThis.showFloatingWindow = true + }) + + }) + }) + }) + }) + }) + }) + }) + globalThis.MoveFloatingWindow = ((offsetX: number, offsetY: number) => { + var xx = (this.floatingWindowOffsetX + offsetX * 2) < 0 ? 0 : ((this.floatingWindowOffsetX + offsetX * 2) > (this.windowWidth - 200) ? (this.windowWidth - 200) : (this.floatingWindowOffsetX + offsetX * 2)) + var yy = (this.floatingWindowOffsetY + offsetY * 2) < 0 ? 0 : ((this.floatingWindowOffsetY + offsetY * 2) > (this.windowHeight - 200) ? (this.windowHeight - 200) : (this.floatingWindowOffsetY + offsetY * 2)) + + wm.find("floatingWindow").then((fltWin) => { + fltWin.moveTo(xx, yy) + }) + }) + + globalThis.SetFloatingWindowPosition = ((offsetX: number, offsetY: number) => { + this.floatingWindowOffsetX = (this.floatingWindowOffsetX + offsetX * 2) < 0 ? 0 : ((this.floatingWindowOffsetX + offsetX * 2) > (this.windowWidth - 200) ? (this.windowWidth - 200) : (this.floatingWindowOffsetX + offsetX * 2)) + this.floatingWindowOffsetY = (this.floatingWindowOffsetY + offsetY * 2) < 0 ? 0 : ((this.floatingWindowOffsetY + offsetY * 2) > (this.windowHeight - 200) ? (this.windowHeight - 200) : (this.floatingWindowOffsetY + offsetY * 2)) + }) + + globalThis.DestroyFloatingWindow = (() => { + wm.find("floatingWindow").then((fltWin) => { + fltWin.destroy().then(() => { + globalThis.showFloatingWindow = false + }) + }) + }) + + globalThis.CreateTitleWindow = (() => { + wm.create(globalThis.abilityContext, 'TitleWindow', 2106).then((floatWin) => { + floatWin.setWindowMode(102).then(() => { + floatWin.moveTo(this.titleWindowOffsetX, this.titleWindowOffsetY).then(() => { + floatWin.resetSize(350, 260).then(() => { + floatWin.getProperties().then((property) => { + property.isTransparent = false + }) + floatWin.loadContent('pages/TitleWindowPage').then(() => { + floatWin.setTransparent(true) + floatWin.hide() + SPLogger.DEBUG(TAG, 'CreateTitleWindow Done') + }) + }) + }) + }) + }) + }) + + globalThis.MoveTitleWindow = ((offsetX: number, offsetY: number) => { + var xx = (this.titleWindowOffsetX + offsetX * 2) < 0 ? 0 : ((this.titleWindowOffsetX + offsetX * 2) > (this.windowWidth - 500) ? (this.windowWidth - 500) : (this.titleWindowOffsetX + offsetX * 2)) + var yy = (this.titleWindowOffsetY + offsetY * 2) < 0 ? 0 : ((this.titleWindowOffsetY + offsetY * 2) > (this.windowHeight - 330) ? (this.windowHeight - 330) : (this.titleWindowOffsetY + offsetY * 2)) + wm.find("TitleWindow").then((fltWin) => { + fltWin.moveTo(xx, yy) + }) + }) + + globalThis.SetTitleWindowPosition = ((offsetX: number, offsetY: number) => { + this.titleWindowOffsetX = (this.titleWindowOffsetX + offsetX * 2) < 0 ? 0 : ((this.titleWindowOffsetX + offsetX * 2) > (this.windowWidth - 500) ? (this.windowWidth - 500) : (this.titleWindowOffsetX + offsetX * 2)) + this.titleWindowOffsetY = (this.titleWindowOffsetY + offsetY * 2) < 0 ? 0 : ((this.titleWindowOffsetY + offsetY * 2) > (this.windowHeight - 330) ? (this.windowHeight - 330) : (this.titleWindowOffsetY + offsetY * 2)) + }) + + globalThis.DestroyTitleWindow = (() => { + wm.find("TitleWindow").then((fltWin) => { + fltWin.destroy().then(() => { + }) + }) + }) + + globalThis.HideTitleWindow = (() => { + wm.find("TitleWindow").then((fltWin) => { + fltWin.hide() + }) + }) + + globalThis.ShowTitleWindow = (() => { + wm.find("TitleWindow").then((fltWin) => { + fltWin.show() + }) + }) + + globalThis.CreateFPSLineChartWindow = (() => { + //5.5SP2 2106 改成 8 + wm.create(globalThis.abilityContext, 'fpsLineChartWindow', 2106).then((floatWin) => { + floatWin.setWindowMode(102).then(() => { + floatWin.moveTo(this.lineChartWindowOffsetX, this.lineChartWindowOffsetY).then(() => { + floatWin.resetSize(130,90).then(() => { + floatWin.loadContent('pages/FpsLineChartPage').then(() => { + floatWin.show().then(() => { + floatWin.hide() + }) + }) + }) + }) + }) + }) + }) + + globalThis.MoveFPSLineChartWindow = ((offsetX: number, offsetY: number) => { + var xx = (this.lineChartWindowOffsetX + offsetX * 2) < 0 ? 0 : ((this.lineChartWindowOffsetX + offsetX * 2) > (this.windowWidth - 200) ? (this.windowWidth - 200) : (this.lineChartWindowOffsetX + offsetX * 2)) + var yy = (this.lineChartWindowOffsetY + offsetY * 2) < 0 ? 0 : ((this.lineChartWindowOffsetY + offsetY * 2) > (this.windowHeight - 200) ? (this.windowHeight - 200) : (this.lineChartWindowOffsetY + offsetY * 2)) + + wm.find("fpsLineChartWindow").then((fltWin) => { + fltWin.moveTo(xx, yy) + }) + }) + + globalThis.SetFPSLineChartWindowPosition = ((offsetX: number, offsetY: number) => { + this.lineChartWindowOffsetX = (this.lineChartWindowOffsetX + offsetX * 2) < 0 ? 0 : ((this.lineChartWindowOffsetX + offsetX * 2) > (this.windowWidth - 200) ? (this.windowWidth - 200) : (this.lineChartWindowOffsetX + offsetX * 2)) + this.lineChartWindowOffsetY = (this.lineChartWindowOffsetY + offsetY * 2) < 0 ? 0 : ((this.lineChartWindowOffsetY + offsetY * 2) > (this.windowHeight - 200) ? (this.windowHeight - 200) : (this.lineChartWindowOffsetY + offsetY * 2)) + }) + + globalThis.DestroyFPSLineChartWindow = (() => { + wm.find("fpsLineChartWindow").then((fltWin) => { + fltWin.destroy().then(() => { + globalThis.showFPSLineChartWindow = false + }) + }) + }) + + globalThis.HideFPSLineChartWindow = (() => { + wm.find("fpsLineChartWindow").then((fltWin) => { + fltWin.hide() + }) + }) + + globalThis.ShowFPSLineChartWindow = (() => { + wm.find("fpsLineChartWindow").then((fltWin) => { + fltWin.show() + }) + }) + } +} + diff --git a/device/device_ui/entry/src/main/ets/common/ui/floatwindow/utils/FloatWindowUtils.ets b/device/device_ui/entry/src/main/ets/common/ui/floatwindow/utils/FloatWindowUtils.ets new file mode 100644 index 0000000000000000000000000000000000000000..171bdcdb627c60e1f5e16c98284f38e503202563 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/ui/floatwindow/utils/FloatWindowUtils.ets @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import wm from '@ohos.window' + +export let floatingWindowOffsetX: number = 50 +export let floatingWindowOffsetY: number = 200 +export let titleWindowOffsetX: number = 300 +export let titleWindowOffsetY: number = 200 +export let lineChartWindowOffsetX:number=1 +export let lineChartWindowOffsetY:number=1 +export let windowWidth: number = 2560 +export let windowHeight: number = 1600 + +export function initFloatWindow() { + createFloatWindow("currentNow") + createFloatWindow("shellBackTemp") + createFloatWindow("ddrFrequency") + createFloatWindow("gpuFrequency") + createFloatWindow("cpu0Frequency") + createFloatWindow("cpu1Frequency") + createFloatWindow("cpu2Frequency") + createFloatWindow("RAM") +} +export function createFloatWindow(floatName:string) { + //5.5SP2 2106 改成 8 + wm.create(globalThis.abilityContext, floatName, 2106).then((floatWin) => { + floatWin.setWindowMode(102).then(() => { + floatWin.moveTo(lineChartWindowOffsetX, lineChartWindowOffsetY).then(() => { + floatWin.resetSize(240,180).then(() => { + if(floatName=="currentNow"){ + floatWin.loadContent('pages/CurrentNowLineChartPage').then(() => { + floatWin.show().then(() => { + floatWin.hide() + }) + }) + }else if(floatName=="shellBackTemp"){ + floatWin.loadContent('pages/ShellBackTempLineChartPage').then(() => { + floatWin.show().then(() => { + floatWin.hide() + }) + }) + } + else if(floatName=="ddrFrequency"){ + floatWin.loadContent('pages/DDRLineChartPage').then(() => { + floatWin.show().then(() => { + floatWin.hide() + }) + }) + } + else if(floatName=="gpuFrequency"){ + floatWin.loadContent('pages/GPULineChartPage').then(() => { + floatWin.show().then(() => { + floatWin.hide() + }) + }) + } + else if(floatName=="cpu0Frequency"){ + floatWin.loadContent('pages/CPU0LineChartPage').then(() => { + floatWin.show().then(() => { + floatWin.hide() + }) + }) + } + else if(floatName=="cpu1Frequency"){ + floatWin.loadContent('pages/CPU1LineChartPage').then(() => { + floatWin.show().then(() => { + floatWin.hide() + }) + }) + } + else if(floatName=="cpu2Frequency"){ + floatWin.loadContent('pages/CPU2LineChartPage').then(() => { + floatWin.show().then(() => { + floatWin.hide() + }) + }) + } + else if(floatName=="RAM"){ + floatWin.loadContent('pages/RAMLineChartPage').then(() => { + floatWin.show().then(() => { + floatWin.hide() + }) + }) + } + }) + }) + }) + }) +} +export function destoryFloatWindow(floatName:string) { + + wm.find(floatName).then((fltWin) => { + fltWin.destroy().then(() => { + globalThis.showFPSLineChartWindow = false + }) + }) + +} +export function hideFloatWindow(floatName:string) { + + wm.find(floatName).then((fltWin) => { + fltWin.hide() + }) + +} +export function showFloatWindow(floatName:string) { + + wm.find(floatName).then((fltWin) => { + fltWin.show() + }) + +} +export function moveFloatWindow(floatName:string,offsetX: number, offsetY: number) { + var xx = (floatingWindowOffsetX + offsetX * 2) < 0 ? 0 : ((floatingWindowOffsetX + offsetX * 2) > (windowWidth - 200) ? (windowWidth - 200) : (floatingWindowOffsetX + offsetX * 2)) + var yy = (floatingWindowOffsetY + offsetY * 2) < 0 ? 0 : ((floatingWindowOffsetY + offsetY * 2) > (windowHeight - 200) ? (windowHeight - 200) : (floatingWindowOffsetY + offsetY * 2)) + + wm.find(floatName).then((fltWin) => { + fltWin.moveTo(xx, yy) + }) + +} +export function setFloatWindow(offsetX: number, offsetY: number) { + this.floatingWindowOffsetX = (floatingWindowOffsetX + offsetX * 2) < 0 ? 0 : ((floatingWindowOffsetX + offsetX * 2) > (windowWidth - 200) ? (windowWidth - 200) : (floatingWindowOffsetX + offsetX * 2)) + this.floatingWindowOffsetY = (floatingWindowOffsetY + offsetY * 2) < 0 ? 0 : ((floatingWindowOffsetY + offsetY * 2) > (windowHeight - 200) ? (windowHeight - 200) : (floatingWindowOffsetY + offsetY * 2)) +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/ui/main/Home.ets b/device/device_ui/entry/src/main/ets/common/ui/main/Home.ets new file mode 100644 index 0000000000000000000000000000000000000000..fbf96d9cb1626258d2f74ed7d424f3d50659100f --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/ui/main/Home.ets @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import deviceInfo from '@ohos.deviceInfo'; +import router from '@system.router'; +import prompt from '@system.prompt'; +import { TopComponent } from '../main/TopComponent'; +import { otherSupportList, OtherSupport, TestMode } from '../../entity/LocalConfigEntity'; + + +/* + home页 + */ +@Component +export struct Home { + @State private deviceStr: string = '' + @State private versionStr: string = '' + @State private circleHeight: string = '180vp' + @State private circleWidth: string = '180vp' + @State private circleRadius: string = '90vp' + @State opacity: number = 0.6 + + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { + Column() { + Column() { + TopComponent({ title: "SmartPerf " }) + + Text('性能/功耗测试') + .fontSize('18fp') + .fontColor($r("app.color.color_fff")) + .textAlign(TextAlign.Start) + .margin({ top: '20vp' }) + + Stack() { + Circle() + .width('180vp') + .height('180vp') + .fill(Color.White) + .fillOpacity(0) + .border({ radius: '90vp', width: '0.5vp', color: $r("app.color.color_fff") }) + .linearGradient({ + angle: 135, + direction: GradientDirection.Left, + colors: [[$r("app.color.color_80B3193F"), 0.0], [$r("app.color.color_80fff"), 1.0]] + }) + + Text('开始测试') + .fontColor($r('app.color.color_fff')) + .fontSize('20fp') + + Column() { + }.width('220vp') + .height('220vp') + + Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { + } + .width(this.circleWidth) + .height(this.circleHeight) + .border({ width: '1vp', radius: this.circleRadius, color: $r("app.color.color_80fff") }) + .opacity(this.opacity) + .animation({ + duration: 1000, + iterations: -1, + curve: Curve.FastOutLinearIn }) + .onAppear(() => { + this.circleWidth = '220vp' + this.circleHeight = '220vp' + this.circleRadius = '100vp' + this.opacity = 0 + }) + }.onClick(() => { + if (!globalThis.showFloatingWindow) { + router.push({ uri: 'pages/StartTestPage' }) + } else { + prompt.showToast({ message: "已经有应用正在测试,请关闭测试再进行操作", duration: 1000 }) + } + }) + + Text(this.deviceStr) + .fontSize('25fp') + .fontColor($r("app.color.color_fff")) + .fontWeight(FontWeight.Bold) + .textAlign(TextAlign.Start) + .margin({ top: '20vp', bottom: '40vp' }) + }.backgroundColor($r('app.color.colorPrimary')).width('100%') + .alignItems(HorizontalAlign.Center) + .onAppear(() => { + this.deviceStr = deviceInfo.brand + " " + deviceInfo.productModel + }) + + GridExample() + } + }.width('100%').height('100%') + } +} + +@Component +struct GridExample { + @State support: Array = otherSupportList + + build() { + Column({ space: 5 }) { + Grid() { + ForEach(this.support, (otherSupport) => { + GridItem() { + Column() { + Image(otherSupport.resource).width(60) + .height(60) + Text(otherSupport.testName) + .fontSize('13fp') + .fontColor($r("app.color.color_333")) + .height('30%') + .textAlign(TextAlign.Center) + + Text(otherSupport.testSrc) + .fontSize('10fp') + .fontColor($r("app.color.color_999")) + .height('30%') + .textAlign(TextAlign.Center) + } + } + .backgroundColor($r("app.color.color_fff")) + .width('100%') + .margin({ top: '10vp' }) + .padding({ top: '8vp', right: '20vp', bottom: '8vp', left: '20vp' }) + .onClick(() => { + if (otherSupport.testMode == TestMode.ONLINE) { + prompt.showToast({ message: "开发中" }) + } else if (otherSupport.testMode == TestMode.BRIGHTNESS) { + router.push({ uri: 'pages/LightAdjust' }) + } + }) + }, otherSupport => otherSupport.testName) + } + .columnsTemplate('1fr 1fr 1fr') + .rowsTemplate('1fr 1fr 1fr') + .width('100%') + .height(450) + }.width('100%').height('100%').backgroundColor('#EEEEEE') + } +} diff --git a/device/device_ui/entry/src/main/ets/common/ui/main/HomeBottomPage.ets b/device/device_ui/entry/src/main/ets/common/ui/main/HomeBottomPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..e5432d6bab783d1ce913da7c482c33bbc3a3f3b4 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/ui/main/HomeBottomPage.ets @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * 主页底部tab + */ +@Component +export struct HomeBottomPage { + @Link currentPage: number + imgW = '60px' + imgH = '60px' + + build() { + Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + + Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center, direction: FlexDirection.Column }) { + if (this.currentPage == 0) { + Image($r('app.media.icon_home_selected')).width(this.imgW).height(this.imgH) + Text('首页').fontSize('12vp').fontColor($r("app.color.colorPrimary")) + } else { + Image($r('app.media.icon_home_unselected')).width(this.imgW).height(this.imgH) + Text('首页').fontSize('12vp').fontColor(Color.Black) + } + } + .onClick(() => { + this.currentPage = 0 + }) + .backgroundColor($r("app.color.color_fff")) + .width('180px') + .height('100%') + + Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center, direction: FlexDirection.Column }) { + if (this.currentPage == 1) { + Image($r('app.media.icon_report_selected')).width(this.imgW).height(this.imgH) + Text('报告').fontSize('12vp').fontColor($r("app.color.colorPrimary")) + } else { + Image($r('app.media.icon_report_unselected')).width(this.imgW).height(this.imgH) + Text('报告').fontSize('12vp').fontColor(Color.Black) + } + } + .onClick(() => { + this.currentPage = 1 + }) + .backgroundColor($r("app.color.color_fff")) + .width('180px') + .height('100%') + + Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center, direction: FlexDirection.Column }) { + if (this.currentPage == 2) { + Image($r('app.media.icon_mine_selected')).width(this.imgW).height(this.imgH) + Text('我的').fontSize('12vp').fontColor($r("app.color.colorPrimary")) + } else { + Image($r('app.media.icon_mine_unselected')).width(this.imgW).height(this.imgH) + Text('我的').fontSize('12vp').fontColor(Color.Black) + } + } + .onClick(() => { + this.currentPage = 2 + }) + .backgroundColor($r("app.color.color_fff")) + .width('180px') + .height('100%') + } + .backgroundColor($r("app.color.color_fff")) + .width('100%') + .height('12%') + } +} diff --git a/device/device_ui/entry/src/main/ets/common/ui/main/Mine.ets b/device/device_ui/entry/src/main/ets/common/ui/main/Mine.ets new file mode 100644 index 0000000000000000000000000000000000000000..6b90577b76270866f235191434acdb94dec228c9 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/ui/main/Mine.ets @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import router from '@system.router'; +import { TopComponent } from '../main/TopComponent'; +import { secToTime } from '../../utils/TimeUtils'; + +/** + * 我的页面 + */ +@Component +export struct Mine { + build() { + Column({ space: '15vp' }) { + TopComponent({ title: "我的" }) + + Image($r('app.media.person')) + .width('80vp') + .height('80vp') + .margin({ top: '30vp' }) + + Text('test') + .height('20vp') + .fontSize('14vp') + .fontColor(0xeeeeee) + .alignSelf(ItemAlign.Center) + + Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceAround }) { + Column() { + Image($r('app.media.test_apps_count')) + .width('40vp') + .height('40vp') + + Text('测试总app数') + .fontSize('16vp') + .margin('20vp') + .fontColor(0xeeeeee) + + Text(String(globalThis.sumTestApp)) + .fontColor(0xeeeeee) + } + + Column() { + Image($r('app.media.test_session_count')) + .width('40vp') + .height('40vp') + + Text('测试总局数') + .fontSize('16vp') + .margin('20vp') + .fontColor(0xeeeeee) + + Text(String(globalThis.sumTest)) + .fontColor(0xeeeeee) + } + + Column() { + Image($r('app.media.test_times_count')) + .width('40vp') + .height('40vp') + + Text('测试总时长') + .fontSize('16vp') + .margin('20vp') + .fontColor(0xeeeeee) + + Text(secToTime(globalThis.sumTestTime).toString()) + .fontColor(0xeeeeee) + } + + }.margin({ top: '15vp' }) + + Column({ space: '10vp' }) { + Row() { + Image($r('app.media.question')).width('20vp').height('20vp').margin({ left: '10vp' }) + Text('常见问题').fontSize('16vp').margin('5vp') + } + .width('100%') + .backgroundColor(0xeeeeee) + .height('35vp') + .borderRadius('5vp') + .onClick( + res => { + router.push({ uri: 'pages/Question' }) + } + ).margin({bottom:5}) + + Row() { + Image($r('app.media.settings')) + .width('20vp') + .height('20vp') + .margin({ left: '10vp' }) + Text('设置').fontSize('16vp').margin('5vp') + } + .width('100%') + .height('35vp') + .backgroundColor(0xeeeeee) + .borderRadius('5vp') + .onClick( + res => { + router.push({ uri: 'pages/SettingsPage' }) + } + ) + }.width('95%') + + }.backgroundColor($r('app.color.colorPrimary')) + .width('100%') + .height('100%') + } +} diff --git a/device/device_ui/entry/src/main/ets/common/ui/main/Report.ets b/device/device_ui/entry/src/main/ets/common/ui/main/Report.ets new file mode 100644 index 0000000000000000000000000000000000000000..108b43ff971cd3fb719073169ca86c63d7a91a31 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/ui/main/Report.ets @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import prompt from '@system.prompt'; +import router from '@system.router'; +import database from '../../database/DatabaseUtils'; +import { secToTime } from '../../utils/TimeUtils'; +import { ReportItem } from '../../entity/LocalConfigEntity'; +import { TopComponent } from '../main/TopComponent'; + +@Component +@Preview +export struct Report { + @State private reportItem: Array = globalThis.reportList + + build() { + Column() { + Row() { + TopComponent({ title: "报告" }) + }.backgroundColor($r("app.color.colorPrimary")) + .width('100%') + .padding({ bottom: '15vp' }) + + List({ space: '20vp', initialIndex: 0 }) { + ForEach(this.reportItem, (item) => { + + ListItem() { + + Flex({ + direction: FlexDirection.Row, + alignItems: ItemAlign.Start, + justifyContent: FlexAlign.SpaceBetween + }) { + Row() { + Image(globalThis.iconMap.get(item.packageName)) + .width('60vp') + .height('60vp') + .padding('10vp') + + Flex({ + direction: FlexDirection.Column, + alignItems: ItemAlign.Start, + justifyContent: FlexAlign.SpaceBetween + }) { + Text(`${item.name}`).fontSize('15fp') + + Text(`${item.appName}`).fontSize('15fp').backgroundColor(0xFFFFFF) + + Text(`${item.startTime}`).fontSize('15fp').backgroundColor(0xFFFFFF) + + Text(secToTime(item.testDuration).toString()).fontSize('15fp').backgroundColor(0xFFFFFF) + } + + Image($r("app.media.report_upload")) + .width('40vp') + .height('40vp') + .padding('10vp') + .margin({ left: 800 }) + .onClick(function (item) { + prompt.showToast({ message: "报告上传功能正在开发中", duration: 1000 }) + }) + + }.margin({ left: '5%', top: '2%', bottom: '2%', right: '2%' }).onClick(() => { + let databasePath: string = item.dbPath + //截取时间戳 + let timeStamp = databasePath.substring(databasePath.lastIndexOf("/") + 1, databasePath.length) + database.queryData(timeStamp + ".db").then(data => { + router.push({ uri: 'pages/ReportDetail', params: { + gpData: data, + reportItem: item + } }) + }) + }) + } + } + }, item => item.toString()) + } + .edgeEffect(EdgeEffect.None) // 滑动到边缘无效果 + .chainAnimation(false) // 联动特效关闭 + .listDirection(Axis.Vertical) // 排列方向 + .divider({ strokeWidth: '2vp', color: 0xdddddd, startMargin: '10vp', endMargin: '12vp' }) // 每行之间的分界线 + + }.height('88%') + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/ui/main/TopComponent.ets b/device/device_ui/entry/src/main/ets/common/ui/main/TopComponent.ets new file mode 100644 index 0000000000000000000000000000000000000000..9146a695f0bd966e6bb7d9a792fa80ac53e8287b --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/ui/main/TopComponent.ets @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * home页、报告页、我的页面top栏 + */ +@Component +export struct TopComponent { + @State title: string = "SmartPerf" + + build() { + //开始测试title + Text(this.title) + .width('100%') + .height('8%') + .fontSize('20fp') + .fontWeight(FontWeight.Bold) + .fontColor($r("app.color.color_fff")) + .alignSelf(ItemAlign.Start) + .textAlign(TextAlign.Start) + .margin({ left: '15vp', top: '30vp' }) + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/utils/AbilityUtils.ts b/device/device_ui/entry/src/main/ets/common/utils/AbilityUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..2a26d1637463fb9bc6455abc0ce016821ee395ee --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/utils/AbilityUtils.ts @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import SPLogger from './SPLogger' +const TAG = "AbilityUtils" +/** + * 启动ability since API8 + * @param bundleName + * @param abilityName + */ +export function commonStartAbility(bundleName: string, abilityName: string, parameters?: { [key: string]: any }) { + SPLogger.INFO(TAG, "Operation bundleName:" + bundleName + "Operation abilityName:" + abilityName); + let str = { + "bundleName": bundleName, + "abilityName": abilityName, + "parameters": parameters + } + console.info(abilityName + ' Operation after. Cause:'); + globalThis.abilityContext.startAbility(str, (err, data) => { + if (err) { + SPLogger.ERROR(TAG,abilityName + ' Operation failed. Cause:' + JSON.stringify(err)); + return; + } + SPLogger.INFO(TAG,abilityName + ' Operation successful. Data: ' + JSON.stringify(data)) + }); +} + + + + + diff --git a/device/device_ui/entry/src/main/ets/common/utils/BundleMangerUtils.ts b/device/device_ui/entry/src/main/ets/common/utils/BundleMangerUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..b87ed0ad0893017c899835122f91174f93de1c18 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/utils/BundleMangerUtils.ts @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import bundle from '@ohos.bundle'; +import ResMgr from '@ohos.resourceManager'; +import { AppInfoItem } from '../entity/LocalConfigEntity'; +import SPLogger from '../utils/SPLogger' +/** + * 包管理 获取应用列表、icon、app名称 + */ +const TAG = "BundleManager" +export default class BundleManager { + static async getResourceManager(context, bundleName, then?: Function) { + if (!then) { + return await ResMgr.getResourceManager(context, bundleName); + } + ResMgr.getResourceManager(context, bundleName).then(then) + } + + //根据包名获取base64 + static async getIconByBundleName(mBundleNameArr: Array): Promise> { + let mBundleNames = Array.from(new Set(mBundleNameArr)) + let mMap = new Map + bundle.getAllApplicationInfo(8, 100).then(async data => { + await + SPLogger.INFO(TAG,'getIconByBundleName data length [' + data.length + ']'); + for (let j = 0; j < data.length; j++) { + let bundleName = data[j].name + for (let i = 0; i < mBundleNames.length; i++) { + if (mBundleNames[i] == bundleName) { + let item = await BundleManager.getResourceManager(globalThis.abilityContext, mBundleNames[i]) + let icon = await item.getMediaBase64(data[j].iconId) + mMap.set(mBundleNames[i], icon) + } + } + } + }) + return mMap + } + + //获取app列表 + static async getAppList(): Promise> { + let appInfoList = new Array() + bundle.getAllApplicationInfo(8, 100).then(async data => { + await + SPLogger.INFO(TAG,'xxx getAllApplicationInfo data length [' + data.length + ']') + for (let i = 0; i < data.length; i++) { + let bundleName = data[i].name + let item = await BundleManager.getResourceManager(globalThis.abilityContext, bundleName) + try { + let appName = await item.getString(data[i].labelId) + let icon = await item.getMediaBase64(data[i].iconId) + bundle.getBundleInfo(bundleName, 1).then(bundleData => { + BundleManager.getAbility(bundleName).then(abilityName => { + console.info("index[" + i + "].getAbility for begin data: ", abilityName); + appInfoList.push(new AppInfoItem(data[i].name, appName, bundleData.versionName, icon, abilityName)) + }); + }) + } catch (err) { + SPLogger.ERROR(TAG,"index[" + i + "] getAllApplicationInfo err" + err); + } + } + }) + return appInfoList + } + //获取启动ability + static async getAbility(bundleName: string): Promise { + let abilityName = ""; + try { + await bundle.queryAbilityByWant({ + bundleName: bundleName, + entities: [ + "entity.system.home", + ], + action: + "action.system.home", + }, 1, 100).then(abilityInfo => { + if (abilityInfo != null) { + abilityName = abilityInfo[0].name; + } + }) + } catch (err) { + SPLogger.ERROR(TAG,"index[" + bundleName + "] getAbility err" + err); + } + SPLogger.INFO(TAG,"index[" + bundleName + "] getAbility abilityName: " + abilityName); + return abilityName; + } +} + + + + + + diff --git a/device/device_ui/entry/src/main/ets/common/utils/CSVUtils.ts b/device/device_ui/entry/src/main/ets/common/utils/CSVUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..c80213261af4dd7fc6c404368174655d22eb0d24 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/utils/CSVUtils.ts @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { TGeneralInfo } from '../entity/DatabaseEntity'; +import { TIndexInfo } from '../entity/DatabaseEntity'; + +//垂直生成 TGenneralInfo to string +export function csvGeneralInfo(tGeneralInfo: TGeneralInfo): string { + let data = "" + for (let k of Object.keys(tGeneralInfo)) { + data += k + "," + tGeneralInfo[k] + "\n" + } + return data +} + +//水平生成 TIndexInfo to string +export function csvTIndexInfo(tIndexInfos: Array): string { + let tittle = csvTIndexInfoTittle() + let data = "" + for (var index = 0; index < tIndexInfos.length; index++) { + const t = tIndexInfos[index]; + for (let k of Object.keys(t)) { + data += t[k] + "," + } + data += "\n" + } + let result = tittle + data + return result +} + +//水平生成 TIndexInfo TITTLE to string +export function csvTIndexInfoTittle(): string { + var tIndexInfo: TIndexInfo = new TIndexInfo() + let data = "" + for (let k of Object.keys(tIndexInfo)) { + data += k + "," + } + data = data.substring(0, data.lastIndexOf(",")) + data += "\n" + return data +} + + + + + diff --git a/device/device_ui/entry/src/main/ets/common/utils/CalculationUtils.ts b/device/device_ui/entry/src/main/ets/common/utils/CalculationUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..812e8766828d4599f7abfa543d0118db3ed1fc48 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/utils/CalculationUtils.ts @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * 计算工具类 + * @param fpsList + * @param gameFPS + */ +export default class CalculationUtils { + public TAG: String = "CalculationTest" + public size: number + public gameFPS: number + //所有fps的集合 + public fpsList: Array = [] + //最低帧数 + public point: number + //低于point帧数的数量 + public count: number = 0 + //所有帧数总和 + private fpsSum: number + + constructor(fpsList: Array, gameFPS: number) { + let removeList: Array = new Array() + for (let i = 0;i < fpsList.length; i++) { + if (i < 0) { + removeList.push(i) + } + } + fpsList.filter((item) => { + return removeList.indexOf(item) < 0 + }) + this.fpsList = fpsList + this.size = fpsList.length + this.gameFPS = gameFPS + this.point = gameFPS == 30 ? 25 : gameFPS == 40 ? 30 : gameFPS == 60 ? 45 : 10 + } + + //抖动率计算 + Jitter_rate(): number { + let jitterRite = 0; + let size = this.fpsList.length; + + let numOfDiff3To = 0; + let numOfDiff5To = 0; + let numOfDiff8To = 0; + let numOfDiff12To = 0; + let numOfDiff16To = 0; + + let numOfDiff3To5 = 0; + let numOfDiff5To8 = 0; + let numOfDiff8To12 = 0; + let numOfDiff6To10 = 0; + let numOfDiff10To16 = 0; + + for (let i = 1; i < size; i++) { + let diff = Math.abs(this.fpsList[i] - this.fpsList[i - 1]); + if (diff > 3) { + numOfDiff3To++; + } + if (diff > 5) { + numOfDiff5To++; + } + if (diff > 8) { + numOfDiff8To++; + } + if (diff > 12) { + numOfDiff12To++; + } + if (diff > 16) { + numOfDiff16To++; + } + if (diff > 3 && diff <= 5) { + numOfDiff3To5++; + } + if (diff > 5 && diff <= 8) { + numOfDiff5To8++; + } + if (diff > 8 && diff <= 12) { + numOfDiff8To12++; + } + if (diff > 6 && diff <= 10) { + numOfDiff6To10++; + } + if (diff > 10 && diff <= 16) { + numOfDiff10To16++; + } + } + + let percentOf3To = 0; + let percentOf5To = 0; + let percentOf8To = 0; + let percentOf12To = 0; + let percentOf16To = 0; + + let percentOf3To5 = 0; + let percentOf5To8 = 0; + let percentOf8To12 = 0; + let percentOf6To10 = 0; + let percentOf10To16 = 0; + + if (size != 1) { + percentOf3To = numOfDiff3To / size; + percentOf5To = numOfDiff5To / size; + percentOf8To = numOfDiff8To / size; + percentOf12To = numOfDiff12To / size; + percentOf16To = numOfDiff16To / size; + + percentOf3To5 = numOfDiff3To5 / size; + percentOf5To8 = numOfDiff5To8 / size; + percentOf8To12 = numOfDiff8To12 / size; + percentOf6To10 = numOfDiff6To10 / size; + percentOf10To16 = numOfDiff10To16 / size; + } + if (this.gameFPS == 25 || this.gameFPS == 30) { + jitterRite = percentOf3To * 100; + } + if (this.gameFPS == 40 || this.gameFPS == 45) { + jitterRite = (percentOf3To5 * 0.4 + percentOf5To * 0.6) * 100; + } + if (this.gameFPS == 60) { + jitterRite = (percentOf3To5 * 0.2 + percentOf5To8 * 0.3 + percentOf8To * 0.5) * 100; + } + if (this.gameFPS == 90) { + jitterRite = (percentOf5To8 * 0.2 + percentOf8To12 * 0.3 + percentOf12To * 0.5) * 100; + } + if (this.gameFPS == 120) { + jitterRite = (percentOf6To10 * 0.2 + percentOf10To16 * 0.3 + percentOf16To * 0.5) * 100; + } + return jitterRite; + } + + //低帧率计算 + Low_Frame_Rate(): number { + for (let i = 0; i < this.fpsList.length; i++) { + if (this.fpsList[i] < this.point) { + this.count++; + } + } + return this.count / this.size * 100; + } + + //卡顿次数 100ms + calculateCaton(fpsJitterList: Array): number{ + let num = 0 + for (let i = 0; i < fpsJitterList.length; i++) { + let jitter = fpsJitterList[i].split(","); + for (let j = 0; j < jitter.length; j++) { + var n = Number(jitter[j]); + if (!isNaN(n) && (n / 1e6 > 100)) { + num++ + } + } + } + return num + } + + //满帧计算 + static calculateFPSNew(fpsList: Array): number { + let FPS = 30 + let moreThan34Count = 0 + let moreThan44Count = 0 + let moreThan70Count = 0 + let moreThan100Count = 0 + for (let i in fpsList) { + if (fpsList[i] >= 100) { + moreThan100Count++ + } else if (fpsList[i] >= 70) { + moreThan70Count++ + } else if (fpsList[i] >= 44) { + moreThan44Count++ + } else if (fpsList[i] >= 34) { + moreThan34Count++ + } + } + if (moreThan100Count >= 1) { + FPS = 120 + } else if (moreThan70Count >= 1) { + FPS = 90 + } else if (moreThan44Count >= 1) { + FPS = 60 + } else if (moreThan34Count >= 1) { + FPS = 45 + } + return FPS + } +} diff --git a/device/device_ui/entry/src/main/ets/common/utils/CheckEmptyUtils.ts b/device/device_ui/entry/src/main/ets/common/utils/CheckEmptyUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..fb5f3ff5dbd69d3c3fdf19e55d0d066087d7c4b8 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/utils/CheckEmptyUtils.ts @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default class CheckEmptyUtils { + + /** + * Check obj is empty. + * + * @param {Object} obj need checked object + * @return {boolean} true(empty) + */ + static isEmpty(obj) { + return (typeof obj === 'undefined' || obj === null || obj === '' || Object.keys(obj).length === 0); + } + + /** + * Check str is empty. + * + * @param {string} str need checked string + * @return {boolean} true(empty) + */ + static checkStrIsEmpty(str) { + return str.trim().length === 0; + } + + /** + * Check array is empty. + * + * @param {Array} arr need checked array + * @return {boolean} true(empty) + */ + static isEmptyArr(arr) { + return arr.length === 0; + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/utils/GameUtils.ets b/device/device_ui/entry/src/main/ets/common/utils/GameUtils.ets new file mode 100644 index 0000000000000000000000000000000000000000..be1993db93312cf7371d5f93d19f88ed7392048f --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/utils/GameUtils.ets @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * 计算工具类 + */ +export default class GameUtils { + // 30,40,60 连续丢帧>=3帧 为一般卡顿 + static GENERAL_CATON_FLAG_LOW: number = 3 + // 30,40,60 连续丢帧>=6帧 为严重卡顿 + static CRITICAL_CATON_FLAG_LOW: number = 6 + // 30,40,60 连续丢帧>=9帧 为致命卡顿 + static FATAL_CATON_FLAG_LOW: number = 9 + // 90,120 连续丢帧>=4帧 为一般卡顿 + static GENERAL_CATON_FLAG_HIGHT: number = 4 + // 90,120 连续丢帧>=8帧 为严重卡顿 + static CRITICAL_CATON_FLAG_HIGHT: number = 8 + // 90,120 连续丢帧>=12帧 为致命卡顿 + static FATAL_CATON_FLAG_HIGHT: number = 12 + + // 连续丢帧数组长度 + private static JANK_SIZE: number = 21; + private static JANK_RANGE_ARRAY_120 = new Array(GameUtils.JANK_SIZE); + private static JANK_RANGE_ARRAY_90 = new Array(GameUtils.JANK_SIZE); + private static JANK_RANGE_ARRAY_60 = new Array(GameUtils.JANK_SIZE); + private static JANK_RANGE_ARRAY_40 = new Array(GameUtils.JANK_SIZE); + private static JANK_RANGE_ARRAY_30 = new Array(GameUtils.JANK_SIZE); + private constructor() { + } + + /** + * 方法描述 计算满帧 + * + * @param maxFps maxFps + * @return java.lang.Integer get full fps + */ + static getFullFps(maxFps: number): number { + /*关于满帧判定,把所有帧率做一次遍历: + * 1、只要有>=100帧,则判断为120帧 + * 2、否则只要有>=70 且所有帧都小于100,则判断为90帧 + * 1、否则只要有>=44 并且 所有帧都小于70的情况,就按照满帧60帧 + * 2、只要有>=34,且所有帧率均小于44的,就按照满帧40帧 + * 3、如果所有帧率均小于34帧的,就按照满帧30 + */ + + if (maxFps >= 100) { + return 120; + } else if (maxFps >= 70) { + return 90; + } else if (maxFps >= 44) { + return 60; + } else if (maxFps >= 34) { + return 40; + } + return 30; + } + + /** + * 获得低帧率的计算标准 + */ + private static getBaseLowFPS(gameFPS: number): number { + if (gameFPS >= 60) { + return 45; + } else if (gameFPS == 40) { + return 30; + } else if (gameFPS == 30) { + return 25; + } + return 20; // 25时候返回20 + } + + /** + * 方法描述 计算帧率中位数 + * + * @param fpsList fpsList + * @return java.lang.Integer fps + */ + private static getMedianFrameRadio(fpsArray: Array): number { + if (null == fpsArray || fpsArray.length == 0) { + return null; + } + + fpsArray.sort() + + let length = fpsArray.length; + + if (length % 2 == 0) { + return ((fpsArray[fpsArray.length / 2] + fpsArray[fpsArray.length / 2 - 1]) / 2); // 偶数个取中间两个数的平均数 + } else { + return fpsArray[fpsArray.length / 2]; // 奇数个取最中间那个数 + } + } + + /** + * 判断电池容量/平均电流等数据是否有效 + * @param value + */ + public static isFloatDataValid(value: number): boolean { + if (null == value || value < 0 || Math.abs(value - 0) < 0.001) { + return false; + } + return true; + } + + /** + * 方法描述 计算kpi抖动率的得分(y=100*EXP(-0.458*x)) + * + * @param param param + * @return java.lang.Integer 得分 + */ + private static getFpsJitterScore(param: number): number{ + if (null == param) { + return null; + } + return Math.round(100.0 * Math.exp(-0.458 * 100 * param)); + } + + public static createJankStr(jankSrcStr: string, fullFPS: number, JankMap: Map): string { + if (null == jankSrcStr || jankSrcStr == "") { + return "NA"; + } + + // 初始化连续丢帧数组 + GameUtils.initJankArray(fullFPS); + + let allDrawFrame: Array = jankSrcStr.split(","); + let jitters = new Array(allDrawFrame.length); + for (let i = 0; i < allDrawFrame.length; i++) { + try { + jitters[i] = parseInt(allDrawFrame[i]); + } catch (e) { + e.printStackTrace(); + } + } + + let jitterStr = "NA"; + let jankCountMap = new Map(); + jitters.forEach(jank => { + let doubleJank = jank / 1e6; + let jankRange = 0; + if (fullFPS == 120) { + jankRange = GameUtils.getJankRange(GameUtils.JANK_RANGE_ARRAY_120, 2, doubleJank); + } else if (fullFPS == 90) { + jankRange = GameUtils.getJankRange(GameUtils.JANK_RANGE_ARRAY_90, 2, doubleJank); + } else if (fullFPS == 60) { + jankRange = GameUtils.getJankRange(GameUtils.JANK_RANGE_ARRAY_60, 2, doubleJank); + } else if (fullFPS == 40) { + jankRange = GameUtils.getJankRange(GameUtils.JANK_RANGE_ARRAY_40, 2, doubleJank); + } else { + jankRange = GameUtils.getJankRange(GameUtils.JANK_RANGE_ARRAY_30, 2, doubleJank); + } + + if (jankRange != 0) { + if (jankCountMap.get(jankRange) == null) { + jankCountMap.set(jankRange, 1); + } else { + jankCountMap.set(jankRange, jankCountMap.get(jankRange) + 1); + } + } + }); + + for (let j = 2; j <= 22; j++) { + if (!jankCountMap.has(j)) { + jankCountMap.set(j, 0); + } + } + + let jitterBuilder = new String(); + + let allKeysIterator = jankCountMap.keys(); + + for (var i = 0; i < jankCountMap.size; i++) { + let key: number = allKeysIterator.next().value + let jankKey = key == 22 ? ">20" : String(key - 1); + jitterBuilder.concat(jankKey).concat(":").concat(String(jankCountMap.get(key))).concat(";"); + JankMap.set(jankKey, jankCountMap.get(key)); + } + + jitterStr = jitterBuilder.slice(0, jitterBuilder.length); + return jitterStr; + } + + private static initJankArray(fullFps: number) { + switch (fullFps) { + case 120: + GameUtils.calJankArray(GameUtils.JANK_RANGE_ARRAY_120, 8.333); + break; + case 90: + GameUtils.calJankArray(GameUtils.JANK_RANGE_ARRAY_90, 11.1111); + break; + case 60: + GameUtils.calJankArray(GameUtils.JANK_RANGE_ARRAY_60, 16.667); + break; + case 40: + GameUtils.calJankArray(GameUtils.JANK_RANGE_ARRAY_40, 25.0); + break; + case 30: + GameUtils.calJankArray(GameUtils.JANK_RANGE_ARRAY_30, 33.333); + break; + default: + break; + } + } + + /** + * 方法描述 + * + * @param jankRangeArray 连续丢帧数组 + * @param defaultJankTime 默认单帧时间 + */ + private static calJankArray(jankRangeArray: Array, defaultJankTime: number) { + if (jankRangeArray[0] < 0.01) { + for (let i = 1; i <= GameUtils.JANK_SIZE; i++) { + jankRangeArray[i - 1] = (defaultJankTime * i + defaultJankTime * (i + 1)) / 2; + } + } + } + + private static getJankRange(jankRangeArray: Array, currRange: number, jank: number): number{ + if (currRange > 22) { + return 0; + } + if (currRange == 2) { + if (jank < jankRangeArray[currRange - 2]) { + return 0; + } + } + if (currRange == 22) { + if (jank >= jankRangeArray[currRange - 2]) { + return currRange; + } else { + return 0; + } + } + if (jank >= jankRangeArray[currRange - 2] && jank < jankRangeArray[currRange - 1]) { + return currRange; + } else { + return GameUtils.getJankRange(jankRangeArray, currRange + 1, jank); + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/utils/IOUtils.ts b/device/device_ui/entry/src/main/ets/common/utils/IOUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..49030ca51b7c73701fb18ccb286defdd4866d309 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/utils/IOUtils.ts @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import fileio from '@ohos.fileio'; +import SPLogger from '../utils/SPLogger' +/** + * create file by path + * @param path + * @param data + */ +const TAG = "IOUtils" +export function createFilePath(path: string, data: string) { + SPLogger.INFO(TAG,"createFilePath called:" + path); + let writer + try { + fileio.mkdirSync(globalThis.abilityContext.getApplicationContext().filesDir + "/" + globalThis.dbTime) + } catch (err) { + SPLogger.INFO(TAG,"createFilePath:mkdirSync" + err); + } + + try { + writer = fileio.openSync(path, 0o102, 0o666); + fileio.writeSync(writer, data); + SPLogger.INFO(TAG,"createFilePath:WRITER SUCCESS"); + } catch (err) { + SPLogger.INFO(TAG,"createFilePath:err" + err); + } finally { + fileio.closeSync(writer); + } +} + + + + + diff --git a/device/device_ui/entry/src/main/ets/common/utils/JsonUtils.ets b/device/device_ui/entry/src/main/ets/common/utils/JsonUtils.ets new file mode 100644 index 0000000000000000000000000000000000000000..8edf9dfd96614326b7522b38a06870efbef9af9a --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/utils/JsonUtils.ets @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default { + _mapToJson(map: Map): string{ + var obj = Object.create(null); + + var iterator = map.keys(); + for (var i = 0; i < map.size; i++) { + var key = iterator.next().value; + obj[key] = map.get(key); + } + return JSON.stringify(obj); + } +} + + + + diff --git a/device/device_ui/entry/src/main/ets/common/utils/SPLogger.ts b/device/device_ui/entry/src/main/ets/common/utils/SPLogger.ts new file mode 100644 index 0000000000000000000000000000000000000000..b6c905d3dd16241cf4d4bc90b54a91680caf5e48 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/utils/SPLogger.ts @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export default class SPLogger { + //控制所有 + private static isPrintLog = true + //控制debug + private static isPrintDebugLog = true + //控制info + private static isPrintInfoLog = true + //控制warn + private static isPrintWarnLog = true + //控制error + private static isPrintErrorLog = true + + private static bastTag = "SmartPerf:" + + //debug debug日志 + static DEBUG(tag: string, msg: string) { + if (SPLogger.isPrintLog && SPLogger.isPrintDebugLog) { + console.debug(SPLogger.bastTag + tag + "," + msg) + } + } + + //info 级别日志 + static INFO(tag: string, msg: string) { + if (SPLogger.isPrintLog && SPLogger.isPrintInfoLog) { + console.info(SPLogger.bastTag + tag + "," + msg) + } + } + + //warn 级别日志 + static WARN(tag: string, msg: string) { + if (SPLogger.isPrintLog && SPLogger.isPrintWarnLog) { + console.warn(SPLogger.bastTag + tag + "," + msg) + } + } + + //error 级别日志 + static ERROR(tag: string, msg: string) { + if (SPLogger.isPrintLog && SPLogger.isPrintErrorLog) { + console.error(SPLogger.bastTag + tag + "," + msg) + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/utils/StringUtils.ts b/device/device_ui/entry/src/main/ets/common/utils/StringUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..4c26e1326bc34a78aac14c9d74adaad64746c3f5 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/utils/StringUtils.ts @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * 字符串工具类 + */ +export default class StringUtils { + static s2L(src: string): number { + let result = -1; + if (typeof src == "undefined" || src == null || src == "") { + return result; + } + try { + result = parseInt(src); + return result; + } catch (e) { + e.printStackTrace(); + return result; + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/common/utils/SystemUtils.ets b/device/device_ui/entry/src/main/ets/common/utils/SystemUtils.ets new file mode 100644 index 0000000000000000000000000000000000000000..bb2316723d2f7c8a64f43cd8ef30ab5f2114495d --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/utils/SystemUtils.ets @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { fileOpen, travelFile } from '../profiler/base/BaseProfilerUtils'; +import { ProcessRunningInfo } from '../utils/../entity/SystemEntity' +import appManager from '@ohos.application.appManager'; + +export function getCpuCoreInfo(): Array { + const basePath = "/sys/devices/system/cpu/cpufreq" + let defaultPolicy = new Array( + "policy0", "policy1", "policy2" + ) + var supportPolicy = [] + let policyArr = travelFile(basePath, "policy") + + policyArr.forEach((policy) => { + defaultPolicy.forEach((defaultItem) => { + if (defaultItem == policy) { + supportPolicy.push(defaultItem) + } + }) + }) + var coreArr = new Array() + for (var index = 0; index < supportPolicy.length; index++) { + const policy = supportPolicy[index]; + var affected_cpus = fileOpen(basePath + "/" + policy + "/affected_cpus") + coreArr.push(affected_cpus.charAt(0)) + } + return coreArr +} + +export function getPidOfAbility(processName: string): Promise { + return appManager.getProcessRunningInfos().then(data => { + let processArr: Array = data + var pid = "-1" + processArr.forEach(process=>{ + if (process.processName == processName) { + pid = process.pid.toString() + } + }) + return pid + }) +} + + diff --git a/device/device_ui/entry/src/main/ets/common/utils/TimeUtils.ts b/device/device_ui/entry/src/main/ets/common/utils/TimeUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..41eb2ba24c6921682f28beeb9d906ae247b0917d --- /dev/null +++ b/device/device_ui/entry/src/main/ets/common/utils/TimeUtils.ts @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * 日期格式化 + * @param Number time 时间戳 + * @param String format 格式 + */ +export function dateFormat(time?: number, format: string='Y-m-d h:i:s') { + const t = new Date(time) + // 日期格式 + format = format || 'Y-m-d h:i:s' + let year = t.getFullYear() + // 由于 getMonth 返回值会比正常月份小 1 + let month = t.getMonth() + 1 + let day = t.getDate() + let hours = t.getHours() + let minutes = t.getMinutes() + let seconds = t.getSeconds() + + const hash = { + 'y': year, + 'm': month, + 'd': day, + 'h': hours, + 'i': minutes, + 's': seconds + } + // 是否补 0 + const isAddZero = (o) => { + return /m|d|h|i|s/.test(o) + } + return format.replace(/\w/g, o => { + let rt = hash[o.toLocaleLowerCase()] + return rt > 9 || !isAddZero(o) ? rt : `0${rt}` + }) +} +/** + * 计时器 转 时分秒字符串 HH:mm:ss + * @param time + */ +export function secToTime(time: number): String { + var timeStr: String = null + var hour: number = 0 + var minute: number = 0 + var second: number = 0 + if (time <= 0) { + return "00:00" + } else { + minute = parseInt((time / 60).toString()) + if (minute < 60) { + second = time % 60 + timeStr = unitFormat(minute) + ":" + unitFormat(second) + } else { + hour = parseInt((minute / 60).toString()) + minute = minute % 60 + second = time - hour * 3600 - minute * 60 + timeStr = + unitFormat(hour) + ":" + unitFormat(minute) + ":" + unitFormat(second) + } + } + return timeStr +} + +export function unitFormat(i: number): String { + var retStr: String + if (i >= 0 && i < 10) { + retStr = "0" + i.toString() + } else { + retStr = "" + i.toString() + } + return retStr +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/AppSelectPage.ets b/device/device_ui/entry/src/main/ets/pages/AppSelectPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..84cab70ffd554418108500b637423a8d9611b60b --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/AppSelectPage.ets @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { StartTestTitleComponent } from '../common/ui/StartTestTitleComponent'; +import { AppInfoItem } from '../common/entity/LocalConfigEntity'; +import router from '@system.router'; + +/** + * app应用选择页 + */ +@Entry +@Component +struct AppSelectPage { + build() { + Column() { + StartTestTitleComponent({ title: "选择应用" }) + appInfoComponent() + }.width('100%').height('100%') + } +} + +@Component +struct appInfoComponent { + @State appInfoList: Array = globalThis.appList + + build() { + List() { + ForEach(this.appInfoList, (appInfoItem) => { + + ListItem() { + Row() { + Image(appInfoItem.appIcon).width('40vp').height('40vp').margin({ left: '2%' }) + Flex({ + justifyContent: FlexAlign.SpaceBetween, + alignItems: ItemAlign.Start, + direction: FlexDirection.Column + }) { + Text(appInfoItem.appName) + .fontSize('15fp') + .fontColor($r("app.color.color_333")) + .fontWeight(FontWeight.Bold) + Text(appInfoItem.appVersion).fontSize('12fp').fontColor($r("app.color.color_333")) + Divider().vertical(false).margin({ top: '5vp' }).height('1vp') + }.margin({ left: '4%' }).height('100%').padding({ top: '20vp' }) + }.alignSelf(ItemAlign.Start).width('100%').height('80vp').onClick(() => { + if (router.getParams()["StartPage"] == "StartTest") { + router.back({ uri: "pages/StartTestPage", params: { + selectPackageName: appInfoItem.packageName, + selectAbilityName: appInfoItem.abilityName, + appName: appInfoItem.appName, + appVersion: appInfoItem.appVersion, + appIconId: appInfoItem.appIcon + } }) + } + }) + } + }, appInfoItem => appInfoItem.packageName) + }.edgeEffect(EdgeEffect.None) // 滑动到边缘无效果 + .chainAnimation(false) // 联动特效关闭 + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/CPU0LineChartPage.ets b/device/device_ui/entry/src/main/ets/pages/CPU0LineChartPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..13c701f9743ec1857b8d8b5844fa404864126e2e --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/CPU0LineChartPage.ets @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hideFloatWindow} from '../common/ui/floatwindow/utils/floatwindowutils' +import { FloatWindowComponent } from '../common/FloatWindowComponent' +import { TaskStatus } from '../common/profiler/base/ProfilerConstant'; + +@Entry +@Component +struct CPU0LineChartPage { + data: number[]= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] //数据集合 + @State random: number= 0 //用于刷新的随机数 + @State cpu0Frequency: number= 0 //数值 + + offsetX: number = -1 //悬浮框移动触摸点 X + offsetY: number = -1 //悬浮框移动触摸点 X + private floatName: string= "cpu0Frequency" + task_state = 1 + + aboutToAppear() { + globalThis.LineChartCollect = setInterval(() => { + this.task_state = globalThis.task_status + if (this.task_state == TaskStatus.task_running) { + if (this.data.length >= 22) { + this.data.shift() //移除第一个元素 + } + if (globalThis.tTndex.cpu0Frequency == undefined) { + this.cpu0Frequency = 0 + } else { + this.cpu0Frequency = parseInt(globalThis.tTndex.cpu0Frequency) / 1e3 + + if (this.cpu0Frequency == 0) { + this.data.push(0) + } else { + let lineCount: number = this.cpu0Frequency / 30 + this.data.push(Math.abs(lineCount)) //在末尾填充一个元素 + } + this.random = Math.random() + } + } else { + //暂停 + } + + }, 1000) + } + + build() { + Stack({ alignContent: Alignment.Top }) { + FloatWindowComponent({ title: `cpu0Frequency`, data: this.data }) + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text(this.floatName + ":" + this.cpu0Frequency + "Hz") + .fontSize('6fp') + .fontColor($r("app.color.color_333")) + .margin({ left: 5, top: 3 }) //文本显示 + Text(this.random + "") + .fontSize('1fp') + .fontColor($r("app.color.color_333")).visibility(Visibility.None) + Image($r("app.media.icon_close_small")).width('15vp').height('15vp').onClick(() => { + hideFloatWindow(this.floatName) + + }).align(Alignment.TopEnd) + }.height('15vp').width('100%').opacity(0.2) + + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/CPU1LineChartPage.ets b/device/device_ui/entry/src/main/ets/pages/CPU1LineChartPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..7c8f8a0e933f1c63cf0e0f86738fad64fb2a460f --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/CPU1LineChartPage.ets @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hideFloatWindow } from '../common/ui/floatwindow/utils/floatwindowutils' +import { FloatWindowComponent } from '../common/FloatWindowComponent' +import { TaskStatus } from '../common/profiler/base/ProfilerConstant'; + +@Entry +@Component +struct CPU1LineChartPage { + data: number[]= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] //数据集合 + @State random: number= 0 //用于刷新的随机数 + @State cpu1Frequency: number= 0 //数值 + + offsetX: number = -1 //悬浮框移动触摸点 X + offsetY: number = -1 //悬浮框移动触摸点 X + private floatName: string= "cpu1Frequency" + task_state = 1 + + aboutToAppear() { + globalThis.LineChartCollect = setInterval(() => { + this.task_state = globalThis.task_status + if (this.task_state == TaskStatus.task_running) { + if (this.data.length >= 22) { + + this.data.shift() //移除第一个元素 + } + if (globalThis.tTndex.cpu4Frequency == undefined) { + this.cpu1Frequency = 0 + } else { + this.cpu1Frequency = parseInt(globalThis.tTndex.cpu4Frequency) / 1e3 + + if (this.cpu1Frequency == 0) { + this.data.push(0) + } else { + let lineCount: number = this.cpu1Frequency / 30 + this.data.push(Math.abs(lineCount)) //在末尾填充一个元素 + } + this.random = Math.random() + + } + } else { + //暂停 + } + }, 1000) + } + + build() { + Stack({ alignContent: Alignment.Top }) { + FloatWindowComponent({ title: `cpu1Frequency`, data: this.data }) + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text(this.floatName + ":" + this.cpu1Frequency + "Hz") + .fontSize('6fp') + .fontColor($r("app.color.color_333")) + .margin({ left: 5, top: 3 }) //文本显示 + Text(this.random + "") + .fontSize('1fp') + .fontColor($r("app.color.color_333")).visibility(Visibility.None) + Image($r("app.media.icon_close_small")).width('15vp').height('15vp').onClick(() => { + hideFloatWindow(this.floatName) + console.log("hideFloatWindow---------------------" + this.floatName) + }).align(Alignment.TopEnd) + }.height('15vp').width('100%') + + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/CPU2LineChartPage.ets b/device/device_ui/entry/src/main/ets/pages/CPU2LineChartPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..4f25eb542e8cd4921cd60b34e8a4dbcbd7c86142 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/CPU2LineChartPage.ets @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import {hideFloatWindow} from '../common/ui/floatwindow/utils/floatwindowutils' +import { FloatWindowComponent } from '../common/FloatWindowComponent' +import { TaskStatus } from '../common/profiler/base/ProfilerConstant'; + +@Entry +@Component +struct CPU2LineChartPage { + data: number[]= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] //数据集合 + @State random: number= 0 //用于刷新的随机数 + @State cpu2Frequency: number= 0 //数值 + + offsetX: number = -1 //悬浮框移动触摸点 X + offsetY: number = -1 //悬浮框移动触摸点 X + private floatName: string= "cpu2Frequency" + task_state = 1 + + aboutToAppear() { + globalThis.LineChartCollect = setInterval(() => { + this.task_state = globalThis.task_status + if (this.task_state == TaskStatus.task_running) { + if (this.data.length >= 22) { + + this.data.shift() //移除第一个元素 + } + if (globalThis.tTndex.cpu7Frequency == undefined) { + this.cpu2Frequency = 0 + } else { + this.cpu2Frequency = parseInt(globalThis.tTndex.cpu7Frequency) / 1e3 + + if (this.cpu2Frequency == 0) { + this.data.push(0) + } else { + let lineCount: number = this.cpu2Frequency / 30 + this.data.push(Math.abs(lineCount)) //在末尾填充一个元素 + } + this.random = Math.random() + } + } else { + //暂停 + } + }, 1000) + } + + build() { + Stack({ alignContent: Alignment.Top }) { + FloatWindowComponent({ title: `cpu2Frequency`, data: this.data }) + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text(this.floatName + ":" + this.cpu2Frequency + "Hz") + .fontSize('6fp') + .fontColor($r("app.color.color_333")) + .margin({ left: 5, top: 3 }) //文本显示 + Text(this.random + "") + .fontSize('1fp') + .fontColor($r("app.color.color_333")).visibility(Visibility.None) + Image($r("app.media.icon_close_small")).width('15vp').height('15vp').onClick(() => { + hideFloatWindow(this.floatName) + console.log("hideFloatWindow---------------------" + this.floatName) + }).align(Alignment.TopEnd) + }.height('15vp').width('100%') + + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/CurrentNowLineChartPage.ets b/device/device_ui/entry/src/main/ets/pages/CurrentNowLineChartPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..e7ddaf0a48e869067ac9c86ee15dce70c8343ecd --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/CurrentNowLineChartPage.ets @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import {hideFloatWindow} from '../common/ui/floatwindow/utils/floatwindowutils' +import { FloatWindowComponent } from '../common/FloatWindowComponent' +import { TaskStatus } from '../common/profiler/base/ProfilerConstant'; + +@Entry +@Component +struct CurrentNowLineChartPage { + data: number[]= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] //数据集合 + @State random: number= 0 //用于刷新的随机数 + @State currentNow: number= 0 //数值 + + offsetX: number = -1 //悬浮框移动触摸点 X + offsetY: number = -1 //悬浮框移动触摸点 X + private floatName: string= "currentNow" + task_state = 1 + + aboutToAppear() { + globalThis.LineChartCollect = setInterval(() => { + this.task_state = globalThis.task_status + if (this.task_state == TaskStatus.task_running) { + if (this.data.length >= 22) { + + this.data.shift() //移除第一个元素 + } + if (globalThis.tTndex.currentNow == undefined) { + this.currentNow = 0 + } else { + this.currentNow = globalThis.tTndex.currentNow + + if (this.currentNow == 0) { + this.data.push(0) + } else { + let lineCount: number = this.currentNow / 30 + this.data.push(Math.abs(lineCount)) //在末尾填充一个元素 + } + this.random = Math.random() + } + } else { + //暂停 + } + }, 1000) + } + + build() { + Stack({ alignContent: Alignment.Top }) { + FloatWindowComponent({ title: `currentNow`, data: this.data }) + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text(this.floatName + ":" + this.currentNow + "mA") + .fontSize('6fp') + .fontColor($r("app.color.color_333")) + .margin({ left: 5, top: 3 }) //文本显示 + Text(this.random + "") + .fontSize('1fp') + .fontColor($r("app.color.color_333")).visibility(Visibility.None) + Image($r("app.media.icon_close_small")).width('15vp').height('15vp').onClick(() => { + hideFloatWindow(this.floatName) + console.log("hideFloatWindow---------------------" + this.floatName) + }).align(Alignment.TopEnd) + }.height('15vp').width('100%') + + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/DDRLineChartPage.ets b/device/device_ui/entry/src/main/ets/pages/DDRLineChartPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..ba8dff5709b4be6f3cb825a738b7140e9528cde7 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/DDRLineChartPage.ets @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hideFloatWindow } from '../common/ui/floatwindow/utils/floatwindowutils' +import { FloatWindowComponent } from '../common/FloatWindowComponent' +import { TaskStatus } from '../common/profiler/base/ProfilerConstant'; + +@Entry +@Component +struct DDRNowLineChartPage { + data: number[]= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] //数据集合 + @State random: number= 0 //用于刷新的随机数 + @State DDR: number= 0 //数值 + + offsetX: number = -1 //悬浮框移动触摸点 X + offsetY: number = -1 //悬浮框移动触摸点 X + private floatName: string= "ddrFrequency" + task_state = 1 + + aboutToAppear() { + globalThis.LineChartCollect = setInterval(() => { + this.task_state = globalThis.task_status + if (this.task_state == TaskStatus.task_running) { + if (this.data.length >= 22) { + + this.data.shift() //移除第一个元素 + } + if (globalThis.tTndex.ddrFrequency == undefined) { + this.DDR = 0 + } else { + this.DDR = Number(globalThis.tTndex.ddrFrequency / 1e6).valueOf() + + if (this.DDR == 0) { + this.data.push(0) + } else { + let lineCount: number = this.DDR / 30 + this.data.push(Math.abs(lineCount)) //在末尾填充一个元素 + } + this.random = Math.random() + } + } else { + //暂停 + } + }, 1000) + } + + build() { + Stack({ alignContent: Alignment.Top }) { + FloatWindowComponent({ title: `ddrFrequency`, data: this.data }) + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text(this.floatName + ":" + this.DDR + "MHz") + .fontSize('6fp') + .fontColor($r("app.color.color_333")) + .margin({ left: 5, top: 3 }) //文本显示 + Text(this.random + "") + .fontSize('1fp') + .fontColor($r("app.color.color_333")).visibility(Visibility.None) + Image($r("app.media.icon_close_small")).width('15vp').height('15vp').onClick(() => { + hideFloatWindow(this.floatName) + + console.log("hideFloatWindow---------------------" + this.floatName) + }).align(Alignment.TopEnd) + }.height('15vp').width('100%') + + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/FloatBall.ets b/device/device_ui/entry/src/main/ets/pages/FloatBall.ets new file mode 100644 index 0000000000000000000000000000000000000000..a0c5f087eca37a7790d979c91da70d9ef6b3875f --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/FloatBall.ets @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { secToTime } from '../common/utils/TimeUtils'; +import { TaskStatus,CatchTraceStatus} from '../common/profiler/base/ProfilerConstant'; +import { MainWorker } from "../common/profiler/MainWorkTask" +import { ProfilerTask } from "../common/profiler/ProfilerTask" +import { initFloatWindow } from '../common/ui/floatwindow/utils/floatwindowutils' +let traceTime = 0 +let socketCollectItems +let isCollectRam = false + +@Entry +@Component +struct FloatBall { + @State playerState: number = TaskStatus.task_init + @State timerNum: number = 0 + @State FpsTimer: number = -1 + timerId: number = -1 + @State windShowState: boolean = false + @State windFpsShowState: boolean = false + offsetX: number = -1 + offsetY: number = -1 + //解決手势失效的问题 + COUNTS = 2 // 点击次数 + DURATION: number = 300 // 规定有效时间 + mHits = Array(this.COUNTS) // 数组 + isDoubleFlag = false // 是否是双击 + singleClickId = 0 // 单击事件ID + + aboutToAppear() { + + ProfilerTask.getInstance().initModule() + ProfilerTask.getInstance().taskInit() + //创建TiTile窗 + globalThis.CreateTitleWindow() + globalThis.CreateFPSLineChartWindow() + globalThis.task_status = TaskStatus.task_init + initFloatWindow() + if (globalThis.collectConfigs.trace) { + globalThis.catchTraceState = CatchTraceStatus.catch_trace_start + globalThis.jitterTrace = false + } + + } + + initAllCollect() { + if (globalThis.collectConfigs != -1 && globalThis.collectPkg != -1) { + globalThis.collectIntervalCollect = setInterval(() => { + if (globalThis.timerFps == undefined) { + } else { + this.FpsTimer = globalThis.timerFps + } + if (this.playerState == TaskStatus.task_running) { + ProfilerTask.getInstance().taskStart() + } + }, 1000) + globalThis.collectSocketCollect = setInterval(() => { + if (this.playerState == TaskStatus.task_running) { + this.timerNum++ + isCollectRam = false + if ((globalThis.collectIntervalNum % 5 == 0) && globalThis.collectConfigs.RAM) { + isCollectRam = true + } else { + isCollectRam = false + } + + socketCollectItems = { + "pkg": globalThis.collectPkg, + "ram": isCollectRam, + "fps": globalThis.collectConfigs.FPS, + "screen_capture": globalThis.collectConfigs.screen_capture, + "is_video": globalThis.collectConfigs.is_video, + "is_camera": globalThis.collectConfigs.is_camera + } + + if (globalThis.collectConfigs.trace) { + this.taskTrace(socketCollectItems) + } + MainWorker.postMessage(socketCollectItems) + } + }, 1000) + } + globalThis.task_status = TaskStatus.task_running + this.playerState = TaskStatus.task_running + } + + getJitterTrace() { + if (globalThis.fpsJitterArr != undefined && globalThis.fpsJitterArr != null && globalThis.fpsJitterArr != "") { + let tempQueue: Array = globalThis.fpsJitterArr + let curJitter = tempQueue.pop() + let tempJitterArr = curJitter.split("==") + for (var i = 0; i < tempJitterArr.length; i++) { + let tmp = tempJitterArr[i] + let jitter = parseInt(tmp) / 1e6 + if (jitter > 100) { + globalThis.jitterTrace = true + return + } + } + } + } + + taskTrace(defaultSocketCollectItems) { + if (globalThis.catchTraceState == CatchTraceStatus.catch_trace_start) { //开始 + defaultSocketCollectItems["catch_trace_start"] = true + globalThis.catchTraceState = CatchTraceStatus.catch_trace_first_running + } else if (globalThis.catchTraceState == CatchTraceStatus.catch_trace_finish) { //抓取 + defaultSocketCollectItems["catch_trace_finish"] = true + defaultSocketCollectItems["traceName"] = this.timerNum + "" + globalThis.catchTraceState = CatchTraceStatus.catch_trace_running; + traceTime = 0 + } else if (globalThis.catchTraceState == CatchTraceStatus.catch_trace_first_running) { //第一次运行 + if (globalThis.jitterTrace) { //抓取 + defaultSocketCollectItems["catch_trace_finish"] = true + defaultSocketCollectItems["traceName"] = this.timerNum + "" + globalThis.catchTraceState = CatchTraceStatus.catch_trace_running; + traceTime = 0 + globalThis.jitterTrace = false + } + } else if (globalThis.catchTraceState == CatchTraceStatus.catch_trace_running) { //有时间间隔的运行 + traceTime++ + if (traceTime > CatchTraceStatus.catch_trace_times) { + globalThis.catchTraceState = CatchTraceStatus.catch_trace_start + } + } + socketCollectItems = defaultSocketCollectItems + } + + singleEvent() { + if (this.playerState == TaskStatus.task_running) { + globalThis.task_status = TaskStatus.task_pause + this.playerState = TaskStatus.task_pause + } + else if (this.playerState == TaskStatus.task_pause) { + globalThis.task_status = TaskStatus.task_running + this.playerState = TaskStatus.task_running + } + } + + fpsEvent(){ + if (this.windFpsShowState) { + globalThis.HideFPSLineChartWindow() + this.windFpsShowState = false + } else { + globalThis.ShowFPSLineChartWindow() + this.windFpsShowState = true + } + } + + doubleEvent() { + // 双击启动悬浮TITLE + if (this.windShowState) { + globalThis.HideTitleWindow() + this.windShowState = false + } else { + globalThis.ShowTitleWindow() + this.windShowState = true + } + } + + longEvent() { + ProfilerTask.getInstance().taskStop() + this.destroyAllWindow() + this.clearAllInterVal() + } + + destroyAllWindow(){ + globalThis.DestroyFloatingWindow() + globalThis.DestroyTitleWindow() + globalThis.DestroyFPSLineChartWindow() + } + + clearAllInterVal(){ + clearInterval(globalThis.collectIntervalCollect) + clearInterval(globalThis.collectSocketCollect) + clearInterval(globalThis.collectOtherSocket) + } + + MoveWindow(offsetX: number, offsetY: number) { + globalThis.MoveFloatingWindow(offsetX, offsetY) + } + + SetWindowPosition(offsetX: number, offsetY: number) { + globalThis.SetFloatingWindowPosition(offsetX, offsetY) + } + + build() { + Stack({ alignContent: Alignment.Center }) { + if (this.playerState == TaskStatus.task_init) { + Circle() + .width('90vp') + .height('90vp') + .fill(Color.White) + .fillOpacity(0) + .opacity(0.8) + .border({ radius: '90vp', width: '0.5vp', color: $r("app.color.colorPrimary") }) + .linearGradient({ + angle: 135, + direction: GradientDirection.Left, + colors: [[$r("app.color.colorPrimary"), 1.0], [$r("app.color.colorPrimary"), 1.0]] + }) + Text('start') + .fontSize(20) + .textAlign(TextAlign.Center) + .fontColor($r("app.color.color_fff")) + .width('100%') + .height('100%') + .onClick(() => { + this.initAllCollect() + }) + .gesture( + GestureGroup(GestureMode.Exclusive, + TapGesture({ count: 2 }) + .onAction(() => { + this.doubleEvent() + }), + PanGesture({}) + .onActionStart(() => { + }) + .onActionUpdate((event: GestureEvent) => { + this.offsetX = event.offsetX + this.offsetY = event.offsetY + }) + .onActionEnd(() => { + this.MoveWindow(this.offsetX, this.offsetY) + this.SetWindowPosition(this.offsetX, this.offsetY) + }) + )) + } + + if (this.playerState == TaskStatus.task_running || this.playerState == TaskStatus.task_pause) { + if (this.playerState == TaskStatus.task_pause) { + Circle() + .width('90vp') + .height('90vp') + .fill(Color.White) + .fillOpacity(0) + .opacity(0.8) + .border({ radius: '90vp', width: '0.5vp', color: $r("app.color.color_666") }) + .linearGradient({ + angle: 135, + direction: GradientDirection.Left, + colors: [[$r("app.color.color_666"), 0.7], [$r("app.color.color_666"), 0.7]] + }) + }else{ + Circle() + .width('90vp') + .height('90vp') + .fill(Color.White) + .fillOpacity(0) + .opacity(0.5) + .border({ radius: '90vp', width: '0.5vp', color: $r("app.color.colorPrimary") }) + .linearGradient({ + angle: 135, + direction: GradientDirection.Left, + colors: [[$r("app.color.colorPrimary"), 0.7], [$r("app.color.colorPrimary"), 0.7]] + }) + } + Text(secToTime(this.timerNum).toString()) + .fontSize(20) + .textAlign(TextAlign.Center) + .fontColor($r("app.color.color_fff")) + .width('100%') + .height('100%') + .onClick(res => { + this.isDoubleFlag = false + for(let i = 0; i < this.mHits.length - 1; i++) { + this.mHits[i] = this.mHits[i + 1] + } + this.mHits[this.mHits.length - 1] = new Date().getTime() + if(this.mHits[0] >= new Date().getTime() - this.DURATION) { + this.doubleEvent() + this.isDoubleFlag = true + this.mHits = Array(this.COUNTS) + } else { + this.singleClickId = setTimeout(()=>{ + if(!this.isDoubleFlag) { + this.singleEvent() + } + }, 300) + } + }) + .gesture( + GestureGroup(GestureMode.Exclusive, + LongPressGesture({ fingers: 1, repeat: false, duration: 1000 }) + .onAction(() => { + this.longEvent() + }), + PanGesture({}) + .onActionStart(() => { + }) + .onActionUpdate((event: GestureEvent) => { + this.offsetX = event.offsetX + this.offsetY = event.offsetY + }) + .onActionEnd(() => { + this.MoveWindow(this.offsetX, this.offsetY) + this.SetWindowPosition(this.offsetX, this.offsetY) + }) + )) + } + }.width('100%').height('100%') + + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/FpsLineChartPage.ets b/device/device_ui/entry/src/main/ets/pages/FpsLineChartPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..c94fe4ade7c7c762966824ac2837a3e979a561e1 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/FpsLineChartPage.ets @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@Entry +@Component +struct FpsLineChartPage { + private settings: RenderingContextSettings = new RenderingContextSettings(true) + private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings) + private XPoint: number = 5 //x起始坐标 + private YPoint: number = 73 //Y起始坐标 + private XScale: number = 5 //刻度 + private YScale: number = 15 //刻度 + private XLength: number = 110 //X轴长度 + private YLength: number = 70 //Y轴长度 + data: number[]= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] //数据集合 + private MaxDataSize: number= this.XLength / this.XScale //数据集合的最大长度 + @State LineFps: number= 0 //FPS数值 + offsetX: number = -1 //悬浮框移动触摸点 X + offsetY: number = -1 //悬浮框移动触摸点 X + + MoveWindow(offsetX: number, offsetY: number) { + globalThis.MoveFPSLineChartWindow(offsetX, offsetY) + } + + SetWindowPosition(offsetX: number, offsetY: number) { + globalThis.SetFPSLineChartWindowPosition(offsetX, offsetY) + } + + aboutToAppear() { + globalThis.LineChartCollect = setInterval(() => { + if (this.data.length >= this.MaxDataSize) { + console.log("GestureEvent--------------shift:" + this.data); + this.data.shift() //移除第一个元素 + } + if (globalThis.timerFps == undefined) { + this.LineFps = 0 + this.data.push(0) //在末尾填充一个元素 + } else { + this.LineFps = globalThis.timerFps + if(this.LineFps==0){ + this.data.push(0) + }else{ + let lineCount: number = this.LineFps / 2 + this.data.push(lineCount)//在末尾填充一个元素 + } + } + + }, 1000) + } + + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Center }) { + + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text("FPS:" + this.LineFps).fontSize('6fp').fontColor($r("app.color.color_333")).margin({ left: 5, top: 3 }) //文本显示 + Image($r("app.media.icon_close_small")).width('15vp').height('15vp').onClick(() => { + globalThis.HideFPSLineChartWindow() + }) + + }.height('15vp').width('100%') + Canvas(this.context) + .width('100%') + .height('100%') + .onReady(() => { + //Y轴 + this.context.clearRect(this.XPoint + 0.5, this.YPoint - this.YLength, this.XLength, this.YLength) + this.context.beginPath() + this.context.moveTo(this.XPoint, this.YPoint - this.YLength) + this.context.lineTo(this.XPoint, this.YPoint) + this.context.stroke() + //X轴 + this.context.beginPath() + this.context.moveTo(this.XPoint, this.YPoint) + this.context.lineTo(this.XPoint + this.XLength, this.YPoint) + this.context.stroke() + //K线绘制 + if (this.data.length > 1) { + for (let i = 1; i < this.data.length; i++) { + this.context.beginPath() + console.log("GestureEvent--------------beginPath:" + this.data[i-1]); + this.context.moveTo(this.XPoint + (i - 1) * this.XScale, this.YPoint - this.data[i-1]) + this.context.lineTo(this.XPoint + i * this.XScale, this.YPoint - this.data[i]) + this.context.stroke() + } + } + }) + } + .width('100%') + .height('100%').gesture( + GestureGroup(GestureMode.Exclusive, + PanGesture({}) + .onActionStart((event: GestureEvent) => { + + }) + .onActionUpdate((event: GestureEvent) => { + this.offsetX = event.offsetX + this.offsetY = event.offsetY + + }) + .onActionEnd(() => { + this.MoveWindow(this.offsetX, this.offsetY) + this.SetWindowPosition(this.offsetX, this.offsetY) + + + }) + )) + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/GPULineChartPage.ets b/device/device_ui/entry/src/main/ets/pages/GPULineChartPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..d28efd4f523dc5675847db26a189b39d15bc6ffa --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/GPULineChartPage.ets @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hideFloatWindow } from '../common/ui/floatwindow/utils/floatwindowutils' +import { FloatWindowComponent } from '../common/FloatWindowComponent' +import { TaskStatus } from '../common/profiler/base/ProfilerConstant'; + +@Entry +@Component +struct GPULineChartPage { + data: number[]= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] //数据集合 + @State random: number= 0 //用于刷新的随机数 + @State gpuFrequency: number= 0 //数值 + + offsetX: number = -1 //悬浮框移动触摸点 X + offsetY: number = -1 //悬浮框移动触摸点 X + private floatName: string= "gpuFrequency" + task_state = 1 + + aboutToAppear() { + globalThis.LineChartCollect = setInterval(() => { + this.task_state = globalThis.task_status + if (this.task_state == TaskStatus.task_running) { + if (this.data.length >= 22) { + + this.data.shift() //移除第一个元素 + } + if (globalThis.tTndex.gpuFrequency == undefined) { + this.gpuFrequency = 0 + } else { + this.gpuFrequency = Number((globalThis.tTndex.gpuFrequency / 1e6).toFixed(2)).valueOf() + + if (this.gpuFrequency == 0) { + this.data.push(0) + } else { + let lineCount: number = this.gpuFrequency / 30 + this.data.push(Math.abs(lineCount)) //在末尾填充一个元素 + } + this.random = Math.random() + } + } else { + //暂停 + } + }, 1000) + } + + build() { + Stack({ alignContent: Alignment.Top }) { + FloatWindowComponent({ title: `gpuFrequency`, data: this.data }) + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text(this.floatName + ":" + this.gpuFrequency + "MHz") + .fontSize('6fp') + .fontColor($r("app.color.color_333")) + .margin({ left: 5, top: 3 }) //文本显示 + Text(this.random + "") + .fontSize('1fp') + .fontColor($r("app.color.color_333")).visibility(Visibility.None) + Image($r("app.media.icon_close_small")).width('15vp').height('15vp').onClick(() => { + hideFloatWindow(this.floatName) + + console.log("hideFloatWindow---------------------" + this.floatName) + }).align(Alignment.TopEnd) + }.height('15vp').width('100%') + + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/LightAdjust.ets b/device/device_ui/entry/src/main/ets/pages/LightAdjust.ets new file mode 100644 index 0000000000000000000000000000000000000000..2045b904d97f39cd5dcd71afe86309a13b7678ed --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/LightAdjust.ets @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import brightness from '@ohos.brightness'; +import { StartTestTitleComponent } from '../common/ui/StartTestTitleComponent'; + +/** + * 亮度调整 + */ +@Entry +@Component +struct LightAdjust { + @State outSetValue: number = 40 + + build() { + Column() { + + StartTestTitleComponent({ title: "亮度调整" }) + + Row() { + Slider({ + value: this.outSetValue, + min: 0, + max: 255, + step: 1, + style: SliderStyle.OutSet + }) + .blockColor(Color.Blue) + .trackColor(Color.Gray) + .selectedColor(Color.Blue) + .showSteps(true) + .onChange((value: number, mode: SliderChangeMode) => { + this.outSetValue = value + brightness.setValue(value) + console.info('value:' + value + 'mode:' + mode.toString()) + }) + }.padding({ top: 50 }) + .width('80%') + + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + + Text("+").fontSize('25fp').fontWeight(FontWeight.Bold).onClick(() => { + if (this.outSetValue == 255) { + return + } + ++this.outSetValue + brightness.setValue(this.outSetValue) + }) + + Text(this.outSetValue.toFixed(0)).fontWeight(FontWeight.Bold).fontSize('25fp') + + Text("-").fontSize('25fp').fontWeight(FontWeight.Bold).onClick(() => { + if (this.outSetValue == 0) { + return + } + --this.outSetValue + brightness.setValue(this.outSetValue) + }) + + }.width('50%').padding({ top: 30 }) + + Row() { + }.backgroundColor($r('app.color.color_fff')).width('50%').height('50%') + }.width('100%').height('100%') + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/LoginPage.ets b/device/device_ui/entry/src/main/ets/pages/LoginPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..fdc357255ee8c9fc7608329bb0694589390b5d04 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/LoginPage.ets @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import router from '@system.router'; + +@Entry +@Component +struct Login { + aboutToAppear() { + console.log("cur router length:" + router.getLength()) + console.log("cur router state:" + router.getState()) + } + + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) { + Column() { + Image($r('app.media.logo')).width('100vp').height('100vp').margin({ top: '180vp' }) + Blank() + Text($r('app.string.login')) + .fontSize('22fp') + .fontColor($r('app.color.color_fff')) + .fontWeight(FontWeight.Bold) + .margin({ bottom: '150vp' }) + .border({ width: '1vp', color: $r('app.color.color_fff'), radius: '20vp' }) + .width('300vp') + .height('45vp') + .textAlign(TextAlign.Center) + .onClick(() => { + router.push({ uri: 'pages/MainPage', params: { + title: "123" + } }) + }) + } + .width('100%') + .height('100%') + } + .width('100%') + .height('100%') + .linearGradient({ + angle: 135, + direction: GradientDirection.Left, + colors: [[$r("app.color.colorPrimary"), 0.0], [$r("app.color.colorPrimary"), 1.0]] + }) + } +} + diff --git a/device/device_ui/entry/src/main/ets/pages/MainPage.ets b/device/device_ui/entry/src/main/ets/pages/MainPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..0d2005ce7bbe989ac8b398ead88f2a51f0e03de6 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/MainPage.ets @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Mine } from '../Common/ui/main/Mine'; +import { Home } from '../Common/ui/main/Home'; +import { Report } from '../Common/ui/main/Report'; +import { HomeBottomPage } from '../Common/ui/main/HomeBottomPage'; +/* + * 主页 程序主页面 + */ +@Entry +@Component +struct Main { + @State currentPage: number = 0 + + build() { + Column() { + Column() { + if (this.currentPage == 0) { + Home() + } else if (this.currentPage == 1) { + Report() + } else if (this.currentPage == 2) { + Mine() + } + }.width('100%').height('88%') + .flexGrow(1) + + HomeBottomPage({ currentPage: $currentPage }) + } + } +} + + + + + + + + + diff --git a/device/device_ui/entry/src/main/ets/pages/Question.ets b/device/device_ui/entry/src/main/ets/pages/Question.ets new file mode 100644 index 0000000000000000000000000000000000000000..de9f58573a60df9da98b131a609580a983c11a76 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/Question.ets @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { StartTestTitleComponent } from '../common/ui/StartTestTitleComponent'; +import { questionList, QuestionItem } from '../common/entity/LocalConfigEntity'; + +@Entry +@Component +struct Question { + build() { + Column() { + StartTestTitleComponent({ title: "常见问题" }) + QuestionComponent() + } + } +} + + +@Component +struct QuestionComponent { + @State questionList: Array = questionList + + build() { + Column() { + List() { + ForEach(this.questionList, (questionItem) => { + ListItem() { + Flex({ + direction: FlexDirection.Column, + alignItems: ItemAlign.Start, + justifyContent: FlexAlign.SpaceBetween + }) { + Text(questionItem.question) + .fontSize(18) + .fontColor('#333333') + .margin({ top: 10, left: 15, right: 15, bottom: 5 }) + Text(questionItem.answer) + .fontSize(15).fontColor('#666666') + .margin({ left: 18, right: 18, bottom: 10 }) + }.width('100%') + // .borderWidth(1).borderRadius(5) + .margin({ bottom: 2, top: 2 }) + .shadow({ radius: 10, color: Color.Gray, offsetX: 10, offsetY: 5 }) + } + }, QuestionItem => QuestionItem.question) + }.edgeEffect(EdgeEffect.None) // 滑动到边缘无效果 + .chainAnimation(false) // 联动特效关闭 + }.width('95%').height('88%') + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/RAMLineChartPage.ets b/device/device_ui/entry/src/main/ets/pages/RAMLineChartPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..69670146182618f5876063be6689c3121ea39805 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/RAMLineChartPage.ets @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hideFloatWindow } from '../common/ui/floatwindow/utils/floatwindowutils' +import { FloatWindowComponent } from '../common/FloatWindowComponent' +import { TaskStatus } from '../common/profiler/base/ProfilerConstant'; + +@Entry +@Component +struct RAMLineChartPage { + data: number[]= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] //数据集合 + @State random: number= 0 //用于刷新的随机数 + @State pss: number= 0 //数值 + + offsetX: number = -1 //悬浮框移动触摸点 X + offsetY: number = -1 //悬浮框移动触摸点 X + private floatName: string= "RAM" + task_state = 1 + + aboutToAppear() { + globalThis.LineChartCollect = setInterval(() => { + this.task_state = globalThis.task_status + if (this.task_state == TaskStatus.task_running) { + if (this.data.length >= 22) { + + this.data.shift() //移除第一个元素 + } + if (globalThis.tTndex.pss == undefined || isNaN(globalThis.tTndex.pss)) { + this.pss = 0 + } else { + this.pss = globalThis.tTndex.pss + + if (this.pss == 0) { + this.data.push(0) + } else { + let lineCount: number = this.pss / 2000 + console.log("shellBackTemp---------------------lineCount:" + lineCount) + this.data.push(Math.abs(lineCount)) //在末尾填充一个元素 + + } + this.random = Math.random() + } + } else { + //暂停 + } + }, 1000) + } + + build() { + Stack({ alignContent: Alignment.Top }) { + FloatWindowComponent({ title: `RAM`, data: this.data }) + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text(this.floatName + ":" + this.pss + "KB") + .fontSize('6fp') + .fontColor($r("app.color.color_333")) + .margin({ left: 5, top: 3 }) //文本显示 + Text(this.random + "") + .fontSize('1fp') + .fontColor($r("app.color.color_333")).visibility(Visibility.None) + Image($r("app.media.icon_close_small")).width('15vp').height('15vp').onClick(() => { + hideFloatWindow(this.floatName) + + }).align(Alignment.TopEnd) + }.height('15vp').width('100%') + + + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/ReportDetail.ets b/device/device_ui/entry/src/main/ets/pages/ReportDetail.ets new file mode 100644 index 0000000000000000000000000000000000000000..b109879b3aabd0cd65b8e0dbe17bdc6872bcf3d2 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/ReportDetail.ets @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { secToTime } from '../common/utils/TimeUtils'; +import { TIndexInfo } from '../common/entity/DatabaseEntity'; +import router from '@system.router'; +import { Summary } from '../common/ui/detail/Summary'; +import { StartTestTitleComponent } from '../common/ui/StartTestTitleComponent'; +import { ReportItem } from '../common/entity/LocalConfigEntity'; + + +@Entry +@Component +struct ReportDetail { + private controller: TabsController = new TabsController() + private gpData: Array = new Array() + private reportItem: ReportItem = null + + aboutToAppear() { + let data = router.getParams()["gpData"] + let report = router.getParams()["reportItem"] + if (data != null) { + this.gpData = data + } + if (report != null) { + this.reportItem = report + } + } + + build() { + + Column() { + StartTestTitleComponent({ title: "报告详情" }) + + Row() { + Flex({ justifyContent: FlexAlign.SpaceBetween }) { + Column() { + Image(globalThis.iconMap.get(this.reportItem.packageName)) + .width('60vp') + .height('60vp') + .margin({ top: '20vp', left: '20vp' }) + }.margin({ left: '4%' }) + + + Column() { + Text(`SP工具`).fontSize('15fp').margin({ top: '30vp' }) + Text(`应用版本:v1.0.2`).fontSize('15fp').margin({ top: '10vp' }) + }.margin({ right: '4%' }) + } + } + + Row() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { + Text(`开始时间:${this.reportItem.startTime}`) + .fontSize('13fp') + .fontColor($r("app.color.color_666")) + .margin({ top: '5vp' }) + Text(`测试时长:${secToTime(Number(this.reportItem.testDuration))}`) + .fontSize('13fp') + .fontColor($r("app.color.color_666")) + .margin({ top: '5vp' }) + Text(`文件路径:${this.reportItem.dbPath}/t_index_info.csv`) + .fontSize('13fp') + .fontColor($r("app.color.color_666")) + .margin({ top: '5vp' }) + }.width('100%').margin({ left: '10vp', top: '10vp' }).height('80') + }.margin({ left: '4%' }) + + Row() { + Flex() { + Tabs({ barPosition: BarPosition.Start, index: 0, controller: this.controller }) { + TabContent() { + Summary({ gpData: this.gpData }) + }.tabBar('概览') + } + .barWidth(360) + .scrollable(true) + .barHeight(60) + .width('100%') + .height('100%') + } + } + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/SettingsPage.ets b/device/device_ui/entry/src/main/ets/pages/SettingsPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..f7596785fc18ecbb6455aaddbee9a9e42b371f51 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/SettingsPage.ets @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import router from '@system.router'; +import { StartTestTitleComponent } from '../common/ui/StartTestTitleComponent'; + +/** + * 设置页面 + */ +@Entry +@Component +struct SettingsPage { + build() { + Column() { + //开始测试title + StartTestTitleComponent({ title: "设置" }) + + Row({ space: '15vp' }) { + Image($r('app.media.icon_language')).width('25vp').height('25vp').margin({ left: '2%' }) + + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text('语言切换').fontSize('15fp').fontColor($r("app.color.color_333")) + + Image($r('app.media.icon_enter')).width('15vp').height('15vp').margin({ left: '15vp' }) + }.height('47vp').width('82%') + }.height('47vp').width('95%').backgroundColor($r("app.color.color_fff")).margin({ top: '10vp' }) + + Divider().layoutWeight(1).visibility(Visibility.Hidden) + + Text('退出登录') + .fontSize('15fp') + .fontColor($r('app.color.color_fff')) + .margin({ bottom: '45vp' }) + .border({ radius: '20vp' }) + .backgroundColor($r("app.color.colorPrimary")) + .width('80%') + .height('40vp') + .textAlign(TextAlign.Center) + .onClick(res => { + router.replace({ uri: 'pages/LoginPage' }) + router.clear() + }) + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/ShellBackTempLineChartPage.ets b/device/device_ui/entry/src/main/ets/pages/ShellBackTempLineChartPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..a3008a0decd40d6c336301de3d0a9508b8613683 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/ShellBackTempLineChartPage.ets @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { hideFloatWindow } from '../common/ui/floatwindow/utils/floatwindowutils' +import { FloatWindowComponent } from '../common/FloatWindowComponent' +import { TaskStatus } from '../common/profiler/base/ProfilerConstant'; + +@Entry +@Component +struct ShellBackTempLineChartPage { + data: number[]= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] //数据集合 + + @State shellBackTemp: number= 0 //数值 + @State random: number= 0 //用于刷新的随机数 + offsetX: number = -1 //悬浮框移动触摸点 X + offsetY: number = -1 //悬浮框移动触摸点 X + private floatName: string= "shellBackTemp" + task_state = 1 + + aboutToAppear() { + globalThis.LineChartCollect = setInterval(() => { + this.task_state = globalThis.task_status + if (this.task_state == TaskStatus.task_running) { + if (this.data.length >= 22) { + + this.data.shift() //移除第一个元素 + } + if (globalThis.tTndex.shellBackTemp == undefined) { + this.shellBackTemp = 0 + } else { + this.shellBackTemp = globalThis.tTndex.shellBackTemp / 1e3 + console.log("shellBackTemp---------------------" + this.shellBackTemp) + if (this.shellBackTemp == 0) { + this.data.push(0) + } else { + console.log("shellBackTemp---------------------" + this.shellBackTemp) + let lineCount: number = this.shellBackTemp + console.log("shellBackTemp---------------------lineCount:" + lineCount) + this.data.push(Math.abs(lineCount)) //在末尾填充一个元素 + + } + this.random = Math.random() + } + } else { + //暂停 + } + }, 1000) + } + + build() { + Stack({ alignContent: Alignment.Top }) { + FloatWindowComponent({ title: `shellBackTemp`, data: this.data }) + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text(this.floatName + ":" + this.shellBackTemp + "℃") + .fontSize('6fp') + .fontColor($r("app.color.color_333")) + .margin({ left: 5, top: 3 }) //文本显示 + Text(this.random + "") + .fontSize('1fp') + .fontColor($r("app.color.color_333")).visibility(Visibility.None) + + Image($r("app.media.icon_close_small")).width('15vp').height('15vp').onClick(() => { + hideFloatWindow(this.floatName) + + }).align(Alignment.TopEnd) + }.height('15vp').width('100%') + + + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/StartTestPage.ets b/device/device_ui/entry/src/main/ets/pages/StartTestPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..3f8fe3a66b3cd7b489c592426288b8825859f163 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/StartTestPage.ets @@ -0,0 +1,425 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { commonStartAbility } from '../common/utils/AbilityUtils'; +import router from '@system.router'; +import { switchList, SwitchItem, CollectItem } from '../common/entity/LocalConfigEntity'; +import { StartTestTitleComponent } from '../common/ui/StartTestTitleComponent'; +import { ProfilerTask } from '../common/profiler/ProfilerTask' +import { CollectorType } from '../common/profiler/base/ProfilerConstant' +import prompt from '@system.prompt'; + + +/* + * 测试配置页 + */ +@Entry +@Component +struct StartTestPage { + @State selectApp: string = "请选择一个应用" + @State selectAppIcon: string = "" + @State private collectConfigs: Array = new Array() + @State private switchList: Array = new Array() + @State private testName: string = "" // 测试名称 + + dialogController: CustomDialogController = new CustomDialogController({ + builder: CustomDialogCollect({ cancel: () => { + }, confirm: () => { + }, collectConfigs: $collectConfigs }), + cancel: () => { + }, + autoCancel: true + }) + textController: CustomDialogController = new CustomDialogController({ + builder: TextInputDialog({ cancel: () => { + }, confirm: () => { + }, testName: $testName }), + cancel: () => { + }, + autoCancel: true + }) + + aboutToAppear() { + let supportMap = ProfilerTask + .getInstance() + .getSupports([ + CollectorType.TYPE_CPU.toString(), + CollectorType.TYPE_GPU.toString(), + CollectorType.TYPE_DDR.toString(), + CollectorType.TYPE_FPS.toString(), + CollectorType.TYPE_POWER.toString(), + CollectorType.TYPE_TEMPERATURE.toString(), + CollectorType.TYPE_RAM.toString(), + CollectorType.TYPE_NET.toString(), + ]) + + var iterator = supportMap.keys() + for (var i = 0; i < supportMap.size; i++) { + let key = iterator.next().value + let val = supportMap.get(key) + console.log("supportMap:item" + key + " " + val); + this.collectConfigs.push( + new CollectItem(key, val, val) + ) + } + this.switchList = switchList + } + + build() { + + Column() { + //开始测试title + StartTestTitleComponent({ title: "开始测试" }) + + Scroll() { + Column() { + //请选择一个应用 + Row({ space: '15vp' }) { + if (this.selectAppIcon == "") { + Image($r('app.media.logo')).width('70vp').height('70vp').margin({ left: '2%' }) + } else { + Image(this.selectAppIcon).width('70vp').height('70vp').margin({ left: '2%' }) + } + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text(this.selectApp).fontSize('15fp').fontColor($r("app.color.color_333")) + + Image($r('app.media.icon_enter')).width('15vp').height('15vp').margin({ right: '35vp' }) + }.height('70vp').width('90%') + } + .height('100vp') + .width('95%') + .borderRadius('5vp') + .backgroundColor($r("app.color.color_fff")) + .margin({ top: '20vp' }) + .onClick(() => { + router.push({ uri: 'pages/AppSelectPage', params: { + StartPage: "StartTest" + } }) + }) + + //测试指标 + Row({ space: '15vp' }) { + Image($r('app.media.icon_test_index')).width('25vp').height('25vp').margin({ left: '2%' }) + + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text('测试指标').fontSize('15fp').fontColor($r("app.color.color_333")) + + Image($r('app.media.icon_enter')).width('15vp').height('15vp').margin({ right: '15vp' }) + }.height('60vp').width('90%').onClick(() => { + if (this.selectApp == "请选择一个应用" || this.selectApp == "SmartPerf") { + prompt.showToast({ message: "please choose app!", duration: 1000 }) + return + } + this.dialogController.open() + }) + } + .height('60vp') + .width('95%') + .borderRadius('5vp') + .backgroundColor($r("app.color.color_fff")) + .margin({ top: '10vp' }) + + //测试名称 + Row({ space: '15vp' }) { + Image($r('app.media.icon_test_name')).width('25vp').height('25vp').margin({ left: '2%' }) + + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text('测试名称').fontSize('15fp').fontColor($r("app.color.color_333")) + + Row() { + Text(this.testName).fontSize('15fp').fontColor($r("app.color.color_333")) + + Image($r('app.media.icon_enter')).width('15vp').height('15vp').margin({ right: '15vp' }) + } + }.height('60vp').width('90%').onClick(() => { + this.textController.open() + }) + + }.height('60vp').width('95%').borderRadius('5vp').backgroundColor($r("app.color.color_fff")) + + SwitchComponent({ switchList: $switchList }) + Blank() + Button('开始测试') + .fontSize('15fp') + .fontColor($r('app.color.color_fff')) + .border({ radius: '20vp' }) + .width('80%') + .height('60vp') + .backgroundColor($r("app.color.colorPrimary")) + .onClick(() => { + + let taskConfig = this.resolveTaskConfig() + console.log("console.log:" + JSON.stringify(taskConfig)); + + if (this.selectApp == "请选择一个应用" || this.selectApp == "SmartPerf") { + prompt.showToast({ message: "please choose app!", duration: 1000 }) + return + } + + if (this.search("is_camera", this.switchList).isOpen && this.search("is_video", this.switchList).isOpen) { + prompt.showToast({ message: "video and camera can't be all selected", duration: 1000 }) + return + } + + //启动app + commonStartAbility(router.getParams()["selectPackageName"], router.getParams()["selectAbilityName"]) + //启动悬浮窗 + globalThis.CreateFloatingWindow() + router.back({ uri: "pages/MainPage" }) + + }) + + Divider().height('15%').width("80%").visibility(Visibility.Hidden) + }.height("100%") + }.width('100%').scrollable(ScrollDirection.Vertical).scrollBar(BarState.Auto) + + }.height('100%').width('100%').backgroundColor('#EEEEEE') + } + + onPageShow() { + console.info("startTestPage" + "onPageShow调用了"); + if (router.getParams()["appName"] == null) { + this.selectApp = "请选择一个应用" + this.testName = "" + this.selectAppIcon = "" + } else { + this.selectApp = router.getParams()["appName"] + globalThis.appName = router.getParams()["appName"] + globalThis.appVersion = router.getParams()["appVersion"] + globalThis.packageName = router.getParams()["selectPackageName"] + this.selectAppIcon = router.getParams()["appIconId"] + let date = new Date() + let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1); + let D = date.getDate() + '-'; + let h + if (date.getHours() < 10) { + h = "0" + date.getHours(); + } else { + h = date.getHours(); + } + let m = date.getMinutes(); + globalThis.testTaskName = "游戏测试" + M + D + h + m + this.testName = "游戏测试" + M + D + h + m + } + } + + resolveTaskConfig() { + let collects = this.collectConfigs + let collectStr = "" + for (var i = 0; i < collects.length; i++) { + const collect = collects[i]; + if (i != collects.length - 1) { + collectStr += collect.name + "::" + collect.isSelect + "," + } else { + collectStr += collect.name + "::" + collect.isSelect + } + } + + let switchs = this.switchList + let switchStr = "" + for (var j = 0; j < switchs.length; j++) { + const st = switchs[j]; + if (j != switchs.length - 1) { + switchStr += st.id + "::" + st.isOpen + "," + } else { + switchStr += st.id + "::" + st.isOpen + } + } + + let taskConfig = { + "selectAppName": globalThis.packageName, + "allConfigs": collectStr + "," + switchStr + } + + let configItems: { [key: string]: boolean } = {} + let allConfigsArr: string[] = [] + let curSelectPkg = "" + if (taskConfig !== undefined) { + allConfigsArr = taskConfig.allConfigs.split(",") + curSelectPkg = taskConfig.selectAppName + } + for (var index = 0; index < allConfigsArr.length; index++) { + const config = allConfigsArr[index]; + let params = config.split("::") + if (params[1] == "true" || params[1] == "1") { + configItems[params[0]] = true + }else if (params[1] == "false" || params[1] == "0") { + configItems[params[0]] = false + }else { + configItems[params[0]] = false + } + } + globalThis.collectConfigs = configItems + globalThis.collectPkg = curSelectPkg + + return taskConfig + } + + search(id: string, myArray: Array): SwitchItem{ + for (var i = 0; i < myArray.length; i++) { + if (myArray[i].id === id) { + return myArray[i]; + } + } + } +} + + +@Component +struct SwitchComponent { + @Link private switchList: Array + + build() { + Column() { + List() { + ForEach(this.switchList, (switchItem) => { + ListItem() { + Row({ space: '15vp' }) { + Image(switchItem.switchSrc).width('25vp').height('25vp').margin({ left: '2%' }) + + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text(switchItem.switchName).fontSize('15fp').fontColor($r("app.color.color_333")) + + Toggle({ type: ToggleType.Switch, isOn: switchItem.isOpen }) + .width('60vp') + .height('25vp') + .enabled(switchItem.enable) + .onChange((isOn) => { + console.log("isOn" + isOn) + switchItem.isOpen = isOn + }) + .margin({ right: '10vp' }) + }.height('60vp').width('90%') + } + .height('60vp') + .width('100%') + .borderRadius('5vp') + .backgroundColor($r("app.color.color_fff")) + .margin({ top: '10vp' }) + } + }, switchItem => switchItem.switchName) + } + }.width('95%') + } +} + +@CustomDialog +struct CustomDialogCollect { + @Link private collectConfigs: Array + controller: CustomDialogController + cancel: () => void + confirm: () => void + + build() { + Column() { + List() { + ForEach(this.collectConfigs, (Item) => { + ListItem() { + if(Item.isSupport) { + Row({ space: '15vp' }) { + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text(Item.name).fontSize('18fp').fontColor($r("app.color.color_333")).margin({ left: 20 }) + Toggle({ type: ToggleType.Switch, isOn: Item.isSupport }) + .width('60vp') + .height('25vp') + .enabled(true) + .onChange((isOn) => { + Item.isSelect = isOn + }) + .margin({ right: '5vp' }) + }.height('60vp').width('90%') + } + .height('60vp') + .width('100%') + .borderRadius('5vp') + .backgroundColor($r("app.color.color_fff")) + .margin({ top: '10vp' }) + } else { + Row({ space: '15vp' }) { + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text(Item.name).fontSize('18fp').fontColor($r("app.color.color_333")).margin({ left: 20 }) + Toggle({ type: ToggleType.Switch, isOn: Item.isSupport }) + .width('60vp') + .height('25vp') + .enabled(false) + .margin({ right: '5vp' }) + }.height('60vp').width('90%') + } + .onClick(() => { + prompt.showToast({ duration: 1000, message: "not support" }) + }) + .height('60vp') + .width('100%') + .borderRadius('5vp') + .backgroundColor($r("app.color.color_eee")) + .margin({ top: '10vp' }) + } + } + }, Item => Item.name) + } + + Flex({ justifyContent: FlexAlign.SpaceAround }) { + Button('cancel') + .onClick(() => { + this.controller.close() + this.cancel() + }).backgroundColor(0xffffff).fontColor(Color.Black) + Button('confirm') + .onClick(() => { + this.controller.close() + this.confirm() + }).backgroundColor(0xffffff).fontColor(Color.Red) + }.margin({ bottom: 10 }) + } + } +} + +@CustomDialog +export struct TextInputDialog { + @Link private testName: String + controller: CustomDialogController + cancel: () => void + confirm: () => void + + aboutToAppear() { + console.log("TextInputDialog called") + } + + build() { + Column() { + TextArea({ placeholder: '请输入测试名称', text: this.testName.toString() }) + .placeholderFont({ size: 15 }) + .fontSize('15fp') + .textAlign(TextAlign.Center) + .fontSize(30) + .onChange((value: string) => { + this.testName = value + }) + .padding(20) + Flex({ justifyContent: FlexAlign.SpaceAround }) { + Button('cancel') + .onClick(() => { + this.controller.close() + this.cancel() + }).backgroundColor(0xffffff).fontColor(Color.Black) + Button('confirm') + .onClick(() => { + this.controller.close() + this.confirm() + }).backgroundColor(0xffffff).fontColor(Color.Red) + }.margin({ bottom: 10 }) + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/pages/TitleWindowPage.ets b/device/device_ui/entry/src/main/ets/pages/TitleWindowPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..3a2b9e68d3d8eca9d4aae0246b0ca333105554a2 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/pages/TitleWindowPage.ets @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { TIndexInfo } from '../common/entity/DatabaseEntity' +import CheckEmptyUtils from '../common/utils/CheckEmptyUtils' +import { showFloatWindow, hideFloatWindow } from '../common/ui/floatwindow/utils/floatwindowutils' +import {FPS, GPUFREQUENCY, CPU0FREQUENCY, CPU1FREQUENCY, CPU2FREQUENCY, RAM } from '../common/ui/floatwindow/FloatWindowConstant' +import SPLogger from '../common/utils/SPLogger' + +//展示配置项 +export enum ShowItemConfig { + ITEM_CPU = 0X01, + ITEM_GPU = 0X01, + ITEM_DDR = 0X01, + ITEM_FPS = 0X00, + ITEM_POWER = 0X01, + ITEM_SOC_TEMP = 0X01, + ITEM_SHELL_FRAME = 0X01, + ITEM_SHELL_BACK = 0X01, + ITEM_SHELL_FRONT = 0X01, + ITEM_RAM = 0X01, + ITEM_UNKNOWN = 0X00, +} + + +@Component +export struct ItemContent { + private icon + private tittle: string + @State value: string = "-1" + private onClickCallBack: () => void + + build() { + Row() { + Image(this.icon).width('20vp').height('20vp').margin({ right: '2%' }) + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Text(this.tittle).fontSize(20).fontColor(Color.White) + Text(this.value).fontSize(20).fontColor(Color.White) + }.width('88%').height('25vp') + } + .height('26vp') + .width('88%') + .onClick(() => { + this.onClickCallBack() + }) + } +} + +@Entry +@Component +struct TitleWindowPage { + private data: boolean[]= [false, false, false, false, false, false, false, false] + //计时器 + @State timerNum: number= 0 + @State tIndexInfo: TIndexInfo = new TIndexInfo() + offsetX: number = -1 + offsetY: number = -1 + + aboutToAppear() { + globalThis.floatIntervalCollect = setInterval(() => { + if (CheckEmptyUtils.isEmptyArr(globalThis.tTndex)) { + this.tIndexInfo.setDefaultValue() + SPLogger.DEBUG("TitleWindowPage","this.tIndexInfo isEmpty" + JSON.stringify(this.tIndexInfo)) + } else { + this.tIndexInfo = globalThis.tTndex + SPLogger.DEBUG("TitleWindowPage","this.tIndexInfo isEmpty" + JSON.stringify(this.tIndexInfo)) + } + }, 999) + } + + MoveWindow(offsetX: number, offsetY: number) { + globalThis.MoveTitleWindow(offsetX, offsetY) + } + + SetWindowPosition(offsetX: number, offsetY: number) { + globalThis.SetTitleWindowPosition(offsetX, offsetY) + } + + floatWindowEvent(floatName: string, flag: number) { + if (this.data[flag]) { + hideFloatWindow(floatName) + this.data[flag] = false + } else { + showFloatWindow(floatName) + this.data[flag] = true + } + } + + build() { + Stack({ alignContent: Alignment.Center }) { + Rect({ width: '100%', height: '100%' }).radius(10).opacity(0.5) + Column({ space: 2 }) { + + Row() { + Image($r("app.media.logo")).width('20vp').height('20vp').margin({ left: '2%' }) + Text( "SmartPerf") + .fontSize('20fp') + .fontColor($r("app.color.color_fff")).margin({ left: '2%' }) + Image($r("app.media.icon_close_small")).height('18vp').width('18vp').margin({ left: '55%' }).onClick(() => { + //关闭实时悬浮框 + globalThis.HideTitleWindow() + }) + } .height('26vp') + .width('95%') + + ItemContent({ + icon: $r("app.media.icon_average_frame_b"), + value: (this.tIndexInfo.fps.toString()) + "FPS", + tittle: "帧率", + onClickCallBack: () => { + this.floatWindowEvent("FPS",FPS) + } + }) + + ItemContent({ + icon: $r("app.media.icon_counter"), + value: (parseInt(this.tIndexInfo.cpu0Frequency.toString()) / 1e3).toString() + "MHz", + tittle: "CPU0频率", + onClickCallBack: () => { + this.floatWindowEvent("cpu0Frequency", CPU0FREQUENCY) + } + }) + ItemContent({ + icon: $r("app.media.icon_counter"), + value: (parseInt(this.tIndexInfo.cpu1Frequency.toString()) / 1e3).toString() + "MHz", + tittle: "CPU1频率", + onClickCallBack: () => { + this.floatWindowEvent("cpu1Frequency", CPU1FREQUENCY) + } + }) + ItemContent({ + icon: $r("app.media.icon_counter"), + value: (parseInt(this.tIndexInfo.cpu2Frequency.toString()) / 1e3).toString() + "MHz", + tittle: "CPU2频率", + onClickCallBack: () => { + this.floatWindowEvent("cpu2Frequency", CPU2FREQUENCY) + } + }) + ItemContent({ + icon: $r("app.media.icon_frame_score"), + value: (parseInt(this.tIndexInfo.gpuFrequency.toString()) / 1e6).toString() + "MHz", + tittle: "GPU频点", + onClickCallBack: () => { + this.floatWindowEvent("gpuFrequency", GPUFREQUENCY) + } + }) + ItemContent({ + icon: $r("app.media.icon_jank_each_hour"), + value: this.tIndexInfo.pss + "KB", + tittle: "RAM", + onClickCallBack: () => { + this.floatWindowEvent("RAM", RAM) + } + }) + ItemContent({ + icon: $r("app.media.icon_max_temperature"), + value: (parseInt(this.tIndexInfo.socThermalTemp.toString()) / 1e3).toString() + "℃", + tittle: "SOC温度" + }) + ItemContent({ + icon: $r("app.media.icon_counter"), + value: this.tIndexInfo.networkUpSpeed.toString() + "kbps" + " " +this.tIndexInfo.networkDownSpeed.toString() + "kbps", + tittle: "带宽" + }) + // ItemContent({ + // icon: $r("app.media.icon_max_temperature"), + // value: (ParseIntValue(this.tIndexInfo.shellBackTemp.toString()) / 1e3).toString() + "℃", + // tittle: "后壳温" + // }) + // ItemContent({ + // icon: $r("app.media.icon_max_temperature"), + // value: (ParseIntValue(this.tIndexInfo.shellFrontTemp.toString()) / 1e3).toString() + "℃", + // tittle: "前壳温" + // }) + // ItemContent({ + // icon: $r("app.media.icon_max_temperature"), + // value: (ParseIntValue(this.tIndexInfo.shellFrameTemp.toString()) / 1e3).toString() + "℃", + // tittle: "壳温" + // }) + // ItemContent({ + // icon: $r("app.media.icon_normalized_current"), + // value: this.tIndexInfo.currentNow + "mA", + // tittle: "电流" + // }) + // ItemContent({ + // icon: $r("app.media.icon_counter"), + // value: (ParseIntValue(this.tIndexInfo.ddrFrequency.toString()) / 1e6).toString() + "MHz", + // tittle: "DDR频点" + // }) + }.width('100%') + .gesture( + GestureGroup(GestureMode.Exclusive, + PanGesture({}) + .onActionStart((event: GestureEvent) => { + }) + .onActionUpdate((event: GestureEvent) => { + this.offsetX = event.offsetX + this.offsetY = event.offsetY + }) + .onActionEnd(() => { + this.MoveWindow(this.offsetX, this.offsetY) + this.SetWindowPosition(this.offsetX, this.offsetY) + }) + )) + } + } +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/ets/workers/worker.js b/device/device_ui/entry/src/main/ets/workers/worker.js new file mode 100644 index 0000000000000000000000000000000000000000..a2146baf49d641352ce083d0f4ad7f83ac4ac3f7 --- /dev/null +++ b/device/device_ui/entry/src/main/ets/workers/worker.js @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import worker from '@ohos.worker'; // 导入worker模块 +import net_socket from '@ohos.net.socket'; + + +let parentPort = worker.parentPort; // 获取parentPort属性 + +export let IPv4 = 1 + +export let IPv4BindAddr = { + address: "127.0.0.1", + family: IPv4, + port: 8283 +} + +export let UdpSendAddress = { + address: "127.0.0.1", + family: IPv4, + port: 8283 +} + +export let flagPackageNum = 0 + +export let udp = net_socket.constructUDPSocketInstance() +udp.bind(IPv4BindAddr, err => { + if (err) { + console.log('Worker socket bind fail'); + return; + } + console.log('Worker socket bind success'); + udp.getState((err, data) => { + if (err) { + console.log('Worker socket getState fail'); + return; + } + console.log('Worker socket getState success:' + JSON.stringify(data)); + }) +}) + + +parentPort.onexit = function (e) { + console.log("Worker onexit") +} + +parentPort.onerror = function (e) { + console.log("Worker onerror") +} + +parentPort.onmessageerror = function (e) { + console.log("Worker onmessageerror") +} + +udp.on('listening', () => { + console.log("Worker socket on listening success"); +}); +udp.on('close', () => { + console.log("Worker socket on close success"); +}); + +udp.on('error', err => { + console.log("Worker socket on error, err:" + JSON.stringify(err)) +}); +parentPort.onmessage = function (e) { + + let socketCollectItems = e.data + console.log("sub worker recv:" + JSON.stringify(e.data)); + + let messageSetPkg = "set_pkgName::" + socketCollectItems.pkg + udp.getState((err, data) => { + if (err) { + parentPort.postMessage("FPS$-1") + console.log("Worker socket getState error", err); + } + console.log('Worker socket getState success:' + JSON.stringify(data)); + + if (flagPackageNum < 2) { + udp.send({ + address: UdpSendAddress, + data: messageSetPkg + }) + } + flagPackageNum++ + + if (socketCollectItems.fps) { + let messageFps = "get_fps_and_jitters::0::0" + if (socketCollectItems.is_video) { + messageFps = "get_fps_and_jitters::1::0" + } else if (socketCollectItems.is_camera) { + messageFps = "get_fps_and_jitters::0::1" + } + udp.send({ + address: UdpSendAddress, + data: messageFps + }) + console.log("sub worker messageFps :" + messageFps); + + } + if (socketCollectItems.ram) { + let messageRam = "get_ram_info::" + socketCollectItems.pkg + udp.send({ + address: UdpSendAddress, + data: messageRam + }) + console.log("sub worker messageRam :" + messageRam); + } + + if (socketCollectItems.screen_capture) { + udp.send({ + address: UdpSendAddress, + data: "get_capture" + }) + console.log("sub worker screen_capture :" + screen_capture); + } + + if (socketCollectItems.power) { + let messagePower = "get_power" + udp.send({ + address: UdpSendAddress, + data: messagePower + }) + console.log("sub worker messagePower :" + messagePower); + } + if (socketCollectItems.catch_trace_start) { + let messageTrace = "catch_trace_start" + udp.send({ + address: UdpSendAddress, + data: messageTrace + }) + } + if (socketCollectItems.catch_trace_finish) { + let messageTrace = "catch_trace_finish::" + socketCollectItems.traceName + udp.send({ + address: UdpSendAddress, + data: messageTrace + }) + } + + + }) +} + +udp.on("message", function (data) { + let buffer = data.message + let dataView = new DataView(buffer) + let str = "" + for (let i = 0;i < dataView.byteLength; ++i) { + str += String.fromCharCode(dataView.getUint8(i)) + } + try { + if (includes(str, "Pss")) { + parentPort.postMessage("RAM$" + str) + } else if (includes(str, "fps")) { + if (str.indexOf("::") != -1) { + let arrStr = str.split("::") + console.log("SockOnMessage solveFps1:" + JSON.stringify(arrStr)) + if (arrStr[1].indexOf(";") != -1) { + let fpsDataArr = arrStr[1].split(";") + console.log("SockOnMessage solveFps2:" + JSON.stringify(fpsDataArr)) + if (fpsDataArr[1].indexOf("|") != -1) { + let fps = fpsDataArr[1].split("|") + console.log("SockOnMessage solveFps fps:" + JSON.stringify(fps)) + if (fpsDataArr.length > 1 && fpsDataArr[2].indexOf("|")) { + let fpsJitter = fpsDataArr[2].split("|") + console.log("SockOnMessage solveFps fpsJitter:" + JSON.stringify(fpsJitter)) + parentPort.postMessage("FPS$" + fps[1].toString() + "$" + fpsJitter[1].toString()) + } + } + } + } + } + } catch (e) { + console.log("SockOnMessage recv callback err:" + e) + } + +}) + + +function includes(all, sub) { + + all = all.toLowerCase(); + sub = sub.toLowerCase(); + + var firstChar = sub.substring(0, 1); + var subLength = sub.length; + + for (let i = 0; i < all.length - subLength + 1; i++) { + + if (all.charAt(i) == firstChar) + { + if (all.substring(i, i + subLength) == sub) + { + return true; + } + } + } + return false; +} + diff --git a/device/device_ui/entry/src/main/module.json5 b/device/device_ui/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..fe95e0f8a2d476797991c0a1575a440eb74331c4 --- /dev/null +++ b/device/device_ui/entry/src/main/module.json5 @@ -0,0 +1,69 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "./ets/Application/AbilityStage.ts", + "mainElement": "MainAbility", + "deviceTypes": [ + "phone", + "tablet", + "wearable", + "car", + "tv", + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "uiSyntax": "ets", + "requestPermissions": [ + { + "name": "ohos.permission.INTERNET" + }, + { + "name": "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED" + }, + { + "name": "ohos.permission.KEEP_BACKGROUND_RUNNING" + }, + { + "name": "ohos.permission.GET_BUNDLE_INFO" + }, + { + "name": "ohos.permission.READ_USER_STORAGE" + }, + { + "name": "ohos.permission.WRITE_USER_STORAGE" + }, + { + "name": "ohos.permission.SYSTEM_FLOAT_WINDOW" + }, + { + "name": "ohos.permission.GET_RUNNING_INFO" + }, + { + "name": "ohos.permission.GET_NETWORK_INFO" + } + ], + "abilities": [ + { + "name": "MainAbility", + "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "description": "$string:MainAbility_desc", + "icon": "$media:logo", + "label": "$string:MainAbility_label", + "visible": true, + "skills": [ + { + "entities": [ + "entity.system.home", + ], + "actions": [ + "action.system.home", + ], + }, + ], + }, + ], + + }, +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/resources/base/element/color.json b/device/device_ui/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..da117bc3d4956b051fc7f99ec9164cb07d55f73e --- /dev/null +++ b/device/device_ui/entry/src/main/resources/base/element/color.json @@ -0,0 +1,37 @@ +{ + "color": [ + { + "name": "colorPrimary", + "value": "#B3193F" + }, + { + "name": "color_fff", + "value": "#ffffff" + }, + { + "name": "color_80fff", + "value": "#80ffffff" + }, + { + "name": "color_eee", + "value": "#eeeeee" + }, + { + "name": "color_80B3193F", + "value": "#80B3193F" + }, + { + "name": "color_333", + "value": "#333333" + }, + { + "name": "color_666", + "value": "#666666" + }, + { + "name": "color_999", + "value": "#999999" + } + + ] +} \ No newline at end of file diff --git a/device/device_ui/entry/src/main/resources/base/element/string.json b/device/device_ui/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..20ce5c7b247d0b28030c11ed9fcc8bbf138f69bd --- /dev/null +++ b/device/device_ui/entry/src/main/resources/base/element/string.json @@ -0,0 +1,56 @@ +{ + "string": [ + { + "name": "entry_desc", + "value": "SmartPerf" + }, + { + "name": "MainAbility_desc", + "value": "SmartPerf" + }, + { + "name": "MainAbility_label", + "value": "SmartPerf" + }, + { + "name": "entry_MainAbility", + "value": "SmartPerf" + }, + { + "name": "mainability_description", + "value": "SmartPerf" + }, + { + "name": "login", + "value": "登录" + }, + { + "name": "description_collectserviceability", + "value": "hap sample empty service" + }, + { + "name": "description_serviceability", + "value": "hap sample empty service" + }, + { + "name": "description_floatwindowability", + "value": "ETS_Empty Ability" + }, + { + "name": "entry_FloatWindowAbility", + "value": "entry_FloatWindowAbility" + }, + { + "name": "description_floatwindowpage", + "value": "ETS_Empty Ability" + }, + { + "name": "entry_FloatWindowPage", + "value": "entry_FloatWindowPage" + }, + { + "name": "description_profileserviceability", + "value": "hap sample empty service" + } + ] +} diff --git a/device/device_ui/entry/src/main/resources/base/media/icon.png b/device/device_ui/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_about_we.png b/device/device_ui/entry/src/main/resources/base/media/icon_about_we.png new file mode 100644 index 0000000000000000000000000000000000000000..956b0386b5b1eda6ed37db73a7831551c0559fae Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_about_we.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_average_frame_b.png b/device/device_ui/entry/src/main/resources/base/media/icon_average_frame_b.png new file mode 100644 index 0000000000000000000000000000000000000000..32f900d06757bd5f19e185b3db20d19c1fae8aaa Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_average_frame_b.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_back.png b/device/device_ui/entry/src/main/resources/base/media/icon_back.png new file mode 100644 index 0000000000000000000000000000000000000000..d69e9792bdd66f644172a05706536b4002234e2b Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_back.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_brightness_plus.png b/device/device_ui/entry/src/main/resources/base/media/icon_brightness_plus.png new file mode 100644 index 0000000000000000000000000000000000000000..fa5eaf118bfd4ad3e9515fbb83b2cb88794f1c62 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_brightness_plus.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_camera.png b/device/device_ui/entry/src/main/resources/base/media/icon_camera.png new file mode 100644 index 0000000000000000000000000000000000000000..82629e8a8cab601d5265fe15ea801246fda4a688 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_camera.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_close_small.png b/device/device_ui/entry/src/main/resources/base/media/icon_close_small.png new file mode 100644 index 0000000000000000000000000000000000000000..c7b9b5e64c1e803cf0f81a299d1ba1278e95c54a Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_close_small.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_counter.png b/device/device_ui/entry/src/main/resources/base/media/icon_counter.png new file mode 100644 index 0000000000000000000000000000000000000000..f95aaf96c33fc31fc9ed2539994214610d1bddd7 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_counter.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_enter.png b/device/device_ui/entry/src/main/resources/base/media/icon_enter.png new file mode 100644 index 0000000000000000000000000000000000000000..0a6e9981d0ab7b582f4d2a13ea542aca6f76e386 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_enter.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_frame_score.png b/device/device_ui/entry/src/main/resources/base/media/icon_frame_score.png new file mode 100644 index 0000000000000000000000000000000000000000..b528934df62c86c905c99fc61c57571d79225f91 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_frame_score.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_home_selected.png b/device/device_ui/entry/src/main/resources/base/media/icon_home_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..13915bec910841b24608c4e5e196c12b2a205f85 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_home_selected.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_home_unselected.png b/device/device_ui/entry/src/main/resources/base/media/icon_home_unselected.png new file mode 100644 index 0000000000000000000000000000000000000000..329a92c8342ae5143e2c619c7afa0263ca873602 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_home_unselected.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_jank_each_hour.png b/device/device_ui/entry/src/main/resources/base/media/icon_jank_each_hour.png new file mode 100644 index 0000000000000000000000000000000000000000..cb44bad8f3b6d3324929a8212113f7fcc723e2a7 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_jank_each_hour.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_jank_score.png b/device/device_ui/entry/src/main/resources/base/media/icon_jank_score.png new file mode 100644 index 0000000000000000000000000000000000000000..339d7d9ffb1df66ee042c557a2d47f09cd0b2853 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_jank_score.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_language.png b/device/device_ui/entry/src/main/resources/base/media/icon_language.png new file mode 100644 index 0000000000000000000000000000000000000000..ae4f3ef596452b0e5dbb5e7bdad40039fe7dafe8 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_language.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_max_temperature.png b/device/device_ui/entry/src/main/resources/base/media/icon_max_temperature.png new file mode 100644 index 0000000000000000000000000000000000000000..9f30f9b7fae954544b28e906464732015d9ae845 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_max_temperature.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_mine_selected.png b/device/device_ui/entry/src/main/resources/base/media/icon_mine_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..f19ceddcf68e5f60d4a007c6ece7c1349816efa9 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_mine_selected.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_mine_unselected.png b/device/device_ui/entry/src/main/resources/base/media/icon_mine_unselected.png new file mode 100644 index 0000000000000000000000000000000000000000..03f579500831a8380c867c5a543a334da672249e Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_mine_unselected.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_net.png b/device/device_ui/entry/src/main/resources/base/media/icon_net.png new file mode 100644 index 0000000000000000000000000000000000000000..434e4bce41aeb6f5e2b9c4224432f08e98987d77 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_net.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_normalized_current.png b/device/device_ui/entry/src/main/resources/base/media/icon_normalized_current.png new file mode 100644 index 0000000000000000000000000000000000000000..0c7d9e1614412f137e4a54941248979f98fbf1ed Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_normalized_current.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_report_selected.png b/device/device_ui/entry/src/main/resources/base/media/icon_report_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..aaf522afbd9299877337f19054939d6f99c81b23 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_report_selected.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_report_unselected.png b/device/device_ui/entry/src/main/resources/base/media/icon_report_unselected.png new file mode 100644 index 0000000000000000000000000000000000000000..80403cb4a55b7204924044ebba873107c6cf0802 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_report_unselected.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_screencap.png b/device/device_ui/entry/src/main/resources/base/media/icon_screencap.png new file mode 100644 index 0000000000000000000000000000000000000000..973f949f9e09100cd52fc0ad3f55358952960390 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_screencap.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_test_index.png b/device/device_ui/entry/src/main/resources/base/media/icon_test_index.png new file mode 100644 index 0000000000000000000000000000000000000000..97de598605d78596af4319daecacdcd71c4a432f Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_test_index.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_test_name.png b/device/device_ui/entry/src/main/resources/base/media/icon_test_name.png new file mode 100644 index 0000000000000000000000000000000000000000..313303a7a9a8b601f2b719716fd4e9335346e77b Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_test_name.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_upload.png b/device/device_ui/entry/src/main/resources/base/media/icon_upload.png new file mode 100644 index 0000000000000000000000000000000000000000..d9de28bc6137b6b0f2e16811bfaf3ccfa0f84740 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_upload.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/icon_video.png b/device/device_ui/entry/src/main/resources/base/media/icon_video.png new file mode 100644 index 0000000000000000000000000000000000000000..21b6064e715aafc80c70506bc9682869708a1cca Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/icon_video.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/logo.png b/device/device_ui/entry/src/main/resources/base/media/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..646d2e62f4ef0dc187e3887a0c619b27b32ede7d Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/logo.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/person.png b/device/device_ui/entry/src/main/resources/base/media/person.png new file mode 100644 index 0000000000000000000000000000000000000000..8f312664a7360b662d4ff898dc4b498d452bf368 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/person.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/question.png b/device/device_ui/entry/src/main/resources/base/media/question.png new file mode 100644 index 0000000000000000000000000000000000000000..d302fe7787be8853a43619f997788d07719dbd35 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/question.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/report_upload.png b/device/device_ui/entry/src/main/resources/base/media/report_upload.png new file mode 100644 index 0000000000000000000000000000000000000000..d9de28bc6137b6b0f2e16811bfaf3ccfa0f84740 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/report_upload.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/settings.png b/device/device_ui/entry/src/main/resources/base/media/settings.png new file mode 100644 index 0000000000000000000000000000000000000000..d8bbfd0a93af43f8026bafff3d408e4e880f3893 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/settings.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/test_apps_count.png b/device/device_ui/entry/src/main/resources/base/media/test_apps_count.png new file mode 100644 index 0000000000000000000000000000000000000000..169147f21a78b6fbd31deea4fdde7ad2e4b30e23 Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/test_apps_count.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/test_session_count.png b/device/device_ui/entry/src/main/resources/base/media/test_session_count.png new file mode 100644 index 0000000000000000000000000000000000000000..3b029556161049b8109344963cb4492da36d401b Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/test_session_count.png differ diff --git a/device/device_ui/entry/src/main/resources/base/media/test_times_count.png b/device/device_ui/entry/src/main/resources/base/media/test_times_count.png new file mode 100644 index 0000000000000000000000000000000000000000..accc8bf7faa31ca02786d2a415f1b697fefb0e4a Binary files /dev/null and b/device/device_ui/entry/src/main/resources/base/media/test_times_count.png differ diff --git a/device/device_ui/entry/src/main/resources/base/profile/main_pages.json b/device/device_ui/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..d748040b9cfa5bf15aa28f478445b91ba7ee393d --- /dev/null +++ b/device/device_ui/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,23 @@ +{ + "src": [ + "pages/MainPage", + "pages/StartTestPage", + "pages/AppSelectPage", + "pages/SettingsPage", + "pages/Question", + "pages/ReportDetail", + "pages/LightAdjust", + "pages/FloatBall", + "pages/TitleWindowPage", + "pages/LoginPage", + "pages/FpsLineChartPage", + "pages/CurrentNowLineChartPage", + "pages/ShellBackTempLineChartPage", + "pages/DDRLineChartPage", + "pages/GPULineChartPage", + "pages/CPU0LineChartPage", + "pages/CPU1LineChartPage", + "pages/CPU2LineChartPage", + "pages/RAMLineChartPage" + ] +} diff --git a/device/device_ui/hvigorfile.js b/device/device_ui/hvigorfile.js new file mode 100644 index 0000000000000000000000000000000000000000..5f2735e3deeaf655828407544bbed9365c258278 --- /dev/null +++ b/device/device_ui/hvigorfile.js @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +module.exports = require('@ohos/hvigor-ohos-plugin').appTasks \ No newline at end of file diff --git a/device/device_ui/package.json b/device/device_ui/package.json new file mode 100644 index 0000000000000000000000000000000000000000..6cae94159d31fca180c507559c1f145f4fa9f5f5 --- /dev/null +++ b/device/device_ui/package.json @@ -0,0 +1,14 @@ +{ + "devDependencies":{}, + "name":"OpenHarmony_SP", + "ohos":{ + "org":"ohos", + "directoryLevel":"project", + "buildTool":"hvigor" + }, + "version":"1.0.0", + "dependencies":{ + "@ohos/hvigor-ohos-plugin":"1.0.4-rc", + "@ohos/hvigor":"1.0.4-rc" + } +} \ No newline at end of file diff --git a/host/doc/compile_smartperf.md b/host/doc/compile_smartperf.md new file mode 100644 index 0000000000000000000000000000000000000000..3f583c19f127775caa1f90c8a14c477483da3835 --- /dev/null +++ b/host/doc/compile_smartperf.md @@ -0,0 +1,93 @@ +# SmartPerf 编译指导 + + +## 1. 编译环境搭建: + 注意:在linux编译环境安装时以root或者其他 sudo 用户身份运行下面的命令 +### 1.1 node 环境安装: +##### 1.1.1 下载Node js安装包(windows推荐, linux跳过此步骤) + 从网站 下载node js安装包 https://nodejs.org/en/download/current/ +##### 1.1.2 安装nodejs. +- ubuntu 20.04 与Debian 11系统中, 直接用apt-get安装,命令如下: +``` + 先切换到 root用户下 sudo su + apt-get update + apt-get install nodejs npm +``` + +- centos 系统中 使用yum 安装,命令如下: +``` + 先切换到 root用户下 sudo su + sudo yum -y install nodejs npm +``` + +- windows系统中, 用安装包一路next即可: + + +- 安装完成后运行检查是否安装成功: +``` + node -v + npm -v +``` + 出现版本号就代表安装成功了. + +##### 1.1.3 安装tsc typeScript 编译器 + +- 直接使用npm 安装运行命令: +``` +npm install -g typescript + +备注:如果安装失败可以更换npm源,再次尝试. +验证安装完成: + tsc -v +``` +### 1.2 go 编译环境安装: +- ubuntu 环境下直接使用apt安装: +``` + apt-get install golang-go +``` +- centos 系统中 使用yum 安装,命令如下: + +``` +先切换到 root用户下 sudo su + + sudo yum -y install go +``` +- windows 系统请自行下载安装包并完成安装。 + +- 安装完成后 命令行运行验证是否安装成功: + +``` + go version +``` +## 2. 项目编译: +#### 2.1 先下载sql.js的二进制包,: + 从如下 https://github.com/sql-js/sql.js/releases/download/v1.6.2/sqljs-all.zip 获取到sql.js的二进制包. + 将压缩包解压后, 将文件放置到项目third-party 目录下. + + +#### 2.2 先编译获取trace_streamer 的二进制包: + 参照:smartperf/trace_streamer/compile_trace_streamer.md 编译出wasm 、linux、Windows版本的二进制文件 + 将获取到二进制文件放入到项目bin目录下,如果项目目录中无bin目录 先创建bin目录. + 然后将trace_streamer的二进制文件放入bin目录中. + + +#### 2.3 代码编译(依赖于上面node环境 和 go环境) + 1) 在项目目录安装项目依赖: + npm install + 2) 在项目目录下运行命令: + npm run compile + 编译成功后会有main 可执行文件生成 + +## 3. 项目部署: + 1. linux 版本部署需要给trace_stream程序赋予执行权限: + cd dist/bin 目录下,执行 chmod +x trace_streamer_* + + 直接运行 ./main 可执行程序,完成项目的部署; + + ## 4. 访问项目: + 在浏览器上打开 https://[部署机器ip地址]:9001/application/ + !!! 注意一定是https. + + 备注:如果未出现如图所示网页.而是显示 无法访问此网站 + 可以在window cmd 里执行telnet [部署机器ip地址] 9001 + 如果显示端口连接失败 可能是防火墙未对9001 端口放开即可 diff --git a/host/doc/compile_trace_streamer.md b/host/doc/compile_trace_streamer.md new file mode 100644 index 0000000000000000000000000000000000000000..b49e34eb624144aa13010efd0abd1e06234a4792 --- /dev/null +++ b/host/doc/compile_trace_streamer.md @@ -0,0 +1,133 @@ +# 1.如何独立编译Trace_streamer +尽管本工具(trace_streamer)是在ohos工具箱中的一员,但你依然可以独立编译此工具。 + +本工具可以编译linux, mac, windows, WebAssembly版本。 + +本工具默认编译方式是使用gn ++ 编译方式 +``` +./build.sh linux/wasm +``` +如果需要编译WebAssembly版本,您需要在prebuilts/目录下安装emsdk +``` +git clone https://github.com/juj/emsdk.git --depth=1 +cd emsdk +git pull +./emsdk update # this may not work, ignore it +./emsdk install latest +./emsdk activate latest +安装之后,您需要将upstream目录复制到prebuilts/emsdk/emsdk,node复制到prebuilts/emsdk/node +``` +安装之后,目录结构当如: +``` +prebuilts/emsdk +├── prebuilts/emsdk/emsdk +│ ├── prebuilts/emsdk/emsdk/bin +│ ├── prebuilts/emsdk/emsdk/emscripten +│ │ ├── prebuilts/emsdk/emsdk/emscripten/cache +│ │ ├── prebuilts/emsdk/emsdk/emscripten/cmake +│ │ ├── prebuilts/emsdk/emsdk/emscripten/docs +│ │ ├── prebuilts/emsdk/emsdk/emscripten/media +│ │ ├── prebuilts/emsdk/emsdk/emscripten/node_modules +│ │ ├── prebuilts/emsdk/emsdk/emscripten/__pycache__ +│ │ ├── prebuilts/emsdk/emsdk/emscripten/src +│ │ ├── prebuilts/emsdk/emsdk/emscripten/system +│ │ ├── prebuilts/emsdk/emsdk/emscripten/tests +│ │ ├── prebuilts/emsdk/emsdk/emscripten/third_party +│ │ └── prebuilts/emsdk/emsdk/emscripten/tools +│ ├── prebuilts/emsdk/emsdk/include +│ │ └── prebuilts/emsdk/emsdk/include/c++ +│ └── prebuilts/emsdk/emsdk/lib +│ └── prebuilts/emsdk/emsdk/lib/clang +└── prebuilts/emsdk/node + └── prebuilts/emsdk/node/14.18.2_64bit + ├── prebuilts/emsdk/node/14.18.2_64bit/bin + ├── prebuilts/emsdk/node/14.18.2_64bit/include + ├── prebuilts/emsdk/node/14.18.2_64bit/lib + └── prebuilts/emsdk/node/14.18.2_64bit/share +``` +之后调用 +``` +./build.sh wasm进行编译,您需要将sh脚本进行部分修改,因为这个脚本内置了一些库的下载和解析方式 +``` +本工具还支持使用QtCreator来编译。 + +src/trace_streamer.pro 是工程文件,编译本工具需要依赖Sqlite库和一些基于proto的pb.h文件 +## 2 准备工程 +### 2.1 基于proto文件生成pb文件 +您需要自行下载并编译一个当前系统(linux)可用的proobuf/protoc程序,此全路径为位于out/linux/protoc +src/protos目录下有一个protogen.sh文件,运行该文件可以在third_party/protogen目录下生成项目需要的pb相关文件 +序列化二进制的解析依赖于基于proto生成的.pb.cc文件。 +在执行protogen.sh脚本之后 +你的目录结构当类似如下结构: +``` +third_party/protogen/types/plugins/ftrace_data/*.pb.cc +third_party/sqlite/*. +third_party/protobuf/* +``` +### 2.2 获取第三方依赖库 +从 +https://gitee.com/openharmony/third_party_sqlite +获取sqlite3目录到代码根目录的third_party目录 +从 +https://gitee.com/openharmony/third_party_protobuf +获取protobuf目录到代码根目录的third_party目录 +之后,你的目录当如下所示 +trace_streamer/third_party/protobuf +trace_streamer/third_party/sqlite +# 3.(linux和ohos平台)使用gn编译TraceStreamer +在编译WebAssembly目标时,需要将sqlite3和protobuf里面相关的ohos_xxx_library统一修改为source_set +## 3.1 准备gn +在自己的项目中使用gn,必须遵循以下要求: +在根目录创建.gn文件,该文件用于指定CONFIG.gn文件的位置; +在BUILDCONFIG.gn中指定编译时使用的编译工具链; +在独立的gn文件中定义编译使用的工具链; +在项目根目录下创建BUILD.gn文件,指定编译的目标。 +``` +cp prebuilts/gn ./ +``` +不同的操作系统下,你需要获取不同的gn +## 3.2 执行编译 +./build.sh linux debug +或./build.sh linux debug +./build.sh将直接编译linux的release版本 +build.sh wasm 命令将可以编译WebAssembly版本 +特别说明:编译WebAssembly版本需要emSDK支持,你需要将build.sh里面的相关路径做更改,以保证编译时必须的文件是存在的 +# 4 编译Windows版本或Mac版本 +## 4.1 编译依赖文件 +### 4.1.1 编译SqliteLib +使用QtCreator打开prebuiltsprebuilts/buildprotobuf/sqlite.pro +### 4.1.2 编译ProtobufLib +使用QtCreator打开prebuilts/buildprotobuf/protobuf.pro +编译之后,文件结构当如下所示: +``` +lib +├── linux +│ ├── libdl.so +│ └── libsqlite.a +├── linux_debug +│ ├── libprotobuf.a +│ └── libsqlite.a +├── macx +│ ├── libprotobuf.a +│ └── libsqlite.a +├── macx_debug +│ ├── libprotobuf.a +│ └── libsqlite.a +├── windows +│ ├── libprotobuf.a +│ └── libsqlite.a +└── windows_debug + ├── libprotobuf.a + └── libsqlite.a +``` +## 4.2 编译TraceStreamer +之后,使用QtCreator打开src/trace_streamer.pro,选择合适的构建工具,执行 Ctrl + b 即可编译 + +编译之后的可执行文件位于out目录 +``` +- out +---- linux (Linux平台下QtCreator或gn生成) +---- macx (mac平台下QtCreator或gn生成) +---- windows (windows平台下QtCreator或gn生成) +``` \ No newline at end of file diff --git a/host/doc/des_stat.md b/host/doc/des_stat.md new file mode 100644 index 0000000000000000000000000000000000000000..e1048f51e1dbb4e9fbe08a809856d2bba903a5d2 --- /dev/null +++ b/host/doc/des_stat.md @@ -0,0 +1,413 @@ +# TraceStreamer 解析数据状态表 +TraceStreamer使用stat表统计解析trace数据源过程遇到的重要事件状态。通过stat表可以对trace数据源中各个类型事件的数据有一个基本了解。 +## stat表支持统计的事件列表如下: +|event_name | +| ---- | +|binder_transaction | +|binder_transaction_alloc_buf | +|binder_transaction_lock | +|binder_transaction_locked | +|binder_transaction_received | +|binder_transaction_unlock | +|clk_disable | +|clk_enable | +|clk_set_rate | +|clock_disable | +|clock_enable | +|clock_set_rate | +|cpu_frequency | +|cpu_idle | +|hidump_fps | +|hilog | +|ipi_entry | +|ipi_exit | +|irq_handler_entry | +|irq_handler_exit | +|memory | +|native_hook_free | +|native_hook_malloc | +|oom_score_adj_update | +|other | +|print | +|regulator_disable | +|regulator_disable_complete | +|regulator_set_voltage | +|regulator_set_voltage_complete | +|sched_process_exit | +|sched_process_free | +|sched_switch | +|sched_wakeup | +|sched_wakeup_new | +|sched_waking | +|signal_deliver | +|signal_generate | +|softirq_entry | +|softirq_exit | +|softirq_raise | +|suspend_resume | +|sys_enter | +|sys_exit | +|sys_memory | +|sys_virtual_memory | +|task_newtask | +|task_rename | +|trace_bblock_bio_queue | +|trace_block_bio_backmerge | +|trace_block_bio_bounce | +|trace_block_bio_complete | +|trace_block_bio_frontmerge | +|trace_block_bio_remap | +|trace_block_dirty_buffer | +|trace_block_getrq | +|trace_block_plug | +|trace_block_rq_complete | +|trace_block_rq_insert | +|trace_block_rq_issue | +|trace_block_rq_remap | +|trace_event_clock_sync | +|tracing_mark_write | +|workqueue_execute_end | +|workqueue_execute_start | + +## 事件对应解析状态: +每种事件解析数据都有5种状态,描述如下表: +|stat_type|description| +|---- |---- | +|received | 统计trace数据源中总共有多少该事件。| +|data_lost | 统计TraceStreamer解析过程中发现丢失数据条数。 | +|not_match | 统计有多少数据与上下文其他数据不匹配。 | +|not_supported | 统计有多少暂不支持解析该事件(一个事件可能包含多种类型的子事件, TraceStreamer可能支持该事件的一部分子事件)。| +|invalid_data | 统计收到多少条该事件的非法数据。| + +## 数据状态级别 +数据状态级别总共有4种,分别是:info, warn, error,fatal。由于数据的重要性不同,不同事件的同一种状态可能对应不同的级别。 +例如binder_transaction_received的 not_supported状态的数据为info级别,而binder_transaction_alloc_buf的not_supported状态数据为warn级别。 + +## 事件,状态与级别对应关系 +| event_name | stat_type | serverity | +|---- |---- |---- | +| binder_transaction | received | info | +| binder_transaction | data_lost | error | +| binder_transaction | not_match | info | +| binder_transaction | not_supported | info | +| binder_transaction | invalid_data | error | +| binder_transaction_received | received | info | +| binder_transaction_received | data_lost | error | +| binder_transaction_received | not_match | info | +| binder_transaction_received | not_supported | info | +| binder_transaction_received | invalid_data | error | +| binder_transaction_alloc_buf | received | info | +| binder_transaction_alloc_buf | data_lost | error | +| binder_transaction_alloc_buf | not_match | info | +| binder_transaction_alloc_buf | not_supported | warn | +| binder_transaction_alloc_buf | invalid_data | error | +| binder_transaction_lock | received | info | +| binder_transaction_lock | data_lost | error | +| binder_transaction_lock | not_match | info | +| binder_transaction_lock | not_supported | warn | +| binder_transaction_lock | invalid_data | error | +| binder_transaction_locked | received | info | +| binder_transaction_locked | data_lost | error | +| binder_transaction_locked | not_match | info | +| binder_transaction_locked | not_supported | warn | +| binder_transaction_locked | invalid_data | error | +| binder_transaction_unlock | received | info | +| binder_transaction_unlock | data_lost | error | +| binder_transaction_unlock | not_match | info | +| binder_transaction_unlock | not_supported | warn | +| binder_transaction_unlock | invalid_data | error | +| sched_switch | received | info | +| sched_switch | data_lost | error | +| sched_switch | not_match | info | +| sched_switch | not_supported | info | +| sched_switch | invalid_data | error | +| task_rename | received | info | +| task_rename | data_lost | error | +| task_rename | not_match | info | +| task_rename | not_supported | info | +| task_rename | invalid_data | error | +| task_newtask | received | info | +| task_newtask | data_lost | error | +| task_newtask | not_match | info | +| task_newtask | not_supported | info | +| task_newtask | invalid_data | error | +| tracing_mark_write | received | info | +| tracing_mark_write | data_lost | error | +| tracing_mark_write | not_match | info | +| tracing_mark_write | not_supported | info | +| tracing_mark_write | invalid_data | error | +| print | received | info | +| print | data_lost | error | +| print | not_match | info | +| print | not_supported | info | +| print | invalid_data | error | +| sched_wakeup | received | info | +| sched_wakeup | data_lost | error | +| sched_wakeup | not_match | info | +| sched_wakeup | not_supported | info | +| sched_wakeup | invalid_data | error | +| sched_waking | received | info | +| sched_waking | data_lost | error | +| sched_waking | not_match | info | +| sched_waking | not_supported | info | +| sched_waking | invalid_data | error | +| cpu_idle | received | info | +| cpu_idle | data_lost | error | +| cpu_idle | not_match | info | +| cpu_idle | not_supported | info | +| cpu_idle | invalid_data | error | +| cpu_frequency | received | info | +| cpu_frequency | data_lost | error | +| cpu_frequency | not_match | info | +| cpu_frequency | not_supported | info | +| cpu_frequency | invalid_data | error | +| suspend_resume | received | info | +| suspend_resume | data_lost | error | +| suspend_resume | not_match | info | +| suspend_resume | not_supported | info | +| suspend_resume | invalid_data | error | +| workqueue_execute_start | received | info | +| workqueue_execute_start | data_lost | error | +| workqueue_execute_start | not_match | info | +| workqueue_execute_start | not_supported | info | +| workqueue_execute_start | invalid_data | error | +| workqueue_execute_end | received | info | +| workqueue_execute_end | data_lost | error | +| workqueue_execute_end | not_match | info | +| workqueue_execute_end | not_supported | warn | +| workqueue_execute_end | invalid_data | error | +| clock_set_rate | received | info | +| clock_set_rate | data_lost | error | +| clock_set_rate | not_match | info | +| clock_set_rate | not_supported | warn | +| clock_set_rate | invalid_data | error | +| clock_enable | received | info | +| clock_enable | data_lost | error | +| clock_enable | not_match | info | +| clock_enable | not_supported | warn | +| clock_enable | invalid_data | error | +| clock_disable | received | info | +| clock_disable | data_lost | error | +| clock_disable | not_match | info | +| clock_disable | not_supported | warn | +| clock_disable | invalid_data | error | +| clk_set_rate | received | info | +| clk_set_rate | data_lost | error | +| clk_set_rate | not_match | info | +| clk_set_rate | not_supported | warn | +| clk_set_rate | invalid_data | error | +| clk_enable | received | info | +| clk_enable | data_lost | error | +| clk_enable | not_match | info | +| clk_enable | not_supported | warn | +| clk_enable | invalid_data | error | +| clk_disable | received | info | +| clk_disable | data_lost | error | +| clk_disable | not_match | info | +| clk_disable | not_supported | warn | +| clk_disable | invalid_data | error | +| sys_enter | received | info | +| sys_enter | data_lost | error | +| sys_enter | not_match | info | +| sys_enter | not_supported | warn | +| sys_enter | invalid_data | error | +| sys_exit | received | info | +| sys_exit | data_lost | error | +| sys_exit | not_match | info | +| sys_exit | not_supported | warn | +| sys_exit | invalid_data | error | +| regulator_set_voltage | received | info | +| regulator_set_voltage | data_lost | error | +| regulator_set_voltage | not_match | info | +| regulator_set_voltage | not_supported | warn | +| regulator_set_voltage | invalid_data | error | +| regulator_set_voltage_complete | received | info | +| regulator_set_voltage_complete | data_lost | error | +| regulator_set_voltage_complete | not_match | info | +| regulator_set_voltage_complete | not_supported | warn | +| regulator_set_voltage_complete | invalid_data | error | +| regulator_disable | received | info | +| regulator_disable | data_lost | error | +| regulator_disable | not_match | info | +| regulator_disable | not_supported | warn | +| regulator_disable | invalid_data | error | +| regulator_disable_complete | received | info | +| regulator_disable_complete | data_lost | error | +| regulator_disable_complete | not_match | info | +| regulator_disable_complete | not_supported | warn | +| regulator_disable_complete | invalid_data | error | +| ipi_entry | received | info | +| ipi_entry | data_lost | error | +| ipi_entry | not_match | info | +| ipi_entry | not_supported | warn | +| ipi_entry | invalid_data | error | +| ipi_exit | received | info | +| ipi_exit | data_lost | error | +| ipi_exit | not_match | info | +| ipi_exit | not_supported | warn | +| ipi_exit | invalid_data | error | +| irq_handler_entry | received | info | +| irq_handler_entry | data_lost | error | +| irq_handler_entry | not_match | info | +| irq_handler_entry | not_supported | warn | +| irq_handler_entry | invalid_data | error | +| irq_handler_exit | received | info | +| irq_handler_exit | data_lost | error | +| irq_handler_exit | not_match | info | +| irq_handler_exit | not_supported | warn | +| irq_handler_exit | invalid_data | error | +| softirq_raise | received | info | +| softirq_raise | data_lost | error | +| softirq_raise | not_match | info | +| softirq_raise | not_supported | warn | +| softirq_raise | invalid_data | error | +| softirq_entry | received | info | +| softirq_entry | data_lost | error | +| softirq_entry | not_match | info | +| softirq_entry | not_supported | warn | +| softirq_entry | invalid_data | error | +| softirq_exit | received | info | +| softirq_exit | data_lost | error | +| softirq_exit | not_match | info | +| softirq_exit | not_supported | warn | +| softirq_exit | invalid_data | error | +| oom_score_adj_update | received | info | +| oom_score_adj_update | data_lost | error | +| oom_score_adj_update | not_match | info | +| oom_score_adj_update | not_supported | warn | +| oom_score_adj_update | invalid_data | error | +| sched_wakeup_new | received | info | +| sched_wakeup_new | data_lost | error | +| sched_wakeup_new | not_match | info | +| sched_wakeup_new | not_supported | warn | +| sched_wakeup_new | invalid_data | error | +| sched_process_exit | received | info | +| sched_process_exit | data_lost | error | +| sched_process_exit | not_match | info | +| sched_process_exit | not_supported | warn | +| sched_process_exit | invalid_data | error | +| sched_process_free | received | info | +| sched_process_free | data_lost | error | +| sched_process_free | not_match | info | +| sched_process_free | not_supported | warn | +| sched_process_free | invalid_data | error | +| trace_event_clock_sync | received | info | +| trace_event_clock_sync | data_lost | error | +| trace_event_clock_sync | not_match | info | +| trace_event_clock_sync | not_supported | warn | +| trace_event_clock_sync | invalid_data | error | +| memory | received | info | +| memory | data_lost | error | +| memory | not_match | info | +| memory | not_supported | warn | +| memory | invalid_data | error | +| hilog | received | info | +| hilog | data_lost | error | +| hilog | not_match | info | +| hilog | not_supported | warn | +| hilog | invalid_data | error | +| hidump_fps | received | info | +| hidump_fps | data_lost | error | +| hidump_fps | not_match | info | +| hidump_fps | not_supported | warn | +| hidump_fps | invalid_data | error | +| native_hook_malloc | received | info | +| native_hook_malloc | data_lost | error | +| native_hook_malloc | not_match | info | +| native_hook_malloc | not_supported | warn | +| native_hook_malloc | invalid_data | error | +| native_hook_free | received | info | +| native_hook_free | data_lost | error | +| native_hook_free | not_match | info | +| native_hook_free | not_supported | warn | +| native_hook_free | invalid_data | error | +| sys_memory | received | info | +| sys_memory | data_lost | error | +| sys_memory | not_match | info | +| sys_memory | not_supported | warn | +| sys_memory | invalid_data | error | +| sys_virtual_memory | received | info | +| sys_virtual_memory | data_lost | error | +| sys_virtual_memory | not_match | info | +| sys_virtual_memory | not_supported | warn | +| sys_virtual_memory | invalid_data | error | +| signal_generate | received | info | +| signal_generate | data_lost | error | +| signal_generate | not_match | info | +| signal_generate | not_supported | warn | +| signal_generate | invalid_data | error | +| signal_deliver | received | info | +| signal_deliver | data_lost | error | +| signal_deliver | not_match | info | +| signal_deliver | not_supported | warn | +| signal_deliver | invalid_data | error | +| trace_block_bio_backmerge | received | info | +| trace_block_bio_backmerge | data_lost | error | +| trace_block_bio_backmerge | not_match | info | +| trace_block_bio_backmerge | not_supported | warn | +| trace_block_bio_backmerge | invalid_data | error | +| trace_block_bio_bounce | received | info | +| trace_block_bio_bounce | data_lost | error | +| trace_block_bio_bounce | not_match | info | +| trace_block_bio_bounce | not_supported | warn | +| trace_block_bio_bounce | invalid_data | error | +| trace_block_bio_complete | received | info | +| trace_block_bio_complete | data_lost | error | +| trace_block_bio_complete | not_match | info | +| trace_block_bio_complete | not_supported | warn | +| trace_block_bio_complete | invalid_data | error | +| trace_block_bio_frontmerge | received | info | +| trace_block_bio_frontmerge | data_lost | error | +| trace_block_bio_frontmerge | not_match | info | +| trace_block_bio_frontmerge | not_supported | warn | +| trace_block_bio_frontmerge | invalid_data | error | +| trace_bblock_bio_queue | received | info | +| trace_bblock_bio_queue | data_lost | error | +| trace_bblock_bio_queue | not_match | info | +| trace_bblock_bio_queue | not_supported | warn | +| trace_bblock_bio_queue | invalid_data | error | +| trace_block_bio_remap | received | info | +| trace_block_bio_remap | data_lost | error | +| trace_block_bio_remap | not_match | info | +| trace_block_bio_remap | not_supported | warn | +| trace_block_bio_remap | invalid_data | error | +| trace_block_dirty_buffer | received | info | +| trace_block_dirty_buffer | data_lost | error | +| trace_block_dirty_buffer | not_match | info | +| trace_block_dirty_buffer | not_supported | warn | +| trace_block_dirty_buffer | invalid_data | error | +| trace_block_getrq | received | info | +| trace_block_getrq | data_lost | error | +| trace_block_getrq | not_match | info | +| trace_block_getrq | not_supported | warn | +| trace_block_getrq | invalid_data | error | +| trace_block_plug | received | info | +| trace_block_plug | data_lost | error | +| trace_block_plug | not_match | info | +| trace_block_plug | not_supported | warn | +| trace_block_plug | invalid_data | error | +| trace_block_rq_complete | received | info | +| trace_block_rq_complete | data_lost | error | +| trace_block_rq_complete | not_match | info | +| trace_block_rq_complete | not_supported | warn | +| trace_block_rq_complete | invalid_data | error | +| trace_block_rq_insert | received | info | +| trace_block_rq_insert | data_lost | error | +| trace_block_rq_insert | not_match | info | +| trace_block_rq_insert | not_supported | warn | +| trace_block_rq_insert | invalid_data | error | +| trace_block_rq_remap | received | info | +| trace_block_rq_remap | data_lost | error | +| trace_block_rq_remap | not_match | info | +| trace_block_rq_remap | not_supported | warn | +| trace_block_rq_remap | invalid_data | error | +| trace_block_rq_issue | received | info | +| trace_block_rq_issue | data_lost | error | +| trace_block_rq_issue | not_match | info | +| trace_block_rq_issue | not_supported | warn | +| trace_block_rq_issue | invalid_data | error | +| other | received | info | +| other | data_lost | error | +| other | not_match | info | +| other | not_supported | warn | +| other | invalid_data | error | diff --git a/host/doc/des_support_event.md b/host/doc/des_support_event.md new file mode 100644 index 0000000000000000000000000000000000000000..bde55dce0c0d849fdf69f5ed882f6d12c9037228 --- /dev/null +++ b/host/doc/des_support_event.md @@ -0,0 +1,224 @@ +# TraceStreamer支持解析事件列表 +## ftrace事件 +``` +binder_transaction +binder_transaction_received +binder_transaction_alloc_buf +binder_transaction_lock +binder_transaction_locked +binder_transaction_unlock +sched_switch +task_rename +task_newtask +tracing_mark_write +print +sched_wakeup +sched_waking +cpu_idle +cpu_frequency +suspend_resume +workqueue_execute_start +workqueue_execute_end +clock_set_rate +clock_enable +clock_disable +clk_set_rate +clk_enable +clk_disable +sys_enter +sys_exit +regulator_set_voltage +regulator_set_voltage_complete +regulator_disable +regulator_disable_complete +ipi_entry +ipi_exit +irq_handler_entry +irq_handler_exit +softirq_raise +softirq_entry +softirq_exit +sched_wakeup_new +sched_process_exit +trace_event_clock_sync +``` +## 内存事件 +``` +mem.vm.size +mem.rss +mem.rss.anon +mem.rss.file +mem.rss.schem +mem.swap +mem.locked +mem.hwm +mem.oom_score_adj +``` +## 系统内存事件 +``` +sys.mem.unspecified +sys.mem.total +sys.mem.free +sys.mem.avaiable +sys.mem.buffers +sys.mem.cached +sys.mem.swap.chard +sys.mem.active +sys.mem.inactive +sys.mem.active.anon +sys.mem.inactive.anon +sys.mem.active_file +sys.mem.inactive_file +sys.mem.unevictable +sys.mem.mlocked +sys.mem.swap.total +sys.mem.swap.free +sys.mem.dirty +sys.mem.writeback +sys.mem.anon.pages +sys.mem.mapped +sys.mem.shmem +sys.mem.slab +sys.mem.slab.reclaimable +sys.mem.slab.unreclaimable +sys.mem.kernel.stack +sys.mem.page.tables +sys.mem.commit.limit +sys.mem.commited.as +sys.mem.vmalloc.total +sys.mem.vmalloc.used +sys.mem.vmalloc.chunk +sys.mem.cma.total +sys.mem.cma.free +``` +## 系统虚拟内存事件 +``` +sys.virtual.mem.unspecified +sys.virtual.mem.nr.free.pages +sys.virtual.mem.nr.alloc.batch +sys.virtual.mem.nr.inactive.anon +sys.virtual.mem.nr.active_anon +sys.virtual.mem.nr.inactive.file +sys.virtual.mem.nr.active_file +sys.virtual.mem.nr.unevictable +sys.virtual.mem.nr.mlock +sys.virtual.mem.anon.pages +sys.virtual.mem.nr.mapped +sys.virtual.mem.nr.file.pages +sys.virtual.mem.nr.dirty +sys.virtual.mem.nr.writeback +sys.virtual.mem.nr.slab.reclaimable +sys.virtual.mem.nr.slab.unreclaimable +sys.virtual.mem.nr.page_table.pages +sys.virtual.mem.nr_kernel.stack +sys.virtual.mem.nr.overhead +sys.virtual.mem.nr.unstable +sys.virtual.mem.nr.bounce +sys.virtual.mem.nr.vmscan.write +sys.virtual.mem.nr.vmscan.immediate.reclaim +sys.virtual.mem.nr.writeback_temp +sys.virtual.mem.nr.isolated_anon +sys.virtual.mem.nr.isolated_file +sys.virtual.mem.nr.shmem +sys.virtual.mem.nr.dirtied +sys.virtual.mem.nr.written +sys.virtual.mem.nr.pages.scanned +sys.virtual.mem.workingset.refault +sys.virtual.mem.workingset.activate +sys.virtual.mem.workingset_nodereclaim +sys.virtual.mem.nr_anon.transparent.hugepages +sys.virtual.mem.nr.free_cma +sys.virtual.mem.nr.swapcache +sys.virtual.mem.nr.dirty.threshold +sys.virtual.mem.nr.dirty.background.threshold +sys.virtual.mem.vmeminfo.pgpgin +sys.virtual.mem.pgpgout +sys.virtual.mem.pgpgoutclean +sys.virtual.mem.pswpin +sys.virtual.mem.pswpout +sys.virtual.mem.pgalloc.dma +sys.virtual.mem.pgalloc.normal +sys.virtual.mem.pgalloc.movable +sys.virtual.mem.pgfree +sys.virtual.mem.pgactivate +sys.virtual.mem.pgdeactivate +sys.virtual.mem.pgfault +sys.virtual.mem.pgmajfault +sys.virtual.mem.pgrefill.dma +sys.virtual.mem.pgrefill.normal +sys.virtual.mem.pgrefill.movable +sys.virtual.mem.pgsteal.kswapd.dma +sys.virtual.mem.pgsteal.kswapd.normal +sys.virtual.mem.pgsteal.kswapd.movable +sys.virtual.mem.pgsteal.direct.dma +sys.virtual.mem.pgsteal.direct.normal +sys.virtual.mem.pgsteal_direct.movable +sys.virtual.mem.pgscan.kswapd.dma +sys.virtual.mem.pgscan_kswapd.normal +sys.virtual.mem.pgscan.kswapd.movable +sys.virtual.mem.pgscan.direct.dma +sys.virtual.mem.pgscan.direct.normal +sys.virtual.mem.pgscan.direct.movable +sys.virtual.mem.pgscan.direct.throttle +sys.virtual.mem.pginodesteal +sys.virtual.mem.slabs_scanned +sys.virtual.mem.kswapd.inodesteal +sys.virtual.mem.kswapd.low.wmark.hit.quickly +sys.virtual.mem.high.wmark.hit.quickly +sys.virtual.mem.pageoutrun +sys.virtual.mem.allocstall +sys.virtual.mem.pgrotated +sys.virtual.mem.drop.pagecache +sys.virtual.mem.drop.slab +sys.virtual.mem.pgmigrate.success +sys.virtual.mem.pgmigrate.fail +sys.virtual.mem.compact.migrate.scanned +sys.virtual.mem.compact.free.scanned +sys.virtual.mem.compact.isolated +sys.virtual.mem.compact.stall +sys.virtual.mem.compact.fail +sys.virtual.mem.compact.success +sys.virtual.mem.compact.daemon.wake +sys.virtual.mem.unevictable.pgs.culled +sys.virtual.mem.unevictable.pgs.scanned +sys.virtual.mem.unevictable.pgs.rescued +sys.virtual.mem.unevictable.pgs.mlocked +sys.virtual.mem.unevictable.pgs.munlocked +sys.virtual.mem.unevictable.pgs.cleared +sys.virtual.mem.unevictable.pgs.stranded +sys.virtual.mem.nr.zspages +sys.virtual.mem.nr.ion.heap +sys.virtual.mem.nr.gpu.heap +sys.virtual.mem.allocstall.dma +sys.virtual.mem.allocstall.movable +sys.virtual.mem.allocstall.normal +sys.virtual.mem.compact_daemon.free.scanned +sys.virtual.mem.compact.daemon.migrate.scanned +sys.virtual.mem.nr.fastrpc +sys.virtual.mem.nr.indirectly.reclaimable +sys.virtual.mem.nr_ion_heap_pool +sys.virtual.mem.nr.kernel_misc.reclaimable +sys.virtual.mem.nr.shadow_call.stack_bytes +sys.virtual.mem.nr.shmem.hugepages +sys.virtual.mem.nr.shmem.pmdmapped +sys.virtual.mem.nr.unreclaimable.pages +sys.virtual.mem.nr.zone.active.anon +sys.virtual.mem.nr.zone.active.file +ys.virtual.mem.nr.zone.inactive_anon +sys.virtual.mem.nr.zone.inactive_file +sys.virtual.mem.nr.zone.unevictable +sys.virtual.mem.nr.zone.write_pending +sys.virtual.mem.oom.kill +sys.virtual.mem.pglazyfree +sys.virtual.mem.pglazyfreed +sys.virtual.mem.pgrefill +sys.virtual.mem.pgscan.direct +sys.virtual.mem.pgscan.kswapd +sys.virtual.mem.pgskip.dma +sys.virtual.mem.pgskip.movable +sys.virtual.mem.pgskip.normal +sys.virtual.mem.pgsteal.direct +sys.virtual.mem.pgsteal.kswapd +sys.virtual.mem.swap.ra +sys.virtual.mem.swap.ra.hit +``` \ No newline at end of file diff --git a/host/doc/des_tables.md b/host/doc/des_tables.md new file mode 100644 index 0000000000000000000000000000000000000000..efe0a6f7b4ab4352fc1a9cce82963d86293d8a4e --- /dev/null +++ b/host/doc/des_tables.md @@ -0,0 +1,306 @@ +# ___概述TraceStreamer生成的数据库___ +``` + TraceStreamer虽然对外提供了各种各样的使用方式,但核心的业务仍是将trace数据源转化为易于理解和使用的数据库。用户可以通过SmartPerf界面直观的研究系统跟踪数据,也可在理解TraceStreamer生成的数据库的基础上,在TraceStreamer的交互模式或者Smartperf的数据库查询模式下,使用SQL查询语句自由组装查看用户关心的数据。 下文将对TraceStreamer生成的数据库进行详细描述,给用户使用SQL查询系统跟踪数据提供帮助。 +``` + +## ___TraceStreamer输出数据库包含以下表格___ +* trace_range : 记录ftrace数据与其他类型数据的时间交集,供前端展示数据时使用。 +* process : 记录进程信息。 +* thread : 记录线程信息。 +* thread_state : 记录线程状态信息。 +* instant : 记录Sched_waking, sched_wakeup事件, 用作ThreadState表的上下文使用。 +* raw : 此数据结构主要作为ThreadState的上下文使用,这张表是sched_waking,sched_wakup, cpu_idle事件的原始记录。 +* callstack : 记录调用堆栈和异步调用,其中depth,stack_id和parent_stack_id仅在非异步调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,否则为线程唯一号。 +* irq : 记录中断相关事件。 +* measure : 记录所有的计量值。 +* log : 记录hilog打印日志数据。 +* heap : 记录堆内存申请与释放相关的数据。 +* heap_frame : 记录堆内存申请与释放相关的调用栈。 +* hidump : 记录FPS(Frame Per Second)数据。 +* symbols : 记录系统调用名称和其函数指针的对应关系,trace中用addr来映射function_name来节省存储空间 +* syscall : 记录用户空间函数与内核空间函数相互调用记录 +* args : 记录方法参数集合 +* sys_event_filter : 记录所有的filter +* clk_event_filter : 记录时钟事件 +* cpu_measure_filter : cpu事件过滤器表。 +* measure_filter : 记录一个递增的filterid队列,所有其他的filter类型在获取过程中,均从此数据列表中获取下一个可用的filter_id并做记录。 +* process_measure_filter : 将进程ID作为key1,进程的内存,界面刷新,屏幕亮度等信息作为key2,唯一确定一个filter_id +* data_type : 记录数据类型和typeId的关联关系。 +* data_dict : 记录常用的字符串,将字符串和索引关联,降低程序运行的内存占用,用作辅助数据。 +* meta : 记录执行解析操作相关的基本信息。 + +## ___表格关系图___ + +### 进程表与线程表关系图: +![GitHub Logo](../figures/process_thread.png) +### 描述: +当一个进程或者线程结束后,系统可能再次将该进程号或者线程号分配给其他进程或者线程,造成一个进程号或线程号代表多个进程或线程的情况。 +Process和Thread表中的id字段可以唯一标识进程和线程。process表中的id在其他表中用作ipid字段。thread表中的id在其他表中用作itid字段。 +thread表通过ipid字段关联process表的id字段,可以查询线程归属进程。 +### 举例: +已知pid = 123,查看当前进程下的所有线程信息,可以使用如下SQL语句: +select thread.* from thread, process where process.pid = 123 and thread.ipid = process.id + +### 线程表与线程运行状态表关系图 +![GitHub Logo](../figures/thread_state.png) +### 描述: +thread_state表记录所有线程的运行状态信息,包含ts(状态起始时间),dur(状态持续时间),cpu, itid, state(线程状态)。 thread表的id字段与thread_state表的itid字段相关联。 +### 举例: +已知tid = 123, 查看当前线程的所有运行状态信息,可以使用如下SQL语句: +select thread_state.* from thread, thread_state where thread.tid = 123 and thread.id = thread_state.itid + +### 堆内存数据变化表关系图 +![GitHub Logo](../figures/dump_and_mem.png) +### 描述: +heap表记录堆内存申请(AllocEvent)和释放(FreeEvent)数据。heap表通过ipid和itid字段分别与process和thread表的id字段关联,通过eventId与heap_frame表的eventId字段相关联。 +heap表字段解释如下: + eventId: 唯一标识一次堆内存申请或释放, 通过与heap_frame表关联可以拿到当前申请或释放的函数调用堆栈。 + addr: 堆内存申请/释放的地址 + heap_size: 堆内存申请/释放的大小 +heap_frame表记录内存申请/释放的调用堆栈。通过eventId区分一组调用堆栈,depth为堆栈深度,depth为0时,表示当前行为栈顶数据。 +### 举例: +已知tid = 123, 查看当前线程的所有堆内存变化信息,可以使用如下SQL语句: +select heap.* from thread, heap where thread.tid = 123 and thread.id = heap.itid +已知eventid = 0, 查看当前内存变化调用堆栈 +select * from heap_frame where eventId = 0 + +### 日志表与进程线程表关系图 +![GitHub Logo](../figures/log.png) +### 描述: +log表记录日志信息。可以根据seq字段的连续性,来判断是否存在日志丢失的情况。 +### 举例: +已知tid = 123, 查看当前线程的所有error级别的日志,可以使用如下SQL语句: +select * from log where tid = 123 and level = "error" + + +## TraceStreamer输出数据库表格详细介绍 +### trace_range表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|start_ts |NUM | +|end_ts |INT | +#### 关键字段描述: +start_ts: trace的开始时间,纳秒为单位 +end_ts: trace的结束时间,纳秒为单位 +### process表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |NUM | +|type |INT | +|pid |NUM | +|name |INT | +|start_ts |NUM | +#### 关键字段描述: +id: 进程在数据库重新重新定义的id,从0开始序列增长 +pid: 进程的真实id +name: 进程名字 +### thread表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |NUM | +|tid |INT | +|name |NUM | +|start_ts |INT | +|end_ts |INT | +|ipid |INT | +|is_main_thread|INT | +#### 字段详细描述: +id: 线程在数据库重新重新定义的id,从0开始序列增长 +ipid: 线程所属的进程id, 关联进程表中的ID +name: 线程名字 +is_main_thread: 是否主线程,主线程即该线程实际就是进程本身 + +### thread_state表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |NUM | +|ts |INT | +|dur |INT | +|cpu |INT | +|itid |INT | +|state |NUM | +#### 字段详细描述: +id: 线程状态在数据库中的id,从0开始序列增长 +ts: 该线程状态的起始时间 +dur: 该线程状态的持续时间 +cpu: 该线程在哪个cpu上执行(针对running状态的线程) +itid: 该状态所属的线程所属的进程id, 关联进程表中的ID +state: 线程实际的的状态值 +``` +'R', Runnable状态 +'S', interruptible sleep +'D', uninterruptible sleep +'T', Stoped +'t', Traced +'X', ExitedDead +'Z', ExitZombie +'x', TaskDead +'I', TaskDead +'K', WakeKill +'P', Parked +'N', NoLoad +``` +### instant表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|ts |INT | +|name |NUM | +|ref |INT | +|ref_type |NUM | +#### 表描述: +记录了系统中的waking和wakeup事件。 +### raw表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |NUM | +|ts |INT | +|name |NUM | +|cpu |INT | +|itid |INT | +#### 表描述: +记录了系统中的waking、wakup、cpu_idel、cpu_frequency数据。 + +### callstack表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|ts |INT | +|dur |INT | +|callid |INT | +|cat |NUM | +|name |NUM | +|depth |INT | +|cookie |INT | +|parent_id |INT | +|argsetid |INT | +|chainId |NUM | +|spanId |NUM | +|parentSpanId |NUM | +|flag |NUM | +|args |NUM | +#### 字段详细描述: +dur: 调用时长 +callid: 调用者的ID,比如针对线程表里面的id +name: 调用名称 +depth: 调用深度 +parent_id: 父调用的id + +### measure表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|type |NUM | +|ts |INT | +|value |INT | +|filter_id |INT | +#### 字段详细描述: + +### heap表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|eventId |INT | +|ipid |INT | +|itid |INT | +|event_type |NUM | +|start_ts |INT | +|end_ts |INT | +|dur |INT | +|addr |INT | +|heap_size |INT | +|all_heap_size |INT | +#### 字段详细描述: + +### heap_frame表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|eventId |INT | +|depth |INT | +|ip |INT | +|sp |INT | +|symbol_name |NUM | +|file_path |NUM | +|offset |INT | +|symbol_offset |INT | +#### 表描述: +记录了内存的申请和释放的堆栈。 +### hidump表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|ts |INT | +|fps |INT | +#### 表描述: +此表记录了设备的帧率信息,fps。 +### symbols表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|funcname |NUM | +|addr |INT | +#### 表描述: +此表记录了数值和函数调用名称的映射关系。 + +### measure_filter表 +记录一个递增的filterid队列,所有其他的filter类型在获取过程中,均从此数据列表中获取下一个可用的filter_id并做记录。 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |NUM | +|type |NUM | +|name |INT | +|source_arg_set_id |INT | + +#### 字段详细描述: +过滤分类(type),过滤名称(key2),数据ID(key1)。 +数据ID在process_measure_filter, sys_event_filter中作为id。 +### process_measure_filter表 +将进程ID作为key1,进程的内存,界面刷新,屏幕亮度等信息作为key2,唯一确定一个filter_id, filter_id同时被记录在measure_filter表中。 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |NUM | +|name |NUM | +|ipid |INT | +#### 字段详细描述: +filterid: 来自measure_filter表 +name: cpu状态名 +ipid: 进程内部编号 +### data_type表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|typeId |INT | +|desc |NUM | +#### 表描述: +此表记录了一个数据类型ID和数据描述的映射。 +### data_dict表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|data |NUM | +#### 表描述: +此表记录了一个数据类型ID和字符串的映射。 +### meta表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|name |NUM | +|value |NUM | +#### 表描述: +此表记录了数据解析或导出时的一些现场数据,比如使用的trace_streamer版本, 工具的发布时间,数据解析的时间,数据的持续时长,以及原始数据的格式。 diff --git a/host/doc/quickstart_hiprofiler_cmd.md b/host/doc/quickstart_hiprofiler_cmd.md new file mode 100644 index 0000000000000000000000000000000000000000..f9a798fb5ae7c8c12a875148b6cd4ed2c319fd30 --- /dev/null +++ b/host/doc/quickstart_hiprofiler_cmd.md @@ -0,0 +1,39 @@ +# 1.hiprofiler_cmd 使用说明 +## 1.1参数说明 + 执行hiprofiler_cmd 为调优业务的离线命令行抓取工具,具体使用方法及命令行参数介绍如下。 + +可以使用`-h`或者`--help`参数查看命令的使用描述信息: + +```sh +# ./hiprofiler_cmd -h +help : + --getport -q : get grpc address + --config -c : start trace by config file + --time -t : trace time + --out -o : output file name + --help -h : make some help +``` + +其余参数使用说明如下: +* `-q`或者`--getport`选项,用于查询服务的端口信息; +* `-c`或者`--config`选项,用于指定配置文件; +* `-t`或者`--time`选项,用于指定抓取时间,单位是秒; +* `-o`或者`--out`选项,用于指定输出的离线数据文件名; +* `-h`或者`--help`选项,用于输出帮助信息; + +# 2.使用具体场景 +![GitHub Logo](../figures/systraceconfig.jpg) +说明: +* Record setting:设置trace的抓取模式,buffer size大小,抓取时长 +* Trace command:生成的抓取命令行 +* Probes config:trace的抓取参数配置 +* Allocations:Nativehook的抓取参数配置 +## 2.1命令行的生成和trace文件的抓取 +点击Probes config,如选择抓取Scheduling details,再点击Record setting,设置buffer size大小,抓取时长 +![GitHub Logo](../figures/Scheduling.jpg) +如下图,就会根据上面的配置生成抓取命令,点击复制按钮,会将命令行复制 +![GitHub Logo](../figures/command.jpg) +进入设备,在执行命令前,需要手动拉起hiprofilerd,hiprofiler_plugins,如果要抓取nativehook数据,还要手动拉起native_daemon,进程都拉起后执行命令 +![GitHub Logo](../figures/excutecommand.jpg) +执行完成后,进入指定目录查看,如/data/local/tmp下就会生成trace文件 +![GitHub Logo](../figures/htrace.jpg) \ No newline at end of file diff --git a/host/doc/quickstart_smartperf.md b/host/doc/quickstart_smartperf.md new file mode 100644 index 0000000000000000000000000000000000000000..b550d64d65d3877f7955d040b701ac214caacc4c --- /dev/null +++ b/host/doc/quickstart_smartperf.md @@ -0,0 +1,66 @@ +# 网页加载trace 使用说明 + +## 1.打开版本包里面的main.exe可执行文件,启动web页面 +![GitHub Logo](../figures/main.jpg) + +## 2.Web页面展开 +![GitHub Logo](../figures/opentrace.jpg) + +说明: ++ Open trace file:导入离线trace文件入口 ++ Record new trace:抓取新的trace文件入口 + +## 3.导入文件后显示页面 +![GitHub Logo](../figures/trace.jpg) +说明: ++ 操作说明:在当前页面可以通过键盘上的wasd四个键位操纵当前的时间轴进行缩放,w放大,s为缩小,a为左移,d为右移。 +## 功能介绍 +模块从上往下主要展示时间轴和cpu使用率、cpu使用情况、进程间通讯数据的方法调用情况、进程、线程和方法调用情况 +### 1. 时间轴和cpu使用率 +![GitHub Logo](../figures/figures/time.jpg) +最上方带刻度的为时间轴,主要展示当前抓取数据的总时长和时间刻度的分布情况,如上图所示,左下角展示总时长, +中间区域展示的是抓取数据时间段内的cpu使用率,颜色越深代表cpu使用率越高,颜色越浅代表cpu使用率越低。 +![GitHub Logo](../figures/highlit.jpg) +在白色背景时间轴区域内可以点击后拖拽鼠标,可以对从鼠标按下到拖拽完成鼠标松开的区域内的数据进行筛选,高亮显示的部分为当前所选区域,如上图所示 +### 2.cpu使用情况 +![GitHub Logo](../figures/cpu.jpg) + +如上图所示,当前抓取数据有4个cpu工作,前四组数据对应的是当前调用cpu的线程和对应的进程情况,以颜色作为区分。后四组数据则为cpu的使用频率信息。鼠标移动到相应的线程上还会将当前选中的进程信息全部置为高亮,其他的进程会置灰,如下图所示 +![GitHub Logo](../figures/gray.jpg) +#### 2.1.cpu使用情况的框选功能 +可以对cpu的数据进行框选,框选后在最下方的弹出层中会展示框选数据的统计表格,总共有三个tab页 +CPU by thread的Tab页,主要显示了在框选时间区间内的进程名,进程号,线程名,线程号,总运行时长,平均运行时长和调度次数信息 +![GitHub Logo](../figures/cpubythread.jpg) +CPU by process的Tab页,主要显示了在框选时间区间内的进程名,进程号,总运行时长,平均运行时长和调度次数信息 +![GitHub Logo](../figures/cpubyprocess.jpg) +CPUUsage的Tab页,主要显示了在框选时间区间内,该频率时间占比前三的信息 +![GitHub Logo](../figures/cpusage.jpg) +#### 2.2.cpu使用情况的单选功能 +单选CPU使用情况数据,单击方法会在选中的方法外层加上深色边框,能够突出当前选中色块,弹出层中会展示当前CPU上的进程名,线程名,开始时间和运行时长,线程运行状态等信息 +![GitHub Logo](../figures/cpuclick.jpg) +### 3.FPS数据 +FPS是帧率的显示,每秒产生画面的个数 +![GitHub Logo](../figures/fps.jpg) +#### 3.1FPS的框选功能 +可以对fps的数据进行框选,框选后在最下方的弹出层中会展示框选时间区间内的统计表格,主要显示了time(时间),FPS(帧率) +![GitHub Logo](../figures/fpsselect.jpg) +### 4.进程,线程和方法数据 +下图是进程数据,左边部分展示进程名称和id +![GitHub Logo](../figures/process.jpg) +点击进程名前面向下箭头可以展开对应的线程进行查看,展开后的线程如下图,如果存在堆内存占用情况,就会显示在第一行,如果出现两个名字和id一样的线程,则第一个为线程的使用情况,第二为线程内的方法栈调用情况 +![GitHub Logo](../figures/threadinfo.jpg) + +#### 4.1进程,线程和方法数据的框选功能 +可以对线程的数据进行框选,框选后在最下方的弹出层中会展示框选数据的统计表格,包含线程运行状态,线程调用栈的统计情况。当框选的数据中同时存在线程运行状态和线程调用栈数据,下方的弹出层中就会出现多个tab选项,可以进行切换 + +下图是线程运行状态框选统计信息,包括进程名,进程号,线程名,线程号,线程状态,状态持续时间,平均持续时间,该线程状态发生的次数 +![GitHub Logo](../figures/threadselect.jpg) + +下图是线程调用栈框选统计信息,包括方法名,持续时间,平均持续时间,调用的次数 +![GitHub Logo](../figures/callstackselect.jpg) +#### 4.2进程,线程和方法数据的单选功能 +单选线程的state数据时,会展示当前选中线程的状态数据,开始时间和持续时长,线程状态,所在进程名称、 +![GitHub Logo](../figures/threadclick.jpg) +单选调用栈数据,单击方法会在选中的方法外层加上黑色边框,能够突出当前选中的方法,弹出层中会展示当前方法的名称、开始时间和运行时长信息。 +![GitHub Logo](../figures/callstackclick.jpg) + diff --git a/host/doc/quickstart_trace_streamer.md b/host/doc/quickstart_trace_streamer.md new file mode 100644 index 0000000000000000000000000000000000000000..eb0deec07b8f4c55fed4152454f49cad6d721cb9 --- /dev/null +++ b/host/doc/quickstart_trace_streamer.md @@ -0,0 +1,309 @@ +# trace_streamer工具说明 +trace_streamer工具可以2种方式使用 +1. 可以将系统离线trace文件解析并转为db,此工具支持基于文本的trace和基于proto的trace。 +2. trace_streamer工具还可以WebAssembly的方式在浏览器中运行,需暴露相关接口给js文件。 + +## 关于trace解析工具的使用说明: +### 导出db模式 +在导出db模式下,trace_streamer.exe trace文件路径名 -e 导出db路径名.db +此命令可以将trace文件转为db +本应用支持在ohos, linux, windows, mac使用。 +关于db文件的说明: +使用db查看工具查看stat表,可以浏览当前数据一共有多少类数据,各类数据都收到多少条,数据是否正常等情况。在meta表会记录数据库导出时的一些系统信息,比如导入和导出的文件全路径,解析时间等信息。 +meta表可以选择不导出(有些情况下会暴露系统敏感信息),在导出时添加 -nm选项即可。 +在数据导出之后,会在本地目录下生成一个trace_streamer.log文件,在导出db的目录下生成一个数据库文件同名,.db.ohos.ts后缀的文件 +文件内容如下: +时间戳:执行结果(数字) +应用运行时间 + +执行结果解释如下:0 代表执行成功 1 表示输入文件不匹配, 2 表示解析错误, 3其他错误 +### 内置浏览器方式 +trace_streamer可以WebAssembly方式在浏览器中运行,暴露如下接口给js +``` +extern "C" { +/* 上传trace数据 + * + * @data: 数据的缓冲区 + * @dataLen: 数据长度 + * + * return: 0:成功; -1:失败 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerParseData(const uint8_t* data, int dataLen); + +/* 通知TS上传trace数据结束 + * + * return: 0:成功; -1:失败 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerParseDataOver(); + +/* 通过sql语句操作数据库 + * + * @sql: sql语句 + * @sqlLen: sql语句长度 + * + * return: 0:成功; -1:失败 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlOperate(const uint8_t* sql, int sqlLen); + +/* 通过sql语句查询数据库 + * + * @sql: sql语句 + * @sqlLen: sql语句长度 + * @out: 查询结果的缓冲区,查询结果为json + * @outLen: 缓冲区长度 + * + * return: >0:查询成功,返回查询结果数据长度; -1:失败 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlQuery(const uint8_t* sql, int sqlLen, uint8_t* out, int outLen); + +} // extern "C" +``` + +### 你也可以执行如下命令查看应用帮助 +./trace_streamer --help +-i 选项可查看应用支持的事件源和具体的事件名列表 + +#### trace_streamer支持的事件解析 +本工具支持基于文本的trace(# TRACE)和基于proto的二进制日志文件的解析,支持的事件列表如下: +##### ftrace事件 +``` +binder_transaction +binder_transaction_received +binder_transaction_alloc_buf +binder_transaction_lock +binder_transaction_locked +binder_transaction_unlock +sched_switch +task_rename +task_newtask +tracing_mark_write +print +sched_wakeup +sched_waking +cpu_idle +cpu_frequency +suspend_resume +workqueue_execute_start +workqueue_execute_end +clock_set_rate +clock_enable +clock_disable +clk_set_rate +clk_enable +clk_disable +sys_enter +sys_exit +regulator_set_voltage +regulator_set_voltage_complete +regulator_disable +regulator_disable_complete +ipi_entry +ipi_exit +irq_handler_entry +irq_handler_exit +softirq_raise +softirq_entry +softirq_exit +sched_wakeup_new +sched_process_exit +trace_event_clock_sync +``` +##### 内存事件 +``` +mem.vm.size +mem.rss +mem.rss.anon +mem.rss.file +mem.rss.schem +mem.swap +mem.locked +mem.hwm +mem.oom_score_adj +``` +##### 系统内存事件 +``` +sys.mem.unspecified +sys.mem.total +sys.mem.free +sys.mem.avaiable +sys.mem.buffers +sys.mem.cached +sys.mem.swap.chard +sys.mem.active +sys.mem.inactive +sys.mem.active.anon +sys.mem.inactive.anon +sys.mem.active_file +sys.mem.inactive_file +sys.mem.unevictable +sys.mem.mlocked +sys.mem.swap.total +sys.mem.swap.free +sys.mem.dirty +sys.mem.writeback +sys.mem.anon.pages +sys.mem.mapped +sys.mem.shmem +sys.mem.slab +sys.mem.slab.reclaimable +sys.mem.slab.unreclaimable +sys.mem.kernel.stack +sys.mem.page.tables +sys.mem.commit.limit +sys.mem.commited.as +sys.mem.vmalloc.total +sys.mem.vmalloc.used +sys.mem.vmalloc.chunk +sys.mem.cma.total +sys.mem.cma.free +``` +##### 系统虚拟内存事件 +``` +sys.virtual.mem.unspecified +sys.virtual.mem.nr.free.pages +sys.virtual.mem.nr.alloc.batch +sys.virtual.mem.nr.inactive.anon +sys.virtual.mem.nr.active_anon +sys.virtual.mem.nr.inactive.file +sys.virtual.mem.nr.active_file +sys.virtual.mem.nr.unevictable +sys.virtual.mem.nr.mlock +sys.virtual.mem.anon.pages +sys.virtual.mem.nr.mapped +sys.virtual.mem.nr.file.pages +sys.virtual.mem.nr.dirty +sys.virtual.mem.nr.writeback +sys.virtual.mem.nr.slab.reclaimable +sys.virtual.mem.nr.slab.unreclaimable +sys.virtual.mem.nr.page_table.pages +sys.virtual.mem.nr_kernel.stack +sys.virtual.mem.nr.overhead +sys.virtual.mem.nr.unstable +sys.virtual.mem.nr.bounce +sys.virtual.mem.nr.vmscan.write +sys.virtual.mem.nr.vmscan.immediate.reclaim +sys.virtual.mem.nr.writeback_temp +sys.virtual.mem.nr.isolated_anon +sys.virtual.mem.nr.isolated_file +sys.virtual.mem.nr.shmem +sys.virtual.mem.nr.dirtied +sys.virtual.mem.nr.written +sys.virtual.mem.nr.pages.scanned +sys.virtual.mem.workingset.refault +sys.virtual.mem.workingset.activate +sys.virtual.mem.workingset_nodereclaim +sys.virtual.mem.nr_anon.transparent.hugepages +sys.virtual.mem.nr.free_cma +sys.virtual.mem.nr.swapcache +sys.virtual.mem.nr.dirty.threshold +sys.virtual.mem.nr.dirty.background.threshold +sys.virtual.mem.vmeminfo.pgpgin +sys.virtual.mem.pgpgout +sys.virtual.mem.pgpgoutclean +sys.virtual.mem.pswpin +sys.virtual.mem.pswpout +sys.virtual.mem.pgalloc.dma +sys.virtual.mem.pgalloc.normal +sys.virtual.mem.pgalloc.movable +sys.virtual.mem.pgfree +sys.virtual.mem.pgactivate +sys.virtual.mem.pgdeactivate +sys.virtual.mem.pgfault +sys.virtual.mem.pgmajfault +sys.virtual.mem.pgrefill.dma +sys.virtual.mem.pgrefill.normal +sys.virtual.mem.pgrefill.movable +sys.virtual.mem.pgsteal.kswapd.dma +sys.virtual.mem.pgsteal.kswapd.normal +sys.virtual.mem.pgsteal.kswapd.movable +sys.virtual.mem.pgsteal.direct.dma +sys.virtual.mem.pgsteal.direct.normal +sys.virtual.mem.pgsteal_direct.movable +sys.virtual.mem.pgscan.kswapd.dma +sys.virtual.mem.pgscan_kswapd.normal +sys.virtual.mem.pgscan.kswapd.movable +sys.virtual.mem.pgscan.direct.dma +sys.virtual.mem.pgscan.direct.normal +sys.virtual.mem.pgscan.direct.movable +sys.virtual.mem.pgscan.direct.throttle +sys.virtual.mem.pginodesteal +sys.virtual.mem.slabs_scanned +sys.virtual.mem.kswapd.inodesteal +sys.virtual.mem.kswapd.low.wmark.hit.quickly +sys.virtual.mem.high.wmark.hit.quickly +sys.virtual.mem.pageoutrun +sys.virtual.mem.allocstall +sys.virtual.mem.pgrotated +sys.virtual.mem.drop.pagecache +sys.virtual.mem.drop.slab +sys.virtual.mem.pgmigrate.success +sys.virtual.mem.pgmigrate.fail +sys.virtual.mem.compact.migrate.scanned +sys.virtual.mem.compact.free.scanned +sys.virtual.mem.compact.isolated +sys.virtual.mem.compact.stall +sys.virtual.mem.compact.fail +sys.virtual.mem.compact.success +sys.virtual.mem.compact.daemon.wake +sys.virtual.mem.unevictable.pgs.culled +sys.virtual.mem.unevictable.pgs.scanned +sys.virtual.mem.unevictable.pgs.rescued +sys.virtual.mem.unevictable.pgs.mlocked +sys.virtual.mem.unevictable.pgs.munlocked +sys.virtual.mem.unevictable.pgs.cleared +sys.virtual.mem.unevictable.pgs.stranded +sys.virtual.mem.nr.zspages +sys.virtual.mem.nr.ion.heap +sys.virtual.mem.nr.gpu.heap +sys.virtual.mem.allocstall.dma +sys.virtual.mem.allocstall.movable +sys.virtual.mem.allocstall.normal +sys.virtual.mem.compact_daemon.free.scanned +sys.virtual.mem.compact.daemon.migrate.scanned +sys.virtual.mem.nr.fastrpc +sys.virtual.mem.nr.indirectly.reclaimable +sys.virtual.mem.nr_ion_heap_pool +sys.virtual.mem.nr.kernel_misc.reclaimable +sys.virtual.mem.nr.shadow_call.stack_bytes +sys.virtual.mem.nr.shmem.hugepages +sys.virtual.mem.nr.shmem.pmdmapped +sys.virtual.mem.nr.unreclaimable.pages +sys.virtual.mem.nr.zone.active.anon +sys.virtual.mem.nr.zone.active.file +ys.virtual.mem.nr.zone.inactive_anon +sys.virtual.mem.nr.zone.inactive_file +sys.virtual.mem.nr.zone.unevictable +sys.virtual.mem.nr.zone.write_pending +sys.virtual.mem.oom.kill +sys.virtual.mem.pglazyfree +sys.virtual.mem.pglazyfreed +sys.virtual.mem.pgrefill +sys.virtual.mem.pgscan.direct +sys.virtual.mem.pgscan.kswapd +sys.virtual.mem.pgskip.dma +sys.virtual.mem.pgskip.movable +sys.virtual.mem.pgskip.normal +sys.virtual.mem.pgsteal.direct +sys.virtual.mem.pgsteal.kswapd +sys.virtual.mem.swap.ra +sys.virtual.mem.swap.ra.hit +``` + +## trace_streamer开发环境搭建和编译运行指引 + +本应用使用gn作为构建工具,支持在linux环境同时编译linux,windows和mac使用QtCreator作为开发IDE +### 1、开发环境 +ubuntu使用vscode,windows和mac使用QtCreator +# 对外部的依赖 +本应用依赖与sqlite,protobuf(htrace解析部分依赖) + +本应用同时依赖于src/protos目录下文件来生成相关pb.h,pb.cc文件 + +### 2.1、 编译linux版应用 +在根目录下执行相关命令进行编译 + +### 2.2、编译Windows版和Mac应用 +在项目目录下有pro文件,为QtCreator的工程文件,但部分内容赖在于上面所添加的外部依赖,如果要编译相关平台应用,开发者需自行补充相关工程文件,或者在论坛留言 + +### 2.3、开始编译 +具体方法可参考《compile_trace_streamer.md》 \ No newline at end of file diff --git a/host/figures/Scheduling.jpg b/host/figures/Scheduling.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f7c5dd57bfcb038656d0fbe80cc7e685701ae479 Binary files /dev/null and b/host/figures/Scheduling.jpg differ diff --git a/host/figures/callstackclick.jpg b/host/figures/callstackclick.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bd9ed65526a34d967a1ac45b15aa8ecf96a0d1a4 Binary files /dev/null and b/host/figures/callstackclick.jpg differ diff --git a/host/figures/callstackselect.jpg b/host/figures/callstackselect.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ccdbde9c618790875c1d1646f49504eca1f39583 Binary files /dev/null and b/host/figures/callstackselect.jpg differ diff --git a/host/figures/command.jpg b/host/figures/command.jpg new file mode 100644 index 0000000000000000000000000000000000000000..553077d0f5dcea3276b090162992f95f650cae1c Binary files /dev/null and b/host/figures/command.jpg differ diff --git a/host/figures/cpu.jpg b/host/figures/cpu.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f21a80d736774623f24a8f6a1472d5d7b4a2ad30 Binary files /dev/null and b/host/figures/cpu.jpg differ diff --git a/host/figures/cpu_frequency.png b/host/figures/cpu_frequency.png new file mode 100644 index 0000000000000000000000000000000000000000..a18715fc696b3231b94425e4acd6aaf319bf399f Binary files /dev/null and b/host/figures/cpu_frequency.png differ diff --git a/host/figures/cpubyprocess.jpg b/host/figures/cpubyprocess.jpg new file mode 100644 index 0000000000000000000000000000000000000000..180597dcbe73e1dba3ce58f348ca5b71da9077bd Binary files /dev/null and b/host/figures/cpubyprocess.jpg differ diff --git a/host/figures/cpubythread.jpg b/host/figures/cpubythread.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0ada58ba849f9b2c5dcfa83c44fdda94ab696879 Binary files /dev/null and b/host/figures/cpubythread.jpg differ diff --git a/host/figures/cpuclick.jpg b/host/figures/cpuclick.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f1a3c6d358474a1c649993cd673b66fade9871d6 Binary files /dev/null and b/host/figures/cpuclick.jpg differ diff --git a/host/figures/cpusage.jpg b/host/figures/cpusage.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0aba4c0ee62c02bc846ab17d3f2cdb244dbe66d2 Binary files /dev/null and b/host/figures/cpusage.jpg differ diff --git a/host/figures/dump_and_mem.png b/host/figures/dump_and_mem.png new file mode 100644 index 0000000000000000000000000000000000000000..b7e3cc26ca286702c9ca9869fc203aff34a8da39 Binary files /dev/null and b/host/figures/dump_and_mem.png differ diff --git a/host/figures/excutecommand.jpg b/host/figures/excutecommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..08335f77d94cb19252bb4cee92944339b8bab64c Binary files /dev/null and b/host/figures/excutecommand.jpg differ diff --git a/host/figures/filters.png b/host/figures/filters.png new file mode 100644 index 0000000000000000000000000000000000000000..a02d9416f08382ff7a03e176e37e6479f5922c08 Binary files /dev/null and b/host/figures/filters.png differ diff --git a/host/figures/fps.jpg b/host/figures/fps.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bfc18dfe881b738f6e9b100e4e32d5ab04dcb383 Binary files /dev/null and b/host/figures/fps.jpg differ diff --git a/host/figures/fpsselect.jpg b/host/figures/fpsselect.jpg new file mode 100644 index 0000000000000000000000000000000000000000..14300f78ce384f8ad0366657e3b0eed2177e7505 Binary files /dev/null and b/host/figures/fpsselect.jpg differ diff --git a/host/figures/gray.jpg b/host/figures/gray.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9bdb38037a286ea531485e6445553ea61f6d2e04 Binary files /dev/null and b/host/figures/gray.jpg differ diff --git a/host/figures/highlit.jpg b/host/figures/highlit.jpg new file mode 100644 index 0000000000000000000000000000000000000000..24278fdc9e13fa79efcac8b8355f5d94919a01a7 Binary files /dev/null and b/host/figures/highlit.jpg differ diff --git a/host/figures/htrace.jpg b/host/figures/htrace.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0c3999d31b19b03d6c2471ff80cbcd4d2e7e2177 Binary files /dev/null and b/host/figures/htrace.jpg differ diff --git a/host/figures/log.png b/host/figures/log.png new file mode 100644 index 0000000000000000000000000000000000000000..dbe3780eb647493dec252d69f23e71cf66ac15a8 Binary files /dev/null and b/host/figures/log.png differ diff --git a/host/figures/main.jpg b/host/figures/main.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5209395cb5c65c857a192b7e0ec768cd2170181e Binary files /dev/null and b/host/figures/main.jpg differ diff --git a/host/figures/mem_usage.png b/host/figures/mem_usage.png new file mode 100644 index 0000000000000000000000000000000000000000..f4ebd6e272c424d6861e2e8150c72c1f4de9802a Binary files /dev/null and b/host/figures/mem_usage.png differ diff --git a/host/figures/opentrace.jpg b/host/figures/opentrace.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c2fcf84c6dea67205d5cd5b6041dad1834631d33 Binary files /dev/null and b/host/figures/opentrace.jpg differ diff --git a/host/figures/process.jpg b/host/figures/process.jpg new file mode 100644 index 0000000000000000000000000000000000000000..62cad6b1f899e3be5abc1e17764a7aba6fca4a39 Binary files /dev/null and b/host/figures/process.jpg differ diff --git a/host/figures/process_thread.png b/host/figures/process_thread.png new file mode 100644 index 0000000000000000000000000000000000000000..abc3867130c10413197482d0156ce0ee00aca255 Binary files /dev/null and b/host/figures/process_thread.png differ diff --git a/host/figures/smartperf_framework.png b/host/figures/smartperf_framework.png new file mode 100644 index 0000000000000000000000000000000000000000..62c1bc6cd61e07ba3014141f70941e6134d75681 Binary files /dev/null and b/host/figures/smartperf_framework.png differ diff --git a/host/figures/systraceconfig.jpg b/host/figures/systraceconfig.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5436850abf26aaea585049af1908c85d1ce67178 Binary files /dev/null and b/host/figures/systraceconfig.jpg differ diff --git a/host/figures/thread_state.png b/host/figures/thread_state.png new file mode 100644 index 0000000000000000000000000000000000000000..186ffb16905c7cfa0178f7c14a0189223f6c9e22 Binary files /dev/null and b/host/figures/thread_state.png differ diff --git a/host/figures/threadclick.jpg b/host/figures/threadclick.jpg new file mode 100644 index 0000000000000000000000000000000000000000..65811e9317fd845bb5b2d3df752ffb742ad743e8 Binary files /dev/null and b/host/figures/threadclick.jpg differ diff --git a/host/figures/threadinfo.jpg b/host/figures/threadinfo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d2b6be2acf86bcc2612ff4ab1a6b820e6551b9b6 Binary files /dev/null and b/host/figures/threadinfo.jpg differ diff --git a/host/figures/threadselect.jpg b/host/figures/threadselect.jpg new file mode 100644 index 0000000000000000000000000000000000000000..38fda253bd3bab6d3388b1e19cd39d488386d2ba Binary files /dev/null and b/host/figures/threadselect.jpg differ diff --git a/host/figures/time.jpg b/host/figures/time.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a0221cb47e5874a05280a7315831fd61ec13cdd0 Binary files /dev/null and b/host/figures/time.jpg differ diff --git a/host/figures/trace.jpg b/host/figures/trace.jpg new file mode 100644 index 0000000000000000000000000000000000000000..378dba3e866095c0b1155175d09eeb615b3dbf9a Binary files /dev/null and b/host/figures/trace.jpg differ diff --git a/host/figures/trace_streamer_stream.png b/host/figures/trace_streamer_stream.png new file mode 100644 index 0000000000000000000000000000000000000000..d36687d164a32bcb07f8f8bd699f0fb0b37e63bd Binary files /dev/null and b/host/figures/trace_streamer_stream.png differ diff --git a/host/ide/LICENSE b/host/ide/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..e454a52586f29b8ce8a6799163eac1f875e9ac01 --- /dev/null +++ b/host/ide/LICENSE @@ -0,0 +1,178 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/host/ide/README_zh.md b/host/ide/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..3f583c19f127775caa1f90c8a14c477483da3835 --- /dev/null +++ b/host/ide/README_zh.md @@ -0,0 +1,93 @@ +# SmartPerf 编译指导 + + +## 1. 编译环境搭建: + 注意:在linux编译环境安装时以root或者其他 sudo 用户身份运行下面的命令 +### 1.1 node 环境安装: +##### 1.1.1 下载Node js安装包(windows推荐, linux跳过此步骤) + 从网站 下载node js安装包 https://nodejs.org/en/download/current/ +##### 1.1.2 安装nodejs. +- ubuntu 20.04 与Debian 11系统中, 直接用apt-get安装,命令如下: +``` + 先切换到 root用户下 sudo su + apt-get update + apt-get install nodejs npm +``` + +- centos 系统中 使用yum 安装,命令如下: +``` + 先切换到 root用户下 sudo su + sudo yum -y install nodejs npm +``` + +- windows系统中, 用安装包一路next即可: + + +- 安装完成后运行检查是否安装成功: +``` + node -v + npm -v +``` + 出现版本号就代表安装成功了. + +##### 1.1.3 安装tsc typeScript 编译器 + +- 直接使用npm 安装运行命令: +``` +npm install -g typescript + +备注:如果安装失败可以更换npm源,再次尝试. +验证安装完成: + tsc -v +``` +### 1.2 go 编译环境安装: +- ubuntu 环境下直接使用apt安装: +``` + apt-get install golang-go +``` +- centos 系统中 使用yum 安装,命令如下: + +``` +先切换到 root用户下 sudo su + + sudo yum -y install go +``` +- windows 系统请自行下载安装包并完成安装。 + +- 安装完成后 命令行运行验证是否安装成功: + +``` + go version +``` +## 2. 项目编译: +#### 2.1 先下载sql.js的二进制包,: + 从如下 https://github.com/sql-js/sql.js/releases/download/v1.6.2/sqljs-all.zip 获取到sql.js的二进制包. + 将压缩包解压后, 将文件放置到项目third-party 目录下. + + +#### 2.2 先编译获取trace_streamer 的二进制包: + 参照:smartperf/trace_streamer/compile_trace_streamer.md 编译出wasm 、linux、Windows版本的二进制文件 + 将获取到二进制文件放入到项目bin目录下,如果项目目录中无bin目录 先创建bin目录. + 然后将trace_streamer的二进制文件放入bin目录中. + + +#### 2.3 代码编译(依赖于上面node环境 和 go环境) + 1) 在项目目录安装项目依赖: + npm install + 2) 在项目目录下运行命令: + npm run compile + 编译成功后会有main 可执行文件生成 + +## 3. 项目部署: + 1. linux 版本部署需要给trace_stream程序赋予执行权限: + cd dist/bin 目录下,执行 chmod +x trace_streamer_* + + 直接运行 ./main 可执行程序,完成项目的部署; + + ## 4. 访问项目: + 在浏览器上打开 https://[部署机器ip地址]:9001/application/ + !!! 注意一定是https. + + 备注:如果未出现如图所示网页.而是显示 无法访问此网站 + 可以在window cmd 里执行telnet [部署机器ip地址] 9001 + 如果显示端口连接失败 可能是防火墙未对9001 端口放开即可 diff --git a/host/ide/build.js b/host/ide/build.js new file mode 100644 index 0000000000000000000000000000000000000000..6a5fbd5f22c8e3b5b2b9a13a8825742df7563583 --- /dev/null +++ b/host/ide/build.js @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const path = require('path'); +const fs = require("fs"); +const child_process = require("child_process"); +const os = require("os"); + +const compileServer = true +const outDir = "dist" + +const staticPath = [ + "/src/img", + "/server/cert", +] + +const staticFiles = [ + "/server/version.txt", + "/src/index.html", + "/src/base-ui/icon.svg" +] + +const thirdParty = [ + {srcFilePath: "/third-party/sql-wasm.wasm", distFilePath:"/trace/database/sql-wasm.wasm" }, + {srcFilePath: "/third-party/sql-wasm.js", distFilePath:"/trace/database/sql-wasm.js" }, + {srcFilePath: "/third-party/worker.sql-wasm.js", distFilePath:"/trace/database/worker.sql-wasm.js"} +] + +function cpFile(from, to) { + fs.writeFileSync(to, fs.readFileSync(from)) +} + +function main() { + // clean outDir + let outPath = path.normalize(path.join(__dirname, "/", outDir)); + if (checkDirExist(outPath)) { + removeDir(outPath) + } + // run tsc compile + let rootPath = path.join(__dirname,"/"); + child_process.execSync("tsc -p "+ rootPath) + // run cp to mv all staticFile + staticFiles.forEach(value => { + let filePath = path.join(__dirname, value) + let distFile; + if(value.startsWith("/src")) { + distFile = path.join(__dirname, outDir, value.substring(4, value.length + 1)) + } else if (value.startsWith("/server")){ + distFile = path.join(__dirname, outDir, value.substring(7, value.length + 1)) + } + cpFile(filePath, distFile); + }) + staticPath.forEach(value => { + let pa = path.join(__dirname, value) + let distPath; + if(value.startsWith("/src")) { + distPath = path.join(__dirname, outDir, value.substring(4, value.length + 1)) + } else if (value.startsWith("/server")){ + distPath = path.join(__dirname, outDir, value.substring(7, value.length + 1)) + } + copyDirectory(pa, distPath); + }) + thirdParty.forEach(value => { + let thirdFile = path.join(__dirname, value.srcFilePath) + let thirdDistFile = path.join(__dirname, outDir, value.distFilePath) + cpFile(thirdFile, thirdDistFile); + }) + let traceStreamer = path.normalize(path.join(__dirname, "/bin")); + if (checkDirExist(traceStreamer)) { + let dest = path.normalize(path.join(__dirname, outDir, "/bin")); + copyDirectory(traceStreamer, dest) + // to mv traceStream Wasm and js + cpFile(traceStreamer + "/trace_streamer_builtin.js", rootPath + outDir +"/trace/database/trace_streamer_builtin.js") + cpFile(traceStreamer + "/trace_streamer_builtin.wasm", rootPath + outDir + "/trace/database/trace_streamer_builtin.wasm") + } else { + throw new Error("traceStreamer dir is Not Exits") + } + // compile server + if (compileServer) { + let serverSrc = path.normalize(path.join(__dirname, "/server/main.go")); + if (os.type() === "Windows_NT") { + child_process.spawnSync("go", ["build", "-o", outPath, serverSrc]) + } else if (os.type() == "Darwin"){ + child_process.spawnSync("go", ["build", "-o", outPath + "/main", serverSrc]) + } else { + child_process.spawnSync("go", ["build", "-o", outPath + "/main", serverSrc]) + } + } +} + + +function copyDirectory(src, dest) { + if (checkDirExist(dest) == false) { + fs.mkdirSync(dest); + } + if (checkDirExist(src) == false) { + return false; + } + let directories = fs.readdirSync(src); + directories.forEach((value) =>{ + let filePath = path.join(src, value); + let fileSys = fs.statSync(filePath); + if (fileSys.isFile()) { + fs.copyFileSync(filePath, path.join(dest, value)); + } else if (fileSys.isDirectory()){ + copyDirectory(filePath, path.join(dest, value)); + } + }); +} + +function checkDirExist(dirPath) { + return fs.existsSync(dirPath) +} + +function removeDir(outPath) { + let files = []; + if(fs.existsSync(outPath)){ + files = fs.readdirSync(outPath); + files.forEach((file, index) => { + let curPath = outPath + "/" + file; + if(fs.statSync(curPath).isDirectory()){ + removeDir(curPath); + } else { + fs.unlinkSync(curPath); + } + }); + fs.rmdirSync(outPath); + } +} +main(); \ No newline at end of file diff --git a/host/ide/package.json b/host/ide/package.json new file mode 100644 index 0000000000000000000000000000000000000000..bc4e0ea0d5faee107ccc936dd72fc662f27c4def --- /dev/null +++ b/host/ide/package.json @@ -0,0 +1,50 @@ +{ + "name": "SmartPerf", + "version": "1.0.0", + "description": "SmartPerf", + "main": "index.js", + "scripts": { + "compile": "node ./build.js", + "test": "jest", + "test-c": "jest --coverage" + }, + "jest": { + "testEnvironment": "jsdom", + "collectCoverageFrom": [ + "/dist/**/*.js", + "!/dist/bin/*", + "!/dist/trace/database/pixi.js", + "!/dist/trace/database/sql-wasm.js", + "!/dist/trace/database/uuidv4.min.js", + "!/dist/trace/database/worker.sql-wasm.js", + "!/dist/trace/database/worker.sql-wasm-debug.js", + "!/node_modules/" + ], + "globals": { + "useWb": true + }, + "setupFiles": [ + "jsdom-worker", + "jest-canvas-mock" + ] + }, + "repository": { + "type": "git", + "url": "" + }, + "author": "", + "license": "Apache License", + "devDependencies": { + "@babel/plugin-proposal-class-properties": "^7.16.7", + "@babel/plugin-proposal-decorators": "^7.17.2", + "@babel/preset-env": "*", + "@babel/preset-typescript": "*", + "@types/jest": "*", + "@types/node": "^17.0.10", + "jest": "*", + "jest-canvas-mock": "^2.3.1", + "typescript": "^4.2.3", + "jsdom-worker": "^0.2.1" + }, + "dependencies": {} +} diff --git a/host/ide/server/go.mod b/host/ide/server/go.mod new file mode 100644 index 0000000000000000000000000000000000000000..aaa88e400a264e7ea35f528c0793e783515c8c70 --- /dev/null +++ b/host/ide/server/go.mod @@ -0,0 +1,21 @@ +// Copyright (C) 2022 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +module dist + +go 1.17 + +require ( + github.com/djimenez/iconv-go v0.0.0-20160305225143-8960e66bd3da + golang.org/x/text v0.3.7 +) \ No newline at end of file diff --git a/host/ide/server/main.go b/host/ide/server/main.go new file mode 100644 index 0000000000000000000000000000000000000000..995cffe734c904b684c312f684c1fba216080618 --- /dev/null +++ b/host/ide/server/main.go @@ -0,0 +1,350 @@ +// Copyright (C) 2022 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +//遇到报错请在当前目录下执行这个命令: go mod download golang.org/x/text +import ( + "bufio" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "math/big" + "net" + "bytes" + "fmt" + "io" + "io/ioutil" + "log" + "mime" + "net/http" + "os" + "os/exec" + "path" + "path/filepath" + "runtime" + "strings" + "time" +) + +const HttpPort = 9000 + +var exPath string + +// CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go +// CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go +func cors(fs http.Handler, version string) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + // return if you do not want the FileServer handle a specific request + r.Header.Add("Cross-Origin-Opener-Policy", "same-origin") + r.Header.Add("Cross-Origin-Embedder-Policy", "require-corp") + w.Header().Add("Cross-Origin-Opener-Policy", "same-origin") + w.Header().Add("Cross-Origin-Embedder-Policy", "require-corp") + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Credentials", "true") + w.Header().Set("Access-Control-Allow-Headers", "x-requested-with, authorization, blade-auth") //* + w.Header().Set("Access-Control-Allow-Methods", "*") //* + w.Header().Set("Access-Control-Max-Age", "3600") + w.Header().Set("data-version", version) + fs.ServeHTTP(w, r) + } +} + +func exist(path string) bool { + _, err := os.Stat(path) + if err != nil { + if os.IsExist(err) { + return true + } + return false + } + return true +} +func genSSL() { + if exist("cert/keyFile.key") || exist("cert/certFile.pem") { + fmt.Println("keyFile.key exists") + return + } + max := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, _ := rand.Int(rand.Reader, max) + subject := pkix.Name{ + Organization: []string{"www.smartperf.com"}, + OrganizationalUnit: []string{"ITs"}, + CommonName: "www.smartperf.com", + } + certificate509 := x509.Certificate{ + SerialNumber: serialNumber, + Subject: subject, + NotBefore: time.Now(), + NotAfter: time.Now().AddDate(10, 0, 0), + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, + } + chekDir("cert") + pk, _ := rsa.GenerateKey(rand.Reader, 1024) + derBytes, _ := x509.CreateCertificate(rand.Reader, &certificate509, &certificate509, &pk.PublicKey, pk) + certOut, _ := os.Create("cert/certFile.pem") + pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + certOut.Close() + keyOut, _ := os.Create("cert/keyFile.key") + pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(pk)}) + keyOut.Close() +} +func main() { + genSSL() + exPath = getCurrentAbPath() + fmt.Println(exPath) + go func() { + version := "" + readVersion, versionErr := ioutil.ReadFile(exPath + "/version.txt") + if versionErr != nil { + version = "" + } else { + version = string(readVersion) + } + mux := http.NewServeMux() + mime.TypeByExtension(".js") + mime.AddExtensionType(".js", "application/javascript") + log.Println(mime.TypeByExtension(".js")) + mux.HandleFunc("/upload", uploadHandler) + mux.Handle("/upload/", http.StripPrefix("/upload/", http.FileServer(http.Dir(exPath+"/upload")))) + fs := http.FileServer(http.Dir(exPath + "/")) + mux.Handle("/application/", http.StripPrefix("/application/", cors(fs, version))) + ser := &http.Server{ + Addr: fmt.Sprintf(":%d", HttpPort), + Handler: mux, + } + log.Println(fmt.Sprintf("HTTP[%d]服务启动", HttpPort)) + open(fmt.Sprintf("https://localhost:%d/application", HttpPort)) + err := ser.ListenAndServeTLS("cert/certFile.pem", "cert/keyFile.key") + CheckErr(err) + }() + select {} +} + +func uploadHandler(w http.ResponseWriter, r *http.Request) { + defer func() { + var err = recover() + fmt.Println(err) + }() + chekDir(exPath + "/upload") + contentType := r.Header["Content-Type"] + if len(contentType) > 0 { + contentTypeName := contentType[0] + if strings.HasPrefix(contentTypeName, "multipart/form-data") { + err := r.ParseMultipartForm(32 << 20) + CheckErr(err) + file, header, err := r.FormFile("file") + CheckErr(err) + filename := header.Filename + index := strings.LastIndex(filename, ".") + distFileName := fmt.Sprintf("%d", time.Now().Unix()) + distFileSuffix := filename[index:] + path := fmt.Sprintf("/upload/%s%s", distFileName, distFileSuffix) + dst, err := os.OpenFile(exPath+path, os.O_WRONLY|os.O_CREATE, 0666) + CheckErr(err) + defer dst.Close() + if _, err := io.Copy(dst, file); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + databaseUrl := transformDatabase(distFileName, distFileSuffix) + if databaseUrl != "" { + ohosTsPath := fmt.Sprintf("./upload/%s.ohos.ts", databaseUrl) + result, _ := PathExists(ohosTsPath) + if result { + readFile, readErr := ioutil.ReadFile(ohosTsPath) + if readErr == nil { + fmt.Println(string(readFile)) + split := SplitLines(string(readFile)) + fmt.Println(split) + if len(split) > 1 { + if strings.HasSuffix(split[0], ":0") { + fmt.Fprintf(w, fmt.Sprintf("/upload/%s", databaseUrl)) + return + } + } + } + } + } + http.Error(w, "文件生成失败", http.StatusNotFound) + return + } + } +} +func SplitLines(s string) []string { + var lines []string + sc := bufio.NewScanner(strings.NewReader(s)) + for sc.Scan() { + lines = append(lines, sc.Text()) + } + return lines +} + +func readFileFirstLine(path string) string { + file, err := os.Open(path) + if err != nil { + return "" + } + defer file.Close() + + readFile := bufio.NewReader(file) + line, readErr := readFile.ReadString('\n') + if readErr != nil || io.EOF == err { + return "" + } + return line +} + +func PathExists(path string) (bool, error) { + _, err := os.Stat(path) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} + +func chekDir(path string) { + _, err := os.Stat(path) + if err != nil { + err := os.Mkdir(path, os.ModePerm) + if err != nil { + fmt.Printf("mkdir failed![%v]\n", err) + } else { + fmt.Printf("mkdir success!\n") + } + } +} +func CheckErr(err error) { + if err != nil { + log.Panicln(err) + } +} + +func open(url string) error { + if isWindows() { + return openUrlWindows(url) + } else if isDarwin() { + return openUrlDarwin(url) + } else { + return openUrlOther(url) + } +} + +func openUrlWindows(url string) error { + cmd := "cmd" + args := []string{"/c", "start", url} + return exec.Command(cmd, args...).Start() +} +func openUrlDarwin(url string) error { + var cmd = "open" + var args = []string{url} + return exec.Command(cmd, args...).Start() +} +func openUrlOther(url string) error { + var cmd = "xdg-open" + var args = []string{url} + return exec.Command(cmd, args...).Start() +} + +func isWindows() bool { + return runtime.GOOS == "windows" +} +func isDarwin() bool { + return runtime.GOOS == "darwin" +} + +func transformDatabase(name string, suffix string) string { + if isWindows() { + cmd := exec.Command( + "cmd", + "/c", + `.\bin\trace_streamer_windows.exe`, + fmt.Sprintf(`.\upload\%s%s`, name, suffix), + "-e", + fmt.Sprintf(`.\upload\%s.db`, name), + ) + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout // 标准输出 + cmd.Stderr = &stderr // 标准错误 + err := cmd.Run() + if err != nil { + return "" + } + return fmt.Sprintf("%s.db", name) + } else if isDarwin() { + cmd := exec.Command( + "/bin/bash", + "-c", + fmt.Sprintf("%s/bin/trace_streamer_mac %s/upload/%s%s -e %s/upload/%s.db", exPath, exPath, name, suffix, exPath, name), + ) + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout // 标准输出 + cmd.Stderr = &stderr // 标准错误 + err := cmd.Run() + outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes()) + fmt.Printf("out:\n%s\n :\n%s\n", outStr, errStr) + if err != nil { + return "" + } + return fmt.Sprintf("%s.db", name) + } else { + cmd := exec.Command( + "/bin/bash", + "-c", + fmt.Sprintf("%s/bin/trace_streamer_linux %s/upload/%s%s -e %s/upload/%s.db", exPath, exPath, name, suffix, exPath, name), + ) + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout // 标准输出 + cmd.Stderr = &stderr // 标准错误 + err := cmd.Run() + outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes()) + fmt.Printf("out:\n%s\n :\n%s\n", outStr, errStr) + if err != nil { + return "" + } + return fmt.Sprintf("%s.db", name) + } + return "" +} +func getCurrentAbPath() string { + dir := getCurrentAbPathByExecutable() + tmpDir, _ := filepath.EvalSymlinks(os.TempDir()) + if strings.Contains(dir, tmpDir) { + return getCurrentAbPathByCaller() + } + return dir +} + +func getCurrentAbPathByCaller() string { + var abPath string + _, filename, _, ok := runtime.Caller(0) + if ok { + abPath = path.Dir(filename) + } + return abPath +} +func getCurrentAbPathByExecutable() string { + exePath, err := os.Executable() + if err != nil { + log.Fatal(err) + } + res, _ := filepath.EvalSymlinks(filepath.Dir(exePath)) + return res +} diff --git a/host/ide/server/version.txt b/host/ide/server/version.txt new file mode 100644 index 0000000000000000000000000000000000000000..13eb9fd76e77a11fbeea787631d5e10c91685e24 --- /dev/null +++ b/host/ide/server/version.txt @@ -0,0 +1 @@ +v1.0.001 \ No newline at end of file diff --git a/host/ide/src/base-ui/BaseElement.ts b/host/ide/src/base-ui/BaseElement.ts new file mode 100644 index 0000000000000000000000000000000000000000..a566c9a99f69ede3dda3aa7ec0fa46cdaa187e46 --- /dev/null +++ b/host/ide/src/base-ui/BaseElement.ts @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +export function element(tag: string) { + return (el: any) => { + if (!customElements.get(tag)) { + customElements.define(tag, el); + } + } +} + +export abstract class BaseElement extends HTMLElement { + args: any; + + public constructor(args: any | undefined | null = null) { + super(); + this.args = args; + this.attachShadow({mode: 'open'}).innerHTML = this.initHtml(); + this.initElements(); + } + + abstract initElements(): void; + + abstract initHtml(): string; + + public connectedCallback() { + } + + public disconnectedCallback() { + } + + public adoptedCallback() { + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + } +} diff --git a/host/ide/src/base-ui/button/LitButton.ts b/host/ide/src/base-ui/button/LitButton.ts new file mode 100644 index 0000000000000000000000000000000000000000..516e1b8034f2ecce311aeceb23a526c8b3ed9063 --- /dev/null +++ b/host/ide/src/base-ui/button/LitButton.ts @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement} from "../BaseElement.js"; + +export class LitButton extends BaseElement { + initHtml(): string { + return ""; + } + + initElements(): void { + + } +} \ No newline at end of file diff --git a/host/ide/src/base-ui/checkbox/LitCheckBox.ts b/host/ide/src/base-ui/checkbox/LitCheckBox.ts new file mode 100644 index 0000000000000000000000000000000000000000..a6b5d913591c14e0eb6c81af6f883627c437833f --- /dev/null +++ b/host/ide/src/base-ui/checkbox/LitCheckBox.ts @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../BaseElement.js"; + +@element('lit-check-box') +export class LitCheckBox extends BaseElement { + + private checkbox: HTMLInputElement | undefined + + static get observedAttributes() { + return ['checked', 'value'] + } + + get indeterminate() { + return this.checkbox!.indeterminate; + } + + set indeterminate(value) { + if (value === null || value === false) { + this.checkbox!.indeterminate = false; + } else { + this.checkbox!.indeterminate = true; + } + } + + get checked() { + return this.getAttribute('checked') !== null; + } + + set checked(value: boolean) { + if (value === null || !value) { + this.removeAttribute('checked'); + } else { + this.setAttribute('checked', ''); + } + } + + get value() { + return this.getAttribute('value') || ''; + } + + set value(value: string) { + this.setAttribute('value', value); + } + + initHtml(): string { + return ` + + + + `; + } + + initElements(): void { + this.checkbox = this.shadowRoot?.getElementById('checkbox') as HTMLInputElement; + } + + connectedCallback() { + this.checkbox!.addEventListener('change', (ev) => { + this.checked = this.checkbox!.checked; + this.dispatchEvent(new CustomEvent("change", { + detail: { + "checked": this.checked + } + })) + }) + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + if (name == 'checked' && this.checkbox) { + this.checkbox.checked = newValue !== null; + } + if (name == 'value') { + let slot = this.shadowRoot?.getElementById("slot") + slot!.textContent = newValue + } + } +} diff --git a/host/ide/src/base-ui/checkbox/LitCheckBoxWithText.ts b/host/ide/src/base-ui/checkbox/LitCheckBoxWithText.ts new file mode 100644 index 0000000000000000000000000000000000000000..2de00a3fe8b08a16bca6f42e2e9f9c2a6869466d --- /dev/null +++ b/host/ide/src/base-ui/checkbox/LitCheckBoxWithText.ts @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../BaseElement.js"; +import {SpCheckDesBox} from "../../trace/component/setting/SpCheckDesBox.js"; + +@element('lit-check-text') +export class LitCheckBoxWithText extends BaseElement { + private _checkBox: SpCheckDesBox | undefined; + private _lowerLimit: HTMLInputElement | undefined; + private _upLimit: HTMLInputElement | undefined; + + static get observedAttributes() { + return ['text', 'lowerLimit', 'upLimit', 'checked'] + } + + get text(): string { + return this.getAttribute("text") || "" + } + + set text(text: string) { + this.setAttribute("text", text) + } + + get lowerLimit(): string { + return this.getAttribute("lowerLimit") || "0" + } + + set lowerLimit(lower: string) { + this.setAttribute("lowerLimit", lower) + } + + get upLimit(): string { + return this.getAttribute("upLimit") || "∞" + } + + set upLimit(upLimit: string) { + this.setAttribute("upLimit", upLimit) + } + + get checked() { + return this.getAttribute("checked") != null; + } + + set checked(checked: boolean) { + if (checked) { + this.setAttribute('checked', ''); + } else { + this.removeAttribute('checked'); + } + } + + initElements(): void { + this._checkBox = this.shadowRoot?.getElementById('checkbox') as SpCheckDesBox; + this._lowerLimit = this.shadowRoot?.getElementById('textLowerLimit') as HTMLInputElement; + this._upLimit = this.shadowRoot?.getElementById('_upLimit') as HTMLInputElement; + } + + initHtml(): string { + return ` + + + + `; + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + if (name == 'checked') { + this._checkBox!.checked = newValue !== null; + } + if (name == 'text') { + this._checkBox?.setAttribute('value', newValue); + } + if (name == 'lowerLimit') { + this._lowerLimit!.textContent = newValue + } + if (name == 'upLimit') { + this._upLimit!.textContent = newValue + } + } + +} \ No newline at end of file diff --git a/host/ide/src/base-ui/checkbox/LitCheckGroup.ts b/host/ide/src/base-ui/checkbox/LitCheckGroup.ts new file mode 100644 index 0000000000000000000000000000000000000000..ec9f31ec206a486b0480ecc18288e62597f1556f --- /dev/null +++ b/host/ide/src/base-ui/checkbox/LitCheckGroup.ts @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../BaseElement.js"; +import {LitCheckBox} from "./LitCheckBox.js"; + +@element('lit-check-group') +export class LitCheckGroup extends BaseElement { + + get direction() { + return this.getAttribute("direction") + } + + get value(): Array { + let values = [] + for (const litCheckBoxElement of this.querySelectorAll('lit-check-box[checked]')) { + values.push(litCheckBoxElement.value) + } + return values; + } + + initElements(): void { + } + + initHtml(): string { + return ` + + `; + } +} \ No newline at end of file diff --git a/host/ide/src/base-ui/icon.svg b/host/ide/src/base-ui/icon.svg new file mode 100644 index 0000000000000000000000000000000000000000..168c113b584dbbbfb6a69687e65adf634768dd8b --- /dev/null +++ b/host/ide/src/base-ui/icon.svg @@ -0,0 +1 @@ + diff --git a/host/ide/src/base-ui/icon/LitIcon.ts b/host/ide/src/base-ui/icon/LitIcon.ts new file mode 100644 index 0000000000000000000000000000000000000000..6fa3d039fdfcbce09fa2716cb139ba58111f65d7 --- /dev/null +++ b/host/ide/src/base-ui/icon/LitIcon.ts @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import {BaseElement, element} from "../BaseElement.js"; + +@element('lit-icon') +export class LitIcon extends BaseElement { + private view?: number + private icon: HTMLElement | undefined | null + private use: SVGUseElement | undefined | null + private d: SVGPathElement | undefined | null + private _name?: string + private _size?: number + private _color?: string + private _path?: string + + static get observedAttributes() { + return ["name", "size", "color", "path"] + } + + get name(): string { + return this.getAttribute("name") || ""; + } + + set name(value: string) { + this._name = value; + this.setAttribute("name", value) + } + + get size(): number { + return parseInt(this.getAttribute("size") || '0', 10) + } + + set size(value: number) { + this._size = value; + this.setAttribute("size", `${value}`) + } + + set color(value: string) { + this._color = value; + this.setAttribute('color', value) + } + + set path(value: string) { + this._path = value + this.setAttribute('path', value); + } + + initHtml(): string { + return ` + + + `; + } + + initElements() { + if (this.shadowRoot) { + this.icon = this.shadowRoot.getElementById("icon"); + this.use = this.shadowRoot.querySelector("use"); + this.d = this.shadowRoot.querySelector("path"); + } + } + + attributeChangedCallback(name: string, oldValue: string, value: string) { + switch (name) { + case "name": + if (this.use) this.use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', `./base-ui/icon.svg#icon-${value}`); + break; + case "path": + if (this.d) this.d.setAttribute("d", value); + break; + case "color": + if (this.icon) this.icon.style.color = value as string; + break; + case "size": + if (this.icon) this.icon.style.fontSize = `${value}px`; + break; + } + } +} + diff --git a/host/ide/src/base-ui/menu/LitMainMenu.ts b/host/ide/src/base-ui/menu/LitMainMenu.ts new file mode 100644 index 0000000000000000000000000000000000000000..008f584689ad7b12aae69de085f20124a0cb50c4 --- /dev/null +++ b/host/ide/src/base-ui/menu/LitMainMenu.ts @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import {BaseElement, element} from "../BaseElement.js"; +import './LitMainMenuItem.js' +import './LitMainMenuGroup.js' +import {LitMainMenuGroup} from "./LitMainMenuGroup.js"; +import {LitMainMenuItem} from "./LitMainMenuItem.js"; + +@element('lit-main-menu') +export class LitMainMenu extends BaseElement { + private slotElements: Element[] | undefined; + private _menus: Array | undefined + + static get observedAttributes() { + return [] + } + + get menus(): Array | undefined { + return this._menus; + } + + set menus(value: Array | undefined) { + this._menus = value; + this.shadowRoot?.querySelectorAll('lit-main-menu-group').forEach(a => a.remove()); + let menuBody = this.shadowRoot?.querySelector('.menu-body'); + value?.forEach(it => { + let group = new LitMainMenuGroup(); + group.setAttribute('title', it.title || ""); + group.setAttribute('describe', it.describe || ""); + if (it.collapsed) { + group.setAttribute('collapsed', ''); + } else { + group.removeAttribute('collapsed'); + } + menuBody?.appendChild(group); + it.children?.forEach((item: any) => { + let th = new LitMainMenuItem(); + th.setAttribute('icon', item.icon || ""); + th.setAttribute('title', item.title || ""); + if (item.fileChoose) { + th.setAttribute('file', ""); + th.addEventListener('file-change', e => { + if (item.fileHandler) { + item.fileHandler(e) + } + }) + } else { + th.removeAttribute('file'); + th.addEventListener('click', e => { + if (item.clickHandler) { + item.clickHandler(item) + } + }) + } + if (item.disabled != undefined) { + th.disabled = item.disabled + } + group?.appendChild(th); + }) + }) + } + + initElements(): void { + let st: HTMLSlotElement | null | undefined = this.shadowRoot?.querySelector('#st'); + st?.addEventListener('slotchange', e => { + this.slotElements = st?.assignedElements(); + this.slotElements?.forEach(it => { + it.querySelectorAll("lit-main-menu-item").forEach(cell => { + }) + }) + }) + let versionDiv: HTMLElement | null | undefined = this.shadowRoot?.querySelector('.version'); + versionDiv!.innerText = (window as any).version || "" + } + + initHtml(): string { + return ` + +
+ + +
+ +
+ `; + } +} + +export interface MenuGroup { + title: string + describe: string + collapsed: boolean + children: Array +} + +export interface MenuItem { + icon: string + title: string + fileChoose?: boolean + clickHandler?: Function + fileHandler?: Function +} diff --git a/host/ide/src/base-ui/menu/LitMainMenuGroup.ts b/host/ide/src/base-ui/menu/LitMainMenuGroup.ts new file mode 100644 index 0000000000000000000000000000000000000000..57c51e0df99bc3d54391624e50b33b29ab24e776 --- /dev/null +++ b/host/ide/src/base-ui/menu/LitMainMenuGroup.ts @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import {BaseElement, element} from "../BaseElement.js"; + +@element('lit-main-menu-group') +export class LitMainMenuGroup extends BaseElement { + protected _collapsed: boolean | undefined; + private groupNameEl: HTMLElement | null | undefined; + private groupDescEl: HTMLElement | null | undefined; + + static get observedAttributes() { + return ['title', 'describe', 'collapsed', 'nocollapse', "radius"] + } + + get collapsed(): boolean { + return this.hasAttribute('collapsed') + } + + set collapsed(value: boolean) { + if (value) { + this.setAttribute('collapsed', '') + } else { + this.removeAttribute('collapsed') + } + } + + get nocollapsed() { + return this.hasAttribute('nocollapsed') + } + + set nocollapsed(value: boolean) { + if (value) { + this.setAttribute('nocollapsed', '') + } else { + this.removeAttribute('nocollapsed') + } + } + + get radius() { + return this.hasAttribute("radius") + } + + initElements(): void { + this.groupNameEl = this.shadowRoot?.querySelector('.group-name'); + this.groupDescEl = this.shadowRoot?.querySelector('.group-describe'); + this.addEventListener('click', (e) => { + if (this.nocollapsed) { + return; + } + this.collapsed = !this.collapsed + }) + } + + initHtml(): string { + return ` + +
+
+ + `; + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + switch (name) { + case "title": + if (this.groupNameEl) this.groupNameEl.textContent = newValue + break; + case "describe": + if (this.groupDescEl) this.groupDescEl.textContent = newValue + break; + } + } +} diff --git a/host/ide/src/base-ui/menu/LitMainMenuItem.ts b/host/ide/src/base-ui/menu/LitMainMenuItem.ts new file mode 100644 index 0000000000000000000000000000000000000000..4af57f10fed85138d48e26c44f29077500c01a80 --- /dev/null +++ b/host/ide/src/base-ui/menu/LitMainMenuItem.ts @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import {BaseElement, element} from "../BaseElement.js"; + +@element('lit-main-menu-item') +export class LitMainMenuItem extends BaseElement { + private titleEl: HTMLElement | null | undefined; + private rootEL: HTMLElement | null | undefined; + private iconEl: HTMLElement | null | undefined; + private fileEL: HTMLInputElement | undefined | null; + + static get observedAttributes() { + return ['title', 'icon', 'file', 'disabled'] + } + + get title(): string { + return this.getAttribute("title") || "" + } + + set title(val: string) { + this.setAttribute("title", val); + } + + get disabled(): boolean { + return this.hasAttribute("disabled") + } + + set disabled(val: boolean) { + if (val) { + this.setAttribute("disabled", val.toString()); + this.fileEL?.setAttribute("disabled", val.toString()); + } else { + this.removeAttribute("disabled"); + this.fileEL?.removeAttribute("disabled"); + } + } + + initElements(): void { + this.rootEL = this.shadowRoot?.querySelector('.root'); + this.titleEl = this.shadowRoot?.querySelector('.name'); + this.iconEl = this.shadowRoot?.querySelector('.icon'); + this.fileEL = this.shadowRoot?.querySelector('.file'); + } + + isFile(): boolean { + if (this.hasAttribute("file")) { + if (this.fileEL) { + return true + } + } + return false + } + + connectedCallback() { + if (this.hasAttribute("file")) { + if (this.fileEL) { + this.fileEL.addEventListener('change', () => { + let files = this.fileEL!.files; + if (files && files.length > 0) { + // @ts-ignore + this.dispatchEvent(new CustomEvent('file-change', {target: this, detail: files[0]})) + if (this.fileEL) this.fileEL.value = '' + } + }); + } + } + this.addEventListener('click', e => { + e.stopPropagation(); + }) + } + + initHtml(): string { + return ` + + + +`; + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + switch (name) { + case "title": + if (this.titleEl) this.titleEl.textContent = newValue; + break; + case "icon": + if (this.iconEl) this.iconEl.setAttribute("name", newValue) + break; + } + } +} diff --git a/host/ide/src/base-ui/popover/LitPopContent.ts b/host/ide/src/base-ui/popover/LitPopContent.ts new file mode 100644 index 0000000000000000000000000000000000000000..2515862ee7267db93771ab4e69f5901f1cbe5ba9 --- /dev/null +++ b/host/ide/src/base-ui/popover/LitPopContent.ts @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../BaseElement.js"; + +@element("lit-pop-content") +export class LitPopContent extends BaseElement { + static get observedAttributes() { + return ["open"] + } + + get open() { + return this.hasAttribute('open'); + } + + set open(value: boolean) { + if (value === null || !value) { + this.removeAttribute('open'); + let parentElement = this.parentNode as Element; + parentElement?.removeAttribute('open'); + } else { + this.setAttribute('open', ''); + let parentElement = this.parentNode as Element; + parentElement?.setAttribute('open', ''); + } + } + + initElements(): void { + } + + initHtml(): string { + return ` + +
+ +
+ `; + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + switch (name) { + case "open": + if (newValue === null || newValue === "false") { + let parentElement = this.parentNode as Element; + parentElement?.removeAttribute('open'); + } else { + let parentElement = this.parentNode as Element; + parentElement?.setAttribute('open', ''); + } + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/host/ide/src/base-ui/popover/LitPopover.ts b/host/ide/src/base-ui/popover/LitPopover.ts new file mode 100644 index 0000000000000000000000000000000000000000..1087d9efdb581f2e55d5602f6f99dafb1df28d86 --- /dev/null +++ b/host/ide/src/base-ui/popover/LitPopover.ts @@ -0,0 +1,458 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../BaseElement.js"; +import {LitPopContent} from "./LitPopContent.js"; +import {LitPopoverTitle} from "./LitPopoverTitle.js"; +import {LitRadioGroup} from "../radiobox/LitRadioGroup.js"; +import {LitRadioBox} from "../radiobox/LitRadioBox.js"; +import {LitCheckBox} from "../checkbox/LitCheckBox.js"; +import {LitCheckGroup} from "../checkbox/LitCheckGroup.js"; +import {LitCheckBoxWithText} from "../checkbox/LitCheckBoxWithText.js"; + +@element("lit-popover") +export class LitPopover extends BaseElement { + private popContent: LitPopContent | null | undefined; + private litGroup: LitRadioGroup | LitCheckGroup | undefined + private _texBox: LitCheckBoxWithText | undefined + + static get observedAttributes() { + return [] + } + + get type() { + return this.getAttribute("type") || '' + } + + set type(type: string) { + this.setAttribute("type", type) + } + + get title() { + return this.getAttribute("title") || '' + } + + set title(title: string) { + this.setAttribute("title", title) + } + + get limit(): LimitText { + if (this._texBox?.checked) { + return {textLowerLimit: this._texBox.lowerLimit, textUpperLimit: this._texBox.upLimit} + } + return {textLowerLimit: "", textUpperLimit: ""} + } + + set dataSource(dataSource: Array) { + this.popContent = this.querySelector('lit-pop-content'); + if (!this.popContent) { + this.popContent = new LitPopContent(); + this.appendChild(this.popContent); + } + switch (this.type) { + case "multiple": + this.litGroup = new LitCheckGroup(); + this.litGroup.setAttribute("layout", "dispersion") + this.popContent!.appendChild(this.litGroup); + dataSource.forEach(data => { + let litCheckBox = new LitCheckBox(); + this.litGroup?.appendChild(litCheckBox) + if (data.isSelected) { + litCheckBox.setAttribute('checked', "true") + } + litCheckBox.setAttribute("value", data.text) + }) + break; + case "radio": + this.litGroup = new LitRadioGroup(); + if (this.title !== '') { + let title = new LitPopoverTitle(); + title.setAttribute('title', this.title || ""); + this.popContent!.appendChild(title); + this.litGroup.setAttribute("layout", "compact") + } else { + this.litGroup.setAttribute("layout", "dispersion") + } + this.popContent!.appendChild(this.litGroup); + dataSource.forEach(data => { + let litRadioBox = new LitRadioBox(); + if (this.title == '') { + litRadioBox.setAttribute('dis', 'round') + } else { + litRadioBox.setAttribute('dis', 'check') + } + if (data.isSelected) { + litRadioBox.setAttribute('checked', "true") + } + this.litGroup?.appendChild(litRadioBox) + litRadioBox.setAttribute("value", data.text) + }) + break; + case "multiple-text": + dataSource.forEach(data => { + this._texBox = new LitCheckBoxWithText(); + this._texBox.setAttribute("text", data.text) + this._texBox.setAttribute("checked", "") + this.popContent!.appendChild(this._texBox); + }) + break; + case "data-ming": + break; + } + } + + get select(): Array | undefined { + if (this._texBox?.checked) { + return [this._texBox!.text] + } + return this.litGroup?.value; + } + + get trigger() { + return this.getAttribute('trigger'); + } + + get direction() { + return this.getAttribute('direction') || 'topright' + } + + set direction(value: string) { + this.setAttribute('direction', value); + } + + get open() { + return this.getAttribute('open') !== null; + } + + set open(value: boolean) { + if (value === null || value === false) { + this.removeAttribute('open'); + } else { + this.setAttribute('open', ''); + } + } + + initElements(): void { + } + + initHtml(): string { + return ` + + + `; + } + + connectedCallback() { + if (!(this.trigger && this.trigger !== 'click')) { + this.addEventListener('click', () => { + this.popContent = this.querySelector('lit-pop-content'); + if (!this.popContent) { + this.popContent = new LitPopContent(); + this.appendChild(this.popContent); + } + this.popContent?.setAttribute("open", 'true') + }); + } + document.addEventListener('mousedown', ev => { + const path = ev.composedPath && ev.composedPath(); + if (this.popContent && !path.includes(this.popContent) && !path.includes(this.children[0]) && !path.includes(this.popContent)) { + this.popContent!.open = false; + } + }); + } +} + +export interface SelectBean { + text: string; + isSelected: boolean; + limitText?: LimitText; +} + +export interface LimitText { + textUpperLimit: string; + textLowerLimit: string; +} + +export interface Charge { + text: string; + isSelected: boolean; +} diff --git a/host/ide/src/base-ui/popover/LitPopoverTitle.ts b/host/ide/src/base-ui/popover/LitPopoverTitle.ts new file mode 100644 index 0000000000000000000000000000000000000000..2761ec9239835ddcce019125e6c037413eafa28f --- /dev/null +++ b/host/ide/src/base-ui/popover/LitPopoverTitle.ts @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../BaseElement.js"; + +@element("lit-popover-title") +export class LitPopoverTitle extends BaseElement { + private titleText: HTMLElement | null | undefined; + + static get observedAttributes() { + return ['title'] + } + + initElements(): void { + this.titleText = this.shadowRoot?.querySelector('.pop-title'); + } + + initHtml(): string { + return ` + +
+ `; + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + switch (name) { + case "title": + if (this.titleText) this.titleText.textContent = newValue + break; + default: + break; + } + } + +} \ No newline at end of file diff --git a/host/ide/src/base-ui/popover/LitPopoverV.ts b/host/ide/src/base-ui/popover/LitPopoverV.ts new file mode 100644 index 0000000000000000000000000000000000000000..6fd0a0861715a7990ef0b08586dd0fc67a4dfb0a --- /dev/null +++ b/host/ide/src/base-ui/popover/LitPopoverV.ts @@ -0,0 +1,494 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {element,BaseElement} from "../BaseElement.js"; + +@element("lit-popover") +export class LitPopover extends BaseElement { + static get observedAttributes() { + return [ + 'title',/*标题*/ + 'trigger',/*触发条件 hover | click | focus[未实现]*/ + 'width',/*自定义高度*/ + 'placement',/*设置方向 topLeft top topRight leftTop left leftBottom rightTop right rightBottom bottomLeft bottom bottomRight*/ + 'visible'/*控制popover是否显示*/ + ] + } + initElements(): void { + + } + get visible(){ + return this.getAttribute('visible') || 'false'; + } + set visible(value){ + if (value) { + this.setAttribute('visible', 'true'); + }else{ + this.setAttribute('visible', 'false'); + } + } + get trigger() { + return this.getAttribute('trigger') || 'hover' + } + + set trigger(value) { + this.setAttribute('trigger', value); + } + + get title() { + return this.getAttribute('title'); + } + + set title(value:any) { + this.setAttribute('title', value); + } + + get width() { + return this.getAttribute('width') || 'max-content'; + } + + set width(value) { + this.setAttribute('width', value); + } + + get haveRadio(){ + return this.getAttribute("haveRadio") + } + + initHtml() { + // super(); + // const shadowRoot = this.attachShadow({mode: 'open'}); + return ` + + +
+
${this.title}
+
+
+ + ` + } + + //当 custom element首次被插入文档DOM时,被调用。 + connectedCallback() { + let popover:any = this.shadowRoot!.querySelector('.popover'); + let checkbox:any = this.shadowRoot!.querySelector('.trigger-click'); + this.setAttribute('tabindex', '1'); + popover.onclick = (e:any) => { + e.stopPropagation(); + } + popover.addEventListener('mousemove',(e:any)=>{ + e.stopPropagation(); + }) + this.onclick = (e) => { + e.stopPropagation(); + // e.preventDefault() + this.focus(); + checkbox.checked = !checkbox.checked; + } + this.onblur = (ev:any) => { + if (ev.relatedTarget&&this.haveRadio) { + if (ev.relatedTarget.type === "radio") { + this.focus(); + }else { + checkbox.checked = false; + } + }else { + checkbox.checked = false; + } + } + } + + //当 custom element从文档DOM中删除时,被调用。 + disconnectedCallback() { + + } + + //当 custom element被移动到新的文档时,被调用。 + adoptedCallback() { + } + + //当 custom element增加、删除、修改自身属性时,被调用。 + attributeChangedCallback(name:any, oldValue:any, newValue:any) { + if(name==='visible'){ + if(newValue==='false'){ + // @ts-ignore + this.shadowRoot!.querySelector('.trigger-click')!.checked=false; + }else{ + // @ts-ignore + this.shadowRoot!.querySelector('.trigger-click')!.checked=true; + } + } + } +} diff --git a/host/ide/src/base-ui/progress-bar/LitProgressBar.ts b/host/ide/src/base-ui/progress-bar/LitProgressBar.ts new file mode 100644 index 0000000000000000000000000000000000000000..befbb3f65dda0ce8f48b93b4d1cb48fb541d26a5 --- /dev/null +++ b/host/ide/src/base-ui/progress-bar/LitProgressBar.ts @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import {BaseElement, element} from "../BaseElement.js"; + +@element("lit-progress-bar") +export class LitProgressBar extends BaseElement { + static get observedAttributes() { + return ['loading'] + } + + get loading(): boolean { + return this.hasAttribute("loading"); + } + + set loading(value: boolean) { + if (value) { + this.setAttribute('loading', ''); + } else { + this.removeAttribute('loading'); + } + } + + initElements(): void { + } + + initHtml(): string { + return ` + +
+
+
+
+ `; + } + +} \ No newline at end of file diff --git a/host/ide/src/base-ui/radiobox/LitRadioBox.ts b/host/ide/src/base-ui/radiobox/LitRadioBox.ts new file mode 100644 index 0000000000000000000000000000000000000000..daef13552c3b351a2f4861bab54a3a97e8c6fc81 --- /dev/null +++ b/host/ide/src/base-ui/radiobox/LitRadioBox.ts @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../BaseElement.js"; +import {LitRadioGroup} from "./LitRadioGroup.js"; + +@element('lit-radio') +export class LitRadioBox extends BaseElement { + + private group: LitRadioGroup | undefined | null + private parent: LitRadioGroup | undefined | null + private radio: HTMLInputElement | undefined | null + + static get observedAttributes() { + return ['checked', 'value'] + } + + get checked() { + return this.getAttribute('checked') !== null; + } + + set checked(value: boolean) { + if (value === null || !value) { + this.removeAttribute('checked'); + } else { + this.setAttribute('checked', ''); + } + } + + get name() { + return this.getAttribute('name'); + } + + get value() { + let slot = this.shadowRoot?.getElementById("slot") + return slot!.textContent || this.textContent || ""; + } + + set value(value: string) { + this.setAttribute('value', value); + } + + set dis(dis: string) { + this.setAttribute('dis', dis) + } + + initHtml(): string { + return ` + + + + `; + } + + initElements(): void { + this.radio = this.shadowRoot?.getElementById('radio') as HTMLInputElement; + } + + connectedCallback() { + this.group = this.closest('lit-radio-group') as LitRadioGroup; + this.parent = this.group || this.getRootNode(); + this.radio = this.shadowRoot?.getElementById('radio') as HTMLInputElement; + this.checked = this.checked; + this.radio.addEventListener('change', () => { + const selector = this.group ? `lit-radio[checked]` : `lit-radio[name="${this.name}"][checked]`; + const siblingNode = this.parent?.querySelector(selector) as LitRadioBox; + if (siblingNode) { + siblingNode.checked = false; + } + this.checked = true; + }) + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + if (name == 'checked' && this.radio) { + this.radio.checked = newValue !== null; + } + if (name == 'value') { + let slot = this.shadowRoot?.getElementById("slot") + slot!.textContent = newValue + } + } +} diff --git a/host/ide/src/base-ui/radiobox/LitRadioGroup.ts b/host/ide/src/base-ui/radiobox/LitRadioGroup.ts new file mode 100644 index 0000000000000000000000000000000000000000..1c4d284b2de76b5538b7f7c23a579fbb561db885 --- /dev/null +++ b/host/ide/src/base-ui/radiobox/LitRadioGroup.ts @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../BaseElement.js"; +import {LitRadioBox} from "./LitRadioBox.js"; + +@element("lit-radio-group") +export class LitRadioGroup extends BaseElement { + static get observedAttributes() { + return ["direction"] + } + + set layout(vale: string) { + this.setAttribute("layout", vale) + } + + get direction() { + return this.getAttribute("direction") + } + + get value(): Array { + const radio = this.querySelector('lit-radio[checked]') as LitRadioBox; + return radio ? [radio.value] : []; + } + + initElements(): void { + } + + //方向 + initHtml(): string { + return ` + + `; + } +} \ No newline at end of file diff --git a/host/ide/src/base-ui/select/LitSelect.ts b/host/ide/src/base-ui/select/LitSelect.ts new file mode 100644 index 0000000000000000000000000000000000000000..460cac9db3c0d3e23a1ea94f2cb96908c9442123 --- /dev/null +++ b/host/ide/src/base-ui/select/LitSelect.ts @@ -0,0 +1,602 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../BaseElement.js"; + +@element('lit-select') +export class LitSelect extends BaseElement { + private focused:any; + private inputElement:any; + private clearElement:any; + private iconElement:any; + private searchElement:any; + private multipleRootElement:any; + static get observedAttributes() { + return [ + 'value',//默认值 + 'default-value',//默认值 + 'placeholder',//placeholder + 'disabled', + 'loading',//是否处于加载状态 + 'allow-clear',//是否允许清除 + 'show-search',//是否允许搜索 + 'list-height',//设置弹窗滚动高度 默认256px + 'border',//是否显示边框 + 'mode',// mode='multiple'多选 + ]; + } + initElements(): void { + + } + + get value() { + return this.getAttribute('value') || this.defaultValue; + } + + set value(value) { + this.setAttribute('value', value); + } + + get border() { + return this.getAttribute('border') || 'true'; + } + + set border(value) { + if (value) { + this.setAttribute('border', 'true'); + } else { + this.setAttribute('border', 'false'); + } + } + + get listHeight() { + return this.getAttribute('list-height') || '256px'; + } + + set listHeight(value) { + this.setAttribute('list-height', value); + } + + get defaultPlaceholder() { + return this.getAttribute('placeholder') || '请选择'; + } + + get showSearch() { + return this.hasAttribute('show-search'); + } + + set defaultValue(value) { + this.setAttribute('default-value', value); + } + + get defaultValue() { + return this.getAttribute('default-value') || ''; + } + + set placeholder(value) { + this.setAttribute('placeholder', value); + } + + get placeholder() { + return this.getAttribute('placeholder') || this.defaultPlaceholder; + } + + get loading() { + return this.hasAttribute('loading'); + } + + set loading(value) { + if (value) { + this.setAttribute('loading', ''); + } else { + this.removeAttribute('loading') + } + } + + initHtml() { + // super(); + // const shadowRoot = this.attachShadow({mode: 'open'}); + return` + +
+
+ + + + +
+
+ + +
+ ` + } + + isMultiple() { + return this.hasAttribute('mode') && this.getAttribute('mode') === 'multiple' + } + + newTag(value:any, text:any) { + let tag:any = document.createElement('div'); + let icon:any = document.createElement('lit-icon'); + icon.classList.add('tag-close') + icon.name = 'close' + let span = document.createElement('span'); + tag.classList.add('tag'); + span.dataset['value'] = value; + span.textContent = text; + tag.append(span); + tag.append(icon); + icon.onclick = (ev:any) => { + tag.parentElement.removeChild(tag); + this.querySelector(`lit-select-option[value=${value}]`)!.removeAttribute('selected') + if (this.shadowRoot!.querySelectorAll('.tag').length == 0) { + this.inputElement.style.width = 'auto'; + this.inputElement.placeholder = this.defaultPlaceholder; + } + ev.stopPropagation(); + } + tag.value = value; + tag.dataset['value'] = value; + tag.text = text; + tag.dataset['text'] = text; + return tag; + } + + //当 custom element首次被插入文档DOM时,被调用。 + connectedCallback() { + this.tabIndex = 0;//设置当前组件为可以获取焦点 + this.focused = false; + this.inputElement = this.shadowRoot!.querySelector('input'); + this.clearElement = this.shadowRoot!.querySelector('.clear'); + this.iconElement = this.shadowRoot!.querySelector('.icon'); + this.searchElement = this.shadowRoot!.querySelector('.search'); + this.multipleRootElement = this.shadowRoot!.querySelector('.multipleRoot'); + //点击清理 清空input值,展示placeholder, + this.clearElement.onclick = (ev:any) => { + if (this.isMultiple()) { + let delNodes:Array = [] + this.multipleRootElement.childNodes.forEach((a:any) => { + if (a.tagName === 'DIV') { + delNodes.push(a); + } + }) + for (let i = 0; i < delNodes.length; i++) { + delNodes[i].remove(); + } + if (this.shadowRoot!.querySelectorAll('.tag').length == 0) { + this.inputElement.style.width = 'auto'; + this.inputElement.placeholder = this.defaultPlaceholder; + } + } + this.querySelectorAll('lit-select-option').forEach(a => a.removeAttribute('selected')); + this.inputElement.value = '' + this.clearElement.style.display = 'none'; + this.iconElement.style.display = 'flex'; + this.blur(); + ev.stopPropagation();//这里不会因为点击清理而触发 选择栏目显示或者隐藏 + this.dispatchEvent(new CustomEvent('onClear', {detail: ev}))//向外派发清理事件 + } + //初始化时遍历所有的option节点 + this.initOptions(); + //当前控件点击时 如果时select本身 需要显示 或 隐藏选择栏目,通过this.focused变量控制(默认为false) + this.onclick = (ev:any) => { + if (ev.target.tagName === 'LIT-SELECT') { + if (this.focused === false) { + this.inputElement.focus(); + this.focused = true; + } else { + this.blur(); + this.focused = false; + } + } + } + this.onmouseover = this.onfocus = ev => { + if (this.hasAttribute('allow-clear')) { + if (this.inputElement.value.length > 0 || this.inputElement.placeholder !== this.defaultPlaceholder) { + this.clearElement.style.display = 'flex' + this.iconElement.style.display = 'none'; + } else { + this.clearElement.style.display = 'none' + this.iconElement.style.display = 'flex'; + } + } + } + this.onmouseout = this.onblur = ev => { + if (this.hasAttribute('allow-clear')) { + this.clearElement.style.display = 'none'; + this.iconElement.style.display = 'flex'; + } + this.focused = false; + } + //输入框获取焦点时,value值 暂存于 placeholder 然后value值清空,这样值会以placeholder形式灰色展示,鼠标位于第一个字符 + this.inputElement.onfocus = (ev:any) => { + if (this.hasAttribute('disabled')) return;//如果控件处于disabled状态 直接忽略 + if (this.inputElement.value.length > 0) { + this.inputElement.placeholder = this.inputElement.value; + this.inputElement.value = '' + } + if (this.hasAttribute('show-search')) {//如果有show-search属性 需要显示放大镜,隐藏向下的箭头 + this.searchElement.style.display = 'flex'; + this.iconElement.style.display = 'none'; + } + this.querySelectorAll('lit-select-option').forEach(a => {//input获取焦点时显示所有可选项,相当于清理了搜索结果 + // @ts-ignore + a.style.display = 'flex'; + }) + } + //当输入框失去焦点的时候 placeholder 的值 保存到value上,input显示值 + this.inputElement.onblur = (ev:any) => { + if (this.hasAttribute('disabled')) return;//如果控件处于disabled状态 直接忽略 + if (this.isMultiple()) { + if (this.hasAttribute('show-search')) {//如果有show-search属性 失去焦点需要 隐藏放大镜图标,显示默认的向下箭头图标 + this.searchElement.style.display = 'none'; + this.iconElement.style.display = 'flex'; + } + } else { + if (this.inputElement.placeholder !== this.defaultPlaceholder) {//如果placeholder为 请输入(默认值)不做处理 + this.inputElement.value = this.inputElement.placeholder; //placeholder 保存的值放入 value中 + this.inputElement.placeholder = this.defaultPlaceholder;//placeholder 值为 默认值(请输入) + } + if (this.hasAttribute('show-search')) {//如果有show-search属性 失去焦点需要 隐藏放大镜图标,显示默认的向下箭头图标 + this.searchElement.style.display = 'none'; + this.iconElement.style.display = 'flex'; + } + } + } + //输入框每次文本变化 会匹配搜索的option 显示或者隐藏,达到搜索的效果 + this.inputElement.oninput = (ev:any) => { + let els = [...this.querySelectorAll('lit-select-option')]; + if (!ev.target.value) { + els.forEach((a:any) => a.style.display = 'flex'); + } else { + els.forEach((a:any) => { + let value = a.getAttribute('value'); + if (value.toLowerCase().indexOf(ev.target.value.toLowerCase()) !== -1 || + a.textContent.toLowerCase().indexOf(ev.target.value.toLowerCase()) !== -1) { + a.style.display = 'flex'; + } else { + a.style.display = 'none'; + } + }) + } + } + //输入框按下回车键,自动输入当前搜索出来的第一行,及display!='none'的第一个,搜索会隐藏其他行 + this.inputElement.onkeydown = (ev:any) => { + if (ev.key === 'Backspace') { + if (this.isMultiple()) { + let tag = this.multipleRootElement.lastElementChild.previousElementSibling; + if (tag) { + this.querySelector(`lit-select-option[value=${tag.value}]`)?.removeAttribute('selected'); + tag.remove() + if (this.shadowRoot!.querySelectorAll('.tag').length == 0) { + this.inputElement.style.width = 'auto'; + this.inputElement.placeholder = this.defaultPlaceholder; + } + } + } else { + this.clear(); + this.dispatchEvent(new CustomEvent('onClear', {detail: ev}))//向外派发清理事件 + } + } else if (ev.key === 'Enter') { + let filter = [...this.querySelectorAll('lit-select-option')].filter((a:any) => a.style.display !== 'none'); + if (filter.length > 0) { + this.inputElement.value = filter[0].textContent; + this.inputElement.placeholder = filter[0].textContent; + this.blur(); + // @ts-ignore + this.value=filter[0].getAttribute('value') + this.dispatchEvent(new CustomEvent('change', { + detail: { + selected: true, + value: filter[0].getAttribute('value'), + text: filter[0].textContent + } + }));//向外层派发change事件,返回当前选中项 + } + } + } + } + + initOptions(){ + this.querySelectorAll('lit-select-option').forEach(a => { + //如果节点的值为 当前控件的默认值 defalut-value则 显示该值对应的option文本 + if (this.isMultiple()) { + a.setAttribute('check', ''); + if (a.getAttribute('value') === this.defaultValue) { + let tag = this.newTag(a.getAttribute('value'), a.textContent); + this.multipleRootElement.insertBefore(tag, this.inputElement); + this.inputElement.placeholder = ''; + this.inputElement.value = ''; + this.inputElement.style.width = '1px'; + a.setAttribute('selected', ''); + } + // this.inputElement.focus(); + } else { + if (a.getAttribute('value') === this.defaultValue) { + this.inputElement.value = a.textContent; + a.setAttribute('selected', ''); + } + } + //每个option设置onSelected事件 接受当前点击的option + a.addEventListener('onSelected', (e:any) => { + //所有option设置为未选中状态 + if (this.isMultiple()) {//多选 + if (a.hasAttribute('selected')) { + let tag = this.shadowRoot!.querySelector(`div[data-value=${e.detail.value}]`); + // @ts-ignore + tag.parentElement!.removeChild(tag); + e.detail.selected = false; + } else { + let tag = this.newTag(e.detail.value, e.detail.text); + this.multipleRootElement.insertBefore(tag, this.inputElement); + this.inputElement.placeholder = ''; + this.inputElement.value = ''; + this.inputElement.style.width = '1px'; + } + if (this.shadowRoot!.querySelectorAll('.tag').length == 0) { + this.inputElement.style.width = 'auto'; + this.inputElement.placeholder = this.defaultPlaceholder; + } + this.inputElement.focus(); + } else {//单选 + [...this.querySelectorAll('lit-select-option')].forEach(a => a.removeAttribute('selected')) + this.blur();//失去焦点,隐藏选择栏目列表 + // @ts-ignore + this.inputElement.value = e.detail.text; + } + //设置当前option为选择状态 + if (a.hasAttribute('selected')) { + a.removeAttribute('selected') + } else { + a.setAttribute('selected', '') + } + //设置input的值为当前选择的文本 + // @ts-ignore + this.value = e.detail.value; + this.dispatchEvent(new CustomEvent('change', {detail: e.detail}));//向外层派发change事件,返回当前选中项 + }) + }) + } + //js调用清理选项 + clear() { + this.inputElement.value = ''; + this.inputElement.placeholder = this.defaultPlaceholder; + } + + //重置为默认值 + reset() { + this.querySelectorAll('lit-select-option').forEach(a => { + //如果节点的值为 当前控件的默认值 defalut-value则 显示该值对应的option文本 + [...this.querySelectorAll('lit-select-option')].forEach(a => a.removeAttribute('selected')) + if (a.getAttribute('value') === this.defaultValue) { + this.inputElement.value = a.textContent; + a.setAttribute('selected', ''); + } + }) + } + + //当 custom element从文档DOM中删除时,被调用。 + disconnectedCallback() { + + } + + //当 custom element被移动到新的文档时,被调用。 + adoptedCallback() { + } + + //当 custom element增加、删除、修改自身属性时,被调用。 + attributeChangedCallback(name:any, oldValue:any, newValue:any) { + if (name === 'value' && this.inputElement) { + if(newValue){ + [...this.querySelectorAll('lit-select-option')].forEach(a => { + if (a.getAttribute('value') === newValue) { + a.setAttribute('selected', ''); + this.inputElement.value = a.textContent; + } else { + a.removeAttribute('selected') + } + }) + }else{ + this.clear(); + } + } + } + set dataSource(value:any){ + value.forEach((a:any)=>{ + let option = document.createElement('lit-select-option'); + option.setAttribute('value',a.key); + option.textContent = a.val; + this.append(option) + }) + this.initOptions(); + } + +} diff --git a/host/ide/src/base-ui/select/LitSelectOption.ts b/host/ide/src/base-ui/select/LitSelectOption.ts new file mode 100644 index 0000000000000000000000000000000000000000..440097f0fbc379ebec633a082b9291028becca8d --- /dev/null +++ b/host/ide/src/base-ui/select/LitSelectOption.ts @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement} from "../BaseElement.js"; +import "../icon/LitIcon.js" + +export class LitSelectOption extends BaseElement { + static get observedAttributes() { + return ['selected','disabled','check'] + } + + initHtml() { + // super(); + // const shadowRoot = this.attachShadow({mode: 'open'}); + return` + +
+ +
+ + + ` + } + + initElements(): void { + + } + + //当 custom element首次被插入文档DOM时,被调用。 + connectedCallback() { + if(!this.hasAttribute('disabled')){ + this.onclick=ev => { + this.dispatchEvent(new CustomEvent('onSelected',{detail:{ + selected:true, + value: this.getAttribute('value'), + text: this.textContent + }})) + } + } + + } + + //当 custom element从文档DOM中删除时,被调用。 + disconnectedCallback() { + + } + + //当 custom element被移动到新的文档时,被调用。 + adoptedCallback() { + } + + //当 custom element增加、删除、修改自身属性时,被调用。 + attributeChangedCallback(name:any, oldValue:any, newValue:any) { + + } +} + +if (!customElements.get('lit-select-option')) { + customElements.define('lit-select-option', LitSelectOption); +} diff --git a/host/ide/src/base-ui/slider/LitSlider.ts b/host/ide/src/base-ui/slider/LitSlider.ts new file mode 100644 index 0000000000000000000000000000000000000000..fa7042104174350c1e69c5345ca2aa7639b50c7e --- /dev/null +++ b/host/ide/src/base-ui/slider/LitSlider.ts @@ -0,0 +1,429 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../BaseElement.js"; + +@element('lit-slider') +export class LitSlider extends BaseElement { + private litSliderStyle: LitSliderStyle | undefined | null; + private litSlider: HTMLInputElement | undefined | null; + private litSliderCon: HTMLDivElement | undefined | null; + private litResult: HTMLInputElement | undefined | null; + private litSliderButton: HTMLDivElement | undefined | null; + private slotEl: HTMLSlotElement | undefined | null; + private currentValue: number = 0; + private sliderLineHeight: string | undefined; + private sliderButtonHeight: string | undefined; + private sliderButtonWidth: string | undefined; + private defaultTimeText: string | undefined | null; + + static get observedAttributes() { + return ['percent', 'disabled-X', 'custom-slider', 'custom-line', 'custom-button'] + } + + get sliderStyle() { + if (this.hasAttribute('custom-slider')) { + this.defaultTimeText = "64"; + return { + minRange: 4, + maxRange: 512, + defaultValue: this.defaultTimeText, + resultUnit: "MB", + stepSize: 2, + lineColor: "var(--dark-color3,#46B1E3)", + buttonColor: "#999999" + } + } else { + let defaultTime = "00:00:50"; + this.defaultTimeText = defaultTime.split(':')[2]; + return { + minRange: 10, + maxRange: 600, + defaultValue: defaultTime, + resultUnit: "h:m:s", + stepSize: 1, + lineColor: "var(--dark-color4,#61CFBE)", + buttonColor: "#999999" + } + } + + } + + set sliderStyle(value) { + this.litSliderStyle = value; + this.litSliderStyle = this.sliderStyle; + this.litSliderStyle.defaultValue = value.defaultValue + if (this.hasAttribute('custom-slider')) { + this.renderCustomSlider(); + } else { + this.renderDefaultSlider(); + } + } + + get disabledX() { + return this.getAttribute('disabled-X') || ''; + } + + set disabledX(value: string) { + if (value) { + this.setAttribute('disabled-X', ''); + } else { + this.removeAttribute('disabled-X'); + } + } + + get customSlider() { + return this.getAttribute('custom-slider') || ''; + } + + set customSlider(value: string) { + if (value) { + this.setAttribute('custom-slider', ''); + } else { + this.removeAttribute('custom-slider'); + } + } + + get customLine() { + return this.getAttribute('custom-line') || ''; + } + + set customLine(value: string) { + this.setAttribute('custom-line', value); + } + + get customButton() { + return this.getAttribute('custom-button') || ''; + } + + set customButton(value: string) { + this.setAttribute('custom-button', value); + } + + get percent() { + return this.getAttribute('percent') || ''; + } + + set percent(value: string) { + this.setAttribute('percent', value); + } + + get resultUnit() { + return this.getAttribute('resultUnit') || ''; + } + + set resultUnit(value: string) { + this.setAttribute('resultUnit', value); + } + + get sliderSize() { + return this.currentValue; + } + + initElements(): void { + } + + initHtml(): string { + this.litSliderStyle = this.sliderStyle; + this.currentValue = Number(this.sliderStyle.defaultValue); + let parentElement = this.parentNode as Element; + if (parentElement) { + parentElement.setAttribute('percent', this.defaultTimeText + ""); + } + return ` + + +
+ + ${this.litSliderStyle?.resultUnit} +
+ ` + } + + // It is called when the custom element is first inserted into the document DOM. + connectedCallback() { + this.slotEl = this.shadowRoot?.querySelector('#slot'); + this.litSlider = this.shadowRoot?.querySelector('#slider'); + this.litSliderCon = this.shadowRoot?.querySelector('#slider-con'); + this.litResult = this.shadowRoot?.querySelector('#result'); + // Add a slider for input event listeners + this.litSlider?.addEventListener('input', this.inputChangeEvent) + this.litSlider?.addEventListener('change', this.inputChangeEvent) + // Add slot slot to change event listeners + this.slotEl?.addEventListener('slotchange', this.slotChangeEvent); + // Add a slider for line click event listeners + this.litSlider?.addEventListener('click', this.sliderClickEvent); + // Add a slider button to start touching the event listener + this.litSliderButton?.addEventListener('TouchEvent', this.sliderStartTouchEvent); + this.litSliderStyle = this.sliderStyle; + + } + + slotChangeEvent = (event: any) => { + } + + sliderClickEvent = (event: any) => { + } + + inputChangeEvent = (event: any) => { + if (this.litSlider) { + this.currentValue = parseInt(this.litSlider?.value) + let resultNumber = (this.currentValue - this.litSliderStyle!.minRange) * 100 / (this.litSliderStyle!.maxRange - this.litSliderStyle!.minRange); + this.percent = Math.floor(resultNumber) + "%"; + this.litSliderCon?.style.setProperty('percent', this.currentValue + "%") + let parentElement = this.parentNode as Element; + parentElement.setAttribute('percent', this.currentValue + ""); + if (this.sliderStyle.resultUnit === 'MB') { + this.litSlider!.style.backgroundSize = this.percent; + this.litResult!.value = " " + this.currentValue; + } else if (this.sliderStyle.resultUnit === 'h:m:s') { + this.litSlider!.style.backgroundSize = this.percent; + let time = this.formatSeconds(this.litSlider?.value); + this.litResult!.value = " " + time; + } + } + } + + sliderStartTouchEvent = (event: any) => { + + } + + sliderMoveTouchEvent = (event: any) => { + + } + + sliderEndTouchEvent = (event: any) => { + + } + + disconnectedCallback() { + this.litSlider?.removeEventListener('input', this.inputChangeEvent); + this.litSlider?.removeEventListener('change', this.inputChangeEvent) + this.litSlider?.removeEventListener('click', this.sliderClickEvent); + this.litSliderButton?.removeEventListener('TouchEvent', this.sliderStartTouchEvent); + } + + adoptedCallback() { + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + switch (name) { + case "percent": + if (newValue === null || newValue === "0%") { + let parentElement = this.parentNode as Element; + parentElement?.removeAttribute('percent'); + } else { + let parentElement = this.parentNode as Element; + } + break; + default: + break; + } + } + + renderCustomSlider() { + } + + renderDefaultSlider() { + if (!this.litSliderStyle) return; + } + + formatSeconds(value: string) { + let result = parseInt(value) + let hours = Math.floor(result / 3600) < 10 ? '0' + Math.floor(result / 3600) : Math.floor(result / 3600); + let minute = Math.floor((result / 60 % 60)) < 10 ? '0' + Math.floor((result / 60 % 60)) : Math.floor((result / 60 % 60)); + let second = Math.floor((result % 60)) < 10 ? '0' + Math.floor((result % 60)) : Math.floor((result % 60)); + let resultTime = ''; + if (hours === '00') { + resultTime += `00:`; + } else { + resultTime += `${hours}:`; + } + if (minute === '00') { + resultTime += `00:`; + } else { + resultTime += `${minute}:`; + } + resultTime += `${second}`; + return resultTime; + } +} + +export interface LitSliderStyle { + minRange: number + maxRange: number + defaultValue: string + resultUnit: string + stepSize?: number + lineColor?: string + buttonColor?: string +} + +export interface LitSliderLineStyle { + lineWith: number + lineHeight: number + border?: string + borderRadiusValue?: number + lineChangeColor?: string +} + +export interface LitSliderButtonStyle { + buttonWith: number + buttonHeight: number + border?: string + borderRadiusValue?: number + buttonChangeColor?: string +} diff --git a/host/ide/src/base-ui/switch/lit-switch.ts b/host/ide/src/base-ui/switch/lit-switch.ts new file mode 100644 index 0000000000000000000000000000000000000000..2dc25eaef92b593d9f371b835930c43792c0cd6d --- /dev/null +++ b/host/ide/src/base-ui/switch/lit-switch.ts @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import {BaseElement, element} from "../BaseElement.js"; + +@element('lit-switch') +export default class LitSwitch extends BaseElement { + private switch: HTMLInputElement | null | undefined + private isfocus: boolean | undefined + + static get observedAttributes() { + return ['disabled', 'checked'] + } + + get disabled() { + return this.getAttribute("disabled") !== null; + } + + set disabled(value) { + if (value === null || value === false) { + this.removeAttribute("disabled"); + } else { + this.setAttribute("disabled", ""); + } + } + + get checked() { + return this.getAttribute("checked") !== null; + } + + set checked(value) { + if (value === null || value === false) { + this.removeAttribute("checked"); + } else { + this.setAttribute("checked", ""); + } + } + + get name() { + return this.getAttribute("name"); + } + + initElements(): void { + + } + + initHtml(): string { + return ` + + + `; + } + + connectedCallback() { + this.switch = this.shadowRoot?.getElementById("switch") as HTMLInputElement; + this.disabled = this.disabled; + this.checked = this.checked; + this.switch!.onchange = (ev) => { + this.checked = this.switch!.checked; + this.dispatchEvent(new CustomEvent("change", {detail: {checked: this.checked}})); + } + this.switch.onkeydown = (ev) => { + switch (ev.keyCode) { + case 13://enter + this.checked = !this.checked; + this.dispatchEvent(new CustomEvent("change", {detail: {checked: this.checked}})); + break; + default: + break; + } + } + this.switch.onfocus = (ev) => { + ev.stopPropagation(); + if (!this.isfocus) { + this.dispatchEvent(new CustomEvent("focus", {detail: {value: this.switch!.value}})) + } + } + this.switch.onblur = ev => { + ev.stopPropagation(); + if (getComputedStyle(this.switch!).zIndex == '2') { + this.isfocus = true; + } else { + this.isfocus = false; + this.dispatchEvent(new CustomEvent("blur", {detail: {value: this.switch!.value}})); + } + } + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + if (name === "disabled" && this.switch) { + if (newValue !== null) { + this.switch.setAttribute("disabled", ""); + } else { + this.switch.removeAttribute("disabled"); + } + } + if (name === "checked" && this.switch) { + if (newValue !== null) { + this.switch.checked = true; + } else { + this.switch.checked = false; + } + } + } +} + diff --git a/host/ide/src/base-ui/table/TableRowObject.ts b/host/ide/src/base-ui/table/TableRowObject.ts new file mode 100644 index 0000000000000000000000000000000000000000..93556e1b8bc586ecebafce96f11320d19a81f859 --- /dev/null +++ b/host/ide/src/base-ui/table/TableRowObject.ts @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class TableRowObject { + public top: number = 0; + public height: number = 0 + public rowIndex: number = 0; + public data: any | undefined + public expanded: boolean = true + public rowHidden: boolean = false; + public children: any[] = [] + public depth: number = -1 +} \ No newline at end of file diff --git a/host/ide/src/base-ui/table/lit-table-column.ts b/host/ide/src/base-ui/table/lit-table-column.ts new file mode 100644 index 0000000000000000000000000000000000000000..b66d3004018cbedfce1300070da3a6e1daad2fc3 --- /dev/null +++ b/host/ide/src/base-ui/table/lit-table-column.ts @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import {element} from "../BaseElement.js"; + +@element('lit-table-column') +export class LitTableColumn extends HTMLElement { + template: Element | undefined | null + private st: HTMLSlotElement | undefined | null + + constructor() { + super(); + const shadowRoot = this.attachShadow({mode: 'open'}); + shadowRoot.innerHTML = ` + + + ` + } + + static get observedAttributes() { + return ['name', 'order'] + } + + connectedCallback() { + this.template = null; + this.st = this.shadowRoot?.querySelector('#slot') + this.st?.addEventListener('slotchange', () => { + const elements = this.st!.assignedElements({flatten: false}); + if (elements!.length > 0) { + this.template = elements[0]; + } + }) + } + + disconnectedCallback() { + + } + + adoptedCallback() { + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + } + +} \ No newline at end of file diff --git a/host/ide/src/base-ui/table/lit-table-group.ts b/host/ide/src/base-ui/table/lit-table-group.ts new file mode 100644 index 0000000000000000000000000000000000000000..78355ef0b530afa921aa4edf4732912cda5957a5 --- /dev/null +++ b/host/ide/src/base-ui/table/lit-table-group.ts @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {element} from "../BaseElement.js"; + +@element('lit-table-group') +export class LitTableGroup extends HTMLElement { + constructor() { + super(); + const shadowRoot = this.attachShadow({mode: 'open'}); + shadowRoot.innerHTML = ` + + + ` + } + + static get observedAttributes() { + return ['title'] + } + + get title() { + return this.getAttribute('title') || ''; + } + + set title(value: string) { + this.setAttribute('title', value); + } + + connectedCallback() { + + } + + disconnectedCallback() { + + } + + adoptedCallback() { + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + } +} \ No newline at end of file diff --git a/host/ide/src/base-ui/table/lit-table.ts b/host/ide/src/base-ui/table/lit-table.ts new file mode 100644 index 0000000000000000000000000000000000000000..7a6dab11a1bd1461c481db69b432914305272191 --- /dev/null +++ b/host/ide/src/base-ui/table/lit-table.ts @@ -0,0 +1,1161 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import {LitTableColumn} from "./lit-table-column.js"; +import {element} from "../BaseElement.js"; +import "../utils/Template.js" +import {TableRowObject} from "./TableRowObject.js"; + +@element('lit-table') +export class LitTable extends HTMLElement { + meauseRowElement: HTMLDivElement | undefined + currentRecycleList: HTMLDivElement[] = [] + currentTreeDivList: HTMLDivElement[] = [] + private ds: Array = [] + private recycleDs: Array = [] + private gridTemplateColumns: any + /*Grid css layout descriptions are obtained according to the clustern[] nested structure*/ + private st: HTMLSlotElement | null | undefined + private tableElement: HTMLDivElement | null | undefined + private theadElement: HTMLDivElement | null | undefined + private columns: Array | null | undefined + private tbodyElement: HTMLDivElement | undefined | null + private treeElement: HTMLDivElement | undefined | null + private tableColumns: NodeListOf | undefined + private colCount: number = 0 + + constructor() { + super(); + const shadowRoot = this.attachShadow({mode: 'open'}); + shadowRoot.innerHTML = ` + + + +
+
+
+
+
+
+
+ ` + + } + + static get observedAttributes() { + return ['scroll-y', 'selectable', 'no-head', 'grid-line', 'defaultOrderColumn'] + } + + get selectable() { + return this.hasAttribute('selectable'); + } + + set selectable(value) { + if (value) { + this.setAttribute('selectable', ''); + } else { + this.removeAttribute('selectable'); + } + } + + get scrollY() { + return this.getAttribute('scroll-y') || 'auto'; + } + + set scrollY(value) { + this.setAttribute('scroll-y', value); + } + + get dataSource() { + return this.ds || []; + } + + set dataSource(value) { + this.ds = value; + if (this.hasAttribute('tree')) { + this.renderTreeTable(); + } else { + this.renderTable(); + } + } + + get recycleDataSource() { + return this.recycleDs || []; + } + + set recycleDataSource(value) { + this.tableElement!.scrollTop = 0 + if (this.hasAttribute('tree')) { + this.recycleDs = this.meauseTreeRowElement(value) + } else { + this.recycleDs = this.meauseAllRowHeight(value) + } + } + + // It is called when the custom element is first inserted into the document DOM. + connectedCallback() { + this.st = this.shadowRoot?.querySelector('#slot'); + this.tableElement = this.shadowRoot?.querySelector('.table'); + this.theadElement = this.shadowRoot?.querySelector('.thead'); + this.treeElement = this.shadowRoot?.querySelector('.tree'); + this.tbodyElement = this.shadowRoot?.querySelector('.body'); + this.tableColumns = this.querySelectorAll('lit-table-column'); + this.colCount = this.tableColumns!.length; + this.st?.addEventListener('slotchange', () => { + this.theadElement!.innerHTML = ''; + setTimeout(() => { + this.columns = this.st!.assignedElements(); + let rowElement = document.createElement('div'); + rowElement.classList.add('th'); + if (this.selectable) { + let box = document.createElement('div'); + box.style.display = 'flex'; + box.style.justifyContent = 'center'; + box.style.alignItems = 'center'; + box.style.gridArea = "_checkbox_"; + box.classList.add('td'); + box.style.backgroundColor = "#ffffff66"; + let checkbox = document.createElement('lit-checkbox'); + checkbox.classList.add('row-checkbox-all'); + checkbox.onchange = (e: any) => { + this.shadowRoot!.querySelectorAll('.row-checkbox').forEach((a: any) => a.checked = e.detail.checked); + if (e.detail.checked) { + this.shadowRoot!.querySelectorAll('.tr').forEach(a => a.setAttribute('checked', '')); + } else { + this.shadowRoot!.querySelectorAll('.tr').forEach(a => a.removeAttribute('checked')); + } + } + + box.appendChild(checkbox); + rowElement.appendChild(box); + } + let area: Array = [], gridTemplateColumns: Array = []; + let resolvingArea = (columns: any, x: any, y: any) => { + columns.forEach((a: any, i: any) => { + if (!area[y]) area[y] = [] + let key = a.getAttribute('key') || a.getAttribute('title') + if (a.tagName === 'LIT-TABLE-GROUP') { + let len = a.querySelectorAll('lit-table-column').length; + let children = [...a.children].filter(a => a.tagName !== 'TEMPLATE'); + if (children.length > 0) { + resolvingArea(children, x, y + 1); + } + for (let j = 0; j < len; j++) { + area[y][x] = {x, y, t: key}; + x++; + } + let h = document.createElement('div'); + h.classList.add('td'); + h.style.justifyContent = a.getAttribute('align') + h.style.borderBottom = '1px solid #f0f0f0' + h.style.gridArea = key; + h.innerText = a.title; + if (a.hasAttribute('fixed')) { + this.fixed(h, a.getAttribute('fixed'), "#42b983") + } + rowElement.append(h); + } else if (a.tagName === 'LIT-TABLE-COLUMN') { + area[y][x] = {x, y, t: key}; + x++; + let h: any = document.createElement('div'); + h.classList.add('td'); + if (a.hasAttribute('order')) { + h.sortType = 0; + h.classList.add('td-order'); + h.style.position = "relative" + let NS = "http://www.w3.org/2000/svg"; + let upSvg: any = document.createElementNS(NS, "svg"); + let upPath: any = document.createElementNS(NS, "path"); + upSvg.setAttribute('fill', '#efefef'); + upSvg.setAttribute('viewBox', '0 0 1024 1024'); + upSvg.setAttribute('stroke', '#000000'); + upSvg.classList.add('up-svg'); + upPath.setAttribute("d", "M858.9 689L530.5 308.2c-9.4-10.9-27.5-10.9-37 0L165.1 689c-12.2 14.2-1.2 35 18.5 35h656.8c19.7 0 30.7-20.8 18.5-35z"); + upSvg.appendChild(upPath); + let downSvg: any = document.createElementNS(NS, "svg"); + let downPath: any = document.createElementNS(NS, "path"); + downSvg.setAttribute('fill', '#efefef'); + downSvg.setAttribute('viewBox', '0 0 1024 1024'); + downSvg.setAttribute('stroke', '#efefef'); + downSvg.classList.add('down-svg'); + downPath.setAttribute("d", "M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"); + downSvg.appendChild(downPath) + if (i == 0) { + h.sortType = 0; // 默认以第一列 降序排序 作为默认排序 + upSvg.setAttribute('fill', '#fff'); + downSvg.setAttribute('fill', '#fff'); + } + upSvg.style.display = 'none'; + downSvg.style.display = 'none'; + h.appendChild(upSvg); + h.appendChild(downSvg); + h.onclick = () => { + this?.shadowRoot?.querySelectorAll('.td-order svg').forEach((it: any) => { + it.setAttribute('fill', '#fff'); + it.setAttribute('fill', '#fff'); + it.sortType = 0; + }) + if (h.sortType == undefined || h.sortType == null) { + h.sortType = 0; + } else if (h.sortType === 2) { + h.sortType = 0; + } else { + h.sortType += 1; + } + switch (h.sortType) { + case 1: + upSvg.setAttribute('fill', '#333'); + downSvg.setAttribute('fill', '#fff'); + upSvg.style.display = 'block'; + downSvg.style.display = 'none'; + break; + case 2: + upSvg.setAttribute('fill', '#fff'); + downSvg.setAttribute('fill', '#333'); + upSvg.style.display = 'none'; + downSvg.style.display = 'block'; + break; + default: + upSvg.setAttribute('fill', "#fff"); + downSvg.setAttribute('fill', "#fff"); + upSvg.style.display = 'none'; + downSvg.style.display = 'none'; + break; + } + this.dispatchEvent(new CustomEvent("column-click", { + detail: { + sort: h.sortType, key: key + }, composed: true + })) + } + } + h.style.justifyContent = a.getAttribute('align') + gridTemplateColumns.push(a.getAttribute('width') || '1fr'); + h.style.gridArea = key; + let titleLabel = document.createElement("label"); + titleLabel.textContent = a.title; + h.appendChild(titleLabel); + if (a.hasAttribute('fixed')) { + this.fixed(h, a.getAttribute('fixed'), "#42b983") + } + rowElement.append(h); + } + }) + } + resolvingArea(this.columns, 0, 0); + area.forEach((rows, j, array) => { + for (let i = 0; i < this.colCount; i++) { + if (!rows[i]) rows[i] = array[j - 1][i]; + } + }) + this.gridTemplateColumns = gridTemplateColumns.join(' '); + if (this.selectable) { + let s = area.map(a => '"_checkbox_ ' + (a.map((aa: any) => aa.t).join(' ')) + '"').join(' '); + rowElement.style.gridTemplateColumns = "60px " + gridTemplateColumns.join(' ');//`repeat(${this.colCount},1fr)` + rowElement.style.gridTemplateRows = `repeat(${area.length},1fr)` + rowElement.style.gridTemplateAreas = s + } else { + let s = area.map(a => '"' + (a.map((aa: any) => aa.t).join(' ')) + '"').join(' '); + rowElement.style.gridTemplateColumns = gridTemplateColumns.join(' ');//`repeat(${this.colCount},1fr)` + rowElement.style.gridTemplateRows = `repeat(${area.length},1fr)` + rowElement.style.gridTemplateAreas = s + } + this.theadElement!.append(rowElement); + this.treeElement!.style.top = this.theadElement?.clientHeight + "px" + }); + + }); + + this.shadowRoot!.addEventListener("load", function (event) { + }); + } + + // Is called when the custom element is removed from the document DOM. + disconnectedCallback() { + + } + + // It is called when the custom element is moved to a new document. + adoptedCallback() { + } + + // It is called when a custom element adds, deletes, or modifies its own properties. + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + + } + + fixed(td: HTMLElement, placement: string, bgColor: string) { + td.style.position = 'sticky'; + if (placement === "left") { + td.style.left = '0px'; + td.style.boxShadow = '3px 0px 5px #33333333' + } else if (placement === "right") { + td.style.right = '0px'; + td.style.boxShadow = '-3px 0px 5px #33333333' + } + } + + renderTable() { + if (!this.columns) return; + if (!this.ds) return; // If no data source is set, it is returned directly + this.tbodyElement!.innerHTML = '';// Clear the table contents + this.ds.forEach((rowData: any) => { + let rowElement = document.createElement('div'); + rowElement.classList.add('tr'); + // @ts-ignore + rowElement.data = rowData; + let gridTemplateColumns: Array = [] + // If the table is configured with selectable (select row mode) add a checkbox at the head of the line alone + if (this.selectable) { + let box = document.createElement('div'); + box.style.display = 'flex'; + box.style.justifyContent = 'center'; + box.style.alignItems = 'center'; + box.classList.add('td'); + let checkbox = document.createElement('lit-checkbox'); + checkbox.classList.add('row-checkbox'); + checkbox.onchange = (e: any) => {// Checkbox checking affects whether the div corresponding to the row has a checked attribute for marking + if (e.detail.checked) { + rowElement.setAttribute('checked', ""); + } else { + rowElement.removeAttribute('checked'); + } + } + box.appendChild(checkbox); + rowElement.appendChild(box); + } + this.tableColumns!.forEach(cl => { + let dataIndex = cl.getAttribute('data-index') || '1'; + gridTemplateColumns.push(cl.getAttribute('width') || '1fr') + if (cl.template) {// If you customize the rendering, you get the nodes from the template + // @ts-ignore + let cloneNode = cl.template.render(rowData).content.cloneNode(true); + let d = document.createElement('div'); + d.classList.add('td'); + d.style.wordBreak = 'break-all' + d.style.whiteSpace = 'pre-wrap' + d.style.justifyContent = cl.getAttribute('align') || '' + if (cl.hasAttribute('fixed')) { + this.fixed(d, cl.getAttribute('fixed') || '', "#ffffff") + } + d.append(cloneNode); + rowElement.append(d); + } else { + let td = document.createElement('div'); + td.classList.add('td'); + td.style.wordBreak = 'break-all' + td.style.whiteSpace = 'pre-wrap' + td.title = rowData[dataIndex] + td.style.justifyContent = cl.getAttribute('align') || '' + if (cl.hasAttribute('fixed')) { + this.fixed(td, cl.getAttribute('fixed') || '', "#ffffff") + } + td.innerHTML = rowData[dataIndex]; + rowElement.append(td); + } + + }) + if (this.selectable) { // If the table with selection is preceded by a 60px column + rowElement.style.gridTemplateColumns = '60px ' + gridTemplateColumns.join(' '); + } else { + rowElement.style.gridTemplateColumns = gridTemplateColumns.join(' ');// + } + rowElement.onclick = e => { + this.dispatchEvent(new CustomEvent('row-click', {detail: rowData, composed: true})); + } + this.tbodyElement!.append(rowElement); + }) + } + + + renderTreeTable() { + if (!this.columns) return; + if (!this.ds) return; + this.tbodyElement!.innerHTML = ''; + this.treeElement!.innerHTML = ''; + let ids = JSON.parse(this.getAttribute('tree') || `["id","pid"]`); + let toTreeData = (data: any, id: any, pid: any) => { + let cloneData = JSON.parse(JSON.stringify(data)); + return cloneData.filter((father: any) => { + let branchArr = cloneData.filter((child: any) => father[id] == child[pid]); + branchArr.length > 0 ? father['children'] = branchArr : ''; + return !father[pid]; + }); + } + let treeData = toTreeData(this.ds, ids[0], ids[1]);// + let offset = 30; + let offsetVal = offset; + const drawRow = (arr: any, parentNode: any) => { + arr.forEach((rowData: any) => { + let rowElement = document.createElement('div'); + rowElement.classList.add('tr'); + // @ts-ignore + rowElement.data = rowData; + let gridTemplateColumns: Array = []; + if (this.selectable) { + let box = document.createElement('div'); + box.style.display = 'flex'; + box.style.justifyContent = 'center'; + box.style.alignItems = 'center'; + box.classList.add('td'); + let checkbox = document.createElement('lit-checkbox'); + checkbox.classList.add('row-checkbox'); + checkbox.onchange = (e: any) => { + if (e.detail.checked) { + rowElement.setAttribute('checked', ""); + } else { + rowElement.removeAttribute('checked'); + } + const changeChildNode = (rowElement: any, checked: any) => { + let id = rowElement.getAttribute('id'); + let pid = rowElement.getAttribute('pid'); + this.shadowRoot!.querySelectorAll(`div[pid=${id}]`).forEach(a => { + // @ts-ignore + a.querySelector('.row-checkbox')!.checked = checked; + if (checked) { + a.setAttribute('checked', ''); + } else { + a.removeAttribute('checked'); + } + changeChildNode(a, checked); + }); + }; + changeChildNode(rowElement, e.detail.checked); + } + box.appendChild(checkbox); + rowElement.appendChild(box); + } + this.tableColumns!.forEach((cl, index) => { + let dataIndex = cl.getAttribute('data-index'); + let td; + if (index !== 0) { + gridTemplateColumns.push(cl.getAttribute('width') || '1fr') + if (cl.template) { + // @ts-ignore + let cloneNode = cl.template.render(rowData).content.cloneNode(true); + // cloneNode.classList.add('td'); + td = document.createElement('div'); + td.classList.add('td'); + td.style.wordBreak = 'break-all' + // td.style.whiteSpace = 'pre-wrap' + td.style.justifyContent = cl.getAttribute('align') || '' + if (cl.hasAttribute('fixed')) { + this.fixed(td, cl.getAttribute('fixed') || '', "#ffffff") + } + td.append(cloneNode); + } else { + td = document.createElement('div'); + td.classList.add('td'); + td.style.wordBreak = 'break-all' + // td.style.whiteSpace = 'pre-wrap' + td.style.justifyContent = cl.getAttribute('align') || '' + if (cl.hasAttribute('fixed')) { + this.fixed(td, cl.getAttribute('fixed') || '', "#ffffff") + } + // td.style.position='sticky'; + // @ts-ignore + td.innerHTML = rowData[dataIndex]; + } + rowElement.append(td) + } else { + this.treeElement!.style.width = cl.getAttribute('width') || "260px" + let treeElement = document.createElement('div'); + treeElement.classList.add("tree-first-body") + if (cl.template) { + // @ts-ignore + let cloneNode = cl.template.render(rowData).content.cloneNode(true); + // cloneNode.classList.add('td'); + td = document.createElement('div'); + td.classList.add('td'); + // td.style.wordBreak = 'break-all' + // td.style.whiteSpace = 'pre-wrap' + td.style.justifyContent = cl.getAttribute('align') || '' + if (cl.hasAttribute('fixed')) { + this.fixed(td, cl.getAttribute('fixed') || '', "#ffffff") + } + td.append(cloneNode); + } else { + td = document.createElement('div'); + td.classList.add('td'); + // td.style.wordBreak = 'break-all' + // td.style.whiteSpace = 'pre-wrap' + td.style.justifyContent = cl.getAttribute('align') || '' + if (cl.hasAttribute('fixed')) { + this.fixed(td, cl.getAttribute('fixed') || '', "#ffffff") + } + // td.style.position='sticky'; + // @ts-ignore + td.innerHTML = rowData[dataIndex]; + } + if (rowData.children && rowData.children.length > 0) { + let btn = document.createElement('lit-icon'); + btn.classList.add('tree-icon'); + // @ts-ignore + btn.name = 'minus-square'; + treeElement.append(btn); + treeElement.append(td) + treeElement.style.paddingLeft = (offsetVal - 30) + 'px'; + } else { + treeElement.append(td) + treeElement.style.paddingLeft = offsetVal + 'px'; + } + this.treeElement!.append(treeElement); + } + + }) + if (this.selectable) { + rowElement.style.gridTemplateColumns = '60px ' + gridTemplateColumns.join(' ');//`repeat(${this.colCount},1fr)` + } else { + rowElement.style.gridTemplateColumns = gridTemplateColumns.join(' ');//`repeat(${this.colCount},1fr)` + } + rowElement.onclick = e => { + this.dispatchEvent(new CustomEvent('row-click', {detail: rowData, composed: true})); + } + rowElement.style.cursor = 'pointer' + parentNode.append(rowElement); + rowElement.setAttribute('id', rowData[ids[0]]); + rowElement.setAttribute('pid', rowData[ids[1]]); + rowElement.setAttribute('expend', ''); + if (rowData.children && rowData.children.length > 0) { + offsetVal = offsetVal + offset; + drawRow(rowData.children, parentNode); + offsetVal = offsetVal - offset; + } + }); + }; + drawRow(treeData, this.tbodyElement); + } + + getCheckRows() { + // @ts-ignore + return [...this.shadowRoot!.querySelectorAll('div[class=tr][checked]')].map(a => a.data).map(a => { + delete a['children']; + return a; + }); + } + + deleteRowsCondition(fn: any) { + this.shadowRoot!.querySelectorAll("div[class=tr]").forEach(tr => { + // @ts-ignore + if (fn(tr.data)) { + tr.remove(); + } + }) + } + + meauseElementHeight(rowData: any) { + return 27; + } + + meauseTreeElementHeight(rowData: any, depth: number) { + return 27; + } + + meauseAllRowHeight(list: any[]): TableRowObject[] { + this.tbodyElement!.innerHTML = ''; + this.meauseRowElement = undefined + this.tbodyElement && (this.tbodyElement.style.width = this.tableElement?.clientWidth + "px") + this.currentRecycleList = [] + let headHeight = 0 + let totalHeight = headHeight + let visibleObjects: TableRowObject[] = []; + list.forEach((rowData, index) => { + let height = this.meauseElementHeight(rowData); + let tableRowObject = new TableRowObject(); + tableRowObject.height = height + tableRowObject.top = totalHeight + tableRowObject.data = rowData + tableRowObject.rowIndex = index + if (Math.max(totalHeight, this.tableElement!.scrollTop + headHeight) <= Math.min(totalHeight + height, this.tableElement!.scrollTop + this.tableElement!.clientHeight + headHeight)) { + let newTableElement = this.createNewTableElement(rowData); + newTableElement.style.transform = `translateY(${totalHeight}px)` + this.tbodyElement?.append(newTableElement) + this.currentRecycleList.push(newTableElement) + } + totalHeight += height + visibleObjects.push(tableRowObject) + }) + this.tbodyElement && (this.tbodyElement.style.height = totalHeight + "px") + this.tableElement && (this.tableElement.onscroll = (event) => { + let top = this.tableElement!.scrollTop; + let skip = 0; + for (let i = 0; i < visibleObjects.length; i++) { + if (visibleObjects[i].top <= top && visibleObjects[i].top + visibleObjects[i].height >= top) { + skip = i + break; + } + } + let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b,0); + if(reduce == 0){ + return + } + while (reduce <= this.tableElement!.clientHeight) { + let newTableElement = this.createNewTableElement(visibleObjects[skip].data); + this.tbodyElement?.append(newTableElement) + this.currentRecycleList.push(newTableElement) + reduce += newTableElement.clientHeight + } + for (let i = 0; i < this.currentRecycleList.length; i++) { + this.freshCurrentLine(this.currentRecycleList[i], visibleObjects[i + skip]) + } + }) + return visibleObjects + } + + meauseTreeRowElement(list: any[]): TableRowObject[] { + this.meauseRowElement = undefined + this.tbodyElement!.innerHTML = ''; + this.treeElement!.innerHTML = ''; + let headHeight = this.theadElement?.clientHeight || 0 + let totalHeight = 0 + let visibleObjects: TableRowObject[] = [] + this.currentRecycleList = [] + this.currentTreeDivList = [] + let resetAllHeight = (list: any[], depth: number, parentNode?: TableRowObject) => { + list.forEach((item) => { + let tableRowObject = new TableRowObject(); + tableRowObject.depth = depth + tableRowObject.data = item + tableRowObject.top = totalHeight + tableRowObject.height = this.meauseTreeElementHeight(tableRowObject, depth) + if (parentNode != undefined) { + parentNode.children.push(tableRowObject) + } + if (Math.max(totalHeight, this.tableElement!.scrollTop) <= Math.min(totalHeight + tableRowObject.height, this.tableElement!.scrollTop + this.tableElement!.clientHeight - headHeight)) { + let newTableElement = this.createNewTreeTableElement(tableRowObject); + newTableElement.style.transform = `translateY(${totalHeight}px)` + this.tbodyElement?.append(newTableElement) + if (this.treeElement?.lastChild) { + (this.treeElement?.lastChild as HTMLElement).style.height = tableRowObject.height + "px"; + } + this.currentRecycleList.push(newTableElement) + } + totalHeight += tableRowObject.height + visibleObjects.push(tableRowObject) + if (item.children != undefined && item.children.length > 0) { + resetAllHeight(item.children, depth + 1, tableRowObject) + } + }) + } + resetAllHeight(list, 0) + this.tbodyElement && (this.tbodyElement.style.height = totalHeight + "px") + this.treeElement!.style.height = (this.tableElement!.clientHeight - this.theadElement!.clientHeight) + "px" + this.tableElement && (this.tableElement.onscroll = (event) => { + let visibleObjects = this.recycleDs.filter((item) => { + return !item.rowHidden + }) + let top = this.tableElement!.scrollTop; + this.treeElement!.style.transform = `translateY(${top}px)` + let skip = 0; + for (let i = 0; i < visibleObjects.length; i++) { + if (visibleObjects[i].top <= top && visibleObjects[i].top + visibleObjects[i].height >= top) { + skip = i + break; + } + } + let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b,0); + if(reduce == 0){ + return + } + while (reduce <= this.tableElement!.clientHeight) { + let newTableElement = this.createNewTreeTableElement(visibleObjects[skip]); + this.tbodyElement?.append(newTableElement) + if (this.treeElement?.lastChild) { + (this.treeElement?.lastChild as HTMLElement).style.height = visibleObjects[skip].height + "px"; + } + this.currentRecycleList.push(newTableElement) + reduce += newTableElement.clientHeight + } + for (let i = 0; i < this.currentRecycleList.length; i++) { + this.freshCurrentLine(this.currentRecycleList[i], visibleObjects[i + skip], (this.treeElement?.children[i] as HTMLElement)); + } + }) + return visibleObjects + } + + + createNewTreeTableElement(rowData: TableRowObject): any { + let newTableElement = document.createElement('div'); + newTableElement.classList.add('tr'); + let gridTemplateColumns: Array = []; + let treeTop = 0; + if (this.treeElement!.children?.length > 0) { + let transX = Number((this.treeElement?.lastChild as HTMLElement).style.transform.replace(/[^0-9]/ig, "")); + treeTop += (transX + rowData.height) + } + this?.columns?.forEach((column: any, index) => { + let dataIndex = column.getAttribute('data-index') || '1'; + let td: any + if (index === 0) { + if (column.template) { + td = column.template.render(rowData.data).content.cloneNode(true); + td.template = column.template + } else { + td = document.createElement('div') + td.innerHTML = rowData.data[dataIndex]; + td.dataIndex = dataIndex + } + if (rowData.data.children && rowData.data.children.length > 0) { + let btn = this.createExpandBtn(rowData) + td.insertBefore(btn, td.firstChild); + td.style.paddingLeft = rowData.depth * 15 + 'px'; + } else { + td.style.paddingLeft = rowData.depth * 15 + 20 + 'px'; + } + td.classList.add('tree-first-body'); + td.style.position = 'absolute'; + td.style.top = '0px' + td.style.left = '0px' + td.onmouseover = () => { + let indexOf = this.currentTreeDivList.indexOf(td); + if (indexOf >= 0 && indexOf < this.currentRecycleList.length && td.innerHTML != "") { + this.setSelectedRow(true,[(this.treeElement?.children[indexOf] as HTMLElement),newTableElement]); + } + } + td.onmouseout = () => { + let indexOf = this.currentTreeDivList.indexOf(td); + if (indexOf >= 0 && indexOf < this.currentRecycleList.length) { + this.setSelectedRow(false,[(this.treeElement?.children[indexOf] as HTMLElement),newTableElement]); + } + } + td.onclick = () => { + this.dispatchEvent(new CustomEvent('row-click', {detail: {...rowData.data,callBack:(isSelected:boolean)=>{ + let indexOf = this.currentTreeDivList.indexOf(td); + this.setSelectedRow(isSelected,[(this.currentRecycleList[indexOf] as HTMLElement),td]) + }}, composed: true,})); + } + this.treeElement!.style.width = column.getAttribute('width') + this.treeElement?.append(td) + this.currentTreeDivList.push(td) + } else { + gridTemplateColumns.push(column.getAttribute('width') || '1fr') + td = document.createElement('div') + td.classList.add('td'); + // td.style.wordBreak = 'break-all' + td.style.overflow = 'hidden' + td.style.textOverflow = 'ellipsis' + td.style.whiteSpace = "nowrap" + td.title = rowData.data[dataIndex] + // td.innerHTML = rowData.data[dataIndex]; + td.dataIndex = dataIndex + td.style.justifyContent = column.getAttribute('align')||'flex-start' + if (column.template) { + td.appendChild(column.template.render(rowData.data).content.cloneNode(true)); + td.template = column.template + } else { + td.innerHTML = rowData.data[dataIndex]; + } + newTableElement.append(td) + } + }); + (this.treeElement?.lastChild as HTMLElement).style.transform = `translateY(${treeTop}px)`; + newTableElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); + newTableElement.style.position = 'absolute'; + newTableElement.style.top = '0px' + newTableElement.style.left = '0px' + newTableElement.style.cursor = 'pointer' + newTableElement.onmouseover = () => { + let indexOf = this.currentRecycleList.indexOf(newTableElement); + if (indexOf >= 0 && indexOf < this.treeElement!.children.length) { + this.setSelectedRow(true,[(this.treeElement?.children[indexOf] as HTMLElement),newTableElement]); + } + } + newTableElement.onmouseout = () => { + let indexOf = this.currentRecycleList.indexOf(newTableElement); + if (indexOf >= 0 && indexOf < this.treeElement!.children.length) { + this.setSelectedRow(false,[(this.treeElement?.children[indexOf] as HTMLElement),newTableElement]); + } + } + newTableElement.onclick = e => { + this.dispatchEvent(new CustomEvent('row-click', {detail: rowData.data, composed: true})); + } + return newTableElement + } + + createExpandBtn(rowData: any) { + let btn: any = document.createElement('lit-icon'); + btn.classList.add('tree-icon'); + // @ts-ignore + if (rowData.expanded) { + btn.name = 'minus-square'; + } else { + btn.name = 'plus-square'; + } + btn.onclick = (e: Event) => { + const resetNodeHidden = (hidden: boolean, rowData: any) => { + if (rowData.children.length > 0) { + if (hidden) { + rowData.children.forEach((child: any) => { + child.rowHidden = true + resetNodeHidden(hidden, child) + }) + } else { + rowData.children.forEach((child: any) => { + child.rowHidden = !rowData.expanded + if (rowData.expanded) { + resetNodeHidden(hidden, child) + } + }) + } + } + } + const foldNode = () => { + rowData.expanded = false + resetNodeHidden(true, rowData) + }; + const expendNode = () => { + rowData.expanded = true + resetNodeHidden(false, rowData) + } + if (rowData.expanded) { + foldNode() + } else { + expendNode() + } + this.reMeauseHeight() + e.stopPropagation(); + }; + return btn + } + + reMeauseHeight() { + if (this.currentRecycleList.length == 0) { + return + } + let totalHeight = 0 + this.recycleDs.forEach((it) => { + if (!it.rowHidden) { + it.top = totalHeight + totalHeight += it.height + } + }) + this.tbodyElement && (this.tbodyElement.style.height = totalHeight + "px") + this.treeElement!.style.height = (this.tableElement!.clientHeight - this.theadElement!.clientHeight) + "px" + let visibleObjects = this.recycleDs.filter((item) => { + return !item.rowHidden + }) + let top = this.tableElement!.scrollTop; + let skip = 0; + for (let i = 0; i < visibleObjects.length; i++) { + if (visibleObjects[i].top <= top && visibleObjects[i].top + visibleObjects[i].height >= top) { + skip = i + break; + } + } + let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b,0); + if(reduce == 0){ + return + } + while (reduce <= this.tableElement!.clientHeight) { + let newTableElement + if (this.hasAttribute('tree')) { + newTableElement = this.createNewTreeTableElement(visibleObjects[skip]); + } else { + newTableElement = this.createNewTableElement(visibleObjects[skip].data) + } + this.tbodyElement?.append(newTableElement) + if (this.hasAttribute('tree')) { + if (this.treeElement?.lastChild) { + (this.treeElement?.lastChild as HTMLElement).style.height = visibleObjects[skip].height + "px"; + } + } + this.currentRecycleList.push(newTableElement) + reduce += newTableElement.clientHeight + } + for (let i = 0; i < this.currentRecycleList.length; i++) { + if (this.hasAttribute('tree')) { + this.freshCurrentLine(this.currentRecycleList[i], visibleObjects[i + skip], (this.treeElement?.children[i] as HTMLElement)) + } else { + this.freshCurrentLine(this.currentRecycleList[i], visibleObjects[i + skip]) + } + } + } + + createNewTableElement(rowData: any): any { + let newTableElement = document.createElement('div'); + newTableElement.classList.add('tr'); + let gridTemplateColumns: Array = []; + this?.columns?.forEach((column: any) => { + let dataIndex = column.getAttribute('data-index') || '1'; + gridTemplateColumns.push(column.getAttribute('width') || '1fr') + let td: any + td = document.createElement('div') + td.classList.add('td'); + td.style.overflow = 'hidden' + td.style.textOverflow = 'ellipsis' + td.style.whiteSpace = "nowrap" + td.dataIndex = dataIndex + td.style.justifyContent = column.getAttribute('align')||'flex-start' + td.title = rowData[dataIndex] + if (column.template) { + td.appendChild(column.template.render(rowData).content.cloneNode(true)); + td.template = column.template + } else { + td.innerHTML = rowData[dataIndex]; + } + newTableElement.append(td) + }) + newTableElement.onclick = ()=>{ + let detail = {...rowData,selectedCallback:()=>{ + if (detail.isSelected != undefined) { + if(detail.isSelected){ + newTableElement.setAttribute("selected","") + }else { + newTableElement.removeAttribute("selected") + } + rowData.isSelected = !rowData.isSelected + } + }} + this.dispatchEvent(new CustomEvent('row-click', {detail: detail, composed: true})); + } + if (rowData.isSelected != undefined) { + if(rowData.isSelected){ + newTableElement.setAttribute("selected","") + }else { + newTableElement.removeAttribute("selected") + } + } + newTableElement.style.cursor = "pointer" + newTableElement.style.gridTemplateColumns = gridTemplateColumns.join(' '); + newTableElement.style.position = 'absolute'; + newTableElement.style.top = '0px' + newTableElement.style.left = '0px' + return newTableElement + } + + freshCurrentLine(element: HTMLElement, rowObject: TableRowObject, firstElement?: HTMLElement) { + if (!rowObject) { + if (firstElement) { + firstElement.style.display = 'none' + } + element.style.display = 'none' + return + } + let childIndex = -1 + element.childNodes.forEach((child) => { + if(child.nodeType!=1)return + childIndex++; + let idx = firstElement != undefined ? childIndex + 1 : childIndex; + if (firstElement != undefined && childIndex == 0) { + if ((this.columns![0] as any).template) { + firstElement.innerHTML = (this.columns![0] as any).template.render(rowObject.data).content.cloneNode(true).innerHTML + } else { + let dataIndex = this.columns![0].getAttribute('data-index') || '1'; + firstElement.innerHTML = rowObject.data[dataIndex] + firstElement.title = rowObject.data[dataIndex] + } + if (rowObject.children && rowObject.children.length > 0) { + let btn = this.createExpandBtn(rowObject) + firstElement.insertBefore(btn, firstElement.firstChild); + firstElement.style.paddingLeft = 15 * rowObject.depth + "px" + } else { + firstElement.style.paddingLeft = 15 + 20 * rowObject.depth + "px" + } + firstElement.onclick = () => { + this.dispatchEvent(new CustomEvent('row-click', {detail: rowObject.data, composed: true})); + } + firstElement.style.transform = `translateY(${rowObject.top - this.tableElement!.scrollTop}px)` + } + if ((this.columns![idx] as any).template) { + (child as HTMLElement).innerHTML = ""; + (child as HTMLElement).appendChild((this.columns![idx] as any).template.render(rowObject.data).content.cloneNode(true)) + } else { + let dataIndex = this.columns![idx].getAttribute('data-index') || '1'; + (child as HTMLElement).innerHTML = rowObject.data[dataIndex]; + (child as HTMLElement).title = rowObject.data[dataIndex]; + } + }) + if(element.style.display == 'none'){ + element.style.display = 'grid' + } + element.style.transform = `translateY(${rowObject.top}px)` + if (firstElement && firstElement.style.display == 'none') { + firstElement.style.display = 'flex' + } + element.onclick = e => { + let datail = {...rowObject.data,selectedCallback:()=>{ + if (datail.isSelected != undefined) { + if(datail.isSelected){ + element.setAttribute("selected","") + }else { + element.removeAttribute("selected") + } + rowObject.data.isSelected = !rowObject.data.isSelected + } + }} + this.dispatchEvent(new CustomEvent('row-click', {detail: datail, composed: true})); + } + if (rowObject.data.isSelected != undefined) { + if(rowObject.data.isSelected){ + element.setAttribute("selected","") + }else { + element.removeAttribute("selected") + } + }else { + element.removeAttribute("selected") + } + } + + setSelectedRow(isSelected:boolean,rows:any[]){ + if(isSelected){ + rows.forEach((row)=>{ + row.style.backgroundColor = "var(--dark-background6,#DEEDFF)" + }) + }else { + rows.forEach((row)=>{ + row.style.backgroundColor = "var(--dark-background,#FFFFFF)" + }) + } + } +} diff --git a/host/ide/src/base-ui/tabs/lit-tabpane.ts b/host/ide/src/base-ui/tabs/lit-tabpane.ts new file mode 100644 index 0000000000000000000000000000000000000000..1f8c681b7b443bac9f651fe04018fe9d42a8fa4c --- /dev/null +++ b/host/ide/src/base-ui/tabs/lit-tabpane.ts @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import {BaseElement, element} from "../BaseElement.js"; +import {LitTabs} from "./lit-tabs.js"; + +@element('lit-tabpane') +export class LitTabpane extends BaseElement { + static get observedAttributes() { + return ['tab', 'key', 'disabled', 'icon', 'closeable', 'hidden']; + } + + get tab() { + return this.getAttribute('tab'); + } + + set tab(value) { + this.setAttribute("tab", value || ""); + } + + get icon() { + return this.getAttribute("icon"); + } + + get disabled() { + return this.getAttribute('disabled') !== null; + } + + set disabled(value) { + if (value === null || value === false) { + this.removeAttribute("disabled"); + } else { + this.setAttribute("disabled", value + ''); + } + } + + get hidden() { + return this.getAttribute('hidden') !== null; + } + + set hidden(value) { + this.setAttribute("hidden", `${value}`); + } + + get closeable() { + return this.getAttribute('closeable') !== null; + } + + set closeable(value) { + if (value === null || value === false) { + this.removeAttribute("closeable"); + } else { + this.setAttribute("closeable", value + ''); + } + } + + get key() { + return this.getAttribute("key") || ''; + } + + set key(value) { + this.setAttribute("key", value); + } + + initElements(): void { + } + + initHtml(): string { + return ` + + +`; + } + + connectedCallback() { + } + + disconnectedCallback() { + } + + adoptedCallback() { + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + if (oldValue !== newValue && newValue !== undefined) { + if (name === 'tab' && this.parentNode && this.parentNode instanceof LitTabs) { + this.parentNode.updateLabel && this.parentNode.updateLabel(this.key, newValue); + } + if (name === 'disabled' && this.parentNode && this.parentNode instanceof LitTabs) { + this.parentNode.updateDisabled && this.parentNode.updateDisabled(this.key, newValue); + } + if (name === 'closeable' && this.parentNode && this.parentNode instanceof LitTabs) { + this.parentNode.updateCloseable && this.parentNode.updateCloseable(this.key, newValue); + } + if (name === 'hidden' && this.parentNode && this.parentNode instanceof LitTabs) { + this.parentNode.updateHidden && this.parentNode.updateHidden(this.key, newValue); + } + } + } +} diff --git a/host/ide/src/base-ui/tabs/lit-tabs.ts b/host/ide/src/base-ui/tabs/lit-tabs.ts new file mode 100644 index 0000000000000000000000000000000000000000..25d23ce87135cb8799f76519a114911c16c2ce46 --- /dev/null +++ b/host/ide/src/base-ui/tabs/lit-tabs.ts @@ -0,0 +1,646 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {element} from "../BaseElement.js"; +import {LitTabpane} from "./lit-tabpane.js"; + +@element('lit-tabs') +export class LitTabs extends HTMLElement { + private tabPos: any + private nav: HTMLDivElement | undefined | null + private line: HTMLDivElement | undefined | null + private slots: HTMLSlotElement | undefined | null + + constructor() { + super(); + const shadowRoot = this.attachShadow({mode: 'open'}); + shadowRoot.innerHTML = ` + + +
+ +
+ NEED CONTENT +
+
+ ` + } + + static get observedAttributes() { + return ['activekey', 'mode', 'position'] + } + + get position() { + return this.getAttribute('position') || 'top'; + } + + set position(value) { + this.setAttribute('position', value); + } + + get mode() { + return this.getAttribute('mode') || 'flat'; + } + + set mode(value) { + this.setAttribute('mode', value); + } + + get activekey() { + return this.getAttribute("activekey") || ''; + } + + set activekey(value: string) { + this.setAttribute('activekey', value); + } + + set onTabClick(fn: any) { + this.addEventListener('onTabClick', fn); + } + + updateLabel(key: string, value: string) { + if (this.nav) { + let item = this.nav.querySelector(`.nav-item[data-key='${key}']`); + if (item) { + item.querySelector("span")!.innerHTML = value; + this.initTabPos() + } + } + } + + updateDisabled(key: string, value: string) { + if (this.nav) { + let item = this.nav.querySelector(`.nav-item[data-key='${key}']`); + if (item) { + if (value) { + item.setAttribute('data-disabled', '') + } else { + item.removeAttribute('data-disabled'); + } + this.initTabPos() + } + } + } + + updateCloseable(key: string, value: string) { + if (this.nav) { + let item = this.nav.querySelector(`.nav-item[data-key='${key}']`); + if (item) { + if (value) { + item.setAttribute('data-closeable', '') + } else { + item.removeAttribute('data-closeable'); + } + this.initTabPos() + } + } + } + + updateHidden(key: string, value: string) { + if (this.nav) { + let item = this.nav.querySelector(`.nav-item[data-key='${key}']`); + if (item) { + if (value === "true") { + item.setAttribute('data-hidden', '') + } else { + item.removeAttribute('data-hidden'); + } + this.initTabPos() + } + } + } + + initTabPos() { + const items = this.nav!.querySelectorAll(".nav-item"); + Array.from(items).forEach((a, index) => { + // @ts-ignore + this.tabPos[a.dataset.key] = { + index: index, + width: a.offsetWidth, + height: a.offsetHeight, + left: a.offsetLeft, + top: a.offsetTop, + label: a.textContent + } + }) + if (this.activekey) { + if (this.position.startsWith('left')) { + this.line?.setAttribute('style', `height:${this.tabPos[this.activekey].height}px;transform:translate(100%,${this.tabPos[this.activekey].top}px)`); + } else if (this.position.startsWith('top')) { + if (this.tabPos[this.activekey]) { + this.line?.setAttribute('style', `width:${this.tabPos[this.activekey].width}px;transform:translate(${this.tabPos[this.activekey].left}px,100%)`); + } + } else if (this.position.startsWith('right')) { + this.line?.setAttribute('style', `height:${this.tabPos[this.activekey].height}px;transform:translate(-100%,${this.tabPos[this.activekey].top}px)`); + } else if (this.position.startsWith('bottom')) { + this.line?.setAttribute('style', `width:${this.tabPos[this.activekey].width}px;transform:translate(${this.tabPos[this.activekey].left}px,100%)`); + } + } + } + + connectedCallback() { + let that = this; + this.tabPos = {} + this.nav = this.shadowRoot?.querySelector('#nav') + this.line = this.shadowRoot?.querySelector('#tab-line') + this.slots = this.shadowRoot?.querySelector('#slot'); + this.slots?.addEventListener('slotchange', () => { + const elements: Element[] | undefined = this.slots?.assignedElements(); + let panes = this.querySelectorAll('lit-tabpane'); + if (this.activekey) { + panes.forEach(a => { + if (a.key === this.activekey) { + a.style.display = 'block' + } else { + a.style.display = 'none'; + } + }) + } else { + panes.forEach((a, index) => { + if (index === 0) { + a.style.display = 'block' + this.activekey = a.key || '' + } else { + a.style.display = 'none'; + } + }) + } + let navHtml = ""; + elements?.map(it => it as LitTabpane).forEach(a => { + if (a.disabled) { + navHtml += ``; + } else if (a.hidden) { + navHtml += ``; + } else { + if (a.key === this.activekey) { + navHtml += ``; + } else { + navHtml += ``; + } + + } + }) + this.nav!.innerHTML = navHtml; + this.initTabPos() + this.nav!.querySelectorAll('.close-icon').forEach(a => { + a.onclick = (e) => { + e.stopPropagation(); + const closeKey = (e.target! as HTMLElement).parentElement!.dataset.key; + this.dispatchEvent(new CustomEvent('close-handler', {detail: {key: closeKey}, composed: true})); + } + }); + }) + this.nav!.onclick = (e) => { + if ((e.target! as HTMLElement).closest('div')!.hasAttribute('data-disabled')) return; + let key = (e.target! as HTMLElement).closest('div')!.dataset.key; + if (key) { + this.activeByKey(key) + } + let label = (e.target! as HTMLElement).closest('div')!.querySelector('span')!.textContent; + this.dispatchEvent(new CustomEvent('onTabClick', {detail: {key: key, tab: label}})) + }; + } + + activeByKey(key: string) { + if (key === null || key === undefined) return; //如果没有key 不做相应 + this.nav!.querySelectorAll('.nav-item').forEach(a => { + if (a.getAttribute('data-key') === key) { + a.setAttribute('data-selected', 'true'); + } else { + a.removeAttribute('data-selected'); + } + }) + let tbp = this.querySelector(`lit-tabpane[key='${key}']`); + let panes = this.querySelectorAll('lit-tabpane'); + panes.forEach(a => { + if (a.key === key) { + a.style.display = 'block'; + this.activekey = a.key; + this.initTabPos() + } else { + a.style.display = 'none'; + } + }) + } + + activePane(key: string) { + if (key === null || key === undefined) return false; + let tbp = this.querySelector(`lit-tabpane[key='${key}']`); + if (tbp) { + this.activeByKey(key) + return true; + } else { + return false; + } + } + + disconnectedCallback() { + + } + + adoptedCallback() { + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + if (name === 'activekey' && this.nav && oldValue !== newValue && newValue != '') { + this.activeByKey(newValue) + } + } +} + diff --git a/host/ide/src/base-ui/utils/Template.ts b/host/ide/src/base-ui/utils/Template.ts new file mode 100644 index 0000000000000000000000000000000000000000..18925a4b712269d2ad9fd51b82bb26fbc9acfd9d --- /dev/null +++ b/host/ide/src/base-ui/utils/Template.ts @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const propsMap: string[] = ['disabled', 'hidden', 'checked', 'selected', 'required', 'open', 'readonly']; + +declare interface HTMLTemplateElement { + render(data: any): any +} + +(HTMLTemplateElement as any).prototype.render = function (data: any) { + if (!this.$fragment) { + const rule = this.getAttribute("rule") || 'v-'; + this.$fragment = this.cloneNode(true); + this.fragment = document.createElement('TEMPLATE'); + + // v-for Loop rendering + //
=> ${ list.map(function(item,index){ return '
' }).join('') } + const repeatEls = this.$fragment.content.querySelectorAll(`[\\${rule}for]`); + repeatEls.forEach((el: any) => { + const strFor = el.getAttribute(`${rule}for`); + const {isArray, items, params} = parseFor(strFor); + el.before('${Object.entries(' + items + ').map(function([' + `${(isArray ? '$index$' : (params[1] || 'name'))},${params[0] || (isArray ? 'item' : 'value')}],${params[2] || 'index'}` + '){ return `'); + el.removeAttribute(`${rule}for`); + el.after('`}).join("")}'); + }) + + // v-if Conditional rendering + //
=> ${ if ? '
' : '' } + const ifEls = this.$fragment.content.querySelectorAll(`[\\${rule}if]`); + ifEls.forEach((el: any) => { + const ifs = el.getAttribute(`${rule}if`); + el.before('${' + ifs + '?`'); + el.removeAttribute(`${rule}if`); + el.after('`:``}'); + }) + + // fragment aa => aa + const fragments = this.$fragment.content.querySelectorAll('fragment,block'); + fragments.forEach((el: any) => { + el.after(el.innerHTML); + el.parentNode.removeChild(el); + }) + } + this.fragment.innerHTML = this.$fragment.innerHTML.interpolate(data); + + // props + const propsEls = this.fragment.content.querySelectorAll(`[${propsMap.join('],[')}]`); + propsEls.forEach((el: any) => { + propsMap.forEach((props: any) => { + // If these attribute values are false, they are removed directly + if (el.getAttribute(props) === 'false') { + el.removeAttribute(props); + } + }) + }) + return this.fragment; +} + +function parseFor(strFor: String) { + // Whether it is an object + const isObject = strFor.includes(' of '); + const reg = /\s(?:in|of)\s/g; + const [keys, obj] = strFor.match(reg) ? strFor.split(reg) : ["item", strFor]; + const items = Number(obj) > 0 ? `[${'null,'.repeat(Number(obj) - 1)}null]` : obj; + const params = keys.split(/[\(|\)|,\s?]/g).filter(Boolean); + return {isArray: !isObject, items, params} +} + +// String to template string +(String as any).prototype.interpolate = function (params: any) { + const names = Object.keys(params); + const vals = Object.values(params); + const str = this.replace(/\{\{([^\}]+)\}\}/g, (all: any, s: any) => `\${${s}}`); + return new Function(...names, `return \`${escape2Html(str)}\`;`)(...vals); +}; + +// HTML Character inversion meaning < => < +function escape2Html(str: string) { + let arrEntities: any = {'lt': '<', 'gt': '>', 'nbsp': ' ', 'amp': '&', 'quot': '"'}; + return str.replace(/&(lt|gt|nbsp|amp|quot);/ig, function (all, t) { + return arrEntities[t]; + }); +} diff --git a/host/ide/src/icon.svg b/host/ide/src/icon.svg new file mode 100644 index 0000000000000000000000000000000000000000..168c113b584dbbbfb6a69687e65adf634768dd8b --- /dev/null +++ b/host/ide/src/icon.svg @@ -0,0 +1 @@ + diff --git a/host/ide/src/img/copy.png b/host/ide/src/img/copy.png new file mode 100644 index 0000000000000000000000000000000000000000..be910ccc40175ea1452faa36d44725662aaea3d5 Binary files /dev/null and b/host/ide/src/img/copy.png differ diff --git a/host/ide/src/img/dark_pic.png b/host/ide/src/img/dark_pic.png new file mode 100644 index 0000000000000000000000000000000000000000..508917c210653e638a13c8eae2c28bba5daad3cc Binary files /dev/null and b/host/ide/src/img/dark_pic.png differ diff --git a/host/ide/src/img/function.png b/host/ide/src/img/function.png new file mode 100644 index 0000000000000000000000000000000000000000..f68381ff4ad756c6a3ddd60b2c219deb80aeb0cc Binary files /dev/null and b/host/ide/src/img/function.png differ diff --git a/host/ide/src/img/library.png b/host/ide/src/img/library.png new file mode 100644 index 0000000000000000000000000000000000000000..c10c520ee27346318c2db99586543dc1d12810ef Binary files /dev/null and b/host/ide/src/img/library.png differ diff --git a/host/ide/src/img/logo.png b/host/ide/src/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..725db32f13c43af3ede6c3e5fe2fa51e2c0ad263 Binary files /dev/null and b/host/ide/src/img/logo.png differ diff --git a/host/ide/src/img/pic.png b/host/ide/src/img/pic.png new file mode 100644 index 0000000000000000000000000000000000000000..5ed51ecbf5c94788e37a11485045558f8c64dd2e Binary files /dev/null and b/host/ide/src/img/pic.png differ diff --git a/host/ide/src/index.html b/host/ide/src/index.html new file mode 100644 index 0000000000000000000000000000000000000000..dc1753f754d8fbc46869cf0a633dc885ebf78b4f --- /dev/null +++ b/host/ide/src/index.html @@ -0,0 +1,47 @@ + + + + Trace Example + + + + + + + + + diff --git a/host/ide/src/log/Log.ts b/host/ide/src/log/Log.ts new file mode 100644 index 0000000000000000000000000000000000000000..d74cbc3c54c78cbd2232564ad2e43cb4857afe47 --- /dev/null +++ b/host/ide/src/log/Log.ts @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export enum LogLevel { + OFF = Number.MAX_VALUE, + ERROR = 4000, + WARN = 3000, + INFO = 2000, + DEBUG = 1000, + TRACE = 500, + ALL = Number.MIN_VALUE +} + +export const error = (message?: any, ...optionalParams: any[]) => { + SpLog.logger(LogLevel.ERROR, message, ...optionalParams); +}; +export const warn = (message?: any, ...optionalParams: any[]) => { + SpLog.logger(LogLevel.WARN, message, ...optionalParams); +}; +export const info = (message?: any, ...optionalParams: any[]) => { + SpLog.logger(LogLevel.INFO, message, ...optionalParams); +}; +export const debug = (message?: any, ...optionalParams: any[]) => { + SpLog.logger(LogLevel.DEBUG, message, ...optionalParams); +}; +export const trace = (message?: any, ...optionalParams: any[]) => { + SpLog.logger(LogLevel.TRACE, message, ...optionalParams); +}; +export const log = (message?: any) => { + SpLog.logger(LogLevel.TRACE, message) +} + +class SpLog { + private static nowLogLevel: LogLevel = LogLevel.ALL; + + public static getNowLogLevel(): LogLevel { + return this.nowLogLevel; + } + + public static setLogLevel(logLevel: LogLevel) { + SpLog.nowLogLevel = logLevel; + } + + public static logger(logLevel: LogLevel, message?: any, ...optionalParams: any[]) { + if (logLevel >= SpLog.nowLogLevel) { + switch (logLevel) { + case LogLevel.ERROR: + console.error(message, ...optionalParams) + break + case LogLevel.WARN: + console.warn(message, ...optionalParams) + break + case LogLevel.INFO: + console.info(message, ...optionalParams) + break + case LogLevel.DEBUG: + console.debug(message, ...optionalParams) + break + case LogLevel.TRACE: + console.trace(message, ...optionalParams) + break + default: + console.log(message) + } + } + } +} + + diff --git a/host/ide/src/trace/SpApplication.ts b/host/ide/src/trace/SpApplication.ts new file mode 100644 index 0000000000000000000000000000000000000000..b5e8eff0a96fc1f0ff8594b3c807c19199257654 --- /dev/null +++ b/host/ide/src/trace/SpApplication.ts @@ -0,0 +1,619 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../base-ui/BaseElement.js"; +import "../base-ui/menu/LitMainMenu.js"; +import "../base-ui/icon/LitIcon.js"; +import {SpMetrics} from "./component/SpMetrics.js"; +import {SpQuerySQL} from "./component/SpQuerySQL.js"; +import "./component/SpQuerySQL.js"; +import {SpSystemTrace} from "./component/SpSystemTrace.js"; +import {LitMainMenu, MenuItem} from "../base-ui/menu/LitMainMenu.js"; +import {SpInfoAndStats} from "./component/SpInfoAndStas.js"; +import "../base-ui/progress-bar/LitProgressBar.js"; +import {LitProgressBar} from "../base-ui/progress-bar/LitProgressBar.js"; +import {SpRecordTrace} from "./component/SpRecordTrace.js"; +import {SpWelcomePage} from "./component/SpWelcomePage.js"; +import {LitSearch} from "./component/trace/search/Search.js"; +import {threadPool} from "./database/SqlLite.js"; +import "./component/trace/search/Search.js"; +import "./component/SpWelcomePage.js"; +import "./component/SpSystemTrace.js"; +import "./component/SpRecordTrace.js"; +import {TraceRow} from "./component/trace/base/TraceRow.js"; + +@element('sp-application') +export class SpApplication extends BaseElement { + static skinChange: Function | null | undefined = null; + static skinChange2: Function | null | undefined = null; + skinChangeArray: Array = []; + private icon: HTMLDivElement | undefined | null + private rootEL: HTMLDivElement | undefined | null + + static get observedAttributes() { + return ["server", "sqlite", "wasm", "dark", "vs", "query-sql"] + } + + get dark() { + return this.hasAttribute('dark'); + } + + set dark(value) { + if (value) { + this.rootEL!.classList.add('dark'); + this.setAttribute('dark', ''); + } else { + this.rootEL!.classList.remove('dark'); + this.removeAttribute('dark'); + } + if (this.skinChangeArray.length > 0) { + this.skinChangeArray.forEach((item) => item(value)); + } + if (SpApplication.skinChange) { + SpApplication.skinChange(value); + } + if (SpApplication.skinChange2) { + SpApplication.skinChange2(value); + } + } + + get vs(): boolean { + return this.hasAttribute("vs") + } + + set vs(isVs: boolean) { + if (isVs) { + this.setAttribute("vs", "") + } + } + + get sqlite(): boolean { + return this.hasAttribute("sqlite") + } + + get wasm(): boolean { + return this.hasAttribute("wasm") + } + + get server(): boolean { + return this.hasAttribute("server") + } + + get querySql(): boolean { + return this.hasAttribute("query-sql") + } + + set server(s: boolean) { + if (s) { + this.setAttribute('server', '') + } else { + this.removeAttribute('server') + } + } + + set search(search: boolean) { + if (search) { + this.setAttribute('search', '') + } else { + this.removeAttribute('search') + } + } + + addSkinListener(handler: Function) { + this.skinChangeArray.push(handler) + }; + + removeSkinListener(handler: Function) { + this.skinChangeArray.splice(this.skinChangeArray.indexOf(handler), 1); + }; + + initHtml(): string { + return ` + +
+ +
+ + +
+
+ + + + +
+
+ `; + } + + initElements() { + let that = this; + this.rootEL = this.shadowRoot!.querySelector(".root") + let spWelcomePage = this.shadowRoot!.querySelector("#sp-welcome") as SpWelcomePage + let spMetrics = new SpMetrics(); + let spSystemTrace = this.shadowRoot!.querySelector("#sp-system-trace") + let spInfoAndStats = new SpInfoAndStats(); + let spRecordTrace = this.shadowRoot!.querySelector("#sp-record-trace") + let spQuerySQL = this.shadowRoot!.querySelector("#sp-query-sql") + let appContent = this.shadowRoot?.querySelector('#app-content') as HTMLDivElement; + let mainMenu = this.shadowRoot?.querySelector('#main-menu') as LitMainMenu + let progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar + let litSearch = this.shadowRoot?.querySelector('#lit-search') as LitSearch + let sidebarButton: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('.sidebar-button') + let childNodes = [spSystemTrace, spRecordTrace, spWelcomePage, spQuerySQL] + litSearch.addEventListener("focus", () => { + spSystemTrace!.keyboardEnable = false + }) + litSearch.addEventListener('blur', () => { + spSystemTrace!.keyboardEnable = true + }) + litSearch.addEventListener("previous-data", (ev: any) => { + litSearch.index = spSystemTrace!.showPreCpuStruct(litSearch.index,litSearch.list); + litSearch.blur(); + }) + litSearch.addEventListener("next-data", (ev: any) => { + litSearch.index = spSystemTrace!.showNextCpuStruct(litSearch.index,litSearch.list); + litSearch.blur(); + // spSystemTrace!.search(e.detail.value) + }) + litSearch.valueChangeHandler = (value: string) => { + if (value.length > 0) { + litSearch.list = spSystemTrace!.searchCPU(value); + } else { + litSearch.list = []; + spSystemTrace?.visibleRows.forEach(it => { + it.highlight = false; + it.draw(); + }); + spSystemTrace?.timerShaftEL?.removeTriangle("inverted"); + } + } + spSystemTrace?.addEventListener("previous-data", (ev: any) => { + litSearch.index = spSystemTrace!.showPreCpuStruct(litSearch.index, litSearch.list); + }) + spSystemTrace?.addEventListener("next-data", (ev: any) => { + litSearch.index = spSystemTrace!.showNextCpuStruct(litSearch.index, litSearch.list); + }) + //打开侧边栏 + sidebarButton!.onclick = (e) => { + let menu: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('#main-menu') + let menuButton: HTMLElement | undefined | null = this.shadowRoot?.querySelector('.sidebar-button') + if (menu) { + menu.style.width = `248px` + // @ts-ignore + menu.style.zIndex = 2000; + menu.style.display = `flex` + } + if (menuButton) { + menuButton.style.width = `0px` + } + } + let icon: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector("#main-menu")?.shadowRoot?.querySelector("div.header > div") + icon!.onclick = (e) => { + let menu: HTMLElement | undefined | null = this.shadowRoot?.querySelector("#main-menu") + let menuButton: HTMLElement | undefined | null = this.shadowRoot?.querySelector('.sidebar-button') + if (menu) { + menu.style.width = `0px` + menu.style.display = `flex` + // @ts-ignore + menu.style.zIndex = 0 + } + if (menuButton) { + menuButton.style.width = `48px` + } + } + + function showContent(showNode: HTMLElement) { + childNodes.forEach((node) => { + if (node === showNode) { + showNode.style.visibility = 'visible' + } else { + node!.style.visibility = 'hidden' + } + }) + } + + function openTraceFile(ev: any) { + litSearch.clear(); + showContent(spSystemTrace!) + that.search = true + progressEL.loading = true + let fileName = (ev as any).name + let fileSize = ((ev as any).size / 1000000).toFixed(1) + document.title = `${fileName.substring(0, fileName.lastIndexOf('.'))} (${fileSize}M)` + if (that.server) { + threadPool.init("server").then(() => { + litSearch.setPercent("parse trace", 1); + // Load the trace file and send it to the background parse to return the db file path + const fd = new FormData() + that.freshMenuDisable(true) + fd.append('file', ev as any) + let uploadPath = `https://${window.location.host.split(':')[0]}:9001/upload` + if (that.vs) { + uploadPath = `http://${window.location.host.split(':')[0]}:${window.location.port}/upload` + } + fetch(uploadPath, { + method: 'POST', + body: fd, + }).then(res => { + litSearch.setPercent("load database", 5); + if (res.ok) { + let menus = [ + { + title: `${fileName.substring(0, fileName.lastIndexOf('.'))} (${fileSize}M)`, + icon: "file-fill", + clickHandler: function () { + that.search = true + showContent(spSystemTrace!) + } + } + ]; + if (that.querySql) { + menus.push({ + title: "Query (SQL)", icon: "file", clickHandler: () => { + showContent(spQuerySQL!) + } + }); + } + mainMenu.menus!.splice(1, 1, { + collapsed: false, + title: "Current Trace", + describe: "Actions on the current trace", + children: menus + }) + + that.freshMenuDisable(true) + return res.text(); + } else { + if (res.status == 404) { + litSearch.setPercent("This File is not supported!", -1) + progressEL.loading = false; + that.freshMenuDisable(false) + return Promise.reject(); + } + } + }).then(res => { + if (res != undefined) { + let loadPath = `https://${window.location.host.split(':')[0]}:9001` + if (that.vs) { + loadPath = `http://${window.location.host.split(':')[0]}:${window.location.port}` + } + spSystemTrace!.loadDatabaseUrl(loadPath + res, (command: string, percent: number) => { + litSearch.setPercent(command + ' ', percent); + }, (res) => { + litSearch.setPercent("", 101); + progressEL.loading = false; + that.freshMenuDisable(false) + }) + } else { + litSearch.setPercent("", 101) + progressEL.loading = false; + that.freshMenuDisable(false) + } + + }) + }) + return; + } + if (that.sqlite) { + litSearch.setPercent("", 0); + threadPool.init("sqlite").then(res => { + let reader = new FileReader(); + reader.readAsArrayBuffer(ev as any) + reader.onloadend = function (ev) { + spSystemTrace!.loadDatabaseArrayBuffer(this.result as ArrayBuffer, (command: string, percent: number) => { + litSearch.setPercent(command + ' ', percent); + }, () => { + litSearch.setPercent("", 101); + progressEL.loading = false; + that.freshMenuDisable(false) + }) + } + }) + return; + } + if (that.wasm) { + litSearch.setPercent("", 1); + threadPool.init("wasm").then(res => { + let reader = new FileReader(); + reader.readAsArrayBuffer(ev as any) + reader.onloadend = function (ev) { + litSearch.setPercent("ArrayBuffer loaded ", 2); + that.freshMenuDisable(true) + let menus = [ + { + title: `${fileName.substring(0, fileName.lastIndexOf('.'))} (${fileSize}M)`, + icon: "file-fill", + clickHandler: function () { + that.search = true + showContent(spSystemTrace!) + } + } + ]; + if (that.querySql) { + menus.push({ + title: "Query (SQL)", icon: "file", clickHandler: () => { + showContent(spQuerySQL!) + } + }); + } + mainMenu.menus!.splice(1, 1, { + collapsed: false, + title: "Current Trace", + describe: "Actions on the current trace", + children: menus + }) + spSystemTrace!.loadDatabaseArrayBuffer(this.result as ArrayBuffer, (command: string, percent: number) => { + litSearch.setPercent(command + ' ', percent); + }, (res) => { + if (res.status) { + litSearch.setPercent("", 101); + progressEL.loading = false; + that.freshMenuDisable(false) + } else { + litSearch.setPercent("This File is not supported!", -1) + progressEL.loading = false; + that.freshMenuDisable(false) + mainMenu.menus!.splice(1, 1); + mainMenu.menus = mainMenu.menus!; + } + }) + } + }) + return; + } + } + + mainMenu.menus = [ + { + collapsed: false, + title: 'Navigation', + describe: 'Open or record a new trace', + children: [ + { + title: "Open trace file", + icon: "folder", + fileChoose: true, + fileHandler: function (ev: InputEvent) { + openTraceFile(ev.detail as any); + } + }, + { + title: "Record new trace", icon: "copyhovered", clickHandler: function (item: MenuItem) { + that.search = false + showContent(spRecordTrace!) + } + } + ] + }, + ] + + let body = document.querySelector("body"); + body!.addEventListener('dragover', (e: any) => { + e.preventDefault(); + e.stopPropagation(); + if (e.dataTransfer.items.length > 0 && e.dataTransfer.items[0].kind === "file") { + e.dataTransfer.dropEffect = 'copy'; + if (!this.rootEL!.classList.contains('filedrag')) { + this.rootEL!.classList.add("filedrag") + } + } + }, false); + body!.addEventListener("dragleave", (e) => { + e.stopPropagation(); + e.preventDefault(); + if (this.rootEL!.classList.contains('filedrag')) { + this.rootEL!.classList.remove("filedrag") + } + }, false); + body!.addEventListener('drop', (e: any) => { + e.preventDefault(); + e.stopPropagation(); + if (this.rootEL!.classList.contains('filedrag')) { + this.rootEL!.classList.remove("filedrag") + } + if (e.dataTransfer.items !== undefined && e.dataTransfer.items.length > 0) { + let item = e.dataTransfer.items[0]; + if (item.webkitGetAsEntry()?.isFile) { + openTraceFile(item.getAsFile()); + } else if (item.webkitGetAsEntry()?.isDirectory) { + litSearch.setPercent("This File is not supported!", -1) + progressEL.loading = false; + that.freshMenuDisable(false) + mainMenu.menus!.splice(1, 1); + mainMenu.menus = mainMenu.menus!; + spSystemTrace!.reset(null); + } + } + }, false); + } + + freshMenuDisable(disable: boolean) { + let mainMenu = this.shadowRoot?.querySelector('#main-menu') as LitMainMenu + // @ts-ignore + mainMenu.menus[0].children[0].disabled = disable + mainMenu.menus = mainMenu.menus; + } +} diff --git a/host/ide/src/trace/bean/BaseStruct.ts b/host/ide/src/trace/bean/BaseStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..eccd75ca575ce9cf43589179d1125ab341853950 --- /dev/null +++ b/host/ide/src/trace/bean/BaseStruct.ts @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {Rect} from "../component/trace/timer-shaft/Rect.js"; + +export class BaseStruct { + frame: Rect | undefined + isHover: boolean = false; +} diff --git a/host/ide/src/trace/bean/BinderArgBean.ts b/host/ide/src/trace/bean/BinderArgBean.ts new file mode 100644 index 0000000000000000000000000000000000000000..b119d214be921ea42d58c652b28dd27983dab8ba --- /dev/null +++ b/host/ide/src/trace/bean/BinderArgBean.ts @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class BinderArgBean { + argset: number | undefined + keyName: string | undefined + id: number | undefined + desc: string | undefined + strValue: string | undefined +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/BoxSelection.ts b/host/ide/src/trace/bean/BoxSelection.ts new file mode 100644 index 0000000000000000000000000000000000000000..788e3c1c035ae492fc446c81462967b02bcac4c2 --- /dev/null +++ b/host/ide/src/trace/bean/BoxSelection.ts @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class SelectionParam { + cpus: Array = []; + threadIds: Array = []; + trackIds: Array = []; + funTids: Array = []; + heapIds: Array = []; + nativeMemory:Array = []; + leftNs: number = 0; + rightNs: number = 0; + hasFps: boolean = false; + statisticsSelectData:any = undefined +} + +export class BoxJumpParam { + leftNs: number = 0; + rightNs: number = 0; + state: string = ""; + processId: number = 0; + threadId: number = 0; +} + +export class SelectionData { + name: string = "" + process: string = "" + pid: string = "" + thread: string = "" + tid: string = "" + wallDuration: number = 0 + avgDuration: string = "" + occurrences: number = 0 + state: string = "" + trackId: number = 0 + delta: string = "" + rate: string = "" + avgWeight: string = "" + count: string = "" + first: string = "" + last: string = "" + min: string = "" + max: string = "" + stateJX: string = "" +} + +export class Counter { + id: number = 0 + trackId: number = 0 + name: string = "" + value: number = 0 + startTime: number = 0 +} + +export class Fps { + startNS: number = 0 + timeStr: string = "" + fps: number = 0 +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/CpuFreqStruct.ts b/host/ide/src/trace/bean/CpuFreqStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..19d3ed70fb9637762eddf36a2824d4aa5ffa9e0e --- /dev/null +++ b/host/ide/src/trace/bean/CpuFreqStruct.ts @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct} from "./BaseStruct.js"; +import {ColorUtils} from "../database/ProcedureWorkerCommon.js"; + +export class CpuFreqStruct extends BaseStruct { + static maxFreq: number = 0 + static maxFreqName: string = "0 GHz" + static hoverCpuFreqStruct: CpuFreqStruct | undefined; + static selectCpuFreqStruct: CpuFreqStruct | undefined; + cpu: number | undefined + value: number | undefined + startNS: number | undefined + dur: number | undefined // Self-supplementing, the database is not returned + + static draw(ctx: any, data: CpuFreqStruct) { + if (data.frame) { + let width = data.frame.width || 0; + let index = data.cpu || 0 + index += 2 + ctx.fillStyle = ColorUtils.colorForTid(index) + ctx.strokeStyle = ColorUtils.colorForTid(index) + if (data.startNS === CpuFreqStruct.hoverCpuFreqStruct?.startNS) { + ctx.lineWidth = 1; + ctx.globalAlpha = 0.6; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / CpuFreqStruct.maxFreq); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + ctx.beginPath() + ctx.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true) + ctx.fill() + ctx.globalAlpha = 1.0; + ctx.stroke(); + ctx.beginPath() + ctx.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight); + ctx.lineWidth = 3; + ctx.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight) + ctx.stroke(); + } else { + ctx.globalAlpha = 0.6; + ctx.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / CpuFreqStruct.maxFreq); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + } + } + ctx.globalAlpha = 1.0; + ctx.lineWidth = 1; + } +} + +const textPadding = 2; + diff --git a/host/ide/src/trace/bean/CpuStruct.ts b/host/ide/src/trace/bean/CpuStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..3a86a4daca85ef132c0600e7d8844c2d9af60741 --- /dev/null +++ b/host/ide/src/trace/bean/CpuStruct.ts @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {ColorUtils} from "../component/trace/base/ColorUtils.js"; +import {BaseStruct} from "./BaseStruct.js"; +import {WakeupBean} from "./WakeupBean.js"; + +export class CpuStruct extends BaseStruct { + static cpuCount: number //最大cpu数量 + static hoverCpuStruct: CpuStruct | undefined; + static selectCpuStruct: CpuStruct | undefined; + static wakeupBean: WakeupBean | null | undefined = null; + cpu: number | undefined + dur: number | undefined + end_state: string | undefined + id: number | undefined + name: string | undefined + priority: number | undefined + processCmdLine: string | undefined + processId: number | undefined + processName: string | undefined + schedId: number | undefined + startTime: number | undefined + tid: number | undefined + type: string | undefined + + static draw(ctx: CanvasRenderingContext2D, data: CpuStruct) { + if (data.frame) { + let width = data.frame.width || 0; + if (data.processId === CpuStruct.hoverCpuStruct?.processId || !CpuStruct.hoverCpuStruct) { + ctx.fillStyle = ColorUtils.colorForTid((data.processId || 0) > 0 ? (data.processId || 0) : (data.tid || 0)) + } else { + ctx.fillStyle = "#e0e0e0" + } + ctx.fillRect(data.frame.x, data.frame.y, width, data.frame.height) + if (width > textPadding * 2) { + let process = `${(data.processName || "Process")} [${data.processId}]` + let thread = `${data.name || "Thread"} [${data.tid}]` + let processMeasure = ctx.measureText(process); + let threadMeasure = ctx.measureText(thread); + let processCharWidth = Math.round(processMeasure.width / process.length) + let threadCharWidth = Math.round(threadMeasure.width / thread.length) + ctx.fillStyle = "#ffffff" + let y = data.frame.height / 2 + data.frame.y; + if (processMeasure.width < width - textPadding * 2) { + let x1 = Math.floor(width / 2 - processMeasure.width / 2 + data.frame.x + textPadding) + ctx.textBaseline = "bottom"; + ctx.fillText(process, x1, y, width - textPadding * 2) + } else if (width - textPadding * 2 > processCharWidth * 4) { + let chatNum = (width - textPadding * 2) / processCharWidth; + let x1 = data.frame.x + textPadding + ctx.textBaseline = "bottom"; + ctx.fillText(process.substring(0, chatNum - 4) + '...', x1, y, width - textPadding * 2) + } + if (threadMeasure.width < width - textPadding * 2) { + ctx.textBaseline = "top"; + let x2 = Math.floor(width / 2 - threadMeasure.width / 2 + data.frame.x + textPadding) + ctx.fillText(thread, x2, y + 2, width - textPadding * 2) + } else if (width - textPadding * 2 > threadCharWidth * 4) { + let chatNum = (width - textPadding * 2) / threadCharWidth; + let x1 = data.frame.x + textPadding + ctx.textBaseline = "top"; + ctx.fillText(thread.substring(0, chatNum - 4) + '...', x1, y + 2, width - textPadding * 2) + } + } + if (CpuStruct.selectCpuStruct && CpuStruct.equals(CpuStruct.selectCpuStruct, data)) { + ctx.strokeStyle = '#232c5d' + ctx.lineWidth = 2 + ctx.strokeRect(data.frame.x, data.frame.y, width - 2, data.frame.height) + } + } + } + + static equals(d1: CpuStruct, d2: CpuStruct): boolean { + if (d1 && d2 && d1.cpu == d2.cpu && + d1.tid == d2.tid && + d1.processId == d2.processId && + d1.startTime == d2.startTime && + d1.dur == d2.dur) { + return true; + } else { + return false; + } + } +} + +const textPadding = 2; + diff --git a/host/ide/src/trace/bean/CpuUsage.ts b/host/ide/src/trace/bean/CpuUsage.ts new file mode 100644 index 0000000000000000000000000000000000000000..63a6e8bdbf9180da0c178f05babc309dfca03fb2 --- /dev/null +++ b/host/ide/src/trace/bean/CpuUsage.ts @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class CpuUsage { + cpu: number = 0 + usage: number = 0 + usageStr: string = "" + top1: number = 0 + top2: number = 0 + top3: number = 0 + top1Percent: number = 0 + top1PercentStr: string = "" + top2Percent: number = 0 + top2PercentStr: string = "" + top3Percent: number = 0 + top3PercentStr: string = "" +} + +export class Freq { + cpu: number = 0 + value: number = 0 + startNs: number = 0 + dur: number = 0 +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/FpsStruct.ts b/host/ide/src/trace/bean/FpsStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..f4e97dc14c4aadad924a9ecba55b284e91459241 --- /dev/null +++ b/host/ide/src/trace/bean/FpsStruct.ts @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {Rect} from "../component/trace/timer-shaft/Rect.js"; +import {BaseStruct} from "./BaseStruct.js"; + +import {ns2x} from "../component/trace/TimerShaftElement.js"; + +export class FpsStruct extends BaseStruct { + static maxFps: number = 0 + static maxFpsName: string = "0 FPS" + static hoverFpsStruct: FpsStruct | undefined; + static selectFpsStruct: FpsStruct | undefined; + fps: number | undefined + startNS: number | undefined = 0 + dur: number | undefined //自补充,数据库没有返回 + + static draw(ctx: CanvasRenderingContext2D, data: FpsStruct) { + if (data.frame) { + let width = data.frame.width || 0; + ctx.fillStyle = '#535da6' + ctx.strokeStyle = '#535da6' + if (data.startNS === FpsStruct.hoverFpsStruct?.startNS) { + ctx.lineWidth = 1; + ctx.globalAlpha = 0.6; + let drawHeight: number = ((data.fps || 0) * (data.frame.height || 0) * 1.0) / FpsStruct.maxFps; + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + ctx.beginPath() + ctx.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true) + ctx.fill() + ctx.globalAlpha = 1.0; + ctx.stroke(); + ctx.beginPath() + ctx.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight); + ctx.lineWidth = 3; + ctx.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight) + ctx.stroke(); + } else { + ctx.globalAlpha = 0.6; + ctx.lineWidth = 1; + let drawHeight: number = ((data.fps || 0) * (data.frame.height || 0) * 1.0) / FpsStruct.maxFps; + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + } + } + ctx.globalAlpha = 1.0; + ctx.lineWidth = 1; + } + + static setFrame(node: FpsStruct, padding: number, startNS: number, endNS: number, totalNS: number, frame: Rect) { + let x1: number, x2: number; + if ((node.startNS || 0) < startNS) { + x1 = 0; + } else { + x1 = ns2x((node.startNS || 0), startNS, endNS, totalNS, frame); + } + if ((node.startNS || 0) + (node.dur || 0) > endNS) { + x2 = frame.width; + } else { + x2 = ns2x((node.startNS || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; + let rectangle: Rect = new Rect(Math.floor(x1), Math.ceil(frame.y + padding), Math.ceil(getV), Math.floor(frame.height - padding * 2)); + node.frame = rectangle; + } +} + +const textPadding = 2; + diff --git a/host/ide/src/trace/bean/FuncStruct.ts b/host/ide/src/trace/bean/FuncStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..d4b2ca911db1475a5dbd30f71548315397aeafe3 --- /dev/null +++ b/host/ide/src/trace/bean/FuncStruct.ts @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import {BaseStruct} from "./BaseStruct.js"; +import {Rect} from "../component/trace/timer-shaft/Rect.js"; +import {ColorUtils} from "../component/trace/base/ColorUtils.js"; + +export class FuncStruct extends BaseStruct { + static hoverFuncStruct: FuncStruct | undefined; + static selectFuncStruct: FuncStruct | undefined; + argsetid: number | undefined + depth: number | undefined + dur: number | undefined + funName: string | undefined + id: number | undefined + is_main_thread: number | undefined + parent_id: number | undefined + startTs: number | undefined + threadName: string | undefined + tid: number | undefined + track_id: number | undefined + + static draw(ctx: CanvasRenderingContext2D, data: FuncStruct) { + if (data.frame) { + if (data.dur == undefined || data.dur == null || data.dur == 0 || FuncStruct.isBinder(data)) { + } else { + let width = data.frame.width || 0; + ctx.fillStyle = ColorUtils.FUNC_COLOR[data.depth || 0 % ColorUtils.FUNC_COLOR.length] + let miniHeight = 20 + ctx.fillRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2) + ctx.fillStyle = "#fff" + FuncStruct.drawString(ctx, data.funName || '', 5, data.frame) + if (FuncStruct.isSelected(data)) { + ctx.strokeStyle = "#000" + ctx.lineWidth = 1 + ctx.strokeRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2) + } + } + } + } + + static drawString(ctx: CanvasRenderingContext2D, str: string, textPadding: number, frame: Rect) { + let textMetrics = ctx.measureText(str); + let charWidth = Math.round(textMetrics.width / str.length) + if (textMetrics.width < frame.width - textPadding * 2) { + let x2 = Math.floor(frame.width / 2 - textMetrics.width / 2 + frame.x + textPadding) + ctx.fillText(str, x2, Math.floor(frame.y + frame.height / 2 + 2), frame.width - textPadding * 2) + return; + } + if (frame.width - textPadding * 2 > charWidth * 4) { + let chatNum = (frame.width - textPadding * 2) / charWidth; + let x1 = frame.x + textPadding + ctx.fillText(str.substring(0, chatNum - 4) + '...', x1, Math.floor(frame.y + frame.height / 2 + 2), frame.width - textPadding * 2) + return; + } + } + + static isSelected(data: FuncStruct): boolean { + return (FuncStruct.selectFuncStruct != undefined && + FuncStruct.selectFuncStruct.startTs == data.startTs && + FuncStruct.selectFuncStruct.dur == data.dur && + FuncStruct.selectFuncStruct.funName == data.funName) + } + + static isBinder(data: FuncStruct): boolean { + if (data.funName != null && + ( + data.funName.toLowerCase().startsWith("binder transaction") + || data.funName.toLowerCase().startsWith("binder async") + || data.funName.toLowerCase().startsWith("binder reply") + ) + ) { + return true; + } else { + return false; + } + } +} + +const padding = 1; diff --git a/host/ide/src/trace/bean/HeapBean.ts b/host/ide/src/trace/bean/HeapBean.ts new file mode 100644 index 0000000000000000000000000000000000000000..ec7541f0fec433d4d134b3c515edc51642117279 --- /dev/null +++ b/host/ide/src/trace/bean/HeapBean.ts @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class HeapBean{ + MoudleName:string|undefined + AllocationFunction:string|undefined + Allocations:number|string = 0 + Deallocations:number|string= 0 + AllocationSize:number|string= 0 + DeAllocationSize:number|string= 0 + Total:number|string= 0 + RemainingSize:number|string= 0 + children:HeapBean[] = [] + depth:number = 0 +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/HeapStruct.ts b/host/ide/src/trace/bean/HeapStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..123ed31c6ab43f75a7e2f2afa679ea8ece08fb25 --- /dev/null +++ b/host/ide/src/trace/bean/HeapStruct.ts @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct} from "./BaseStruct.js"; +import {ns2x} from "../component/trace/TimerShaftElement.js"; +import {Rect} from "../component/trace/timer-shaft/Rect.js"; + +export class HeapStruct extends BaseStruct { + static hoverHeapStruct: HeapStruct | undefined; + startTime: number | undefined + endTime: number | undefined + dur: number | undefined + eventType:string | undefined + heapsize: number | undefined + maxHeapSize: number = 0 + minHeapSize: number = 0 + + static setFrame(node: HeapStruct, padding: number, startNS: number, endNS: number, totalNS: number, frame: Rect) { + let x1: number, x2: number; + if ((node.startTime || 0) < startNS) { + x1 = 0; + } else { + x1 = ns2x((node.startTime || 0), startNS, endNS, totalNS, frame); + } + if ((node.startTime || 0) + (node.dur || 0) > endNS) { + x2 = frame.width; + } else { + // @ts-ignore + x2 = ns2x(node.startTime + node.dur, startNS, endNS, totalNS, frame); + } + let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; + let rectangle: Rect = new Rect(Math.floor(x1), Math.ceil(frame.y + padding), Math.ceil(getV), Math.floor(frame.height - padding * 2)); + node.frame = rectangle; + } + + static draw(ctx: CanvasRenderingContext2D, data: HeapStruct) { + if (data.frame) { + let width = data.frame.width || 0; + ctx.fillStyle = "#2db3aa" + ctx.strokeStyle = "#2db3aa" + if (data.startTime === HeapStruct.hoverHeapStruct?.startTime) { + ctx.lineWidth = 1; + ctx.globalAlpha = 0.6; + let drawHeight: number = Math.ceil(((data.heapsize || 0) * (data.frame.height || 0)) / data.maxHeapSize); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + ctx.beginPath() + ctx.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true) + ctx.fill() + ctx.globalAlpha = 1.0; + ctx.stroke(); + ctx.beginPath() + ctx.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight); + ctx.lineWidth = 3; + ctx.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight) + ctx.stroke(); + } else { + ctx.globalAlpha = 0.6; + ctx.lineWidth = 1; + let drawHeight: number = Math.ceil(((data.heapsize || 0) * (data.frame.height || 0)) / data.maxHeapSize); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + } + } + ctx.globalAlpha = 1.0; + ctx.lineWidth = 1; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/HeapTreeDataBean.ts b/host/ide/src/trace/bean/HeapTreeDataBean.ts new file mode 100644 index 0000000000000000000000000000000000000000..a155a5865f7b112c7b9a4e52ed0b4d2cf5a07ae7 --- /dev/null +++ b/host/ide/src/trace/bean/HeapTreeDataBean.ts @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class HeapTreeDataBean{ + MoudleName:string|undefined + AllocationFunction:string|undefined + startTs:number = 0 + endTs:number = 0 + eventType:string|undefined + depth:number = 0 + heapSize:number = 0 + eventId:string="" +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/NativeHook.ts b/host/ide/src/trace/bean/NativeHook.ts new file mode 100644 index 0000000000000000000000000000000000000000..99168e0009843c259d8ab533fbc0ec995c41ecd4 --- /dev/null +++ b/host/ide/src/trace/bean/NativeHook.ts @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {Utils} from "../component/trace/base/Utils.js"; + +export class NativeHookStatistics{ + eventId:number = 0; + eventType:string = ""; + subType:string = ""; + heapSize:number = 0; + addr:string = ""; + startTs:number = 0; + endTs:number = 0; + sumHeapSize:number = 0; + max:number = 0; + count:number = 0; + tid:number = 0; + isSelected:boolean = false; +} + +export class NativeHookMalloc{ + eventType:string = ""; + subType:string = ""; + heapSize:number = 0; + allocByte:number = 0; + allocCount:number = 0; + freeByte:number = 0; + freeCount:number = 0; +} + +export class NativeEventHeap{ + eventType:string = ""; + sumHeapSize:number = 0 +} + +export class NativeHookProcess{ + ipid:number = 0; + pid:number = 0; + name:String = "" +} + +export class NativeHookStatisticsTableData{ + memoryTap:string = ""; + existing:number = 0; + existingString:string = ""; + allocCount:number = 0; + freeCount:number = 0; + totalBytes:number = 0 + totalBytesString:string = ""; + maxStr:string = ""; + max:number = 0 + totalCount:number = 0; + existingValue:Array = []; +} + +export class NativeMemory{ + index:number = 0; + eventId:number = 0; + eventType:string = ""; + subType:string = ""; + addr:string = ""; + startTs:number = 0; + timestamp:string = "" + heapSize:number = 0; + heapSizeUnit:string = ""; + symbol:string = ""; + library:string = ""; +} + +export class NativeHookCallInfo{ + id:string = ""; + pid:string | undefined; + threadId:number = 0; + symbol:string = ""; + library:string = ""; + title:string = ""; + count:number = 0; + type:number = 0; + heapSize:number = 0; + heapSizeStr:string = ""; + eventId:number = 0 + depth:number = 0; + children:Array = []; +} + +export class NativeHookSamplerInfo { + current:string = "" + currentSize:number = 0 + startTs:number = 0; + heapSize:number = 0; + snapshot:string = ""; + growth:string = ""; + total:number = 0; + totalGrowth:string = "" + existing:number = 0; + children:Array = []; + tempList:Array = []; + timestamp:string = "" + eventId:number = -1 + merageObj(merageObj:NativeHookSamplerInfo){ + this.currentSize+=merageObj.currentSize + this.heapSize += merageObj.heapSize + this.existing += merageObj.existing + this.total += merageObj.total + this.growth = Utils.getByteWithUnit(this.heapSize) + this.current = Utils.getByteWithUnit(this.currentSize) + this.totalGrowth = Utils.getByteWithUnit(this.total) + } +} + +export class NativeHookSampleQueryInfo { + eventId:number = -1 + current:number = 0 + eventType:string = ""; + subType:string = ""; + growth:number = 0; + existing:number = 0; + addr:string = ""; + startTs:number = 0; + endTs:number = 0; + total:number = 0; + children:Array = []; +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/ProcessMemStruct.ts b/host/ide/src/trace/bean/ProcessMemStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..636722b714d5906408c63d0c75d9bb58ec8023ce --- /dev/null +++ b/host/ide/src/trace/bean/ProcessMemStruct.ts @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct} from "./BaseStruct.js"; +import {ColorUtils} from "../component/trace/base/ColorUtils.js"; + +export class ProcessMemStruct extends BaseStruct { + trackId: number | undefined + processName: string | undefined + pid: number | undefined + upid: number | undefined + trackName: string | undefined + type: string | undefined + track_id: string | undefined + value: number | undefined + startTime: number | undefined + duration: number | undefined + maxValue: number | undefined + delta: number | undefined; + + static draw(ctx: CanvasRenderingContext2D, data: ProcessMemStruct) { + if (data.frame) { + let width = data.frame.width || 0; + ctx.fillStyle = ColorUtils.colorForTid(data.maxValue || 0) + ctx.strokeStyle = ColorUtils.colorForTid(data.maxValue || 0) + ctx.globalAlpha = 0.6; + ctx.lineWidth = 1; + let drawHeight: number = ((data.value || 0) * (data.frame.height || 0) * 1.0) / (data.maxValue || 1); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + } + ctx.globalAlpha = 1.0; + ctx.lineWidth = 1; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/ProcessStruct.ts b/host/ide/src/trace/bean/ProcessStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..f9844f7e8299d7b1820248d2acb4a9c840f9b880 --- /dev/null +++ b/host/ide/src/trace/bean/ProcessStruct.ts @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {ColorUtils} from "../component/trace/base/ColorUtils.js"; +import {CpuStruct} from "./CpuStruct.js"; +import {BaseStruct} from "./BaseStruct.js"; + +const padding = 1; + +export class ProcessStruct extends BaseStruct { + cpu: number | undefined + dur: number | undefined + id: number | undefined + pid: number | undefined + process: string | undefined + startTime: number | undefined + state: string | undefined + thread: string | undefined + tid: number | undefined + ts: number | undefined + type: string | undefined + utid: number | undefined + + static draw(ctx: CanvasRenderingContext2D, data: ProcessStruct) { + if (data.frame) { + let width = data.frame.width || 0; + ctx.fillStyle = ColorUtils.colorForTid(data.pid || 0) + let miniHeight = Math.round(data.frame.height / CpuStruct.cpuCount) + ctx.fillRect(data.frame.x, data.frame.y + (data.cpu || 0) * miniHeight + padding, data.frame.width, miniHeight - padding * 2) + } + } +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/StateProcessThread.ts b/host/ide/src/trace/bean/StateProcessThread.ts new file mode 100644 index 0000000000000000000000000000000000000000..642d399ef9d84abbf1cb5511ae45e05e4cf1abde --- /dev/null +++ b/host/ide/src/trace/bean/StateProcessThread.ts @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class StateProcessThread { + id: string = "" + pid: string = "" + title: string | null | undefined = "" + children: Array = [] + process: string = "" + processId: number = -1 + thread: string = "" + threadId: number = -1 + state: string = "" + wallDuration: number = 0 + avgDuration: string = "" + count: number = 0 + minDuration: number = 0 + maxDuration: number = 0 + stdDuration: string = "" +} + +export class SPTChild { + process: string = "" + processId: number = 0 + processName: string = "" + thread: string = "" + threadId: number = 0 + threadName: string = "" + state: string = "" + startNs: number = 0 + startTime: string = "" + duration: number = 0 + cpu: number | undefined = undefined + core: string = "" + priority: number = 0 + prior: string = "" + note: string = "-" +} + +export class SPT { + process: string = "" + processId: number = 0 + thread: string = "" + threadId: number = 0 + state: string = "" + dur: number = 0 + start_ts: number = 0 + end_ts: number = 0 + cpu: number = 0; + priority: string = "-" + note: string = "-" +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/ThreadStruct.ts b/host/ide/src/trace/bean/ThreadStruct.ts new file mode 100644 index 0000000000000000000000000000000000000000..ade6a0ad1520f9f6022a2f013d0744ae2204f591 --- /dev/null +++ b/host/ide/src/trace/bean/ThreadStruct.ts @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct} from "./BaseStruct.js"; +import {Rect} from "../component/trace/timer-shaft/Rect.js"; + +const padding = 1; + +export class ThreadStruct extends BaseStruct { + static runningColor: string = "#467b3b"; + static rColor = "#a0b84d"; + static uninterruptibleSleepColor = "#f19d38"; + static sColor = "#FBFBFB"; + static hoverThreadStruct: ThreadStruct | undefined; + static selectThreadStruct: ThreadStruct | undefined; + static statusMap: any = { + "D": "Uninterruptible Sleep", + "S": "Sleeping", + "R": "Runnable", + "Running": "Running", + "R+": "Runnable (Preempted)", + "DK": "Uninterruptible Sleep + Wake Kill", + "I": "Task Dead", + "T": "Stopped", + "t": "Traced", + "X": "Exit (Dead)", + "Z": "Exit (Zombie)", + "K": "Wake Kill", + "W": "Waking", + "P": "Parked", + "N": "No Load" + } + hasSched: number | undefined; + pid: number | undefined; + processName: string | undefined; + threadName: string | undefined; + tid: number | undefined; + upid: number | undefined; + utid: number | undefined; + cpu: number | undefined; + dur: number | undefined; + end_ts: number | undefined; + id: number | undefined; + is_main_thread: number | undefined; + name: string | undefined; + startTime: number | undefined; + start_ts: number | undefined; + state: string | undefined; + type: string | undefined; + + static draw(ctx: CanvasRenderingContext2D, data: ThreadStruct) { + if (data.frame) { + ctx.globalAlpha = 1 + let stateText = data.state || ''; + if ("S" == data.state) { + ctx.fillStyle = ThreadStruct.sColor; + ctx.globalAlpha = 0.2; // transparency + ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) + ctx.globalAlpha = 1; // transparency + } else if ("R" == data.state) { + ctx.fillStyle = ThreadStruct.rColor; + ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) + ctx.fillStyle = "#fff"; + ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame); + } else if ("D" == data.state) { + ctx.fillStyle = ThreadStruct.uninterruptibleSleepColor; + ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) + ctx.fillStyle = "#fff"; + ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame); + } else if ("Running" == data.state) { + ctx.fillStyle = ThreadStruct.runningColor; + ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) + ctx.fillStyle = "#fff"; + ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame); + } else { + ctx.fillStyle = ThreadStruct.rColor; + ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) + ctx.fillStyle = "#fff"; + ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame); + } + if (ThreadStruct.selectThreadStruct && ThreadStruct.equals(ThreadStruct.selectThreadStruct, data) && ThreadStruct.selectThreadStruct.state != "S") { + ctx.strokeStyle = '#232c5d' + ctx.lineWidth = 2 + ctx.strokeRect(data.frame.x, data.frame.y + padding, data.frame.width - 2, data.frame.height - padding * 2) + } + } + } + + static drawString(ctx: CanvasRenderingContext2D, str: string, textPadding: number, frame: Rect) { + let textMetrics = ctx.measureText(str); + let charWidth = Math.round(textMetrics.width / str.length) + if (textMetrics.width < frame.width - textPadding * 2) { + let x2 = Math.floor(frame.width / 2 - textMetrics.width / 2 + frame.x + textPadding) + ctx.textBaseline = "middle" + ctx.fillText(str, x2, Math.floor(frame.y + frame.height / 2), frame.width - textPadding * 2) + return; + } + if (frame.width - textPadding * 2 > charWidth * 4) { + let chatNum = (frame.width - textPadding * 2) / charWidth; + let x1 = frame.x + textPadding + ctx.textBaseline = "middle" + ctx.fillText(str.substring(0, chatNum - 4) + '...', x1, Math.floor(frame.y + frame.height / 2), frame.width - textPadding * 2) + return; + } + } + + static getEndState(state: string): string { + let statusMapElement = ThreadStruct.statusMap[state]; + if (statusMapElement) { + return statusMapElement + } else { + if ("" == statusMapElement || statusMapElement == null) { + return ""; + } + return "Unknown State"; + } + } + + static equals(d1: ThreadStruct, d2: ThreadStruct): boolean { + if (d1 && d2 && d1.cpu == d2.cpu && + d1.tid == d2.tid && + d1.state == d2.state && + d1.startTime == d2.startTime && + d1.dur == d2.dur) { + return true; + } else { + return false; + } + } +} diff --git a/host/ide/src/trace/bean/WakeUpTimeBean.ts b/host/ide/src/trace/bean/WakeUpTimeBean.ts new file mode 100644 index 0000000000000000000000000000000000000000..1a20fbb430e513a0585f91c5e984cea306420aec --- /dev/null +++ b/host/ide/src/trace/bean/WakeUpTimeBean.ts @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class WakeUpTimeBean { + wakeTs: number | undefined + startTs: number | undefined + preRow: number | undefined +} \ No newline at end of file diff --git a/host/ide/src/trace/bean/WakeupBean.ts b/host/ide/src/trace/bean/WakeupBean.ts new file mode 100644 index 0000000000000000000000000000000000000000..f8d6fbc30562f034ca1c864976725a2b255dc25a --- /dev/null +++ b/host/ide/src/trace/bean/WakeupBean.ts @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class WakeupBean { + wakeupTime: number | undefined + cpu: number | undefined + process: string | undefined + pid: number | undefined + thread: string | undefined + tid: number | undefined + schedulingLatency: number | undefined + schedulingDesc: string | undefined +} \ No newline at end of file diff --git a/host/ide/src/trace/component/SpInfoAndStas.ts b/host/ide/src/trace/component/SpInfoAndStas.ts new file mode 100644 index 0000000000000000000000000000000000000000..a450ef9e5a21674e81df606200b19bc826e87482 --- /dev/null +++ b/host/ide/src/trace/component/SpInfoAndStas.ts @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../base-ui/BaseElement.js"; + +@element('sp-info-and-stats') +export class SpInfoAndStats extends BaseElement { + initElements(): void { + } + + initHtml(): string { + return ` +
System info and metadata
+ `; + } +} diff --git a/host/ide/src/trace/component/SpMetrics.ts b/host/ide/src/trace/component/SpMetrics.ts new file mode 100644 index 0000000000000000000000000000000000000000..3e06d04c8d084a51f7eb3e9349518d2e64fd896c --- /dev/null +++ b/host/ide/src/trace/component/SpMetrics.ts @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../base-ui/BaseElement.js"; + +@element('sp-metrics') +export class SpMetrics extends BaseElement { + initElements(): void { + } + + initHtml(): string { + return ` + +
+ + trace_metadata: { + trace_duration_ns: 14726175738 + trace_uuid: "00000000-0000-0000-c0bd-eb5c5728bf40" + statsd_triggering_subscription_id: 0 + unique_session_name: "" + trace_size_bytes: 57202082 + trace_config_pbtxt: "buffers: { size_kb: 63488\\n fill_policy: DISCARD\\n}\\nbuffers: {\\n size_kb: 2048\\n fill_policy: DISCARD\\n}\\ndata_sources: {\\n config: {\\n name: \\"linux.process_stats\\"\\n target_buffer: 1\\n trace_duration_ms: 0\\n tracing_session_id: 0\\n enable_extra_guardrails: false\\n ftrace_config: {\\n buffer_size_kb: 0\\n drain_period_ms: 0\\n }\\n chrome_config: {\\n trace_config: \\"\\"\\n privacy_filtering_enabled: false\\n }\\n inode_file_config: {\\n scan_interval_ms: 0\\n scan_delay_ms: 0\\n scan_batch_size: 0\\n do_not_scan: false\\n }\\n process_stats_config: {\\n scan_all_processes_on_start: true\\n record_thread_names: false\\n proc_stats_poll_ms: 1000\\n proc_stats_cache_ttl_ms: 0\\n }\\n sys_stats_config: {\\n meminfo_period_ms: 0\\n vmstat_period_ms: 0\\n stat_period_ms: 0\\n }\\n heapprofd_config: {\\n sampling_interval_bytes: 0\\n all: false\\n continuous_dump_config: {\\n dump_phase_ms: 0\\n dump_interval_ms: 0\\n }\\n shmem_size_bytes: 0\\n block_client: false\\n }\\n android_power_config: {\\n battery_poll_ms: 0\\n collect_power_rails: false\\n }\\n android_log_config: {\\n min_prio: PRIO_UNSPECIFIED\\n }\\n packages_list_config: {\\n }\\n legacy_config: \\"\\"\\n }\\n}\\ndata_sources: {\\n config: {\\n name: \\"linux.ftrace\\"\\n target_buffer: 0\\n trace_duration_ms: 0\\n tracing_session_id: 0\\n enable_extra_guardrails: false\\n ftrace_config: {\\n ftrace_events: \\"sched/sched_switch\\"\\n ftrace_events: \\"power/suspend_resume\\"\\n ftrace_events: \\"sched/sched_wakeup\\"\\n ftrace_events: \\"sched/sched_wakeup_new\\"\\n ftrace_events: \\"sched/sched_waking\\"\\n ftrace_events: \\"power/cpu_frequency\\"\\n ftrace_events: \\"power/cpu_idle\\"\\n ftrace_events: \\"sched/sched_process_exit\\"\\n ftrace_events: \\"sched/sched_process_free\\"\\n ftrace_events: \\"task/task_newtask\\"\\n ftrace_events: \\"task/task_rename\\"\\n ftrace_events: \\"lowmemorykiller/lowmemory_kill\\"\\n ftrace_events: \\"oom/oom_score_adj_update\\"\\n ftrace_events: \\"ftrace/print\\"\\n atrace_categories: \\"gfx\\"\\n atrace_apps: \\"lmkd\\"\\n buffer_size_kb: 0\\n drain_period_ms: 0\\n }\\n chrome_config: {\\n trace_config: \\"\\"\\n privacy_filtering_enabled: false\\n }\\n inode_file_config: {\\n scan_interval_ms: 0\\n scan_delay_ms: 0\\n scan_batch_size: 0\\n do_not_scan: false\\n }\\n process_stats_config: {\\n scan_all_processes_on_start: false\\n record_thread_names: false\\n proc_stats_poll_ms: 0\\n proc_stats_cache_ttl_ms: 0\\n }\\n sys_stats_config: {\\n meminfo_period_ms: 0\\n vmstat_period_ms: 0\\n stat_period_ms: 0\\n }\\n heapprofd_config: {\\n sampling_interval_bytes: 0\\n all: false\\n continuous_dump_config: {\\n dump_phase_ms: 0\\n dump_interval_ms: 0\\n }\\n shmem_size_bytes: 0\\n block_client: false\\n }\\n android_power_config: {\\n battery_poll_ms: 0\\n collect_power_rails: false\\n }\\n android_log_config: {\\n min_prio: PRIO_UNSPECIFIED\\n }\\n packages_list_config: {\\n }\\n legacy_config: \\"\\"\\n }\\n}\\nduration_ms: 15000\\nenable_extra_guardrails: false\\nlockdown_mode: LOCKDOWN_UNCHANGED\\nstatsd_metadata: {\\n triggering_alert_id: 0\\n triggering_config_uid: 0\\n triggering_config_id: 0\\n triggering_subscription_id: 0\\n}\\nwrite_into_file: false\\nfile_write_period_ms: 0\\nmax_file_size_bytes: 0\\nguardrail_overrides: {\\n max_upload_per_day_bytes: 0\\n}\\ndeferred_start: false\\nflush_period_ms: 0\\nflush_timeout_ms: 0\\nnotify_traceur: false\\ntrigger_config: {\\n trigger_mode: UNSPECIFIED\\n trigger_timeout_ms: 0\\n}\\nallow_user_build_tracing: false\\nbuiltin_data_sources: {\\n disable_clock_snapshotting: false\\n disable_trace_config: false\\n disable_system_info: false\\n}\\nincremental_state_config: {\\n clear_period_ms: 0\\n}\\nunique_session_name: \\"\\"\\ncompression_type: COMPRESSION_TYPE_UNSPECIFIED\\nincident_report_config: {\\n destination_package: \\"\\"\\n destination_class: \\"\\"\\n privacy_level: 0\\n skip_dropbox: false\\n}" + sched_duration_ns: 14726119124 +} + +
+ `; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/SpQuerySQL.ts b/host/ide/src/trace/component/SpQuerySQL.ts new file mode 100644 index 0000000000000000000000000000000000000000..291793d293b1daf8b70c4b5afcb69743302504df --- /dev/null +++ b/host/ide/src/trace/component/SpQuerySQL.ts @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../base-ui/BaseElement.js"; +import {querySql, queryThreadsByPid} from "../database/SqlLite.js"; + +@element('sp-query-sql') +export class SpQuerySQL extends BaseElement { + initElements(): void { + let sqlInput: HTMLInputElement | undefined | null = this.shadowRoot?.querySelector('#sql-input'); + let contentEL: HTMLPreElement | undefined | null = this.shadowRoot?.querySelector('#content'); + if (sqlInput) { + sqlInput.addEventListener('change', e => { + let dateA = new Date().getTime(); + if(sqlInput&&sqlInput.value) { + querySql(sqlInput.value).then(res=>{ + let dur = new Date().getTime() - dateA; + contentEL!.innerHTML = `耗时:${dur}ms 记录:${res.length}条\n${JSON.stringify(res,null,4)}` + }) + } + }) + } + } + + connectedCallback() { + } + + initHtml(): string { + return ` + +
+ +

+
+ `; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/SpRecordTrace.ts b/host/ide/src/trace/component/SpRecordTrace.ts new file mode 100644 index 0000000000000000000000000000000000000000..2e7674f29cb55bc413555cf7415ec06e3d34e778 --- /dev/null +++ b/host/ide/src/trace/component/SpRecordTrace.ts @@ -0,0 +1,574 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../base-ui/BaseElement.js"; +import "../../base-ui/popover/LitPopover.js" +import {LitMainMenuGroup} from "../../base-ui/menu/LitMainMenuGroup.js"; +import {LitMainMenuItem} from "../../base-ui/menu/LitMainMenuItem.js"; +import {SpRecordSetting} from "./setting/SpRecordSetting.js"; +import {MenuItem} from "../../base-ui/menu/LitMainMenu.js"; +import {SpProbesConfig} from "./setting/SpProbesConfig.js"; +import {SpTraceCommand} from "./setting/SpTraceCommand.js"; +import { + CreateSessionRequest, + FpsConfig, + HilogConfig, + levelFromJSON, + MemoryConfig, + NativeHookConfig, + ProfilerPluginConfig, + ProfilerSessionConfig, + ProfilerSessionConfigBufferConfig, + ProfilerSessionConfigBufferConfigPolicy, + ProfilerSessionConfigMode, + sysMeminfoTypeFromJSON, + sysVMeminfoTypeFromJSON, + TracePluginConfig, + Type +} from "./setting/bean/ProfilerServiceTypes.js"; +import {PluginConvertUtils} from "./setting/utils/PluginConvertUtils.js"; +import {SpAllocations} from "./setting/SpAllocations.js"; + +@element('sp-record-trace') +export class SpRecordTrace extends BaseElement { + static MEM_INFO = ["MEMINFO_ACTIVE", "MEMINFO_ACTIVE_ANON", "MEMINFO_ACTIVE_FILE", "MEMINFO_ANON_PAGES", "MEMINFO_BUFFERS", + "MEMINFO_CACHED", "MEMINFO_CMA_FREE", "MEMINFO_CMA_TOTAL", "MEMINFO_COMMIT_LIMIT", "MEMINFO_COMMITED_AS", + "MEMINFO_DIRTY", "MEMINFO_INACTIVE", "MEMINFO_INACTIVE_ANON", "MEMINFO_INACTIVE_FILE", + "MEMINFO_KERNEL_STACK", "MEMINFO_MAPPED", "MEMINFO_MEM_AVAILABLE", "MEMINFO_MEM_FREE", "MEMINFO_MEM_TOTAL", + "MEMINFO_MLOCKED", "MEMINFO_PAGE_TABLES", "MEMINFO_SHMEM", "MEMINFO_SLAB", "MEMINFO_SLAB_RECLAIMABLE", + "MEMINFO_SLAB_UNRECLAIMABLE", "MEMINFO_SWAP_CACHED", "MEMINFO_SWAP_FREE", "MEMINFO_SWAP_TOTAL", + "MEMINFO_UNEVICTABLE", "MEMINFO_VMALLOC_CHUNK", "MEMINFO_VMALLOC_TOTAL", "MEMINFO_VMALLOC_USED", + "MEMINFO_WRITEBACK"] + static VMEM_INFO = ["VMEMINFO_UNSPECIFIED", "VMEMINFO_NR_FREE_PAGES", "VMEMINFO_NR_ALLOC_BATCH", + "VMEMINFO_NR_INACTIVE_ANON", "VMEMINFO_NR_ACTIVE_ANON", "VMEMINFO_NR_INACTIVE_FILE", + "VMEMINFO_NR_ACTIVE_FILE", "VMEMINFO_NR_UNEVICTABLE", "VMEMINFO_NR_MLOCK", "VMEMINFO_NR_ANON_PAGES", + "VMEMINFO_NR_MAPPED", "VMEMINFO_NR_FILE_PAGES", "VMEMINFO_NR_DIRTY", "VMEMINFO_NR_WRITEBACK", + "VMEMINFO_NR_SLAB_RECLAIMABLE", "VMEMINFO_NR_SLAB_UNRECLAIMABLE", "VMEMINFO_NR_PAGE_TABLE_PAGES", + "VMEMINFO_NR_KERNEL_STACK", "VMEMINFO_NR_OVERHEAD", "VMEMINFO_NR_UNSTABLE", "VMEMINFO_NR_BOUNCE", + "VMEMINFO_NR_VMSCAN_WRITE", "VMEMINFO_NR_VMSCAN_IMMEDIATE_RECLAIM", "VMEMINFO_NR_WRITEBACK_TEMP", + "VMEMINFO_NR_ISOLATED_ANON", "VMEMINFO_NR_ISOLATED_FILE", "VMEMINFO_NR_SHMEM", "VMEMINFO_NR_DIRTIED", + "VMEMINFO_NR_WRITTEN", "VMEMINFO_NR_PAGES_SCANNED", "VMEMINFO_WORKINGSET_REFAULT", + "VMEMINFO_WORKINGSET_ACTIVATE", "VMEMINFO_WORKINGSET_NODERECLAIM", "VMEMINFO_NR_ANON_TRANSPARENT_HUGEPAGES", + "VMEMINFO_NR_FREE_CMA", "VMEMINFO_NR_SWAPCACHE", "VMEMINFO_NR_DIRTY_THRESHOLD", + "VMEMINFO_NR_DIRTY_BACKGROUND_THRESHOLD", "VMEMINFO_PGPGIN", "VMEMINFO_PGPGOUT", "VMEMINFO_PGPGOUTCLEAN", + "VMEMINFO_PSWPIN", "VMEMINFO_PSWPOUT", "VMEMINFO_PGALLOC_DMA"] + static VMEM_INFO_SECOND = ["VMEMINFO_PGALLOC_NORMAL", "VMEMINFO_PGALLOC_MOVABLE", "VMEMINFO_PGFREE", "VMEMINFO_PGACTIVATE", + "VMEMINFO_PGDEACTIVATE", "VMEMINFO_PGFAULT", "VMEMINFO_PGMAJFAULT", "VMEMINFO_PGREFILL_DMA", + "VMEMINFO_PGREFILL_NORMAL", "VMEMINFO_PGREFILL_MOVABLE", "VMEMINFO_PGSTEAL_KSWAPD_DMA", + "VMEMINFO_PGSTEAL_KSWAPD_NORMAL", "VMEMINFO_PGSTEAL_KSWAPD_MOVABLE", "VMEMINFO_PGSTEAL_DIRECT_DMA", + "VMEMINFO_PGSTEAL_DIRECT_NORMAL", "VMEMINFO_PGSTEAL_DIRECT_MOVABLE", "VMEMINFO_PGSCAN_KSWAPD_DMA", + "VMEMINFO_PGSCAN_KSWAPD_NORMAL", "VMEMINFO_PGSCAN_KSWAPD_MOVABLE", "VMEMINFO_PGSCAN_DIRECT_DMA", + "VMEMINFO_PGSCAN_DIRECT_NORMAL", "VMEMINFO_PGSCAN_DIRECT_MOVABLE", "VMEMINFO_PGSCAN_DIRECT_THROTTLE", + "VMEMINFO_PGINODESTEAL", "VMEMINFO_SLABS_SCANNED", "VMEMINFO_KSWAPD_INODESTEAL", + "VMEMINFO_KSWAPD_LOW_WMARK_HIT_QUICKLY", "VMEMINFO_KSWAPD_HIGH_WMARK_HIT_QUICKLY", "VMEMINFO_PAGEOUTRUN", + "VMEMINFO_ALLOCSTALL", "VMEMINFO_PGROTATED", "VMEMINFO_DROP_PAGECACHE", "VMEMINFO_DROP_SLAB", + "VMEMINFO_PGMIGRATE_SUCCESS", "VMEMINFO_PGMIGRATE_FAIL", "VMEMINFO_COMPACT_MIGRATE_SCANNED", + "VMEMINFO_COMPACT_FREE_SCANNED", "VMEMINFO_COMPACT_ISOLATED", "VMEMINFO_COMPACT_STALL", + "VMEMINFO_COMPACT_FAIL", "VMEMINFO_COMPACT_SUCCESS", "VMEMINFO_COMPACT_DAEMON_WAKE", + "VMEMINFO_UNEVICTABLE_PGS_CULLED", "VMEMINFO_UNEVICTABLE_PGS_SCANNED", "VMEMINFO_UNEVICTABLE_PGS_RESCUED", + "VMEMINFO_UNEVICTABLE_PGS_MLOCKED", "VMEMINFO_UNEVICTABLE_PGS_MUNLOCKED"] + static VMEM_INFO_THIRD = [ + "VMEMINFO_UNEVICTABLE_PGS_CLEARED", "VMEMINFO_UNEVICTABLE_PGS_STRANDED", "VMEMINFO_NR_ZSPAGES", + "VMEMINFO_NR_ION_HEAP", "VMEMINFO_NR_GPU_HEAP", "VMEMINFO_ALLOCSTALL_DMA", "VMEMINFO_ALLOCSTALL_MOVABLE", + "VMEMINFO_ALLOCSTALL_NORMAL", "VMEMINFO_COMPACT_DAEMON_FREE_SCANNED", + "VMEMINFO_COMPACT_DAEMON_MIGRATE_SCANNED", "VMEMINFO_NR_FASTRPC", "VMEMINFO_NR_INDIRECTLY_RECLAIMABLE", + "VMEMINFO_NR_ION_HEAP_POOL", "VMEMINFO_NR_KERNEL_MISC_RECLAIMABLE", "VMEMINFO_NR_SHADOW_CALL_STACK_BYTES", + "VMEMINFO_NR_SHMEM_HUGEPAGES", "VMEMINFO_NR_SHMEM_PMDMAPPED", "VMEMINFO_NR_UNRECLAIMABLE_PAGES", + "VMEMINFO_NR_ZONE_ACTIVE_ANON", "VMEMINFO_NR_ZONE_ACTIVE_FILE", "VMEMINFO_NR_ZONE_INACTIVE_ANON", + "VMEMINFO_NR_ZONE_INACTIVE_FILE", "VMEMINFO_NR_ZONE_UNEVICTABLE", "VMEMINFO_NR_ZONE_WRITE_PENDING", + "VMEMINFO_OOM_KILL", "VMEMINFO_PGLAZYFREE", "VMEMINFO_PGLAZYFREED", "VMEMINFO_PGREFILL", + "VMEMINFO_PGSCAN_DIRECT", "VMEMINFO_PGSCAN_KSWAPD", "VMEMINFO_PGSKIP_DMA", "VMEMINFO_PGSKIP_MOVABLE", + "VMEMINFO_PGSKIP_NORMAL", "VMEMINFO_PGSTEAL_DIRECT", "VMEMINFO_PGSTEAL_KSWAPD", "VMEMINFO_SWAP_RA", + "VMEMINFO_SWAP_RA_HIT", "VMEMINFO_WORKINGSET_RESTORE" + ] + schedulingEvents = [ + "sched/sched_switch", + "power/suspend_resume", + "sched/sched_wakeup", + "sched/sched_wakeup_new", + "sched/sched_waking", + "sched/sched_process_exit", + "sched/sched_process_free", + "task/task_newtask", + "task/task_rename" + ] + powerEvents = [ + "regulator/regulator_set_voltage", + "regulator/regulator_set_voltage_complete", + "power/clock_enable", + "power/clock_disable", + "power/clock_set_rate", + "power/suspend_resume" + ] + cpuFreqEvents = [ + "power/cpu_frequency", + "power/cpu_idle", + "power/suspend_resume" + ] + sysCallsEvents = [ + "raw_syscalls/sys_enter", + "raw_syscalls/sys_exit" + ] + highFrequencyEvents = [ + "mm_event/mm_event_record", + "kmem/rss_stat", + "ion/ion_stat", + "dmabuf_heap/dma_heap_stat", + "kmem/ion_heap_grow", + "kmem/ion_heap_shrink" + ] + advancedConfigEvents = ["sched/sched_switch", + "sched/sched_wakeup", + "sched/sched_wakeup_new", + "sched/sched_waking", + "sched/sched_process_exit", + "sched/sched_process_free", + "irq/irq_handler_entry", + "irq/irq_handler_exit", + "irq/softirq_entry", + "irq/softirq_exit", + "irq/softirq_raise", + "power/clock_disable", + "power/clock_enable", + "power/clock_set_rate", + "power/cpu_frequency", + "power/cpu_idle", + "clk/clk_disable", + "clk/clk_disable_complete", + "clk/clk_enable", + "clk/clk_enable_complete", + "clk/clk_set_rate", + "clk/clk_set_rate_complete", + "binder/binder_transaction", + "binder/binder_transaction_alloc_buf", + "binder/binder_transaction_received", + "binder/binder_lock", + "binder/binder_locked", + "binder/binder_unlock", + "workqueue/workqueue_execute_start", + "workqueue/workqueue_execute_end", + "oom/oom_score_adj_update", + "ftrace/print" + ] + private _menuItems: Array | undefined + + initElements(): void { + let that = this + let parentElement = this.parentNode as HTMLElement; + parentElement.style.overflow = 'hidden' + let recordSetting = new SpRecordSetting(); + let probesConfig = new SpProbesConfig(); + let traceCommand = new SpTraceCommand(); + let spAllocations = new SpAllocations(); + let menuGroup = this.shadowRoot?.querySelector('#menu-group') as LitMainMenuGroup + let appContent = this.shadowRoot?.querySelector('#app-content') as HTMLElement + appContent.append(recordSetting) + this._menuItems = [ + { + title: "Record setting", + icon: "properties", + fileChoose: false, + clickHandler: function (ev: InputEvent) { + appContent!.innerHTML = "" + appContent.append(recordSetting) + } + }, + { + title: "Trace command", + icon: "dbsetbreakpoint", + fileChoose: false, + clickHandler: function (ev: InputEvent) { + let maxDur = recordSetting.maxDur; + let bufferSize = recordSetting.bufferSize; + let bufferConfig: ProfilerSessionConfigBufferConfig = { + pages: bufferSize * 256, + policy: ProfilerSessionConfigBufferConfigPolicy.RECYCLE + } + let sessionConfig: ProfilerSessionConfig = { + buffers: [bufferConfig], + sessionMode: ProfilerSessionConfigMode.OFFLINE, + resultFile: "/data/local/tmp/hiprofiler_data.htrace", + resultMaxSize: 0, + sampleDuration: maxDur * 1000, + keepAliveTime: 0 + } + let request: CreateSessionRequest = { + requestId: 1, + sessionConfig: sessionConfig, + pluginConfigs: [] + } + if (probesConfig.traceConfig.length > 0) { + request.pluginConfigs.push(that.createHtracePluginConfig(that, probesConfig, recordSetting)) + if (probesConfig.traceConfig.indexOf("FPS") != -1) { + request.pluginConfigs.push(that.createFpsPluginConfig()) + } + } + let reportingFrequency: number; + if (maxDur > 20) { + reportingFrequency = 5 + } else { + reportingFrequency = 2 + } + if (probesConfig.memoryConfig.length > 0) { + request.pluginConfigs.push(that.createMemoryPluginConfig(probesConfig, that, reportingFrequency)) + } + if (spAllocations.appProcess != "") { + request.pluginConfigs.push(that.createNativePluginConfig(spAllocations, reportingFrequency)) + } + appContent!.innerHTML = "" + appContent.append(traceCommand) + traceCommand.hdcCommon = + PluginConvertUtils.createHdcCmd( + PluginConvertUtils.BeanToCmdTxt(request, false), maxDur) + } + }, + { + title: "Probes config", icon: "realIntentionBulb", fileChoose: false, + clickHandler: function (ev: InputEvent) { + appContent!.innerHTML = "" + appContent.append(probesConfig) + } + }, + { + title: "Allocations", + icon: "externaltools", + fileChoose: false, + clickHandler: function (ev: InputEvent) { + appContent!.innerHTML = "" + appContent.append(spAllocations) + } + } + ] + this._menuItems?.forEach(item => { + let th = new LitMainMenuItem(); + th.setAttribute('icon', item.icon || ""); + th.setAttribute('title', item.title || ""); + th.style.height = "60px" + th.style.fontFamily = "Helvetica-Bold" + th.style.fontSize = "16px" + th.style.lineHeight = "28px" + th.style.fontWeight = "700" + th.style.opacity = "0.9" + th.removeAttribute('file'); + th.addEventListener('click', e => { + if (item.clickHandler) { + item.clickHandler(item) + } + }) + menuGroup.appendChild(th); + }) + } + + createTraceEvents(traceConfig: Array): Array { + let traceEvents = new Set(); + traceConfig.forEach(config => { + switch (config) { + case "Scheduling details": + this.schedulingEvents.forEach((eve: string) => { + traceEvents.add(eve) + }); + break; + case "CPU Frequency and idle states": + this.cpuFreqEvents.forEach((eve: string) => { + traceEvents.add(eve) + }); + break; + case "High frequency memory": + this.highFrequencyEvents.forEach((eve: string) => { + traceEvents.add(eve) + }); + break; + case "Advanced ftrace config": + this.advancedConfigEvents.forEach((eve: string) => { + traceEvents.add(eve) + }); + break; + case "Syscalls": + this.sysCallsEvents.forEach((eve: string) => { + traceEvents.add(eve) + }); + break; + case "Board voltages & frequency": + this.powerEvents.forEach((eve: string) => { + traceEvents.add(eve) + }); + break; + } + } + ) + let ftraceEventsArray: string[] = []; + for (const ftraceEvent of traceEvents) { + ftraceEventsArray.push(ftraceEvent) + } + return ftraceEventsArray + } + + initHtml(): string { + return ` + +
+ +
+ +
+
+
+
+`; + } + + private createHilogConfig(probesConfig: SpProbesConfig, reportingFrequency: number) { + let hilogConfig: HilogConfig = { + deviceType: Type.HI3516, + logLevel: levelFromJSON(probesConfig.hilogConfig[0]), + needClear: true + } + let hilogConfigProfilerPluginConfig: ProfilerPluginConfig = { + pluginName: "hilog-plugin", + sampleInterval: reportingFrequency * 1000, + configData: hilogConfig, + } + return hilogConfigProfilerPluginConfig; + } + + private createNativePluginConfig(spAllocations: SpAllocations, reportingFrequency: number) { + let appProcess = spAllocations.appProcess; + let re = /^[0-9]+.?[0-9]*/; + let pid = 0; + let processName = ""; + if (re.test(appProcess)) { + pid = Number(appProcess); + } else { + processName = appProcess; + } + let nativeConfig: NativeHookConfig = { + pid: pid, + saveFile: false, + fileName: "", + filterSize: spAllocations.filter, + smbPages: spAllocations.shared, + maxStackDepth: spAllocations.unwind, + processName: processName + } + let nativePluginConfig: ProfilerPluginConfig = { + pluginName: "nativehook", + sampleInterval: reportingFrequency * 1000, + configData: nativeConfig, + } + return nativePluginConfig; + } + + private createMemoryPluginConfig(probesConfig: SpProbesConfig, that: this, reportingFrequency: number) { + let memoryconfig: MemoryConfig = { + reportProcessTree: true, + reportSysmemMemInfo: true, + sysMeminfoCounters: [], + reportSysmemVmemInfo: true, + sysVmeminfoCounters: [], + reportProcessMemInfo: true, + reportAppMemInfo: false, + reportAppMemByMemoryService: false, + pid: [] + } + probesConfig.memoryConfig.forEach(value => { + if (value.indexOf("Kernel meminfo") != -1) { + SpRecordTrace.MEM_INFO.forEach(va => { + memoryconfig.sysMeminfoCounters.push(sysMeminfoTypeFromJSON(va)); + }) + } + if (value.indexOf("Virtual memory stats") != -1) { + SpRecordTrace.VMEM_INFO.forEach((me => { + memoryconfig.sysVmeminfoCounters.push(sysVMeminfoTypeFromJSON(me)) + })) + SpRecordTrace.VMEM_INFO_SECOND.forEach((me => { + memoryconfig.sysVmeminfoCounters.push(sysVMeminfoTypeFromJSON(me)) + })) + SpRecordTrace.VMEM_INFO_THIRD.forEach((me => { + memoryconfig.sysVmeminfoCounters.push(sysVMeminfoTypeFromJSON(me)) + })) + } + }) + let profilerPluginConfig: ProfilerPluginConfig = { + pluginName: "memory-plugin", + sampleInterval: reportingFrequency * 1000, + configData: memoryconfig, + } + return profilerPluginConfig; + } + + private createFpsPluginConfig() { + let fpsConfig: FpsConfig = { + reportFps: true + } + let fpsPlugin: ProfilerPluginConfig = { + pluginName: "hidump-plugin", + sampleInterval: 1000, + configData: fpsConfig + } + return fpsPlugin; + } + + private createHtracePluginConfig(that: this, probesConfig: SpProbesConfig, recordSetting: SpRecordSetting) { + let tracePluginConfig: TracePluginConfig = { + ftraceEvents: that.createTraceEvents(probesConfig.traceConfig), + hitraceCategories: [], + hitraceApps: [], + bufferSizeKb: 2048, + flushIntervalMs: 1000, + flushThresholdKb: 4096, + parseKsyms: true, + clock: "mono", + tracePeriodMs: 200, + rawDataPrefix: "", + traceDurationMs: 0, + debugOn: false, + hitraceTime: recordSetting.maxDur + } + if (probesConfig.traceEvents.length > 0) { + tracePluginConfig.hitraceCategories = probesConfig.traceEvents + } + let htraceProfilerPluginConfig: ProfilerPluginConfig = { + pluginName: "ftrace-plugin", + sampleInterval: 1000, + configData: tracePluginConfig + } + return htraceProfilerPluginConfig; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/SpRecyclerSystemTrace.ts b/host/ide/src/trace/component/SpRecyclerSystemTrace.ts new file mode 100644 index 0000000000000000000000000000000000000000..a0a4ed179770527b4804ca2c8c72391e4c2839af --- /dev/null +++ b/host/ide/src/trace/component/SpRecyclerSystemTrace.ts @@ -0,0 +1,805 @@ +// @ts-nocheck +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../base-ui/BaseElement.js"; +import "./trace/TimerShaftElement.js"; +import "./trace/base/TraceRow.js"; +import "./trace/base/TraceRowRecyclerView.js" +import { + getAsyncEvents, + getCpuUtilizationRate, + getFps, + getFunDataByTid, + queryCpuData, + queryCpuFreq, + queryCpuFreqData, + queryCpuMax, + queryCpuMaxFreq, + queryHeapByPid, + queryHeapPid, + queryProcess, + queryProcessData, + queryProcessMem, + queryProcessMemData, + queryProcessThreads, + queryThreadData, + queryTotalTime, + threadPool +} from "../database/SqlLite.js"; +import {TraceRow} from "./trace/base/TraceRow.js"; +import {TimerShaftElement} from "./trace/TimerShaftElement.js"; +import {TimeRange} from "./trace/timer-shaft/RangeRuler.js"; +import {CpuStruct} from "../bean/CpuStruct.js"; +import {CpuFreqStruct} from "../bean/CpuFreqStruct.js"; +import {ProcessStruct} from "../bean/ProcessStruct.js"; +import {ColorUtils} from "./trace/base/ColorUtils.js"; +import "./trace/base/TraceSheet.js"; +import {TraceSheet} from "./trace/base/TraceSheet.js"; +import {ThreadStruct} from "../bean/ThreadStruct.js"; +import {ProcessMemStruct} from "../bean/ProcessMemStruct.js"; +import {FuncStruct} from "../bean/FuncStruct.js"; +import {FpsStruct} from "../bean/FpsStruct.js"; +import {RangeSelect} from "./trace/base/RangeSelect.js"; +import {SelectionParam} from "../bean/BoxSelection.js"; +import {procedurePool} from "../database/Procedure.js"; +import {SportRuler} from "./trace/timer-shaft/SportRuler.js"; +import {TraceRowRecyclerView} from "./trace/base/TraceRowRecyclerView.js"; +import {TraceRowObject} from "./trace/base/TraceRowObject.js"; +import {Rect} from "./trace/timer-shaft/Rect.js"; + +@element('sp-recycler-system-trace') +export class SpRecyclerSystemTrace extends BaseElement { + static scrollViewWidth = 0 + rowsEL: TraceRowRecyclerView | undefined | null; + private timerShaftEL: TimerShaftElement | null | undefined; + private range: TimeRange | undefined + private traceSheetEL: TraceSheet | undefined | null; + private rangeSelect!: RangeSelect; + private processThreads: Array = [] + private processAsyncEvent: Array = [] + private processMem: Array = [] + + initElements(): void { + this.rowsEL = this.shadowRoot?.querySelector('.rows') + this.timerShaftEL = this.shadowRoot?.querySelector('.timer-shaft') + this.traceSheetEL = this.shadowRoot?.querySelector('.trace-sheet') + this.rangeSelect = new RangeSelect(this.timerShaftEL); + this.rangeSelect.rowsEL = this.rowsEL; + document?.addEventListener("flag-change", (event: any) => { + let flag = event.detail; + this.timerShaftEL?.modifyFlagList(event.detail.type, event.detail.flagObj) + if (flag.hidden) { + this.traceSheetEL?.setAttribute("mode", 'hidden'); + } + }) + SpRecyclerSystemTrace.scrollViewWidth = this.getScrollWidth() + this.rangeSelect.selectHandler = (rows) => { + let selection = new SelectionParam(); + // 框选的 cpu ,无则不传 + selection.cpus = []; + // 框选的 线程 id,无则不传 + selection.threadIds = []; + // 款选的函数的 线程id ,无则不传 + selection.funTids = []; + // 框选的 内存 trackId ,无则不传 + selection.trackIds = []; + // 框选的起始时间 + selection.leftNs = 0; + // 框选的结束时间 + selection.rightNs = 0; + rows.forEach(it => { + if (it.rowType == TraceRow.ROW_TYPE_CPU) { + selection.cpus.push(parseInt(it.rowId!)) + } else if (it.rowType == TraceRow.ROW_TYPE_THREAD) { + selection.threadIds.push(parseInt(it.rowId!)) + } else if (it.rowType == TraceRow.ROW_TYPE_FUNC) { + selection.funTids.push(parseInt(it.rowId!)) + } else if (it.rowType == TraceRow.ROW_TYPE_MEM) { + selection.trackIds.push(parseInt(it.rowId!)) + } else if (it.rowType == TraceRow.ROW_TYPE_FPS) { + selection.hasFps = true; + } else if (it.rowType == TraceRow.ROW_TYPE_HEAP) { + selection.heapIds.push(parseInt(it.rowId!)) + } + if (it.rangeSelect && it.rangeSelect.startNS) { + selection.leftNs = it.rangeSelect.startNS; + } + if (it.rangeSelect && it.rangeSelect.endNS) { + selection.rightNs = it.rangeSelect.endNS; + } + }) + this.traceSheetEL?.boxSelection(selection) + } + // @ts-ignore + new ResizeObserver((entries) => { + let width = entries[0].contentRect.width - 1 - SpRecyclerSystemTrace.scrollViewWidth; + requestAnimationFrame(() => { + this.timerShaftEL?.updateWidth(width) + this.shadowRoot!.querySelectorAll>("trace-row").forEach(it => it.updateWidth(width)) + }) + }).observe(this) + // @ts-ignore + new ResizeObserver((entries) => { + let width = this.clientWidth - 1 - SpRecyclerSystemTrace.scrollViewWidth + requestAnimationFrame(() => { + this.timerShaftEL?.updateWidth(width) + this.shadowRoot!.querySelectorAll>("trace-row").forEach(it => it.updateWidth(width)) + }) + // this.shadowRoot!.querySelectorAll>("trace-row").forEach(it=>it.updateWidth(width)) + }).observe(window.document.body) + } + + getScrollWidth() { + let noScroll, scroll, oDiv = document.createElement('div'); + oDiv.style.cssText = 'position:absolute; top:-1000px; width:100px; height:100px; overflow:hidden;'; + noScroll = document.body.appendChild(oDiv).clientWidth; + oDiv.style.overflowY = 'scroll'; + scroll = oDiv.clientWidth; + document.body.removeChild(oDiv); + return noScroll - scroll + 1; + } + + getVisibleRows(): Array> { + return [...this.rowsEL!.shadowRoot!.querySelectorAll>("trace-row")]; + } + + timerShaftELRangeChange = (e: any) => { + this.range = e.detail; + TraceRow.range = this.range; + let scrollTop = this.rowsEL?.scrollTop || 0 + let scrollHeight = this.rowsEL?.clientHeight || 0 + //在rowsEL显示范围内的 trace-row组件将收到时间区间变化通知 + this.getVisibleRows().forEach(it => { + it.dataListCache.length = 0; + this.hoverStructNull(); + it.drawObject(); + }) + } + + rowsElOnScroll = (e: any) => { + this.hoverStructNull(); + let rows = this.getVisibleRows(); + rows.forEach((it, index) => { + if (index == 0 || index == rows.length - 1) { + it.dataListCache.length = 0; + it.drawObject(); + } + }) + } + + documentOnMouseDown = (ev: MouseEvent) => { + this.rangeSelect.mouseDown(ev) + } + + documentOnMouseUp = (ev: MouseEvent) => { + this.rangeSelect.mouseUp(ev); + } + + documentOnMouseMove = (ev: MouseEvent) => { + let rows = this.getVisibleRows(); + this.rangeSelect.mouseMove(rows, ev) + rows.forEach(tr => { + let x = ev.offsetX - (tr.canvasContainer?.offsetLeft || 0); + let y = ev.offsetY - (tr.canvasContainer?.offsetTop || 0) + (this.rowsEL?.scrollTop || 0); + //判断鼠标是否在当前 trace-row + if (x > tr.frame.x && x < tr.frame.x + tr.frame.width && y > tr.frame.y && y < tr.frame.y + tr.frame.height) { + this.hoverStructNull(); + if (tr.rowType === TraceRow.ROW_TYPE_CPU) { + CpuStruct.hoverCpuStruct = tr.onMouseHover(x, y); + if (CpuStruct.hoverCpuStruct) { + tr.tip = `P:${CpuStruct.hoverCpuStruct.processName || "Process"} [${CpuStruct.hoverCpuStruct.processId}]T:${CpuStruct.hoverCpuStruct.name} [${CpuStruct.hoverCpuStruct.tid}]`; + } + tr.setTipLeft(x, CpuStruct.hoverCpuStruct) + } else if (tr.rowType === TraceRow.ROW_TYPE_CPU_FREQ) { + CpuFreqStruct.hoverCpuFreqStruct = tr.onMouseHover(x, y); + if (CpuFreqStruct.hoverCpuFreqStruct) { + tr.tip = `${ColorUtils.formatNumberComma(CpuFreqStruct.hoverCpuFreqStruct.value!)} kHz` + } + tr.setTipLeft(x, CpuFreqStruct.hoverCpuFreqStruct) + } else if (tr.rowType === TraceRow.ROW_TYPE_THREAD) { + ThreadStruct.hoverThreadStruct = tr.onMouseHover(x, y, false); + } else if (tr.rowType === TraceRow.ROW_TYPE_FUNC) { + FuncStruct.hoverFuncStruct = tr.onMouseHover(x, y, false) + } else if (tr.rowType === TraceRow.ROW_TYPE_HEAP) { + HeapStruct.hoverHeapStruct = tr.onMouseHover(x, y, false) + if (HeapStruct.hoverHeapStruct) { + tr.tip = `${ColorUtils.formatNumberComma(HeapStruct.hoverHeapStruct.heapsize!)} byte` + } + tr.setTipLeft(x, HeapStruct.hoverHeapStruct) + } else { + this.hoverStructNull(); + } + } else { + tr.onMouseLeave(x, y); + } + tr.drawObject(); + }) + } + + hoverStructNull() { + CpuStruct.hoverCpuStruct = undefined; + CpuFreqStruct.hoverCpuFreqStruct = undefined; + ThreadStruct.hoverThreadStruct = undefined; + FuncStruct.hoverFuncStruct = undefined; + } + + selectStructNull() { + CpuStruct.selectCpuStruct = undefined; + CpuFreqStruct.selectCpuFreqStruct = undefined; + ThreadStruct.selectThreadStruct = undefined; + FuncStruct.selectFuncStruct = undefined; + } + + documentOnClick = (ev: MouseEvent) => { + if (this.rangeSelect.isDrag()) { + return; + } + this.rowsEL?.querySelectorAll>("trace-row").forEach(it => it.rangeSelect = undefined) + this.selectStructNull(); + if (CpuStruct.hoverCpuStruct) { + CpuStruct.selectCpuStruct = CpuStruct.hoverCpuStruct + this.traceSheetEL?.displayCpuData(CpuStruct.hoverCpuStruct); + } else if (ThreadStruct.hoverThreadStruct) { + ThreadStruct.selectThreadStruct = ThreadStruct.hoverThreadStruct; + this.traceSheetEL?.displayThreadData(ThreadStruct.hoverThreadStruct) + } else if (FuncStruct.hoverFuncStruct) { + FuncStruct.selectFuncStruct = FuncStruct.hoverFuncStruct; + this.traceSheetEL?.displayFuncData(FuncStruct.hoverFuncStruct) + } else if (SportRuler.rulerFlagObj) { + + } else { + this.traceSheetEL?.setAttribute("mode", 'hidden'); + } + this.documentOnMouseMove(ev) + } + + connectedCallback() { + /** + * 监听时间轴区间变化 + */ + this.timerShaftEL?.addEventListener('range-change', this.timerShaftELRangeChange) + /** + * 监听rowsEL的滚动时间,刷新可见区域的trace-row组件的时间区间(将触发trace-row组件重绘) + */ + this.rowsEL?.addEventListener('scroll', this.rowsElOnScroll) + /** + * 监听document的mousemove事件 坐标通过换算后找到当前鼠标所在的trace-row组件,将坐标传入 + */ + document.addEventListener('mousemove', this.documentOnMouseMove) + document.addEventListener('mousedown', this.documentOnMouseDown) + document.addEventListener('mouseup', this.documentOnMouseUp) + document.addEventListener('click', this.documentOnClick) + } + + disconnectedCallback() { + this.timerShaftEL?.removeEventListener('range-change', this.timerShaftELRangeChange); + this.rowsEL?.removeEventListener('scroll', this.rowsElOnScroll); + document.removeEventListener('mousemove', this.documentOnMouseMove); + document.removeEventListener('click', this.documentOnClick); + } + + loadDatabaseUrl(url: string, complete?: Function) { + this.init({url: url}).then(() => { + let scrollTop = this.rowsEL?.scrollTop || 0 + let scrollHeight = this.rowsEL?.clientHeight || 0 + this.rowsEL?.querySelectorAll("trace-row").forEach((it: any) => { + let top = it.offsetTop - (this.rowsEL?.offsetTop || 0); + if (top + it.clientHeight > scrollTop && top + it.clientHeight < scrollTop + scrollHeight + it.clientHeight) { + (it as TraceRow).dataListCache.length = 0; + } + }) + if (complete) { + complete(); + } + }) + } + + loadDatabaseArrayBuffer(buf: ArrayBuffer, complete?: Function) { + this.init({buf}).then(() => { + let scrollTop = this.rowsEL?.scrollTop || 0 + let scrollHeight = this.rowsEL?.clientHeight || 0 + this.rowsEL?.querySelectorAll("trace-row").forEach((it: any) => { + let top = it.offsetTop - (this.rowsEL?.offsetTop || 0); + if (top + it.clientHeight > scrollTop && top + it.clientHeight < scrollTop + scrollHeight + it.clientHeight) { + (it as TraceRow).dataListCache.length = 0; + } + }) + if (complete) { + complete(); + } + }) + } + + init = async (param: { buf?: ArrayBuffer, url?: string }) => { + if (this.rowsEL) this.rowsEL.innerHTML = '' + this.traceSheetEL?.setAttribute("mode", "hidden") + this.timerShaftEL?.reset(); + procedurePool.clearCache(); + param.buf && await threadPool.initSqlite(param.buf); + param.url && await threadPool.initServer(param.url); + this.processThreads = await queryProcessThreads(); + this.processMem = await queryProcessMem() + this.processAsyncEvent = await getAsyncEvents() + await this.initTotalTime(); + let cpuObjs = await this.initCpu(); + await this.initCpuRate(); + let freqObjs = await this.initCpuFreq(); + let fpsObjs = await this.initFPS(); + let processObjs = await this.initProcess(); + this.rowsEL.dataSource = [...cpuObjs, ...freqObjs, ...fpsObjs, ...processObjs] + this.getVisibleRows().forEach(it => it.drawObject()); + } + initCpuRate = async () => { + let rates = await getCpuUtilizationRate(0, this.timerShaftEL?.totalNS || 0); + if (this.timerShaftEL) this.timerShaftEL.cpuUsage = rates; + } + initTotalTime = async () => { + let res = await queryTotalTime(); + if (this.timerShaftEL) { + this.timerShaftEL.totalNS = res[0].total + this.timerShaftEL.loadComplete = true; + } + } + initCpu = async () => { + let objs = []; + let array = await queryCpuMax(); + if (array && array.length > 0 && array[0]) { + let cpuMax = array[0].cpu + CpuStruct.cpuCount = cpuMax + 1; + for (let i1 = 0; i1 < CpuStruct.cpuCount; i1++) { + const cpuId = i1; + let traceRow = new TraceRowObject(); + traceRow.rowId = `${cpuId}` + traceRow.rowType = TraceRow.ROW_TYPE_CPU + traceRow.rowParentId = '' + traceRow.rowHeight = 40 + traceRow.frame = new Rect(0, 0, this.rowsEL.clientWidth - 248, traceRow.rowHeight) + traceRow.name = `Cpu ${cpuId}` + traceRow.supplier = () => queryCpuData(cpuId, 0, this.timerShaftEL?.totalNS || 0) + traceRow.onThreadHandler = ((row, ctx) => { + procedurePool.submitWithName("cpu", `cpu${cpuId}`, { + list: traceRow.must ? traceRow.dataList : undefined, + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: traceRow.frame + }, (res: any) => { + traceRow.dataListCache = res; + traceRow.must = false; + row.clearCanvas(); + row.c!.beginPath(); + row.drawLines(); + for (let i = 0; i < res.length; i++) { + CpuStruct.draw(ctx, res[i]) + } + row.drawSelection(); + row.c!.closePath(); + }) + }) + objs.push(traceRow) + } + } + return objs; + } + + initCpuFreq = async () => { + let objs = []; + let freqList = await queryCpuFreq(); + let freqMaxList = await queryCpuMaxFreq(); + CpuFreqStruct.maxFreq = freqMaxList[0].maxFreq; + let math = () => { + let units: Array = ["", "K", "M", "G", "T", "E"]; + let sb = " "; + CpuFreqStruct.maxFreqName = " "; + if (CpuFreqStruct.maxFreq > 0) { + let log10: number = Math.ceil(Math.log10(CpuFreqStruct.maxFreq)); + let pow10: number = Math.pow(10, log10); + let afterCeil: number = Math.ceil(CpuFreqStruct.maxFreq / (pow10 / 4)) * (pow10 / 4); + CpuFreqStruct.maxFreq = afterCeil; + let unitIndex: number = Math.floor(log10 / 3); + sb = `${afterCeil / Math.pow(10, unitIndex * 3)}${units[unitIndex + 1]}hz` + } + CpuFreqStruct.maxFreqName = sb.toString(); + } + math(); + for (let i = 0; i < freqList.length; i++) { + const it = freqList[i]; + let traceRow = new TraceRowObject(); + traceRow.rowId = `${it.cpu}` + traceRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ + traceRow.rowParentId = '' + traceRow.rowHeight = 40 + traceRow.frame = new Rect(0, 0, this.rowsEL.clientWidth - 248, traceRow.rowHeight) + traceRow.name = `Cpu ${it.cpu} Frequency`; + traceRow.supplier = () => queryCpuFreqData(it.cpu) + traceRow.onThreadHandler = (row, ctx) => { + procedurePool.submitWithName("freq", `freq${it.cpu}`, { + list: traceRow.must ? traceRow.dataList : undefined, + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: traceRow.frame + }, (res: any) => { + traceRow.dataListCache = res; + traceRow.must = false; + row.clearCanvas(); + row.drawLines(); + row.c!.beginPath(); + for (let i = 0; i < res.length; i++) { + CpuFreqStruct.draw(ctx, res[i]) + } + row.drawSelection(); + row.c!.closePath(); + let s = CpuFreqStruct.maxFreqName + let textMetrics = ctx.measureText(s); + row.c!.globalAlpha = 0.8 + row.c!.fillStyle = "#f0f0f0" + row.c!.fillRect(0, 5, textMetrics.width + 8, 18) + row.c!.globalAlpha = 1 + row.c!.fillStyle = "#333" + ctx.textBaseline = "middle" + ctx.fillText(maxFps, 4, 5 + 9) + }) + } + objs.push(traceRow) + } + return objs; + } + + initFPS = async () => { + let objs = []; + let fpsRow = new TraceRowObject(); + fpsRow.rowId = `fps` + fpsRow.rowType = TraceRow.ROW_TYPE_FPS + fpsRow.rowParentId = '' + FpsStruct.maxFps = 0 + fpsRow.rowHeight = 40 + fpsRow.frame = new Rect(0, 0, this.rowsEL.clientWidth - 248, fpsRow.rowHeight) + fpsRow.name = "FPS" + fpsRow.supplier = () => getFps() + fpsRow.onDrawHandler = (row, ctx) => { + if (fpsRow.dataListCache.length > 0) { + for (let i = 0; i < fpsRow.dataListCache.length; i++) { + FpsStruct.draw(ctx, fpsRow.dataListCache[i]) + } + } else { + if (fpsRow.dataList) { + for (let i = 0; i < fpsRow.dataList.length; i++) { + let it = fpsRow.dataList[i]; + if ((it.fps || 0) > FpsStruct.maxFps) { + FpsStruct.maxFps = it.fps || 0 + } + if (i === fpsRow.dataList.length - 1) { + it.dur = (TraceRow.range?.endNS || 0) - (it.startNS || 0) + } else { + it.dur = (fpsRow.dataList[i + 1].startNS || 0) - (it.startNS || 0) + } + if ((it.startNS || 0) + (it.dur || 0) > (TraceRow.range?.startNS || 0) && (it.startNS || 0) < (TraceRow.range?.endNS || 0)) { + FpsStruct.setFrame(fpsRow.dataList[i], 5, TraceRow.range?.startNS || 0, TraceRow.range?.endNS || 0, TraceRow.range?.totalNS || 0, fpsRow.frame) + if (i > 0 && ((fpsRow.dataList[i - 1].frame?.x || 0) == (fpsRow.dataList[i].frame?.x || 0) && (fpsRow.dataList[i - 1].frame?.width || 0) == (fpsRow.dataList[i].frame?.width || 0))) { + + } else { + fpsRow.dataListCache.push(fpsRow.dataList[i]) + FpsStruct.draw(ctx, fpsRow.dataList[i]) + } + } + } + } + } + if (ctx) { + let maxFps = FpsStruct.maxFps + "FPS" + let textMetrics = ctx.measureText(maxFps); + ctx.globalAlpha = 0.8 + ctx.fillStyle = "#f0f0f0" + ctx.fillRect(0, 5, textMetrics.width + 8, 18) + ctx.globalAlpha = 1 + ctx.fillStyle = "#333" + ctx.textBaseline = "middle" + ctx.fillText(maxFps, 4, 5 + 9) + } + } + objs.push(fpsRow) + return objs; + } + + /** + * 添加进程信息 + */ + initProcess = async () => { + let objs = []; + let processList = await queryProcess(); + let heapPidList = await queryHeapPid() + for (let i = 0; i < processList.length; i++) { + const it = processList[i]; + let processRow = new TraceRowObject(); + processRow.rowId = `${it.pid}` + processRow.rowType = TraceRow.ROW_TYPE_PROCESS + processRow.rowParentId = '' + processRow.frame = new Rect(0, 0, this.rowsEL.clientWidth - 248, processRow.rowHeight); + processRow.folder = true; + processRow.name = `${it.processName || "Process"} ${it.pid}`; + processRow.supplier = () => queryProcessData(it.pid || -1, 0, TraceRow.range?.totalNS || 0) + processRow.onThreadHandler = (row, ctx) => { + procedurePool.submitWithName("process", `process ${it.pid} ${it.processName}`, { + list: processRow.must ? processRow.dataList : undefined, + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: processRow.frame + }, (res: any) => { + processRow.dataListCache = res; + processRow.must = false; + row.clearCanvas(); + row.drawLines(); + row.c!.beginPath(); + for (let i = 0; i < res.length; i++) { + ProcessStruct.draw(ctx, res[i]) + } + row.drawSelection(); + row.c!.closePath(); + }) + } + objs.push(processRow); + if (heapPidList != undefined && Array.isArray(heapPidList) && heapPidList.filter((item) => { + return item.pid == it.pid + }).length > 0) { + /** + * 添加heap信息 + */ + let allHeapRow = new TraceRowObject(); + allHeapRow.rowParentId = `${it.pid}` + allHeapRow.rowHidden = !processRow.expansion + allHeapRow.rowHeight = 40 + allHeapRow.name = "All Heap Allocations"; + allHeapRow.folder = false; + allHeapRow.rowType = TraceRow.ROW_TYPE_HEAP + allHeapRow.frame = new Rect(0, 0, this.rowsEL.clientWidth - 248, allHeapRow.rowHeight) + allHeapRow.children = true + allHeapRow.supplier = () => queryHeapByPid(0, TraceRow.range?.totalNS || 0, it.pid || 0).then((res) => { + let heapList: HeapStruct[] = [] + let allocMap: Map = new Map() + let currentHeapSize = 0 + let maxHeapSize = 0; + for (let j = 0; j < res.length; j++) { + let struct = new HeapStruct(); + if (res[j].eventType == "AllocEvent") { + currentHeapSize += (res[j].heapsize || 0) + if (allocMap.has(res[j].addr || "")) { + allocMap.get(res[j].addr || "")?.push(res[j]) + } else { + allocMap.set(res[j].addr || "", [res[j]]) + } + } else if (res[j].eventType == "FreeEvent") { + if (allocMap.has(res[j].addr || "")) { + let allocList = allocMap.get(res[j].addr || ""); + if (allocList != undefined && allocList.length > 0) { + currentHeapSize -= allocList[allocList.length - 1].heapsize || 0 + } + } + } + if (currentHeapSize > maxHeapSize) { + maxHeapSize = currentHeapSize + } + struct.pid = it.pid + "" + struct.startTime = res[j].startTime + if (j != res.length - 1) { + struct.endTime = res[j + 1].startTime + } else { + struct.endTime = allHeapRow.range?.totalNS || 0 + } + struct.duration = (struct.endTime || 0) - (struct.startTime || 0) + struct.heapsize = currentHeapSize + heapList.push(struct) + } + for (let j = 0; j < heapList.length; j++) { + heapList[j].maxHeapSize = maxHeapSize + } + return heapList + }) + allHeapRow.onDrawHandler = ctx => { + if (allHeapRow.dataList) { + for (let i = 0; i < allHeapRow.dataList.length; i++) { + let it = allHeapRow.dataList[i]; + if ((it.startTime || 0) + (it.duration || 0) > (TraceRow.range?.startNS || 0) && (it.startTime || 0) < (TraceRow.range?.endNS || 0)) { + HeapStruct.setFrame(allHeapRow.dataList[i], 5, TraceRow.range?.startNS || 0, TraceRow.range?.endNS || 0, TraceRow.range?.totalNS || 0, allHeapRow.frame) + HeapStruct.draw(ctx, allHeapRow.dataList[i]) + } + } + } + } + objs.push(allHeapRow); + } + + /** + * 添加进程内存信息 + */ + let processMem = this.processMem.filter(mem => mem.pid === it.pid); + processMem.forEach(mem => { + let row = new TraceRowObject(); + row.rowId = `${mem.trackId}` + row.rowType = TraceRow.ROW_TYPE_MEM + row.rowParentId = `${it.pid}` + row.rowHidden = !processRow.expansion + row.rowHeight = 40 + row.frame = new Rect(0, 0, this.rowsEL.clientWidth - 248, row.rowHeight) + row.name = `${mem.trackName}`; + row.children = true; + row.supplier = () => queryProcessMemData(mem.trackId).then(res => { + let maxValue = Math.max(...res.map(it => it.value || 0)) + for (let j = 0; j < res.length; j++) { + res[j].maxValue = maxValue; + if (j == res.length - 1) { + res[j].duration = this.range?.totalNS || 0; + } else { + res[j].duration = (res[j + 1].startTime || 0) - (res[j].startTime || 0); + } + if (j > 0) { + res[j].delta = (res[j].value || 0) - (res[j - 1].value || 0); + } else { + res[j].delta = 0; + } + } + return res + }); + row.onThreadHandler = (r, ctx) => { + procedurePool.submitWithName("mem", `mem ${mem.trackId} ${mem.trackName}`, { + list: row.must ? row.dataList : undefined, + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: row.frame + }, (res: any) => { + row.dataListCache = res; + row.must = false; + r.clearCanvas(); + r.drawLines(); + r.c!.beginPath(); + for (let i = 0; i < res.length; i++) { + ProcessMemStruct.draw(ctx, res[i]) + } + r.drawSelection(); + r.c!.closePath(); + }) + } + objs.push(row); + }); + /** + * 添加进程线程信息 + */ + let threads = this.processThreads.filter(thread => thread.pid === it.pid && thread.tid != 0 && thread.threadName != null); + threads.forEach((thread, i) => { + let threadRow = new TraceRowObject(); + threadRow.rowId = `${thread.tid}` + threadRow.rowType = TraceRow.ROW_TYPE_THREAD + threadRow.rowParentId = `${it.pid}` + threadRow.rowHidden = !processRow.expansion + threadRow.rowHeight = 40 + threadRow.frame = new Rect(0, 0, this.rowsEL.clientWidth - 248, threadRow.rowHeight); + threadRow.name = `${thread.threadName} ${thread.tid}`; + threadRow.children = true; + threadRow.supplier = () => queryThreadData(thread.tid || 0).then(res => { + getFunDataByTid(thread.tid || 0).then(funs => { + if (funs.length > 0) { + let maxHeight = (Math.max(...funs.map(it => it.depth || 0)) + 1) * 20 + 20; + let funcRow = new TraceRowObject(); + funcRow.rowId = `${thread.tid}` + funcRow.rowType = TraceRow.ROW_TYPE_FUNC + funcRow.rowParentId = `${it.pid}` + funcRow.rowHidden = !processRow.expansion + funcRow.rowHeight = maxHeight; + funcRow.frame = new Rect(0, 0, this.rowsEL.clientWidth - 248, funcRow.rowHeight); + funcRow.name = `${thread.threadName} ${thread.tid}`; + funcRow.children = true; + funcRow.supplier = () => new Promise((resolve, reject) => resolve(funs)) + funcRow.onThreadHandler = (r, ctx) => { + procedurePool.submitWithName("func", `func ${thread.tid} ${thread.threadName}`, { + list: funcRow.must ? funcRow.dataList : undefined, + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: threadRow.frame + }, (res: any) => { + funcRow.must = false; + funcRow.dataListCache = res; + r.clearCanvas(); + r.drawLines(); + r.c!.beginPath(); + for (let i = 0; i < res.length; i++) { + FuncStruct.draw(ctx, res[i]) + } + r.drawSelection(); + r.c!.closePath(); + }) + } + } + }) + return res; + }) + threadRow.onThreadHandler = (r, ctx) => { + procedurePool.submitWithName("thread", `thread ${thread.tid} ${thread.threadName}`, { + list: threadRow.must ? threadRow.dataList : undefined, + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: threadRow.frame + }, (res: any) => { + threadRow.dataListCache = res; + threadRow.must = false; + r.clearCanvas(); + r.drawLines(); + r.c!.beginPath(); + for (let i = 0; i < res.length; i++) { + ThreadStruct.draw(ctx, res[i]) + } + r.drawSelection(); + r.c!.closePath(); + }) + } + objs.push(threadRow); + }) + } + return objs; + } + + insertAfter(newEl: HTMLElement, targetEl: HTMLElement) { + let parentEl = targetEl.parentNode; + if (parentEl!.lastChild == targetEl) { + parentEl!.appendChild(newEl); + } else { + parentEl!.insertBefore(newEl, targetEl.nextSibling); + } + } + + initHtml(): string { + return ` + +
+ + + +
+ `; + } + +} diff --git a/host/ide/src/trace/component/SpSystemTrace.ts b/host/ide/src/trace/component/SpSystemTrace.ts new file mode 100644 index 0000000000000000000000000000000000000000..9b8d6294092fddb4e9e23a9cfb71a2e1758d0437 --- /dev/null +++ b/host/ide/src/trace/component/SpSystemTrace.ts @@ -0,0 +1,1517 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../base-ui/BaseElement.js"; +import "./trace/TimerShaftElement.js"; +import "./trace/base/TraceRow.js"; +import { + getAsyncEvents, + getCpuUtilizationRate, + getFps, + getFunDataByTid, + getStatesProcessThreadData, + getStatesProcessThreadDataCount, + queryCpuData, + queryCpuFreq, + queryCpuFreqData, + queryCpuMax, + queryCpuMaxFreq, + queryHeapAllTable, + queryHeapByEventType, + queryHeapByPid, + queryHeapFrameCount, + queryHeapGroupByEvent, + queryHeapPid, + queryNativeHookProcess, + queryProcess, + queryProcessData, + queryProcessMem, + queryProcessMemData, + queryProcessThreads, + queryThreadData, + queryTotalTime, + threadPool +} from "../database/SqlLite.js"; +import {TraceRow} from "./trace/base/TraceRow.js"; +import {TimerShaftElement} from "./trace/TimerShaftElement.js"; +import {CpuStruct} from "../bean/CpuStruct.js"; +import {CpuFreqStruct} from "../bean/CpuFreqStruct.js"; +import {ProcessStruct} from "../bean/ProcessStruct.js"; +import {ColorUtils} from "./trace/base/ColorUtils.js"; +import "./trace/base/TraceSheet.js"; +import {TraceSheet} from "./trace/base/TraceSheet.js"; +import {ThreadStruct} from "../bean/ThreadStruct.js"; +import {ProcessMemStruct} from "../bean/ProcessMemStruct.js"; +import {FuncStruct} from "../bean/FuncStruct.js"; +import {FpsStruct} from "../bean/FpsStruct.js"; +import {RangeSelect} from "./trace/base/RangeSelect.js"; +import {SelectionParam} from "../bean/BoxSelection.js"; +import {HeapStruct} from "../bean/HeapStruct.js"; +import {procedurePool} from "../database/Procedure.js"; +import {Utils} from "./trace/base/Utils.js"; +import {SpApplication} from "../SpApplication.js"; +import {SPT} from "../bean/StateProcessThread.js"; +import {HeapTreeDataBean} from "../bean/HeapTreeDataBean.js"; +import {Flag} from "./trace/timer-shaft/Flag.js"; +import {SportRuler} from "./trace/timer-shaft/SportRuler.js"; +import {NativeEventHeap} from "../bean/NativeHook.js"; + +@element('sp-system-trace') +export class SpSystemTrace extends BaseElement { + static scrollViewWidth = 0 + static isCanvasOffScreen = true; + static SPT_DATA: Array = []; + static EVENT_HEAP: Array = []; + static HEAP_FRAME_DATA: Array = []; + rowsEL: HTMLDivElement | undefined | null; + spacerEL: HTMLDivElement | undefined | null; + visibleRows: Array> = []; + keyboardEnable = true; + currentRowType = "";/*保存当前鼠标所在行的类型*/ + observerScrollHeightEnable: boolean = false; + observerScrollHeightCallback: Function | undefined; + // @ts-ignore + observer = new ResizeObserver((entries) => { + if (this.observerScrollHeightEnable && this.observerScrollHeightCallback) { + this.observerScrollHeightCallback(); + } + }); + isMousePointInSheet = false; + hoverFlag: Flag | undefined | null = undefined + selectFlag: Flag | undefined | null = undefined + public timerShaftEL: TimerShaftElement | null | undefined; + private traceSheetEL: TraceSheet | undefined | null; + private rangeSelect!: RangeSelect; + private processThreads: Array = [] + private processAsyncEvent: Array = [] + private processMem: Array = [] + + initElements(): void { + this.rowsEL = this.shadowRoot?.querySelector('.rows'); + this.spacerEL = this.shadowRoot?.querySelector('.spacer'); + this.timerShaftEL = this.shadowRoot?.querySelector('.timer-shaft'); + this.traceSheetEL = this.shadowRoot?.querySelector('.trace-sheet'); + this.rangeSelect = new RangeSelect(this.timerShaftEL); + this.rangeSelect.rowsEL = this.rowsEL; + document?.addEventListener("triangle-flag", (event: any) => { + this.timerShaftEL?.drawTriangle(event.detail.time, event.detail.type); + }) + + document?.addEventListener("flag-change", (event: any) => { + this.timerShaftEL?.modifyFlagList(event.detail) + if (event.detail.hidden) { + this.selectFlag = undefined; + this.traceSheetEL?.setAttribute("mode", 'hidden'); + this.visibleRows.forEach(it => it.draw(true)); + } + }) + + SpSystemTrace.scrollViewWidth = this.getScrollWidth(); + this.rangeSelect.selectHandler = (rows, refreshCheckBox) => { + if (rows.length == 0) { + this.rowsEL!.querySelectorAll>("trace-row").forEach(it => { + it.checkType = "-1" + }) + this.getVisibleRows().forEach(it => { + it.draw(true); + }); + this.traceSheetEL?.setAttribute("mode", 'hidden'); + return; + } + if (refreshCheckBox) { + if (rows.length > 0) { + this.rowsEL?.querySelectorAll>("trace-row").forEach(row => row.checkType = "0") + rows.forEach(it => it.checkType = "2") + } else { + this.rowsEL?.querySelectorAll>("trace-row").forEach(row => row.checkType = "-1") + return + } + } + let selection = new SelectionParam(); + selection.cpus = []; + selection.threadIds = []; + selection.funTids = []; + selection.trackIds = []; + selection.leftNs = 0; + selection.rightNs = 0; + let native_memory = ["All Heap & Anonymous VM", "All Heap", "All Anonymous VM"]; + rows.forEach(it => { + if (it.rowType == TraceRow.ROW_TYPE_CPU) { + selection.cpus.push(parseInt(it.rowId!)) + } else if (it.rowType == TraceRow.ROW_TYPE_PROCESS) { + this.rowsEL?.querySelectorAll>(`trace-row[row-parent-id='${it.rowId}']`).forEach(th => { + th.rangeSelect = true; + th.checkType = "2" + selection.threadIds.push(parseInt(th.rowId!)) + }) + } else if (it.rowType == TraceRow.ROW_TYPE_NATIVE_MEMORY) { + this.rowsEL?.querySelectorAll>(`trace-row[row-parent-id='${it.rowId}']`).forEach(th => { + th.rangeSelect = true; + th.checkType = "2" + selection.nativeMemory.push(th.rowId!); + }) + }else if (it.rowType == TraceRow.ROW_TYPE_THREAD) { + selection.threadIds.push(parseInt(it.rowId!)) + } else if (it.rowType == TraceRow.ROW_TYPE_FUNC) { + selection.funTids.push(parseInt(it.rowId!)) + } else if (it.rowType == TraceRow.ROW_TYPE_MEM) { + selection.trackIds.push(parseInt(it.rowId!)) + } else if (it.rowType == TraceRow.ROW_TYPE_FPS) { + selection.hasFps = true; + } else if (it.rowType == TraceRow.ROW_TYPE_HEAP) { + if (native_memory.indexOf(it.rowId ?? "") != -1) { + selection.nativeMemory.push(it.rowId!); + } else { + selection.heapIds.push(parseInt(it.rowId!)) + } + } + }) + selection.leftNs = TraceRow.rangeSelectObject?.startNS || 0; + selection.rightNs = TraceRow.rangeSelectObject?.endNS || 0; + this.traceSheetEL?.boxSelection(selection); + } + // @ts-ignore + new ResizeObserver((entries) => { + let width = entries[0].contentRect.width - 1 - SpSystemTrace.scrollViewWidth; + requestAnimationFrame(() => { + this.timerShaftEL?.updateWidth(width) + this.shadowRoot!.querySelectorAll>("trace-row").forEach(it => it.updateWidth(width)) + }) + }).observe(this); + + new ResizeObserver((entries) => { + this.getVisibleRows().forEach(it => { + it.draw(true); + }); + if (this.traceSheetEL!.getAttribute("mode") == "hidden") { + this.timerShaftEL?.removeTriangle("triangle") + } + }).observe(this.rowsEL!); + } + + getScrollWidth() { + let totalScrollDiv, scrollDiv, overflowDiv = document.createElement('div'); + overflowDiv.style.cssText = 'position:absolute; top:-2000px;width:200px; height:200px; overflow:hidden;'; + totalScrollDiv = document.body.appendChild(overflowDiv).clientWidth; + overflowDiv.style.overflowY = 'scroll'; + scrollDiv = overflowDiv.clientWidth; + document.body.removeChild(overflowDiv); + return totalScrollDiv - scrollDiv; + } + + getVisibleRows(): Array> { + let scrollTop = this.rowsEL?.scrollTop || 0; + let scrollHeight = this.rowsEL?.clientHeight || 0; + let res = [...this.rowsEL!.querySelectorAll>("trace-row")].filter((it) => { + let tr = (it as TraceRow); + let top = it.offsetTop - (this.rowsEL?.offsetTop || 0); + if ((top + it.clientHeight > scrollTop && top + it.clientHeight < scrollTop + scrollHeight + it.clientHeight) || it.collect) { + it.sleeping = false; + return true + } else { + if (!it.hasAttribute("collect-type")) { + it.sleeping = true; + } + return false; + } + }) + this.visibleRows = res; + return res; + } + + timerShaftELFlagClickHandler = (flag: Flag | undefined | null) => { + if (flag) { + setTimeout(() => { + this.traceSheetEL?.displayFlagData(flag); + }, 100) + } + } + + timerShaftELFlagChange = (hoverFlag: Flag | undefined | null, selectFlag: Flag | undefined | null) => { + this.hoverFlag = hoverFlag; + this.selectFlag = selectFlag; + this.visibleRows.forEach(it => it.draw(true)); + } + + timerShaftELRangeChange = (e: any) => { + TraceRow.range = e; + //在rowsEL显示范围内的 trace-row组件将收到时间区间变化通知 + for (let i = 0; i < this.visibleRows.length; i++) { + this.visibleRows[i].draw(); + } + } + + rowsElOnScroll = (e: any) => { + this.hoverStructNull(); + this.visibleRows = this.getVisibleRows(); + for (let index = 0; index < this.visibleRows.length; index++) { + if (index == 0 || index == this.visibleRows.length - 1) { + this.visibleRows[index].isHover = false; + } + } + } + + documentOnMouseDown = (ev: MouseEvent) => { + if (this.isMouseInSheet(ev)) return; + this.observerScrollHeightEnable = false; + if (ev.offsetX > this.timerShaftEL!.canvas!.offsetLeft) { + this.rangeSelect.mouseDown(ev) + this.timerShaftEL?.documentOnMouseDown(ev) + this.visibleRows.forEach(it => { + it.draw(); + }) + } + } + + documentOnMouseUp = (ev: MouseEvent) => { + this.rangeSelect.isMouseDown = false; + if (this.isMouseInSheet(ev)) return; + this.rangeSelect.mouseUp(ev); + this.timerShaftEL?.documentOnMouseUp(ev) + } + + documentOnMouseOut = (ev: MouseEvent) => { + if (this.isMouseInSheet(ev)) return; + if (ev.offsetX > this.timerShaftEL!.canvas!.offsetLeft) { + this.timerShaftEL?.documentOnMouseOut(ev) + } + } + + documentOnKeyPress = (ev: KeyboardEvent) => { + if (this.isMousePointInSheet) { + return; + } + this.observerScrollHeightEnable = false; + this.keyboardEnable && this.timerShaftEL!.documentOnKeyPress(ev); + } + + documentOnKeyUp = (ev: KeyboardEvent) => { + if (this.isMousePointInSheet) { + return; + } + this.observerScrollHeightEnable = false; + this.keyboardEnable && this.timerShaftEL!.documentOnKeyUp(ev); + if (ev.code == "Enter") { + if (ev.shiftKey) { + this.dispatchEvent(new CustomEvent("previous-data", { + detail: {} + })); + } else { + this.dispatchEvent(new CustomEvent("next-data", { + detail: {} + })); + } + } + } + + isMouseInSheet = (ev: MouseEvent) => { + this.isMousePointInSheet = this.traceSheetEL?.getAttribute("mode") != "hidden" && ev.offsetX > this.traceSheetEL!.offsetLeft && ev.offsetY > this.traceSheetEL!.offsetTop; + return this.isMousePointInSheet; + } + + favoriteChangeHandler = (row: TraceRow) => { + this.getVisibleRows(); + } + + selectChangeHandler = (rows: Array>) => { + this.rangeSelect.rangeTraceRow = rows; + this.rangeSelect.selectHandler?.(this.rangeSelect.rangeTraceRow, false); + } + + documentOnMouseMove = (ev: MouseEvent) => { + if (this.isMouseInSheet(ev)) return; + let rows = this.visibleRows; + if (this.timerShaftEL?.isScaling()) { + return; + } + this.timerShaftEL?.documentOnMouseMove(ev) + this.rangeSelect.mouseMove(rows, ev); + if (this.rangeSelect.isMouseDown) { + for (let i = 0; i < rows.length; i++) { + rows[i].tipEL!.style.display = "none"; + rows[i].draw(true); + } + } else { + for (let i = 0; i < rows.length; i++) { + let tr = rows[i]; + let rowsELScrollTop = this.rowsEL?.scrollTop || 0; + let x = ev.offsetX - (tr.canvasContainer?.offsetLeft || 0); + let y = ev.offsetY - (tr.canvasContainer?.offsetTop || 0) + rowsELScrollTop; + if ((!tr.collect && x > tr.frame.x && x < tr.frame.x + tr.frame.width && ev.offsetY + rowsELScrollTop > tr.offsetTop && ev.offsetY + rowsELScrollTop < tr.offsetTop + tr.frame.height) || + (tr.collect && x > tr.frame.x && x < tr.frame.x + tr.frame.width && ev.offsetY > tr.offsetTop - 48 && ev.offsetY < tr.offsetTop - 48 + tr.frame.height)) { + tr.isHover = true; + tr.hoverX = x; + tr.hoverY = tr.collect ? (ev.offsetY + 48 - tr.offsetTop) : y; + if (tr.rowType === TraceRow.ROW_TYPE_CPU) { + this.currentRowType = TraceRow.ROW_TYPE_CPU; + if (CpuStruct.hoverCpuStruct) { + tr.tip = `P:${CpuStruct.hoverCpuStruct.processName || "Process"} [${CpuStruct.hoverCpuStruct.processId}]T:${CpuStruct.hoverCpuStruct.name} [${CpuStruct.hoverCpuStruct.tid}]`; + } + tr.setTipLeft(x, CpuStruct.hoverCpuStruct) + } else if (tr.rowType === TraceRow.ROW_TYPE_CPU_FREQ) { + this.currentRowType = TraceRow.ROW_TYPE_CPU_FREQ; + if (CpuFreqStruct.hoverCpuFreqStruct) { + tr.tip = `${ColorUtils.formatNumberComma(CpuFreqStruct.hoverCpuFreqStruct.value!)} kHz` + } + tr.setTipLeft(x, CpuFreqStruct.hoverCpuFreqStruct) + } else if (tr.rowType === TraceRow.ROW_TYPE_THREAD) { + this.currentRowType = TraceRow.ROW_TYPE_THREAD; + } else if (tr.rowType === TraceRow.ROW_TYPE_FUNC) { + this.currentRowType = TraceRow.ROW_TYPE_FUNC; + } else if (tr.rowType === TraceRow.ROW_TYPE_HEAP) { + this.currentRowType = TraceRow.ROW_TYPE_HEAP; + if (HeapStruct.hoverHeapStruct) { + if (tr.drawType === 1) { + tr.tip = `${HeapStruct.hoverHeapStruct.heapsize}` + } else { + tr.tip = `${Utils.getByteWithUnit(HeapStruct.hoverHeapStruct.heapsize!)}` + } + } + tr.setTipLeft(x, HeapStruct.hoverHeapStruct) + } else { + this.hoverStructNull(); + } + tr.draw(true); + } else { + tr.onMouseLeave(x, y); + tr.isHover = false; + tr.hoverX = x; + tr.hoverY = y; + } + + } + if (ev.offsetX > this.timerShaftEL!.canvas!.offsetLeft! + && ev.offsetX < this.timerShaftEL!.canvas!.offsetLeft! + this.timerShaftEL!.canvas!.offsetWidth! + && ev.offsetY > this.rowsEL!.offsetTop + && ev.offsetY < this.rowsEL!.offsetTop + this.rowsEL!.offsetHeight + ) { + } else { + this.hoverStructNull(); + for (let i = 0, len = rows.length; i < len; i++) { + if (!(rows[i].rowType === TraceRow.ROW_TYPE_PROCESS) && this.currentRowType === rows[i].rowType) { // + rows[i].draw(true); + } + } + } + } + } + + hoverStructNull() { + CpuStruct.hoverCpuStruct = undefined; + CpuFreqStruct.hoverCpuFreqStruct = undefined; + ThreadStruct.hoverThreadStruct = undefined; + FuncStruct.hoverFuncStruct = undefined; + } + + selectStructNull() { + CpuStruct.selectCpuStruct = undefined; + CpuStruct.wakeupBean = null; + CpuFreqStruct.selectCpuFreqStruct = undefined; + ThreadStruct.selectThreadStruct = undefined; + FuncStruct.selectFuncStruct = undefined; + } + + documentOnClick = (ev: MouseEvent) => { + if (this.isMouseInSheet(ev)) return; + if (this.rangeSelect.isDrag()) { + return; + } + this.onClickHandler(); + this.documentOnMouseMove(ev) + } + + onClickHandler(){ + this.rowsEL?.querySelectorAll>("trace-row").forEach(it => it.rangeSelect = false) + this.selectStructNull(); + let threadClickHandler: any; + let cpuClickHandler: any; + threadClickHandler = (d: ThreadStruct) => { + this.observerScrollHeightEnable = false; + this.goProcess(`${d.cpu}`, "", "cpu", true); + let row = this.shadowRoot!.querySelector>(`trace-row[row-id='${d.pid}'][row-type='process'][folder]`); + if (row) { + row.expansion = false; + } + let cpuRow = this.rowsEL?.querySelectorAll>(`trace-row[row-id='${d.cpu}'][row-type='cpu']`)[0]; + let findEntry = cpuRow!.dataList!.find(it => it.startTime === d.startTime); + this.hoverStructNull(); + this.selectStructNull(); + CpuStruct.hoverCpuStruct = findEntry; + CpuStruct.selectCpuStruct = findEntry; + cpuRow!.draw(); + this.traceSheetEL?.displayCpuData(CpuStruct.selectCpuStruct!, (wakeUpBean) => { + CpuStruct.wakeupBean = wakeUpBean; + this.visibleRows.forEach(it => it.draw()); + }, cpuClickHandler); + } + let scrollTimer: any; + cpuClickHandler = (d: CpuStruct) => { + this.observerScrollHeightEnable = true; + let threadRow = this.rowsEL?.querySelectorAll>(`trace-row[row-id='${d.tid}'][row-type='thread']`)[0]; + this.goProcess(`${d.tid}`, `${d.processId}`, "thread", true) + this.observerScrollHeightCallback = () => { + if (threadRow!.isComplete) { + let findEntry = threadRow!.dataList!.find((dat) => dat.startTime === d.startTime); + this.hoverStructNull(); + this.selectStructNull(); + ThreadStruct.hoverThreadStruct = findEntry; + ThreadStruct.selectThreadStruct = findEntry; + threadRow!.draw(); + this.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct!, threadClickHandler); + // clearTimeout(scrollTimer); + this.goProcess(`${d.tid}`, `${d.processId}`, "thread", true) + } else { + threadRow!.onComplete = () => { + let findEntry = threadRow!.dataList!.find((dat) => dat.startTime === d.startTime); + this.hoverStructNull(); + this.selectStructNull(); + ThreadStruct.hoverThreadStruct = findEntry; + ThreadStruct.selectThreadStruct = findEntry; + threadRow!.draw(); + this.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct!, threadClickHandler); + clearTimeout(scrollTimer); + scrollTimer = setTimeout(() => this.goProcess(`${d.tid}`, `${d.processId}`, "thread", false), 100) + } + } + } + } + + if (CpuStruct.hoverCpuStruct) { + CpuStruct.selectCpuStruct = CpuStruct.hoverCpuStruct + this.traceSheetEL?.displayCpuData(CpuStruct.selectCpuStruct, (wakeUpBean) => { + CpuStruct.wakeupBean = wakeUpBean; + this.visibleRows.forEach(it => it.draw()); + }, cpuClickHandler); + this.timerShaftEL?.modifyFlagList(undefined); + } else if (ThreadStruct.hoverThreadStruct) { + ThreadStruct.selectThreadStruct = ThreadStruct.hoverThreadStruct; + this.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct, threadClickHandler); + this.timerShaftEL?.modifyFlagList(undefined); + } else if (FuncStruct.hoverFuncStruct) { + FuncStruct.selectFuncStruct = FuncStruct.hoverFuncStruct; + this.traceSheetEL?.displayFuncData(FuncStruct.hoverFuncStruct) + this.timerShaftEL?.modifyFlagList(undefined); + } else { + this.observerScrollHeightEnable = false; + this.selectFlag = null; + if (!SportRuler.isMouseInSportRuler) { + this.traceSheetEL?.setAttribute("mode", 'hidden'); + this.getVisibleRows().forEach(it => it.draw(true)); + } + } + } + + connectedCallback() { + /** + * 监听时间轴区间变化 + */ + this.timerShaftEL!.rangeChangeHandler = this.timerShaftELRangeChange; + this.timerShaftEL!.flagChangeHandler = this.timerShaftELFlagChange; + this.timerShaftEL!.flagClickHandler = this.timerShaftELFlagClickHandler; + /** + * 监听rowsEL的滚动时间,刷新可见区域的trace-row组件的时间区间(将触发trace-row组件重绘) + */ + this.rowsEL?.addEventListener('scroll', this.rowsElOnScroll) + /** + * 监听document的mousemove事件 坐标通过换算后找到当前鼠标所在的trace-row组件,将坐标传入 + */ + this.addEventListener('mousemove', this.documentOnMouseMove) + this.addEventListener('click', this.documentOnClick) + this.addEventListener('mousedown', this.documentOnMouseDown) + this.addEventListener('mouseup', this.documentOnMouseUp) + this.addEventListener('mouseout', this.documentOnMouseOut) + document.addEventListener('keypress', this.documentOnKeyPress) + document.addEventListener('keyup', this.documentOnKeyUp) + SpApplication.skinChange2 = (val: boolean) => { + this.timerShaftEL?.render() + this.rowsEL!.querySelectorAll>(`trace-row:not([sleeping])`).forEach(it => { + this.hoverStructNull(); + it.draw(); + }) + } + } + + goProcess(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true) { + let row = this.shadowRoot!.querySelector>(`trace-row[row-id='${rowParentId}'][folder]`); + if (row) { + row.expansion = true + } + let rootRow = this.shadowRoot!.querySelector>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`); + this.rowsEL!.scroll({ + top: rootRow!.offsetTop - this.rowsEL!.offsetTop - this.rowsEL!.offsetHeight + rootRow!.offsetHeight, + left: 0, + behavior: smooth ? "smooth" : undefined + }) + } + + rowScrollTo(offset: number, callback: Function) { + const fixedOffset = offset; + const onScroll = () => { + if (this.rowsEL!.scrollTop === fixedOffset) { + this.rowsEL!.removeEventListener('scroll', onScroll) + callback() + } + } + + this.rowsEL!.addEventListener('scroll', onScroll) + onScroll() + this.rowsEL!.scrollTo({ + top: offset, + behavior: 'smooth' + }) + } + + disconnectedCallback() { + this.timerShaftEL?.removeEventListener('range-change', this.timerShaftELRangeChange); + this.rowsEL?.removeEventListener('scroll', this.rowsElOnScroll); + this.removeEventListener('mousemove', this.documentOnMouseMove); + this.removeEventListener('click', this.documentOnClick); + this.removeEventListener('mousedown', this.documentOnMouseDown) + this.removeEventListener('mouseup', this.documentOnMouseUp) + this.removeEventListener('mouseout', this.documentOnMouseOut) + document.removeEventListener('keypress', this.documentOnKeyPress) + document.removeEventListener('keyup', this.documentOnKeyUp) + } + + loadDatabaseUrl(url: string, progress: Function, complete?: ((res: { status: boolean, msg: string }) => void) | undefined) { + this.init({url: url}, progress).then((res) => { + if (complete) { + complete(res); + } + }) + } + + loadDatabaseArrayBuffer(buf: ArrayBuffer, progress: ((name: string, percent: number) => void), complete?: ((res: { status: boolean, msg: string }) => void) | undefined) { + this.init({buf}, progress).then((res) => { + let scrollTop = this.rowsEL?.scrollTop || 0 + let scrollHeight = this.rowsEL?.clientHeight || 0 + this.rowsEL?.querySelectorAll("trace-row").forEach((it: any) => { + this.observer.observe(it); + }) + if (complete) { + complete(res); + } + }) + } + + search(query: string) { + this.shadowRoot?.querySelectorAll>('trace-row').forEach(item => { + if (query == null || query == undefined || query == '') { + if (item.rowType == TraceRow.ROW_TYPE_CPU || + item.rowType == TraceRow.ROW_TYPE_CPU_FREQ || + item.rowType == TraceRow.ROW_TYPE_NATIVE_MEMORY || + item.rowType == TraceRow.ROW_TYPE_FPS || + item.rowType == TraceRow.ROW_TYPE_PROCESS) { + item.expansion = false; + item.rowHidden = false; + } else { + item.rowHidden = true; + } + } else { + if (item.name.toLowerCase().indexOf(query.toLowerCase()) >= 0) { + item.rowHidden = false; + } else { + item.rowHidden = true; + } + } + }) + this.getVisibleRows().forEach(it => it.rowHidden = false && it.draw(true)) + } + + searchCPU(query: string): Array { + let searchResults: Array = [] + this.rowsEL!.querySelectorAll>(`trace-row[row-type='cpu']`).forEach(item => { + let res = item!.dataList!.filter(it => (it.name && it.name.search(query) >= 0) || it.tid == query + || it.processId == query + || (it.processName && it.processName.search(query) >= 0) + ) + searchResults.push(...res); + }) + searchResults.sort((a, b) => (a.startTime || 0) - (b.startTime || 0)); + return searchResults; + } + + showPreCpuStruct(currentIndex: number, cpuStructs: Array): number { + if (cpuStructs.length == 0) { + return 0; + } + let findIndex = -1; + for (let i = cpuStructs.length - 1; i >= 0; i--) { + let it = cpuStructs[i]; + if (i < currentIndex && (it.startTime!) >= (TraceRow.range!.startNS) && (it.startTime!) + (it.dur!) <= (TraceRow.range!.endNS)) { + findIndex = i; + break; + } + } + if (findIndex >= 0) { + let findEntry = cpuStructs[findIndex]; + CpuStruct.selectCpuStruct = findEntry; + this.rowsEL!.querySelectorAll>(`trace-row[row-type='cpu']`).forEach(item =>{ + item.highlight = item.rowId == `${findEntry.cpu}`; + item.draw(true); + }) + this.timerShaftEL?.drawTriangle(findEntry.startTime||0, "inverted"); + } else { + for (let i = cpuStructs.length - 1; i >= 0; i--) { + let it = cpuStructs[i]; + if ((it.startTime! + it.dur!) < (TraceRow.range!.startNS)) { + findIndex = i; + break; + } + } + let findEntry: CpuStruct; + if (findIndex == -1) { + findIndex = cpuStructs.length - 1; + } + findEntry = cpuStructs[findIndex]; + CpuStruct.selectCpuStruct = findEntry; + let startNS = this.timerShaftEL?.getRange()?.startNS || 0; + let endNS = this.timerShaftEL?.getRange()?.endNS || 0; + let harfDur = Math.trunc((endNS - startNS) / 2 - findEntry.dur! / 2); + this.timerShaftEL?.setRangeNS(findEntry.startTime! - harfDur, findEntry.startTime! + findEntry.dur! + harfDur); + this.rowsEL!.querySelectorAll>(`trace-row[row-type='cpu']`).forEach(item => { + item.highlight = item.rowId == `${findEntry.cpu}`; + item.draw(true) + }) + this.timerShaftEL?.drawTriangle(findEntry.startTime||0, "inverted"); + } + CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; + this.onClickHandler(); + return findIndex; + } + + showNextCpuStruct(currentIndex: number, cpuStructs: Array): number { + if (cpuStructs.length == 0) { + return 0; + } + let findIndex = cpuStructs.findIndex((it, idx) => { + return idx > currentIndex && (it.startTime!) >= (TraceRow.range!.startNS) && (it.startTime!) + (it.dur!) <= (TraceRow.range!.endNS) + }) + if (findIndex >= 0) { + let findEntry = cpuStructs[findIndex]; + CpuStruct.selectCpuStruct = findEntry; + this.rowsEL!.querySelectorAll>(`trace-row[row-type='cpu']`).forEach(item =>{ + item.highlight = item.rowId == `${findEntry.cpu}`; + item.draw(true); + }) + this.timerShaftEL?.drawTriangle(findEntry.startTime||0, "inverted"); + } else { + findIndex = cpuStructs.findIndex((it) => (it.startTime!) > (TraceRow.range!.endNS)) + let findEntry: CpuStruct; + if (findIndex == -1) { + findIndex = 0; + } + findEntry = cpuStructs[findIndex]; + CpuStruct.selectCpuStruct = findEntry; + let startNS = this.timerShaftEL?.getRange()?.startNS || 0; + let endNS = this.timerShaftEL?.getRange()?.endNS || 0; + let harfDur = Math.trunc((endNS - startNS) / 2 - findEntry.dur! / 2); + this.timerShaftEL?.setRangeNS(findEntry.startTime! - harfDur, findEntry.startTime! + findEntry.dur! + harfDur); + this.rowsEL!.querySelectorAll>(`trace-row[row-type='cpu']`).forEach(item => { + item.highlight = item.rowId == `${findEntry.cpu}`; + item.draw(true); + }) + this.timerShaftEL?.drawTriangle(findEntry.startTime||0, "inverted"); + } + CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; + this.onClickHandler(); + return findIndex; + } + + reset(progress: Function | undefined | null) { + if (this.rowsEL) this.rowsEL.innerHTML = '' + this.spacerEL!.style.height = '0px'; + this.rangeSelect.rangeTraceRow = []; + CpuStruct.wakeupBean = undefined; + this.selectStructNull(); + this.hoverStructNull(); + this.traceSheetEL?.setAttribute("mode", "hidden") + progress && progress("rest timershaft", 8); + this.timerShaftEL?.reset(); + progress && progress("clear cache", 10); + procedurePool.clearCache(); + } + + init = async (param: { buf?: ArrayBuffer, url?: string }, progress: Function) => { + progress("Load database", 6); + this.reset(progress); + if (param.buf) { + let {status, msg} = await threadPool.initSqlite(param.buf, progress); + if (!status) { + return {status: false, msg: msg} + } + } + if (param.url) { + let {status, msg} = await threadPool.initServer(param.url, progress); + if (!status) { + return {status: false, msg: msg} + } + } + + progress("load process threads", 50); + this.processThreads = await queryProcessThreads(); + progress("process memory", 60); + this.processMem = await queryProcessMem() + progress("async event", 63); + this.processAsyncEvent = await getAsyncEvents() + progress("time range", 65); + await this.initTotalTime(); + progress("cpu", 70); + await this.initCpu(); + progress("cpu rate", 75); + await this.initCpuRate(); + progress("cpu freq", 80); + await this.initCpuFreq(); + progress("fps", 85); + await this.initFPS(); + progress("native memory", 87); + await this.initNativeMemory(); + progress("process", 90); + await this.initProcess(); + progress("process", 93); + await this.initProcessThreadStateData(progress); + await this.initHeapStateData(progress) + progress("display", 95); + this.getVisibleRows().forEach(it => { + it.draw(); + }); + this.processThreads.length = 0; + this.processMem.length = 0; + this.processAsyncEvent.length = 0; + this.rowsEL?.querySelectorAll>("trace-row").forEach((it: any) => { + it.addEventListener('expansion-change', () => { + this.getVisibleRows().forEach(it2 => it2.draw()); + }) + }) + progress("completed", 100); + return {status: true, msg: "success"} + } + + initCpuRate = async () => { + let rates = await getCpuUtilizationRate(0, this.timerShaftEL?.totalNS || 0); + if (this.timerShaftEL) this.timerShaftEL.cpuUsage = rates; + } + + initTotalTime = async () => { + let res = await queryTotalTime(); + if (this.timerShaftEL) { + this.timerShaftEL.totalNS = res[0].total + this.timerShaftEL.loadComplete = true; + } + } + + initCpu = async () => { + let array = await queryCpuMax(); + if (array && array.length > 0 && array[0]) { + let cpuMax = array[0].cpu + CpuStruct.cpuCount = cpuMax + 1; + for (let i1 = 0; i1 < CpuStruct.cpuCount; i1++) { + const cpuId = i1; + let traceRow = new TraceRow({ + canvasNumber: 1, + alpha: true, + contextId: '2d', + isOffScreen: SpSystemTrace.isCanvasOffScreen + }); + traceRow.rowId = `${cpuId}` + traceRow.rowType = TraceRow.ROW_TYPE_CPU + traceRow.rowParentId = '' + traceRow.style.height = '40px' + traceRow.name = `Cpu ${cpuId}` + traceRow.favoriteChangeHandler = this.favoriteChangeHandler; + traceRow.selectChangeHandler = this.selectChangeHandler; + traceRow.supplier = () => queryCpuData(cpuId, 0, this.timerShaftEL?.totalNS || 0) + traceRow.onThreadHandler = ((useCache: boolean) => { + procedurePool.submitWithName(`cpu${cpuId % procedurePool.cpusLen.length}`, `cpu${cpuId}`, { + list: traceRow.must ? traceRow.dataList : undefined, + offscreen: traceRow.must ? traceRow.offscreen[0] : undefined,//是否离屏 + dpr: traceRow.dpr,//屏幕dpr值 + xs: TraceRow.range?.xs,//线条坐标信息 + isHover: traceRow.isHover, + flagMoveInfo: this.hoverFlag, + flagSelectedInfo: this.selectFlag, + hoverX: traceRow.hoverX, + hoverY: traceRow.hoverY, + canvasWidth: traceRow.canvasWidth, + canvasHeight: traceRow.canvasHeight, + hoverCpuStruct: CpuStruct.hoverCpuStruct, + selectCpuStruct: CpuStruct.selectCpuStruct, + wakeupBean: CpuStruct.wakeupBean, + isRangeSelect: traceRow.rangeSelect, + rangeSelectObject: TraceRow.rangeSelectObject, + useCache: useCache, + lineColor: traceRow.getLineColor(), + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: traceRow.frame + }, traceRow.must && traceRow.args.isOffScreen ? traceRow.offscreen[0] : undefined, (res: any, hover: any) => { + traceRow.must = false; + if (traceRow.args.isOffScreen == true) { + if (traceRow.isHover) { + CpuStruct.hoverCpuStruct = hover; + this.visibleRows.filter(it => it.rowType === TraceRow.ROW_TYPE_CPU && it.name !== traceRow.name).forEach(it => it.draw(true)); + } + return; + } + }) + }) + this.rowsEL?.appendChild(traceRow) + } + } + } + + initCpuFreq = async () => { + let freqList = await queryCpuFreq(); + let freqMaxList = await queryCpuMaxFreq(); + CpuFreqStruct.maxFreq = freqMaxList[0].maxFreq; + let math = () => { + let units: Array = ["", "K", "M", "G", "T", "E"]; + let sb = " "; + CpuFreqStruct.maxFreqName = " "; + if (CpuFreqStruct.maxFreq > 0) { + let log10: number = Math.ceil(Math.log10(CpuFreqStruct.maxFreq)); + let pow10: number = Math.pow(10, log10); + let afterCeil: number = Math.ceil(CpuFreqStruct.maxFreq / (pow10 / 4)) * (pow10 / 4); + CpuFreqStruct.maxFreq = afterCeil; + let unitIndex: number = Math.floor(log10 / 3); + sb = `${afterCeil / Math.pow(10, unitIndex * 3)}${units[unitIndex + 1]}hz` + } + CpuFreqStruct.maxFreqName = sb.toString(); + } + math(); + for (let i = 0; i < freqList.length; i++) { + const it = freqList[i]; + let traceRow = new TraceRow({ + canvasNumber: 1, + alpha: true, + contextId: '2d', + isOffScreen: SpSystemTrace.isCanvasOffScreen + }); + traceRow.rowId = `${it.cpu}` + traceRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ + traceRow.rowParentId = '' + traceRow.style.height = '40px' + traceRow.name = `Cpu ${it.cpu} Frequency`; + traceRow.favoriteChangeHandler = this.favoriteChangeHandler; + traceRow.selectChangeHandler = this.selectChangeHandler; + traceRow.supplier = () => queryCpuFreqData(it.cpu) + traceRow.onThreadHandler = (useCache) => { + procedurePool.submitWithName(`freq${it.cpu % procedurePool.freqLen.length}`, `freq${it.cpu}`, { + list: traceRow.must ? traceRow.dataList : undefined, + offscreen: traceRow.must ? traceRow.offscreen[0] : undefined, + xs: TraceRow.range?.xs, + dpr: traceRow.dpr, + isHover: traceRow.isHover, + flagMoveInfo: this.hoverFlag, + flagSelectedInfo: this.selectFlag, + hoverX: traceRow.hoverX, + hoverY: traceRow.hoverY, + canvasWidth: traceRow.canvasWidth, + canvasHeight: traceRow.canvasHeight, + hoverCpuFreqStruct: CpuFreqStruct.hoverCpuFreqStruct, + selectCpuFreqStruct: CpuFreqStruct.selectCpuFreqStruct, + wakeupBean: CpuStruct.wakeupBean, + isRangeSelect: traceRow.rangeSelect, + rangeSelectObject: TraceRow.rangeSelectObject, + maxFreq: CpuFreqStruct.maxFreq, + maxFreqName: CpuFreqStruct.maxFreqName, + useCache: useCache, + lineColor: traceRow.getLineColor(), + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: traceRow.frame + }, traceRow.must && traceRow.args.isOffScreen ? traceRow.offscreen[0] : undefined, (res: any, hover: any) => { + traceRow.must = false; + if (traceRow.args.isOffScreen == true) { + if (traceRow.isHover) { + CpuFreqStruct.hoverCpuFreqStruct = hover; + this.visibleRows.filter(it => it.rowType === TraceRow.ROW_TYPE_CPU_FREQ && it.name !== traceRow.name).forEach(it => it.draw(true)); + } + return; + } + }) + + } + this.rowsEL?.appendChild(traceRow) + } + } + + initFPS = async () => { + let fpsRow = new TraceRow({canvasNumber: 1, alpha: true, contextId: '2d', isOffScreen: true}); + fpsRow.rowId = `fps` + fpsRow.rowType = TraceRow.ROW_TYPE_FPS + fpsRow.rowParentId = '' + FpsStruct.maxFps = 0 + fpsRow.style.height = '40px' + fpsRow.name = "FPS" + fpsRow.supplier = () => getFps() + fpsRow.favoriteChangeHandler = this.favoriteChangeHandler; + fpsRow.selectChangeHandler = this.selectChangeHandler; + fpsRow.onThreadHandler = (useCache) => { + procedurePool.submitWithName(`process0`, `fps0`, { + list: fpsRow.must ? fpsRow.dataList : undefined, + offscreen: fpsRow.must ? fpsRow.offscreen[0] : undefined, + xs: TraceRow.range?.xs, + dpr: fpsRow.dpr, + isHover: fpsRow.isHover, + flagMoveInfo: this.hoverFlag, + flagSelectedInfo: this.selectFlag, + hoverX: fpsRow.hoverX, + hoverY: fpsRow.hoverY, + canvasWidth: fpsRow.canvasWidth, + canvasHeight: fpsRow.canvasHeight, + wakeupBean: CpuStruct.wakeupBean, + isRangeSelect: fpsRow.rangeSelect, + rangeSelectObject: TraceRow.rangeSelectObject, + useCache: useCache, + lineColor: fpsRow.getLineColor(), + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: fpsRow.frame + }, fpsRow.must && fpsRow.args.isOffScreen ? fpsRow.offscreen[0] : undefined, (res: any, hover: any) => { + fpsRow.must = false; + }) + } + this.rowsEL?.appendChild(fpsRow) + } + + initNativeMemory = async () => { + let nativeProcess = await queryNativeHookProcess(); + if (nativeProcess.length == 0) { + return; + } + SpSystemTrace.EVENT_HEAP = await queryHeapGroupByEvent(); + let nativeRow = new TraceRow({ + canvasNumber: 1, + alpha: false, + contextId: '2d', + isOffScreen: SpSystemTrace.isCanvasOffScreen + }); + let process = ""; + if (nativeProcess.length > 0) { + process = ` ${nativeProcess[0].pid}` + } + nativeRow.rowId = `native-memory` + nativeRow.index = 0; + nativeRow.rowType = TraceRow.ROW_TYPE_NATIVE_MEMORY + nativeRow.drawType = 0; + nativeRow.rowParentId = ''; + nativeRow.folder = true; + nativeRow.name = `Native Memory` + process; + nativeRow.favoriteChangeHandler = this.favoriteChangeHandler; + nativeRow.selectChangeHandler = this.selectChangeHandler; + nativeRow.onDrawTypeChangeHandler = (type) => { + this.rowsEL?.querySelectorAll>(`trace-row[row-type='heap']`).forEach(it => { + it.drawType = type; + it.isComplete = false; + it.draw(); + }) + }; + nativeRow.supplier = () => new Promise>((resolve, reject) => resolve([])); + nativeRow.onThreadHandler = (useCache) => { + procedurePool.submitWithName(`process${nativeRow.index}`, `native-memory`, { + list: nativeRow.must ? nativeRow.dataList : undefined, + offscreen: nativeRow.must ? nativeRow.offscreen[0] : undefined, + xs: TraceRow.range?.xs, + dpr: nativeRow.dpr, + isHover: nativeRow.isHover, + flagMoveInfo: this.hoverFlag, + flagSelectedInfo: this.selectFlag, + hoverX: nativeRow.hoverX, + hoverY: nativeRow.hoverY, + canvasWidth: nativeRow.canvasWidth, + canvasHeight: nativeRow.canvasHeight, + isRangeSelect: nativeRow.rangeSelect, + rangeSelectObject: TraceRow.rangeSelectObject, + useCache: useCache, + lineColor: nativeRow.getLineColor(), + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: nativeRow.frame + }, nativeRow.must && nativeRow.args.isOffScreen ? nativeRow.offscreen[0] : undefined, (res: any) => { + nativeRow.must = false; + }) + } + + this.rowsEL?.appendChild(nativeRow) + /** + * 添加heap信息 + */ + let native_memory = ["All Heap & Anonymous VM", "All Heap", "All Anonymous VM"]; + for (let i = 0; i < native_memory.length; i++) { + let nm = native_memory[i]; + let allHeapRow = new TraceRow({ + canvasNumber: 1, + alpha: false, + contextId: '2d', + isOffScreen: true + }); + allHeapRow.index = i; + allHeapRow.rowParentId = `native-memory` + allHeapRow.rowHidden = !nativeRow.expansion + allHeapRow.style.height = '40px' + allHeapRow.name = nm; + allHeapRow.rowId = nm; + allHeapRow.drawType = 0; + allHeapRow.folder = false; + allHeapRow.rowType = TraceRow.ROW_TYPE_HEAP; + allHeapRow.favoriteChangeHandler = this.favoriteChangeHandler; + allHeapRow.selectChangeHandler = this.selectChangeHandler; + allHeapRow.setAttribute('children', '') + let arg1 = ""; + let arg2 = ""; + if (nm == "All Heap") { + arg1 = "where event_type = 'AllocEvent' or event_type = 'FreeEvent'" + arg2 = "and (event_type = 'AllocEvent' or event_type = 'FreeEvent')" + } else if (nm == "All Anonymous VM") { + arg1 = "where event_type = 'MmapEvent' or event_type = 'MunmapEvent'" + arg2 = "and (event_type = 'MmapEvent' or event_type = 'MunmapEvent')" + } else { + arg1 = "" + arg2 = "" + } + allHeapRow.supplier = () => { + if (allHeapRow.drawType === 0) { + return queryHeapByEventType(0, TraceRow.range?.totalNS || 0, arg1, arg2); + } else { + return queryHeapByEventType(0, TraceRow.range?.totalNS || 0, arg1, arg2).then(res => { + let arr: Array = []; + if (res.length > 0) { + let first = new HeapStruct(); + first.startTime = res[0].startTime; + first.endTime = res[0].endTime; + first.dur = res[0].dur; + first.eventType = res[0].eventType; + if (first.eventType == "AllocEvent" || first.eventType == "MmapEvent") { + first.heapsize = 1; + } else { + first.heapsize = -1; + } + arr.push(first); + let max = first.heapsize; + let min = first.heapsize; + for (let i = 1, len = res.length; i < len; i++) { + let heap = new HeapStruct(); + heap.startTime = res[i].startTime; + heap.endTime = res[i].endTime; + heap.eventType = res[i].eventType; + arr[i - 1].dur = heap.startTime! - arr[i - 1].startTime!; + if (i == len - 1) { + heap.dur = TraceRow.range?.totalNS! - heap.startTime!; + } + if (heap.eventType == "AllocEvent" || heap.eventType == "MmapEvent") { + heap.heapsize = arr[i - 1].heapsize! + 1; + } else { + heap.heapsize = arr[i - 1].heapsize! - 1; + } + if (heap.heapsize > max) { + max = heap.heapsize; + } + if (heap.heapsize < min) { + min = heap.heapsize; + } + arr.push(heap); + } + arr.map((heap) => { + heap.maxHeapSize = max; + heap.minHeapSize = min; + }) + } + return arr; + }) + } + } + allHeapRow.onThreadHandler = (useCache) => { + procedurePool.submitWithName(`process${allHeapRow.index}`, `heap-${nm}`, { + list: allHeapRow.must ? allHeapRow.dataList : undefined, + offscreen: !allHeapRow.isTransferCanvas ? allHeapRow.offscreen[0] : undefined, + xs: TraceRow.range?.xs, + dpr: allHeapRow.dpr, + isHover: allHeapRow.isHover, + flagMoveInfo: this.hoverFlag, + flagSelectedInfo: this.selectFlag, + hoverX: allHeapRow.hoverX, + hoverY: allHeapRow.hoverY, + canvasWidth: allHeapRow.canvasWidth, + canvasHeight: allHeapRow.canvasHeight, + isRangeSelect: allHeapRow.rangeSelect, + rangeSelectObject: TraceRow.rangeSelectObject, + useCache: useCache, + lineColor: allHeapRow.getLineColor(), + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: allHeapRow.frame + }, !allHeapRow.isTransferCanvas ? allHeapRow.offscreen[0] : undefined, (res: any, hover: any) => { + allHeapRow.must = false; + allHeapRow.isTransferCanvas = true; + if (allHeapRow.isHover) { + HeapStruct.hoverHeapStruct = hover; + } + }) + } + this.rowsEL?.appendChild(allHeapRow) + } + } + + initProcessThreadStateData = async (progress: Function) => { + SpSystemTrace.SPT_DATA = []; + let res = await getStatesProcessThreadDataCount(); + let count: number = (res[0] as any).count; + let pageSize = 500000; + let pages = Math.ceil(count / pageSize); + let percent = 93; + for (let i = 0; i < pages; i++) { + progress("StateProcessThread", percent + ((i + 1) / 100)); + let arr = await getStatesProcessThreadData(pageSize, i * pageSize); + SpSystemTrace.SPT_DATA = SpSystemTrace.SPT_DATA.concat(arr); + } + } + + initHeapStateData = async (progress: Function) => { + SpSystemTrace.HEAP_FRAME_DATA = []; + let res = await queryHeapFrameCount(); + let count = 0; + if (res != undefined && res.length > 0 && (res[0] as any).count != undefined) { + count = (res[0] as any).count; + } + if (count > 0) { + let pageSize = 500000; + let pages = Math.ceil(count / pageSize); + let percent = 94; + for (let i = 0; i < pages; i++) { + progress("StateHeap", percent + ((i + 1) / 100)); + let arr = await queryHeapAllTable(pageSize, i * pageSize); + SpSystemTrace.HEAP_FRAME_DATA = SpSystemTrace.HEAP_FRAME_DATA.concat(arr); + } + } + } + + /** + * 添加进程信息 + */ + initProcess = async () => { + let processList = await queryProcess(); + let heapPidList = await queryHeapPid() + for (let i = 0; i < processList.length; i++) { + const it = processList[i]; + let processRow = new TraceRow({ + canvasNumber: 1, + alpha: false, + contextId: '2d', + isOffScreen: SpSystemTrace.isCanvasOffScreen + }); + processRow.rowId = `${it.pid}` + processRow.index = i; + processRow.rowType = TraceRow.ROW_TYPE_PROCESS + processRow.rowParentId = ''; + processRow.folder = true; + processRow.name = `${it.processName || "Process"} ${it.pid}`; + processRow.supplier = () => queryProcessData(it.pid || -1, 0, TraceRow.range?.totalNS || 0); + processRow.favoriteChangeHandler = this.favoriteChangeHandler; + processRow.selectChangeHandler = this.selectChangeHandler; + processRow.onThreadHandler = (useCache) => { + procedurePool.submitWithName(`process${(processRow.index) % procedurePool.processLen.length}`, `process ${processRow.index} ${it.processName}`, { + list: processRow.must ? processRow.dataList : undefined, + offscreen: processRow.must ? processRow.offscreen[0] : undefined, + xs: TraceRow.range?.xs, + dpr: processRow.dpr, + isHover: processRow.isHover, + flagMoveInfo: this.hoverFlag, + flagSelectedInfo: this.selectFlag, + hoverX: processRow.hoverX, + hoverY: processRow.hoverY, + canvasWidth: processRow.canvasWidth, + canvasHeight: processRow.canvasHeight, + isRangeSelect: processRow.rangeSelect, + rangeSelectObject: TraceRow.rangeSelectObject, + wakeupBean: CpuStruct.wakeupBean, + cpuCount: CpuStruct.cpuCount, + useCache: useCache, + lineColor: processRow.getLineColor(), + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: processRow.frame + }, processRow.must && processRow.args.isOffScreen ? processRow.offscreen[0] : undefined, (res: any) => { + processRow.must = false; + }) + } + this.rowsEL?.appendChild(processRow) + /** + * 添加进程内存信息 + */ + let processMem = this.processMem.filter(mem => mem.pid === it.pid); + processMem.forEach(mem => { + let row = new TraceRow({ + canvasNumber: 1, + alpha: false, + contextId: '2d', + isOffScreen: SpSystemTrace.isCanvasOffScreen + }); + row.rowId = `${mem.trackId}` + row.rowType = TraceRow.ROW_TYPE_MEM + row.rowParentId = `${it.pid}` + row.rowHidden = !processRow.expansion + row.style.height = '40px' + row.style.width = `100%`; + row.name = `${mem.trackName}`; + row.setAttribute('children', ''); + row.favoriteChangeHandler = this.favoriteChangeHandler; + row.selectChangeHandler = this.selectChangeHandler; + row.supplier = () => queryProcessMemData(mem.trackId).then(res => { + let maxValue = Math.max(...res.map(it => it.value || 0)) + for (let j = 0; j < res.length; j++) { + res[j].maxValue = maxValue; + if (j == res.length - 1) { + res[j].duration = (TraceRow.range?.totalNS || 0) - (res[j].startTime || 0); + } else { + res[j].duration = (res[j + 1].startTime || 0) - (res[j].startTime || 0); + } + if (j > 0) { + res[j].delta = (res[j].value || 0) - (res[j - 1].value || 0); + } else { + res[j].delta = 0; + } + } + return res + }); + row.onThreadHandler = (useCache) => { + procedurePool.submitWithName(`cpu${mem.trackId % procedurePool.cpusLen.length}`, `mem ${mem.trackId} ${mem.trackName}`, { + list: row.must ? row.dataList : undefined, + offscreen: row.must ? row.offscreen[0] : undefined,//是否离屏 + dpr: row.dpr,//屏幕dpr值 + xs: TraceRow.range?.xs,//线条坐标信息 + isHover: row.isHover, + flagMoveInfo: this.hoverFlag, + flagSelectedInfo: this.selectFlag, + hoverX: row.hoverX, + hoverY: row.hoverY, + canvasWidth: row.canvasWidth, + canvasHeight: row.canvasHeight, + wakeupBean: CpuStruct.wakeupBean, + isRangeSelect: row.rangeSelect, + rangeSelectObject: TraceRow.rangeSelectObject, + useCache: useCache, + lineColor: row.getLineColor(), + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: row.frame + }, row.must && row.args.isOffScreen ? row.offscreen[0] : undefined, (res: any) => { + row.must = false; + }) + } + this.rowsEL?.appendChild(row) + }); + /** + * 添加进程线程信息 + */ + let threads = this.processThreads.filter(thread => thread.pid === it.pid && thread.tid != 0 && thread.threadName != null); + for (let j = 0; j < threads.length; j++) { + let thread = threads[j]; + let threadRow = new TraceRow({ + canvasNumber: 1, + alpha: false, + contextId: '2d', + isOffScreen: SpSystemTrace.isCanvasOffScreen + }); + threadRow.rowId = `${thread.tid}` + threadRow.rowType = TraceRow.ROW_TYPE_THREAD + threadRow.rowParentId = `${it.pid}` + threadRow.rowHidden = !processRow.expansion + threadRow.index = j + threadRow.style.height = '30px' + threadRow.setAttribute("height", `30`); + threadRow.style.width = `100%`; + threadRow.name = `${thread.threadName} ${thread.tid}`; + threadRow.setAttribute('children', '') + threadRow.favoriteChangeHandler = this.favoriteChangeHandler; + threadRow.selectChangeHandler = this.selectChangeHandler; + threadRow.supplier = () => queryThreadData(thread.tid || 0).then(res => { + getFunDataByTid(thread.tid || 0).then((funs: Array) => { + if (funs.length > 0) { + const groupedBy: Array = []; + for (let i = 0; i < funs.length; i++) { + if (groupedBy[funs[i].depth || 0]) { + groupedBy[funs[i].depth || 0].push(funs[i]); + } else { + groupedBy[funs[i].depth || 0] = [funs[i]]; + } + } + let max = Math.max(...funs.map(it => it.depth || 0)) + 1 + let maxHeight = max * 20; + let funcRow = new TraceRow({ + canvasNumber: max, + alpha: false, + contextId: '2d', + isOffScreen: SpSystemTrace.isCanvasOffScreen + }); + funcRow.rowId = `${thread.tid}` + funcRow.rowType = TraceRow.ROW_TYPE_FUNC + funcRow.rowParentId = `${it.pid}` + funcRow.rowHidden = !processRow.expansion + funcRow.checkType = threadRow.checkType; + funcRow.style.width = `100%`; + funcRow.setAttribute("height", `${maxHeight}`); + funcRow.name = `${thread.threadName} ${thread.tid}`; + funcRow.setAttribute('children', '') + funcRow.supplier = () => new Promise((resolve, reject) => resolve(funs)) + funcRow.favoriteChangeHandler = this.favoriteChangeHandler; + funcRow.selectChangeHandler = this.selectChangeHandler; + funcRow.onThreadHandler = (useCache) => { + for (let k = 0; k < groupedBy.length; k++) { + procedurePool.submitWithName(`cpu${k % procedurePool.cpusLen.length}`, `func${thread.tid}${k}${thread.threadName}`, { + list: funcRow.must ? groupedBy[k] : undefined, + offscreen: funcRow.must ? funcRow.offscreen[k] : undefined,//是否离屏 + dpr: funcRow.dpr,//屏幕dpr值 + xs: TraceRow.range?.xs,//线条坐标信息 + isHover: funcRow.isHover, + flagMoveInfo: this.hoverFlag, + flagSelectedInfo: this.selectFlag, + hoverX: funcRow.hoverX, + hoverY: funcRow.hoverY, + depth: k, + canvasWidth: funcRow.canvasWidth, + canvasHeight: funcRow.canvasHeight, + maxHeight: maxHeight, + hoverFuncStruct: FuncStruct.hoverFuncStruct, + selectFuncStruct: FuncStruct.selectFuncStruct, + wakeupBean: CpuStruct.wakeupBean, + isRangeSelect: funcRow.rangeSelect, + rangeSelectObject: TraceRow.rangeSelectObject, + useCache: useCache, + lineColor: funcRow.getLineColor(), + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: funcRow.frame + }, funcRow.must && funcRow.args.isOffScreen ? funcRow.offscreen[k] : undefined, (res: any, hover: any) => { + funcRow.must = false; + if (funcRow.args.isOffScreen == true) { + if (funcRow.isHover && hover) { + FuncStruct.hoverFuncStruct = hover; + // this.visibleRows.filter(it => it.rowType === TraceRow.ROW_TYPE_CPU && it.name !== traceRow.name).forEach(it => it.draw()); + } + return; + } + }) + } + } + this.insertAfter(funcRow, threadRow) + this.observer.observe(funcRow) + funcRow.draw(); + this.getVisibleRows();//function 由于后插入dom,所以需要重新获取可见行 + } + }) + return res; + }) + threadRow.onThreadHandler = (useCache) => { + procedurePool.submitWithName(`process${(threadRow.index) % procedurePool.processLen.length}`, `thread ${thread.tid} ${thread.threadName}`, { + list: threadRow.must ? threadRow.dataList : undefined, + offscreen: threadRow.must ? threadRow.offscreen[0] : undefined,//是否离屏 + dpr: threadRow.dpr,//屏幕dpr值 + xs: TraceRow.range?.xs,//线条坐标信息 + isHover: threadRow.isHover, + flagMoveInfo: this.hoverFlag, + flagSelectedInfo: this.selectFlag, + hoverX: threadRow.hoverX, + hoverY: threadRow.hoverY, + canvasWidth: threadRow.canvasWidth, + canvasHeight: threadRow.canvasHeight, + hoverThreadStruct: ThreadStruct.hoverThreadStruct, + selectThreadStruct: ThreadStruct.selectThreadStruct, + wakeupBean: CpuStruct.wakeupBean, + isRangeSelect: threadRow.rangeSelect, + rangeSelectObject: TraceRow.rangeSelectObject, + useCache: useCache, + lineColor: threadRow.getLineColor(), + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + totalNS: TraceRow.range?.totalNS || 0, + frame: threadRow.frame + }, threadRow.must && threadRow.args.isOffScreen ? threadRow.offscreen[0] : undefined, (res: any, hover: any) => { + threadRow.must = false; + if (threadRow.args.isOffScreen == true) { + if (threadRow.isHover) { + ThreadStruct.hoverThreadStruct = hover; + // this.visibleRows.filter(it => it.rowType === TraceRow.ROW_TYPE_CPU && it.name !== traceRow.name).forEach(it => it.draw()); + } + return; + } + }) + } + this.rowsEL?.appendChild(threadRow) + }; + } + } + + insertAfter(newEl: HTMLElement, targetEl: HTMLElement) { + let parentEl = targetEl.parentNode; + if (parentEl!.lastChild == targetEl) { + parentEl!.appendChild(newEl); + } else { + parentEl!.insertBefore(newEl, targetEl.nextSibling); + } + } + + initHtml(): string { + return ` + +
+ +
+
+ +
+ `; + } +} diff --git a/host/ide/src/trace/component/SpWelcomePage.ts b/host/ide/src/trace/component/SpWelcomePage.ts new file mode 100644 index 0000000000000000000000000000000000000000..8da17c7e03409b23b747aab944f013461c0baba9 --- /dev/null +++ b/host/ide/src/trace/component/SpWelcomePage.ts @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../base-ui/BaseElement.js"; + +@element('sp-welcome') +export class SpWelcomePage extends BaseElement { + initElements(): void { + } + + initHtml(): string { + return ` + +
+ +
+ `; + } + +} diff --git a/host/ide/src/trace/component/Sptext.ts b/host/ide/src/trace/component/Sptext.ts new file mode 100644 index 0000000000000000000000000000000000000000..f0b089aa105f695adff15cbac60f151f6fc6004c --- /dev/null +++ b/host/ide/src/trace/component/Sptext.ts @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../base-ui/BaseElement.js"; +import "../../base-ui/popover/LitPopover.js" +import {LitPopover} from "../../base-ui/popover/LitPopover.js"; + +@element('sp-text') +export class Sptext extends BaseElement { + initElements(): void { + let litPopover = this.shadowRoot?.querySelector('lit-popover'); + litPopover!.dataSource = [{ + text: "# Samples", + isSelected: true + },] + } + + initHtml(): string { + return ` + +
+
+ + + + +
+
`; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/StackBar.ts b/host/ide/src/trace/component/StackBar.ts new file mode 100644 index 0000000000000000000000000000000000000000..9c9a0b259bdad2aa04f54ba8b2a1e6a38838472d --- /dev/null +++ b/host/ide/src/trace/component/StackBar.ts @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../base-ui/BaseElement.js"; +import {SelectionData} from "../bean/BoxSelection.js"; +import {Utils} from "./trace/base/Utils.js"; + +@element('stack-bar') +export class StackBar extends BaseElement { + private container: HTMLDivElement | undefined | null; + + static get observedAttributes() { + return ['mode'];// max min hidden show 三种状态 + } + + set data(val: Array) { + let map = new Map(); + for (let v of val) { + if (map.has(v.state)) { + let sv = map.get(v.state) + sv!.value = sv!.value + v.wallDuration; + sv!.state = v.state + " : " + sv!.value.toFixed(7) + "ms"; + } else { + let sv = new StackValue(); + sv.value = v.wallDuration; + sv.state = v.state + " : " + sv.value.toFixed(7) + "ms"; + sv.color = Utils.getStateColor(v.stateJX); + map.set(v.state, sv); + } + } + let totalDuration = 0 + let arr: Array = [] + for (let key of map.keys()) { + if (key == " ") { + totalDuration = map.get(key)!.value; + } else { + arr.push(map.get(key)!); + } + } + arr.sort((a, b) => a.value - b.value) + this.container!.innerHTML = '' + for (let stackValue of arr) { + this.container!.appendChild(this.createBarElement(stackValue, totalDuration)) + } + } + + initElements(): void { + this.container = this.shadowRoot?.querySelector('#container'); + } + + initHtml(): string { + return ` + +
+
`; + } + + getStateWidth(state: string): number { + let canvas = document.createElement("canvas"); + let context = canvas.getContext("2d"); + context!.font = "9pt"; + let metrics = context!.measureText(state); + return metrics.width; + } + + createBarElement(sv: StackValue, total: number): HTMLDivElement { + let bar = document.createElement('div'); + bar.setAttribute('class', 'state-text'); + bar.setAttribute('need-width', this.getStateWidth(sv.state) + ""); + bar.style.backgroundColor = sv.color; + bar.textContent = sv.state + if (sv.state.startsWith("Sleeping")) { + bar.style.color = '#555555'; + } else { + bar.style.color = '#ffffff'; + } + let weight = (sv.value * 1.0 / total) * 100.00 + if (weight < 1) { + weight = 1; + } + bar.style.width = weight + "%" + bar.addEventListener('mouseover', (event) => { + let needWidth = parseFloat(bar.getAttribute('need-width')!); + let trueWidth = parseFloat(window.getComputedStyle(bar).width); + if (trueWidth < needWidth) { + bar.style.width = (needWidth + 100) + "px" + } + }) + bar.addEventListener('mouseleave', (event) => { + let weight = (sv.value * 1.0 / total) * 100.00 + if (weight < 1) { + weight = 1; + } + bar.style.width = weight + "%" + }) + return bar; + } +} + +export class StackValue { + state: string = ""; + color: string = ""; + value: number = 0 +} \ No newline at end of file diff --git a/host/ide/src/trace/component/setting/SpAllocations.ts b/host/ide/src/trace/component/setting/SpAllocations.ts new file mode 100644 index 0000000000000000000000000000000000000000..9763ea000f6fc7338230c6f67e5828a0a02edfb1 --- /dev/null +++ b/host/ide/src/trace/component/setting/SpAllocations.ts @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../base-ui/BaseElement.js"; + +@element('sp-allocations') +export class SpAllocations extends BaseElement { + private processId: HTMLInputElement | null | undefined; + private unwindEL: HTMLInputElement | null | undefined; + private shareMemory: HTMLInputElement | null | undefined; + private shareMemoryUnit: HTMLSelectElement | null | undefined; + private filterMemory: HTMLInputElement | null | undefined; + private filterMemoryUnit: HTMLSelectElement | null | undefined; + + get appProcess(): string { + return this.processId!.value; + } + + get unwind(): number { + return Number(this.unwindEL!.value); + } + + get shared(): number { + let value = this.shareMemory?.value || ""; + if (value != "") { + let unit = this.shareMemoryUnit?.value || ""; + return this.convertToValue(value, unit); + } + return 8192; + } + + get filter(): number { + let value = this.filterMemory?.value || ""; + if (value != "") { + return Number(value); + } + return 0; + } + + initElements(): void { + this.processId = this.shadowRoot?.getElementById("pid") as HTMLInputElement + this.unwindEL = this.shadowRoot?.getElementById("unwind") as HTMLInputElement + this.shareMemory = this.shadowRoot?.getElementById("shareMemory") as HTMLInputElement + this.shareMemoryUnit = this.shadowRoot?.getElementById("shareMemoryUnit") as HTMLSelectElement + this.filterMemory = this.shadowRoot?.getElementById("filterSized") as HTMLInputElement + this.filterMemoryUnit = this.shadowRoot?.getElementById("filterSizedUnit") as HTMLSelectElement + } + + initHtml(): string { + return ` + +
+
+ Allocations +
+
+ ProcessId or ProcessName : + +
+
+ Max unwind level : + +
+
+ Shared Memory Size (Must be a multiple of 4 KB) : +
+ + +
+
+
+ Filter Memory Size : +
+ + +
+
+
`; + } + + private convertToValue(input: string, unit: string): number { + let value: number; + switch (unit) { + case "MB": + value = Number(input) * 1024 * 1024; + break; + case "KB": + value = Number(input) * 1024; + break; + default: + value = 0; + } + let number = value / 4096; + if (number > 0 && number < 1) { + return 8192; + } + return parseInt(String(number)); + } +} diff --git a/host/ide/src/trace/component/setting/SpCheckDesBox.ts b/host/ide/src/trace/component/setting/SpCheckDesBox.ts new file mode 100644 index 0000000000000000000000000000000000000000..1f2d2d7ec8f6077393708fe0a9c0f75f90a9cc17 --- /dev/null +++ b/host/ide/src/trace/component/setting/SpCheckDesBox.ts @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../base-ui/BaseElement.js"; +import {LitCheckBox} from "../../../base-ui/checkbox/LitCheckBox.js"; + +@element('check-des-box') +export class SpCheckDesBox extends BaseElement { + private _checkBox: LitCheckBox | undefined + private _des: HTMLSpanElement | undefined; + + static get observedAttributes() { + return ['checked', 'value', 'des'] + } + + set des(des: string) { + this.setAttribute("des", des) + } + + get value(): string { + return this.getAttribute("value") || ''; + } + + set value(value: string) { + this.setAttribute("value", value) + this._checkBox!.value = value + } + + get checked() { + return this.getAttribute("checked") != null + } + + set checked(checked: boolean) { + if (checked) { + this.setAttribute("checked", 'true') + this._checkBox!.checked = true + } else { + this.removeAttribute("checked") + this._checkBox!.checked = false + } + } + + initElements(): void { + this._checkBox = this.shadowRoot?.getElementById('checkBox') as LitCheckBox + this._des = this.shadowRoot?.getElementById("des") as HTMLSpanElement; + } + + initHtml(): string { + return ` + + +
+ +
`; + } + + public connectedCallback() { + this._checkBox?.addEventListener("change", (ev: any) => { + let detail = ev.detail; + this.checked = detail.checked + this.dispatchEvent(new CustomEvent("onchange", {detail})) + }) + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + if (name == 'checked') { + this._checkBox!.checked = newValue !== null; + } + if (name == 'value') { + this._checkBox!.value = newValue + } + if (name == 'des') { + this._des!.textContent = newValue + } + } +} + +export interface checkDesBean { + value: string; + isSelect: boolean; + des: string; +} diff --git a/host/ide/src/trace/component/setting/SpProbesConfig.ts b/host/ide/src/trace/component/setting/SpProbesConfig.ts new file mode 100644 index 0000000000000000000000000000000000000000..a2af05c5580c7c489e9612bb8f5f68039e030214 --- /dev/null +++ b/host/ide/src/trace/component/setting/SpProbesConfig.ts @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../base-ui/BaseElement.js"; +import {checkDesBean, SpCheckDesBox} from "./SpCheckDesBox.js"; +import {LitCheckBox} from "../../../base-ui/checkbox/LitCheckBox.js"; +import {LitRadioGroup} from "../../../base-ui/radiobox/LitRadioGroup.js"; + +@element('probes-config') +export class SpProbesConfig extends BaseElement { + private traceConfigList: Array | undefined + private memoryConfigList: Array | undefined + private hitraceConfigList: Array | undefined; + private hitrace: SpCheckDesBox | undefined + + private _traceConfig: HTMLElement | undefined; + private _memoryConfig: HTMLElement | undefined | null; + + get traceConfig() { + let selectedTrace = this._traceConfig?.querySelectorAll(`check-des-box[checked]`) || []; + let values = [] + for (const litCheckBoxElement of selectedTrace) { + values.push(litCheckBoxElement.value) + } + if (this.hitrace && this.hitrace.checked) { + values.push(this.hitrace.value) + } + return values; + } + + get memoryConfig() { + let values = [] + let selectedMemory = this._memoryConfig?.querySelectorAll(`check-des-box[checked]`) as NodeListOf + for (const litCheckBoxElement of selectedMemory) { + values.push(litCheckBoxElement.value) + } + return values + } + + get traceEvents() { + let values = [] + if (this.hitrace && this.hitrace.checked) { + let parent = this.shadowRoot?.querySelector('.user-events') as Element + const siblingNode = parent?.querySelectorAll(`lit-check-box[name=userEvents][checked]`); + for (const litCheckBoxElement of siblingNode) { + values.push(litCheckBoxElement.value) + } + } + return values; + } + + get hilogConfig() { + let logLevel = this.shadowRoot?.getElementById('logLevel') as LitCheckBox; + if (logLevel.checked) { + let logRadio = this.shadowRoot?.getElementById('log-radio') as LitRadioGroup; + return logRadio.value; + } else { + return [] + } + } + + initElements(): void { + this.traceConfigList = [ + {value: 'Scheduling details', isSelect: false, des: "enables high-detailed tracking of scheduling events"} + , { + value: "Board voltages & frequency", isSelect: false, + des: "Tracks voltage and frequency changes from board sensors" + } + , { + value: "CPU Frequency and idle states", isSelect: false, + des: "Records cpu frequency and idle state change viaftrace" + } + , { + value: "High frequency memory", isSelect: false, + des: "Allows to track short memory splikes and transitories through ftrace's mm_event." + + " rss_stat and ion events. " + + "Available only on recent Kernel version >= 4.19" + } + , { + value: "Advanced ftrace config", isSelect: false, + des: "Enable individual events and tune the kernel-tracng(ftrace) module." + + "The events enabled here are in addition to those from" + + " enabled by other probes." + } + , {value: "Syscalls", isSelect: false, des: "Tracks the enter and exit of all syscalls"} + , {value: "FPS", isSelect: false, des: "Tracks the FPS"}] + this._traceConfig = this.shadowRoot?.querySelector(".trace-config") as HTMLElement + this.traceConfigList.forEach(configBean => { + let checkDesBox = new SpCheckDesBox(); + checkDesBox.value = configBean.value; + checkDesBox.checked = configBean.isSelect; + checkDesBox.des = configBean.des; + this._traceConfig?.appendChild(checkDesBox) + }) + this.memoryConfigList = [ + {value: 'Kernel meminfo', isSelect: false, des: "polling of /proc/meminfo"}, + { + value: 'Virtual memory stats', + isSelect: false, + des: "Periodically polls virtual memory stats from /proc/vmstat." + + " Allows to gather statistics about swap," + + "eviction, compression and pagecache efficiency" + }] + this._memoryConfig = this.shadowRoot?.querySelector(".memory-config") + this.memoryConfigList.forEach(configBean => { + let checkDesBox = new SpCheckDesBox(); + checkDesBox.value = configBean.value; + checkDesBox.checked = configBean.isSelect; + checkDesBox.des = configBean.des; + this._memoryConfig?.appendChild(checkDesBox) + }) + this.hitraceConfigList = ["ability", "ace", "app", "ark", "binder", "disk", "distributeddatamgr" + , "dsoftbus", "freq", "graphic", "i2c", "idle", "irq", "mdfs", "memory", "memreclaim", "misc", "mmc", + "msdp", "multimodalinput", "notification", "ohos", "pagecache", "regulators", "rpc", "sched", "sensors", "sync" + , "window", "workq", "zaudio", "zcamera", "zimage", "zmedia"] + this.hitrace = this.shadowRoot?.getElementById("hitrace") as SpCheckDesBox + let parent = this.shadowRoot?.querySelector('.user-events') as Element + this.hitraceConfigList?.forEach(value => { + let litCheckBox = new LitCheckBox(); + litCheckBox.setAttribute("name", "userEvents") + litCheckBox.value = value; + litCheckBox.addEventListener("change", (ev: any) => { + let detail = ev.detail; + if (this.hitrace?.checked == false) { + this.hitrace.checked = detail.checked + } + if (detail.checked == false && this.hitrace?.checked == true) { + let hasChecked = false; + const nodes = parent?.querySelectorAll(`lit-check-box[name=userEvents]`); + nodes.forEach(vv => { + if (vv.checked) { + hasChecked = true; + } + }) + if (!hasChecked) { + this.hitrace.checked = hasChecked + } + } + }) + parent.append(litCheckBox) + }) + } + + initHtml(): string { + return ` + +
+
Record mode
+
+
+
+
+ +
+ +
+
+
+
+
+ Memory Config +
+
+
+
`; + } + + //当 custom element首次被插入文档DOM时,被调用。 + public connectedCallback() { + let parent = this.shadowRoot?.querySelector('.user-events') as Element + const siblingNode = parent?.querySelectorAll(`lit-check-box[name=userEvents]`); + this.hitrace!.addEventListener('onchange', (ev: any) => { + let detail = ev.detail; + siblingNode.forEach(node => { + node.checked = detail.checked + }) + }) + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/setting/SpRecordSetting.ts b/host/ide/src/trace/component/setting/SpRecordSetting.ts new file mode 100644 index 0000000000000000000000000000000000000000..9db5328af629b8ba41a39402b9bedbaf4b7d7436 --- /dev/null +++ b/host/ide/src/trace/component/setting/SpRecordSetting.ts @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../base-ui/BaseElement.js"; +import "../../../base-ui/radiobox/LitRadioBox.js"; +import {LitRadioBox} from "../../../base-ui/radiobox/LitRadioBox.js"; +import "../../../base-ui/slider/LitSlider.js"; +import {LitSlider} from "../../../base-ui/slider/LitSlider.js"; + +@element('record-setting') +export class SpRecordSetting extends BaseElement { + private memoryBufferSlider: LitSlider | undefined; + private maxDurationSliders: LitSlider | undefined; + private radioBox: LitRadioBox | undefined + + get recordMod(): boolean { + if (this.radioBox) { + return this.radioBox.checked + } + return false; + } + + get bufferSize(): number { + let bufferSize = this.shadowRoot?.querySelector(".buffer-size") as HTMLElement + return Number(bufferSize.getAttribute("percent")); + } + + get maxDur(): number { + let bufferSize = this.shadowRoot?.querySelector(".max-duration") as HTMLElement + return Number(bufferSize.getAttribute("percent")); + } + + initElements(): void { + this.radioBox = this.shadowRoot?.querySelector("#litradio") as LitRadioBox + this.memoryBufferSlider = this.shadowRoot?.querySelector('#memory-buffer') as LitSlider; + let sliderSize1 = this.memoryBufferSlider.sliderSize; + this.maxDurationSliders = this.shadowRoot?.querySelector('#max-duration') as LitSlider; + let sliderSize2 = this.maxDurationSliders.sliderSize; + } + + initHtml(): string { + return ` + +
+
+ Record mode + Stop when full +
+
+ In-memory buffer size + +
+
+ Max duration + +
+
`; + } +} diff --git a/host/ide/src/trace/component/setting/SpTraceCommand.ts b/host/ide/src/trace/component/setting/SpTraceCommand.ts new file mode 100644 index 0000000000000000000000000000000000000000..b3f2a542c08dd2e18081e2c665c6020ad30fef09 --- /dev/null +++ b/host/ide/src/trace/component/setting/SpTraceCommand.ts @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../base-ui/BaseElement.js"; + +@element('trace-command') +export class SpTraceCommand extends BaseElement { + private codeHl: HTMLTextAreaElement | undefined | null; + private copyEl: HTMLElement | undefined | null; + private codeCopyText: HTMLInputElement | undefined; + + get hdcCommon(): string { + return this.codeHl!.textContent + ""; + } + + set hdcCommon(value: string) { + this.codeHl!.textContent = value; + } + + //当 custom element首次被插入文档DOM时,被调用。 + public connectedCallback() { + this.codeHl = this.shadowRoot?.querySelector('#code-text') as HTMLTextAreaElement; + this.copyEl = this.shadowRoot?.querySelector('#copy-image') as HTMLElement; + this.codeHl.textContent = "" + this.copyEl?.addEventListener('click', this.codeCopyEvent) + this.codeHl.addEventListener('selectionchange', this.textSelectEvent) + } + + public disconnectedCallback() { + this.copyEl?.removeEventListener('click', this.codeCopyEvent) + } + + codeCopyEvent = (event: any) => { + this.codeHl?.select(); + document.execCommand('copy'); + } + + textSelectEvent = (event: any) => { + this.copyEl!.style.backgroundColor = '#FFFFFF'; + } + + initElements(): void { + } + + initHtml(): string { + return ` + +
+ + +
`; + } +} diff --git a/host/ide/src/trace/component/setting/bean/ProfilerServiceTypes.ts b/host/ide/src/trace/component/setting/bean/ProfilerServiceTypes.ts new file mode 100644 index 0000000000000000000000000000000000000000..88464f8e900e24126542ee29ea9d5abaa83ed58c --- /dev/null +++ b/host/ide/src/trace/component/setting/bean/ProfilerServiceTypes.ts @@ -0,0 +1,850 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface ProfilerSessionConfigBufferConfig { + pages: number; + policy: ProfilerSessionConfigBufferConfigPolicy; +} + +export enum ProfilerSessionConfigBufferConfigPolicy { + RECYCLE = 0, + FLATTEN = 1, + UNRECOGNIZED = 2, +} + +export interface ProfilerSessionConfig { + buffers: ProfilerSessionConfigBufferConfig[]; + sessionMode: ProfilerSessionConfigMode; + /** for OFFLINE mode, result file path */ + resultFile: string; + /** for OFFLINE mode, result file max size in KB */ + resultMaxSize: number; + /** for OFFLINE mode, sample duration in ms */ + sampleDuration: number; + /** if set to non-zero value, session will auto-destroyed after CreateSession in ms */ + keepAliveTime: number; +} + +export enum ProfilerSessionConfigMode { + /** OFFLINE - save all plugin results to result file. */ + OFFLINE = 0, + /** ONLINE - push all plugin results to host PC with streamed FetchDataResponse. */ + ONLINE = 1, + UNRECOGNIZED = -1, +} + +export interface TracePluginConfig { + /** kernel event set */ + ftraceEvents: string[]; + /** bytrace event set */ + hitraceCategories: string[]; + /** bytrace app set */ + hitraceApps: string[]; + /** kernel trace buffer size */ + bufferSizeKb: number; + /** time interval in milliseconds to notify service process */ + flushIntervalMs: number; + /** buffer water mark threshold to notify service process */ + flushThresholdKb: number; + /** parse /proc/kallsyms or not */ + parseKsyms: boolean; + /** value for trace_clock */ + clock: string; + /** time interval in milliseconds to read kernel trace buffer */ + tracePeriodMs: number; + /** raw data file prefix for debug */ + rawDataPrefix: string; + /** time duration in millisconds for trace actions */ + traceDurationMs: number; + /** enable debug options */ + debugOn: boolean; + hitraceTime: number; +} + +export interface CreateSessionRequest { + requestId: number; + sessionConfig: ProfilerSessionConfig | undefined; + pluginConfigs: ProfilerPluginConfig[]; +} + +export interface ProfilerPluginConfig { + pluginName: string; + sampleInterval: number; + configData: T; +} + + +export interface MemoryConfig { + /** set true to report process list */ + reportProcessTree: boolean; + /** set true to report memory counter from /proc/meminfo */ + reportSysmemMemInfo: boolean; + /** set required counter list of system meminfo, eg:MemTotal, MemFree, etc. */ + sysMeminfoCounters: SysMeminfoType[]; + /** set true to report memory counter from /proc/vmstat */ + reportSysmemVmemInfo: boolean; + /** set required counter list of virtual system meminfo, eg:nr_free_pages, nr_anon_pages, etc. */ + sysVmeminfoCounters: SysVMeminfoType[]; + /** set true to report process meminfo from /proc/${pid}/stat */ + reportProcessMemInfo: boolean; + /** set true to report application memory usage summary, eg:java heap memory, native heap, stack memory, etc. */ + reportAppMemInfo: boolean; + /** + * set true to report application memory by memory service, otherwise, + * application memory will count up by /proc/${pid}/smaps information + */ + reportAppMemByMemoryService: boolean; + /** set required pid list */ + pid: number[]; +} + + +export function sysVMeminfoTypeFromJSON(object: any): SysVMeminfoType { + switch (object) { + case 0: + case "VMEMINFO_UNSPECIFIED": + return SysVMeminfoType.VMEMINFO_UNSPECIFIED; + case 1: + case "VMEMINFO_NR_FREE_PAGES": + return SysVMeminfoType.VMEMINFO_NR_FREE_PAGES; + case 2: + case "VMEMINFO_NR_ALLOC_BATCH": + return SysVMeminfoType.VMEMINFO_NR_ALLOC_BATCH; + case 3: + case "VMEMINFO_NR_INACTIVE_ANON": + return SysVMeminfoType.VMEMINFO_NR_INACTIVE_ANON; + case 4: + case "VMEMINFO_NR_ACTIVE_ANON": + return SysVMeminfoType.VMEMINFO_NR_ACTIVE_ANON; + case 5: + case "VMEMINFO_NR_INACTIVE_FILE": + return SysVMeminfoType.VMEMINFO_NR_INACTIVE_FILE; + case 6: + case "VMEMINFO_NR_ACTIVE_FILE": + return SysVMeminfoType.VMEMINFO_NR_ACTIVE_FILE; + case 7: + case "VMEMINFO_NR_UNEVICTABLE": + return SysVMeminfoType.VMEMINFO_NR_UNEVICTABLE; + case 8: + case "VMEMINFO_NR_MLOCK": + return SysVMeminfoType.VMEMINFO_NR_MLOCK; + case 9: + case "VMEMINFO_NR_ANON_PAGES": + return SysVMeminfoType.VMEMINFO_NR_ANON_PAGES; + case 10: + case "VMEMINFO_NR_MAPPED": + return SysVMeminfoType.VMEMINFO_NR_MAPPED; + case 11: + case "VMEMINFO_NR_FILE_PAGES": + return SysVMeminfoType.VMEMINFO_NR_FILE_PAGES; + case 12: + case "VMEMINFO_NR_DIRTY": + return SysVMeminfoType.VMEMINFO_NR_DIRTY; + case 13: + case "VMEMINFO_NR_WRITEBACK": + return SysVMeminfoType.VMEMINFO_NR_WRITEBACK; + case 14: + case "VMEMINFO_NR_SLAB_RECLAIMABLE": + return SysVMeminfoType.VMEMINFO_NR_SLAB_RECLAIMABLE; + case 15: + case "VMEMINFO_NR_SLAB_UNRECLAIMABLE": + return SysVMeminfoType.VMEMINFO_NR_SLAB_UNRECLAIMABLE; + case 16: + case "VMEMINFO_NR_PAGE_TABLE_PAGES": + return SysVMeminfoType.VMEMINFO_NR_PAGE_TABLE_PAGES; + case 17: + case "VMEMINFO_NR_KERNEL_STACK": + return SysVMeminfoType.VMEMINFO_NR_KERNEL_STACK; + case 18: + case "VMEMINFO_NR_OVERHEAD": + return SysVMeminfoType.VMEMINFO_NR_OVERHEAD; + case 19: + case "VMEMINFO_NR_UNSTABLE": + return SysVMeminfoType.VMEMINFO_NR_UNSTABLE; + case 20: + case "VMEMINFO_NR_BOUNCE": + return SysVMeminfoType.VMEMINFO_NR_BOUNCE; + case 21: + case "VMEMINFO_NR_VMSCAN_WRITE": + return SysVMeminfoType.VMEMINFO_NR_VMSCAN_WRITE; + case 22: + case "VMEMINFO_NR_VMSCAN_IMMEDIATE_RECLAIM": + return SysVMeminfoType.VMEMINFO_NR_VMSCAN_IMMEDIATE_RECLAIM; + case 23: + case "VMEMINFO_NR_WRITEBACK_TEMP": + return SysVMeminfoType.VMEMINFO_NR_WRITEBACK_TEMP; + case 24: + case "VMEMINFO_NR_ISOLATED_ANON": + return SysVMeminfoType.VMEMINFO_NR_ISOLATED_ANON; + case 25: + case "VMEMINFO_NR_ISOLATED_FILE": + return SysVMeminfoType.VMEMINFO_NR_ISOLATED_FILE; + case 26: + case "VMEMINFO_NR_SHMEM": + return SysVMeminfoType.VMEMINFO_NR_SHMEM; + case 27: + case "VMEMINFO_NR_DIRTIED": + return SysVMeminfoType.VMEMINFO_NR_DIRTIED; + case 28: + case "VMEMINFO_NR_WRITTEN": + return SysVMeminfoType.VMEMINFO_NR_WRITTEN; + case 29: + case "VMEMINFO_NR_PAGES_SCANNED": + return SysVMeminfoType.VMEMINFO_NR_PAGES_SCANNED; + case 30: + case "VMEMINFO_WORKINGSET_REFAULT": + return SysVMeminfoType.VMEMINFO_WORKINGSET_REFAULT; + case 31: + case "VMEMINFO_WORKINGSET_ACTIVATE": + return SysVMeminfoType.VMEMINFO_WORKINGSET_ACTIVATE; + case 32: + case "VMEMINFO_WORKINGSET_NODERECLAIM": + return SysVMeminfoType.VMEMINFO_WORKINGSET_NODERECLAIM; + case 33: + case "VMEMINFO_NR_ANON_TRANSPARENT_HUGEPAGES": + return SysVMeminfoType.VMEMINFO_NR_ANON_TRANSPARENT_HUGEPAGES; + case 34: + case "VMEMINFO_NR_FREE_CMA": + return SysVMeminfoType.VMEMINFO_NR_FREE_CMA; + case 35: + case "VMEMINFO_NR_SWAPCACHE": + return SysVMeminfoType.VMEMINFO_NR_SWAPCACHE; + case 36: + case "VMEMINFO_NR_DIRTY_THRESHOLD": + return SysVMeminfoType.VMEMINFO_NR_DIRTY_THRESHOLD; + case 37: + case "VMEMINFO_NR_DIRTY_BACKGROUND_THRESHOLD": + return SysVMeminfoType.VMEMINFO_NR_DIRTY_BACKGROUND_THRESHOLD; + case 38: + case "VMEMINFO_PGPGIN": + return SysVMeminfoType.VMEMINFO_PGPGIN; + case 39: + case "VMEMINFO_PGPGOUT": + return SysVMeminfoType.VMEMINFO_PGPGOUT; + case 40: + case "VMEMINFO_PGPGOUTCLEAN": + return SysVMeminfoType.VMEMINFO_PGPGOUTCLEAN; + case 41: + case "VMEMINFO_PSWPIN": + return SysVMeminfoType.VMEMINFO_PSWPIN; + case 42: + case "VMEMINFO_PSWPOUT": + return SysVMeminfoType.VMEMINFO_PSWPOUT; + case 43: + case "VMEMINFO_PGALLOC_DMA": + return SysVMeminfoType.VMEMINFO_PGALLOC_DMA; + case 44: + case "VMEMINFO_PGALLOC_NORMAL": + return SysVMeminfoType.VMEMINFO_PGALLOC_NORMAL; + case 45: + case "VMEMINFO_PGALLOC_MOVABLE": + return SysVMeminfoType.VMEMINFO_PGALLOC_MOVABLE; + case 46: + case "VMEMINFO_PGFREE": + return SysVMeminfoType.VMEMINFO_PGFREE; + case 47: + case "VMEMINFO_PGACTIVATE": + return SysVMeminfoType.VMEMINFO_PGACTIVATE; + case 48: + case "VMEMINFO_PGDEACTIVATE": + return SysVMeminfoType.VMEMINFO_PGDEACTIVATE; + case 49: + case "VMEMINFO_PGFAULT": + return SysVMeminfoType.VMEMINFO_PGFAULT; + case 50: + case "VMEMINFO_PGMAJFAULT": + return SysVMeminfoType.VMEMINFO_PGMAJFAULT; + case 51: + case "VMEMINFO_PGREFILL_DMA": + return SysVMeminfoType.VMEMINFO_PGREFILL_DMA; + case 52: + case "VMEMINFO_PGREFILL_NORMAL": + return SysVMeminfoType.VMEMINFO_PGREFILL_NORMAL; + case 53: + case "VMEMINFO_PGREFILL_MOVABLE": + return SysVMeminfoType.VMEMINFO_PGREFILL_MOVABLE; + case 54: + case "VMEMINFO_PGSTEAL_KSWAPD_DMA": + return SysVMeminfoType.VMEMINFO_PGSTEAL_KSWAPD_DMA; + case 55: + case "VMEMINFO_PGSTEAL_KSWAPD_NORMAL": + return SysVMeminfoType.VMEMINFO_PGSTEAL_KSWAPD_NORMAL; + case 56: + case "VMEMINFO_PGSTEAL_KSWAPD_MOVABLE": + return SysVMeminfoType.VMEMINFO_PGSTEAL_KSWAPD_MOVABLE; + case 57: + case "VMEMINFO_PGSTEAL_DIRECT_DMA": + return SysVMeminfoType.VMEMINFO_PGSTEAL_DIRECT_DMA; + case 58: + case "VMEMINFO_PGSTEAL_DIRECT_NORMAL": + return SysVMeminfoType.VMEMINFO_PGSTEAL_DIRECT_NORMAL; + case 59: + case "VMEMINFO_PGSTEAL_DIRECT_MOVABLE": + return SysVMeminfoType.VMEMINFO_PGSTEAL_DIRECT_MOVABLE; + case 60: + case "VMEMINFO_PGSCAN_KSWAPD_DMA": + return SysVMeminfoType.VMEMINFO_PGSCAN_KSWAPD_DMA; + case 61: + case "VMEMINFO_PGSCAN_KSWAPD_NORMAL": + return SysVMeminfoType.VMEMINFO_PGSCAN_KSWAPD_NORMAL; + case 62: + case "VMEMINFO_PGSCAN_KSWAPD_MOVABLE": + return SysVMeminfoType.VMEMINFO_PGSCAN_KSWAPD_MOVABLE; + case 63: + case "VMEMINFO_PGSCAN_DIRECT_DMA": + return SysVMeminfoType.VMEMINFO_PGSCAN_DIRECT_DMA; + case 64: + case "VMEMINFO_PGSCAN_DIRECT_NORMAL": + return SysVMeminfoType.VMEMINFO_PGSCAN_DIRECT_NORMAL; + case 65: + case "VMEMINFO_PGSCAN_DIRECT_MOVABLE": + return SysVMeminfoType.VMEMINFO_PGSCAN_DIRECT_MOVABLE; + case 66: + case "VMEMINFO_PGSCAN_DIRECT_THROTTLE": + return SysVMeminfoType.VMEMINFO_PGSCAN_DIRECT_THROTTLE; + case 67: + case "VMEMINFO_PGINODESTEAL": + return SysVMeminfoType.VMEMINFO_PGINODESTEAL; + case 68: + case "VMEMINFO_SLABS_SCANNED": + return SysVMeminfoType.VMEMINFO_SLABS_SCANNED; + case 69: + case "VMEMINFO_KSWAPD_INODESTEAL": + return SysVMeminfoType.VMEMINFO_KSWAPD_INODESTEAL; + case 70: + case "VMEMINFO_KSWAPD_LOW_WMARK_HIT_QUICKLY": + return SysVMeminfoType.VMEMINFO_KSWAPD_LOW_WMARK_HIT_QUICKLY; + case 71: + case "VMEMINFO_KSWAPD_HIGH_WMARK_HIT_QUICKLY": + return SysVMeminfoType.VMEMINFO_KSWAPD_HIGH_WMARK_HIT_QUICKLY; + case 72: + case "VMEMINFO_PAGEOUTRUN": + return SysVMeminfoType.VMEMINFO_PAGEOUTRUN; + case 73: + case "VMEMINFO_ALLOCSTALL": + return SysVMeminfoType.VMEMINFO_ALLOCSTALL; + case 74: + case "VMEMINFO_PGROTATED": + return SysVMeminfoType.VMEMINFO_PGROTATED; + case 75: + case "VMEMINFO_DROP_PAGECACHE": + return SysVMeminfoType.VMEMINFO_DROP_PAGECACHE; + case 76: + case "VMEMINFO_DROP_SLAB": + return SysVMeminfoType.VMEMINFO_DROP_SLAB; + case 77: + case "VMEMINFO_PGMIGRATE_SUCCESS": + return SysVMeminfoType.VMEMINFO_PGMIGRATE_SUCCESS; + case 78: + case "VMEMINFO_PGMIGRATE_FAIL": + return SysVMeminfoType.VMEMINFO_PGMIGRATE_FAIL; + case 79: + case "VMEMINFO_COMPACT_MIGRATE_SCANNED": + return SysVMeminfoType.VMEMINFO_COMPACT_MIGRATE_SCANNED; + case 80: + case "VMEMINFO_COMPACT_FREE_SCANNED": + return SysVMeminfoType.VMEMINFO_COMPACT_FREE_SCANNED; + case 81: + case "VMEMINFO_COMPACT_ISOLATED": + return SysVMeminfoType.VMEMINFO_COMPACT_ISOLATED; + case 82: + case "VMEMINFO_COMPACT_STALL": + return SysVMeminfoType.VMEMINFO_COMPACT_STALL; + case 83: + case "VMEMINFO_COMPACT_FAIL": + return SysVMeminfoType.VMEMINFO_COMPACT_FAIL; + case 84: + case "VMEMINFO_COMPACT_SUCCESS": + return SysVMeminfoType.VMEMINFO_COMPACT_SUCCESS; + case 85: + case "VMEMINFO_COMPACT_DAEMON_WAKE": + return SysVMeminfoType.VMEMINFO_COMPACT_DAEMON_WAKE; + case 86: + case "VMEMINFO_UNEVICTABLE_PGS_CULLED": + return SysVMeminfoType.VMEMINFO_UNEVICTABLE_PGS_CULLED; + case 87: + case "VMEMINFO_UNEVICTABLE_PGS_SCANNED": + return SysVMeminfoType.VMEMINFO_UNEVICTABLE_PGS_SCANNED; + case 88: + case "VMEMINFO_UNEVICTABLE_PGS_RESCUED": + return SysVMeminfoType.VMEMINFO_UNEVICTABLE_PGS_RESCUED; + case 89: + case "VMEMINFO_UNEVICTABLE_PGS_MLOCKED": + return SysVMeminfoType.VMEMINFO_UNEVICTABLE_PGS_MLOCKED; + case 90: + case "VMEMINFO_UNEVICTABLE_PGS_MUNLOCKED": + return SysVMeminfoType.VMEMINFO_UNEVICTABLE_PGS_MUNLOCKED; + case 91: + case "VMEMINFO_UNEVICTABLE_PGS_CLEARED": + return SysVMeminfoType.VMEMINFO_UNEVICTABLE_PGS_CLEARED; + case 92: + case "VMEMINFO_UNEVICTABLE_PGS_STRANDED": + return SysVMeminfoType.VMEMINFO_UNEVICTABLE_PGS_STRANDED; + case 93: + case "VMEMINFO_NR_ZSPAGES": + return SysVMeminfoType.VMEMINFO_NR_ZSPAGES; + case 94: + case "VMEMINFO_NR_ION_HEAP": + return SysVMeminfoType.VMEMINFO_NR_ION_HEAP; + case 95: + case "VMEMINFO_NR_GPU_HEAP": + return SysVMeminfoType.VMEMINFO_NR_GPU_HEAP; + case 96: + case "VMEMINFO_ALLOCSTALL_DMA": + return SysVMeminfoType.VMEMINFO_ALLOCSTALL_DMA; + case 97: + case "VMEMINFO_ALLOCSTALL_MOVABLE": + return SysVMeminfoType.VMEMINFO_ALLOCSTALL_MOVABLE; + case 98: + case "VMEMINFO_ALLOCSTALL_NORMAL": + return SysVMeminfoType.VMEMINFO_ALLOCSTALL_NORMAL; + case 99: + case "VMEMINFO_COMPACT_DAEMON_FREE_SCANNED": + return SysVMeminfoType.VMEMINFO_COMPACT_DAEMON_FREE_SCANNED; + case 100: + case "VMEMINFO_COMPACT_DAEMON_MIGRATE_SCANNED": + return SysVMeminfoType.VMEMINFO_COMPACT_DAEMON_MIGRATE_SCANNED; + case 101: + case "VMEMINFO_NR_FASTRPC": + return SysVMeminfoType.VMEMINFO_NR_FASTRPC; + case 102: + case "VMEMINFO_NR_INDIRECTLY_RECLAIMABLE": + return SysVMeminfoType.VMEMINFO_NR_INDIRECTLY_RECLAIMABLE; + case 103: + case "VMEMINFO_NR_ION_HEAP_POOL": + return SysVMeminfoType.VMEMINFO_NR_ION_HEAP_POOL; + case 104: + case "VMEMINFO_NR_KERNEL_MISC_RECLAIMABLE": + return SysVMeminfoType.VMEMINFO_NR_KERNEL_MISC_RECLAIMABLE; + case 105: + case "VMEMINFO_NR_SHADOW_CALL_STACK_BYTES": + return SysVMeminfoType.VMEMINFO_NR_SHADOW_CALL_STACK_BYTES; + case 106: + case "VMEMINFO_NR_SHMEM_HUGEPAGES": + return SysVMeminfoType.VMEMINFO_NR_SHMEM_HUGEPAGES; + case 107: + case "VMEMINFO_NR_SHMEM_PMDMAPPED": + return SysVMeminfoType.VMEMINFO_NR_SHMEM_PMDMAPPED; + case 108: + case "VMEMINFO_NR_UNRECLAIMABLE_PAGES": + return SysVMeminfoType.VMEMINFO_NR_UNRECLAIMABLE_PAGES; + case 109: + case "VMEMINFO_NR_ZONE_ACTIVE_ANON": + return SysVMeminfoType.VMEMINFO_NR_ZONE_ACTIVE_ANON; + case 110: + case "VMEMINFO_NR_ZONE_ACTIVE_FILE": + return SysVMeminfoType.VMEMINFO_NR_ZONE_ACTIVE_FILE; + case 111: + case "VMEMINFO_NR_ZONE_INACTIVE_ANON": + return SysVMeminfoType.VMEMINFO_NR_ZONE_INACTIVE_ANON; + case 112: + case "VMEMINFO_NR_ZONE_INACTIVE_FILE": + return SysVMeminfoType.VMEMINFO_NR_ZONE_INACTIVE_FILE; + case 113: + case "VMEMINFO_NR_ZONE_UNEVICTABLE": + return SysVMeminfoType.VMEMINFO_NR_ZONE_UNEVICTABLE; + case 114: + case "VMEMINFO_NR_ZONE_WRITE_PENDING": + return SysVMeminfoType.VMEMINFO_NR_ZONE_WRITE_PENDING; + case 115: + case "VMEMINFO_OOM_KILL": + return SysVMeminfoType.VMEMINFO_OOM_KILL; + case 116: + case "VMEMINFO_PGLAZYFREE": + return SysVMeminfoType.VMEMINFO_PGLAZYFREE; + case 117: + case "VMEMINFO_PGLAZYFREED": + return SysVMeminfoType.VMEMINFO_PGLAZYFREED; + case 118: + case "VMEMINFO_PGREFILL": + return SysVMeminfoType.VMEMINFO_PGREFILL; + case 119: + case "VMEMINFO_PGSCAN_DIRECT": + return SysVMeminfoType.VMEMINFO_PGSCAN_DIRECT; + case 120: + case "VMEMINFO_PGSCAN_KSWAPD": + return SysVMeminfoType.VMEMINFO_PGSCAN_KSWAPD; + case 121: + case "VMEMINFO_PGSKIP_DMA": + return SysVMeminfoType.VMEMINFO_PGSKIP_DMA; + case 122: + case "VMEMINFO_PGSKIP_MOVABLE": + return SysVMeminfoType.VMEMINFO_PGSKIP_MOVABLE; + case 123: + case "VMEMINFO_PGSKIP_NORMAL": + return SysVMeminfoType.VMEMINFO_PGSKIP_NORMAL; + case 124: + case "VMEMINFO_PGSTEAL_DIRECT": + return SysVMeminfoType.VMEMINFO_PGSTEAL_DIRECT; + case 125: + case "VMEMINFO_PGSTEAL_KSWAPD": + return SysVMeminfoType.VMEMINFO_PGSTEAL_KSWAPD; + case 126: + case "VMEMINFO_SWAP_RA": + return SysVMeminfoType.VMEMINFO_SWAP_RA; + case 127: + case "VMEMINFO_SWAP_RA_HIT": + return SysVMeminfoType.VMEMINFO_SWAP_RA_HIT; + case 128: + case "VMEMINFO_WORKINGSET_RESTORE": + return SysVMeminfoType.VMEMINFO_WORKINGSET_RESTORE; + case -1: + case "UNRECOGNIZED": + default: + return SysVMeminfoType.UNRECOGNIZED; + } +} + +export enum SysVMeminfoType { + UNRECOGNIZED = "UNRECOGNIZED", + VMEMINFO_UNSPECIFIED = "VMEMINFO_UNSPECIFIED", + VMEMINFO_NR_FREE_PAGES = "VMEMINFO_NR_FREE_PAGES", + VMEMINFO_NR_ALLOC_BATCH = "VMEMINFO_NR_ALLOC_BATCH", + VMEMINFO_NR_INACTIVE_ANON = "VMEMINFO_NR_INACTIVE_ANON", + VMEMINFO_NR_ACTIVE_ANON = "VMEMINFO_NR_ACTIVE_ANON", + VMEMINFO_NR_INACTIVE_FILE = "VMEMINFO_NR_INACTIVE_FILE", + VMEMINFO_NR_ACTIVE_FILE = "VMEMINFO_NR_ACTIVE_FILE", + VMEMINFO_NR_UNEVICTABLE = "VMEMINFO_NR_UNEVICTABLE", + VMEMINFO_NR_MLOCK = "VMEMINFO_NR_MLOCK", + VMEMINFO_NR_ANON_PAGES = "VMEMINFO_NR_ANON_PAGES", + VMEMINFO_NR_MAPPED = "VMEMINFO_NR_MAPPED", + VMEMINFO_NR_FILE_PAGES = "VMEMINFO_NR_FILE_PAGES", + VMEMINFO_NR_DIRTY = "VMEMINFO_NR_DIRTY", + VMEMINFO_NR_WRITEBACK = "VMEMINFO_NR_WRITEBACK", + VMEMINFO_NR_SLAB_RECLAIMABLE = "VMEMINFO_NR_SLAB_RECLAIMABLE", + VMEMINFO_NR_SLAB_UNRECLAIMABLE = "VMEMINFO_NR_SLAB_UNRECLAIMABLE", + VMEMINFO_NR_PAGE_TABLE_PAGES = "VMEMINFO_NR_PAGE_TABLE_PAGES", + VMEMINFO_NR_KERNEL_STACK = "VMEMINFO_NR_KERNEL_STACK", + VMEMINFO_NR_OVERHEAD = "VMEMINFO_NR_OVERHEAD", + VMEMINFO_NR_UNSTABLE = "VMEMINFO_NR_UNSTABLE", + VMEMINFO_NR_BOUNCE = "VMEMINFO_NR_BOUNCE", + VMEMINFO_NR_VMSCAN_WRITE = "VMEMINFO_NR_VMSCAN_WRITE", + VMEMINFO_NR_VMSCAN_IMMEDIATE_RECLAIM = "VMEMINFO_NR_VMSCAN_IMMEDIATE_RECLAIM", + VMEMINFO_NR_WRITEBACK_TEMP = "VMEMINFO_NR_WRITEBACK_TEMP", + VMEMINFO_NR_ISOLATED_ANON = "VMEMINFO_NR_ISOLATED_ANON", + VMEMINFO_NR_ISOLATED_FILE = "VMEMINFO_NR_ISOLATED_FILE", + VMEMINFO_NR_SHMEM = "VMEMINFO_NR_SHMEM", + VMEMINFO_NR_DIRTIED = "VMEMINFO_NR_DIRTIED", + VMEMINFO_NR_WRITTEN = "VMEMINFO_NR_WRITTEN", + VMEMINFO_NR_PAGES_SCANNED = "VMEMINFO_NR_PAGES_SCANNED", + VMEMINFO_WORKINGSET_REFAULT = "VMEMINFO_WORKINGSET_REFAULT", + VMEMINFO_WORKINGSET_ACTIVATE = "VMEMINFO_WORKINGSET_ACTIVATE", + VMEMINFO_WORKINGSET_NODERECLAIM = "VMEMINFO_WORKINGSET_NODERECLAIM", + VMEMINFO_NR_ANON_TRANSPARENT_HUGEPAGES = "VMEMINFO_NR_ANON_TRANSPARENT_HUGEPAGES", + VMEMINFO_NR_FREE_CMA = "VMEMINFO_NR_FREE_CMA", + VMEMINFO_NR_SWAPCACHE = "VMEMINFO_NR_SWAPCACHE", + VMEMINFO_NR_DIRTY_THRESHOLD = "VMEMINFO_NR_DIRTY_THRESHOLD", + VMEMINFO_NR_DIRTY_BACKGROUND_THRESHOLD = "VMEMINFO_NR_DIRTY_BACKGROUND_THRESHOLD", + VMEMINFO_PGPGIN = "VMEMINFO_PGPGIN", + VMEMINFO_PGPGOUT = "VMEMINFO_PGPGOUT", + VMEMINFO_PGPGOUTCLEAN = "VMEMINFO_PGPGOUTCLEAN", + VMEMINFO_PSWPIN = "VMEMINFO_PSWPIN", + VMEMINFO_PSWPOUT = "VMEMINFO_PSWPOUT", + VMEMINFO_PGALLOC_DMA = "VMEMINFO_PGALLOC_DMA", + VMEMINFO_PGALLOC_NORMAL = "VMEMINFO_PGALLOC_NORMAL", + VMEMINFO_PGALLOC_MOVABLE = "VMEMINFO_PGALLOC_MOVABLE", + VMEMINFO_PGFREE = "VMEMINFO_PGFREE", + VMEMINFO_PGACTIVATE = "VMEMINFO_PGACTIVATE", + VMEMINFO_PGDEACTIVATE = "VMEMINFO_PGDEACTIVATE", + VMEMINFO_PGFAULT = "VMEMINFO_PGFAULT", + VMEMINFO_PGMAJFAULT = "VMEMINFO_PGMAJFAULT", + VMEMINFO_PGREFILL_DMA = "VMEMINFO_PGREFILL_DMA", + VMEMINFO_PGREFILL_NORMAL = "VMEMINFO_PGREFILL_NORMAL", + VMEMINFO_PGREFILL_MOVABLE = "VMEMINFO_PGREFILL_MOVABLE", + VMEMINFO_PGSTEAL_KSWAPD_DMA = "VMEMINFO_PGSTEAL_KSWAPD_DMA", + VMEMINFO_PGSTEAL_KSWAPD_NORMAL = "VMEMINFO_PGSTEAL_KSWAPD_NORMAL", + VMEMINFO_PGSTEAL_KSWAPD_MOVABLE = "VMEMINFO_PGSTEAL_KSWAPD_MOVABLE", + VMEMINFO_PGSTEAL_DIRECT_DMA = "VMEMINFO_PGSTEAL_DIRECT_DMA", + VMEMINFO_PGSTEAL_DIRECT_NORMAL = "VMEMINFO_PGSTEAL_DIRECT_NORMAL", + VMEMINFO_PGSTEAL_DIRECT_MOVABLE = "VMEMINFO_PGSTEAL_DIRECT_MOVABLE", + VMEMINFO_PGSCAN_KSWAPD_DMA = "VMEMINFO_PGSCAN_KSWAPD_DMA", + VMEMINFO_PGSCAN_KSWAPD_NORMAL = "VMEMINFO_PGSCAN_KSWAPD_NORMAL", + VMEMINFO_PGSCAN_KSWAPD_MOVABLE = "VMEMINFO_PGSCAN_KSWAPD_MOVABLE", + VMEMINFO_PGSCAN_DIRECT_DMA = "VMEMINFO_PGSCAN_DIRECT_DMA", + VMEMINFO_PGSCAN_DIRECT_NORMAL = "VMEMINFO_PGSCAN_DIRECT_NORMAL", + VMEMINFO_PGSCAN_DIRECT_MOVABLE = "VMEMINFO_PGSCAN_DIRECT_MOVABLE", + VMEMINFO_PGSCAN_DIRECT_THROTTLE = "VMEMINFO_PGSCAN_DIRECT_THROTTLE", + VMEMINFO_PGINODESTEAL = "VMEMINFO_PGINODESTEAL", + VMEMINFO_SLABS_SCANNED = "VMEMINFO_SLABS_SCANNED", + VMEMINFO_KSWAPD_INODESTEAL = "VMEMINFO_KSWAPD_INODESTEAL", + VMEMINFO_KSWAPD_LOW_WMARK_HIT_QUICKLY = "VMEMINFO_KSWAPD_LOW_WMARK_HIT_QUICKLY", + VMEMINFO_KSWAPD_HIGH_WMARK_HIT_QUICKLY = "VMEMINFO_KSWAPD_HIGH_WMARK_HIT_QUICKLY", + VMEMINFO_PAGEOUTRUN = "VMEMINFO_PAGEOUTRUN", + VMEMINFO_ALLOCSTALL = "VMEMINFO_ALLOCSTALL", + VMEMINFO_PGROTATED = "VMEMINFO_PGROTATED", + VMEMINFO_DROP_PAGECACHE = "VMEMINFO_DROP_PAGECACHE", + VMEMINFO_DROP_SLAB = "VMEMINFO_DROP_SLAB", + VMEMINFO_PGMIGRATE_SUCCESS = "VMEMINFO_PGMIGRATE_SUCCESS", + VMEMINFO_PGMIGRATE_FAIL = "VMEMINFO_PGMIGRATE_FAIL", + VMEMINFO_COMPACT_MIGRATE_SCANNED = "VMEMINFO_COMPACT_MIGRATE_SCANNED", + VMEMINFO_COMPACT_FREE_SCANNED = "VMEMINFO_COMPACT_FREE_SCANNED", + VMEMINFO_COMPACT_ISOLATED = "VMEMINFO_COMPACT_ISOLATED", + VMEMINFO_COMPACT_STALL = "VMEMINFO_COMPACT_STALL", + VMEMINFO_COMPACT_FAIL = "VMEMINFO_COMPACT_FAIL", + VMEMINFO_COMPACT_SUCCESS = "VMEMINFO_COMPACT_SUCCESS", + VMEMINFO_COMPACT_DAEMON_WAKE = "VMEMINFO_COMPACT_DAEMON_WAKE", + VMEMINFO_UNEVICTABLE_PGS_CULLED = "VMEMINFO_UNEVICTABLE_PGS_CULLED", + VMEMINFO_UNEVICTABLE_PGS_SCANNED = "VMEMINFO_UNEVICTABLE_PGS_SCANNED ", + VMEMINFO_UNEVICTABLE_PGS_RESCUED = "VMEMINFO_UNEVICTABLE_PGS_RESCUED", + VMEMINFO_UNEVICTABLE_PGS_MLOCKED = "VMEMINFO_UNEVICTABLE_PGS_MLOCKED", + VMEMINFO_UNEVICTABLE_PGS_MUNLOCKED = "VMEMINFO_UNEVICTABLE_PGS_MUNLOCKED", + VMEMINFO_UNEVICTABLE_PGS_CLEARED = "VMEMINFO_UNEVICTABLE_PGS_CLEARED", + VMEMINFO_UNEVICTABLE_PGS_STRANDED = "VMEMINFO_UNEVICTABLE_PGS_STRANDED", + VMEMINFO_NR_ZSPAGES = "VMEMINFO_NR_ZSPAGES", + VMEMINFO_NR_ION_HEAP = "VMEMINFO_NR_ION_HEAP", + VMEMINFO_NR_GPU_HEAP = "VMEMINFO_NR_GPU_HEAP", + VMEMINFO_ALLOCSTALL_DMA = "VMEMINFO_ALLOCSTALL_DMA", + VMEMINFO_ALLOCSTALL_MOVABLE = "VMEMINFO_ALLOCSTALL_MOVABLE", + VMEMINFO_ALLOCSTALL_NORMAL = "VMEMINFO_ALLOCSTALL_NORMAL", + VMEMINFO_COMPACT_DAEMON_FREE_SCANNED = "VMEMINFO_COMPACT_DAEMON_FREE_SCANNED", + VMEMINFO_COMPACT_DAEMON_MIGRATE_SCANNED = "VMEMINFO_COMPACT_DAEMON_MIGRATE_SCANNED", + VMEMINFO_NR_FASTRPC = "VMEMINFO_NR_FASTRPC", + VMEMINFO_NR_INDIRECTLY_RECLAIMABLE = "VMEMINFO_NR_INDIRECTLY_RECLAIMABLE", + VMEMINFO_NR_ION_HEAP_POOL = "VMEMINFO_NR_ION_HEAP_POOL", + VMEMINFO_NR_KERNEL_MISC_RECLAIMABLE = "VMEMINFO_NR_KERNEL_MISC_RECLAIMABLE", + VMEMINFO_NR_SHADOW_CALL_STACK_BYTES = "VMEMINFO_NR_SHADOW_CALL_STACK_BYTES", + VMEMINFO_NR_SHMEM_HUGEPAGES = "VMEMINFO_NR_SHMEM_HUGEPAGES", + VMEMINFO_NR_SHMEM_PMDMAPPED = "VMEMINFO_NR_SHMEM_PMDMAPPED", + VMEMINFO_NR_UNRECLAIMABLE_PAGES = "VMEMINFO_NR_UNRECLAIMABLE_PAGES", + VMEMINFO_NR_ZONE_ACTIVE_ANON = "VMEMINFO_NR_ZONE_ACTIVE_ANON", + VMEMINFO_NR_ZONE_ACTIVE_FILE = "VMEMINFO_NR_ZONE_ACTIVE_FILE", + VMEMINFO_NR_ZONE_INACTIVE_ANON = "VMEMINFO_NR_ZONE_INACTIVE_ANON", + VMEMINFO_NR_ZONE_INACTIVE_FILE = "VMEMINFO_NR_ZONE_INACTIVE_FILE", + VMEMINFO_NR_ZONE_UNEVICTABLE = "VMEMINFO_NR_ZONE_UNEVICTABLE", + VMEMINFO_NR_ZONE_WRITE_PENDING = "VMEMINFO_NR_ZONE_WRITE_PENDING", + VMEMINFO_OOM_KILL = "VMEMINFO_OOM_KILL ", + VMEMINFO_PGLAZYFREE = "VMEMINFO_PGLAZYFREE", + VMEMINFO_PGLAZYFREED = "VMEMINFO_PGLAZYFREED", + VMEMINFO_PGREFILL = "VMEMINFO_PGREFILL", + VMEMINFO_PGSCAN_DIRECT = "VMEMINFO_PGSCAN_DIRECT", + VMEMINFO_PGSCAN_KSWAPD = "VMEMINFO_PGSCAN_KSWAPD", + VMEMINFO_PGSKIP_DMA = "VMEMINFO_PGSKIP_DMA", + VMEMINFO_PGSKIP_MOVABLE = "VMEMINFO_PGSKIP_MOVABLE", + VMEMINFO_PGSKIP_NORMAL = "VMEMINFO_PGSKIP_NORMAL", + VMEMINFO_PGSTEAL_DIRECT = "VMEMINFO_PGSTEAL_DIRECT", + VMEMINFO_PGSTEAL_KSWAPD = "VMEMINFO_PGSTEAL_KSWAPD", + VMEMINFO_SWAP_RA = "VMEMINFO_SWAP_RA", + VMEMINFO_SWAP_RA_HIT = "VMEMINFO_SWAP_RA_HIT", + VMEMINFO_WORKINGSET_RESTORE = "VMEMINFO_WORKINGSET_RESTORE", +} + +export enum SysMeminfoType { + MEMINFO_UNSPECIFIED = "PMEM_UNSPECIFIED", + MEMINFO_MEM_TOTAL = "PMEM_MEM_TOTAL", + MEMINFO_MEM_FREE = "PMEM_MEM_FREE", + MEMINFO_MEM_AVAILABLE = "PMEM_MEM_AVAILABLE", + MEMINFO_BUFFERS = "PMEM_BUFFERS", + MEMINFO_CACHED = "PMEM_CACHED", + MEMINFO_SWAP_CACHED = "PMEM_SWAP_CACHED", + MEMINFO_ACTIVE = "PMEM_ACTIVE", + MEMINFO_INACTIVE = "PMEM_INACTIVE", + MEMINFO_ACTIVE_ANON = "PMEM_ACTIVE_ANON", + MEMINFO_INACTIVE_ANON = "PMEM_INACTIVE_ANON", + MEMINFO_ACTIVE_FILE = "PMEM_ACTIVE_FILE", + MEMINFO_INACTIVE_FILE = "PMEM_INACTIVE_FILE", + MEMINFO_UNEVICTABLE = "PMEM_UNEVICTABLE", + MEMINFO_MLOCKED = "PMEM_MLOCKED", + MEMINFO_SWAP_TOTAL = "PMEM_SWAP_TOTAL", + MEMINFO_SWAP_FREE = "PMEM_SWAP_FREE", + MEMINFO_DIRTY = "PMEM_DIRTY", + MEMINFO_WRITEBACK = "PMEM_WRITEBACK", + MEMINFO_ANON_PAGES = "PMEM_ANON_PAGES", + MEMINFO_MAPPED = "PMEM_MAPPED", + MEMINFO_SHMEM = "PMEM_SHMEM", + MEMINFO_SLAB = "PMEM_SLAB", + MEMINFO_SLAB_RECLAIMABLE = "PMEM_SLAB_RECLAIMABLE", + MEMINFO_SLAB_UNRECLAIMABLE = "PMEM_SLAB_UNRECLAIMABLE", + MEMINFO_KERNEL_STACK = "PMEM_KERNEL_STACK", + MEMINFO_PAGE_TABLES = "PMEM_PAGE_TABLES", + MEMINFO_COMMIT_LIMIT = "PMEM_COMMIT_LIMIT", + MEMINFO_COMMITED_AS = "PMEM_COMMITED_AS", + MEMINFO_VMALLOC_TOTAL = "PMEM_VMALLOC_TOTAL", + MEMINFO_VMALLOC_USED = "PMEM_VMALLOC_USED", + MEMINFO_VMALLOC_CHUNK = "PMEM_VMALLOC_CHUNK", + MEMINFO_CMA_TOTAL = "PMEM_CMA_TOTAL", + MEMINFO_CMA_FREE = "PMEM_CMA_FREE", + UNRECOGNIZED = "UNRECOGNIZED", +} + +export function sysMeminfoTypeFromJSON(object: any): SysMeminfoType { + switch (object) { + case 0: + case "MEMINFO_UNSPECIFIED": + return SysMeminfoType.MEMINFO_UNSPECIFIED; + case 1: + case "MEMINFO_MEM_TOTAL": + return SysMeminfoType.MEMINFO_MEM_TOTAL; + case 2: + case "MEMINFO_MEM_FREE": + return SysMeminfoType.MEMINFO_MEM_FREE; + case 3: + case "MEMINFO_MEM_AVAILABLE": + return SysMeminfoType.MEMINFO_MEM_AVAILABLE; + case 4: + case "MEMINFO_BUFFERS": + return SysMeminfoType.MEMINFO_BUFFERS; + case 5: + case "MEMINFO_CACHED": + return SysMeminfoType.MEMINFO_CACHED; + case 6: + case "MEMINFO_SWAP_CACHED": + return SysMeminfoType.MEMINFO_SWAP_CACHED; + case 7: + case "MEMINFO_ACTIVE": + return SysMeminfoType.MEMINFO_ACTIVE; + case 8: + case "MEMINFO_INACTIVE": + return SysMeminfoType.MEMINFO_INACTIVE; + case 9: + case "MEMINFO_ACTIVE_ANON": + return SysMeminfoType.MEMINFO_ACTIVE_ANON; + case 10: + case "MEMINFO_INACTIVE_ANON": + return SysMeminfoType.MEMINFO_INACTIVE_ANON; + case 11: + case "MEMINFO_ACTIVE_FILE": + return SysMeminfoType.MEMINFO_ACTIVE_FILE; + case 12: + case "MEMINFO_INACTIVE_FILE": + return SysMeminfoType.MEMINFO_INACTIVE_FILE; + case 13: + case "MEMINFO_UNEVICTABLE": + return SysMeminfoType.MEMINFO_UNEVICTABLE; + case 14: + case "MEMINFO_MLOCKED": + return SysMeminfoType.MEMINFO_MLOCKED; + case 15: + case "MEMINFO_SWAP_TOTAL": + return SysMeminfoType.MEMINFO_SWAP_TOTAL; + case 16: + case "MEMINFO_SWAP_FREE": + return SysMeminfoType.MEMINFO_SWAP_FREE; + case 17: + case "MEMINFO_DIRTY": + return SysMeminfoType.MEMINFO_DIRTY; + case 18: + case "MEMINFO_WRITEBACK": + return SysMeminfoType.MEMINFO_WRITEBACK; + case 19: + case "MEMINFO_ANON_PAGES": + return SysMeminfoType.MEMINFO_ANON_PAGES; + case 20: + case "MEMINFO_MAPPED": + return SysMeminfoType.MEMINFO_MAPPED; + case 21: + case "MEMINFO_SHMEM": + return SysMeminfoType.MEMINFO_SHMEM; + case 22: + case "MEMINFO_SLAB": + return SysMeminfoType.MEMINFO_SLAB; + case 23: + case "MEMINFO_SLAB_RECLAIMABLE": + return SysMeminfoType.MEMINFO_SLAB_RECLAIMABLE; + case 24: + case "MEMINFO_SLAB_UNRECLAIMABLE": + return SysMeminfoType.MEMINFO_SLAB_UNRECLAIMABLE; + case 25: + case "MEMINFO_KERNEL_STACK": + return SysMeminfoType.MEMINFO_KERNEL_STACK; + case 26: + case "MEMINFO_PAGE_TABLES": + return SysMeminfoType.MEMINFO_PAGE_TABLES; + case 27: + case "MEMINFO_COMMIT_LIMIT": + return SysMeminfoType.MEMINFO_COMMIT_LIMIT; + case 28: + case "MEMINFO_COMMITED_AS": + return SysMeminfoType.MEMINFO_COMMITED_AS; + case 29: + case "MEMINFO_VMALLOC_TOTAL": + return SysMeminfoType.MEMINFO_VMALLOC_TOTAL; + case 30: + case "MEMINFO_VMALLOC_USED": + return SysMeminfoType.MEMINFO_VMALLOC_USED; + case 31: + case "MEMINFO_VMALLOC_CHUNK": + return SysMeminfoType.MEMINFO_VMALLOC_CHUNK; + case 32: + case "MEMINFO_CMA_TOTAL": + return SysMeminfoType.MEMINFO_CMA_TOTAL; + case 33: + case "MEMINFO_CMA_FREE": + return SysMeminfoType.MEMINFO_CMA_FREE; + case -1: + case "UNRECOGNIZED": + default: + return SysMeminfoType.UNRECOGNIZED; + } +} + +export enum Type { + TYPE_UNSPECIFIED = 0, + HI3516 = 1, + P40 = 2, + UNRECOGNIZED = -1, +} + +export interface HilogConfig { + deviceType: Type; + logLevel: Level; + needClear: boolean; +} + +export function levelFromJSON(object: any): Level { + switch (object) { + case 0: + case "LEVEL_UNSPECIFIED": + return Level.LOG_UNSPECIFIED; + case 1: + case "Error": + return Level.LOG_ERROR; + case 2: + case "Info": + return Level.LOG_INFO; + case 3: + case "Debug": + return Level.LOG_DEBUG; + case 4: + case "Warns": + return Level.LOG_WARN; + case -1: + case "UNRECOGNIZED": + default: + return Level.UNRECOGNIZED; + } +} + +export enum Level { + LOG_UNSPECIFIED = "LOG_UNSPECIFIED", + LOG_ERROR = "LOG_ERROR", + LOG_INFO = "LOG_INFO", + LOG_DEBUG = "LOG_DEBUG", + LOG_WARN = "LOG_WARN", + UNRECOGNIZED = -1, +} + +export interface NativeHookConfig { + pid: number, + saveFile: boolean, + fileName: string, + filterSize: number, + smbPages: number, + maxStackDepth: number + processName: string +} + +export interface FpsConfig { + reportFps: boolean; +} diff --git a/host/ide/src/trace/component/setting/utils/PluginConvertUtils.ts b/host/ide/src/trace/component/setting/utils/PluginConvertUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..895520db8b4c4564b71681162f2ee8662e7bf0c9 --- /dev/null +++ b/host/ide/src/trace/component/setting/utils/PluginConvertUtils.ts @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class PluginConvertUtils { + private static crlf: string = "\n"; + private static leftBrace: string = "{" + private static rightBrace: string = "}" + + public static createHdcCmd(requestString: string, time: number) { + return "hiprofiler_cmd \\" + this.crlf + + " -c - \\" + this.crlf + + " -o /data/local/tmp/hiprofiler_data.htrace \\" + this.crlf + + " -t " + time + " \\" + this.crlf + + "<, indentation: number, needColon: boolean, spacesNumber: number): string { + let text = ""; + arr.forEach(arrValue => { + switch (typeof arrValue) { + case "bigint": + text = text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + ": " + arrValue.toString() + this.crlf + break + case "boolean": + text = text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + ": " + arrValue.toString() + this.crlf + break + case "number": + text = text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + ": " + arrValue.toString() + this.crlf + break + case "string": + if (arrValue == '') { + break + } + if (arrValue.startsWith("VMEMINFO") || arrValue.startsWith("PMEM")) { + text = text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + ": " + arrValue.toString() + this.crlf + } else { + text = text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + ": \"" + arrValue.toString() + "\"" + this.crlf + } + break + case "object": + default: + if (needColon) { + text = text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + ": " + this.handleObj(arrValue, indentation + 1, needColon, spacesNumber) + "" + this.crlf + } else { + text = text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + this.handleObj(arrValue, indentation + 1, needColon, spacesNumber) + "" + this.crlf + } + } + }) + return text; + } + + // 驼峰转snake + private static humpToSnake(humpString: string): string { + return humpString.replace(/[A-Z]/g, (value) => '_' + value.toLowerCase()); + } + +} + diff --git a/host/ide/src/trace/component/trace/TimerShaftElement.ts b/host/ide/src/trace/component/trace/TimerShaftElement.ts new file mode 100644 index 0000000000000000000000000000000000000000..04bb21e77cd9f1cafd4770788cc0d76c0fd90062 --- /dev/null +++ b/host/ide/src/trace/component/trace/TimerShaftElement.ts @@ -0,0 +1,521 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../base-ui/BaseElement.js"; +import {TimeRuler} from "./timer-shaft/TimeRuler.js"; +import {Rect} from "./timer-shaft/Rect.js"; +import {RangeRuler, TimeRange} from "./timer-shaft/RangeRuler.js"; +import {SportRuler} from "./timer-shaft/SportRuler.js"; +import {procedurePool} from "../../database/Procedure.js"; +import {Flag} from "./timer-shaft/Flag.js"; + +//随机生成十六位进制颜色 +export function randomRgbColor() { + const letters = '0123456789ABCDEF'; + let color = '#'; + for (let i = 0; i < 6; i++) { + color += letters[Math.floor(Math.random() * 16)] + } + return color; +} + +export function ns2s(ns: number): string { + let second1 = 1_000_000_000; // 1 second + let millisecond1 = 1_000_000; // 1 millisecond + let microsecond1 = 1_000; // 1 microsecond + let nanosecond1 = 1000.0; + let res; + if (ns >= second1) { + res = (ns / 1000 / 1000 / 1000).toFixed(1) + " s"; + } else if (ns >= millisecond1) { + res = (ns / 1000 / 1000).toFixed(1) + " ms"; + } else if (ns >= microsecond1) { + res = (ns / 1000).toFixed(1) + " μs"; + } else if (ns > 0) { + res = ns.toFixed(1) + " ns"; + } else { + res = ns.toFixed(1) + " s"; + } + return res; +} + +export function ns2x(ns: number, startNS: number, endNS: number, duration: number, rect: Rect) { + if (endNS == 0) { + endNS = duration; + } + let xSize: number = (ns - startNS) * rect.width / (endNS - startNS); + if (xSize < 0) { + xSize = 0; + } + if (xSize > rect.width) { + xSize = rect.width; + } + return xSize; +} + +@element('timer-shaft-element') +export class TimerShaftElement extends BaseElement { + // @ts-ignore + offscreen: OffscreenCanvas | undefined; + isOffScreen: boolean = false; + public ctx: CanvasRenderingContext2D | undefined | null + public canvas: HTMLCanvasElement | null | undefined + public totalEL: HTMLDivElement | null | undefined + public timeTotalEL: HTMLSpanElement | null | undefined + public timeOffsetEL: HTMLSpanElement | null | undefined + public loadComplete: boolean = false + rangeChangeHandler: ((timeRange: TimeRange) => void) | undefined = undefined + flagChangeHandler: ((hoverFlag: Flag | undefined | null, selectFlag: Flag | undefined | null) => void) | undefined = undefined + flagClickHandler: ((flag: Flag | undefined | null) => void) | undefined = undefined + /** + * 离线渲染需要的变量 + */ + dpr = window.devicePixelRatio || 1; + frame: Rect = new Rect(0, 0, 0, 0); + must: boolean = true + hoverX: number = 0 + hoverY: number = 0 + canvasWidth: number = 0 + canvasHeight: number = 0 + _cpuUsage: Array<{ cpu: number, ro: number, rate: number }> = [] + protected timeRuler: TimeRuler | undefined; + protected rangeRuler: RangeRuler | undefined; + protected _sportRuler: SportRuler | undefined; + private root: HTMLDivElement | undefined | null + private _totalNS: number = 10_000_000_000; + private _startNS: number = 0; + private _endNS: number = 10_000_000_000; + + get sportRuler(): SportRuler | undefined { + return this._sportRuler; + } + + set cpuUsage(value: Array<{ cpu: number, ro: number, rate: number }>) { + this._cpuUsage = value; + if (this.rangeRuler) { + this.rangeRuler.cpuUsage = this._cpuUsage; + } + } + + get totalNS(): number { + return this._totalNS; + } + + set totalNS(value: number) { + this._totalNS = value; + if (this.timeRuler) this.timeRuler.totalNS = value; + if (this.rangeRuler) this.rangeRuler.range.totalNS = value; + if (this.timeTotalEL) this.timeTotalEL.textContent = `${ns2s(value)}` + requestAnimationFrame(() => this.render()) + } + + get startNS(): number { + return this._startNS; + } + + set startNS(value: number) { + this._startNS = value; + } + + get endNS(): number { + return this._endNS; + } + + set endNS(value: number) { + this._endNS = value; + } + + isScaling(): boolean { + return this.rangeRuler?.isPress || false; + } + + reset(): void { + this.loadComplete = false; + if (this.rangeRuler) { + this.rangeRuler.markA.frame.x = 0; + this.rangeRuler.markB.frame.x = this.rangeRuler.frame.width + this.rangeRuler.cpuUsage = [] + this.sportRuler!.flagList.length = 0 + this.sportRuler!.isRangeSelect = false + } + this.removeTriangle("inverted"); + this.totalNS = 10_000_000_000; + } + + initElements(): void { + this.root = this.shadowRoot?.querySelector('.root') + this.canvas = this.shadowRoot?.querySelector('.panel') + this.totalEL = this.shadowRoot?.querySelector('.total') + this.timeTotalEL = this.shadowRoot?.querySelector('.time-total') + this.timeOffsetEL = this.shadowRoot?.querySelector('.time-offset') + procedurePool.timelineChange = (a: any) => { + this.rangeChangeHandler?.(a); + } + } + + connectedCallback() { + if (this.canvas) { + if (this.isOffScreen) { + // @ts-ignore + this.offscreen = this.canvas.transferControlToOffscreen(); + return; + } else { + this.ctx = this.canvas?.getContext('2d', {alpha: true}); + } + } + if (this.timeTotalEL) this.timeTotalEL.textContent = ns2s(this._totalNS) + if (this.timeOffsetEL) this.timeOffsetEL.textContent = ns2s(this._startNS) + const width = this.canvas?.clientWidth || 0; + const height = this.canvas?.clientHeight || 0; + if (!this.timeRuler) { + this.timeRuler = new TimeRuler(this, new Rect(0, 0, width, 20), this._totalNS); + } + if (!this._sportRuler) { + this._sportRuler = new SportRuler(this, new Rect(0, 100, width, height - 100), + (hoverFlag, selectFlag) => { + this.flagChangeHandler?.(hoverFlag, selectFlag); + }, (flag) => { + this.flagClickHandler?.(flag); + }); + } + if (!this.rangeRuler) { + this.rangeRuler = new RangeRuler(this, new Rect(0, 25, width, 75), { + startX: 0, + endX: this.canvas?.clientWidth || 0, + startNS: 0, + endNS: this.totalNS, + totalNS: this.totalNS, + xs: [], + xsTxt: [] + }, (a) => { + if (this._sportRuler) { + this._sportRuler.range = a; + } + if (this.timeOffsetEL) { + this.timeOffsetEL.textContent = ns2s(a.startNS) + } + if (this.loadComplete) { + this.rangeChangeHandler?.(a) + } + }); + } + this.rangeRuler.frame.width = width; + this._sportRuler.frame.width = width; + this.timeRuler.frame.width = width; + } + + setRangeNS(startNS: number, endNS: number) { + this.rangeRuler?.setRangeNS(startNS, endNS); + } + + getRange(): TimeRange | undefined { + return this.rangeRuler?.getRange(); + } + + updateWidth(width: number) { + if (this.isOffScreen) { + this.frame.width = width - (this.totalEL?.clientWidth || 0); + this.frame.height = this.shadowRoot!.host.clientHeight || 0; + this.canvasWidth = Math.round((this.frame.width) * this.dpr); + this.canvasHeight = Math.round((this.frame.height) * this.dpr); + this.render(); + return; + } + this.canvas!.width = width - (this.totalEL?.clientWidth || 0); + this.canvas!.height = this.shadowRoot!.host.clientHeight || 0; + let oldWidth = this.canvas!.width; + let oldHeight = this.canvas!.height; + this.canvas!.width = Math.ceil((oldWidth) * this.dpr); + this.canvas!.height = Math.ceil(oldHeight * this.dpr); + this.canvas!.style.width = oldWidth + 'px'; + this.canvas!.style.height = oldHeight + 'px'; + this.ctx?.scale(this.dpr, this.dpr); + this.ctx?.translate(0, 0) + this.rangeRuler!.frame.width = oldWidth; + this._sportRuler!.frame.width = oldWidth; + this.timeRuler!.frame.width = oldWidth; + this.rangeRuler?.fillX() + this.render() + } + + documentOnMouseDown = (ev: MouseEvent) => { + if (this.isOffScreen) { + procedurePool.submitWithName(`timeline`, `timeline`, { + offscreen: this.must ? this.offscreen : undefined,//是否离屏 + dpr: this.dpr,//屏幕dpr值 + hoverX: this.hoverX, + hoverY: this.hoverY, + canvasWidth: this.canvasWidth, + canvasHeight: this.canvasHeight, + offsetLeft: this.canvas?.offsetLeft || 0, + offsetTop: this.canvas?.offsetTop || 0, + mouseDown: {offsetX: ev.offsetX, offsetY: ev.offsetY}, + mouseUp: null, + mouseMove: null, + mouseOut: null, + keyPressCode: null, + keyUpCode: null, + lineColor: "#dadada", + startNS: this.startNS, + endNS: this.endNS, + totalNS: this.totalNS, + frame: this.frame, + }, this.must ? this.offscreen : undefined, (res: any) => { + this.must = false; + }) + } else { + this.rangeRuler?.mouseDown(ev); + } + } + + documentOnMouseUp = (ev: MouseEvent) => { + if (this.isOffScreen) { + procedurePool.submitWithName(`timeline`, `timeline`, { + offscreen: this.must ? this.offscreen : undefined,//是否离屏 + dpr: this.dpr,//屏幕dpr值 + hoverX: this.hoverX, + hoverY: this.hoverY, + canvasWidth: this.canvasWidth, + canvasHeight: this.canvasHeight, + offsetLeft: this.canvas?.offsetLeft || 0, + offsetTop: this.canvas?.offsetTop || 0, + mouseUp: {offsetX: ev.offsetX, offsetY: ev.offsetY}, + mouseMove: null, + mouseOut: null, + keyPressCode: null, + keyUpCode: null, + lineColor: "#dadada", + startNS: this.startNS, + endNS: this.endNS, + totalNS: this.totalNS, + frame: this.frame, + }, this.must ? this.offscreen : undefined, (res: any) => { + this.must = false; + }) + } else { + this.rangeRuler?.mouseUp(ev); + this._sportRuler?.mouseUp(ev); + } + } + + documentOnMouseMove = (ev: MouseEvent) => { + if (this.isOffScreen) { + procedurePool.submitWithName(`timeline`, `timeline`, { + offscreen: this.must ? this.offscreen : undefined,//是否离屏 + dpr: this.dpr,//屏幕dpr值 + hoverX: this.hoverX, + hoverY: this.hoverY, + canvasWidth: this.canvasWidth, + canvasHeight: this.canvasHeight, + offsetLeft: this.canvas?.offsetLeft || 0, + offsetTop: this.canvas?.offsetTop || 0, + mouseMove: {offsetX: ev.offsetX, offsetY: ev.offsetY}, + mouseOut: null, + keyPressCode: null, + keyUpCode: null, + lineColor: "#dadada", + startNS: this.startNS, + endNS: this.endNS, + totalNS: this.totalNS, + frame: this.frame, + }, this.must ? this.offscreen : undefined, (res: any) => { + this.must = false; + }) + } else { + this.rangeRuler?.mouseMove(ev); + this._sportRuler?.mouseMove(ev); + } + } + + documentOnMouseOut = (ev: MouseEvent) => { + if (this.isOffScreen) { + procedurePool.submitWithName(`timeline`, `timeline`, { + offscreen: this.must ? this.offscreen : undefined,//是否离屏 + dpr: this.dpr,//屏幕dpr值 + hoverX: this.hoverX, + hoverY: this.hoverY, + canvasWidth: this.canvasWidth, + canvasHeight: this.canvasHeight, + offsetLeft: this.canvas?.offsetLeft || 0, + offsetTop: this.canvas?.offsetTop || 0, + mouseOut: {offsetX: ev.offsetX, offsetY: ev.offsetY}, + keyPressCode: null, + keyUpCode: null, + lineColor: "#dadada", + startNS: this.startNS, + endNS: this.endNS, + totalNS: this.totalNS, + frame: this.frame, + }, this.must ? this.offscreen : undefined, (res: any) => { + this.must = false; + }) + } else { + this.rangeRuler?.mouseOut(ev); + } + } + + documentOnKeyPress = (ev: KeyboardEvent) => { + if (this.isOffScreen) { + procedurePool.submitWithName(`timeline`, `timeline`, { + offscreen: this.must ? this.offscreen : undefined,//是否离屏 + dpr: this.dpr,//屏幕dpr值 + hoverX: this.hoverX, + hoverY: this.hoverY, + canvasWidth: this.canvasWidth, + canvasHeight: this.canvasHeight, + keyPressCode: {key: ev.key}, + keyUpCode: null, + lineColor: "#dadada", + startNS: this.startNS, + endNS: this.endNS, + totalNS: this.totalNS, + frame: this.frame, + }, this.must ? this.offscreen : undefined, (res: any) => { + this.must = false; + }) + } else { + this.rangeRuler?.keyPress(ev); + } + } + + documentOnKeyUp = (ev: KeyboardEvent) => { + if (this.isOffScreen) { + procedurePool.submitWithName(`timeline`, `timeline`, { + offscreen: this.must ? this.offscreen : undefined,//是否离屏 + dpr: this.dpr,//屏幕dpr值 + hoverX: this.hoverX, + hoverY: this.hoverY, + canvasWidth: this.canvasWidth, + canvasHeight: this.canvasHeight, + keyPressCode: null, + keyUpCode: {key: ev.key}, + lineColor: "#dadada", + startNS: this.startNS, + endNS: this.endNS, + totalNS: this.totalNS, + frame: this.frame, + }, this.must ? this.offscreen : undefined, (res: any) => { + this.must = false; + }) + } else { + this.rangeRuler?.keyUp(ev); + } + } + + disconnectedCallback() { + } + + render() { + if (this.ctx) { + this.ctx.fillStyle = 'transparent'; + this.ctx?.fillRect(0, 0, this.canvas?.width || 0, this.canvas?.height || 0) + this.timeRuler?.draw() + this.rangeRuler?.draw() + this._sportRuler?.draw() + } else { + procedurePool.submitWithName(`timeline`, `timeline`, { + offscreen: this.must ? this.offscreen : undefined,//是否离屏 + dpr: this.dpr,//屏幕dpr值 + hoverX: this.hoverX, + hoverY: this.hoverY, + canvasWidth: this.canvasWidth, + canvasHeight: this.canvasHeight, + keyPressCode: null, + keyUpCode: null, + lineColor: "#dadada", + startNS: this.startNS, + endNS: this.endNS, + totalNS: this.totalNS, + frame: this.frame, + }, this.must ? this.offscreen : undefined, (res: any) => { + this.must = false; + }) + } + } + + modifyFlagList(flag: Flag | null | undefined) { + this._sportRuler?.modifyFlagList(flag); + } + + drawTriangle(time: number, type: string) { + this._sportRuler?.drawTriangle(time, type); + } + + removeTriangle(type:string){ + this._sportRuler?.removeTriangle(type) + } + + initHtml(): string { + return ` + +
+
+
+
+ 10 + 0 +
+
+ +
+ `; + } +} diff --git a/host/ide/src/trace/component/trace/base/ColorUtils.ts b/host/ide/src/trace/component/trace/base/ColorUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..e5798ef2ee798b9c6dc93218fc0947fb819f46ff --- /dev/null +++ b/host/ide/src/trace/component/trace/base/ColorUtils.ts @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {CpuStruct} from "../../../bean/CpuStruct.js"; + +export class ColorUtils { + public static GREY_COLOR: string = "#f0f0f0" + + public static MD_PALETTE: Array = [ + "#3391ff", + "#0076ff", + "#66adff", + "#2db3aa", + "#008078", + "#73e6de", + "#535da6", + "#38428c", + "#7a84cc", + "#ff9201", + "#ff7500", + "#ffab40", + "#2db4e2", + "#0094c6", + "#7cdeff", + "#ffd44a", + "#fbbf00", + "#ffe593", + ]; + public static FUNC_COLOR: Array = [ + "#3391ff", + "#2db4e2", + "#2db3aa", + "#ffd44a", + "#535da6", + "#008078", + "#ff9201", + "#38428c"]; + + public static hash(str: string, max: number): number { + let colorA: number = 0x811c9dc5; + let colorB: number = 0xfffffff; + let colorC: number = 16777619; + let colorD: number = 0xffffffff; + let hash: number = colorA & colorB; + + for (let index: number = 0; index < str.length; index++) { + hash ^= str.charCodeAt(index); + hash = (hash * colorC) & colorD; + } + return Math.abs(hash) % max; + } + + public static colorForThread(thread: CpuStruct): string { + if (thread == null) { + return ColorUtils.GREY_COLOR; + } + let tid: number | undefined | null = (thread.processId || -1) >= 0 ? thread.processId : thread.tid; + return ColorUtils.colorForTid(tid || 0); + } + + public static colorForTid(tid: number): string { + let colorIdx: number = ColorUtils.hash(`${tid}`, ColorUtils.MD_PALETTE.length); + return ColorUtils.MD_PALETTE[colorIdx]; + } + + public static formatNumberComma(str: number): string { + let l = str.toString().split("").reverse(); + let t: string = ""; + for (let i = 0; i < l.length; i++) { + t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? "," : ""); + } + return t.split("").reverse().join("") + } +} diff --git a/host/ide/src/trace/component/trace/base/RangeSelect.ts b/host/ide/src/trace/component/trace/base/RangeSelect.ts new file mode 100644 index 0000000000000000000000000000000000000000..3e2e8f5b3f9d8f1dab7d6e4a42f97a39f43cdb03 --- /dev/null +++ b/host/ide/src/trace/component/trace/base/RangeSelect.ts @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {RangeSelectStruct, TraceRow} from "./TraceRow.js"; +import {Rect} from "../timer-shaft/Rect.js"; +import {ns2x, TimerShaftElement} from "../TimerShaftElement.js"; + +export class RangeSelect { + rowsEL: HTMLDivElement | undefined | null; + isMouseDown: boolean = false; + public rangeTraceRow: Array> | undefined + public selectHandler: ((ds: Array>, refreshCheckBox: boolean) => void) | undefined; + private startX: number = 0 + private endX: number = 0; + private startY: number = 0 + private endY: number = 0; + private startY2: number = 0 + private endY2: number = 0; + private timerShaftEL: TimerShaftElement | null | undefined; + private timerShaftDragEL: HTMLDivElement | null | undefined; + private isHover: boolean = false; + private movingMark: string = ""; + private mark: { startMark: number, endMark: number } = {startMark: 0, endMark: 0} + private spacerEL: HTMLDivElement; + + constructor(timerShaftEL: TimerShaftElement | null | undefined) { + this.timerShaftEL = timerShaftEL; + this.timerShaftDragEL = this.timerShaftEL?.shadowRoot?.querySelector(".total > div:nth-child(1)"); + this.spacerEL = this.timerShaftEL?.nextElementSibling! as HTMLDivElement; + } + + isInRowsEl(ev: MouseEvent): boolean { + return (ev.offsetY > this.timerShaftDragEL!.clientHeight! && + ev.offsetY < this.rowsEL!.offsetTop + this.rowsEL!.offsetHeight && + ev.offsetX > this.rowsEL!.offsetLeft! && + ev.offsetX < this.rowsEL!.offsetLeft + this.rowsEL!.offsetWidth + ) + } + + isInSpacerEL(ev: MouseEvent): boolean { + return (ev.offsetY > this.spacerEL.offsetTop && + ev.offsetY < this.spacerEL.offsetTop + this.spacerEL.offsetHeight && + ev.offsetX > this.spacerEL.offsetLeft! && + ev.offsetX < this.spacerEL.offsetLeft + this.spacerEL.offsetWidth + ) + } + + mouseDown(ev: MouseEvent) { + if (this.isHover) { + this.isMouseDown = true; + return; + } + if (this.isInRowsEl(ev)) { + this.rangeTraceRow = []; + this.isMouseDown = true; + this.startX = ev.offsetX - this.rowsEL!.offsetLeft!; + if (this.isInSpacerEL(ev)) { + this.startY = 0; + this.startY2 = ev.offsetY + 48; + } else { + this.startY = ev.offsetY - this.rowsEL!.offsetTop!; + this.startY2 = this.spacerEL.offsetTop + this.spacerEL.offsetHeight! + 48; + } + } + } + + mouseUp(ev: MouseEvent) { + if (this.isInRowsEl(ev) && this.isDrag()) { + this.endX = ev.offsetX - this.rowsEL!.offsetLeft!; + if (this.isInSpacerEL(ev)) { + this.endY = ev.offsetY - this.rowsEL!.clientTop! + this.rowsEL!.offsetTop!; + this.endY2 = ev.offsetY + 48; + } else { + this.endY = ev.offsetY - this.rowsEL!.clientTop! + this.rowsEL!.offsetTop!; + this.endY2 = this.spacerEL.offsetTop + this.spacerEL.offsetHeight! + 48; + } + if (this.selectHandler) { + this.selectHandler(this.rangeTraceRow || [], !this.isHover); + } + } + this.isMouseDown = false; + } + + isDrag(): boolean { + return this.startX != this.endX && (this.startY != this.endY || this.startY2 != this.endY2) + } + + isTouchMark(ev: MouseEvent): boolean { + let notTimeHeight: boolean = ev.offsetY > (this.timerShaftDragEL!.clientHeight || 0) + if (!notTimeHeight) { + this.isHover = false; + return false + } + if ((this.rangeTraceRow ? this.rangeTraceRow.length == 0 : false) && !this.isMouseDown) { + this.isHover = false; + } + return notTimeHeight && (this.rangeTraceRow ? this.rangeTraceRow.length > 0 : false) && !this.isMouseDown + } + + mouseMove(rows: Array>, ev: MouseEvent) { + if (this.isTouchMark(ev)) { + let markA = ns2x(TraceRow.rangeSelectObject!.startNS!, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS!, {width: this.timerShaftEL?.canvas?.clientWidth || 0} as Rect); + let markB = ns2x(TraceRow.rangeSelectObject!.endNS!, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS!, {width: this.timerShaftEL?.canvas?.clientWidth || 0} as Rect); + this.mark = {startMark: markA, endMark: markB}; + let mouseX = ev.offsetX - (this.timerShaftEL?.totalEL?.clientWidth || 0) + if ((mouseX > markA - 5 && mouseX < markA + 5)) { + this.isHover = true; + document.body.style.cursor = "ew-resize" + this.movingMark = markA < markB ? "markA" : "markB" + } else if (mouseX > markB - 5 && mouseX < markB + 5) { + this.isHover = true; + document.body.style.cursor = "ew-resize" + this.movingMark = markB < markA ? "markA" : "markB" + } else { + this.isHover = false; + } + } + if (this.isHover && this.isMouseDown) { + let rangeSelect: RangeSelectStruct | undefined; + this.rangeTraceRow = rows.filter(it => { + if (it.rangeSelect) { + if (!rangeSelect) { + rangeSelect = new RangeSelectStruct(); + let mouseX = ev.offsetX - this.rowsEL!.offsetLeft! - (it.canvasContainer?.offsetLeft || 248) + let markA = this.movingMark == "markA" ? mouseX : this.mark.startMark; + let markB = this.movingMark == "markB" ? mouseX : this.mark.endMark; + let startX = markA < markB ? markA : markB + let endX = markB < markA ? markA : markB + rangeSelect.startNS = Math.floor((TraceRow.range!.endNS - TraceRow.range!.startNS) * startX / it.frame.width + TraceRow.range!.startNS!); + rangeSelect.endNS = Math.floor((TraceRow.range!.endNS - TraceRow.range!.startNS) * endX / it.frame.width + TraceRow.range!.startNS!); + if (rangeSelect.startNS <= TraceRow.range!.startNS) { + rangeSelect.startNS = TraceRow.range!.startNS + } + if (rangeSelect.endNS >= TraceRow.range!.endNS) { + rangeSelect.endNS = TraceRow.range!.endNS + } + } + TraceRow.rangeSelectObject = rangeSelect; + return true + } + }) + this.timerShaftEL!.sportRuler!.isRangeSelect = (this.rangeTraceRow?.length || 0) > 0; + this.timerShaftEL!.sportRuler!.draw(); + return; + } + if (!this.isMouseDown) { + this.timerShaftEL!.sportRuler!.isRangeSelect = (this.rangeTraceRow?.length || 0) > 0; + this.timerShaftEL!.sportRuler!.draw(); + return; + } + this.endX = ev.offsetX - this.rowsEL!.offsetLeft!; + if (this.isInSpacerEL(ev)) { + this.endY = 0; + this.endY2 = ev.offsetY + 48; + } else { + this.endY = ev.offsetY - this.rowsEL!.offsetTop!; + this.endY2 = this.spacerEL.offsetTop + this.spacerEL.offsetHeight! + 48; + } + let scrollTop = this.rowsEL?.scrollTop || 0 + let xMin = this.startX < this.endX ? this.startX : this.endX; + let xMax = this.startX > this.endX ? this.startX : this.endX; + let yMin = this.startY < this.endY ? this.startY : this.endY; + let yMax = this.startY > this.endY ? this.startY : this.endY; + let rangeSelect: RangeSelectStruct | undefined; + this.rangeTraceRow = rows.filter(it => { + let rt: Rect; + let canvasOffsetLeft = (it.canvasContainer?.offsetLeft || 0); + let canvasOffsetTop = (it.canvasContainer?.offsetTop || 0); + if (it.collect) { + rt = new Rect(xMin - canvasOffsetLeft, Math.min(this.startY2, this.endY2) - it.offsetTop, xMax - xMin, Math.abs(this.startY2 - this.endY2)); + } else { + rt = new Rect(xMin - canvasOffsetLeft, yMin - canvasOffsetTop + scrollTop + this.rowsEL!.offsetTop, xMax - xMin, yMax - yMin); + } + if (Rect.intersect(it.frame, rt)) { + if (!rangeSelect) { + rangeSelect = new RangeSelectStruct(); + let startX = Math.floor(rt.x <= 0 ? 0 : rt.x); + let endX = Math.floor((rt.x + rt.width) > it.frame.width ? it.frame.width : (rt.x + rt.width)); + rangeSelect.startNS = Math.floor((TraceRow.range!.endNS - TraceRow.range!.startNS) * startX / it.frame.width + TraceRow.range!.startNS!); + rangeSelect.endNS = Math.floor((TraceRow.range!.endNS - TraceRow.range!.startNS) * endX / it.frame.width + TraceRow.range!.startNS!); + } + TraceRow.rangeSelectObject = rangeSelect; + it.rangeSelect = true; + return true + } else { + it.rangeSelect = false; + return false; + } + }) + this.timerShaftEL!.sportRuler!.isRangeSelect = (this.rangeTraceRow?.length || 0) > 0; + this.timerShaftEL!.sportRuler!.draw(); + } +} diff --git a/host/ide/src/trace/component/trace/base/TraceRow.ts b/host/ide/src/trace/component/trace/base/TraceRow.ts new file mode 100644 index 0000000000000000000000000000000000000000..dc54efbbd5b7119d649fb579d795c6ba0b3ecf8b --- /dev/null +++ b/host/ide/src/trace/component/trace/base/TraceRow.ts @@ -0,0 +1,823 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {element} from "../../../../base-ui/BaseElement.js"; +import {TimeRange} from "../timer-shaft/RangeRuler.js"; +import '../../../../base-ui/icon/LitIcon.js' +import {Rect} from "../timer-shaft/Rect.js"; +import {BaseStruct} from "../../../bean/BaseStruct.js"; +import {SpSystemTrace} from "../../SpSystemTrace.js"; +import {ns2x} from "../TimerShaftElement.js"; +import {TraceRowObject} from "./TraceRowObject.js"; +import {LitCheckBox} from "../../../../base-ui/checkbox/LitCheckBox.js"; +import {LitIcon} from "../../../../base-ui/icon/LitIcon"; +import "../../../../base-ui/popover/LitPopoverV.js" +import {LitPopover} from "../../../../base-ui/popover/LitPopoverV.js"; + +export class RangeSelectStruct { + startX: number | undefined + endX: number | undefined + startNS: number | undefined + endNS: number | undefined +} + +@element('trace-row') +export class TraceRow extends HTMLElement { + static ROW_TYPE_CPU = "cpu" + static ROW_TYPE_CPU_FREQ = "cpu-freq" + static ROW_TYPE_FPS = "fps" + static ROW_TYPE_NATIVE_MEMORY = "native-memory" + static ROW_TYPE_PROCESS = "process" + static ROW_TYPE_THREAD = "thread" + static ROW_TYPE_MEM = "mem" + static ROW_TYPE_HEAP = "heap" + static ROW_TYPE_FUNC = "func" + static range: TimeRange | undefined | null; + static rangeSelectObject: RangeSelectStruct | undefined + public obj: TraceRowObject | undefined | null; + isHover: boolean = false; + hoverX: number = 0; + hoverY: number = 0; + index: number = 0; + public must: boolean = false; + public isTransferCanvas = false; + onComplete: Function | undefined; + isComplete: boolean = false; + public dataList: undefined | Array; + public describeEl: Element | null | undefined; + public canvas: Array = []; + public canvasContainer: HTMLDivElement | null | undefined; + public tipEL: HTMLDivElement | null | undefined; + public checkBoxEL: LitCheckBox | null | undefined; + public collectEL: LitIcon | null | undefined; + public onDrawHandler: ((ctx: CanvasRenderingContext2D) => void) | undefined | null + public onThreadHandler: ((useCache: boolean) => void) | undefined | null + public onDrawTypeChangeHandler: ((type: number) => void) | undefined | null + public supplier: (() => Promise>) | undefined | null + public favoriteChangeHandler: ((fav: TraceRow) => void) | undefined | null + public selectChangeHandler: ((list: Array>) => void) | undefined | null + dpr = window.devicePixelRatio || 1; + // @ts-ignore + offscreen: Array = []; + canvasWidth = 0 + canvasHeight = 0 + public _frame: Rect | undefined; + private rootEL: HTMLDivElement | null | undefined; + private nameEL: HTMLLabelElement | null | undefined; + public isLoading: boolean = false + private _rangeSelect: boolean = false; + public readonly args: any; + private _drawType: number = 0 + + constructor(args: { canvasNumber: number, alpha: boolean, contextId: string, isOffScreen: boolean }) { + super(); + this.args = args; + this.attachShadow({mode: 'open'}).innerHTML = this.initHtml(); + this.initElements(); + } + + static get observedAttributes() { + return ["folder", "name", "expansion", "children", "height", "row-type", "row-id", "row-parent-id", "sleeping", + "check-type", + "collect-type" + ]; + } + + get collect() { + return this.hasAttribute("collect-type") + } + + set collect(value) { + if (value) { + this.setAttribute("collect-type", "") + } else { + this.removeAttribute("collect-type") + } + } + + get rangeSelect(): boolean { + return this._rangeSelect; + } + + set rangeSelect(value: boolean) { + this._rangeSelect = value; + } + + get sleeping(): boolean { + return this.hasAttribute("sleeping"); + } + + set sleeping(value: boolean) { + if (value) { + this.setAttribute("sleeping", "") + } else { + this.removeAttribute("sleeping") + this.draw(); + } + } + + get rowType(): string | undefined | null { + return this.getAttribute("row-type"); + } + + set rowType(val) { + this.setAttribute("row-type", val || "") + } + + get rowId(): string | undefined | null { + return this.getAttribute("row-id"); + } + + set rowId(val) { + this.setAttribute("row-id", val || "") + } + + get rowParentId(): string | undefined | null { + return this.getAttribute("row-parent-id"); + } + + set rowParentId(val) { + this.setAttribute("row-parent-id", val || "") + } + + set rowHidden(val: boolean) { + if (val) { + this.setAttribute("row-hidden", "") + } else { + this.removeAttribute("row-hidden") + } + } + + get name(): string { + return this.getAttribute("name") || "" + } + + set name(value: string) { + this.setAttribute("name", value) + } + + get folder(): boolean { + return this.hasAttribute("folder"); + } + + set folder(value: boolean) { + if (value) { + this.setAttribute("folder", '') + } else { + this.removeAttribute('folder') + } + } + + get expansion(): boolean { + return this.hasAttribute("expansion") + } + + set expansion(value) { + if (value) { + this.setAttribute("expansion", ''); + } else { + this.removeAttribute('expansion') + } + this.parentElement?.querySelectorAll>(`trace-row[row-parent-id='${this.rowId}']`).forEach(it => { + if (!it.collect) { + it.rowHidden = !this.expansion; + } + }) + this.dispatchEvent(new CustomEvent("expansion-change", { + detail: { + expansion: this.expansion, + rowType: this.rowType, + rowId: this.rowId, + rowParentId: this.rowParentId + } + })) + } + + set tip(value: string) { + if (this.tipEL) { + this.tipEL.innerHTML = value; + } + } + + get frame(): Rect { + let cHeight = 0; + this.canvas.forEach(it => { + cHeight += (it?.clientHeight || 40); + }) + if (this._frame) { + this._frame.width = (this.parentElement?.clientWidth || 0) - 248 - SpSystemTrace.scrollViewWidth; + this._frame.height = cHeight; + return this._frame; + } else { + this._frame = new Rect(0, 0, (this.parentElement?.clientWidth || 0) - 248 - SpSystemTrace.scrollViewWidth, cHeight); + return this._frame; + } + } + + set frame(f: Rect) { + this._frame = f; + } + + get checkType(): string { + return this.getAttribute("check-type") || ""; + } + + set checkType(value: string) { + this.setAttribute("check-type", value); + switch (value) { + case "-1": + this.checkBoxEL!.style.display = "none"; + this.rangeSelect = false; + break; + case "0": + this.checkBoxEL!.style.display = "flex"; + this.checkBoxEL!.checked = false; + this.checkBoxEL!.indeterminate = false; + this.rangeSelect = false; + break; + case "1": + this.checkBoxEL!.style.display = "flex"; + this.checkBoxEL!.checked = false + this.checkBoxEL!.indeterminate = true; + this.rangeSelect = false; + break; + case "2": + this.rangeSelect = true; + this.checkBoxEL!.style.display = "flex"; + this.checkBoxEL!.checked = true; + this.checkBoxEL!.indeterminate = false; + break; + } + } + + get drawType(): number { + return this._drawType; + } + + set drawType(value: number) { + this._drawType = value; + let radioList: NodeListOf = this.shadowRoot!.querySelectorAll("input[type=radio][name=status]") + if (radioList!.length > 0) { + radioList[Number(value)].checked = true + } + } + + get highlight(): boolean { + return this.hasAttribute("expansion"); + } + + set highlight(value: boolean) { + if (value) { + this.setAttribute("highlight", '') + } else { + this.removeAttribute('highlight') + } + } + + initElements(): void { + this.rootEL = this.shadowRoot?.querySelector('.root') + this.checkBoxEL = this.shadowRoot?.querySelector('.lit-check-box') + this.collectEL = this.shadowRoot?.querySelector('.collect') + this.describeEl = this.shadowRoot?.querySelector('.describe') + this.nameEL = this.shadowRoot?.querySelector('.name') + this.canvasContainer = this.shadowRoot?.querySelector('.panel-container') + this.tipEL = this.shadowRoot?.querySelector('.tip') + let canvasNumber = this.args["canvasNumber"]; + for (let i = 0; i < canvasNumber; i++) { + let canvas = document.createElement('canvas'); + canvas.className = "panel"; + this.canvas.push(canvas); + this.canvasContainer!.appendChild(canvas); + } + this.describeEl?.addEventListener('click', () => { + if (this.folder) { + this.expansion = !this.expansion + } + }) + } + + initCanvas(list: Array): void { + let timerShaftCanvas = this.parentElement!.parentElement!.querySelector("timer-shaft-element")!.shadowRoot!.querySelector("canvas"); + let tempHeight:number = 0; + if(this.rowType==TraceRow.ROW_TYPE_FUNC ){ + tempHeight = 20; + }else if(this.rowType==TraceRow.ROW_TYPE_THREAD ){ + tempHeight = 30; + }else{ + tempHeight = 40; + } + list.forEach((canvas, i) => { + // let oldWidth = (this.shadowRoot!.host.clientWidth || 0) - (this.describeEl?.clientWidth || 248) - SpSystemTrace.scrollViewWidth; + this.rootEL!.style.height = `${this.getAttribute("height") || '40'}px` + canvas.style.width = timerShaftCanvas!.style.width; + canvas.style.height = tempHeight + 'px'; + // canvas.style.backgroundColor = `${randomRgbColor()}` + this.canvasWidth = timerShaftCanvas!.width; + this.canvasHeight = Math.ceil(tempHeight * this.dpr); + canvas.width = this.canvasWidth; + canvas.height = this.canvasHeight; + // @ts-ignore + this.offscreen.push(canvas!.transferControlToOffscreen()); + }) + } + + updateWidth(width: number) { + let dpr = window.devicePixelRatio || 1; + let tempHeight = 40; + let tempTop = 0; + if (this.canvas.length > 1) { + tempHeight = 20; + tempTop = 10; + } + this.canvas.forEach(it => { + this.canvasWidth = Math.ceil((width - (this.describeEl?.clientWidth || 248)) * dpr); + this.canvasHeight = Math.ceil(tempHeight * this.dpr); + it!.style.width = (width - (this.describeEl?.clientWidth || 248)) + 'px'; + if (this.args.isOffScreen) { + this.draw(true); + } + }) + } + + connectedCallback() { + this.checkBoxEL!.onchange = (ev: any) => { + if (!ev.target.checked) { + this.rangeSelect = false; + this.checkType = "0" + this.draw(); + } else { + this.rangeSelect = true; + this.checkType = "2" + this.draw(); + } + this.setCheckBox(ev.target.checked); + } + this.collectEL!.onclick = (e) => { + this.collect = !this.collect; + let spacer = this.parentElement!.previousElementSibling! as HTMLDivElement; + if (this.collect) { + spacer.style.height = `${spacer.offsetHeight + this.offsetHeight!}px`; + } else { + spacer.style.height = `${spacer.offsetHeight - this.offsetHeight!}px`; + let parent = this.parentElement!.querySelector>(`trace-row[row-id='${this.rowParentId}']`); + if (parent) { + this.rowHidden = !parent.expansion; + } + } + let collectList = this.parentElement!.querySelectorAll>(`trace-row[collect-type]`); + collectList.forEach((it, i) => { + if (i == 0) { + it.style.top = `${spacer.offsetTop + 48}px`; + } else { + it.style.top = `${collectList[i - 1].offsetTop + collectList[i - 1].offsetHeight}px`; + } + }) + this.favoriteChangeHandler?.(this) + } + this.initCanvas(this.canvas); + let _this = this; + let radioList = this.shadowRoot!.querySelectorAll("input[type=radio][name=status]") + let popover = this.shadowRoot!.querySelector(".popover") + this.shadowRoot!.querySelector("#first-radio")!.onclick = (e) => { + // @ts-ignore + radioList[0]!.checked = true; + // @ts-ignore + popover!.visible = false + setTimeout(() => { + this.onDrawTypeChangeHandler?.(0); + }, 300); + } + this.shadowRoot!.querySelector("#second-radio")!.onclick = (e) => { + // @ts-ignore + radioList[1]!.checked = true; + // @ts-ignore + popover!.visible = false + setTimeout(() => { + this.onDrawTypeChangeHandler?.(1); + }, 300); + } + } + + setCheckBox(isCheck: boolean) { + if (this.folder) { + let allRow = this.parentElement?.querySelectorAll>(`trace-row[row-parent-id='${this.rowId}'][check-type]`) + allRow!.forEach((ck) => { + ck.setAttribute("check-type", isCheck ? "2" : "0") + let allCheck: LitCheckBox | null | undefined = ck?.shadowRoot?.querySelector(".lit-check-box") + allCheck!.checked = isCheck + }) + } else if (this.rowParentId == "" && !this.folder) { + this.selectChangeHandler?.([...this.parentElement!.querySelectorAll>("trace-row[check-type='2']")]) + return; + } + let checkList = this.parentElement?.querySelectorAll>(`trace-row[row-parent-id='${this.folder ? this.rowId : this.rowParentId}'][check-type="2"]`) + let unselectedList = this.parentElement?.querySelectorAll>(`trace-row[row-parent-id='${this.folder ? this.rowId : this.rowParentId}'][check-type="0"]`) + let parentRow = this.parentElement?.querySelector>(`trace-row[row-id='${this.folder ? this.rowId : this.rowParentId}'][folder]`) + let parentCheck: LitCheckBox | null | undefined = parentRow?.shadowRoot?.querySelector(".lit-check-box") + + if (unselectedList!.length == 0) { + parentRow!.setAttribute("check-type", "2") + parentCheck!.checked = true + parentCheck!.indeterminate = false; + checkList?.forEach((it) => { + it.checkType = "2"; + it.rangeSelect = true; + it.draw() + }) + } else { + parentRow!.setAttribute("check-type", "1") + parentCheck!.checked = false + parentCheck!.indeterminate = true; + checkList?.forEach((it) => { + it.checkType = "2"; + it.rangeSelect = true; + it.draw() + }) + unselectedList?.forEach((it) => { + it.checkType = "0"; + it.rangeSelect = false; + it.draw() + }) + } + + if (checkList!.length == 0) { + parentRow!.setAttribute("check-type", "0") + parentCheck!.checked = false + parentCheck!.indeterminate = false; + unselectedList?.forEach((it) => { + it.checkType = "0"; + it.rangeSelect = false; + it.draw() + }) + } + this.selectChangeHandler?.([...this.parentElement!.querySelectorAll>("trace-row[check-type='2']")]) + } + + onMouseHover(x: number, y: number, tip: boolean = true): T | undefined | null { + if (this.tipEL) { + this.tipEL.style.display = 'none'; + } + return null; + } + + setTipLeft(x: number, struct: any) { + if (struct == null && this.tipEL) { + this.tipEL.style.display = 'none'; + return + } + if (this.tipEL) { + this.tipEL.style.display = 'flex'; + if (x + this.tipEL.clientWidth > (this.canvas[0]!.clientWidth || 0)) { + this.tipEL.style.transform = `translateX(${x - this.tipEL.clientWidth - 1}px)`; + } else { + this.tipEL.style.transform = `translateX(${x}px)`; + } + } + } + + onMouseLeave(x: number, y: number) { + if (this.tipEL) { + this.tipEL.style.display = 'none'; + } + } + + draw(useCache: boolean = false) { + if (this.sleeping) { + return; + } + if (!this.isComplete) { + if (this.supplier && !this.isLoading) { + this.isLoading = true; + this.must = true; + if (this.supplier) { + let promise = this.supplier(); + if (promise) { + promise.then(res => { + this.dataList = res + if (this.onComplete) { + this.onComplete(); + } + this.isComplete = true; + this.isLoading = false; + this.draw(false); + }) + } else { + this.isLoading = false; + this.draw(false); + } + } + } + } else { + if (this.onThreadHandler && this.dataList) { + this.onThreadHandler!(useCache) + } + } + } + + clearCanvas(ctx: CanvasRenderingContext2D) { + if (ctx) { + this.canvas.forEach(it => { + ctx.clearRect(0, 0, it!.clientWidth || 0, it!.clientHeight || 0) + }) + } + } + + drawLines(ctx: CanvasRenderingContext2D) { + if (ctx) { + ctx.lineWidth = 1; + ctx.strokeStyle = this.getLineColor(); + TraceRow.range?.xs.forEach(it => { + ctx.moveTo(Math.floor(it), 0) + ctx.lineTo(Math.floor(it), this.shadowRoot?.host.clientHeight || 0) + }) + ctx.stroke(); + } + } + + getLineColor() { + return window.getComputedStyle(this.rootEL!, null).getPropertyValue("border-bottom-color") + } + + drawSelection(ctx: CanvasRenderingContext2D) { + if (this.rangeSelect) { + TraceRow.rangeSelectObject!.startX = Math.floor(ns2x(TraceRow.rangeSelectObject!.startNS!, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS!, this.frame)); + TraceRow.rangeSelectObject!.endX = Math.floor(ns2x(TraceRow.rangeSelectObject!.endNS!, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS!, this.frame)); + if (ctx) { + ctx.globalAlpha = 0.5 + ctx.fillStyle = "#666666" + ctx.fillRect(TraceRow.rangeSelectObject!.startX!, this.frame.y, TraceRow.rangeSelectObject!.endX! - TraceRow.rangeSelectObject!.startX!, this.frame.height) + ctx.globalAlpha = 1 + } + } + } + + isInTimeRange(startTime: number, duration: number): boolean { + return ((startTime || 0) + (duration || 0) > (TraceRow.range?.startNS || 0) && (startTime || 0) < (TraceRow.range?.endNS || 0)); + } + + attributeChangedCallback(name: string, oldValue: string, newValue: string) { + switch (name) { + case "name": + if (this.nameEL) { + this.nameEL.textContent = newValue; + this.nameEL.title = newValue; + } + break; + case "height": + if (newValue != oldValue) { + if (!this.args.isOffScreen) { + } + } + break; + case "check-type": + if (newValue === "check") { + this.checkBoxEL?.setAttribute("checked", ""); + } else { + this.checkBoxEL?.removeAttribute("checked"); + } + break; + } + } + + initHtml(): string { + return ` + +
+
+ + + + +
+
Current Bytes
+
Native Memory Density
+
+ +
+ +
+
+
+ P:process [1573]
+ T:Thread [675] +
+
+
+ `; + } + +} diff --git a/host/ide/src/trace/component/trace/base/TraceRowObject.ts b/host/ide/src/trace/component/trace/base/TraceRowObject.ts new file mode 100644 index 0000000000000000000000000000000000000000..7aa7207472e0703330e518b239be2771a0325634 --- /dev/null +++ b/host/ide/src/trace/component/trace/base/TraceRowObject.ts @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import {BaseStruct} from "../../../bean/BaseStruct.js"; +import {Rect} from "../timer-shaft/Rect.js"; +import {TraceRow} from "./TraceRow.js"; + +export class TraceRowObject { + public rowId: string | undefined; + public rowType: string | undefined; + public rowParentId: string | undefined; + public rowHidden: boolean = false; + public rowHeight: number = 40; + public name: string | undefined; + public must: boolean = true; + public folder: boolean = false; + public isLoading: boolean = false; + public children: boolean = false; + public expansion: boolean = false; + public dataList: Array | undefined; + public dataListCache: Array = []; + public color: string | undefined; + public frame: Rect | undefined; + public supplier: (() => Promise>) | undefined | null + public onThreadHandler: ((row: TraceRow, ctx: ImageBitmapRenderingContext | CanvasRenderingContext2D | WebGLRenderingContext | WebGL2RenderingContext | null | undefined) => void) | undefined | null + public onDrawHandler: ((ctx: ImageBitmapRenderingContext | CanvasRenderingContext2D | WebGLRenderingContext | WebGL2RenderingContext | null | undefined) => void) | undefined | null + public top: number = 0; + public rowIndex: number = 0; + public preObject: TraceRowObject | undefined | null; + public nextObject: TraceRowObject | undefined | null; +} diff --git a/host/ide/src/trace/component/trace/base/TraceRowRecyclerView.ts b/host/ide/src/trace/component/trace/base/TraceRowRecyclerView.ts new file mode 100644 index 0000000000000000000000000000000000000000..f5ce8484b72dfae6b9e4a74d0b4d23296bef5dfb --- /dev/null +++ b/host/ide/src/trace/component/trace/base/TraceRowRecyclerView.ts @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {TraceRowObject} from "./TraceRowObject.js"; +import {TraceRow} from "./TraceRow.js"; + +@element("trace-row-recycler-view") +export class TraceRowRecyclerView extends BaseElement { + private recycler: boolean = true; + private gasketEL: HTMLDivElement | null | undefined; + private container: HTMLDivElement | null | undefined; + private visibleRowsCount: number = 0; + private visibleObjects: TraceRowObject[] = []; + private totalHeight: number = 0; + + private _dataSource: Array> = []; + private _renderType: string = 'div'; + + get dataSource(): Array> { + return this._dataSource; + } + + set dataSource(value: Array>) { + this._dataSource = value; + this.measureHeight(); + this.initUI(); + let els = [...(this.shadowRoot!.querySelectorAll>(".recycler-cell"))]; + for (let i = 0; i < els.length; i++) { + this.refreshRow(els[i], this.visibleObjects[i]); + } + } + + get renderType(): string { + return this._renderType; + } + + set renderType(value: string) { + this._renderType = value; + } + + refreshRow(el: TraceRow, obj: TraceRowObject) { + if (!obj) { + return; + } + el.obj = obj; + el.folder = obj.folder; + el.style.top = `${obj.top}px`; + el.name = obj.name || ''; + if (obj.children) { + el.setAttribute("children", ``); + } else { + el.removeAttribute("children"); + } + el.style.visibility = 'visible'; + el.rowId = obj.rowId + el.rowType = obj.rowType + el.rowParentId = obj.rowParentId + el.expansion = obj.expansion + el.rowHidden = obj.rowHidden + el.setAttribute("height", `${obj.rowHeight}`); + requestAnimationFrame(() => { + }) + } + + initElements(): void { + this.container = this.shadowRoot?.querySelector(".container"); + this.gasketEL = this.shadowRoot?.querySelector(".gasket"); + let els: Array> | undefined | null; + this.container!.onscroll = (ev) => { + let top = this.container!.scrollTop; + let skip = 0; + for (let i = 0; i < this.visibleObjects.length; i++) { + if (this.visibleObjects[i].top >= top) { + skip = this.visibleObjects[i].rowIndex - 1; + break; + } + } + if (skip < 0) skip = 0; + if (!els) els = [...(this.shadowRoot!.querySelectorAll>(".recycler-cell"))]; + for (let i = 0; i < els.length; i++) { + let obj = this.visibleObjects[i + skip]; + this.refreshRow(els[i], obj); + } + } + } + + + measureHeight() { + this.visibleObjects = this.dataSource.filter(it => !it.rowHidden); + this.totalHeight = this.visibleObjects.map((it) => it.rowHeight).reduce((a, b) => a + b); + let totalHeight = 0; + for (let i = 0; i < this.visibleObjects.length; i++) { + this.visibleObjects[i].top = totalHeight; + this.visibleObjects[i].rowIndex = i; + totalHeight += this.visibleObjects[i].rowHeight; + this.visibleObjects[i].preObject = i == 0 ? null : this.visibleObjects[i - 1]; + this.visibleObjects[i].nextObject = i == this.visibleObjects.length - 1 ? null : this.visibleObjects[i + 1]; + } + this.gasketEL && (this.gasketEL.style.height = `${this.totalHeight}px`); + } + + initUI() { + this.visibleRowsCount = Math.ceil(this.clientHeight / 40); + if (this.visibleRowsCount >= this.visibleObjects.length) { + this.visibleRowsCount = this.visibleObjects.length; + } + if (!this.recycler) this.visibleRowsCount = this.dataSource.length; + for (let i = 0; i <= this.visibleRowsCount; i++) { + let el = new TraceRow({canvasNumber:1,alpha: true, contextId: '2d', isOffScreen: true}); + el.className = "recycler-cell" + this.container?.appendChild(el); + el.addEventListener('expansion-change', (ev: any) => { + el.obj!.expansion = ev.detail.expansion; + for (let j = 0; j < this.dataSource.length; j++) { + if (this.dataSource[j].rowParentId == ev.detail.rowId) { + this.dataSource[j].rowHidden = !ev.detail.expansion; + } + } + this.measureHeight(); + let els = [...(this.shadowRoot!.querySelectorAll>(".recycler-cell"))]; + let top = this.container!.scrollTop; + let skip = 0; + for (let i = 0; i < this.visibleObjects.length; i++) { + if (this.visibleObjects[i].top >= top) { + skip = this.visibleObjects[i].rowIndex - 1; + break; + } + } + if (skip < 0) skip = 0; + for (let i = 0; i < els.length; i++) { + let obj = this.visibleObjects[i + skip]; + this.refreshRow(els[i], obj); + } + }) + } + } + + initHtml(): string { + return ` + +
+
+
+ +`; + } + +} diff --git a/host/ide/src/trace/component/trace/base/TraceSheet.ts b/host/ide/src/trace/component/trace/base/TraceSheet.ts new file mode 100644 index 0000000000000000000000000000000000000000..0ede469f0d6d9fe0302cb43c0f8a077e1887145e --- /dev/null +++ b/host/ide/src/trace/component/trace/base/TraceSheet.ts @@ -0,0 +1,586 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTabs} from "../../../../base-ui/tabs/lit-tabs.js"; +import "../../../../base-ui/tabs/lit-tabpane.js"; +import {CpuStruct} from "../../../bean/CpuStruct.js"; +import "../../../../base-ui/table/lit-table.js"; +import {LitTabpane} from "../../../../base-ui/tabs/lit-tabpane.js"; +import "../sheet/TabPaneCpu.js"; +import "../sheet/TabPaneThreadStates.js" +import "../sheet/TabPaneSlices.js" +import "../sheet/TabPaneCounter.js" +import "../sheet/TabPaneCpuByProcess.js" +import "../sheet/TabPaneCpuByThread.js" +import "../sheet/TabPaneFps.js" +import "../sheet/TabPaneSPT.js" +import "../sheet/TabPanePTS.js" +import "../sheet/TabPaneContextSwitch.js" +import "../sheet/TabPaneThreadSwitch.js" +import "../sheet/TabPaneCpuUsage.js"; +import "../sheet/TabPaneBoxChild.js"; +import "../sheet/TabPaneHeap.js"; +import "../sheet/TabPaneNMStatstics.js"; +import "../sheet/TabPaneNMCallInfo.js"; +import "../sheet/TabPaneNMemory.js"; +import "../sheet/TabPaneNMSampleList.js"; +import {BoxJumpParam, SelectionParam} from "../../../bean/BoxSelection.js"; +import {TabPaneThreadStates} from "../sheet/TabPaneThreadStates.js"; +import {TabPaneCpuByProcess} from "../sheet/TabPaneCpuByProcess.js"; +import {TabPaneCpuByThread} from "../sheet/TabPaneCpuByThread.js"; +import {TabPaneSlices} from "../sheet/TabPaneSlices.js"; +import {TabPaneSPT} from "../sheet/TabPaneSPT.js"; +import {TabPanePTS} from "../sheet/TabPanePTS.js"; +import {TabPaneContextSwitch} from "../sheet/TabPaneContextSwitch.js"; +import {TabPaneThreadSwitch} from "../sheet/TabPaneThreadSwitch.js"; +import {TabPaneBoxChild} from "../sheet/TabPaneBoxChild.js"; +import {TabPaneCounter} from "../sheet/TabPaneCounter.js"; +import "../sheet/TabPaneCurrentSelection.js"; +import {TabPaneCurrentSelection} from "../sheet/TabPaneCurrentSelection.js"; +import {FuncStruct} from "../../../bean/FuncStruct.js"; +import {ProcessMemStruct} from "../../../bean/ProcessMemStruct.js"; +import {ThreadStruct} from "../../../bean/ThreadStruct.js"; +import {TabPaneFps} from "../sheet/TabPaneFps.js"; +import {TabPaneCpuUsage} from "../sheet/TabPaneCpuUsage.js"; +import "../timer-shaft/TabPaneFlag.js"; +import {TabPaneFlag} from "../timer-shaft/TabPaneFlag.js"; +import {Flag} from "../timer-shaft/Flag.js"; +import {TabPaneHeap} from "../sheet/TabPaneHeap.js"; +import {TabPaneNMStatstics} from "../sheet/TabPaneNMStatstics.js"; +import {TabPaneNMCallInfo} from "../sheet/TabPaneNMCallInfo.js"; +import {TabPaneNMemory} from "../sheet/TabPaneNMemory.js"; +import {TabPaneNMSampleList} from "../sheet/TabPaneNMSampleList.js"; +import {WakeupBean} from "../../../bean/WakeupBean.js"; +import {LitIcon} from "../../../../base-ui/icon/LitIcon.js"; + +@element("trace-sheet") +export class TraceSheet extends BaseElement { + private litTabs: LitTabs | undefined | null + private nav: HTMLDivElement | undefined | null + private tabCurrentSelection: LitTabpane | undefined | null + private tabBoxCpuThread: LitTabpane | undefined | null + private tabBoxCpuProcess: LitTabpane | undefined | null + private tabBoxThreadStates: LitTabpane | undefined | null + private tabBoxSlices: LitTabpane | undefined | null + private tabBoxCounters: LitTabpane | undefined | null + private tabBoxFps: LitTabpane | undefined | null + private tabBoxSPT: LitTabpane | undefined | null + private tabBoxPTS: LitTabpane | undefined | null + private tabBoxContextSwitch: LitTabpane | undefined | null + private tabBoxThreadSwitch: LitTabpane | undefined | null + private tabBoxCpuUsage: LitTabpane | undefined | null + private tabBoxChild: LitTabpane | undefined | null + private tabBoxFlag: TabPaneFlag | undefined | null + private tabBoxHeap: LitTabpane | undefined | null + private tabBoxNMStatistics: LitTabpane | undefined | null + private tabBoxNMCallInfo: LitTabpane | undefined | null + private tabBoxNMemory: LitTabpane | undefined | null + private tabBoxNMSample: LitTabpane | undefined | null + private tabSPT: TabPaneSPT | undefined | null + private tabPTS: TabPanePTS | undefined | null + private tabCs: TabPaneContextSwitch | undefined | null + private tabTs: TabPaneThreadSwitch | undefined | null + private tabChild: TabPaneBoxChild | undefined | null + private tabNativeStatistics: TabPaneNMStatstics | undefined | null + private tabNativeMemory: TabPaneNMemory | undefined | null + private tabNativeCallInfo: TabPaneNMCallInfo | undefined | null + private tabNativeSample: TabPaneNMSampleList | undefined | null + private currentKey: string = "1"; + private selection: SelectionParam | undefined | null; + + static get observedAttributes() { + return ['mode']; + } + + initElements(): void { + this.litTabs = this.shadowRoot?.querySelector("#tabs"); + this.tabCurrentSelection = this.shadowRoot?.querySelector("#current-selection"); + this.tabBoxCpuThread = this.shadowRoot?.querySelector("#box-cpu-thread"); + this.tabBoxCpuProcess = this.shadowRoot?.querySelector("#box-cpu-process"); + this.tabBoxThreadStates = this.shadowRoot?.querySelector("#box-thread-states"); + this.tabBoxSlices = this.shadowRoot?.querySelector("#box-slices"); + this.tabBoxCounters = this.shadowRoot?.querySelector("#box-counters"); + this.tabBoxFps = this.shadowRoot?.querySelector("#box-fps"); + this.tabBoxSPT = this.shadowRoot?.querySelector("#box-spt"); + this.tabBoxPTS = this.shadowRoot?.querySelector("#box-pts"); + this.tabBoxContextSwitch = this.shadowRoot?.querySelector("#box-cs"); + this.tabBoxThreadSwitch = this.shadowRoot?.querySelector("#box-ts"); + this.tabBoxCpuUsage = this.shadowRoot?.querySelector("#box-cpu-usage"); + this.tabBoxChild = this.shadowRoot?.querySelector("#box-cpu-child"); + this.tabBoxFlag = this.shadowRoot?.querySelector("#box-flag"); + this.tabBoxHeap = this.shadowRoot?.querySelector("#box-heap"); + + this.tabBoxNMStatistics = this.shadowRoot?.querySelector("#box-native-statstics"); + this.tabBoxNMCallInfo = this.shadowRoot?.querySelector("#box-native-callinfo"); + this.tabBoxNMemory = this.shadowRoot?.querySelector("#box-native-memory"); + this.tabBoxNMSample = this.shadowRoot?.querySelector("#box-native-sample"); + + this.tabSPT = this.shadowRoot!.querySelector('#tab-spt'); + this.tabPTS = this.shadowRoot!.querySelector('#tab-pts'); + this.tabCs = this.shadowRoot!.querySelector('#tab-cs'); + this.tabTs = this.shadowRoot!.querySelector('#tab-ts'); + this.tabChild = this.shadowRoot!.querySelector('#tab-box-child'); + + this.tabNativeStatistics = this.shadowRoot!.querySelector('#tab-box-native-stats'); + this.tabNativeCallInfo = this.shadowRoot!.querySelector('#tab-box-native-callinfo'); + this.tabNativeMemory = this.shadowRoot!.querySelector('#tab-box-native-memory'); + this.tabNativeSample = this.shadowRoot!.querySelector('#tab-box-native-sample'); + + let minBtn = this.shadowRoot?.querySelector("#min-btn"); + minBtn?.addEventListener('click', (e) => { + }) + this.litTabs!.onTabClick = (e: any) => { + this.loadTabPaneData(e.detail.key) + } + this.litTabs!.addEventListener("close-handler", (e) => { + this.recoveryBoxSelection(); + this.tabBoxChild!.hidden = true; + this.litTabs?.activeByKey(this.currentKey); + }) + this.tabSPT!.addEventListener("row-click", (e) => { + this.jumpBoxChild("11", e) + }) + this.tabPTS!.addEventListener("row-click", (e) => { + this.jumpBoxChild("12", e) + }) + this.tabCs!.addEventListener("row-click", (e) => { + this.jumpBoxChild("13", e) + }) + this.tabTs!.addEventListener("row-click", (e) => { + this.jumpBoxChild("14", e) + }) + this.tabNativeStatistics!.addEventListener("row-click",(e)=>{ + // @ts-ignore + this.selection!.statisticsSelectData = e.detail + this.tabNativeMemory?.fromStastics(this.selection) + this.litTabs?.activeByKey("18"); + }) + } + + connectedCallback() { + this.nav = this.shadowRoot?.querySelector("#tabs")?.shadowRoot?.querySelector('#nav') + let tabs: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('#tabs') + let navRoot: HTMLDivElement | null | undefined = this.shadowRoot?.querySelector("#tabs")?.shadowRoot?.querySelector('.nav-root') + + let search: HTMLDivElement | undefined | null = document.querySelector("body > sp-application")?.shadowRoot?.querySelector("div > div.search-container") + let timerShaft: HTMLDivElement | undefined | null = this.parentElement?.querySelector(".timer-shaft") + + let borderTop: number = 1; + let initialHeight = { + tabs: `calc(30vh + 39px)`, + node: "30vh" + } + this.nav!.onmousedown = (event) => { + let litTabpane: NodeListOf | undefined | null = this.shadowRoot?.querySelectorAll("#tabs > lit-tabpane") + let preY = event.pageY; + + let preHeight = tabs!.offsetHeight; + + document.onmousemove = function (event) { + let moveY: number; + + moveY = preHeight - (event.pageY - preY) + litTabpane!.forEach((node: HTMLDivElement, b) => { + if (navRoot!.offsetHeight <= moveY && (search!.offsetHeight + timerShaft!.offsetHeight + borderTop) <= (window.innerHeight - moveY)) { + tabs!.style.height = moveY + "px" + node!.style.height = (moveY - navRoot!.offsetHeight) + "px" + tabsPackUp!.name = "down" + } else if (navRoot!.offsetHeight >= moveY) { + tabs!.style.height = navRoot!.offsetHeight + "px" + node!.style.height = "0px" + tabsPackUp!.name = "up" + } else if ((search!.offsetHeight + timerShaft!.offsetHeight + borderTop) >= (window.innerHeight - moveY)) { + tabs!.style.height = (window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - borderTop) + "px" + node!.style.height = (window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - navRoot!.offsetHeight - borderTop) + "px" + tabsPackUp!.name = "down" + } + }) + + } + document.onmouseup = function (event) { + litTabpane!.forEach((node: HTMLDivElement, b) => { + if (node!.style.height !== "0px" && tabs!.style.height != "") { + initialHeight.node = node!.style.height; + initialHeight.tabs = tabs!.style.height; + } + }) + this.onmousemove = null; + this.onmouseup = null; + } + } + let tabsOpenUp: LitIcon | undefined | null = this.shadowRoot?.querySelector("#tabs > div > lit-icon:nth-child(1)") + let tabsPackUp: LitIcon | undefined | null = this.shadowRoot?.querySelector("#tabs > div > lit-icon:nth-child(2)") + tabsOpenUp!.onclick = (e) => { + tabs!.style.height = (window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - borderTop) + "px" + let litTabpane: NodeListOf | undefined | null = this.shadowRoot?.querySelectorAll("#tabs > lit-tabpane") + litTabpane!.forEach((node: HTMLDivElement, b) => { + node!.style.height = (window.innerHeight - search!.offsetHeight - timerShaft!.offsetHeight - navRoot!.offsetHeight - borderTop) + "px" + initialHeight.node = node!.style.height; + }) + initialHeight.tabs = tabs!.style.height; + tabsPackUp!.name = "down" + } + tabsPackUp!.onclick = (e) => { + let litTabpane: NodeListOf | undefined | null = this.shadowRoot?.querySelectorAll("#tabs > lit-tabpane") + if (tabsPackUp!.name == "down") { + tabs!.style.height = navRoot!.offsetHeight + "px" + litTabpane!.forEach((node: HTMLDivElement, b) => { + node!.style.height = "0px" + }) + tabsPackUp!.name = "up" + } else { + tabsPackUp!.name = "down" + tabs!.style.height = initialHeight.tabs; + litTabpane!.forEach((node: HTMLDivElement, b) => { + node!.style.height = initialHeight.node; + }) + } + } + } + + initHtml(): string { + return ` + +
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + +
+
`; + } + + clear() { + this.shadowRoot?.querySelectorAll("lit-tabpane").forEach(it => this.litTabs?.removeChild(it)) + } + + displayThreadData(data: ThreadStruct, scrollCallback: ((e: ThreadStruct) => void) | undefined) { + this.setAttribute("mode", "max") + this.tabCurrentSelection!.hidden = false; + this.hideBoxTab(); + this.litTabs?.activeByKey("1") + let tabCpu = this.shadowRoot!.querySelector('#tabpane-cpu'); + tabCpu!.setThreadData(data, scrollCallback); + } + + displayMemData(data: ProcessMemStruct) { + this.setAttribute("mode", "max") + this.tabCurrentSelection!.hidden = false; + this.hideBoxTab(); + this.litTabs?.activeByKey("1") + let tabCpu = this.shadowRoot!.querySelector('#tabpane-cpu'); + tabCpu!.setMemData(data) + } + + displayFuncData(data: FuncStruct) { + this.setAttribute("mode", "max") + this.tabCurrentSelection!.hidden = false; + this.hideBoxTab(); + this.litTabs?.activeByKey("1") + let tabCpu = this.shadowRoot!.querySelector('#tabpane-cpu'); + tabCpu!.setFunctionData(data) + } + + displayCpuData(data: CpuStruct, + callback: ((data: WakeupBean | null) => void) | undefined = undefined, + scrollCallback?: (data: CpuStruct) => void) { + this.setAttribute("mode", "max") + this.tabCurrentSelection!.hidden = false; + this.hideBoxTab(); + this.litTabs?.activeByKey("1") + let tabCpu = this.shadowRoot!.querySelector('#tabpane-cpu'); + tabCpu!.setCpuData(data, callback, scrollCallback) + } + + displayFlagData(flagObj: Flag) { + this.setAttribute("mode", "max") + this.tabCurrentSelection!.hidden = true; + this.hideBoxTab(); + this.tabBoxFlag!.hidden = false; + this.litTabs?.activeByKey("10") + let tabFlag = this.shadowRoot!.querySelector('#tab-flag'); + tabFlag!.setFlagObj(flagObj) + } + + boxSelection(selection: SelectionParam):boolean { + this.tabBoxChild!.hidden = true; + this.selection = selection; + if (selection.hasFps || selection.cpus.length > 0 || selection.threadIds.length > 0 + || selection.funTids.length > 0 || selection.trackIds.length > 0 || selection.heapIds.length > 0 + || selection.nativeMemory.length > 0) { + this.setAttribute("mode", "max") + this.tabCurrentSelection!.hidden = true; + this.tabBoxFlag!.hidden = true; + this.tabBoxCpuThread!.hidden = selection.cpus.length == 0; + this.tabBoxCpuProcess!.hidden = selection.cpus.length == 0; + this.tabBoxCpuUsage!.hidden = selection.cpus.length == 0; + this.tabBoxSPT!.hidden = selection.cpus.length == 0; + this.tabBoxPTS!.hidden = selection.cpus.length == 0; + this.tabBoxContextSwitch!.hidden = selection.cpus.length == 0; + this.tabBoxThreadSwitch!.hidden = selection.cpus.length == 0; + this.tabBoxThreadStates!.hidden = selection.threadIds.length == 0; + this.tabBoxSlices!.hidden = selection.funTids.length == 0; + this.tabBoxCounters!.hidden = selection.trackIds.length == 0; + this.tabBoxFps!.hidden = !selection.hasFps; + this.tabBoxHeap!.hidden = selection.heapIds.length == 0; + this.tabBoxNMStatistics!.hidden = selection.nativeMemory.length == 0 + this.tabBoxNMCallInfo!.hidden = selection.nativeMemory.length == 0 + this.tabBoxNMemory!.hidden = selection.nativeMemory.length == 0 + this.tabBoxNMSample!.hidden = selection.nativeMemory.length == 0 + this.setBoxActiveKey(selection); + return true; + } else { + this.setAttribute("mode", "hidden") + return false; + } + } + + recoveryBoxSelection() { + this.tabCurrentSelection!.hidden = true; + this.tabBoxCpuThread!.hidden = !(this.selection!.cpus.length > 0); + this.tabBoxCpuProcess!.hidden = !(this.selection!.cpus.length > 0); + this.tabBoxCpuUsage!.hidden = !(this.selection!.cpus.length > 0); + this.tabBoxSPT!.hidden = !(this.selection!.cpus.length > 0); + this.tabBoxPTS!.hidden = !(this.selection!.cpus.length > 0); + this.tabBoxContextSwitch!.hidden = !(this.selection!.cpus.length > 0); + this.tabBoxThreadSwitch!.hidden = !(this.selection!.cpus.length > 0); + this.tabBoxThreadStates!.hidden = !(this.selection!.threadIds.length > 0); + this.tabBoxSlices!.hidden = !(this.selection!.funTids.length > 0); + this.tabBoxCounters!.hidden = !(this.selection!.trackIds.length > 0) + this.tabBoxHeap!.hidden = !(this.selection!.heapIds.length > 0) + this.tabBoxFps!.hidden = !this.selection?.hasFps; + this.tabBoxNMStatistics!.hidden = !(this.selection!.nativeMemory.length > 0) + this.tabBoxNMCallInfo!.hidden = !(this.selection!.nativeMemory.length > 0) + this.tabBoxNMemory!.hidden = !(this.selection!.nativeMemory.length > 0) + this.tabBoxNMSample!.hidden = !(this.selection!.nativeMemory.length > 0) + } + + setBoxActiveKey(val: SelectionParam) { + if (val.cpus.length > 0) { + this.litTabs?.activeByKey("2") + this.loadTabPaneData("2") + } else if (val.threadIds.length > 0) { + this.litTabs?.activeByKey("4") + this.loadTabPaneData("4") + } else if (val.funTids.length > 0) { + this.litTabs?.activeByKey("5") + this.loadTabPaneData("5") + } else if (val.trackIds.length > 0) { + this.litTabs?.activeByKey("6") + this.loadTabPaneData("6") + } else if (val.hasFps) { + this.litTabs?.activeByKey("7") + this.loadTabPaneData("7") + } else if (val.heapIds.length > 0) { + this.litTabs?.activeByKey("9") + this.loadTabPaneData("9") + } else if(val.nativeMemory.length > 0) { + this.litTabs?.activeByKey("16") + this.loadTabPaneData("16") + }else{ + this.litTabs?.activeByKey("1") + this.loadTabPaneData("1") + } + } + + loadTabPaneData(key: string) { + if (key == "2") { + let tabCpuThread = this.shadowRoot!.querySelector('#tab-cpu-thread'); + tabCpuThread!.data = this.selection; + } else if (key == "3") { + let tabCpuProcess = this.shadowRoot!.querySelector('#tab-cpu-process'); + tabCpuProcess!.data = this.selection; + } else if (key == "4") { + let tabThreadStates = this.shadowRoot!.querySelector('#tab-thread-states'); + tabThreadStates!.data = this.selection; + } else if (key == "5") { + let tabSlices = this.shadowRoot!.querySelector('#tab-slices'); + tabSlices!.data = this.selection; + } else if (key == "6") { + let tabCounters = this.shadowRoot!.querySelector('#tab-counters'); + tabCounters!.data = this.selection; + } else if (key == "7") { + let tabFps = this.shadowRoot!.querySelector('#tab-fps'); + tabFps!.data = this.selection; + } else if (key == "8") { + let tabCpuUsage = this.shadowRoot!.querySelector('#tab-cpu-usage'); + tabCpuUsage!.data = this.selection; + } else if (key == "9") { + let tabHeap = this.shadowRoot!.querySelector('#tab-heap'); + tabHeap!.data = this.selection; + } else if (key == "10") { + + } else if (key == "11") { + this.tabSPT!.data = this.selection; + } else if (key == "12") { + this.tabPTS!.data = this.selection; + } else if (key == "13") { + this.tabCs!.data = this.selection; + } else if (key == "14") { + this.tabTs!.data = this.selection; + } else if (key == "16") { + this.tabNativeStatistics!.data = this.selection; + } else if (key == "17") { + this.tabNativeCallInfo!.data = this.selection; + } else if (key == "18") { + this.tabNativeMemory!.data = this.selection; + } else if (key == "19") { + this.tabNativeSample!.data = this.selection; + } + } + + hideBoxTab() { + this.tabBoxCpuThread!.hidden = true; + this.tabBoxCpuProcess!.hidden = true; + this.tabBoxThreadStates!.hidden = true; + this.tabBoxSlices!.hidden = true; + this.tabBoxCounters!.hidden = true; + this.tabBoxFps!.hidden = true; + this.tabBoxSPT!.hidden = true; + this.tabBoxPTS!.hidden = true; + this.tabBoxContextSwitch!.hidden = true; + this.tabBoxThreadSwitch!.hidden = true; + this.tabBoxCpuUsage!.hidden = true; + this.tabBoxFlag!.hidden = true; + this.tabBoxHeap!.hidden = true; + this.tabBoxChild!.hidden = true; + this.tabBoxNMStatistics!.hidden = true; + this.tabBoxNMCallInfo!.hidden = true; + this.tabBoxNMemory!.hidden = true; + this.tabBoxNMSample!.hidden = true; + } + + hideOtherBoxTab(key: string) { + this.tabBoxCpuThread!.hidden = true; + this.tabBoxCpuProcess!.hidden = true; + this.tabBoxThreadStates!.hidden = true; + this.tabBoxSlices!.hidden = true; + this.tabBoxCounters!.hidden = true; + this.tabBoxFps!.hidden = true; + this.tabBoxCpuUsage!.hidden = true; + this.tabBoxHeap!.hidden = true; + this.tabBoxNMStatistics!.hidden = true; + this.tabBoxNMCallInfo!.hidden = true; + this.tabBoxNMemory!.hidden = true; + this.tabBoxNMSample!.hidden = true; + if (key == "11") { + this.tabBoxPTS!.hidden = true; + this.tabBoxContextSwitch!.hidden = true; + this.tabBoxThreadSwitch!.hidden = true; + } else if (key == "12") { + this.tabBoxSPT!.hidden = true; + this.tabBoxContextSwitch!.hidden = true; + this.tabBoxThreadSwitch!.hidden = true; + } else if (key == "13") { + this.tabBoxSPT!.hidden = true; + this.tabBoxPTS!.hidden = true; + this.tabBoxThreadSwitch!.hidden = true; + } else if (key == "14") { + this.tabBoxSPT!.hidden = true; + this.tabBoxPTS!.hidden = true; + this.tabBoxContextSwitch!.hidden = true; + } + this.tabBoxChild!.hidden = false + this.currentKey = key + this.litTabs?.activeByKey("15") + } + + jumpBoxChild(key: string, e: any) { + this.hideOtherBoxTab(key) + this.tabBoxChild!.tab = e.detail.title + let param = new BoxJumpParam(); + param.leftNs = this.selection!.leftNs; + param.rightNs = this.selection!.rightNs; + param.state = e.detail.state; + param.threadId = e.detail.threadId; + param.processId = e.detail.processId; + this.tabChild!.data = param; + } + +} diff --git a/host/ide/src/trace/component/trace/base/Utils.ts b/host/ide/src/trace/component/trace/base/Utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..cb7e6dad238611e49ff712b5c3dc88695d98dd94 --- /dev/null +++ b/host/ide/src/trace/component/trace/base/Utils.ts @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class Utils { + private static statusMap: Map = new Map(); + private static instance: Utils | null = null; + + constructor() { + Utils.statusMap.set("D", "Uninterruptible Sleep"); + Utils.statusMap.set("S", "Sleeping"); + Utils.statusMap.set("R", "Runnable"); + Utils.statusMap.set("Running", "Running"); + Utils.statusMap.set("R+", "Runnable (Preempted)"); + Utils.statusMap.set("DK", "Uninterruptible Sleep + Wake Kill"); + Utils.statusMap.set("I", "Task Dead"); + Utils.statusMap.set("T", "Traced"); + Utils.statusMap.set("t", "Traced"); + Utils.statusMap.set("X", "Exit (Dead)"); + Utils.statusMap.set("Z", "Exit (Zombie)"); + Utils.statusMap.set("K", "Wake Kill"); + Utils.statusMap.set("W", "Waking"); + Utils.statusMap.set("P", "Parked"); + Utils.statusMap.set("N", "No Load"); + } + + public static getInstance(): Utils { + if (Utils.instance == null) { + Utils.instance = new Utils(); + } + return Utils.instance + } + + public static getEndState(state: string): string | null | undefined { + if (Utils.getInstance().getStatusMap().has(state)) { + return Utils.getInstance().getStatusMap().get(state); + } else { + if ("" == state || state == null) { + return ""; + } + return "Unknown State"; + } + } + + public static getStateColor(state: string): string { + if (state == "D" || state == "DK") { + return "#f19b38" + } else if (state == "R" || state == "R+") { + return "#a0b84d" + } else if (state == "I") { + return "#673ab7" + } else if (state == "Running") { + return "#467b3b" + } else if (state == "S") { + return "#e0e0e0" + } else { + return "#ff6e40" + } + } + + public static getTimeString(ns: number): string { + let currentNs = ns + let hour1 = 3600_000_000_000 + let minute1 = 60_000_000_000 + let second1 = 1_000_000_000; + let millisecond1 = 1_000_000; + let microsecond1 = 1_000; + let res = ""; + if (currentNs >= hour1) { + res += Math.floor(currentNs / hour1) + "h "; + currentNs = currentNs - Math.floor(currentNs / hour1) * hour1 + } + if (currentNs >= minute1) { + res += Math.floor(currentNs / minute1) + "m "; + currentNs = currentNs - Math.floor(ns / minute1) * minute1 + } + if (currentNs >= second1) { + res += Math.floor(currentNs / second1) + "s "; + currentNs = currentNs - Math.floor(currentNs / second1) * second1 + } + if (currentNs >= millisecond1) { + res += Math.floor(currentNs / millisecond1) + "ms "; + currentNs = currentNs - Math.floor(currentNs / millisecond1) * millisecond1 + } + if (currentNs >= microsecond1) { + res += Math.floor(currentNs / microsecond1) + "μs "; + currentNs = currentNs - Math.floor(currentNs / microsecond1) * microsecond1 + } + if (currentNs > 0) { + res += currentNs + "ns "; + } + if (res == "") { + res = ns + ""; + } + return res + } + + public static getTimeStringHMS(ns: number): string { + let currentNs = ns + let hour1 = 3600_000_000_000 + let minute1 = 60_000_000_000 + let second1 = 1_000_000_000; // 1 second + let millisecond1 = 1_000_000; // 1 millisecond + let microsecond1 = 1_000; // 1 microsecond + let res = ""; + if (currentNs >= hour1) { + res += Math.floor(currentNs / hour1) + ":"; + currentNs = currentNs - Math.floor(currentNs / hour1) * hour1 + } + if (currentNs >= minute1) { + res += Math.floor(currentNs / minute1) + ":"; + currentNs = currentNs - Math.floor(ns / minute1) * minute1 + } + if (currentNs >= second1) { + res += Math.floor(currentNs / second1) + ":"; + currentNs = currentNs - Math.floor(currentNs / second1) * second1 + } + if (currentNs >= millisecond1) { + res += Math.floor(currentNs / millisecond1) + "."; + currentNs = currentNs - Math.floor(currentNs / millisecond1) * millisecond1 + } + if (currentNs >= microsecond1) { + res += Math.floor(currentNs / microsecond1) + "."; + currentNs = currentNs - Math.floor(currentNs / microsecond1) * microsecond1 + } + if (currentNs > 0) { + res += currentNs + ""; + } + if (res == "") { + res = ns + ""; + } + return res + } + + public static getByteWithUnit(bytes: number): string { + if (bytes < 0) { + return "-" + this.getByteWithUnit(Math.abs(bytes)) + } + let currentBytes = bytes + let kb1 = 1024 + let mb1 = 1048576 + let gb1 = 1073741824; // 1 gb + let res = "" + if (currentBytes > gb1) { + res += (currentBytes / gb1).toFixed(2) + " Gb"; + } else if (currentBytes > mb1) { + res += (currentBytes / mb1).toFixed(2) + " Mb"; + } else if (currentBytes > kb1) { + res += (currentBytes / kb1).toFixed(2) + " kb"; + } else { + res += currentBytes + " byte"; + } + return res + } + + public getStatusMap(): Map { + return Utils.statusMap; + } +} diff --git a/host/ide/src/trace/component/trace/search/Search.ts b/host/ide/src/trace/component/trace/search/Search.ts new file mode 100644 index 0000000000000000000000000000000000000000..23ff8f918a5925be94ed571142ac4d903073f40c --- /dev/null +++ b/host/ide/src/trace/component/trace/search/Search.ts @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; + +@element("lit-search") +export class LitSearch extends BaseElement { + valueChangeHandler: ((str: string) => void) | undefined | null; + private search: HTMLInputElement | undefined | null; + private _total: number = 0; + private _index: number = 0; + private _list: Array = []; + private totalEL: HTMLSpanElement | null | undefined; + private indexEL: HTMLSpanElement | null | undefined; + + get list(): Array { + return this._list; + } + + set list(value: Array) { + this._list = value; + this.total = value.length; + } + + get index(): number { + return this._index; + } + + set index(value: number) { + this._index = value; + this.indexEL!.textContent = `${value+1}`; + } + + get total(): number { + return this._total; + } + + set total(value: number) { + value > 0 ? this.setAttribute("show-search-info", '') : this.removeAttribute("show-search-info"); + this._total = value; + this.indexEL!.textContent = '0'; + this.totalEL!.textContent = value.toString(); + } + + setPercent(name: string = "", value: number) { + let searchHide = this.shadowRoot!.querySelector(".root") + let searchIcon = this.shadowRoot!.querySelector("#search-icon") + if (value > 0 && value <= 100) { + searchHide!.style.display = "flex" + searchHide!.style.backgroundColor = "var(--dark-background5,#e3e3e3)" + searchIcon?.setAttribute('name', "cloud-sync"); + this.search!.setAttribute('placeholder', `${name}${value}%`); + this.search!.setAttribute('readonly', ""); + this.search!.className = "readonly" + } else if (value > 100) { + searchHide!.style.display = "flex" + searchHide!.style.backgroundColor = "var(--dark-background5,#fff)" + searchIcon?.setAttribute('name', "search"); + this.search?.setAttribute('placeholder', `search`); + this.search?.removeAttribute('readonly'); + this.search!.className = "write" + } else if (value == -1) { + searchHide!.style.display = "flex" + searchHide!.style.backgroundColor = "var(--dark-background5,#e3e3e3)" + searchIcon?.setAttribute('name', "cloud-sync"); + this.search!.setAttribute('placeholder', `${name}`); + this.search!.setAttribute('readonly', ""); + this.search!.className = "readonly" + } else { + searchHide!.style.display = "none" + } + } + + clear() { + this.search = this.shadowRoot!.querySelector("input"); + this.search!.value = ""; + this.list = []; + } + + blur(){ + this.search?.blur(); + } + initElements(): void { + this.search = this.shadowRoot!.querySelector("input"); + this.totalEL = this.shadowRoot!.querySelector("#total"); + this.indexEL = this.shadowRoot!.querySelector("#index"); + this.search!.addEventListener("focus", (e) => { + this.dispatchEvent(new CustomEvent("focus", { + detail: { + value: this.search!.value + } + })); + }); + this.search!.addEventListener("blur", (e) => { + this.dispatchEvent(new CustomEvent("blur", { + detail: { + value: this.search!.value + } + })); + }); + this.search!.addEventListener("keyup", (e: KeyboardEvent) => { + if (e.code == "Enter") { + if (e.shiftKey) { + this.dispatchEvent(new CustomEvent("previous-data", { + detail: { + value: this.search!.value + } + })); + } else { + this.dispatchEvent(new CustomEvent("next-data", { + detail: { + value: this.search!.value + } + })); + } + } else { + this.valueChangeHandler?.(this.search!.value); + } + }); + this.shadowRoot?.querySelector("#arrow-left")?.addEventListener("click", (e) => { + this.dispatchEvent(new CustomEvent("previous-data", { + detail: { + value: this.search!.value + } + })); + }); + this.shadowRoot?.querySelector("#arrow-right")?.addEventListener("click", (e) => { + this.dispatchEvent(new CustomEvent("next-data", { + detail: { + value: this.search!.value + } + })); + }); + } + + initHtml(): string { + return ` + + + `; + } + +} diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneBoxChild.ts b/host/ide/src/trace/component/trace/sheet/TabPaneBoxChild.ts new file mode 100644 index 0000000000000000000000000000000000000000..c37351bf74ec91f3ef5d077f474657fda33ffda8 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneBoxChild.ts @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {BoxJumpParam, SelectionData} from "../../../bean/BoxSelection.js"; +import {getTabBoxChildData} from "../../../database/SqlLite.js"; +import {Utils} from "../base/Utils.js"; +import {SpSystemTrace} from "../../SpSystemTrace.js"; +import {SPTChild} from "../../../bean/StateProcessThread.js"; + +@element('tabpane-box-child') +export class TabPaneBoxChild extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private source: Array = []; + private loadDataInCache: boolean = true; + + set data(val: BoxJumpParam) { + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table")?.style?.height = (this.parentElement!.clientHeight - 45)+"px"; + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" + if (this.loadDataInCache) { + this.getDataByCache(val).then((arr) => { + this.source = arr; + // @ts-ignore + this.tbl?.recycleDataSource = arr; + }) + } else { + this.getDataByDB(val) + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-cpu-thread'); + this.range = this.shadowRoot?.querySelector('#time-range'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45)+"px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + + getDataByDB(val: BoxJumpParam) { + getTabBoxChildData(val.leftNs, val.rightNs, val.state, val.processId, val.threadId).then((result) => { + if (result.length != null && result.length > 0) { + result.map((e) => { + e.startTime = Utils.getTimeString(e.startNs) + e.state = Utils.getEndState(e.state)! + e.prior = e.priority == undefined || e.priority == null ? "-" : e.priority + "" + e.core = e.cpu == undefined || e.cpu == null ? "-" : "CPU" + e.cpu + e.processName = (e.process == undefined || e.process == null ? "process" : e.process) + "(" + e.processId + ")" + e.threadName = (e.thread == undefined || e.thread == null ? "thread" : e.thread) + "(" + e.threadId + ")" + }) + this.source = result; + // @ts-ignore + this.tbl?.dataSource = result; + } else { + this.source = []; + // @ts-ignore + this.tbl?.dataSource = [] + } + }) + } + + getDataByCache(val: BoxJumpParam): Promise> { + return new Promise>((resolve, reject) => { + let time = Date.now(); + let arr: Array = []; + SpSystemTrace.SPT_DATA.map((spt) => { + let b1 = (val.state != undefined && val.state != '') ? spt.state == val.state : true + let b2 = (val.processId != undefined && val.processId != -1) ? spt.processId == val.processId : true + let b3 = (val.threadId != undefined && val.threadId != -1) ? spt.threadId == val.threadId : true + if(!(spt.end_ts < val.leftNs || spt.start_ts > val.rightNs) && b1 && b2 && b3){ + let sptChild = new SPTChild(); + sptChild.startTime = Utils.getTimeString(spt.start_ts) + sptChild.state = Utils.getEndState(spt.state)! + sptChild.prior = spt.priority == undefined || spt.priority == null ? "-" : spt.priority + "" + sptChild.core = spt.cpu == undefined || spt.cpu == null ? "-" : "CPU" + spt.cpu + sptChild.processName = (spt.process == undefined || spt.process == null || spt.process == "" ? "process" : spt.process) + "(" + spt.processId + ")" + sptChild.threadName = (spt.thread == undefined || spt.thread == null || spt.thread == "" ? "thread" : spt.thread) + "(" + spt.threadId + ")" + arr.push(sptChild); + } + }) + resolve(arr); + }) + + } + + initHtml(): string { + return ` + + + + + + + + + + + + `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: SelectionData, b: SelectionData) { + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } else { + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + } + + // @ts-ignore + this.source.sort(compare(detail.key, detail.sort, 'string')) + this.tbl!.dataSource = this.source; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneContextSwitch.ts b/host/ide/src/trace/component/trace/sheet/TabPaneContextSwitch.ts new file mode 100644 index 0000000000000000000000000000000000000000..0098d18d90f375868153e0469ce679acee218153 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneContextSwitch.ts @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../bean/BoxSelection.js"; +import { + getTabStatesGroupByProcess, + getTabStatesGroupByProcessThread, + getTabStatesGroupByStatePidTid +} from "../../../database/SqlLite.js"; +import {StateProcessThread} from "../../../bean/StateProcessThread.js"; +import {Utils} from "../base/Utils.js"; +import {SpSystemTrace} from "../../SpSystemTrace.js"; + +@element('tabpane-context-switch') +export class TabPaneContextSwitch extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private loadDataInCache: boolean = true; + + set data(val: SelectionParam | any) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45)+"px" + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" + if (this.loadDataInCache) { + this.queryDataInCacheData(val).then((arr) => { + this.tbl!.recycleDataSource = arr; + }); + } else { + this.queryDataByDB(val) + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-cs'); + this.range = this.shadowRoot?.querySelector('#time-range') + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45)+"px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + + async queryDataInCacheData(val: SelectionParam | any): Promise> { + return new Promise>((resolve, reject) => { + let pMap: Map = new Map(); + let ptMap: Map = new Map(); + let ptsMap: Map = new Map(); + SpSystemTrace.SPT_DATA.map((d)=>{ + if(!(d.end_ts < val.leftNs || d.start_ts > val.rightNs)){ + if (pMap.has(d.processId + "")) { + let obj1 = pMap.get(d.processId + ""); + obj1!.count++; + obj1!.wallDuration += d.dur; + obj1!.avgDuration = (obj1!.wallDuration / obj1!.count).toFixed(2); + if (d.dur > obj1!.maxDuration) { + obj1!.maxDuration = d.dur; + } + if (d.dur < obj1!.minDuration) { + obj1!.minDuration = d.dur; + } + } else { + let obj1 = new StateProcessThread(); + obj1.id = "p" + d.processId; + obj1.title = (d.process == null || d.process == "" ? "Process" : d.process) + "(" + d.processId + ")"; + obj1.process = d.process; + obj1.processId = d.processId; + obj1.minDuration = d.dur; + obj1.maxDuration = d.dur; + obj1.count = 1; + obj1.avgDuration = d.dur + ""; + obj1.wallDuration = d.dur; + pMap.set(d.processId + "", obj1); + } + if (ptMap.has(d.processId + "_" + d.threadId)) { + let obj2 = ptMap.get(d.processId + "_" + d.threadId); + obj2!.count++; + obj2!.wallDuration += d.dur; + obj2!.avgDuration = (obj2!.wallDuration / obj2!.count).toFixed(2); + if (d.dur > obj2!.maxDuration) { + obj2!.maxDuration = d.dur; + } + if (d.dur < obj2!.minDuration) { + obj2!.minDuration = d.dur; + } + } else { + let obj2 = new StateProcessThread(); + obj2.id = "p" + d.processId + "_" + "t" + d.threadId; + obj2.pid = "p" + d.processId; + obj2.title = (d.thread == null || d.thread == "" ? "Thread" : d.thread) + "(" + d.threadId + ")" + obj2.processId = d.processId; + obj2.process = d.process; + obj2.thread = d.thread; + obj2.threadId = d.threadId; + obj2.minDuration = d.dur; + obj2.maxDuration = d.dur; + obj2.count = 1; + obj2.avgDuration = d.dur + ""; + obj2.wallDuration = d.dur; + ptMap.set(d.processId + "_" + d.threadId, obj2); + } + if (ptsMap.has(d.processId + "_" + d.threadId + "_" + d.state)) { + let obj3 = ptsMap.get(d.processId + "_" + d.threadId + "_" + d.state); + obj3!.count++; + obj3!.wallDuration += d.dur; + obj3!.avgDuration = (obj3!.wallDuration / obj3!.count).toFixed(2); + if (d.dur > obj3!.maxDuration) { + obj3!.maxDuration = d.dur; + } + if (d.dur < obj3!.minDuration) { + obj3!.minDuration = d.dur; + } + } else { + let obj3 = new StateProcessThread(); + obj3.id = "p" + d.processId + "_" + "t" + d.threadId + "_" + (d.state == "R+" ? "RP" : d.state) + obj3.pid = "p" + d.processId + "_" + "t" + d.threadId; + obj3.title = Utils.getEndState(d.state) + obj3.processId = d.processId; + obj3.process = d.process; + obj3.thread = d.thread; + obj3.threadId = d.threadId; + obj3.state = d.state; + obj3.minDuration = d.dur; + obj3.maxDuration = d.dur; + obj3.count = 1; + obj3.avgDuration = d.dur + ""; + obj3.wallDuration = d.dur; + ptsMap.set(d.processId + "_" + d.threadId + "_" + d.state, obj3); + } + } + }) + let arr: Array = []; + for (let key of pMap.keys()) { + let s = pMap.get(key); + s!.children = []; + for (let ks of ptMap.keys()) { + if (ks.startsWith(key + "_")) { + let sp = ptMap.get(ks) + sp!.children = []; + for (let kst of ptsMap.keys()) { + if (kst.startsWith(ks + "_")) { + let spt = ptsMap.get(kst) + sp!.children.push(spt!); + } + } + s!.children.push(sp!) + } + } + arr.push(s!) + } + resolve(arr); + }) + } + + queryDataByDB(val: SelectionParam | any) { + Promise.all([ + getTabStatesGroupByProcess(val.leftNs, val.rightNs), + getTabStatesGroupByProcessThread(val.leftNs, val.rightNs), + getTabStatesGroupByStatePidTid(val.leftNs, val.rightNs)]).then((values) => { + let processes = values[0]; + processes.map((spt) => { + spt.id = "p" + spt.processId + spt.title = (spt.process == null || spt.process == "" ? "Process" : spt.process) + "(" + spt.processId + ")" + }); + let threadMap = this.groupByProcessToMap(values[1]); + let stateMap = this.groupByProcessThreadToMap(values[2]); + for (let process of processes) { + let threads = threadMap.get(process.processId); + if (threads != undefined) { + threads!.map((spt) => { + spt.id = "p" + spt.processId + "_" + "t" + spt.threadId; + spt.pid = "p" + spt.processId; + spt.title = (spt.thread == null || spt.thread == "" ? "Thread" : spt.thread) + "(" + spt.threadId + ")" + }) + } + process.children = threads ?? []; + let map = stateMap.get(process.processId); + for (let thread of threads!) { + let states = map!.get(thread.threadId); + states!.map((spt) => { + spt.id = "p" + spt.processId + "_" + "t" + spt.threadId + "_" + (spt.state == "R+" ? "RP" : spt.state) + spt.pid = "p" + spt.processId + "_" + "t" + spt.threadId; + spt.title = Utils.getEndState(spt.state) + }) + thread.children = states ?? []; + } + } + this.tbl!.dataSource = processes; + }) + } + + groupByThreadToMap(arr: Array): Map> { + let map = new Map>(); + for (let spt of arr) { + if (map.has(spt.threadId)) { + map.get(spt.threadId)!.push(spt); + } else { + let list: Array = []; + list.push(spt); + map.set(spt.threadId, list); + } + } + return map; + } + + groupByProcessToMap(arr: Array): Map> { + let map = new Map>(); + for (let spt of arr) { + if (map.has(spt.processId)) { + map.get(spt.processId)!.push(spt); + } else { + let list: Array = []; + list.push(spt); + map.set(spt.processId, list); + } + } + return map; + } + + groupByProcessThreadToMap(arr: Array): Map>> { + let map = new Map>>(); + let processMap = this.groupByProcessToMap(arr); + for (let key of processMap.keys()) { + let threadMap = this.groupByThreadToMap(processMap.get(key)!) + map.set(key, threadMap); + } + return map; + } + + initHtml(): string { + return ` + + + + + + + `; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneCounter.ts b/host/ide/src/trace/component/trace/sheet/TabPaneCounter.ts new file mode 100644 index 0000000000000000000000000000000000000000..582811f47cd5d8fe5010859197fb228720f38110 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneCounter.ts @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {Counter, SelectionData, SelectionParam} from "../../../bean/BoxSelection.js"; +import {getTabCounters} from "../../../database/SqlLite.js"; + +@element('tabpane-counter') +export class TabPaneCounter extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private source: Array = [] + + set data(val: SelectionParam | any) { + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" + getTabCounters(val.trackIds, val.rightNs).then((result) => { + if (result != null && result.length > 0) { + let dataSource: Array = []; + let collect = this.groupByTrackIdToMap(result); + let sumCount = 0; + for (let key of collect.keys()) { + let counters = collect.get(key); + let list:Array = []; + let index = counters!.findIndex((item) => item.startTime >= val.leftNs); + if (index != -1) { + list = counters!.splice(index > 0 ? index - 1 : index) + } else { + list.push(counters![counters!.length - 1]); + } + let sd = this.createSelectCounterData(list, val.leftNs, val.rightNs); + sumCount += Number.parseInt(sd.count); + dataSource.push(sd); + } + let sumData = new SelectionData(); + sumData.count = sumCount.toString(); + sumData.process = " "; + dataSource.splice(0, 0, sumData); + this.source = dataSource + this.tbl!.dataSource = dataSource + } else { + this.source = []; + this.tbl!.dataSource = this.source + } + }); + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-counter'); + this.range = this.shadowRoot?.querySelector('#time-range'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + `; + } + + groupByTrackIdToMap(arr: Array): Map> { + let map = new Map>(); + for (let counter of arr) { + if (map.has(counter.trackId)) { + map.get(counter.trackId)!.push(counter); + } else { + let list: Array = []; + list.push(counter); + map.set(counter.trackId, list); + } + } + return map; + } + + createSelectCounterData(list: Array, leftNs: number, rightNs: number): SelectionData { + let selectData = new SelectionData(); + if (list.length > 0) { + let range = rightNs - leftNs; + let first = list[0]; + selectData.trackId = first.trackId; + selectData.name = first.name; + selectData.first = first.value + ""; + selectData.count = list.length + ""; + selectData.last = list[list.length - 1].value + ""; + selectData.delta = (parseInt(selectData.last) - parseInt(selectData.first)) + ""; + selectData.rate = (parseInt(selectData.delta) / (range * 1.0 / 1000000000)).toFixed(4); + selectData.min = first.value + ""; + selectData.max = "0"; + let weightAvg = 0.0; + for (let i = 0; i < list.length; i++) { + let counter = list[i]; + if (counter.value < parseInt(selectData.min)) { + selectData.min = counter.value.toString(); + } + if (counter.value > parseInt(selectData.max)) { + selectData.max = counter.value.toString(); + } + let start = i == 0 ? leftNs : counter.startTime + let end = i == list.length - 1 ? rightNs : list[i + 1].startTime + weightAvg += counter.value * ((end - start) * 1.0 / range); + } + selectData.avgWeight = weightAvg.toFixed(2) + } + return selectData; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: SelectionData, b: SelectionData) { + if (a.process == " " || b.process == " ") { + return 0; + } + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } else { + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + } + + if (detail.key === 'name') { + this.source.sort(compare(detail.key, detail.sort, 'string')) + } else { + this.source.sort(compare(detail.key, detail.sort, 'number')) + } + this.tbl!.dataSource = this.source; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneCpu.ts b/host/ide/src/trace/component/trace/sheet/TabPaneCpu.ts new file mode 100644 index 0000000000000000000000000000000000000000..cb5a3a769f90dbb9e4eb9bc55edb379707067ed8 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneCpu.ts @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {CpuStruct} from "../../../bean/CpuStruct.js"; + +@element('tabpane-cpu') +export class TabPaneCpu extends BaseElement { + private tbl: LitTable | null | undefined; + + set data(val: CpuStruct) { + this.tbl!.dataSource = [ + {name: 'Process', value: `${val.processName || 'Process'} [${val.processId}]`}, + {name: 'Thread', value: `${val.name || 'Thread'} [${val.tid}]`}, + {name: 'Cmdline', value: val.processCmdLine}, + {name: 'Start time', value: val.startTime}, + {name: 'Duration', value: val.dur}, + {name: 'Prio', value: val.priority}, + {name: 'End State', value: val.end_state}, + {name: 'Slice ID', value: val.id} + ] + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tbl3'); + } + + initHtml(): string { + return ` + + + + + + + `; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneCpuByProcess.ts b/host/ide/src/trace/component/trace/sheet/TabPaneCpuByProcess.ts new file mode 100644 index 0000000000000000000000000000000000000000..5537ba596159ba28b00eada557613f78b5e82969 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneCpuByProcess.ts @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {SelectionData, SelectionParam} from "../../../bean/BoxSelection.js"; +import {getTabCpuByProcess} from "../../../database/SqlLite.js"; + +@element('tabpane-cpu-process') +export class TabPaneCpuByProcess extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private source: Array = [] + + set data(val: SelectionParam | any) { + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" + getTabCpuByProcess(val.cpus, val.leftNs, val.rightNs).then((result) => { + if (result != null && result.length > 0) { + let sumWall = 0.0; + let sumOcc = 0; + for (let e of result) { + e.process = e.process == null || e.process.length == 0 ? "[NULL]" : e.process + sumWall += e.wallDuration + sumOcc += e.occurrences + e.wallDuration = parseFloat((e.wallDuration / 1000000.0).toFixed(5)); + e.avgDuration = parseFloat((parseFloat(e.avgDuration) / 1000000.0).toFixed(5)).toString(); + } + let count = new SelectionData() + count.process = " " + count.wallDuration = parseFloat((sumWall / 1000000.0).toFixed(5)); + count.occurrences = sumOcc; + result.splice(0, 0, count) + this.source = result + this.tbl!.dataSource = result + } else { + this.source = []; + this.tbl!.dataSource = this.source + } + }); + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-cpu-process'); + this.range = this.shadowRoot?.querySelector('#time-range') + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + } + + initHtml(): string { + return ` + + + + + + + + + + `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: SelectionData, b: SelectionData) { + if (a.process == " " || b.process == " ") { + return 0; + } + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } else { + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + } + + if (detail.key === 'pid' || detail.key === 'wallDuration' || detail.key === 'avgDuration' || detail.key === 'occurrences') { + this.source.sort(compare(detail.key, detail.sort, 'number')) + } else { + this.source.sort(compare(detail.key, detail.sort, 'string')) + } + this.tbl!.dataSource = this.source; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneCpuByThread.ts b/host/ide/src/trace/component/trace/sheet/TabPaneCpuByThread.ts new file mode 100644 index 0000000000000000000000000000000000000000..69192ddcf5a4bfe3c422a1d3b242806ae7ed23e2 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneCpuByThread.ts @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {SelectionData, SelectionParam} from "../../../bean/BoxSelection.js"; +import {getTabCpuByThread} from "../../../database/SqlLite.js"; + +@element('tabpane-cpu-thread') +export class TabPaneCpuByThread extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private source: Array = [] + + set data(val: SelectionParam | any) { + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" + getTabCpuByThread(val.cpus, val.leftNs, val.rightNs).then((result) => { + if (result != null && result.length > 0) { + let sumWall = 0.0; + let sumOcc = 0; + for (let e of result) { + e.process = e.process == null || e.process.length == 0 ? "[NULL]" : e.process + e.thread = e.thread == null || e.thread.length == 0 ? "[NULL]" : e.thread + sumWall += e.wallDuration + sumOcc += e.occurrences + e.wallDuration = parseFloat((e.wallDuration / 1000000.0).toFixed(5)); + e.avgDuration = parseFloat((parseFloat(e.avgDuration) / 1000000.0).toFixed(5)).toString(); + } + let count = new SelectionData() + count.process = " " + count.wallDuration = parseFloat((sumWall / 1000000.0).toFixed(7)); + count.occurrences = sumOcc; + result.splice(0, 0, count) + this.source = result + this.tbl!.dataSource = result + } else { + this.source = []; + this.tbl!.dataSource = this.source + } + }) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-cpu-thread'); + this.range = this.shadowRoot?.querySelector('#time-range'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + + } + + initHtml(): string { + return ` + + + + + + + + + + + + `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: SelectionData, b: SelectionData) { + if (a.process == " " || b.process == " ") { + return 0; + } + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } else { + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + } + + if (detail.key === 'pid' || detail.key == "tid" || detail.key === 'wallDuration' || detail.key === 'avgDuration' || detail.key === 'occurrences') { + this.source.sort(compare(detail.key, detail.sort, 'number')) + } else { + this.source.sort(compare(detail.key, detail.sort, 'string')) + } + this.tbl!.dataSource = this.source; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneCpuUsage.ts b/host/ide/src/trace/component/trace/sheet/TabPaneCpuUsage.ts new file mode 100644 index 0000000000000000000000000000000000000000..e66a633683079dc4fe57679590b0db39d30e8ca5 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneCpuUsage.ts @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../bean/BoxSelection.js"; +import {getTabCpuFreq, getTabCpuUsage} from "../../../database/SqlLite.js"; +import {CpuUsage, Freq} from "../../../bean/CpuUsage.js"; + +@element('tabpane-cpu-usage') +export class TabPaneCpuUsage extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private orderByOldList: any[] = []; + + set data(val: SelectionParam | any) { + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" + Promise.all([getTabCpuUsage(val.cpus, val.leftNs, val.rightNs), getTabCpuFreq(val.cpus, val.leftNs, val.rightNs)]).then((result) => { + let usages = result[0]; + let freqMap = this.groupByCpuToMap(result[1]) + let data = []; + let range = val.rightNs - val.leftNs; + for (let cpu of val.cpus) { + let usage = new CpuUsage(); + usage.cpu = cpu; + let u = usages.find((e) => e.cpu == cpu); + if (u != undefined && u != null) { + usage.usage = u.usage + } else { + usage.usage = 0; + } + if (usage.usage > 1) { + usage.usage = 1; + } + usage.usageStr = (usage.usage * 100.0).toFixed(2) + "%" + let arr = []; + if (freqMap.has(usage.cpu)) { + let freqList = freqMap.get(usage.cpu) + let list = [] + for (let i = 0; i < freqList!.length; i++) { + let freq = freqList![i]; + if (i == freqList!.length - 1) { + freq.dur = val.rightNs - freq.startNs + } else { + freq.dur = freqList![i + 1].startNs - freq.startNs + } + if (freq.startNs + freq.dur > val.leftNs) { + list.push(freq); + } + } + if (list.length > 0) { + if (list[0].startNs < val.leftNs) { + list[0].dur = list[0].startNs + list[0].dur - val.leftNs + list[0].startNs = val.leftNs; + } + } + arr = this.sortFreq(list); + this.getFreqTop3(usage, arr[0], arr[1], arr[2], range) + } + data.push(usage) + } + this.tbl!.dataSource = data; + this.orderByOldList = [...data] + }) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-cpu-usage'); + this.range = this.shadowRoot?.querySelector('#time-range') + this.tbl?.addEventListener("column-click", event => { + // @ts-ignore + let orderType = event.detail; + if (orderType.sort == 1) {//倒序 注意 sort会改变原数组,需要传入table上的数组 不能传入缓存排序数组 + this.sortTable(this.tbl!.dataSource, orderType.key, false) + } else if (orderType.sort == 2) {//正序 + this.sortTable(this.tbl!.dataSource, orderType.key, true) + } else {//默认排序 + this.tbl!.dataSource = [...this.orderByOldList]; + } + }) + } + + sortTable(arr: any[], key: string, sort: boolean) { + this.tbl!.dataSource = arr.sort((item1, item2) => { + let value1 = Number(item1[key].toString().replace("%", "")); + let value2 = Number(item2[key].toString().replace("%", "")); + if (value1 > value2) { + return sort ? -1 : 1 + } else if (value1 < value2) { + return sort ? 1 : -1 + } else { + return 0 + } + }); + } + + sortFreq(arr: Array): Array> { + let map = new Map(); + for (let freq of arr) { + if (map.has(freq.value)) { + let sumDur = map.get(freq.value)! + freq.dur; + map.set(freq.value, sumDur) + } else { + map.set(freq.value, freq.dur); + } + } + let array = Array.from(map); + array.sort((a, b) => b[1] - a[1]) + return array + } + + getFreqTop3(usage: CpuUsage, top1: Array, top2: Array, top3: Array, range: number) { + // @ts-ignore + usage.top1 = top1 == undefined ? '-' : top1[0] + usage.top1Percent = top1 == undefined ? 0 : top1[1] * 1.0 / range; + usage.top1PercentStr = top1 == undefined ? "-" : (usage.top1Percent * 100).toFixed(2) + "%" + // @ts-ignore + usage.top2 = top2 == undefined ? '-' : top2[0] + usage.top2Percent = top2 == undefined ? 0 : top2[1] * 1.0 / range; + usage.top2PercentStr = top2 == undefined ? "-" : (usage.top2Percent * 100).toFixed(2) + "%" + // @ts-ignore + usage.top3 = top3 == undefined ? '-' : top3[0] + usage.top3Percent = top3 == undefined ? 0 : top3[1] * 1.0 / range; + usage.top3PercentStr = top3 == undefined ? "-" : (usage.top3Percent * 100).toFixed(2) + "%" + } + + groupByCpuToMap(arr: Array): Map> { + let map = new Map>(); + for (let spt of arr) { + if (map.has(spt.cpu)) { + map.get(spt.cpu)!.push(spt); + } else { + let list: Array = []; + list.push(spt); + map.set(spt.cpu, list); + } + } + return map; + } + + initHtml(): string { + return ` + + + + + + + + + + + + + `; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts b/host/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts new file mode 100644 index 0000000000000000000000000000000000000000..6ffdaf1669a00a2177962e936eebcb94253ec909 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts @@ -0,0 +1,450 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {CpuStruct} from "../../../bean/CpuStruct.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import "../../../../base-ui/table/lit-table-column.js"; + +import { + queryBinderArgsByArgset, + queryWakeUpThread_WakeThread, + queryWakeUpThread_WakeTime +} from "../../../database/SqlLite.js"; +import {WakeupBean} from "../../../bean/WakeupBean.js"; +import {ThreadStruct} from "../../../bean/ThreadStruct.js"; +import {ProcessMemStruct} from "../../../bean/ProcessMemStruct.js"; +import {FuncStruct} from "../../../bean/FuncStruct.js"; +import {SpApplication} from "../../../SpApplication.js"; + +const STATUS_MAP: any = { + D: "Uninterruptible Sleep", + S: "Sleeping", + R: "Runnable", + "Running": "Running", + "R+": "Runnable (Preempted)", + DK: "Uninterruptible Sleep + Wake Kill", + I: "Task Dead", + T: "Traced", + t: "Traced", + X: "Exit (Dead)", + Z: "Exit (Zombie)", + K: "Wake Kill", + W: "Waking", + P: "Parked", + N: "No Load" +} +const INPUT_WORD = "This is the interval from when the task became eligible to run \n(e.g.because of notifying a wait queue it was a suspended on) to\n when it started running." + +export function getTimeString(ns: number): string { + let currentNs = ns + let hour1 = 3600_000_000_000 + let minute1 = 60_000_000_000 + let second1 = 1_000_000_000; // 1 second + let millisecond1 = 1_000_000; // 1 millisecond + let microsecond1 = 1_000; // 1 microsecond + let res = ""; + if (currentNs >= hour1) { + res += Math.floor(currentNs / hour1) + "h "; + currentNs = currentNs - Math.floor(currentNs / hour1) * hour1 + } + if (currentNs >= minute1) { + res += Math.floor(currentNs / minute1) + "m "; + currentNs = currentNs - Math.floor(ns / minute1) * minute1 + } + if (currentNs >= second1) { + res += Math.floor(currentNs / second1) + "s "; + currentNs = currentNs - Math.floor(currentNs / second1) * second1 + } + if (currentNs >= millisecond1) { + res += Math.floor(currentNs / millisecond1) + "ms "; + currentNs = currentNs - Math.floor(currentNs / millisecond1) * millisecond1 + } + if (currentNs >= microsecond1) { + res += Math.floor(currentNs / microsecond1) + "μs "; + currentNs = currentNs - Math.floor(currentNs / microsecond1) * microsecond1 + } + if (currentNs > 0) { + res += currentNs + "ns "; + } + return res +} + +@element('tabpane-current-selection') +export class TabPaneCurrentSelection extends BaseElement { + weakUpBean: WakeupBean | null | undefined; + private tbl: LitTable | null | undefined; + private tableObserver: MutationObserver | undefined + // @ts-ignore + private dpr: any = window.devicePixelRatio || window.webkitDevicePixelRatio || window.mozDevicePixelRatio || 1; + + set data(value: any) { + this.setCpuData(value) + } + + setCpuData(data: CpuStruct, callback: ((data: WakeupBean | null) => void) | undefined = undefined, scrollCallback?: (data: CpuStruct) => void) { + let leftTitle: HTMLElement | null | undefined = this?.shadowRoot?.querySelector("#leftTitle"); + if (leftTitle) { + leftTitle.innerText = "Slice Details" + } + let list: any[] = [] + let process = data.processName + let processId = data.processId + if (process == null || process == "") { + process = data.name + processId = data.tid + } + let state = "" + if (data.end_state) { + state = STATUS_MAP[data.end_state] + } else if (data.end_state == "" || data.end_state == null) { + state = "" + } else { + state = "Unknown State" + } + + list.push({name: 'Process', value: `${process || 'Process'} [${processId}]`}) + list.push({ + name: 'Thread', value: `
+
${data.name || 'Process'} [${data.tid}]
+ +
` + }) + list.push({name: 'CmdLine', value: `${data.processCmdLine}`}) + list.push({name: 'StartTime', value: getTimeString(data.startTime || 0)}) + list.push({name: 'Duration', value: getTimeString(data.dur || 0)}) + list.push({name: 'Prio', value: data.priority || 0}) + list.push({name: 'End State', value: state}) + this.queryWakeUpData(data).then((bean) => { + if (callback) { + callback(bean) + } + this.tbl!.dataSource = list + let rightArea: HTMLElement | null | undefined = this?.shadowRoot?.querySelector("#right-table"); + let rightTitle: HTMLElement | null | undefined = this?.shadowRoot?.querySelector("#rightTitle"); + let threadClick = this.tbl?.shadowRoot?.querySelector("#thread-id") + threadClick?.addEventListener("click", () => { + //cpu点击 + if (scrollCallback) { + scrollCallback(data) + } + }) + let canvas = this.initCanvas(); + if (bean != null) { + this.weakUpBean = bean; + if (rightArea != null && rightArea) { + rightArea.style.visibility = "visible" + } + if (rightTitle != null && rightTitle) { + rightTitle.style.visibility = "visible" + } + this.drawRight(canvas, bean) + } else { + this.weakUpBean = null; + if (rightArea != null && rightArea) { + rightArea.style.visibility = "hidden" + } + if (rightTitle != null && rightTitle) { + rightTitle.style.visibility = "hidden" + } + } + }) + } + + setFunctionData(data: FuncStruct) {//方法信息 + this.initCanvas() + let leftTitle: HTMLElement | null | undefined = this?.shadowRoot?.querySelector("#leftTitle"); + let rightTitle: HTMLElement | null | undefined = this?.shadowRoot?.querySelector("#rightTitle"); + if (rightTitle) { + rightTitle.style.visibility = "hidden" + } + if (leftTitle) { + leftTitle.innerText = "Slice Details" + } + let list: any[] = [] + list.push({name: 'Name', value: data.funName}) + // list.push({name: 'Category', value:data.category}) 暂无参数 + list.push({name: 'StartTime', value: getTimeString(data.startTs || 0)}) + list.push({name: 'Duration', value: getTimeString(data.dur || 0)}) + if (FuncStruct.isBinder(data)) { + if (data.argsetid != undefined) { + queryBinderArgsByArgset(data.argsetid).then((argset) => { + argset.forEach((item) => { + list.push({name: item.keyName, value: item.strValue}) + }) + + }); + } + list.push({name: 'depth', value: data.depth}) + list.push({name: 'arg_set_id', value: data.argsetid}) + } + this.tbl!.dataSource = list + + } + + setMemData(data: ProcessMemStruct) {//时钟信息 + this.initCanvas() + let leftTitle: HTMLElement | null | undefined = this?.shadowRoot?.querySelector("#leftTitle"); + if (leftTitle) { + leftTitle.innerText = "Counter Details" + } + let list: any[] = [] + list.push({name: 'Start time', value: getTimeString(data.startTime || 0)}) + list.push({name: 'Value', value: data.value}) + list.push({name: 'Delta', value: data.delta}) + list.push({name: 'Duration', value: getTimeString(data.duration || 0)}) + this.tbl!.dataSource = list + + } + + setThreadData(data: ThreadStruct, scrollCallback: ((d: any) => void) | undefined) {//线程信息 + this.initCanvas() + let leftTitle: HTMLElement | null | undefined = this?.shadowRoot?.querySelector("#leftTitle"); + let rightTitle: HTMLElement | null | undefined = this?.shadowRoot?.querySelector("#rightTitle"); + if (rightTitle) { + rightTitle.style.visibility = "hidden" + } + if (leftTitle) { + leftTitle.innerText = "Counter Details" + } + let list: any[] = [] + list.push({name: 'StartTime', value: getTimeString(data.startTime || 0)}) + list.push({name: 'Duration', value: getTimeString(data.dur || 0)}) + let state = "" + if (data.state) { + state = STATUS_MAP[data.state] + } else if (data.state == "" || data.state == null) { + state = "" + } else { + state = "Unknown State" + } + if ("Running" == state) { + state = state + " on CPU " + data.cpu; + } + if (data.cpu == null || data.cpu == undefined) { + list.push({name: 'State', value: `${state}`}) + } else { + list.push({ + name: 'State', value: `
+
${state}
+ +
` + }) + } + let processName = data.processName; + if (processName == null || processName == "" || processName.toLowerCase() == "null") { + processName = data.name; + } + list.push({name: 'Process', value: processName + " [" + data.pid + "] "}) + this.tbl!.dataSource = list + this.tbl?.shadowRoot?.querySelector("#state-click")?.addEventListener("click", () => { + //线程点击 + if (scrollCallback) { + scrollCallback(data) + } + }) + } + + async queryWakeUpData(data: CpuStruct) { + let wb: WakeupBean | null = null + if (data.id == undefined || data.startTime == undefined) { + return null + } + let wakeupTimes = await queryWakeUpThread_WakeTime(data.id, data.startTime)// 3,4835380000 + if (wakeupTimes != undefined && wakeupTimes.length > 0) { + let wakeupTime = wakeupTimes[0] + if (wakeupTime.wakeTs != undefined && wakeupTime.preRow != undefined && wakeupTime.wakeTs < wakeupTime.preRow) { + return null + } + if (wakeupTime.wakeTs == undefined) { + return null + } + let wakeupBeans = await queryWakeUpThread_WakeThread(wakeupTime.wakeTs) + if (wakeupBeans != undefined && wakeupBeans.length > 0) { + wb = wakeupBeans[0] + if (wb != null) { + if (wakeupTime.wakeTs != undefined && wakeupTime.startTs != undefined) { + wb.wakeupTime = wakeupTime.wakeTs - wakeupTime.startTs + } + wb.schedulingLatency = (data.startTime || 0) - (wb.wakeupTime || 0) + if (wb.process == null) { + wb.process = wb.thread; + } + if (wb.pid == undefined) { + wb.pid = wb.tid; + } + wb.schedulingDesc = INPUT_WORD + } + } + } + return wb + } + + initCanvas(): HTMLCanvasElement | null { + let canvas = this.shadowRoot!.querySelector("#rightDraw") + let width = getComputedStyle(this.tbl!).getPropertyValue("width") + let height = getComputedStyle(this.tbl!).getPropertyValue("height") + if (canvas != null) { + canvas.width = Math.round(Number(width.replace("px", "")) * this.dpr) + canvas.height = Math.round(Number(height.replace("px", "")) * this.dpr) + canvas.style.width = width + canvas.style.height = height + canvas.getContext("2d")!.scale(this.dpr, this.dpr) + } + SpApplication.skinChange = (val: boolean) => { + this.drawRight(canvas, this.weakUpBean!) + } + return canvas + } + + drawRight(cavs: HTMLCanvasElement | null, wakeupBean: WakeupBean | null) { + if (cavs == null) { + return + } + let context = cavs.getContext("2d"); + if (context != null) { + //绘制竖线 + if (document.querySelector("sp-application")!.dark) { + context.strokeStyle = "#ffffff"; + context.fillStyle = "#ffffff"; + } else { + context.strokeStyle = "#000000"; + context.fillStyle = "#000000"; + } + context.lineWidth = 2; + context.moveTo(10, 15); + context.lineTo(10, 125); + context.stroke(); + //绘制菱形 + context.lineWidth = 1; + context.beginPath() + context.moveTo(10, 30); + context.lineTo(4, 40); + context.lineTo(10, 50); + context.lineTo(16, 40); + context.lineTo(10, 30); + context.closePath() + context.fill() + context.font = 12 + "px sans-serif"; + //绘制wake up 文字 + let strList = [] + strList.push("wakeup @ " + getTimeString(wakeupBean?.wakeupTime || 0) + " on CPU " + wakeupBean?.cpu + " by") + strList.push("P:" + wakeupBean?.process + " [ " + wakeupBean?.pid + " ]") + strList.push("F:" + wakeupBean?.thread + " [ " + wakeupBean?.tid + " ]") + strList.forEach((str, index) => { + if (context != null) { + context.fillText(str, 40, 40 + 16 * index) + } + }) + //绘制左右箭头 + context.lineWidth = 2; + context.lineJoin = "bevel" + context.moveTo(10, 95) + context.lineTo(20, 90) + context.moveTo(10, 95) + context.lineTo(20, 100) + context.moveTo(10, 95) + context.lineTo(80, 95) + context.lineTo(70, 90) + context.moveTo(80, 95) + context.lineTo(70, 100) + context.stroke(); + //绘制latency + context.font = 12 + "px sans-serif"; + context.fillText("Scheduling latency:" + getTimeString(wakeupBean?.schedulingLatency || 0) + , 90, 100) + //绘制最下方提示语句 + context.font = 10 + "px sans-serif"; + INPUT_WORD.split("\n").forEach((str, index) => { + context?.fillText(str, 90, 120 + 12 * index) + }) + + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#selectionTbl'); + this.tbl?.addEventListener("column-click", (ev: any) => { + }) + this.addTableObserver() + } + + addTableObserver() { + let MutationObserver = window.MutationObserver + this.tableObserver = new MutationObserver((list) => { + if (this.tbl) { + let width = getComputedStyle(this.tbl).getPropertyValue("width") + let height = getComputedStyle(this.tbl).getPropertyValue("height") + } + }) + let selector = this.shadowRoot?.querySelector(".left-table"); + this.tableObserver?.observe(selector!, {attributes: true, attributeFilter: ['style'], attributeOldValue: true}) + } + + initHtml(): string { + return ` + +
+
+

+

Scheduling Latency

+
+
+
+ + + + + + + + +
+
+ +
+
+
+ `; + } + +} diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneFilter.ts b/host/ide/src/trace/component/trace/sheet/TabPaneFilter.ts new file mode 100644 index 0000000000000000000000000000000000000000..4ce88d324c97cdd4f4759eb2f36505c50010bb9f --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneFilter.ts @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import "../../../../base-ui/select/LitSelect.js"; +import "../../../../base-ui/select/LitSelectOption.js"; +import '../../../../base-ui/icon/LitIcon.js' +import {LitIcon} from "../../../../base-ui/icon/LitIcon.js"; + +export interface FilterData{ + inputValue:string, + firstSelect:string|null|undefined, + secondSelect:string|null|undefined, + mark:boolean|null|undefined, + icon:string|null, +} + +@element('tab-pane-filter') +export class TabPaneFilter extends BaseElement { + private filterInputEL: HTMLInputElement | null | undefined; + private firstSelectEL: HTMLSelectElement | null | undefined; + private secondSelectEL: HTMLSelectElement | null | undefined; + private markButtonEL: HTMLButtonElement | null | undefined; + private iconEL: LitIcon | null | undefined; + private getFilter: ((e:FilterData)=>void) | undefined; + + initElements(): void { + // this.firstSelectEL = this.shadowRoot?.querySelector("#first-select") + // this.secondSelectEL = this.shadowRoot?.querySelector("#second-select") + this.filterInputEL = this.shadowRoot?.querySelector("#filter-input") + this.markButtonEL = this.shadowRoot?.querySelector("#mark") + this.iconEL = this.shadowRoot?.querySelector("#icon") + + this.iconEL!.onclick=(e)=>{ + if (this.iconEL!.name == "statistics") { + this.iconEL!.name = "menu"; + this.iconEL!.size = 18; + if (this.getFilter) { + this.getFilter({ + inputValue:this.filterInputEL!.value, + firstSelect:this.firstSelectEL?.value, + secondSelect:this.secondSelectEL?.value, + mark:false, + icon:this.icon + }) + } + }else if (this.iconEL!.name == "menu") { + this.iconEL!.name = "statistics"; + this.iconEL!.size = 16; + if (this.getFilter) { + this.getFilter({ + inputValue:this.filterInputEL!.value, + firstSelect:this.firstSelectEL?.value, + secondSelect:this.secondSelectEL?.value, + mark:false, + icon:this.icon + }) + } + } + } + + this.markButtonEL!.onclick=(e)=>{ + if (this.getFilter) { + this.getFilter({ + inputValue:this.filterInputEL!.value, + firstSelect:this.firstSelectEL?.value, + secondSelect:this.secondSelectEL?.value, + mark:true, + icon:this.icon + }) + } + } + + this.filterInputEL?.addEventListener("keydown", (event:any) => { + if (event.keyCode == 13) { + this.iconEL!.name="menu" + if (this.getFilter) { + this.getFilter({ + inputValue:event.target.value, + firstSelect:this.firstSelectEL?.value, + secondSelect:this.secondSelectEL?.value, + mark:false, + icon:this.icon + }) + } + } + }); + + // this.firstSelectEL!.onchange = (e)=>{ + // if (this.getFilter) { + // this.getFilter({ + // inputValue:this.filterInputEL!.value, + // firstSelect:this.firstSelectEL?.value, + // secondSelect:this.secondSelectEL?.value, + // mark:false + // }) + // } + // } + // this.secondSelectEL!.onchange = (e)=>{ + // if (this.getFilter) { + // this.getFilter({ + // inputValue:this.filterInputEL!.value, + // firstSelect:this.firstSelectEL?.value, + // secondSelect:this.secondSelectEL?.value, + // mark:false + // }) + // } + // } + this.setSelectList() + } + + set firstSelect(value:string){ + this.firstSelectEL!.value = value; + } + + get firstSelect(){ + return this.firstSelectEL?.value||"" + } + + set secondSelect(value:string){ + this.secondSelectEL!.value = value; + } + + get secondSelect(){ + return this.secondSelectEL?.value||"" + } + + set filterValue(value:string){ + this.filterInputEL!.value = value; + } + get filterValue(){ + return this.filterInputEL!.value + } + + get inputPlaceholder(){ + return this.getAttribute("inputPlaceholder") || "Detail Filter"; + } + + get icon(){ + if (this.getAttribute("icon") != "false") { + if (this.iconEL!.name == "statistics") { + return "tree" + }else if (this.iconEL!.name == "menu") { + return "block" + }else { + return "" + } + } else { + return ""; + } + } + + set icon(value:string){ + if (value == "block") { + this.iconEL!.name = "menu"; + this.iconEL!.size = 18; + }else if (value == "tree") { + this.iconEL!.name = "statistics"; + this.iconEL!.size = 16; + } + } + + + getFilterData(getFilter:(v:FilterData)=>void){ + this.getFilter = getFilter + } + + setSelectList(firstList :Array|null|undefined = [ "All Allocations" ,"Created & Existing" ,"Created & Destroyed" ], + secondList :Array|null|undefined = ["All Heap & Anonymous VM", "All Heap", "All Anonymous VM"]){ + if (!firstList && !secondList) return; + let sLE = this.shadowRoot?.querySelector("#load") + let html = ``; + if (firstList) { + html += ` + Allocation Lifespan` + firstList!.forEach((a,b)=>{ + html+=`${a}` + }) + html+=`` + } + if (secondList) { + html+=` + Allocation Type` + secondList!.forEach((a,b)=>{ + html+=`${a}` + }) + html+=`` + } + if (!firstList) { + this.secondSelectEL!.outerHTML = html; + } else if (!secondList) { + this.firstSelectEL!.outerHTML = html; + }else { + sLE!.innerHTML=html; + } + + this.firstSelectEL = this.shadowRoot?.querySelector("#first-select") + this.secondSelectEL = this.shadowRoot?.querySelector("#second-select") + + this.firstSelectEL!.onchange = (e)=>{ + if (this.getFilter) { + this.getFilter({ + inputValue:this.filterInputEL!.value, + firstSelect:this.firstSelectEL?.value, + secondSelect:this.secondSelectEL?.value, + mark:false, + icon:this.icon + }) + } + } + this.secondSelectEL!.onchange = (e)=>{ + if (this.getFilter) { + this.getFilter({ + inputValue:this.filterInputEL!.value, + firstSelect:this.firstSelectEL?.value, + secondSelect:this.secondSelectEL?.value, + mark:false, + icon:this.icon + }) + } + } + + } + + initHtml(): string { + return ` + + +Input Filter + + +
+ +
+ + + + + + + + + + + + + Call Tree + Call Tree Constraints + Data Mining + `; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneFps.ts b/host/ide/src/trace/component/trace/sheet/TabPaneFps.ts new file mode 100644 index 0000000000000000000000000000000000000000..c98bab228108ded48609e6dc37e0f80771b2db85 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneFps.ts @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../bean/BoxSelection.js"; +import {getTabFps} from "../../../database/SqlLite.js"; +import {Utils} from "../base/Utils.js"; + +@element('tabpane-fps') +export class TabPaneFps extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + + set data(val: SelectionParam | any) { + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" + getTabFps(val.leftNs, val.rightNs).then((result) => { + if (result != null && result.length > 0) { + let index = result.findIndex((d) => d.startNS >= val.leftNs); + if (index != -1) { + let arr = result.splice(index > 0 ? index - 1 : index) + arr.map(e => e.timeStr = Utils.getTimeString(e.startNS)) + this.tbl!.dataSource = arr + } else { + let last = result[result.length - 1] + last.timeStr = Utils.getTimeString(last.startNS) + this.tbl!.dataSource = [last] + } + } else { + this.tbl!.dataSource = [] + } + }); + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-fps'); + this.range = this.shadowRoot?.querySelector('#time-range') + } + + initHtml(): string { + return ` + + + + + + + `; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneHeap.ts b/host/ide/src/trace/component/trace/sheet/TabPaneHeap.ts new file mode 100644 index 0000000000000000000000000000000000000000..ae9da25baf3b17b0b9aec65a3cff110ecd1dd59f --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneHeap.ts @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import "../../../../base-ui/table/lit-table-column.js"; +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../bean/BoxSelection.js"; +import {queryHeapAllData, queryHeapAllTable, queryHeapTable, queryHeapTreeTable} from "../../../database/SqlLite.js"; +import {Utils} from "../base/Utils.js"; +import {HeapBean} from "../../../bean/HeapBean.js"; +import {HeapTreeDataBean} from "../../../bean/HeapTreeDataBean.js"; +import {SpSystemTrace} from "../../SpSystemTrace.js"; + +@element('tabpane-heap') +export class TabPaneHeap extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-heap'); + this.range = this.shadowRoot?.querySelector('#time-range') + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20)+"px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + + + + set data(val: SelectionParam|any) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20)+"px" + queryHeapAllData(val.leftNs,val.rightNs,val.heapIds).then((allHeap)=>{ + if(allHeap.length>0){ + let groups:any = {}; + let treeGroup:any = {} + let treeData:HeapBean[] = [] + allHeap.forEach((heapData)=>{ + groups[heapData.eventId] = heapData + }) + SpSystemTrace.HEAP_FRAME_DATA.map((frame)=>{ + if(groups[frame.eventId]){ + treeGroup[frame.eventId] = treeGroup[frame.eventId]||[] + frame.heapSize = groups[frame.eventId].heapSize + frame.startTs = groups[frame.eventId].startTs + frame.endTs = groups[frame.eventId].endTs + frame.eventType = groups[frame.eventId].eventType + treeGroup[frame.eventId].push(frame) + } + }) + Object.keys(treeGroup).forEach((key)=>{ + if (treeGroup[key].length > 0) { + if(treeData.length>0){ + this.merageTree(0,treeData,treeGroup[key],val) + }else { + let currentData = new HeapBean() + let firstData = treeGroup[key][0] + currentData.AllocationFunction = firstData.AllocationFunction + currentData.depth = firstData.depth + currentData.MoudleName = firstData.MoudleName + treeData.push(currentData) + this.merageTree(0,treeData,treeGroup[key],val) + } + } + }) + this.setTreeDataSize(treeData) + this.tbl!.recycleDataSource = treeData + }else { + this.tbl!.recycleDataSource = [] + } + + }) + } + + setTreeDataSize(list:HeapBean[]){ + list.forEach((item)=>{ + item.AllocationSize = Utils.getByteWithUnit(Number(item.AllocationSize)) + item.DeAllocationSize = Utils.getByteWithUnit(Number(item.DeAllocationSize)) + item.RemainingSize = Utils.getByteWithUnit(Number(item.RemainingSize)) + if(item.children.length>0){ + this.setTreeDataSize(item.children) + } + }) + } + + merageTree(depth: number,beanList:HeapBean[],list:HeapTreeDataBean[],selection: SelectionParam|any){ + if(beanList.length>0){ + if(depth < list.length){ + let treeData = list[depth] + let currentData = beanList.find((item)=>{ + return treeData.MoudleName == item.MoudleName && treeData.AllocationFunction == item.AllocationFunction + }) + if(currentData!=undefined){ + (currentData.Allocations as number) += selection.leftNstreeData.endTs?1:0; + (currentData.AllocationSize as number) += selection.leftNstreeData.endTs?treeData.heapSize:0; + ( currentData.Total as number) = (currentData.Allocations as number) - (currentData.Deallocations as number); + currentData.RemainingSize = (currentData.AllocationSize as number) - (currentData.DeAllocationSize as number) + }else { + currentData = new HeapBean() + currentData.AllocationFunction = treeData.AllocationFunction + currentData.depth = treeData.depth + currentData.MoudleName = (treeData.MoudleName as string); + (currentData.Allocations as number) += selection.leftNstreeData.endTs?1:0; + (currentData.AllocationSize as number) += selection.leftNstreeData.endTs?treeData.heapSize:0; + currentData.Total = (currentData.Allocations as number) - (currentData.Deallocations as number); + currentData.RemainingSize = (currentData.AllocationSize as number) - (currentData.DeAllocationSize as number); + beanList.push(currentData) + } + if(depth+1 +:host{ + display: flex; + flex-direction: column; + padding: 10px 10px; +} + + + + + + + + + + + + + + + + + + + + + `; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneNMCallInfo.ts b/host/ide/src/trace/component/trace/sheet/TabPaneNMCallInfo.ts new file mode 100644 index 0000000000000000000000000000000000000000..0ad18bf9d6c346e1443979afa0bc1de4b0a1340d --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneNMCallInfo.ts @@ -0,0 +1,344 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../bean/BoxSelection.js"; +import {queryNativeHookEventTid} from "../../../database/SqlLite.js"; +import {NativeHookCallInfo, NativeHookStatistics} from "../../../bean/NativeHook.js"; +import {SpSystemTrace} from "../../SpSystemTrace.js"; +import {Utils} from "../base/Utils.js"; +import "./TabPaneFilter.js" +import {FilterData, TabPaneFilter} from "./TabPaneFilter"; + +@element('tabpane-native-callinfo') +export class TabPaneNMCallInfo extends BaseElement { + private tbl: LitTable | null | undefined; + private tblData: LitTable | null | undefined; + private source: Array = [] + private queryResult: Array = [] + private native_type:Array = ["All Heap & Anonymous VM","All Heap","All Anonymous VM"]; + private filterAllocationType:string = "0" + private filterNativeType:string = "0" + private currentSelection:SelectionParam|undefined + set data(val: SelectionParam | any) { + if(val!=this.currentSelection){ + this.currentSelection = val + this.initFilterTypes() + } + let types:Array = [] + if(val.nativeMemory.indexOf(this.native_type[0]) != -1){ + types.push("'AllocEvent'"); + types.push("'MmapEvent'"); + }else{ + if(val.nativeMemory.indexOf(this.native_type[1]) != -1){ + types.push("'AllocEvent'"); + } + if(val.nativeMemory.indexOf(this.native_type[2]) != -1){ + types.push("'MmapEvent'"); + } + } + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) + "px" + // @ts-ignore + this.tblData?.recycleDataSource = []; + // @ts-ignore + this.tbl?.recycleDataSource = []; + queryNativeHookEventTid(val.leftNs,val.rightNs,types).then((result)=>{ + if(result.length > 0){ + this.queryResult = result + this.source = this.handleQueryResult(result); + }else{ + this.source = []; + } + this.filterQueryData() + }) + } + + handleQueryResult(result:Array):Array{ + let resultMap = new Map(); + result.map((r)=>{ + resultMap.set(r.eventId,r); + }) + let map = new Map(); + SpSystemTrace.HEAP_FRAME_DATA.map((frame) => { + let frameEventId = parseInt(frame.eventId); + if(frameEventId >= result[0].eventId && frameEventId <= result[result.length - 1].eventId){ + if(resultMap.has(frameEventId)){ + let hook = resultMap.get(frameEventId); + if(hook != undefined){ + let target = new NativeHookCallInfo(); + target.id = frame.eventId + "_" + frame.depth; + target.eventId = frameEventId; + target.depth = frame.depth; + target.count = 1; + target.heapSize = hook.heapSize; + target.threadId = hook.tid; + target.heapSizeStr = Utils.getByteWithUnit(target.heapSize); + let sym_arr = frame.AllocationFunction?.split("/"); + let lib_arr = frame.MoudleName?.split("/"); + target.symbol = sym_arr![sym_arr!.length - 1]; + target.library = lib_arr![lib_arr!.length - 1]; + target.title = `[ ${target.symbol} ] ${target.library}`; + target.type = (target.library.endsWith(".so.1") || target.library.endsWith(".dll") || target.library.endsWith(".so")) ? 0 : 1; + if(map.has(frame.eventId)){ + let src = map.get(frame.eventId); + this.listToTree(target,src!); + }else{ + map.set(frame.eventId,target); + } + } + } + } + if(frameEventId > result[result.length -1].eventId){ + return false; + } + }); + let groupMap = new Map>(); + for (let value of map.values()) { + let key = value.threadId+ "_" + value.symbol; + if(groupMap.has(key)){ + groupMap.get(key)!.push(value); + }else{ + let arr:Array = []; + arr.push(value); + groupMap.set(key,arr); + } + } + let data:Array = []; + for (let arr of groupMap.values()) { + if(arr.length > 1){ + for (let i = 1; i < arr.length; i++) { + if(arr[i].children.length > 0){ + this.mergeTree(arr[i].children[0],arr[0]); + }else{ + arr[0].heapSize += arr[i].heapSize; + arr[0].heapSizeStr = Utils.getByteWithUnit(arr[0].heapSize); + } + } + } + arr[0].count = arr.length; + data.push(arr[0]); + } + return this.groupByWithTid(data) + } + + groupByWithTid(data:Array):Array{ + let tidMap = new Map(); + for (let call of data) { + call.pid = "tid_"+call.threadId; + if(tidMap.has(call.threadId)){ + let tidCall = tidMap.get(call.threadId); + tidCall!.heapSize += call.heapSize; + tidCall!.heapSizeStr = Utils.getByteWithUnit(tidCall!.heapSize); + tidCall!.count += call.count; + tidCall!.children.push(call); + }else{ + let tidCall = new NativeHookCallInfo(); + tidCall.id = "tid_" + call.threadId; + tidCall.count = call.count; + tidCall.heapSize = call.heapSize; + tidCall.heapSizeStr = Utils.getByteWithUnit(call.heapSize); + tidCall.title = "Thread " + call.threadId; + tidCall.type = -1; + tidCall.children.push(call); + tidMap.set(call.threadId,tidCall); + } + } + return Array.from(tidMap.values()); + } + + listToTree(target:NativeHookCallInfo,src:NativeHookCallInfo){ + if(target.depth == src.depth + 1){ + target.pid = src.id; + src.children.push(target) + }else{ + if(src.children.length > 0){ + this.listToTree(target,src.children[0]); + } + } + } + + mergeTree(target:NativeHookCallInfo,src:NativeHookCallInfo){ + let len = src.children.length; + if(len == 0){ + target.pid = src.id; + src.heapSize += target.heapSize; + src.heapSizeStr = Utils.getByteWithUnit(src.heapSize); + src.children.push(target); + }else{ + let index = src.children.findIndex((hook) => hook.symbol == target.symbol && hook.depth == target.depth); + src.heapSize += target.heapSize; + src.heapSizeStr = Utils.getByteWithUnit(src.heapSize); + if(index != -1){ + let srcChild = src.children[index]; + srcChild.count += 1; + if(target.children.length > 0){ + this.mergeTree(target.children[0],srcChild) + }else{ + srcChild.heapSize += target.heapSize; + srcChild.heapSizeStr = Utils.getByteWithUnit(srcChild.heapSize) + } + }else{ + target.pid = src.id; + src.children.push(target) + } + } + } + + setRightTableData(hook:NativeHookCallInfo){ + let arr:Array = []; + let maxEventId = hook.eventId; + let maxHeap = 0; + function findMaxStack(hook:NativeHookCallInfo){ + if(hook.children.length == 0){ + if(hook.heapSize > maxHeap){ + maxHeap = hook.heapSize; + maxEventId = hook.eventId; + } + }else{ + hook.children.map((hookChild)=>{ + findMaxStack(hookChild); + }) + } + } + findMaxStack(hook); + SpSystemTrace.HEAP_FRAME_DATA.map((frame) => { + let eventId = parseInt(frame.eventId); + if(eventId == maxEventId){ + let target = new NativeHookCallInfo(); + target.eventId = eventId; + target.depth = frame.depth; + let sym_arr = frame.AllocationFunction?.split("/"); + let lib_arr = frame.MoudleName?.split("/"); + target.symbol = sym_arr![sym_arr!.length - 1]; + target.library = lib_arr![lib_arr!.length - 1]; + target.title = `[ ${target.symbol} ] ${target.library}`; + target.type = (target.library.endsWith(".so.1") || target.library.endsWith(".dll") || target.library.endsWith(".so")) ? 0 : 1; + arr.push(target); + } + if(eventId > maxEventId){ + return false; + } + }); + // @ts-ignore + this.tblData?.recycleDataSource = arr; + } + + initFilterTypes(){ + let filter = this.shadowRoot?.querySelector("#filter") + this.queryResult = [] + filter!.firstSelect = "0" + filter!.secondSelect = "0" + this.filterAllocationType = "0" + this.filterNativeType = "0" + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-native-callinfo'); + this.tblData = this.shadowRoot?.querySelector('#tb-native-data'); + this.tbl!.addEventListener("row-click", (e) => { + // @ts-ignore + let data = (e.detail as NativeHookCallInfo) + this.setRightTableData(data); + }) + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight)-10-31+"px"; + this.tbl?.reMeauseHeight() + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight) -10+"px" + this.tblData?.reMeauseHeight() + } + }).observe(this.parentElement!); + this.shadowRoot?.querySelector("#filter")!.getFilterData((data:FilterData)=>{ + this.filterAllocationType = data.firstSelect||"0" + this.filterNativeType = data.secondSelect||"0" + this.filterQueryData() + }) + this.initFilterTypes() + } + + filterQueryData(){ + if (this.queryResult.length > 0&&this.currentSelection) { + let filter = this.queryResult.filter((item)=>{ + let filterAllocation = true + let filterNative = true + if(this.filterAllocationType=="1"){ + filterAllocation = item.startTs>=this.currentSelection!.leftNs&&item.startTs<=this.currentSelection!.rightNs&&item.endTs>this.currentSelection!.rightNs + }else if(this.filterAllocationType=="2"){ + filterAllocation = item.startTs>=this.currentSelection!.leftNs&&item.startTs<=this.currentSelection!.rightNs&&item.endTs<=this.currentSelection!.rightNs + } + if(this.filterNativeType=="1"){ + filterNative = item.eventType == "AllocEvent" + }else if(this.filterNativeType=="2"){ + filterNative = item.eventType == "MmapEvent" + } + return filterAllocation&&filterNative + }) + if(filter.length>0){ + this.source = this.handleQueryResult(filter); + this.tbl!.recycleDataSource = this.source; + }else { + this.source = [] + this.tbl!.recycleDataSource = []; + } + } + } + + initHtml(): string { + return ` + +
+
+ + + + + + + + + +
+
+ + + + + + +
+
+ + `; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneNMSampleList.ts b/host/ide/src/trace/component/trace/sheet/TabPaneNMSampleList.ts new file mode 100644 index 0000000000000000000000000000000000000000..df7e7eb1fddf4b477df473ed2b30cf8f1a00fd88 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneNMSampleList.ts @@ -0,0 +1,456 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import "../../../../base-ui/table/lit-table-column.js"; +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {Counter, SelectionData, SelectionParam} from "../../../bean/BoxSelection.js"; +import { + getTabCounters, queryAllHookData, + queryNativeHookEventId, + queryNativeHookSnapshot, + queryNativeHookSnapshotTypes +} from "../../../database/SqlLite.js"; +import {SpSystemTrace} from "../../SpSystemTrace.js"; +import { + NativeHookCallInfo, + NativeHookSampleQueryInfo, + NativeHookSamplerInfo, + NativeMemory +} from "../../../bean/NativeHook.js"; +import {Utils} from "../base/Utils.js"; +import "./TabPaneFilter.js" +import {FilterData, TabPaneFilter} from "./TabPaneFilter.js"; + +@element('tabpane-native-sample') +export class TabPaneNMSampleList extends BaseElement { + static tblData: LitTable | null | undefined; + static tbl: LitTable | null | undefined; + static filter: any + static filterSelect: string = "0" + static source: Array = []; + static groups:any = undefined; + static types:Array = [] + static native_type:Array = ["All Heap & Anonymous VM","All Heap","All Anonymous VM"]; + static tableMarkData: Array = [] + static selectionParam:SelectionParam|undefined = undefined + static sampleTypes:Array = [] + static sampleTypesList:any[] = [] + set data(val: SelectionParam | any) { + TabPaneNMSampleList.serSelection(val) + this.filterAllList() + } + + static serSelection(val: SelectionParam){ + if(this.selectionParam !== val){ + this.clearData() + this.selectionParam = val + this.initTypes() + } + if(val.nativeMemory.indexOf(this.native_type[0]) != -1){ + this.types.push("'AllocEvent'"); + this.types.push("'MmapEvent'"); + }else{ + if(val.nativeMemory.indexOf(this.native_type[1]) != -1){ + this.types.push("'AllocEvent'"); + } + if(val.nativeMemory.indexOf(this.native_type[2]) != -1){ + this.types.push("'MmapEvent'"); + } + } + } + + static initTypes(){ + queryNativeHookSnapshotTypes().then((result)=>{ + if(result.length>0){ + this.sampleTypes = result + } + }) + } + + + static addSampleData(data:any){ + if(TabPaneNMSampleList.tableMarkData.indexOf(data)!=-1){ + return + } + TabPaneNMSampleList.tableMarkData.push(data) + this.initGroups() + let rootSample = new NativeHookSamplerInfo() + rootSample.snapshot = "Snapshot"+this.numberToWord(this.source.length+1) + rootSample.startTs = data.startTs + rootSample.timestamp = Utils.getTimeString(data.startTs) + rootSample.eventId = data.eventId + this.queryAllHookInfo(data,rootSample) + } + + static querySnapshot(data:any,rootSample:NativeHookSamplerInfo){ + let copyTypes = this.sampleTypes.map((type)=>{ + let copyType = new NativeHookSampleQueryInfo() + copyType.eventType = type.eventType + copyType.subType = type.subType + return copyType + }) + queryNativeHookSnapshot(data.startTs).then((result)=>{ + if(result.length>0){ + let nameGroup:any = {} + copyTypes.forEach((item)=> { + nameGroup[item.eventType] = nameGroup[item.eventType] || [] + nameGroup[item.eventType].push(item) + }) + result.forEach((item)=>{ + if(nameGroup[item.eventType]!=undefined){ + if(item.subType == null){ + nameGroup[item.eventType][0].existing = item.existing + nameGroup[item.eventType][0].growth = item.growth + }else{ + let filter = nameGroup[item.eventType].filter((type:any)=>{ + return type.subType == item.subType + }) + if (filter.length > 0) { + filter[0].existing = item.existing + filter[0].growth = item.growth + } + } + } + }) + if(this.sampleTypesList.length>0){ + let sampleTypesListElement = this.sampleTypesList[this.sampleTypesList.length-1]; + sampleTypesListElement.forEach((item:any,index:number)=>{ + copyTypes[index].current = copyTypes[index].growth + if(index{ + item.current = item.growth + }) + } + this.sampleTypesList.push(copyTypes) + this.createTree(nameGroup,rootSample) + rootSample.tempList = [...rootSample.children] + this.source.push(rootSample) + } + }) + } + + static merageSampleData(leftTime:number,startNs:number,rootSample:NativeHookSampleQueryInfo,merageSample:NativeHookSampleQueryInfo){ + if(merageSample.endTs >= startNs){ + rootSample.growth += merageSample.growth + } + if(merageSample.startTs > leftTime){ + rootSample.existing++; + let childSample = new NativeHookSamplerInfo()//新增最下层的叶子节点 + childSample.snapshot = "0x"+merageSample.addr + childSample.eventId = merageSample.eventId; + childSample.heapSize = merageSample.growth + childSample.growth = Utils.getByteWithUnit(merageSample.growth) + childSample.totalGrowth = childSample.growth + childSample.startTs = merageSample.startTs + childSample.timestamp = Utils.getTimeString(merageSample.startTs); + (childSample as any).existing = "" + rootSample.children.push(childSample) + } + rootSample.total += merageSample.growth + } + + static queryAllHookInfo(data:any,rootSample:NativeHookSamplerInfo){ + let copyTypes = this.sampleTypes.map((type)=>{ + let copyType = new NativeHookSampleQueryInfo() + copyType.eventType = type.eventType + copyType.subType = type.subType + return copyType + }) + queryAllHookData(data.startTs).then((result)=>{ + if(result.length > 0){ + let nameGroup:any = {} + copyTypes.forEach((item)=> { + nameGroup[item.eventType] = nameGroup[item.eventType] || [] + nameGroup[item.eventType].push(item) + }) + let leftTime = TabPaneNMSampleList.tableMarkData.length == 1?0:TabPaneNMSampleList.tableMarkData[TabPaneNMSampleList.tableMarkData.length - 2].startTs + result.forEach((item)=>{ + if(nameGroup[item.eventType]!=undefined){ + if(item.subType == null){ + this.merageSampleData(leftTime,data.startTs,nameGroup[item.eventType][0],item) + }else{ + let filter = nameGroup[item.eventType].filter((type:any)=>{ + return type.subType == item.subType + }) + if (filter.length > 0) { + this.merageSampleData(leftTime,data.startTs,filter[0],item) + } + } + } + }) + if(this.sampleTypesList.length>0){ + let sampleTypesListElement = this.sampleTypesList[this.sampleTypesList.length-1]; + sampleTypesListElement.forEach((item:any,index:number)=>{ + copyTypes[index].current = copyTypes[index].growth + if(index{ + item.current = item.growth + }) + } + this.sampleTypesList.push(copyTypes) + this.createTree(nameGroup,rootSample) + rootSample.tempList = [...rootSample.children] + this.source.push(rootSample) + } + }) + } + + static initGroups(){ + if(this.groups==undefined){ + this.groups = {} + SpSystemTrace.HEAP_FRAME_DATA.map((frame)=>{ + this.groups[frame.eventId] = this.groups[frame.eventId]||[] + this.groups[frame.eventId].push(frame) + }) + } + } + + static createTree(nameGroup:any,rootSample:NativeHookSamplerInfo){ + Object.keys(nameGroup).forEach((key)=>{ + let parentSample = new NativeHookSamplerInfo() + parentSample.snapshot = key + if (nameGroup[key].length > 0) { + nameGroup[key].forEach((child:any)=>{ + let childSample = new NativeHookSamplerInfo() + childSample.snapshot = child.subType||child.eventType + childSample.heapSize = child.growth + childSample.growth = Utils.getByteWithUnit(child.growth) + childSample.total = child.total + childSample.totalGrowth = Utils.getByteWithUnit(child.total) + childSample.existing = child.existing + childSample.currentSize = child.current + childSample.current = Utils.getByteWithUnit(child.current) + parentSample.merageObj(childSample) + if(childSample.snapshot != parentSample.snapshot){//根据名称是否一致来判断是否需要添加子节点 + childSample.children.push(...child.children) + parentSample.children.push(childSample) + }else { + parentSample.children.push(...child.children) + } + }) + } + rootSample.merageObj(parentSample) + rootSample.children.push(parentSample) + }) + } + + static prepChild(currentSample:NativeHookSamplerInfo,rootSample:NativeHookSamplerInfo){ + currentSample.heapSize -= rootSample.heapSize + currentSample.growth = Utils.getByteWithUnit(currentSample.heapSize) + let currentMap:any = {} + currentSample.children.forEach((currentChild)=>{ + currentMap[currentChild.snapshot] = currentChild + }) + rootSample.children.forEach((rootChild)=>{ + if (currentMap[rootChild.snapshot] == undefined) { + let perpSample = new NativeHookSamplerInfo() + perpSample.snapshot =rootChild.snapshot + currentMap[rootChild.snapshot] = perpSample + currentSample.children.push(perpSample) + } + this.prepChild(currentMap[rootChild.snapshot],rootChild) + }) + } + + static clearData(){ + this.types = [] + this.source = [] + this.tblData!.dataSource = [] + this.tbl!.recycleDataSource = [] + this.sampleTypesList = [] + this.tableMarkData = [] + TabPaneNMSampleList.filter!.firstSelect = "0" + } + + static numberToWord(num:number){ + let word = "" + while (num>0){ + let end = num%26 + end = end === 0?(end = 26):end; + word = String.fromCharCode(96 + end)+word + num = ( num - end ) / 26 + } + return word.toUpperCase() + } + + setRightTableData(eventId:number){ + let arr:Array = []; + let frameArr = TabPaneNMSampleList.groups[eventId]; + if(frameArr){ + frameArr.map((frame:any)=>{ + let target = new NativeHookCallInfo(); + target.eventId = parseInt(frame.eventId); + target.depth = frame.depth; + let sym_arr = frame.AllocationFunction?.split("/"); + let lib_arr = frame.MoudleName?.split("/"); + target.symbol = sym_arr![sym_arr!.length - 1]; + target.library = lib_arr![lib_arr!.length - 1]; + target.title = `[ ${target.symbol} ] ${target.library}`; + target.type = (target.library.endsWith(".so.1") || target.library.endsWith(".dll") || target.library.endsWith(".so")) ? 0 : 1; + arr.push(target); + }) + } + // @ts-ignore + TabPaneNMSampleList.tblData?.recycleDataSource = arr; + } + + initElements(): void { + TabPaneNMSampleList.tbl = this.shadowRoot?.querySelector('#tb-native-sample'); + TabPaneNMSampleList.tbl!.addEventListener('row-click', (evt:any) => { + // @ts-ignore + this.setRightTableData(evt.detail.eventId); + }) + TabPaneNMSampleList.tblData = this.shadowRoot?.querySelector('#tb-native-data'); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + TabPaneNMSampleList.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 10 - 31)+"px" + TabPaneNMSampleList.tbl?.reMeauseHeight() + // @ts-ignore + TabPaneNMSampleList.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 10)+"px" + TabPaneNMSampleList.tblData?.reMeauseHeight() + } + }).observe(this.parentElement!) + TabPaneNMSampleList.filter = this.shadowRoot?.querySelector("#filter") + this.shadowRoot?.querySelector("#filter")!.setSelectList(TabPaneNMSampleList.native_type,null) + this.shadowRoot?.querySelector("#filter")!.getFilterData((data:FilterData)=>{ + if(data.firstSelect){ + TabPaneNMSampleList.filterSelect = data.firstSelect + this.filterAllList() + } + }) + TabPaneNMSampleList.filter!.firstSelect = TabPaneNMSampleList.filterSelect + + } + + filterAllList(){ + TabPaneNMSampleList.source.forEach((rootSample)=>{ + rootSample.heapSize = 0 + rootSample.existing = 0 + rootSample.total = 0 + if(TabPaneNMSampleList.filterSelect == "0"){ + rootSample.children = [...rootSample.tempList] + rootSample.tempList.forEach((parentSample)=>{ + rootSample.heapSize +=parentSample.heapSize + rootSample.existing +=parentSample.existing + rootSample.total +=parentSample.total + }) + rootSample.growth = Utils.getByteWithUnit(rootSample.heapSize) + rootSample.totalGrowth =Utils.getByteWithUnit(rootSample.total) + }else if(TabPaneNMSampleList.filterSelect == "2"){ + if(rootSample.tempList.length>1){ + rootSample.children = [rootSample.tempList[1]] + rootSample.heapSize +=rootSample.tempList[1].heapSize + rootSample.existing +=rootSample.tempList[1].existing + rootSample.growth = Utils.getByteWithUnit(rootSample.heapSize) + rootSample.total += rootSample.tempList[1].total + rootSample.totalGrowth = Utils.getByteWithUnit(rootSample.total) + }else { + rootSample.children = [] + rootSample.growth = "" + rootSample.totalGrowth = "" + } + }else { + if(rootSample.tempList.length>0){ + rootSample.children = [rootSample.tempList[0]] + rootSample.heapSize +=rootSample.tempList[0].heapSize + rootSample.existing +=rootSample.tempList[0].existing + rootSample.growth = Utils.getByteWithUnit(rootSample.heapSize) + rootSample.total += rootSample.tempList[0].total + rootSample.totalGrowth = Utils.getByteWithUnit(rootSample.total) + }else { + rootSample.children = [] + rootSample.growth = "" + rootSample.totalGrowth = "" + } + } + }) + TabPaneNMSampleList.tbl!.recycleDataSource = TabPaneNMSampleList.source; + } + + initHtml(): string { + return ` + +
+
+ + + + + + + + +
+
+ + + + + + +
+
+ `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: SelectionData, b: SelectionData) { + if (a.process == " " || b.process == " ") { + return 0; + } + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } else { + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + } + + TabPaneNMSampleList.tbl!.recycleDataSource = TabPaneNMSampleList.source; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneNMStatstics.ts b/host/ide/src/trace/component/trace/sheet/TabPaneNMStatstics.ts new file mode 100644 index 0000000000000000000000000000000000000000..e022aaff55750b1ba630c1abf5646b0b58357e2f --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneNMStatstics.ts @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import { SelectionParam} from "../../../bean/BoxSelection.js"; +import { + queryNativeHookStatistics, + queryNativeHookStatisticsMalloc, + queryNativeHookStatisticsSubType +} from "../../../database/SqlLite.js"; +import { + NativeHookMalloc, + NativeHookStatistics, + NativeHookStatisticsTableData, + NativeMemory +} from "../../../bean/NativeHook.js"; +import {Utils} from "../base/Utils.js"; +import {SpSystemTrace} from "../../SpSystemTrace.js"; +import "./TabProgressBar.js" + +@element('tabpane-native-statistics') +export class TabPaneNMStatstics extends BaseElement { + private tbl: LitTable | null | undefined; + private source: Array = [] + private native_type:Array = ["All Heap & Anonymous VM","All Heap","All Anonymous VM"]; + private allMax:number = 0; + + set data(val: SelectionParam | any) { + this.allMax = 0; + SpSystemTrace.EVENT_HEAP.map((heap)=>{ + this.allMax += heap.sumHeapSize; + }); + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20) + "px" + // @ts-ignore + this.tbl?.recycleDataSource = []; + Promise.all([queryNativeHookStatistics(val.leftNs,val.rightNs), + queryNativeHookStatisticsSubType(val.leftNs,val.rightNs), + queryNativeHookStatisticsMalloc(val.leftNs,val.rightNs) + ]).then((values)=>{ + let arr:Array = []; + let index1 = val.nativeMemory.indexOf(this.native_type[0]) + let index2 = val.nativeMemory.indexOf(this.native_type[1]) + let index3 = val.nativeMemory.indexOf(this.native_type[2]) + this.setMemoryTypeData(val,values[0],arr); + if(index1 != -1 || index3 != -1){ + this.setSubTypeTableData(values[1],arr); + } + if(index1 != -1 || index2 != -1){ + this.setMallocTableData(values[2],arr); + } + this.tbl!.recycleDataSource = arr; + }) + } + + setMallocTableData(result:Array,arr:Array){ + result.map((malloc)=>{ + let data = new NativeHookStatisticsTableData(); + data.memoryTap = "Malloc " + Utils.getByteWithUnit(malloc.heapSize); + data.existing = malloc.allocByte; + data.allocCount = malloc.allocCount; + data.freeCount = malloc.freeCount; + data.totalBytes = malloc.allocByte + malloc.freeByte; + data.totalCount = malloc.allocCount + malloc.freeCount; + data.max = malloc.heapSize; + data.existingString = Utils.getByteWithUnit(data.existing); + data.totalBytesString = Utils.getByteWithUnit(data.totalBytes); + data.maxStr = Utils.getByteWithUnit(malloc.heapSize); + data.existingValue = [data.existing,data.totalBytes,this.allMax]; + arr.push(data); + }) + } + + setSubTypeTableData(result:Array,arr:Array){ + result.map((sub)=>{ + let data = new NativeHookStatisticsTableData(); + data.memoryTap = sub.subType + data.existing = sub.allocByte + data.allocCount = sub.allocCount; + data.freeCount = sub.freeCount; + data.totalBytes = sub.allocByte + sub.freeByte; + data.totalCount = sub.allocCount + sub.freeCount; + data.max = sub.heapSize; + data.existingString = Utils.getByteWithUnit(data.existing); + data.totalBytesString = Utils.getByteWithUnit(data.totalBytes); + data.maxStr = Utils.getByteWithUnit(sub.heapSize); + data.existingValue = [data.existing,data.totalBytes,this.allMax]; + arr.push(data); + }) + } + + setMemoryTypeData(val:SelectionParam,result:Array,arr:Array){ + let all:NativeHookStatisticsTableData | null = null + let heap:NativeHookStatisticsTableData | null = null + let anonymous:NativeHookStatisticsTableData | null = null + if(val.nativeMemory.indexOf(this.native_type[0]) != -1){ + all = new NativeHookStatisticsTableData(); + all.memoryTap = this.native_type[0]; + } + if(val.nativeMemory.indexOf(this.native_type[1]) != -1){ + heap = new NativeHookStatisticsTableData(); + heap.memoryTap = this.native_type[1]; + } + if(val.nativeMemory.indexOf(this.native_type[2]) != -1){ + anonymous = new NativeHookStatisticsTableData(); + anonymous.memoryTap = this.native_type[2]; + } + for (let hook of result) { + if(all != null){ + if(hook.eventType == "AllocEvent" || hook.eventType == "MmapEvent"){ + all.existing += hook.sumHeapSize; + all.allocCount += hook.count; + all.totalBytes += hook.sumHeapSize; + all.totalCount += hook.count; + if(hook.max > all.max){ + all.max = hook.max; + all.maxStr = Utils.getByteWithUnit(all.max); + } + }else if(hook.eventType == "FreeEvent" || hook.eventType == "MunmapEvent"){ + all.totalBytes += hook.sumHeapSize; + all.freeCount += hook.count; + all.totalCount += hook.count; + } + } + if(heap != null){ + if(hook.eventType == "AllocEvent" ){ + heap.existing += hook.sumHeapSize; + heap.allocCount += hook.count; + heap.totalBytes += hook.sumHeapSize; + heap.totalCount += hook.count; + if(hook.max > heap.max){ + heap.max = hook.max; + heap.maxStr = Utils.getByteWithUnit(heap.max); + } + }else if(hook.eventType == "FreeEvent"){ + heap.totalBytes += hook.sumHeapSize; + heap.totalCount += hook.count; + heap.freeCount += hook.count; + } + } + if(anonymous != null){ + if(hook.eventType == "MmapEvent" ){ + anonymous.existing += hook.sumHeapSize; + anonymous.allocCount += hook.count; + anonymous.totalBytes += hook.sumHeapSize; + anonymous.totalCount += hook.count; + if(hook.max > anonymous.max){ + anonymous.max = hook.max; + anonymous.maxStr = Utils.getByteWithUnit(anonymous.max); + } + }else if(hook.eventType == "MunmapEvent"){ + anonymous.totalBytes += hook.sumHeapSize; + anonymous.freeCount += hook.count; + anonymous.totalCount += hook.count; + } + } + } + if(all != null){ + all.existingString = Utils.getByteWithUnit(all.existing) + all.totalBytesString = Utils.getByteWithUnit(all.totalBytes) + all.existingValue = [all.existing,all.totalBytes,this.allMax] + arr.push(all) + } + if(heap != null){ + heap.existingString = Utils.getByteWithUnit(heap.existing) + heap.totalBytesString = Utils.getByteWithUnit(heap.totalBytes) + heap.existingValue = [heap.existing,heap.totalBytes,this.allMax] + arr.push(heap) + } + if(anonymous != null){ + anonymous.existingString = Utils.getByteWithUnit(anonymous.existing) + anonymous.totalBytesString = Utils.getByteWithUnit(anonymous.totalBytes) + anonymous.existingValue = [anonymous.existing,anonymous.totalBytes,this.allMax] + arr.push(anonymous) + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-native-statstics'); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20)+"px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + + + initHtml(): string { + return ` + + + + + + + + + + + + + + `; + } +} diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneNMemory.ts b/host/ide/src/trace/component/trace/sheet/TabPaneNMemory.ts new file mode 100644 index 0000000000000000000000000000000000000000..43fde1a8ed02f124de021d53177c3312b4c0266d --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneNMemory.ts @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../bean/BoxSelection.js"; +import {queryNativeHookEventId} from "../../../database/SqlLite.js"; +import {NativeHookCallInfo, NativeHookStatistics, NativeMemory} from "../../../bean/NativeHook.js"; +import {SpSystemTrace} from "../../SpSystemTrace.js"; +import {HeapTreeDataBean} from "../../../bean/HeapTreeDataBean.js"; +import {Utils} from "../base/Utils.js"; +import "./TabPaneFilter.js" +import {FilterData, TabPaneFilter} from "./TabPaneFilter"; +import {TabPaneNMSampleList} from "./TabPaneNMSampleList.js"; + +@element('tabpane-native-memory') +export class TabPaneNMemory extends BaseElement { + private defaultNativeTypes = ["All Heap & Anonymous VM","All Heap","All Anonymous VM"]; + private tbl: LitTable | null | undefined; + private tblData: LitTable | null | undefined; + private source: Array = [] + private native_type:Array = [...this.defaultNativeTypes]; + private statsticsSelection: Array = [] + private queryResult: Array = [] + private filterAllocationType:string = "0" + private filterNativeType:string = "0" + private currentSelection:SelectionParam|undefined + private rowSelectData:any = undefined; + set data(val: SelectionParam | any) { + if(val==this.currentSelection){ + return + } + this.currentSelection = val + this.initFilterTypes() + let types:Array = [] + if(val.nativeMemory.indexOf(this.defaultNativeTypes[0]) != -1){ + types.push("'AllocEvent'"); + types.push("'MmapEvent'"); + }else{ + if(val.nativeMemory.indexOf(this.defaultNativeTypes[1]) != -1){ + types.push("'AllocEvent'"); + } + if(val.nativeMemory.indexOf(this.defaultNativeTypes[2]) != -1){ + types.push("'MmapEvent'"); + } + } + TabPaneNMSampleList.serSelection(val) + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 20 - 31) + "px" + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight -20)+"px" + // @ts-ignore + this.tblData?.recycleDataSource = []; + // @ts-ignore + this.tbl?.recycleDataSource = []; + queryNativeHookEventId(val.leftNs,val.rightNs,types).then((result)=>{ + if(result.length > 0){ + this.queryResult = result + this.source = this.handleQueryResult(result); + }else{ + this.source = []; + } + this.filterQueryData() + }) + } + + fromStastics(val: SelectionParam | any){ + let filter = this.shadowRoot?.querySelector("#filter") + let typeIndexOf = this.native_type.indexOf(val.statisticsSelectData.memoryTap); + if(this.statsticsSelection.indexOf(val.statisticsSelectData) == -1&&typeIndexOf == -1){ + this.statsticsSelection.push(val.statisticsSelectData) + this.native_type.push(val.statisticsSelectData.memoryTap) + typeIndexOf = this.native_type.length - 1 + } + if(this.currentSelection != val){ + //设置选项后刷新当前的数据 + this.data = val + //todo 设置filter当前的选项和选中项 + filter!.setSelectList(null,this.native_type) + filter!.secondSelect = typeIndexOf+"" + this.filterNativeType = typeIndexOf+"" + }else{ + this.tblData!.recycleDataSource = []; + this.rowSelectData = undefined + filter!.setSelectList(null,this.native_type) + filter!.secondSelect = typeIndexOf+"" + this.filterNativeType = typeIndexOf+"" + //直接将当前数据过滤即可 + this.filterQueryData() + } + } + + getTypeFromIndex(indexOf:number,item:NativeHookStatistics):boolean{ + if(indexOf == -1){ + return false; + } + if(indexOf < 3){ + if(indexOf == 0){ + return true + }else if(indexOf == 1){ + return item.eventType == "AllocEvent" + }else if(indexOf == 2){ + return item.eventType == "MmapEvent" + } + }else if(indexOf-3 < this.statsticsSelection.length){ + let selectionElement = this.statsticsSelection[indexOf - 3]; + if(selectionElement.memoryTap!=undefined&&selectionElement.max!=undefined){ + if (selectionElement.memoryTap.indexOf("Malloc") != -1) { + return item.eventType == "AllocEvent"&&item.heapSize == selectionElement.max + }else { + return item.subType == selectionElement.memoryTap&&item.heapSize == selectionElement.max + } + } + } + return false; + } + + handleQueryResult(result:Array):Array{ + let resultMap = new Map(); + result.map((r)=>{ + resultMap.set(r.eventId,r); + }) + let data :Array = []; + let frameArr: Array = []; + SpSystemTrace.HEAP_FRAME_DATA.map((frame) => { + let frameEventId = parseInt(frame.eventId); + if(frameEventId >= result[0].eventId && frameEventId <= result[result.length - 1].eventId){ + if(resultMap.has(frameEventId) && frame.depth == 0){ + frameArr.push(frame); + } + } + if(frameEventId > result[result.length -1].eventId){ + return false; + } + }); + + let frameMap = new Map(); + frameArr.map((frame)=>{ + frameMap.set(parseInt(frame.eventId),frame); + }) + for (let i = 0,len = result.length; i < len; i++) { + let hook = result[i]; + let memory = new NativeMemory(); + memory.index = i; + memory.eventId = hook.eventId; + memory.eventType = hook.eventType; + memory.subType = hook.subType; + memory.heapSize = hook.heapSize; + memory.heapSizeUnit = Utils.getByteWithUnit(hook.heapSize); + memory.addr = "0x"+hook.addr; + memory.startTs = hook.startTs; + memory.timestamp = Utils.getTimeString(hook.startTs); + (memory as any).isSelected = hook.isSelected; + let frame = frameMap.get(hook.eventId); + if(frame != null && frame != undefined){ + let sym_arr = frame.AllocationFunction?.split("/"); + let lib_arr = frame.MoudleName?.split("/"); + memory.symbol = sym_arr![sym_arr!.length - 1]; + memory.library = lib_arr![lib_arr!.length - 1]; + } + data.push(memory); + } + return data + } + + initFilterTypes(){ + let filter = this.shadowRoot?.querySelector("#filter") + this.queryResult = [] + filter!.setSelectList(null,this.defaultNativeTypes) + filter!.firstSelect = "0" + filter!.secondSelect = "0" + this.filterAllocationType = "0" + this.filterNativeType = "0" + this.rowSelectData = undefined + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-native-memory'); + this.tblData = this.shadowRoot?.querySelector('#tb-native-data'); + this.tbl!.addEventListener("row-click", (e) => { + // @ts-ignore + let data = (e.detail as NativeMemory); + this.rowSelectData = data + this.setRightTableData(data); + document.dispatchEvent(new CustomEvent('triangle-flag', {detail: {time:data.startTs,type:"triangle"}})); + }) + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight)-10-31+"px"; + this.tbl?.reMeauseHeight(); + // @ts-ignore + this.tblData?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight)-10+"px" + this.tblData?.reMeauseHeight() + } + }).observe(this.parentElement!) + let filter = this.shadowRoot?.querySelector("#filter") + this.shadowRoot?.querySelector("#filter")!.getFilterData((data:FilterData)=>{ + if (data.mark) { + if(this.rowSelectData!=undefined){ + let filterTemp = this.queryResult.filter((tempItem)=>{ + return tempItem.eventId == this.rowSelectData.eventId + }) + if(filterTemp.length>0){ + filterTemp[0].isSelected = true + } + TabPaneNMSampleList.addSampleData(this.rowSelectData) + if(this.rowSelectData.selectedCallback){ + this.rowSelectData.isSelected = true + this.rowSelectData.selectedCallback() + } + document.dispatchEvent(new CustomEvent('triangle-flag', {detail: {time:this.rowSelectData.startTs,type:"square"}})); + } + }else { + this.filterAllocationType = data.firstSelect||"0" + this.filterNativeType = data.secondSelect||"0" + this.filterQueryData() + } + }) + filter!.firstSelect = "1" + } + + filterQueryData(){ + if (this.queryResult.length > 0&&this.currentSelection) { + let filter = this.queryResult.filter((item)=>{ + let filterAllocation = true + if(this.filterAllocationType=="1"){ + filterAllocation = item.startTs>=this.currentSelection!.leftNs&&item.startTs<=this.currentSelection!.rightNs&&item.endTs>this.currentSelection!.rightNs + }else if(this.filterAllocationType=="2"){ + filterAllocation = item.startTs>=this.currentSelection!.leftNs&&item.startTs<=this.currentSelection!.rightNs&&item.endTs<=this.currentSelection!.rightNs + } + let filterNative = this.getTypeFromIndex(parseInt(this.filterNativeType),item) + return filterAllocation&&filterNative + }) + if(filter.length>0){ + this.source = this.handleQueryResult(filter); + this.tbl!.recycleDataSource = this.source; + }else { + this.source = [] + this.tbl!.recycleDataSource = []; + } + } + } + + setRightTableData(hook:NativeMemory){ + let arr:Array = []; + let frameArr = SpSystemTrace.HEAP_FRAME_DATA.filter((frame) => parseInt(frame.eventId) == hook.eventId); + frameArr.map((frame)=>{ + let target = new NativeHookCallInfo(); + target.eventId = parseInt(frame.eventId); + target.depth = frame.depth; + let sym_arr = frame.AllocationFunction?.split("/"); + let lib_arr = frame.MoudleName?.split("/"); + target.symbol = sym_arr![sym_arr!.length - 1]; + target.library = lib_arr![lib_arr!.length - 1]; + target.title = `[ ${target.symbol} ] ${target.library}`; + target.type = (target.library.endsWith(".so.1") || target.library.endsWith(".dll") || target.library.endsWith(".so")) ? 0 : 1; + arr.push(target); + }) + // @ts-ignore + this.tblData?.recycleDataSource = arr; + } + + initHtml(): string { + return ` + +
+
+ + + + + + + + + + +
+
+ + + + + + +
+
+ `; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPanePTS.ts b/host/ide/src/trace/component/trace/sheet/TabPanePTS.ts new file mode 100644 index 0000000000000000000000000000000000000000..9b3bf4c8b4ac48cfd85f21891491d6dbf08c7111 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPanePTS.ts @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../bean/BoxSelection.js"; +import { + getTabStatesGroupByProcess, + getTabStatesGroupByProcessThread, + getTabStatesGroupByStatePidTid +} from "../../../database/SqlLite.js"; +import {StateProcessThread} from "../../../bean/StateProcessThread.js"; +import {Utils} from "../base/Utils.js"; +import {SpSystemTrace} from "../../SpSystemTrace.js"; + +@element('tabpane-pts') +export class TabPanePTS extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private loadDataInCache: boolean = true; + + set data(val: SelectionParam | any) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" + if (this.loadDataInCache) { + this.queryDataInCacheData(val).then((arr) => { + this.tbl!.recycleDataSource = arr; + }); + } else { + this.queryDataByDB(val) + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-states'); + this.range = this.shadowRoot?.querySelector('#time-range') + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45)+"px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + + async queryDataInCacheData(val: SelectionParam | any): Promise> { + return new Promise>((resolve, reject) => { + let pMap: Map = new Map(); + let ptMap: Map = new Map(); + let ptsMap: Map = new Map(); + SpSystemTrace.SPT_DATA.map((d)=>{ + if(!(d.end_ts < val.leftNs || d.start_ts > val.rightNs)){ + if (pMap.has(d.processId + "")) { + let obj1 = pMap.get(d.processId + ""); + obj1!.count++; + obj1!.wallDuration += d.dur; + obj1!.avgDuration = (obj1!.wallDuration / obj1!.count).toFixed(2); + if (d.dur > obj1!.maxDuration) { + obj1!.maxDuration = d.dur; + } + if (d.dur < obj1!.minDuration) { + obj1!.minDuration = d.dur; + } + } else { + let obj1 = new StateProcessThread(); + obj1.id = "p" + d.processId; + obj1.title = (d.process == null || d.process == "" ? "Process" : d.process) + "(" + d.processId + ")"; + obj1.process = d.process; + obj1.processId = d.processId; + obj1.minDuration = d.dur; + obj1.maxDuration = d.dur; + obj1.count = 1; + obj1.avgDuration = d.dur + ""; + obj1.wallDuration = d.dur; + pMap.set(d.processId + "", obj1); + } + if (ptMap.has(d.processId + "_" + d.threadId)) { + let obj2 = ptMap.get(d.processId + "_" + d.threadId); + obj2!.count++; + obj2!.wallDuration += d.dur; + obj2!.avgDuration = (obj2!.wallDuration / obj2!.count).toFixed(2); + if (d.dur > obj2!.maxDuration) { + obj2!.maxDuration = d.dur; + } + if (d.dur < obj2!.minDuration) { + obj2!.minDuration = d.dur; + } + } else { + let obj2 = new StateProcessThread(); + obj2.id = "p" + d.processId + "_" + "t" + d.threadId; + obj2.pid = "p" + d.processId; + obj2.title = (d.thread == null || d.thread == "" ? "Thread" : d.thread) + "(" + d.threadId + ")" + obj2.processId = d.processId; + obj2.process = d.process; + obj2.thread = d.thread; + obj2.threadId = d.threadId; + obj2.minDuration = d.dur; + obj2.maxDuration = d.dur; + obj2.count = 1; + obj2.avgDuration = d.dur + ""; + obj2.wallDuration = d.dur; + ptMap.set(d.processId + "_" + d.threadId, obj2); + } + if (ptsMap.has(d.processId + "_" + d.threadId + "_" + d.state)) { + let obj3 = ptsMap.get(d.processId + "_" + d.threadId + "_" + d.state); + obj3!.count++; + obj3!.wallDuration += d.dur; + obj3!.avgDuration = (obj3!.wallDuration / obj3!.count).toFixed(2); + if (d.dur > obj3!.maxDuration) { + obj3!.maxDuration = d.dur; + } + if (d.dur < obj3!.minDuration) { + obj3!.minDuration = d.dur; + } + } else { + let obj3 = new StateProcessThread(); + obj3.id = "p" + d.processId + "_" + "t" + d.threadId + "_" + (d.state == "R+" ? "RP" : d.state) + obj3.pid = "p" + d.processId + "_" + "t" + d.threadId; + obj3.title = Utils.getEndState(d.state) + obj3.processId = d.processId; + obj3.process = d.process; + obj3.thread = d.thread; + obj3.threadId = d.threadId; + obj3.state = d.state; + obj3.minDuration = d.dur; + obj3.maxDuration = d.dur; + obj3.count = 1; + obj3.avgDuration = d.dur + ""; + obj3.wallDuration = d.dur; + ptsMap.set(d.processId + "_" + d.threadId + "_" + d.state, obj3); + } + } + }) + let arr: Array = []; + for (let key of pMap.keys()) { + let s = pMap.get(key); + s!.children = []; + for (let ks of ptMap.keys()) { + if (ks.startsWith(key + "_")) { + let sp = ptMap.get(ks) + sp!.children = []; + for (let kst of ptsMap.keys()) { + if (kst.startsWith(ks + "_")) { + let spt = ptsMap.get(kst) + sp!.children.push(spt!); + } + } + s!.children.push(sp!) + } + } + arr.push(s!) + } + resolve(arr); + }); + } + + queryDataByDB(val: SelectionParam | any) { + Promise.all([ + getTabStatesGroupByProcess(val.leftNs, val.rightNs), + getTabStatesGroupByProcessThread(val.leftNs, val.rightNs), + getTabStatesGroupByStatePidTid(val.leftNs, val.rightNs)]).then((values) => { + let processes = values[0]; + processes.map((spt) => { + spt.id = "p" + spt.processId + spt.title = (spt.process == null || spt.process == "" ? "Process" : spt.process) + "(" + spt.processId + ")" + }); + let threadMap = this.groupByProcessToMap(values[1]); + let stateMap = this.groupByProcessThreadToMap(values[2]); + for (let process of processes) { + let threads = threadMap.get(process.processId); + if (threads != undefined) { + threads!.map((spt) => { + spt.id = "p" + spt.processId + "_" + "t" + spt.threadId; + spt.pid = "p" + spt.processId; + spt.title = (spt.thread == null || spt.thread == "" ? "Thread" : spt.thread) + "(" + spt.threadId + ")" + }) + } + process.children = threads ?? []; + let map = stateMap.get(process.processId); + for (let thread of threads!) { + let states = map!.get(thread.threadId); + states!.map((spt) => { + spt.id = "p" + spt.processId + "_" + "t" + spt.threadId + "_" + (spt.state == "R+" ? "RP" : spt.state) + spt.pid = "p" + spt.processId + "_" + "t" + spt.threadId; + spt.title = Utils.getEndState(spt.state) + }) + thread.children = states ?? []; + } + } + this.tbl!.dataSource = processes; + }) + } + + groupByThreadToMap(arr: Array): Map> { + let map = new Map>(); + for (let spt of arr) { + if (map.has(spt.threadId)) { + map.get(spt.threadId)!.push(spt); + } else { + let list: Array = []; + list.push(spt); + map.set(spt.threadId, list); + } + } + return map; + } + + groupByProcessToMap(arr: Array): Map> { + let map = new Map>(); + for (let spt of arr) { + if (map.has(spt.processId)) { + map.get(spt.processId)!.push(spt); + } else { + let list: Array = []; + list.push(spt); + map.set(spt.processId, list); + } + } + return map; + } + + groupByProcessThreadToMap(arr: Array): Map>> { + let map = new Map>>(); + let processMap = this.groupByProcessToMap(arr); + for (let key of processMap.keys()) { + let threadMap = this.groupByThreadToMap(processMap.get(key)!) + map.set(key, threadMap); + } + return map; + } + + initHtml(): string { + return ` + + + + + + + + + + + + `; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneSPT.ts b/host/ide/src/trace/component/trace/sheet/TabPaneSPT.ts new file mode 100644 index 0000000000000000000000000000000000000000..2c068cdf95997c8cf1a15d7c4c73853633fc0509 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneSPT.ts @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../bean/BoxSelection.js"; +import { + getTabStatesGroupByState, + getTabStatesGroupByStatePid, + getTabStatesGroupByStatePidTid +} from "../../../database/SqlLite.js"; +import {StateProcessThread} from "../../../bean/StateProcessThread.js"; +import {Utils} from "../base/Utils.js"; +import {SpSystemTrace} from "../../SpSystemTrace.js"; + +@element('tabpane-spt') +export class TabPaneSPT extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private loadDataInCache: boolean = true; + + set data(val: SelectionParam | any) { + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement!.clientHeight - 45)+"px" + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" + if (this.loadDataInCache) { + this.queryDataByCacheData(val).then((result) => { + this.tbl!.recycleDataSource = result; + }); + } else { + this.queryDataByDB(val); + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-states'); + this.range = this.shadowRoot?.querySelector('#time-range') + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement!.clientHeight - 45)+"px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!) + } + + async queryDataByCacheData(val: SelectionParam | any): Promise> { + //1. 框选时间区间的数据过滤出来 + return new Promise>((resolve, reject) => { + let statesMap: Map = new Map(); + let spMap: Map = new Map(); + let sptMap: Map = new Map(); + // @ts-ignore + SpSystemTrace.SPT_DATA.map((d) => { + if(!(d.end_ts < val.leftNs || d.start_ts > val.rightNs)){ + if (statesMap.has(d.state)) { + let obj1 = statesMap.get(d.state); + obj1!.count++; + obj1!.wallDuration += d.dur; + obj1!.avgDuration = (obj1!.wallDuration / obj1!.count).toFixed(2); + if (d.dur > obj1!.maxDuration) { + obj1!.maxDuration = d.dur; + } + if (d.dur < obj1!.minDuration) { + obj1!.minDuration = d.dur; + } + } else { + let obj1 = new StateProcessThread(); + obj1.id = (d.state == "R+" ? "RP" : d.state) + obj1.title = Utils.getEndState(d.state); + obj1.state = d.state; + obj1.minDuration = d.dur; + obj1.maxDuration = d.dur; + obj1.count = 1; + obj1.avgDuration = d.dur + ""; + obj1.wallDuration = d.dur; + statesMap.set(d.state, obj1); + } + if (spMap.has(d.state + "_" + d.processId)) { + let obj2 = spMap.get(d.state + "_" + d.processId); + obj2!.count++; + obj2!.wallDuration += d.dur; + obj2!.avgDuration = (obj2!.wallDuration / obj2!.count).toFixed(2); + if (d.dur > obj2!.maxDuration) { + obj2!.maxDuration = d.dur; + } + if (d.dur < obj2!.minDuration) { + obj2!.minDuration = d.dur; + } + } else { + let obj2 = new StateProcessThread(); + obj2.id = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId; + obj2.pid = (d.state == "R+" ? "RP" : d.state); + obj2.title = (d.process == null || d.process == "" ? "Process" : d.process) + "(" + d.processId + ")" + obj2.processId = d.processId; + obj2.process = d.process; + obj2.state = d.state; + obj2.minDuration = d.dur; + obj2.maxDuration = d.dur; + obj2.count = 1; + obj2.avgDuration = d.dur + ""; + obj2.wallDuration = d.dur; + spMap.set(d.state + "_" + d.processId, obj2); + } + if (sptMap.has(d.state + "_" + d.processId + "_" + d.threadId)) { + let obj3 = sptMap.get(d.state + "_" + d.processId + "_" + d.threadId); + obj3!.count++; + obj3!.wallDuration += d.dur; + obj3!.avgDuration = (obj3!.wallDuration / obj3!.count).toFixed(2); + if (d.dur > obj3!.maxDuration) { + obj3!.maxDuration = d.dur; + } + if (d.dur < obj3!.minDuration) { + obj3!.minDuration = d.dur; + } + } else { + let obj3 = new StateProcessThread(); + obj3.id = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId + "_" + d.threadId + obj3.pid = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId + obj3.title = (d.thread == null || d.thread == "" ? "Thread" : d.thread) + "(" + d.threadId + ")" + obj3.processId = d.processId; + obj3.process = d.process; + obj3.thread = d.thread; + obj3.threadId = d.threadId; + obj3.state = d.state; + obj3.minDuration = d.dur; + obj3.maxDuration = d.dur; + obj3.count = 1; + obj3.avgDuration = d.dur + ""; + obj3.wallDuration = d.dur; + sptMap.set(d.state + "_" + d.processId + "_" + d.threadId, obj3); + } + } + }); + let arr: Array = []; + for (let key of statesMap.keys()) { + let s = statesMap.get(key); + s!.children = []; + for (let ks of spMap.keys()) { + if (ks.startsWith(key + "_")) { + let sp = spMap.get(ks) + sp!.children = []; + for (let kst of sptMap.keys()) { + if (kst.startsWith(ks + "_")) { + let spt = sptMap.get(kst) + sp!.children.push(spt!); + } + } + s!.children.push(sp!) + } + } + arr.push(s!) + } + resolve(arr); + }); + } + + queryDataByDB(val: SelectionParam | any) { + Promise.all([ + getTabStatesGroupByState(val.leftNs, val.rightNs), + getTabStatesGroupByStatePid(val.leftNs, val.rightNs), + getTabStatesGroupByStatePidTid(val.leftNs, val.rightNs)]).then((values) => { + let states = values[0]; + states.map((spt) => { + spt.id = (spt.state == "R+" ? "RP" : spt.state) + spt.title = Utils.getEndState(spt.state); + }); + let processMap = this.groupByStateToMap(values[1]); + let threadMap = this.groupByStateProcessToMap(values[2]); + for (let state of states) { + let processes = processMap.get(state.state); + processes!.map((spt) => { + spt.id = (spt.state == "R+" ? "RP" : spt.state) + "_" + spt.processId; + spt.pid = (spt.state == "R+" ? "RP" : spt.state); + spt.title = (spt.process == null || spt.process == "" ? "Process" : spt.process) + "(" + spt.processId + ")" + }) + state.children = processes ?? []; + let map = threadMap.get(state.state); + for (let process of processes!) { + let threads = map!.get(process.processId); + threads!.map((spt) => { + spt.id = (spt.state == "R+" ? "RP" : spt.state) + "_" + spt.processId + "_" + spt.threadId + spt.pid = (spt.state == "R+" ? "RP" : spt.state) + "_" + spt.processId + spt.title = (spt.thread == null || spt.thread == "" ? "Thread" : spt.thread) + "(" + spt.threadId + ")" + }) + process.children = threads ?? []; + } + } + this.tbl!.recycleDataSource = states; + }) + } + + groupByStateToMap(arr: Array): Map> { + let map = new Map>(); + for (let spt of arr) { + if (map.has(spt.state)) { + map.get(spt.state)!.push(spt); + } else { + let list: Array = []; + list.push(spt); + map.set(spt.state, list); + } + } + return map; + } + + groupByProcessToMap(arr: Array): Map> { + let map = new Map>(); + for (let spt of arr) { + if (map.has(spt.processId)) { + map.get(spt.processId)!.push(spt); + } else { + let list: Array = []; + list.push(spt); + map.set(spt.processId, list); + } + } + return map; + } + + groupByStateProcessToMap(arr: Array): Map>> { + let map = new Map>>(); + let stateMap = this.groupByStateToMap(arr); + for (let key of stateMap.keys()) { + let processMap = this.groupByProcessToMap(stateMap.get(key)!) + map.set(key, processMap); + } + return map; + } + + initHtml(): string { + return ` + + + + + + + + + + + + `; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneSlices.ts b/host/ide/src/trace/component/trace/sheet/TabPaneSlices.ts new file mode 100644 index 0000000000000000000000000000000000000000..705749bde1c3f9c88721b02cb51372de1f4bb241 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneSlices.ts @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {SelectionData, SelectionParam} from "../../../bean/BoxSelection.js"; +import {getTabSlices} from "../../../database/SqlLite.js"; + +@element('tabpane-slices') +export class TabPaneSlices extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private source: Array = [] + + set data(val: SelectionParam | any) { + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" + getTabSlices(val.funTids, val.leftNs, val.rightNs).then((result) => { + if (result != null && result.length > 0) { + let sumWall = 0.0; + let sumOcc = 0; + for (let e of result) { + e.name = e.name == null ? "" : e.name + sumWall += e.wallDuration + sumOcc += e.occurrences + e.wallDuration = parseFloat((e.wallDuration / 1000000.0).toFixed(5)); + e.avgDuration = parseFloat((e.avgDuration / 1000000.0).toFixed(5)); + } + let count = new SelectionData() + count.process = " "; + count.wallDuration = parseFloat((sumWall / 1000000.0).toFixed(5)); + count.occurrences = sumOcc; + result.splice(0, 0, count) + this.source = result + this.tbl!.dataSource = result + } else { + this.source = []; + this.tbl!.dataSource = this.source; + } + }); + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-slices'); + this.range = this.shadowRoot?.querySelector('#time-range'); + this.tbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail) + }); + } + + initHtml(): string { + return ` + + + + + + + + + `; + } + + sortByColumn(detail: any) { + // @ts-ignore + function compare(property, sort, type) { + return function (a: SelectionData, b: SelectionData) { + if (a.process == " " || b.process == " ") { + return 0; + } + if (type === 'number') { + // @ts-ignore + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } else { + // @ts-ignore + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else { // @ts-ignore + if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + } + + if (detail.key === "name") { + this.source.sort(compare(detail.key, detail.sort, 'string')) + } else { + this.source.sort(compare(detail.key, detail.sort, 'number')) + } + this.tbl!.dataSource = this.source; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneThreadStates.ts b/host/ide/src/trace/component/trace/sheet/TabPaneThreadStates.ts new file mode 100644 index 0000000000000000000000000000000000000000..a9ab4a43b2d40ff482493d0631ddca5e9c622c19 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneThreadStates.ts @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {SelectionData, SelectionParam} from "../../../bean/BoxSelection.js"; +import "../../StackBar.js" +import {getTabThreadStates} from "../../../database/SqlLite.js"; +import {Utils} from "../base/Utils.js"; +import {StackBar} from "../../StackBar.js"; + +@element('tabpane-thread-states') +export class TabPaneThreadStates extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private stackBar: StackBar | null | undefined; + private source: Array = [] + + set data(val: SelectionParam | any) { + // // @ts-ignore + this.range!.textContent = "Selected range: " + ((val.rightNs - val.leftNs) / 1000000.0).toFixed(5) + " ms" + getTabThreadStates(val.threadIds, val.leftNs, val.rightNs).then((result) => { + if (result != null && result.length > 0) { + let sumWall = 0.0; + let sumOcc = 0; + for (let e of result) { + e.process = e.process == null || e.process.length == 0 ? "[NULL]" : e.process + e.thread = e.thread == null || e.thread.length == 0 ? "[NULL]" : e.thread + sumWall += e.wallDuration + sumOcc += e.occurrences + e.stateJX = e.state + e.state = Utils.getEndState(e.stateJX); + e.wallDuration = parseFloat((e.wallDuration / 1000000.0).toFixed(5)); + e.avgDuration = parseFloat((e.avgDuration / 1000000.0).toFixed(5)); + } + let count = new SelectionData() + count.process = " " + count.state = " " + count.wallDuration = parseFloat((sumWall / 1000000.0).toFixed(5)); + count.occurrences = sumOcc; + result.splice(0, 0, count) + this.source = result; + this.tbl!.dataSource = result + this.stackBar!.data = result; + } else { + this.source = [] + this.stackBar!.data = [] + this.tbl!.dataSource = [] + } + }) + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-thread-states'); + this.range = this.shadowRoot?.querySelector('#time-range'); + this.stackBar = this.shadowRoot?.querySelector('#stack-bar'); + this.tbl!.addEventListener('column-click', (evt: any) => { + this.sortByColumn(evt.detail) + }); + } + + initHtml(): string { + return ` + +
+ + +
+ + + + + + + + + + + `; + } + + sortByColumn(detail: any) { + function compare(property: any, sort: any, type: any) { + return function (a: SelectionData | any, b: SelectionData | any) { + if (a.process == " " || b.process == " ") { + return 0; + } + if (type === 'number') { + return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); + } else { + if (b[property] > a[property]) { + return sort === 2 ? 1 : -1; + } else if (b[property] == a[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + } + + if (detail.key === "name" || detail.key === "thread" || detail.key === "state") { + this.source.sort(compare(detail.key, detail.sort, 'string')) + } else { + this.source.sort(compare(detail.key, detail.sort, 'number')) + } + this.tbl!.dataSource = this.source; + } + +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabPaneThreadSwitch.ts b/host/ide/src/trace/component/trace/sheet/TabPaneThreadSwitch.ts new file mode 100644 index 0000000000000000000000000000000000000000..9af0690e12a460a5c9c331fd940b6ac01e7c5360 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabPaneThreadSwitch.ts @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {LitTable} from "../../../../base-ui/table/lit-table.js"; +import {SelectionParam} from "../../../bean/BoxSelection.js"; +import { + getTabStatesGroupByState, + getTabStatesGroupByStatePid, + getTabStatesGroupByStatePidTid +} from "../../../database/SqlLite.js"; +import {StateProcessThread} from "../../../bean/StateProcessThread.js"; +import {Utils} from "../base/Utils.js"; +import {SpSystemTrace} from "../../SpSystemTrace.js"; + +@element('tabpane-thread-switch') +export class TabPaneThreadSwitch extends BaseElement { + private tbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private loadDataInCache: boolean = true; + + set data(val: SelectionParam | any) { + //@ts-ignore + this.tbl?.shadowRoot?.querySelector(".table")?.style?.height = (this.parentElement!.clientHeight - 45)+"px"; + this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms"; + if (this.loadDataInCache) { + this.queryDataByCacheData(val).then((arr) => { + this.tbl!.recycleDataSource = arr; + }); + } else { + this.queryDataByDB(val); + } + } + + initElements(): void { + this.tbl = this.shadowRoot?.querySelector('#tb-ts'); + this.range = this.shadowRoot?.querySelector('#time-range'); + new ResizeObserver((entries) => { + if (this.parentElement?.clientHeight != 0) { + // @ts-ignore + this.tbl?.shadowRoot?.querySelector(".table").style.height = (this.parentElement!.clientHeight - 45)+"px" + this.tbl?.reMeauseHeight() + } + }).observe(this.parentElement!); + } + + async queryDataByCacheData(val: SelectionParam | any): Promise> { + //1. 框选时间区间的数据过滤出来 + return new Promise>(((resolve, reject) => { + let statesMap: Map = new Map(); + let spMap: Map = new Map(); + let sptMap: Map = new Map(); + SpSystemTrace.SPT_DATA.map((d) => { + if(!(d.end_ts < val.leftNs || d.start_ts > val.rightNs)){ + if (statesMap.has(d.state)) { + let obj1 = statesMap.get(d.state); + obj1!.count++; + obj1!.wallDuration += d.dur; + obj1!.avgDuration = (obj1!.wallDuration / obj1!.count).toFixed(2); + if (d.dur > obj1!.maxDuration) { + obj1!.maxDuration = d.dur; + } + if (d.dur < obj1!.minDuration) { + obj1!.minDuration = d.dur; + } + } else { + let obj1 = new StateProcessThread(); + obj1.id = (d.state == "R+" ? "RP" : d.state) + obj1.title = Utils.getEndState(d.state); + obj1.state = d.state; + obj1.minDuration = d.dur; + obj1.maxDuration = d.dur; + obj1.count = 1; + obj1.avgDuration = d.dur + ""; + obj1.wallDuration = d.dur; + statesMap.set(d.state, obj1); + } + if (spMap.has(d.state + "_" + d.processId)) { + let obj2 = spMap.get(d.state + "_" + d.processId); + obj2!.count++; + obj2!.wallDuration += d.dur; + obj2!.avgDuration = (obj2!.wallDuration / obj2!.count).toFixed(2); + if (d.dur > obj2!.maxDuration) { + obj2!.maxDuration = d.dur; + } + if (d.dur < obj2!.minDuration) { + obj2!.minDuration = d.dur; + } + } else { + let obj2 = new StateProcessThread(); + obj2.id = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId; + obj2.pid = (d.state == "R+" ? "RP" : d.state); + obj2.title = (d.process == null || d.process == "" ? "Process" : d.process) + "(" + d.processId + ")" + obj2.processId = d.processId; + obj2.process = d.process; + obj2.state = d.state; + obj2.minDuration = d.dur; + obj2.maxDuration = d.dur; + obj2.count = 1; + obj2.avgDuration = d.dur + ""; + obj2.wallDuration = d.dur; + spMap.set(d.state + "_" + d.processId, obj2); + } + if (sptMap.has(d.state + "_" + d.processId + "_" + d.threadId)) { + let obj3 = sptMap.get(d.state + "_" + d.processId + "_" + d.threadId); + obj3!.count++; + obj3!.wallDuration += d.dur; + obj3!.avgDuration = (obj3!.wallDuration / obj3!.count).toFixed(2); + if (d.dur > obj3!.maxDuration) { + obj3!.maxDuration = d.dur; + } + if (d.dur < obj3!.minDuration) { + obj3!.minDuration = d.dur; + } + } else { + let obj3 = new StateProcessThread(); + obj3.id = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId + "_" + d.threadId + obj3.pid = (d.state == "R+" ? "RP" : d.state) + "_" + d.processId + obj3.title = (d.thread == null || d.thread == "" ? "Thread" : d.thread) + "(" + d.threadId + ")" + obj3.processId = d.processId; + obj3.process = d.process; + obj3.thread = d.thread; + obj3.threadId = d.threadId; + obj3.state = d.state; + obj3.minDuration = d.dur; + obj3.maxDuration = d.dur; + obj3.count = 1; + obj3.avgDuration = d.dur + ""; + obj3.wallDuration = d.dur; + sptMap.set(d.state + "_" + d.processId + "_" + d.threadId, obj3); + } + } + }) + let arr: Array = []; + for (let key of statesMap.keys()) { + let s = statesMap.get(key); + s!.children = []; + for (let ks of spMap.keys()) { + if (ks.startsWith(key + "_")) { + let sp = spMap.get(ks) + sp!.children = []; + for (let kst of sptMap.keys()) { + if (kst.startsWith(ks + "_")) { + let spt = sptMap.get(kst) + sp!.children.push(spt!); + } + } + s!.children.push(sp!) + } + } + arr.push(s!) + } + resolve(arr); + })); + } + + queryDataByDB(val: SelectionParam | any) { + Promise.all([ + getTabStatesGroupByState(val.leftNs, val.rightNs), + getTabStatesGroupByStatePid(val.leftNs, val.rightNs), + getTabStatesGroupByStatePidTid(val.leftNs, val.rightNs)]).then((values) => { + let states = values[0]; + states.map((spt) => { + spt.id = (spt.state == "R+" ? "RP" : spt.state) + spt.title = Utils.getEndState(spt.state); + }); + let processMap = this.groupByStateToMap(values[1]); + let threadMap = this.groupByStateProcessToMap(values[2]); + for (let state of states) { + let processes = processMap.get(state.state); + processes!.map((spt) => { + spt.id = (spt.state == "R+" ? "RP" : spt.state) + "_" + spt.processId; + spt.pid = (spt.state == "R+" ? "RP" : spt.state); + spt.title = (spt.process == null || spt.process == "" ? "Process" : spt.process) + "(" + spt.processId + ")" + }) + state.children = processes ?? []; + let map = threadMap.get(state.state); + for (let process of processes!) { + let threads = map!.get(process.processId); + threads!.map((spt) => { + spt.id = (spt.state == "R+" ? "RP" : spt.state) + "_" + spt.processId + "_" + spt.threadId + spt.pid = (spt.state == "R+" ? "RP" : spt.state) + "_" + spt.processId + spt.title = (spt.thread == null || spt.thread == "" ? "Thread" : spt.thread) + "(" + spt.threadId + ")" + }) + process.children = threads ?? []; + } + } + this.tbl!.recycleDataSource = states; + }) + } + + groupByStateToMap(arr: Array): Map> { + let map = new Map>(); + for (let spt of arr) { + if (map.has(spt.state)) { + map.get(spt.state)!.push(spt); + } else { + let list: Array = []; + list.push(spt); + map.set(spt.state, list); + } + } + return map; + } + + groupByProcessToMap(arr: Array): Map> { + let map = new Map>(); + for (let spt of arr) { + if (map.has(spt.processId)) { + map.get(spt.processId)!.push(spt); + } else { + let list: Array = []; + list.push(spt); + map.set(spt.processId, list); + } + } + return map; + } + + groupByStateProcessToMap(arr: Array): Map>> { + let map = new Map>>(); + let stateMap = this.groupByStateToMap(arr); + for (let key of stateMap.keys()) { + let processMap = this.groupByProcessToMap(stateMap.get(key)!) + map.set(key, processMap); + } + return map; + } + + initHtml(): string { + return ` + + + + + + + `; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/component/trace/sheet/TabProgressBar.ts b/host/ide/src/trace/component/trace/sheet/TabProgressBar.ts new file mode 100644 index 0000000000000000000000000000000000000000..74640f8beaf93160964e685a981084b507dbe700 --- /dev/null +++ b/host/ide/src/trace/component/trace/sheet/TabProgressBar.ts @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; + + +@element('tab-progress-bar') +export class TabProgressBar extends BaseElement { + + initElements(): void { + let data:Array = this.getAttribute("data")!.split(",") + let first: HTMLDivElement | undefined | null =this.shadowRoot?.querySelector("#first") + let second: HTMLDivElement | undefined | null =this.shadowRoot?.querySelector("#second") + if (data!.length > 0 && data && data![2]!="0") { + if (parseInt(data[0])< 0) { + first!.style.width = (Number((Math.abs(parseInt(data[0]))/parseInt(data[2]))*100)).toFixed(2) + "%" + first!.style.background = "#FC74FF" + }else { + first!.style.width = (Number((parseInt(data[0])/parseInt(data[2]))*100)).toFixed(2) + "%" + } + if (parseInt(data[1])< 0) { + second!.style.width = (Number((Math.abs(parseInt(data[1])) / parseInt(data[2])) * 100)).toFixed(2) + "%" + first!.style.background = "#CC34CF" + }else { + second!.style.width = (Number((parseInt(data[1]) / parseInt(data[2])) * 100)).toFixed(2) + "%" + } + } + + } + + + + initHtml(): string { + return ` + +
+
+ `; + } +} diff --git a/host/ide/src/trace/component/trace/timer-shaft/Flag.ts b/host/ide/src/trace/component/trace/timer-shaft/Flag.ts new file mode 100644 index 0000000000000000000000000000000000000000..aaf2f2974001db4f43d11bbf1b23b48b87768fdc --- /dev/null +++ b/host/ide/src/trace/component/trace/timer-shaft/Flag.ts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class Flag { + x: number = 0 + y: number = 0 + width: number = 0 + height: number = 0 + time: number = 0 + color: string = "" + selected: boolean = false + text: string = "" + hidden: boolean = false; + type:string = ""; + constructor(x: number, y: number, width: number, height: number, time: number, color: string = "#999999", selected = false, type:string="") { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + this.time = time; + this.color = color; + this.selected = selected; + this.type = type; + } +} + diff --git a/host/ide/src/trace/component/trace/timer-shaft/Graph.ts b/host/ide/src/trace/component/trace/timer-shaft/Graph.ts new file mode 100644 index 0000000000000000000000000000000000000000..23a2278f40c5a9e0113164fc028ad120c359be77 --- /dev/null +++ b/host/ide/src/trace/component/trace/timer-shaft/Graph.ts @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {Rect} from "./Rect.js"; + +export abstract class Graph { + frame: Rect + c: CanvasRenderingContext2D; + canvas: HTMLCanvasElement | undefined | null; + + protected constructor(canvas: HTMLCanvasElement | undefined | null, c: CanvasRenderingContext2D, frame: Rect) { + this.canvas = canvas; + this.frame = frame; + this.c = c; + } + + abstract draw(): void; +} diff --git a/host/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts b/host/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts new file mode 100644 index 0000000000000000000000000000000000000000..3836cbf27b5cef43a9db005bf5763996dd52e5b5 --- /dev/null +++ b/host/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts @@ -0,0 +1,469 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {Graph} from "./Graph.js"; +import {Rect} from "./Rect.js"; +import {ns2s, TimerShaftElement} from "../TimerShaftElement.js"; +import {ColorUtils} from "../base/ColorUtils.js"; +import {CpuStruct} from "../../../bean/CpuStruct.js"; + +const markPadding = 5; + +export class Mark extends Graph { + name: string | undefined + inspectionFrame: Rect + private _isHover: boolean = false + + constructor(canvas: HTMLCanvasElement | undefined | null, name: string, c: CanvasRenderingContext2D, frame: Rect) { + super(canvas, c, frame); + this.name = name; + this.inspectionFrame = new Rect(frame.x - markPadding, frame.y, frame.width + markPadding * 2, frame.height) + } + + get isHover(): boolean { + return this._isHover; + } + + set isHover(value: boolean) { + this._isHover = value; + if (value) { + document.body.style.cursor = 'ew-resize' + } else { + document.body.style.cursor = 'default' + } + } + + draw(): void { + this.c.beginPath(); + this.c.lineWidth = 7 + this.c.strokeStyle = '#999999' + this.c.moveTo(this.frame.x, this.frame.y); + this.c.lineTo(this.frame.x, this.frame.y + this.frame.height / 3) + this.c.stroke(); + this.c.lineWidth = 1 + this.c.strokeStyle = '#999999' + this.c.moveTo(this.frame.x, this.frame.y); + this.c.lineTo(this.frame.x, this.frame.y + this.frame.height) + this.c.stroke(); + this.c.closePath(); + } +} + +export interface TimeRange { + totalNS: number + startX: number + endX: number + startNS: number + endNS: number + xs: Array + xsTxt: Array +} + +export class RangeRuler extends Graph { + public rangeRect: Rect + public markA: Mark + public markB: Mark + public range: TimeRange; + mouseDownOffsetX = 0 + mouseDownMovingMarkX = 0 + movingMark: Mark | undefined | null; + isMouseDown: boolean = false; + isMovingRange: boolean = false; + isNewRange: boolean = false; + markAX: number = 0; + markBX: number = 0; + isPress: boolean = false + pressFrameId: number = -1 + currentDuration: number = 0 + centerXPercentage: number = 0; + animaStartTime: number | undefined + animTime: number = 100; + p: number = 800; + private readonly notifyHandler: (r: TimeRange) => void; + private scale: number = 0; + //缩放级别 + private scales: Array = [50, 100, 200, 500, 1_000, 2_000, 5_000, 10_000, 20_000, 50_000, 100_000, 200_000, 500_000, + 1_000_000, 2_000_000, 5_000_000, 10_000_000, 20_000_000, 50_000_000, 100_000_000, 200_000_000, 500_000_000, + 1_000_000_000, 2_000_000_000, 5_000_000_000, 10_000_000_000, 20_000_000_000, 50_000_000_000, + 100_000_000_000, 200_000_000_000, 500_000_000_000]; + private _cpuUsage: Array<{ cpu: number, ro: number, rate: number }> = [] + + constructor(timerShaftEL:TimerShaftElement, frame: Rect, range: TimeRange, notifyHandler: (r: TimeRange) => void) { + super(timerShaftEL.canvas, timerShaftEL.ctx!, frame) + this.range = range; + this.notifyHandler = notifyHandler; + this.markA = new Mark(timerShaftEL.canvas, 'A', timerShaftEL.ctx!, new Rect(range.startX, frame.y, 1, frame.height)) + this.markB = new Mark(timerShaftEL.canvas, 'B', timerShaftEL.ctx!, new Rect(range.endX, frame.y, 1, frame.height)) + this.rangeRect = new Rect(range.startX, frame.y, range.endX - range.startX, frame.height) + } + + set cpuUsage(value: Array<{ cpu: number, ro: number, rate: number }>) { + this._cpuUsage = value + this.draw(); + } + + drawCpuUsage() { + let maxNum = Math.round(this._cpuUsage.length / 100) + let miniHeight = Math.round(this.frame.height / CpuStruct.cpuCount);//每格高度 + let miniWidth = Math.ceil(this.frame.width / 100);//每格宽度 + for (let i = 0; i < this._cpuUsage.length; i++) { + let it = this._cpuUsage[i] + this.c.fillStyle = ColorUtils.MD_PALETTE[it.cpu] + this.c.globalAlpha = it.rate + this.c.fillRect(this.frame.x + miniWidth * it.ro, this.frame.y + it.cpu * miniHeight, miniWidth, miniHeight) + } + } + + draw(discardNotify: boolean = false): void { + this.c.clearRect(this.frame.x - markPadding, this.frame.y, this.frame.width + markPadding * 2, this.frame.height) + this.c.beginPath(); + if (this._cpuUsage.length > 0) { + this.drawCpuUsage() + this.c.globalAlpha = 0; + } else { + this.c.globalAlpha = 1; + } + //绘制选中区域 + this.c.fillStyle = window.getComputedStyle(this.canvas!, null).getPropertyValue("background-color");//"#ffffff" + this.rangeRect.x = this.markA.frame.x < this.markB.frame.x ? this.markA.frame.x : this.markB.frame.x + this.rangeRect.width = Math.abs(this.markB.frame.x - this.markA.frame.x) + this.c.fillRect(this.rangeRect.x, this.rangeRect.y, this.rangeRect.width, this.rangeRect.height) + this.c.globalAlpha = 1; + this.c.globalAlpha = .5; + this.c.fillStyle = "#999999" + this.c.fillRect(this.frame.x, this.frame.y, this.rangeRect.x, this.rangeRect.height) + this.c.fillRect(this.rangeRect.x + this.rangeRect.width, this.frame.y, this.frame.width - this.rangeRect.width, this.rangeRect.height) + this.c.globalAlpha = 1; + this.c.closePath(); + this.markA.draw(); + this.markB.draw(); + if (this.notifyHandler) { + this.range.startX = this.rangeRect.x + this.range.endX = this.rangeRect.x + this.rangeRect.width + this.range.startNS = this.range.startX * this.range.totalNS / (this.canvas?.clientWidth || 0) + this.range.endNS = this.range.endX * this.range.totalNS / (this.canvas?.clientWidth || 0) + let l20 = (this.range.endNS - this.range.startNS) / 20; + let min = 0; + let max = 0; + let weight = 0; + for (let index = 0; index < this.scales.length; index++) { + if (this.scales[index] > l20) { + if (index > 0) { + min = this.scales[index - 1]; + } else { + min = 0; + } + max = this.scales[index]; + weight = (l20 - min) * 1.0 / (max - min); + if (weight > 0.243) { + this.scale = max; + } else { + this.scale = min; + } + break; + } + } + if (this.scale == 0) { + this.scale = this.scales[0]; + } + let tmpNs = 0; + let yu = this.range.startNS % this.scale; + let realW = (this.scale * this.frame.width) / (this.range.endNS - this.range.startNS); + let startX = 0; + if (this.range.xs) { + this.range.xs.length = 0 + } else { + this.range.xs = [] + } + if (this.range.xsTxt) { + this.range.xsTxt.length = 0 + } else { + this.range.xsTxt = [] + } + if (yu != 0) { + let firstNodeWidth = ((this.scale - yu) / this.scale * realW); + startX += firstNodeWidth; + tmpNs += yu; + this.range.xs.push(startX) + this.range.xsTxt.push(ns2s(tmpNs)) + } + while (tmpNs < this.range.endNS - this.range.startNS) { + startX += realW; + tmpNs += this.scale; + this.range.xs.push(startX) + this.range.xsTxt.push(ns2s(tmpNs)) + } + if (!discardNotify) { + this.notifyHandler(this.range) + } + } + } + + mouseDown(ev: MouseEvent) { + let x = ev.offsetX - (this.canvas?.offsetLeft || 0) + let y = ev.offsetY - (this.canvas?.offsetTop || 0) + this.isMouseDown = true; + this.mouseDownOffsetX = x; + if (this.markA.isHover) { + this.movingMark = this.markA; + this.mouseDownMovingMarkX = this.movingMark.frame.x || 0 + } else if (this.markB.isHover) { + this.movingMark = this.markB; + this.mouseDownMovingMarkX = this.movingMark.frame.x || 0 + } else { + this.movingMark = null; + } + if (this.rangeRect.containsWithPadding(x, y, 5, 0)) { + this.isMovingRange = true; + this.markAX = this.markA.frame.x; + this.markBX = this.markB.frame.x; + document.body.style.cursor = "move" + } else if (this.frame.containsWithMargin(x, y, 20, 0, 0, 0) && !this.rangeRect.containsWithMargin(x, y, 0, markPadding, 0, markPadding)) { + this.isNewRange = true; + } + } + + mouseUp(ev: MouseEvent) { + this.isMouseDown = false; + this.isMovingRange = false; + this.isNewRange = false; + this.movingMark = null; + } + + mouseMove(ev: MouseEvent) { + let x = ev.offsetX - (this.canvas?.offsetLeft || 0); + let y = ev.offsetY - (this.canvas?.offsetTop || 0) + this.centerXPercentage = x / (this.canvas?.clientWidth || 0) + if (this.centerXPercentage <= 0) { + this.centerXPercentage = 0 + } else if (this.centerXPercentage >= 1) { + this.centerXPercentage = 1 + } + let maxX = this.canvas?.clientWidth || 0 + if (this.markA.inspectionFrame.contains(x, y)) { + this.markA.isHover = true + } else if (this.markB.inspectionFrame.contains(x, y)) { + this.markB.isHover = true; + } else { + this.markA.isHover = false; + this.markB.isHover = false; + } + if (this.movingMark) { + let result = x - this.mouseDownOffsetX + this.mouseDownMovingMarkX; + if (result >= 0 && result <= maxX) { + this.movingMark.frame.x = result + } else if (result < 0) { + this.movingMark.frame.x = 0 + } else { + this.movingMark.frame.x = maxX + } + this.movingMark.inspectionFrame.x = this.movingMark.frame.x - markPadding + requestAnimationFrame(() => this.draw()); + } else if (this.rangeRect.containsWithPadding(x, y, markPadding, 0)) { + document.body.style.cursor = "move" + } else if (this.frame.containsWithMargin(x, y, 20, 0, 0, 0) && !this.rangeRect.containsWithMargin(x, y, 0, markPadding, 0, markPadding)) { + document.body.style.cursor = "crosshair"; + } + if (this.isMovingRange && this.isMouseDown) { + let result = x - this.mouseDownOffsetX; + let mA = result + this.markAX + let mB = result + this.markBX + if (mA >= 0 && mA <= maxX) { + this.markA.frame.x = mA + } else if (mA < 0) { + this.markA.frame.x = 0 + } else { + this.markA.frame.x = maxX + } + this.markA.inspectionFrame.x = this.markA.frame.x - markPadding + if (mB >= 0 && mB <= maxX) { + this.markB.frame.x = mB; + } else if (mB < 0) { + this.markB.frame.x = 0 + } else { + this.markB.frame.x = maxX + } + this.markB.inspectionFrame.x = this.markB.frame.x - markPadding + requestAnimationFrame(() => this.draw()); + } else if (this.isNewRange) { + this.markA.frame.x = this.mouseDownOffsetX; + this.markA.inspectionFrame.x = this.mouseDownOffsetX - markPadding; + if (x >= 0 && x <= maxX) { + this.markB.frame.x = x; + } else if (x < 0) { + this.markB.frame.x = 0; + } else { + this.markB.frame.x = maxX; + } + this.markB.inspectionFrame.x = this.markB.frame.x - markPadding; + requestAnimationFrame(() => this.draw()); + } + } + + mouseOut(ev: MouseEvent) { + this.movingMark = null; + } + + fillX() { + if (this.range.startNS < 0) this.range.startNS = 0; + if (this.range.endNS < 0) this.range.endNS = 0; + if (this.range.endNS > this.range.totalNS) this.range.endNS = this.range.totalNS; + if (this.range.startNS > this.range.totalNS) this.range.startNS = this.range.totalNS; + this.range.startX = this.range.startNS * (this.canvas?.clientWidth || 0) / this.range.totalNS + this.range.endX = this.range.endNS * (this.canvas?.clientWidth || 0) / this.range.totalNS + this.markA.frame.x = this.range.startX + this.markA.inspectionFrame.x = this.markA.frame.x - markPadding + this.markB.frame.x = this.range.endX + this.markB.inspectionFrame.x = this.markB.frame.x - markPadding + } + + setRangeNS(startNS:number,endNS:number) { + this.range.startNS = startNS + this.range.endNS = endNS + this.fillX() + this.draw(); + } + getRange():TimeRange{ + return this.range; + } + + keyPress(ev: KeyboardEvent) { + if (this.animaStartTime === undefined) { + this.animaStartTime = new Date().getTime(); + } + let startTime = new Date().getTime(); + let duration = (startTime - this.animaStartTime); + if (duration < this.animTime) duration = this.animTime + this.currentDuration = duration + if (this.isPress) return + this.isPress = true + switch (ev.key.toLocaleLowerCase()) { + case "w": + let animW = () => { + if (this.scale === 50) return; + this.range.startNS += (this.centerXPercentage * this.currentDuration * 2 * this.scale / this.p); + this.range.endNS -= ((1 - this.centerXPercentage) * this.currentDuration * 2 * this.scale / this.p); + this.fillX(); + this.draw(); + this.pressFrameId = requestAnimationFrame(animW) + } + this.pressFrameId = requestAnimationFrame(animW) + break; + case "s": + let animS = () => { + if (this.range.startNS <= 0 && this.range.endNS >= this.range.totalNS) return; + this.range.startNS -= (this.centerXPercentage * this.currentDuration * 2 * this.scale / this.p); + this.range.endNS += ((1 - this.centerXPercentage) * this.currentDuration * 2 * this.scale / this.p); + this.fillX(); + this.draw(); + this.pressFrameId = requestAnimationFrame(animS) + } + this.pressFrameId = requestAnimationFrame(animS) + break; + case "a": + let animA = () => { + if (this.range.startNS == 0) return; + let s = this.scale / this.p * this.currentDuration; + this.range.startNS -= s; + this.range.endNS -= s; + this.fillX(); + this.draw(); + this.pressFrameId = requestAnimationFrame(animA) + } + this.pressFrameId = requestAnimationFrame(animA) + break; + case "d": + let animD = () => { + if (this.range.endNS >= this.range.totalNS) return; + this.range.startNS += this.scale / this.p * this.currentDuration; + this.range.endNS += this.scale / this.p * this.currentDuration; + this.fillX(); + this.draw(); + this.pressFrameId = requestAnimationFrame(animD) + } + this.pressFrameId = requestAnimationFrame(animD) + break; + } + } + + keyUp(ev: KeyboardEvent) { + this.animaStartTime = undefined; + this.isPress = false + if (this.pressFrameId != -1) { + cancelAnimationFrame(this.pressFrameId) + } + let startTime = new Date().getTime(); + switch (ev.key) { + case "w": + let animW = () => { + if (this.scale === 50) return; + let dur = (new Date().getTime() - startTime); + this.range.startNS += (this.centerXPercentage * 100 * this.scale / this.p); + this.range.endNS -= ((1 - this.centerXPercentage) * 100 * this.scale / this.p); + this.fillX(); + this.draw(); + if (dur < 200) { + requestAnimationFrame(animW) + } + } + requestAnimationFrame(animW) + break; + case "s": + let animS = () => { + if (this.range.startNS <= 0 && this.range.endNS >= this.range.totalNS) return; + let dur = (new Date().getTime() - startTime); + this.range.startNS -= (this.centerXPercentage * 100 * this.scale / this.p); + this.range.endNS += ((1 - this.centerXPercentage) * 100 * this.scale / this.p); + this.fillX(); + this.draw(); + if (dur < 200) { + requestAnimationFrame(animS) + } + } + requestAnimationFrame(animS) + break; + case "a": + let animA = () => { + if (this.range.startNS <= 0) return + let dur = (new Date().getTime() - startTime); + let s = this.scale * 80 / this.p; + this.range.startNS -= s; + this.range.endNS -= s; + this.fillX(); + this.draw(); + if (dur < 200) { + requestAnimationFrame(animA) + } + } + animA(); + break; + case "d": + let animD = () => { + if (this.range.endNS >= this.range.totalNS) return; + let dur = (new Date().getTime() - startTime); + let s = this.scale * 80 / this.p; + this.range.startNS += s; + this.range.endNS += s; + this.fillX(); + this.draw(); + if (dur < 200) { + requestAnimationFrame(animD) + } + } + animD(); + break; + } + } +} diff --git a/host/ide/src/trace/component/trace/timer-shaft/Rect.ts b/host/ide/src/trace/component/trace/timer-shaft/Rect.ts new file mode 100644 index 0000000000000000000000000000000000000000..1197ec56c284692d28d71c7d47ba3872d321a08a --- /dev/null +++ b/host/ide/src/trace/component/trace/timer-shaft/Rect.ts @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class Rect { + x: number = 0 + y: number = 0 + width: number = 0 + height: number = 0 + + constructor(x: number, y: number, width: number, height: number) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + static contains(rect: Rect, x: number, y: number): boolean { + return rect.x <= x && x <= rect.x + rect.width && rect.y <= y && y <= rect.y + rect.height; + } + + static containsWithPadding(rect: Rect, x: number, y: number, paddingLeftRight: number, paddingTopBottom: number): boolean { + return rect.x + paddingLeftRight <= x + && x <= rect.x + rect.width - paddingLeftRight + && rect.y + paddingTopBottom <= y + && y <= rect.y + rect.height - paddingTopBottom; + } + + static containsWithMargin(rect: Rect, x: number, y: number, t: number, r: number, b: number, l: number): boolean { + return rect.x - l <= x + && x <= rect.x + rect.width + r + && rect.y - t <= y + && y <= rect.y + rect.height + b; + } + + static intersect(r1: Rect, rect: Rect): boolean { + let maxX = r1.x + r1.width > rect.x + rect.width ? r1.x + r1.width : rect.x + rect.width; + let maxY = r1.y + r1.height > rect.y + rect.height ? r1.y + r1.height : rect.y + rect.height; + let minX = r1.x < rect.x ? r1.x : rect.x; + let minY = r1.y < rect.y ? r1.y : rect.y; + if (maxX - minX < rect.width + r1.width && maxY - minY < r1.height + rect.height) { + return true; + } else { + return false; + } + } + + contains(x: number, y: number): boolean { + return this.x <= x && x <= this.x + this.width && this.y <= y && y <= this.y + this.height; + } + + containsWithPadding(x: number, y: number, paddingLeftRight: number, paddingTopBottom: number): boolean { + return this.x + paddingLeftRight <= x + && x <= this.x + this.width - paddingLeftRight + && this.y + paddingTopBottom <= y + && y <= this.y + this.height - paddingTopBottom; + } + + containsWithMargin(x: number, y: number, t: number, r: number, b: number, l: number): boolean { + return this.x - l <= x + && x <= this.x + this.width + r + && this.y - t <= y + && y <= this.y + this.height + b; + } + + /** + * 判断是否相交 + * @param rect + */ + intersect(rect: Rect): boolean { + let maxX = this.x + this.width >= rect.x + rect.width ? this.x + this.width : rect.x + rect.width; + let maxY = this.y + this.height >= rect.y + rect.height ? this.y + this.height : rect.y + rect.height; + let minX = this.x <= rect.x ? this.x : rect.x; + let minY = this.y <= rect.y ? this.y : rect.y; + if (maxX - minX <= rect.width + this.width && maxY - minY <= this.height + rect.height) { + return true; + } else { + return false; + } + } +} + +export class Point { + x: number = 0 + y: number = 0 + + constructor(x: number, y: number) { + this.x = x; + this.y = y; + } +} diff --git a/host/ide/src/trace/component/trace/timer-shaft/SportRuler.ts b/host/ide/src/trace/component/trace/timer-shaft/SportRuler.ts new file mode 100644 index 0000000000000000000000000000000000000000..ac43c903e494a2a8a152cae61103ba18ab84835a --- /dev/null +++ b/host/ide/src/trace/component/trace/timer-shaft/SportRuler.ts @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {Graph} from "./Graph.js"; +import {Rect} from "./Rect.js"; +import {TimeRange} from "./RangeRuler.js"; +import {Flag} from "./Flag.js"; +import {ns2s, ns2x, randomRgbColor, TimerShaftElement} from "../TimerShaftElement.js"; +import {TraceRow} from "../base/TraceRow.js"; +import {SpApplication} from "../../../SpApplication.js"; + +export class SportRuler extends Graph { + public flagList: Array = []; + private hoverFlag: Flag = new Flag(0, 0, 0, 0, 0); + private lineColor: string | null = null; + private rulerW = 0; + private _range: TimeRange = {} as TimeRange; + private readonly notifyHandler: ((hoverFlag: Flag | undefined | null, selectFlag: Flag | undefined | null) => void) | undefined; + private readonly flagClickHandler: ((flag: Flag | undefined | null) => void) | undefined; + private invertedTriangleTime: number | null | undefined = null; + isRangeSelect: boolean = false;//region selection + constructor(timerShaftEL: TimerShaftElement, frame: Rect, notifyHandler: (hoverFlag: Flag | undefined | null, selectFlag: Flag | undefined | null) => void, flagClickHandler: (flag: Flag | undefined | null) => void) { + super(timerShaftEL.canvas, timerShaftEL.ctx!, frame) + this.notifyHandler = notifyHandler; + this.flagClickHandler = flagClickHandler; + } + + get range(): TimeRange { + return this._range; + } + + set range(value: TimeRange) { + this._range = value; + this.draw() + } + + modifyFlagList(flag: Flag | null | undefined) { + if (flag) { + if (flag.hidden) { + let i = this.flagList.findIndex(it => it.time == flag.time) + this.flagList.splice(i, 1) + } else { + let i = this.flagList.findIndex(it => it.time == flag.time) + this.flagList[i] = flag; + } + } else { + this.flagList.forEach(it => it.selected = false); + } + this.draw(); + } + + draw(): void { + this.rulerW = this.canvas!.offsetWidth + this.c.clearRect(this.frame.x, this.frame.y, this.frame.width, this.frame.height+1) + this.c.beginPath(); + this.lineColor = window.getComputedStyle(this.canvas!, null).getPropertyValue("color"); + this.c.strokeStyle = this.lineColor //"#dadada" + this.c.lineWidth = 1; + this.c.moveTo(this.frame.x, this.frame.y) + this.c.lineTo(this.frame.x + this.frame.width, this.frame.y) + this.c.stroke(); + this.c.closePath(); + this.c.beginPath(); + this.c.lineWidth = 3; + this.c.strokeStyle = "#999999" + this.c.moveTo(this.frame.x, this.frame.y) + this.c.lineTo(this.frame.x, this.frame.y + this.frame.height) + this.c.stroke(); + this.c.closePath(); + this.c.beginPath(); + this.c.lineWidth = 1; + this.c.strokeStyle = this.lineColor;//"#999999" + this.c.fillStyle = '#999999' + this.c.font = '8px sans-serif' + this.range.xs?.forEach((it, i) => { + this.c.moveTo(it, this.frame.y) + this.c.lineTo(it, this.frame.y + this.frame.height) + this.c.fillText(`+${this.range.xsTxt[i]}`, it + 3, this.frame.y + 12) + }) + this.c.stroke(); + this.c.closePath(); + //绘制旗子 + this.flagList.forEach((flagObj: Flag, b) => { + if (flagObj.time >= this.range.startNS && flagObj.time <= this.range.endNS) { + flagObj.x = Math.round(this.rulerW * (flagObj.time - this.range.startNS) / (this.range.endNS - this.range.startNS)); + this.drawFlag(flagObj.x, flagObj.color, flagObj.selected, flagObj.text, flagObj.type) + } + }) + !this.hoverFlag.hidden && this.drawFlag(this.hoverFlag.x, this.hoverFlag.color, true, this.hoverFlag.text) + //If region selection is enabled, the serial number draws a line on the axis to show the length of the box selection + if (this.isRangeSelect) { + let range = TraceRow.rangeSelectObject; + this.c.beginPath(); + if (document.querySelector("sp-application")!.dark) { + this.c.strokeStyle = "#FFF" + this.c.fillStyle = "#FFF" + } else { + this.c.strokeStyle = "#000" + this.c.fillStyle = "#000" + } + let startX = ns2x(range?.startNS || 0, this.range.startNS, this.range.endNS, this.range.totalNS, this.frame); + let endX = ns2x(range?.endNS || 0, this.range.startNS, this.range.endNS, this.range.totalNS, this.frame); + let lineWidth = endX - startX; + let txt = ns2s((range?.endNS || 0) - (range?.startNS || 0)); + this.c.moveTo(startX, this.frame.y + 22); + this.c.lineTo(endX, this.frame.y + 22); + this.c.moveTo(startX, this.frame.y + 22 - 5); + this.c.lineTo(startX, this.frame.y + 22 + 5); + this.c.moveTo(endX, this.frame.y + 22 - 5); + this.c.lineTo(endX, this.frame.y + 22 + 5); + let txtWidth = this.c.measureText(txt).width; + if (lineWidth > txtWidth) { + this.c.fillText(`${txt}`, startX + (lineWidth - txtWidth) / 2, this.frame.y + 20) + } else { + if (endX + txtWidth >= this.frame.width) { + this.c.fillText(`${txt}`, startX - 5 - txtWidth, this.frame.y + 20) + } else { + this.c.fillText(`${txt}`, endX + 5, this.frame.y + 20) + } + } + this.c.stroke(); + this.c.closePath(); + } + if (this.invertedTriangleTime != null && typeof (this.invertedTriangleTime) != undefined) { + this.drawInvertedTriangle(this.invertedTriangleTime,document.querySelector("sp-application")!.dark?"#FFFFFF":"#000000") + } + } + + drawTriangle(time: number, type: string) { + if (time != null && typeof (time) != undefined) { + let i = this.flagList.findIndex(it => it.time == time); + if (type == "triangle") { + let triangle = this.flagList.findIndex(it => it.type == type); + if (i !== -1) { + if (triangle !== -1) { + this.flagList[i].type == "" ? this.flagList.splice(triangle, 1) : "" + } + this.flagList.forEach(it => it.selected = false) + this.flagList[i].selected = true; + + } else { + if (triangle == -1) { + this.flagList.forEach(it => it.selected = false) + this.flagList.push(new Flag(0, 125, 18, 18, time, randomRgbColor(), true, "triangle")); + } else { + this.flagList.forEach(it => it.selected = false) + this.flagList[triangle].time = time; + this.flagList[triangle].selected = true; + } + } + } else if (type == "square") { + if (i != -1) { + this.flagList[i].type = ""; + } + } else if (type == "inverted") { + this.invertedTriangleTime = time + } + this.draw(); + this.notifyHandler && this.notifyHandler( + !this.hoverFlag.hidden ? this.hoverFlag : null, + this.flagList.find(it => it.selected) || null + ) + } + } + + removeTriangle(type:string){ + if (type == "inverted") { + this.invertedTriangleTime = null; + }else { + let i = this.flagList.findIndex(it => it.type == type) + if (i !== -1) { + this.flagList.splice(i, 1) + } + } + this.draw(); + this.notifyHandler && this.notifyHandler( + !this.hoverFlag.hidden ? this.hoverFlag : null, + this.flagList.find(it => it.selected) || null + ) + } + + drawInvertedTriangle(time: number, color: string = "#000000"){ + if (time != null && typeof (time) != undefined) { + let x = Math.round(this.rulerW * (time - this.range.startNS) / (this.range.endNS - this.range.startNS)); + this.c.beginPath(); + this.c.fillStyle = color; + this.c.strokeStyle = color; + this.c.moveTo(x-2, 142); + this.c.lineTo(x+2, 142); + this.c.lineTo(x, 145); + this.c.fill() + this.c.closePath() + this.c.stroke(); + } + } + + //绘制旗子 + drawFlag(x: number, color: string = "#999999", isFill: boolean = false, text: string = "", type: string = "") { + this.c.beginPath(); + this.c.fillStyle = color; + this.c.strokeStyle = color; + this.c.moveTo(x, 125); + if (type == "triangle") { + this.c.lineTo(x + 15, 131); + } else { + this.c.lineTo(x + 10, 125); + this.c.lineTo(x + 10, 127); + this.c.lineTo(x + 18, 127); + this.c.lineTo(x + 18, 137); + this.c.lineTo(x + 10, 137); + this.c.lineTo(x + 10, 135); + } + this.c.lineTo(x + 2, 135); + this.c.lineTo(x + 2, 142); + this.c.lineTo(x, 142); + this.c.closePath() + isFill && this.c.fill() + this.c.stroke(); + if (text !== "") { + this.c.font = "10px Microsoft YaHei" + const {width} = this.c.measureText(text); + this.c.fillStyle = 'rgba(255, 255, 255, 0.8)'; // + this.c.fillRect(x + 21, 132, width + 4, 12); + this.c.fillStyle = "black"; + this.c.fillText(text, x + 23, 142); + this.c.stroke(); + } + } + + mouseUp(ev: MouseEvent) { + if (this.edgeDetection(ev)) { + this.flagList.forEach(it => it.selected = false) + let x = ev.offsetX - (this.canvas?.offsetLeft || 0) + let findFlag = this.flagList.find(it => x >= it.x && x <= it.x + 18) + if (findFlag) { + findFlag.selected = true; + } else { + let flagAtRulerTime = Math.round((this.range.endNS - this.range.startNS) * x / this.rulerW) + if (flagAtRulerTime > 0 && (this.range.startNS + flagAtRulerTime) < this.range.endNS) { + this.flagList.push(new Flag(x, 125, 18, 18, flagAtRulerTime + this.range.startNS, randomRgbColor(), true)); + } + } + this.flagClickHandler && this.flagClickHandler(this.flagList.find(it => it.selected)); + } + } + + mouseMove(ev: MouseEvent) { + if (this.edgeDetection(ev)) { + let x = ev.offsetX - (this.canvas?.offsetLeft || 0) + let flg = this.flagList.find((it) => x >= it.x && x <= it.x + 18); + if (flg) { + this.hoverFlag.hidden = true; + } else { + this.hoverFlag.hidden = false; + this.hoverFlag.x = x; + this.hoverFlag.color = "#999999"; + } + } else { + this.hoverFlag.hidden = true; + } + this.draw(); + this.notifyHandler && this.notifyHandler( + !this.hoverFlag.hidden ? this.hoverFlag : null, + this.flagList.find(it => it.selected) || null + ) + } + + static isMouseInSportRuler = false; + + edgeDetection(ev: MouseEvent): boolean { + let x = ev.offsetX - (this.canvas?.offsetLeft || 0) + let y = ev.offsetY - (this.canvas?.offsetTop || 0) + SportRuler.isMouseInSportRuler = x > 0 && x < this.canvas!.offsetWidth && ev.offsetY - this.frame.y > 20 && ev.offsetY - this.frame.y < this.frame.height; + return SportRuler.isMouseInSportRuler; + } +} diff --git a/host/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts b/host/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts new file mode 100644 index 0000000000000000000000000000000000000000..e397fbe1585bf9b62d7dc1b301f494d51d7eca01 --- /dev/null +++ b/host/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseElement, element} from "../../../../base-ui/BaseElement.js"; +import {Flag} from "./Flag.js"; +import {ns2s} from "../TimerShaftElement.js"; + +@element('tabpane-flag') +export class TabPaneFlag extends BaseElement { + private flagListIdx: number | null = null; + private flag: Flag | null = null; + + initElements(): void { + this.shadowRoot?.querySelector("#color-input")?.addEventListener("change", (event: any) => { + if (this.flag) { + this.flag.color = event?.target.value + document.dispatchEvent(new CustomEvent('flag-change', {detail: this.flag})); + } + }); + this.shadowRoot?.querySelector("#text-input")?.addEventListener("keydown", (event: any) => { + if (event.keyCode == "13") { + if (this.flag) { + this.flag.text = event?.target.value + document.dispatchEvent(new CustomEvent('flag-change', {detail: this.flag})); + } + } + }); + this.shadowRoot?.querySelector("#remove-flag")?.addEventListener("click", (event: any) => { + if (this.flag) { + this.flag.hidden = true; + document.dispatchEvent(new CustomEvent('flag-change', {detail: this.flag})); + } + }); + } + + setFlagObj(flagObj: Flag) { + this.flag = flagObj; + this.shadowRoot!.querySelector("#color-input")!.value = flagObj.color; + this.shadowRoot!.querySelector("#text-input")!.value = flagObj.text; + this.shadowRoot!.querySelector("#flag-time")!.innerHTML = ns2s(flagObj.time) + } + + initHtml(): string { + return ` + +
+
Annotation at
+ + Change color: + +
+ `; + } + +} diff --git a/host/ide/src/trace/component/trace/timer-shaft/TimeRuler.ts b/host/ide/src/trace/component/trace/timer-shaft/TimeRuler.ts new file mode 100644 index 0000000000000000000000000000000000000000..a7ae0cc6726accac07ba45c7bd7c6b1aabdf30e0 --- /dev/null +++ b/host/ide/src/trace/component/trace/timer-shaft/TimeRuler.ts @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {Graph} from "./Graph.js"; +import {Rect} from "./Rect.js"; +import {ns2s, TimerShaftElement} from "../TimerShaftElement.js"; + +export class TimeRuler extends Graph { + totalNS: number + private stepSmall: number; + private step: number; + private stepNS: number; + + constructor(timerShaftEL: TimerShaftElement, frame: Rect, totalNS: number = 10_000_000_000) { + super(timerShaftEL.canvas, timerShaftEL.ctx!, frame) + this.totalNS = totalNS; + this.step = this.frame.width / 10; + this.stepSmall = this.frame.width / 100; + this.stepNS = this.totalNS / 10; + } + + draw() { + this.step = this.frame.width / 10; + this.stepSmall = this.frame.width / 100; + this.stepNS = this.totalNS / 10; + this.c.clearRect(this.frame.x, this.frame.y, this.frame.width, this.frame.height) + this.c.beginPath(); + this.c.strokeStyle = "#999" + this.c.lineWidth = 1; + for (let i = 0; i <= 10; i++) { + let x = Math.floor(i * this.step) + this.frame.x; + this.c.moveTo(x, 0); + this.c.lineTo(x, this.frame.height); + if (i == 10) break; + for (let j = 1; j < 10; j++) { + this.c.moveTo(x + Math.floor(j * this.stepSmall), 0); + this.c.lineTo(x + Math.floor(j * this.stepSmall), this.frame.height / 4); + } + this.c.fillStyle = '#999' + this.c.fillText(`${ns2s(i * this.stepNS)}`, x + 5, this.frame.height - 1) + } + this.c.stroke(); + this.c.closePath(); + } +} + + + diff --git a/host/ide/src/trace/database/Procedure.ts b/host/ide/src/trace/database/Procedure.ts new file mode 100644 index 0000000000000000000000000000000000000000..8793eafdc3fb95164ad9ec762b3e35ab9fc83de4 --- /dev/null +++ b/host/ide/src/trace/database/Procedure.ts @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class ProcedureThread extends Worker { + busy: boolean = false; + isCancelled: boolean = false; + id: number = -1; + taskMap: any = {}; + name: string | undefined + + uuid(): string { + // @ts-ignore + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)); + } + + queryFunc(type: string, args: any, transfer: any, handler: Function) { + this.busy = true; + let id = this.uuid(); + this.taskMap[id] = handler + let pam = { + id: id, + type: type, + params: args, + } + if (transfer) { + try { + this.postMessage(pam, [transfer]); + } catch (e: any) { + } + } else { + this.postMessage(pam); + } + } + + cancel() { + this.isCancelled = true; + this.terminate(); + } +} + +class ProcedurePool { + static cpuCount = Math.floor((window.navigator.hardwareConcurrency || 4) / 2); + maxThreadNumber: number = 1 + works: Array = [] + proxyRunningNum: any; + timelineChange: ((a: any) => void) | undefined | null = null; + cpusLen = ProcedurePool.build('cpu', 8); + freqLen = ProcedurePool.build('freq', 2); + processLen = ProcedurePool.build('process', 8); + // names = [...this.cpusLen, ...this.freqLen, ...this.processLen, ...this.memLen, ...this.threadLen, ...this.funcLen]; + names = [...this.cpusLen, ...this.processLen, ...this.freqLen]; + onComplete: Function | undefined;//任务完成回调 + + constructor(threadBuild: (() => ProcedureThread) | undefined = undefined) { + this.init(threadBuild); + } + + static build(name: string, len: number) { + return [...Array(len).keys()].map(it => `${name}${it}`) + } + + init(threadBuild: (() => ProcedureThread) | undefined = undefined) { + this.maxThreadNumber = this.names.length + for (let i = 0; i < this.maxThreadNumber; i++) { + this.newThread(); + } + } + + newThread() { + let thread: ProcedureThread = new ProcedureThread("trace/database/ProcedureWorker.js", {type: "module"}) + thread.name = this.names[this.works.length] + thread.onmessage = (event: MessageEvent) => { + thread.busy = false; + if ((event.data.type as string) == "timeline-range-changed") { + this.timelineChange && this.timelineChange(event.data.results); + thread.busy = false; + return; + } + if (Reflect.has(thread.taskMap, event.data.id)) { + if (event.data) { + let fun = thread.taskMap[event.data.id]; + if (fun) { + fun(event.data.results, event.data.hover); + } + Reflect.deleteProperty(thread.taskMap, event.data.id) + } + } + if (this.isIdle() && this.onComplete) { + this.onComplete(); + } + } + thread.onmessageerror = e => { + } + thread.onerror = e => { + } + thread.id = this.works.length + thread.busy = false + this.works?.push(thread) + return thread; + } + + close = () => { + for (let i = 0; i < this.works.length; i++) { + let thread = this.works[i]; + thread.terminate(); + } + this.works.length = 0; + } + + clearCache = () => { + for (let i = 0; i < this.works.length; i++) { + let thread = this.works[i]; + thread.queryFunc("clear", {}, undefined, () => { + }) + } + } + + submitWithName(name: string, type: string, args: any, transfer: any, handler: Function): ProcedureThread | undefined { + let noBusyThreads = this.works.filter(it => it.name === name); + let thread: ProcedureThread | undefined + if (noBusyThreads.length > 0) { //取第一个空闲的线程进行任务 + thread = noBusyThreads[0]; + thread!.queryFunc(type, args, transfer, handler) + } + return thread; + } + + isIdle() { + return this.works.every(it => !it.busy); + } +} + + +export const procedurePool = new ProcedurePool() \ No newline at end of file diff --git a/host/ide/src/trace/database/ProcedureWorker.ts b/host/ide/src/trace/database/ProcedureWorker.ts new file mode 100644 index 0000000000000000000000000000000000000000..0adeae3816bf762cc8097be118c7f31ab7cdde7a --- /dev/null +++ b/host/ide/src/trace/database/ProcedureWorker.ts @@ -0,0 +1,457 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {cpu, CpuStruct, WakeupBean} from "./ProcedureWorkerCPU.js"; +import {drawFlagLine, drawLines, ns2s, ns2x, Rect} from "./ProcedureWorkerCommon.js"; +import {CpuFreqStruct, freq} from "./ProcedureWorkerFreq.js"; +import {proc, ProcessStruct} from "./ProcedureWorkerProcess.js"; +import {mem, ProcessMemStruct} from "./ProcedureWorkerMem.js"; +import {thread, ThreadStruct} from "./ProcedureWorkerThread.js"; +import {func, FuncStruct} from "./ProcedureWorkerFunc.js"; +import {fps, FpsStruct} from "./ProcedureWorkerFPS.js"; +import {heap, HeapStruct} from "./ProcedureWorkerHeap.js"; +import {timeline} from "./ProcedureWorkerTimeline.js"; + +let dataList: any = {} +let dataFilter: any = {} +let canvasList: any = {} +let contextList: any = {} + +function drawSelection(context: any, params: any) { + if (params.isRangeSelect) { + params.rangeSelectObject!.startX = Math.floor(ns2x(params.rangeSelectObject!.startNS!, params.startNS, params.endNS, params.totalNS, params.frame)); + params.rangeSelectObject!.endX = Math.floor(ns2x(params.rangeSelectObject!.endNS!, params.startNS, params.endNS, params.totalNS, params.frame)); + if (context) { + context.globalAlpha = 0.5 + context.fillStyle = "#666666" + context.fillRect(params.rangeSelectObject!.startX!, params.frame.y, params.rangeSelectObject!.endX! - params.rangeSelectObject!.startX!, params.frame.height) + context.globalAlpha = 1 + } + } +} + +function drawWakeUp(context: CanvasRenderingContext2D | any, wake: WakeupBean | null, startNS: number, endNS: number, totalNS: number, frame: Rect, selectCpuStruct: CpuStruct | undefined = undefined, currentCpu: number | undefined = undefined) { + if (wake) { + let x1 = Math.floor(ns2x((wake.wakeupTime || 0), startNS, endNS, totalNS, frame)); + context.beginPath(); + context.lineWidth = 2; + context.fillStyle = "#000000"; + if (x1 > 0 && x1 < frame.x + frame.width) { + context.moveTo(x1, frame.y); + context.lineTo(x1, frame.y + frame.height); + if (currentCpu == wake.cpu) { + let centerY = Math.floor(frame.y + frame.height / 2); + context.moveTo(x1, centerY - 6); + context.lineTo(x1 + 4, centerY); + context.lineTo(x1, centerY + 6); + context.lineTo(x1 - 4, centerY); + context.lineTo(x1, centerY - 6); + context.fill(); + } + } + if (selectCpuStruct) { + let x2 = Math.floor(ns2x((selectCpuStruct.startTime || 0), startNS, endNS, totalNS, frame)); + let y = frame.y + frame.height - 10; + context.moveTo(x1, y); + context.lineTo(x2, y); + + let s = ns2s((selectCpuStruct.startTime || 0) - (wake.wakeupTime || 0)); + let distance = x2 - x1; + if (distance > 12) { + context.moveTo(x1, y); + context.lineTo(x1 + 6, y - 3); + context.moveTo(x1, y); + context.lineTo(x1 + 6, y + 3); + context.moveTo(x2, y); + context.lineTo(x2 - 6, y - 3); + context.moveTo(x2, y); + context.lineTo(x2 - 6, y + 3); + let measure = context.measureText(s); + let tHeight = measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent + let xStart = x1 + Math.floor(distance / 2 - measure.width / 2); + if (distance > measure.width + 4) { + context.fillStyle = "#ffffff" + context.fillRect(xStart - 2, y - 4 - tHeight, measure.width + 4, tHeight + 4); + context.font = "10px solid"; + context.fillStyle = "#000000"; + context.textBaseline = "bottom"; + context.fillText(s, xStart, y - 2); + } + + } + } + context.strokeStyle = "#000000"; + context.stroke(); + context.closePath(); + } +} + +self.onmessage = function (e: any) { + if ((e.data.type as string).startsWith("clear")) { + dataList = {}; + dataFilter = {}; + canvasList = {}; + contextList = {}; + // @ts-ignore + self.postMessage({ + id: e.data.id, + type: e.data.type, + results: null, + }); + return; + } + let res: any + if (e.data.params.list) { + dataList[e.data.type] = e.data.params.list; + dataFilter[e.data.type] = new Set(); + if (e.data.params.offscreen) { + canvasList[e.data.type] = e.data.params.offscreen; + contextList[e.data.type] = e.data.params.offscreen!.getContext('2d'); + contextList[e.data.type].scale(e.data.params.dpr, e.data.params.dpr); + } + } + if(!dataFilter[e.data.type]){ + dataFilter[e.data.type] = new Set(); + } + let canvas = canvasList[e.data.type]; + let context = contextList[e.data.type]; + let type = e.data.type as string; + let params = e.data.params; + let isRangeSelect = e.data.params.isRangeSelect; + let isHover = e.data.params.isHover; + let xs = e.data.params.xs; + let frame = e.data.params.frame; + let flagMoveInfo = e.data.params.flagMoveInfo; + let flagSelectedInfo = e.data.params.flagSelectedInfo; + let hoverX = e.data.params.hoverX; + let hoverY = e.data.params.hoverY; + let startNS = e.data.params.startNS; + let endNS = e.data.params.endNS; + let totalNS = e.data.params.totalNS; + let canvasWidth = e.data.params.canvasWidth; + let canvasHeight = e.data.params.canvasHeight; + let useCache = e.data.params.useCache; + let lineColor = e.data.params.lineColor; + let wakeupBean: WakeupBean | null = e.data.params.wakeupBean; + if (canvas) { + if (canvas.width !== canvasWidth || canvas.height !== canvasHeight) { + canvas.width = canvasWidth; + canvas.height = canvasHeight; + context.scale(e.data.params.dpr, e.data.params.dpr); + } + } + if (type.startsWith("timeline")) { + timeline(canvas, context, startNS, endNS, totalNS, frame, + e.data.params.keyPressCode, e.data.params.keyUpCode, + e.data.params.mouseDown, e.data.params.mouseUp, + e.data.params.mouseMove, e.data.params.mouseOut, + e.data.params.offsetLeft, e.data.params.offsetTop, + (a: any) => { + //@ts-ignore + self.postMessage({ + id: "timeline", + type: "timeline-range-changed", + results: a, + }); + } + ); + // @ts-ignore + self.postMessage({ + id: e.data.id, + type: type, + results: null, + }); + } else if (type.startsWith("cpu")) { + if (!useCache) { + cpu(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame); + } + if (canvas) { + context.clearRect(0, 0, canvas.width, canvas.height); + context.beginPath(); + drawLines(context, xs, frame.height, lineColor); + CpuStruct.hoverCpuStruct = undefined; + if (isHover) { + for (let re of dataFilter[e.data.type]) { + if (hoverX >= re.frame.x && hoverX <= re.frame.x + re.frame.width && hoverY >= re.frame.y && hoverY <= re.frame.y + re.frame.height) { + CpuStruct.hoverCpuStruct = re; + break; + } + } + } else { + CpuStruct.hoverCpuStruct = e.data.params.hoverCpuStruct; + } + CpuStruct.selectCpuStruct = e.data.params.selectCpuStruct; + for (let re of dataFilter[type]) { + CpuStruct.draw(context, re); + } + drawSelection(context, params); + context.closePath(); + drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); + let currentCpu = parseInt(type.replace("cpu", "")); + drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame, type == `cpu${CpuStruct.selectCpuStruct?.cpu || 0}` ? CpuStruct.selectCpuStruct : undefined, currentCpu); + } + // @ts-ignore + self.postMessage({ + id: e.data.id, + type: type, + results: canvas ? undefined : dataFilter[type], + hover: CpuStruct.hoverCpuStruct + }); + } else if (type.startsWith("fps")) { + if (!useCache) { + fps(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame); + } + if (canvas) { + context.clearRect(0, 0, canvas.width, canvas.height); + context.beginPath(); + drawLines(context, xs, frame.height, lineColor) + for (let re of dataFilter[type]) { + FpsStruct.draw(context, re) + } + drawSelection(context, params); + context.closePath(); + let maxFps = FpsStruct.maxFps + "FPS" + let textMetrics = context.measureText(maxFps); + context.globalAlpha = 0.8 + context.fillStyle = "#f0f0f0" + context.fillRect(0, 5, textMetrics.width + 8, 18) + context.globalAlpha = 1 + context.fillStyle = "#333" + context.textBaseline = "middle" + context.fillText(maxFps, 4, 5 + 9); + drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame); + drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); + } + // @ts-ignore + self.postMessage({id: e.data.id, type: type, results: canvas ? undefined : dataFilter[type], hover: undefined}); + } else if (type.startsWith("freq")) { + if (!useCache) { + freq(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame) + } + if (canvas) { + context.clearRect(0, 0, canvas.width, canvas.height); + context.beginPath(); + CpuFreqStruct.maxFreq = e.data.params.maxFreq; + CpuFreqStruct.maxFreqName = e.data.params.maxFreqName; + drawLines(context, xs, frame.height, lineColor) + CpuFreqStruct.hoverCpuFreqStruct = undefined; + if (isHover) { + for (let re of dataFilter[type]) { + if (hoverX >= re.frame.x && hoverX <= re.frame.x + re.frame.width && hoverY >= re.frame.y && hoverY <= re.frame.y + re.frame.height) { + CpuFreqStruct.hoverCpuFreqStruct = re; + break; + } + } + } else { + CpuFreqStruct.hoverCpuFreqStruct = e.data.params.hoverCpuFreqStruct; + } + CpuFreqStruct.selectCpuFreqStruct = e.data.params.selectCpuFreqStruct; + for (let re of dataFilter[type]) { + CpuFreqStruct.draw(context, re) + } + drawSelection(context, params); + context.closePath(); + let s = CpuFreqStruct.maxFreqName + let textMetrics = context.measureText(s); + context.globalAlpha = 0.8 + context.fillStyle = "#f0f0f0" + context.fillRect(0, 5, textMetrics.width + 8, 18) + context.globalAlpha = 1 + context.fillStyle = "#333" + context.textBaseline = "middle" + context.fillText(s, 4, 5 + 9) + drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame); + drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); + } + // @ts-ignore + self.postMessage({ + id: e.data.id, + type: type, + results: canvas ? undefined : dataFilter[type], + hover: CpuFreqStruct.hoverCpuFreqStruct + }); + } else if (type.startsWith("process")) { + if (!useCache) { + proc(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame) + } + if (canvas) { + context.clearRect(0, 0, canvas.width, canvas.height); + context.beginPath(); + CpuStruct.cpuCount = e.data.params.cpuCount; + drawLines(context, xs, frame.height, lineColor) + for (let re of dataFilter[type]) { + ProcessStruct.draw(context, re) + } + drawSelection(context, params); + drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame); + context.closePath(); + drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); + } + // @ts-ignore + self.postMessage({id: e.data.id, type: type, results: canvas ? undefined : dataFilter[type], hover: undefined}); + } else if (type.startsWith("heap")) { + if (!useCache) { + heap(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame); + } + if (canvas) { + context.clearRect(0, 0, canvas.width, canvas.height); + context.beginPath(); + drawLines(context, xs, frame.height, lineColor) + HeapStruct.hoverHeapStruct = undefined; + if (isHover) { + for (let re of dataFilter[e.data.type]) { + if (hoverX >= re.frame.x && hoverX <= re.frame.x + re.frame.width && hoverY >= re.frame.y && hoverY <= re.frame.y + re.frame.height) { + HeapStruct.hoverHeapStruct = re; + break; + } + } + } else { + HeapStruct.hoverHeapStruct = e.data.params.hoverHeapStruct; + } + // HeapStruct.selectHeapStruct = e.data.params.selectHeapStruct; + for (let re of dataFilter[type]) { + HeapStruct.draw(context, re) + } + drawSelection(context, params); + drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame); + context.closePath(); + drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); + } + // @ts-ignore + self.postMessage({ + id: e.data.id, + type: type, + results: canvas ? undefined : dataFilter[type], + hover: HeapStruct.hoverHeapStruct + }); + } else if (type.startsWith("mem")) { + if (!useCache) { + mem(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame) + } + if (canvas) { + context.clearRect(0, 0, canvas.width, canvas.height); + context.beginPath(); + drawLines(context, xs, frame.height, lineColor) + for (let re of dataFilter[type]) { + ProcessMemStruct.draw(context, re) + } + drawSelection(context, params); + drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame); + context.closePath(); + drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); + } + // @ts-ignore + self.postMessage({id: e.data.id, type: type, results: canvas ? undefined : dataFilter[type], hover: undefined}); + } else if (type.startsWith("thread")) { + if (!useCache) { + thread(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame) + } + if (canvas) { + context.clearRect(0, 0, canvas.width, canvas.height); + context.beginPath(); + drawLines(context, xs, frame.height, lineColor) + ThreadStruct.hoverThreadStruct = undefined; + if (isHover) { + for (let re of dataFilter[e.data.type]) { + if (hoverX >= re.frame.x && hoverX <= re.frame.x + re.frame.width && hoverY >= re.frame.y && hoverY <= re.frame.y + re.frame.height) { + ThreadStruct.hoverThreadStruct = re; + break; + } + } + } else { + ThreadStruct.hoverThreadStruct = e.data.params.hoverThreadStruct; + } + ThreadStruct.selectThreadStruct = e.data.params.selectThreadStruct; + for (let re of dataFilter[type]) { + ThreadStruct.draw(context, re) + } + drawSelection(context, params); + drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame); + context.closePath(); + drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); + } + // @ts-ignore + self.postMessage({ + id: e.data.id, + type: type, + results: canvas ? undefined : dataFilter[type], + hover: ThreadStruct.hoverThreadStruct + }); + } else if (type.startsWith("func")) { + if (!useCache) { + func(dataList[type], dataFilter[type], startNS, endNS, totalNS, frame) + } + if (canvas) { + if (canvas.height == 150) { + canvas.width = frame.width; + canvas.height = e.data.params.maxHeight; + context.scale(e.data.params.dpr, e.data.params.dpr); + } + // canvasList[type]!.width = frame.width; + // canvasList[type]!.height = frame.height; + context.clearRect(0, 0, canvas.width, canvas.height); + context.beginPath(); + drawLines(context, xs, frame.height, lineColor) + FuncStruct.hoverFuncStruct = undefined; + if (isHover) { + for (let re of dataFilter[type]) { + if (re.dur && re.dur > 0 && hoverX >= re.frame.x && hoverX <= re.frame.x + re.frame.width && hoverY >= re.frame.y + (re.depth * 20) && hoverY <= re.frame.y + re.frame.height + (re.depth * 20)) { + FuncStruct.hoverFuncStruct = re; + break; + } + } + } else { + FuncStruct.hoverFuncStruct = e.data.params.hoverFuncStruct; + } + FuncStruct.selectFuncStruct = e.data.params.selectFuncStruct; + for (let re of dataFilter[type]) { + FuncStruct.draw(context, re) + } + drawSelection(context, params); + drawWakeUp(context, wakeupBean, startNS, endNS, totalNS, frame); + context.closePath(); + drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); + } + // @ts-ignore + self.postMessage({ + id: e.data.id, + type: type, + results: canvas ? undefined : dataFilter[type], + hover: FuncStruct.hoverFuncStruct + }); + } else if (type.startsWith("native")) { + if (canvas) { + context.clearRect(0, 0, canvas.width, canvas.height); + context.beginPath(); + drawLines(context, xs, frame.height, lineColor) + drawSelection(context, params); + context.closePath(); + drawFlagLine(context, flagMoveInfo, flagSelectedInfo, startNS, endNS, totalNS, frame); + } + // @ts-ignore + self.postMessage({ + id: e.data.id, + type: type, + results: canvas ? undefined : dataFilter[type], + hover: ThreadStruct.hoverThreadStruct + }); + } +}; +self.onmessageerror = function (e: any) { +} + + + + diff --git a/host/ide/src/trace/database/ProcedureWorkerCPU.ts b/host/ide/src/trace/database/ProcedureWorkerCPU.ts new file mode 100644 index 0000000000000000000000000000000000000000..a0f22b246d0b4efc6767bcd1d2414c6f6e0a26ca --- /dev/null +++ b/host/ide/src/trace/database/ProcedureWorkerCPU.ts @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct, ColorUtils} from "./ProcedureWorkerCommon.js"; + +export function cpu(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { + res.clear(); + if (list) { + let pns = (endNS - startNS) / frame.width; + let y = frame.y + 5; + let height = frame.height - 10; + for (let i = 0, len = list.length; i < len; i++) { + let it = list[i]; + if ((it.startTime || 0) + (it.dur || 0) > startNS && (it.startTime || 0) < endNS) { + // setCpuFrame(list[i], 5, startNS, endNS, totalNS, frame) + if (!list[i].frame) { + list[i].frame = {}; + list[i].frame.y = y; + list[i].frame.height = height; + } + CpuStruct.setCpuFrame(list[i], pns, startNS, endNS, frame) + if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && ((list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0)))) { + + } else { + res.add(list[i]) + } + } + } + } +} + +export class CpuStruct extends BaseStruct { + static cpuCount: number = 1 //最大cpu数量 + static hoverCpuStruct: CpuStruct | undefined; + static selectCpuStruct: CpuStruct | undefined; + cpu: number | undefined + dur: number | undefined + end_state: string | undefined + id: number | undefined + name: string | undefined + priority: number | undefined + processCmdLine: string | undefined + processId: number | undefined + processName: string | undefined + schedId: number | undefined + startTime: number | undefined + tid: number | undefined + type: string | undefined + + // static setFrame(node: CpuStruct, padding: number, startNS: number, endNS: number, totalNS: number, frame: Rect) { + // let x1: number; + // let x2: number; + // if ((node.startTime || 0) < startNS) { + // x1 = 0; + // } else { + // x1 = ns2x((node.startTime || 0), startNS, endNS, totalNS, frame); + // } + // if ((node.startTime || 0) + (node.dur || 0) > endNS) { + // x2 = frame.width; + // } else { + // x2 = ns2x((node.startTime || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + // } + // let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; + // let rectangle: Rect = new Rect(Math.floor(x1), frame.y + padding, Math.ceil(getV), frame.height - padding * 2); + // node.frame = rectangle; + // node.isHover = false; + // } + + static draw(ctx: CanvasRenderingContext2D, data: CpuStruct) { + if (data.frame) { + let width = data.frame.width || 0; + if (data.processId === CpuStruct.hoverCpuStruct?.processId || !CpuStruct.hoverCpuStruct) { + ctx.fillStyle = ColorUtils.colorForTid((data.processId || 0) > 0 ? (data.processId || 0) : (data.tid || 0)) + } else { + ctx.fillStyle = "#e0e0e0" + } + ctx.fillRect(data.frame.x, data.frame.y, width, data.frame.height) + if (width > textPadding * 2) { + let process = `${(data.processName || "Process")} [${data.processId}]` + let thread = `${data.name || "Thread"} [${data.tid}]` + let processMeasure = ctx.measureText(process); + let threadMeasure = ctx.measureText(thread); + let processCharWidth = Math.round(processMeasure.width / process.length) + let threadCharWidth = Math.round(threadMeasure.width / thread.length) + ctx.fillStyle = "#ffffff" + let y = data.frame.height / 2 + data.frame.y; + if (processMeasure.width < width - textPadding * 2) { + let x1 = Math.floor(width / 2 - processMeasure.width / 2 + data.frame.x + textPadding) + ctx.textBaseline = "bottom"; + ctx.fillText(process, x1, y, width - textPadding * 2) + } else if (width - textPadding * 2 > processCharWidth * 4) { + let chatNum = (width - textPadding * 2) / processCharWidth; + let x1 = data.frame.x + textPadding + ctx.textBaseline = "bottom"; + ctx.fillText(process.substring(0, chatNum - 4) + '...', x1, y, width - textPadding * 2) + } + if (threadMeasure.width < width - textPadding * 2) { + ctx.textBaseline = "top"; + let x2 = Math.floor(width / 2 - threadMeasure.width / 2 + data.frame.x + textPadding) + ctx.fillText(thread, x2, y + 2, width - textPadding * 2) + } else if (width - textPadding * 2 > threadCharWidth * 4) { + let chatNum = (width - textPadding * 2) / threadCharWidth; + let x1 = data.frame.x + textPadding + ctx.textBaseline = "top"; + ctx.fillText(thread.substring(0, chatNum - 4) + '...', x1, y + 2, width - textPadding * 2) + } + } + if (CpuStruct.selectCpuStruct && CpuStruct.equals(CpuStruct.selectCpuStruct, data)) { + ctx.strokeStyle = '#232c5d' + ctx.lineWidth = 2 + ctx.strokeRect(data.frame.x, data.frame.y, width - 2, data.frame.height) + } + } + } + + static setCpuFrame(node: any, pns: number, startNS: number, endNS: number, frame: any) { + if ((node.startTime || 0) < startNS) { + node.frame.x = 0; + } else { + node.frame.x = Math.floor(((node.startTime || 0) - startNS) / pns); + } + if ((node.startTime || 0) + (node.dur || 0) > endNS) { + node.frame.width = frame.width - node.frame.x; + } else { + node.frame.width = Math.ceil(((node.startTime || 0) + (node.dur || 0) - startNS) / pns - node.frame.x); + } + if (node.frame.width < 1) { + node.frame.width = 1; + } + } + + static equals(d1: CpuStruct, d2: CpuStruct): boolean { + if (d1 && d2 && d1.cpu == d2.cpu && + d1.tid == d2.tid && + d1.processId == d2.processId && + d1.startTime == d2.startTime && + d1.dur == d2.dur) { + return true; + } else { + return false; + } + } +} + +export class WakeupBean { + wakeupTime: number | undefined + cpu: number | undefined + process: string | undefined + pid: number | undefined + thread: string | undefined + tid: number | undefined + schedulingLatency: number | undefined + schedulingDesc: string | undefined + +} + +const textPadding = 2; \ No newline at end of file diff --git a/host/ide/src/trace/database/ProcedureWorkerCommon.ts b/host/ide/src/trace/database/ProcedureWorkerCommon.ts new file mode 100644 index 0000000000000000000000000000000000000000..2672f456510da3415e74d4ebdd4dc8e61d7e84d9 --- /dev/null +++ b/host/ide/src/trace/database/ProcedureWorkerCommon.ts @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export function ns2s(ns: number): string { + let second1 = 1_000_000_000; // 1 second + let millisecond1 = 1_000_000; // 1 millisecond + let microsecond1 = 1_000; // 1 microsecond + let nanosecond1 = 1000.0; + let res; + if (ns >= second1) { + res = (ns / 1000 / 1000 / 1000).toFixed(1) + " s"; + } else if (ns >= millisecond1) { + res = (ns / 1000 / 1000).toFixed(1) + " ms"; + } else if (ns >= microsecond1) { + res = (ns / 1000).toFixed(1) + " μs"; + } else if (ns > 0) { + res = ns.toFixed(1) + " ns"; + } else { + res = ns.toFixed(1) + " s"; + } + return res; +} + +export function ns2x(ns: number, startNS: number, endNS: number, duration: number, rect: any) { + // @ts-ignore + // return _ns2x(ns,startNS,endNS,duration,rect.width); + if (endNS == 0) { + endNS = duration; + } + let xSize: number = (ns - startNS) * rect.width / (endNS - startNS); + if (xSize < 0) { + xSize = 0; + } else if (xSize > rect.width) { + xSize = rect.width; + } + return xSize; +} + +export class Rect { + x: number = 0 + y: number = 0 + width: number = 0 + height: number = 0 + + constructor(x: number, y: number, width: number, height: number) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + static contains(rect: Rect, x: number, y: number): boolean { + return rect.x <= x && x <= rect.x + rect.width && rect.y <= y && y <= rect.y + rect.height; + } + + static containsWithPadding(rect: Rect, x: number, y: number, paddingLeftRight: number, paddingTopBottom: number): boolean { + return rect.x + paddingLeftRight <= x + && x <= rect.x + rect.width - paddingLeftRight + && rect.y + paddingTopBottom <= y + && y <= rect.y + rect.height - paddingTopBottom; + } + + static containsWithMargin(rect: Rect, x: number, y: number, t: number, r: number, b: number, l: number): boolean { + return rect.x - l <= x + && x <= rect.x + rect.width + r + && rect.y - t <= y + && y <= rect.y + rect.height + b; + } + + static intersect(r1: Rect, rect: Rect): boolean { + let maxX = r1.x + r1.width >= rect.x + rect.width ? r1.x + r1.width : rect.x + rect.width; + let maxY = r1.y + r1.height >= rect.y + rect.height ? r1.y + r1.height : rect.y + rect.height; + let minX = r1.x <= rect.x ? r1.x : rect.x; + let minY = r1.y <= rect.y ? r1.y : rect.y; + if (maxX - minX <= rect.width + r1.width && maxY - minY <= r1.height + rect.height) { + return true; + } else { + return false; + } + } + + contains(x: number, y: number): boolean { + return this.x <= x && x <= this.x + this.width && this.y <= y && y <= this.y + this.height; + } + + containsWithPadding(x: number, y: number, paddingLeftRight: number, paddingTopBottom: number): boolean { + return this.x + paddingLeftRight <= x + && x <= this.x + this.width - paddingLeftRight + && this.y + paddingTopBottom <= y + && y <= this.y + this.height - paddingTopBottom; + } + + containsWithMargin(x: number, y: number, t: number, r: number, b: number, l: number): boolean { + return this.x - l <= x + && x <= this.x + this.width + r + && this.y - t <= y + && y <= this.y + this.height + b; + } + + /** + * 判断是否相交 + * @param rect + */ + intersect(rect: Rect): boolean { + let maxX = this.x + this.width >= rect.x + rect.width ? this.x + this.width : rect.x + rect.width; + let maxY = this.y + this.height >= rect.y + rect.height ? this.y + this.height : rect.y + rect.height; + let minX = this.x <= rect.x ? this.x : rect.x; + let minY = this.y <= rect.y ? this.y : rect.y; + if (maxX - minX <= rect.width + this.width && maxY - minY <= this.height + rect.height) { + return true; + } else { + return false; + } + } +} + +export class Point { + x: number = 0 + y: number = 0 + + constructor(x: number, y: number) { + this.x = x; + this.y = y; + } +} + +export class BaseStruct { + frame: Rect | undefined + isHover: boolean = false; +} + + +export class ColorUtils { + // public static GREY_COLOR:string = Color.getHSBColor(0, 0, 62); // grey + public static GREY_COLOR: string = "#f0f0f0" + /** + * Color array of all current columns + */ + public static MD_PALETTE: Array = [ + "#3391ff",// red + "#0076ff",// pink + "#66adff",// purple + "#2db3aa",// deep purple + "#008078",// indigo + "#73e6de",// blue + "#535da6",// light blue + "#38428c", // cyan + "#7a84cc",// teal + "#ff9201",// green + "#ff7500",// light green + "#ffab40",// lime + "#2db4e2",// amber 0xffc105 + "#0094c6", // orange + "#7cdeff",// deep orange + "#ffd44a", // brown + "#fbbf00",// blue gray + "#ffe593",// yellow 0xffec3d + ]; + public static FUNC_COLOR: Array = [ + "#3391ff", // purple + "#2db4e2", + "#2db3aa", // deep purple + "#ffd44a", + "#535da6", // indigo + "#008078", // blue + "#ff9201", + "#38428c"]; + + /** + * Get the color value according to the length of the string + * + * @param str str + * @param max max + * @return int + */ + public static hash(str: string, max: number): number { + let colorA: number = 0x811c9dc5; + let colorB: number = 0xfffffff; + let colorC: number = 16777619; + let colorD: number = 0xffffffff; + let hash: number = colorA & colorB; + + for (let index: number = 0; index < str.length; index++) { + hash ^= str.charCodeAt(index); + hash = (hash * colorC) & colorD; + } + return Math.abs(hash) % max; + } + + /** + * Get color according to tid + * + * @param tid tid + * @return Color + */ + public static colorForTid(tid: number): string { + let colorIdx: number = ColorUtils.hash(`${tid}`, ColorUtils.MD_PALETTE.length); + return ColorUtils.MD_PALETTE[colorIdx]; + } + + public static formatNumberComma(str: number): string { + let l = str.toString().split("").reverse(); + let t: string = ""; + for (let i = 0; i < l.length; i++) { + t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? "," : ""); + } + return t.split("").reverse().join("") + } +} + +export function drawLines(ctx: any, xs: Array, height: number, lineColor: string) { + if (ctx) { + ctx.lineWidth = 1; + // ctx.strokeStyle = window.getComputedStyle(this.rootEL!, null).getPropertyValue("border-bottom-color");//"#dadada" "#474e59";// + ctx.strokeStyle = lineColor || "#dadada"; + xs?.forEach(it => { + ctx.moveTo(Math.floor(it), 0) + ctx.lineTo(Math.floor(it), height) + }) + ctx.stroke(); + } +} + +export function drawFlagLine(ctx: any, hoverFlag: any, selectFlag: any, startNS: number, endNS: number, totalNS: number, frame: any) { + if (ctx) { + if (hoverFlag) { + ctx.beginPath(); + ctx.lineWidth = 2; + ctx.strokeStyle = hoverFlag?.color || "#dadada"; + ctx.moveTo(Math.floor(hoverFlag.x), 0) + ctx.lineTo(Math.floor(hoverFlag.x), frame.height) + ctx.stroke(); + ctx.closePath(); + } + if (selectFlag) { + ctx.beginPath(); + ctx.lineWidth = 2; + ctx.strokeStyle = selectFlag?.color || "#dadada"; + selectFlag.x = ns2x(selectFlag.time, startNS, endNS, totalNS, frame); + ctx.moveTo(Math.floor(selectFlag.x), 0) + ctx.lineTo(Math.floor(selectFlag.x), frame.height) + ctx.stroke(); + ctx.closePath(); + } + } +} + diff --git a/host/ide/src/trace/database/ProcedureWorkerFPS.ts b/host/ide/src/trace/database/ProcedureWorkerFPS.ts new file mode 100644 index 0000000000000000000000000000000000000000..48bb896313a1e31d514f9a9bd9e46f31ae28e48f --- /dev/null +++ b/host/ide/src/trace/database/ProcedureWorkerFPS.ts @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct, ns2x, Rect} from "./ProcedureWorkerCommon.js"; + +export function fps(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { + res.clear(); + FpsStruct.maxFps = 0 + if (list) { + for (let i = 0, len = list.length; i < len; i++) { + let it = list[i]; + if ((it.fps || 0) > FpsStruct.maxFps) { + FpsStruct.maxFps = it.fps || 0 + } + if (i === list.length - 1) { + it.dur = (endNS || 0) - (it.startNS || 0) + } else { + it.dur = (list[i + 1].startNS || 0) - (it.startNS || 0) + } + if ((it.startNS || 0) + (it.dur || 0) > (startNS) && (it.startNS || 0) < (endNS)) { + FpsStruct.setFrame(list[i], 5, startNS, endNS, totalNS, frame) + if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { + + } else { + res.add(list[i]) + } + } + } + } +} + +export class FpsStruct extends BaseStruct { + static maxFps: number = 0 + static maxFpsName: string = "0 FPS" + static hoverFpsStruct: FpsStruct | undefined; + static selectFpsStruct: FpsStruct | undefined; + fps: number | undefined + startNS: number | undefined = 0 + dur: number | undefined //自补充,数据库没有返回 + + static draw(ctx: CanvasRenderingContext2D, data: FpsStruct) { + if (data.frame) { + let width = data.frame.width || 0; + ctx.fillStyle = '#535da6' + ctx.strokeStyle = '#535da6' + if (data.startNS === FpsStruct.hoverFpsStruct?.startNS) { + ctx.lineWidth = 1; + ctx.globalAlpha = 0.6; + let drawHeight: number = ((data.fps || 0) * (data.frame.height || 0) * 1.0) / FpsStruct.maxFps; + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + ctx.beginPath() + ctx.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true) + ctx.fill() + ctx.globalAlpha = 1.0; + ctx.stroke(); + ctx.beginPath() + ctx.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight); + ctx.lineWidth = 3; + ctx.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight) + ctx.stroke(); + } else { + ctx.globalAlpha = 0.6; + ctx.lineWidth = 1; + let drawHeight: number = ((data.fps || 0) * (data.frame.height || 0) * 1.0) / FpsStruct.maxFps; + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + } + } + ctx.globalAlpha = 1.0; + ctx.lineWidth = 1; + } + + static setFrame(node: FpsStruct, padding: number, startNS: number, endNS: number, totalNS: number, frame: Rect) { + let x1: number, x2: number; + if ((node.startNS || 0) < startNS) { + x1 = 0; + } else { + x1 = ns2x((node.startNS || 0), startNS, endNS, totalNS, frame); + } + if ((node.startNS || 0) + (node.dur || 0) > endNS) { + x2 = frame.width; + } else { + x2 = ns2x((node.startNS || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; + let rectangle: Rect = new Rect(Math.floor(x1), Math.ceil(frame.y + padding), Math.ceil(getV), Math.floor(frame.height - padding * 2)); + node.frame = rectangle; + } +} + +const textPadding = 2; \ No newline at end of file diff --git a/host/ide/src/trace/database/ProcedureWorkerFreq.ts b/host/ide/src/trace/database/ProcedureWorkerFreq.ts new file mode 100644 index 0000000000000000000000000000000000000000..8a2097d2d5bfc0dbeb0bc6e38fb3a9df741ed92f --- /dev/null +++ b/host/ide/src/trace/database/ProcedureWorkerFreq.ts @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct, ColorUtils, ns2x} from "./ProcedureWorkerCommon.js"; + +export function freq(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { + res.clear(); + if (list) { + for (let i = 0, len = list.length; i < len; i++) { + let it = list[i]; + if (i === list.length - 1) { + it.dur = (endNS || 0) - (it.startNS || 0) + } else { + it.dur = (list[i + 1].startNS || 0) - (it.startNS || 0) + } + if ((it.startNS || 0) + (it.dur || 0) > (startNS || 0) && (it.startNS || 0) < (endNS || 0)) { + CpuFreqStruct.setFreqFrame(list[i], 5, startNS || 0, endNS || 0, totalNS || 0, frame) + if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { + + } else { + res.add(it) + } + } + } + } + +} + +export class CpuFreqStruct extends BaseStruct { + static maxFreq: number = 0 + static maxFreqName: string = "0 GHz" + static hoverCpuFreqStruct: CpuFreqStruct | undefined; + static selectCpuFreqStruct: CpuFreqStruct | undefined; + cpu: number | undefined + value: number | undefined + startNS: number | undefined + dur: number | undefined //自补充,数据库没有返回 + + static draw(ctx: CanvasRenderingContext2D, data: CpuFreqStruct) { + if (data.frame) { + let width = data.frame.width || 0; + let index = data.cpu || 0 + index += 2 + ctx.fillStyle = ColorUtils.colorForTid(index) + ctx.strokeStyle = ColorUtils.colorForTid(index) + if (data.startNS === CpuFreqStruct.hoverCpuFreqStruct?.startNS) { + ctx.lineWidth = 1; + ctx.globalAlpha = 0.6; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / CpuFreqStruct.maxFreq); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + ctx.beginPath() + ctx.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true) + ctx.fill() + ctx.globalAlpha = 1.0; + ctx.stroke(); + ctx.beginPath() + ctx.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight); + ctx.lineWidth = 3; + ctx.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight) + ctx.stroke(); + } else { + ctx.globalAlpha = 0.6; + ctx.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / CpuFreqStruct.maxFreq); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + } + } + ctx.globalAlpha = 1.0; + ctx.lineWidth = 1; + } + + static setFreqFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let x1: number, x2: number; + if ((node.startNS || 0) < startNS) { + x1 = 0; + } else { + x1 = ns2x((node.startNS || 0), startNS, endNS, totalNS, frame); + } + if ((node.startNS || 0) + (node.dur || 0) > endNS) { + x2 = frame.width; + } else { + x2 = ns2x((node.startNS || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(x1); + node.frame.y = frame.y + padding; + node.frame.width = Math.ceil(getV); + node.frame.height = Math.floor(frame.height - padding * 2); + } +} + +const textPadding = 2; \ No newline at end of file diff --git a/host/ide/src/trace/database/ProcedureWorkerFunc.ts b/host/ide/src/trace/database/ProcedureWorkerFunc.ts new file mode 100644 index 0000000000000000000000000000000000000000..773ff7bc0d00c16508f92be40ae1ff42543501b5 --- /dev/null +++ b/host/ide/src/trace/database/ProcedureWorkerFunc.ts @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct, ColorUtils, ns2x, Rect} from "./ProcedureWorkerCommon.js"; + +export function func(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { + res.clear(); + if (list) { + for (let i = 0, len = list.length; i < len; i++) { + let it = list[i]; + if ((it.startTs || 0) + (it.dur || 0) > (startNS || 0) && (it.startTs || 0) < (endNS || 0)) { + FuncStruct.setFuncFrame(list[i], 0, startNS || 0, endNS || 0, totalNS || 0, frame) + if (i > 0 && (list[i - 1].frame?.y || 0) == (list[i].frame?.y || 0) && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { + + } else { + res.add(list[i]) + } + } + } + } +} + +export class FuncStruct extends BaseStruct { + static hoverFuncStruct: FuncStruct | undefined; + static selectFuncStruct: FuncStruct | undefined; + argsetid: number | undefined // 53161 + depth: number | undefined // 0 + dur: number | undefined // 570000 + funName: string | undefined //"binder transaction" + id: number | undefined // 92749 + is_main_thread: number | undefined // 0 + parent_id: number | undefined // null + startTs: number | undefined // 9729867000 + threadName: string | undefined // "Thread-15" + tid: number | undefined // 2785 + track_id: number | undefined // 414 + + static setFuncFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let x1: number, x2: number; + if ((node.startTs || 0) < startNS) { + x1 = 0; + } else { + x1 = ns2x((node.startTs || 0), startNS, endNS, totalNS, frame); + } + if ((node.startTs || 0) + (node.dur || 0) > endNS) { + x2 = frame.width; + } else { + x2 = ns2x((node.startTs || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(x1); + node.frame.y = 0; + node.frame.width = Math.floor(getV); + node.frame.height = 20; + } + + static draw(ctx: CanvasRenderingContext2D, data: FuncStruct) { + if (data.frame) { + let isBinder = FuncStruct.isBinder(data); + if (data.dur == undefined || data.dur == null || data.dur == 0) { + } else { + ctx.fillStyle = ColorUtils.FUNC_COLOR[(data.funName?.length || 0) % ColorUtils.FUNC_COLOR.length] + let miniHeight = 20 + ctx.fillRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2) + if (data.frame.width > 10) { + ctx.fillStyle = "#fff" + FuncStruct.drawString(ctx, data.funName || '', 5, data.frame) + } + if (FuncStruct.isSelected(data)) { + ctx.strokeStyle = "#000" + ctx.lineWidth = 1 + ctx.strokeRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2) + } + } + } + } + + static drawString(ctx: CanvasRenderingContext2D, str: string, textPadding: number, frame: Rect): boolean { + let textMetrics = ctx.measureText(str); + let charWidth = Math.round(textMetrics.width / str.length) + if (textMetrics.width < frame.width - textPadding * 2) { + let x2 = Math.floor(frame.width / 2 - textMetrics.width / 2 + frame.x + textPadding) + ctx.fillText(str, x2, Math.floor(frame.y + frame.height / 2 + 2), frame.width - textPadding * 2) + return true; + } + if (frame.width - textPadding * 2 > charWidth * 4) { + let chatNum = (frame.width - textPadding * 2) / charWidth; + let x1 = frame.x + textPadding + ctx.fillText(str.substring(0, chatNum - 4) + '...', x1, Math.floor(frame.y + frame.height / 2 + 2), frame.width - textPadding * 2) + return true; + } + return false; + } + + static isSelected(data: FuncStruct): boolean { + return (FuncStruct.selectFuncStruct != undefined && + FuncStruct.selectFuncStruct.startTs == data.startTs && + FuncStruct.selectFuncStruct.depth == data.depth && + FuncStruct.selectFuncStruct.dur == data.dur && + FuncStruct.selectFuncStruct.funName == data.funName) + } + + static isBinder(data: FuncStruct): boolean { + if (data.funName != null && + ( + data.funName.toLowerCase().startsWith("binder transaction") + || data.funName.toLowerCase().startsWith("binder async") + || data.funName.toLowerCase().startsWith("binder reply") + ) + ) { + return true; + } else { + return false; + } + } +} + +const padding = 1; \ No newline at end of file diff --git a/host/ide/src/trace/database/ProcedureWorkerHeap.ts b/host/ide/src/trace/database/ProcedureWorkerHeap.ts new file mode 100644 index 0000000000000000000000000000000000000000..9a11b403c1df8dc3d9c4537310cda9a312d28ff9 --- /dev/null +++ b/host/ide/src/trace/database/ProcedureWorkerHeap.ts @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct, ns2x, Rect} from "./ProcedureWorkerCommon.js"; + +export function heap(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { + res.clear(); + if (list) { + for (let i = 0; i < list.length; i++) { + let it = list[i]; + if ((it.startTime || 0) + (it.dur || 0) > (startNS || 0) && (it.startTime || 0) < (endNS || 0)) { + HeapStruct.setFrame(list[i], 5, startNS || 0, endNS || 0, totalNS || 0, frame) + if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { + continue; + } else { + res.add(list[i]) + } + } + } + } +} + +export class HeapStruct extends BaseStruct { + static hoverHeapStruct: HeapStruct | undefined; + startTime: number | undefined + endTime: number | undefined + dur: number | undefined + heapsize: number | undefined + maxHeapSize: number = 0 + minHeapSize: number = 0 + + static setFrame(node: HeapStruct, padding: number, startNS: number, endNS: number, totalNS: number, frame: Rect) { + let x1: number, x2: number; + if ((node.startTime || 0) < startNS) { + x1 = 0; + } else { + x1 = ns2x((node.startTime || 0), startNS, endNS, totalNS, frame); + } + if ((node.startTime || 0) + (node.dur || 0) > endNS) { + x2 = frame.width; + } else { + // @ts-ignore + x2 = ns2x(node.startTime + node.dur, startNS, endNS, totalNS, frame); + } + let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; + let rectangle: Rect = new Rect(Math.floor(x1), Math.ceil(frame.y + padding), Math.ceil(getV), Math.floor(frame.height - padding * 2)); + node.frame = rectangle; + } + + static draw(ctx: CanvasRenderingContext2D, data: HeapStruct) { + if (data.frame) { + let width = data.frame.width || 0; + ctx.fillStyle = "#2db3aa" + ctx.strokeStyle = "#2db3aa" + if (data.startTime === HeapStruct.hoverHeapStruct?.startTime) { + ctx.lineWidth = 1; + ctx.globalAlpha = 0.6; + let drawHeight:number = 0; + if(data.minHeapSize < 0 ){ + drawHeight = Math.ceil((((data.heapsize || 0) - data.minHeapSize) * (data.frame.height || 0)) / (data.maxHeapSize - data.minHeapSize)); + }else{ + drawHeight = Math.ceil(((data.heapsize || 0) * (data.frame.height || 0)) / data.maxHeapSize); + } + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + ctx.beginPath() + ctx.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true) + ctx.fill() + ctx.globalAlpha = 1.0; + ctx.stroke(); + ctx.beginPath() + ctx.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight); + ctx.lineWidth = 3; + ctx.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight) + ctx.stroke(); + } else { + ctx.globalAlpha = 0.6; + ctx.lineWidth = 1; + let drawHeight: number = Math.ceil(((data.heapsize || 0) * (data.frame.height || 0)) / data.maxHeapSize); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + } + } + ctx.globalAlpha = 1.0; + ctx.lineWidth = 1; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/database/ProcedureWorkerMem.ts b/host/ide/src/trace/database/ProcedureWorkerMem.ts new file mode 100644 index 0000000000000000000000000000000000000000..1405ee962bb994c0ad6907013c6fe0561e92f85c --- /dev/null +++ b/host/ide/src/trace/database/ProcedureWorkerMem.ts @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct, ColorUtils, ns2x} from "./ProcedureWorkerCommon.js"; + +function setMemFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let x1: number; + let x2: number; + if ((node.startTime || 0) <= startNS) { + x1 = 0; + } else { + x1 = ns2x((node.startTime || 0), startNS, endNS, totalNS, frame); + } + if ((node.startTime || 0) + (node.duration || 0) >= endNS) { + x2 = frame.width; + } else { + x2 = ns2x((node.startTime || 0) + (node.duration || 0), startNS, endNS, totalNS, frame); + } + let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(x1); + node.frame.y = Math.floor(frame.y + padding); + node.frame.width = Math.ceil(getV); + node.frame.height = Math.floor(frame.height - padding * 2); +} + +export function mem(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { + res.clear(); + if (list) { + for (let i = 0, len = list.length; i < len; i++) { + let it = list[i]; + if ((it.startTime || 0) + (it.duration || 0) > startNS && (it.startTime || 0) < endNS) { + setMemFrame(list[i], 5, startNS, endNS, totalNS, frame) + if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { + + } else { + res.add(list[i]) + } + } + } + } +} + +export class ProcessMemStruct extends BaseStruct { + trackId: number | undefined + processName: string | undefined + pid: number | undefined + upid: number | undefined + trackName: string | undefined + + type: string | undefined + track_id: string | undefined + value: number | undefined + startTime: number | undefined + duration: number | undefined + maxValue: number | undefined + delta: number | undefined; + + static draw(ctx: CanvasRenderingContext2D, data: ProcessMemStruct) { + if (data.frame) { + let width = data.frame.width || 0; + ctx.fillStyle = ColorUtils.colorForTid(data.maxValue || 0) + ctx.strokeStyle = ColorUtils.colorForTid(data.maxValue || 0) + ctx.globalAlpha = 0.6; + ctx.lineWidth = 1; + let drawHeight: number = ((data.value || 0) * (data.frame.height || 0) * 1.0) / (data.maxValue || 1); + ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight) + } + ctx.globalAlpha = 1.0; + ctx.lineWidth = 1; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/database/ProcedureWorkerProcess.ts b/host/ide/src/trace/database/ProcedureWorkerProcess.ts new file mode 100644 index 0000000000000000000000000000000000000000..01669edf0aadec9ff2143c76bf87dce618035b36 --- /dev/null +++ b/host/ide/src/trace/database/ProcedureWorkerProcess.ts @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct, ColorUtils, ns2x} from "./ProcedureWorkerCommon.js"; +import {CpuStruct} from "./ProcedureWorkerCPU.js"; + +export function proc(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { + res.clear(); + if (list) { + for (let i = 0, len = list.length; i < len; i++) { + let it = list[i]; + if ((it.startTime || 0) + (it.dur || 0) > (startNS || 0) && (it.startTime || 0) < (endNS || 0)) { + ProcessStruct.setProcessFrame(list[i], 5, startNS || 0, endNS || 0, totalNS || 0, frame) + if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { + + } else { + res.add(list[i]) + } + } + } + } +} + +const padding = 1; + +export class ProcessStruct extends BaseStruct { + cpu: number | undefined + dur: number | undefined + id: number | undefined + pid: number | undefined + process: string | undefined + startTime: number | undefined + state: string | undefined + thread: string | undefined + tid: number | undefined + ts: number | undefined + type: string | undefined + utid: number | undefined + + static draw(ctx: CanvasRenderingContext2D, data: ProcessStruct) { + if (data.frame) { + let width = data.frame.width || 0; + ctx.fillStyle = ColorUtils.colorForTid(data.pid || 0) + let miniHeight = Math.round(data.frame.height / CpuStruct.cpuCount) + ctx.fillRect(data.frame.x, data.frame.y + (data.cpu || 0) * miniHeight + padding, data.frame.width, miniHeight - padding * 2) + } + } + + static setFrame(node: any, pns: number, startNS: number, endNS: number, frame: any) { + if ((node.startTime || 0) < startNS) { + node.frame.x = 0; + } else { + node.frame.x = Math.floor(((node.startTime || 0) - startNS) / pns); + } + if ((node.startTime || 0) + (node.dur || 0) > endNS) { + node.frame.width = frame.width - node.frame.x; + } else { + node.frame.width = Math.ceil(((node.startTime || 0) + (node.dur || 0) - startNS) / pns - node.frame.x); + } + if (node.frame.width < 1) { + node.frame.width = 1; + } + } + + static setProcessFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let x1: number; + let x2: number; + if ((node.startTime || 0) < startNS) { + x1 = 0; + } else { + x1 = ns2x((node.startTime || 0), startNS, endNS, totalNS, frame); + } + if ((node.startTime || 0) + (node.dur || 0) > endNS) { + x2 = frame.width; + } else { + x2 = ns2x((node.startTime || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(x1); + node.frame.y = Math.floor(frame.y + padding); + node.frame.width = Math.ceil(getV); + node.frame.height = Math.floor(frame.height - padding * 2); + } +} \ No newline at end of file diff --git a/host/ide/src/trace/database/ProcedureWorkerThread.ts b/host/ide/src/trace/database/ProcedureWorkerThread.ts new file mode 100644 index 0000000000000000000000000000000000000000..a285e7982af4cc05018df8adf1d568b3e25980b9 --- /dev/null +++ b/host/ide/src/trace/database/ProcedureWorkerThread.ts @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {BaseStruct, ns2x, Rect} from "./ProcedureWorkerCommon.js"; + +export function thread(list: Array, res: Set, startNS: number, endNS: number, totalNS: number, frame: any) { + res.clear(); + if (list) { + for (let i = 0, len = list.length; i < len; i++) { + let it = list[i]; + if ((it.startTime || 0) + (it.dur || 0) > startNS && (it.startTime || 0) < endNS) { + ThreadStruct.setThreadFrame(list[i], 5, startNS, endNS, totalNS, frame) + if (i > 0 && ((list[i - 1].frame?.x || 0) == (list[i].frame?.x || 0) && (list[i - 1].frame?.width || 0) == (list[i].frame?.width || 0))) { + + } else { + res.add(list[i]) + } + } + } + } +} + +const padding = 3; + +export class ThreadStruct extends BaseStruct { + static runningColor: string = "#467b3b"; + static rColor = "#a0b84d"; + static otherColor = "#673ab7"; + static uninterruptibleSleepColor = "#f19d38"; + static traceColor = "#0d47a1"; + static sColor = "#FBFBFB"; + static hoverThreadStruct: ThreadStruct | undefined; + static selectThreadStruct: ThreadStruct | undefined; + static statusMap: any = { + "D": "Uninterruptible Sleep", + "S": "Sleeping", + "R": "Runnable", + "Running": "Running", + "R+": "Runnable (Preempted)", + "DK": "Uninterruptible Sleep + Wake Kill", + "I": "Task Dead", + "T": "Traced", + "t": "Traced", + "X": "Exit (Dead)", + "Z": "Exit (Zombie)", + "K": "Wake Kill", + "W": "Waking", + "P": "Parked", + "N": "No Load" + } + hasSched: number | undefined;// 14724852000 + pid: number | undefined// 2519 + processName: string | undefined //null + threadName: string | undefined//"ACCS0" + tid: number | undefined //2716 + upid: number | undefined // 1 + utid: number | undefined // 1 + cpu: number | undefined // null + dur: number | undefined // 405000 + end_ts: number | undefined // null + id: number | undefined // 1 + is_main_thread: number | undefined // 0 + name: string | undefined // "ACCS0" + startTime: number | undefined // 58000 + start_ts: number | undefined // null + state: string | undefined // "S" + type: string | undefined // "thread" + + static setThreadFrame(node: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { + let x1: number; + let x2: number; + if ((node.startTime || 0) < startNS) { + x1 = 0; + } else { + x1 = ns2x((node.startTime || 0), startNS, endNS, totalNS, frame); + } + if ((node.startTime || 0) + (node.dur || 0) > endNS) { + x2 = frame.width; + } else { + x2 = ns2x((node.startTime || 0) + (node.dur || 0), startNS, endNS, totalNS, frame); + } + let getV: number = x2 - x1 <= 1 ? 1 : x2 - x1; + if (!node.frame) { + node.frame = {}; + } + node.frame.x = Math.floor(x1); + node.frame.y = frame.y + padding; + node.frame.width = Math.ceil(getV); + node.frame.height = 30 - padding * 2; + } + + static draw(ctx: CanvasRenderingContext2D, data: ThreadStruct) { + if (data.frame) { + ctx.globalAlpha = 1 + let stateText = data.state || ''; + if ("S" == data.state) { + ctx.fillStyle = ThreadStruct.sColor; + ctx.globalAlpha = 0.2; // transparency + ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) + ctx.globalAlpha = 1; // transparency + } else if ("R" == data.state || "R+" == data.state) { + ctx.fillStyle = ThreadStruct.rColor; + ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) + ctx.fillStyle = "#fff"; + data.frame.width > 4 && ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame); + } else if ("D" == data.state) { + ctx.fillStyle = ThreadStruct.uninterruptibleSleepColor; + ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) + ctx.fillStyle = "#fff"; + data.frame.width > 4 && ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame); + } else if ("Running" == data.state) { + ctx.fillStyle = ThreadStruct.runningColor; + ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) + ctx.fillStyle = "#fff"; + data.frame.width > 4 && ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame); + } else if("T" == data.state || "t" == data.state) { + ctx.fillStyle = ThreadStruct.traceColor; + ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) + ctx.fillStyle = "#fff"; + ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame); + } else { + ctx.fillStyle = ThreadStruct.otherColor; + ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) + ctx.fillStyle = "#fff"; + data.frame.width > 4 && ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame); + } + if (ThreadStruct.selectThreadStruct && ThreadStruct.equals(ThreadStruct.selectThreadStruct, data) && ThreadStruct.selectThreadStruct.state != "S") { + ctx.strokeStyle = '#232c5d' + ctx.lineWidth = 2 + ctx.strokeRect(data.frame.x, data.frame.y + padding, data.frame.width - 2, data.frame.height - padding * 2) + } + } + } + + static drawString(ctx: CanvasRenderingContext2D, str: string, textPadding: number, frame: Rect) { + let textMetrics = ctx.measureText(str); + let charWidth = Math.round(textMetrics.width / str.length) + if (textMetrics.width < frame.width - textPadding * 2) { + let x2 = Math.floor(frame.width / 2 - textMetrics.width / 2 + frame.x + textPadding) + ctx.textBaseline = "middle" + ctx.font = "8px sans-serif"; + ctx.fillText(str, x2, Math.floor(frame.y + frame.height / 2), frame.width - textPadding * 2) + return; + } + if (frame.width - textPadding * 2 > charWidth * 4) { + let chatNum = (frame.width - textPadding * 2) / charWidth; + let x1 = frame.x + textPadding + ctx.textBaseline = "middle" + ctx.font = "8px sans-serif"; + ctx.fillText(str.substring(0, chatNum - 4) + '...', x1, Math.floor(frame.y + frame.height / 2), frame.width - textPadding * 2) + return; + } + } + + static getEndState(state: string): string { + let statusMapElement = ThreadStruct.statusMap[state]; + if (statusMapElement) { + return statusMapElement + } else { + if ("" == statusMapElement || statusMapElement == null) { + return ""; + } + return "Unknown State"; + } + } + + static equals(d1: ThreadStruct, d2: ThreadStruct): boolean { + if (d1 && d2 && d1.cpu == d2.cpu && + d1.tid == d2.tid && + d1.state == d2.state && + d1.startTime == d2.startTime && + d1.dur == d2.dur) { + return true; + } else { + return false; + } + } +} \ No newline at end of file diff --git a/host/ide/src/trace/database/ProcedureWorkerTimeline.ts b/host/ide/src/trace/database/ProcedureWorkerTimeline.ts new file mode 100644 index 0000000000000000000000000000000000000000..4d9d47d50b62343664fea0303967cf35b5a69d87 --- /dev/null +++ b/host/ide/src/trace/database/ProcedureWorkerTimeline.ts @@ -0,0 +1,728 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {ns2s, Rect} from "./ProcedureWorkerCommon.js"; +import {CpuStruct} from "../bean/CpuStruct.js"; +import {ColorUtils} from "../component/trace/base/ColorUtils.js"; + +//绘制时间轴 +let timeRuler: TimeRuler | undefined; +let rangeRuler: RangeRuler | undefined; +let sportRuler: SportRuler | undefined; +let offsetTop: number = 0; +let offsetLeft: number = 0; + +// @ts-ignore +export function timeline(canvas: OffscreenCanvas, ctx: OffscreenCanvasRenderingContext2D, startNS: number, endNS: number, totalNS: number, frame: Rect, keyPressCode: any, keyUpCode: any, mouseDown: any, mouseUp: any, mouseMove: any, mouseOut: any, _offsetLeft: number, _offsetTop: number, changeHandler: Function) { + offsetLeft = _offsetLeft; + offsetTop = _offsetTop; + if (timeRuler == undefined) { + timeRuler = new TimeRuler(canvas, ctx, new Rect(0, 0, frame.width, 20), totalNS); + } + if (!sportRuler) { + sportRuler = new SportRuler(canvas, ctx, new Rect(0, 100.5, frame.width, frame.height - 100)); + } + if (!rangeRuler) { + rangeRuler = new RangeRuler(canvas, ctx!, new Rect(0, 25, frame.width, 75), { + startX: 0, + endX: frame.width, + startNS: 0, + endNS: totalNS, + totalNS: totalNS, + xs: [], + xsTxt: [] + }, (a) => { + if (sportRuler) { + sportRuler.range = a; + } + changeHandler(a); + }); + } + + rangeRuler.frame.width = frame.width; + sportRuler.frame.width = frame.width; + timeRuler.frame.width = frame.width; + if (keyPressCode) { + rangeRuler.keyPress(keyPressCode); + } else if (keyUpCode) { + rangeRuler.keyUp(keyUpCode); + } else if (mouseDown) { + rangeRuler.mouseDown(mouseDown); + } else if (mouseUp) { + rangeRuler.mouseUp(mouseUp); + } else if (mouseMove) { + rangeRuler.mouseMove(mouseMove); + } else if (mouseOut) { + rangeRuler.mouseOut(mouseOut); + } else { + timeRuler.draw(); + rangeRuler.draw(); + } +} + +export abstract class Graph { + // @ts-ignore + c: OffscreenCanvasRenderingContext2D; + // @ts-ignore + canvas: OffscreenCanvas | undefined | null; + frame: Rect; + + // @ts-ignore + protected constructor(canvas: OffscreenCanvas | undefined | null, c: OffscreenCanvasRenderingContext2D, frame: Rect) { + this.canvas = canvas; + this.frame = frame; + this.c = c; + } + + abstract draw(): void; +} + +export class TimeRuler extends Graph { + totalNS: number + private stepSmall: number; + private step: number; + private stepNS: number; + + // @ts-ignore + constructor(canvas: OffscreenCanvas | undefined | null, c: OffscreenCanvasRenderingContext2D, frame: Rect, totalNS: number = 10_000_000_000) { + super(canvas, c, frame) + this.totalNS = totalNS; + this.step = this.frame.width / 10; + this.stepSmall = this.frame.width / 100; + this.stepNS = this.totalNS / 10; + } + + draw() { + this.step = this.frame.width / 10; + this.stepSmall = this.frame.width / 100; + this.stepNS = this.totalNS / 10; + this.c.clearRect(this.frame.x, this.frame.y, this.frame.width, this.frame.height) + this.c.beginPath(); + this.c.strokeStyle = "#999" + this.c.lineWidth = 1; + for (let i = 0; i <= 10; i++) { + let x = Math.floor(i * this.step) + this.frame.x; + this.c.moveTo(x, 0); + this.c.lineTo(x, this.frame.height); + if (i == 10) break; + for (let j = 1; j < 10; j++) { + this.c.moveTo(x + Math.floor(j * this.stepSmall), 0); + this.c.lineTo(x + Math.floor(j * this.stepSmall), this.frame.height / 4); + } + this.c.fillStyle = '#999' + this.c.fillText(`${ns2s(i * this.stepNS)}`, x + 5, this.frame.height - 1) + } + this.c.stroke(); + this.c.closePath(); + } +} + +/** + * SportRuler + */ +export class SportRuler extends Graph { + public static rulerFlagObj: Flag | null = null; + public flagList: Array = []; + public flagListIdx: number | null = null + public obj = [{x: 3}, {x: 2}]; + lineColor: string | null = null; + private rangeFlag = new Flag(0, 0, 0, 0, 0); + private ruler_w = 1022; + private _range: TimeRange = {} as TimeRange; + + // @ts-ignore + constructor(canvas: OffscreenCanvas | undefined | null, c: OffscreenCanvasRenderingContext2D, frame: Rect) { + super(canvas, c, frame) + } + + get range(): TimeRange { + return this._range; + } + + set range(value: TimeRange) { + this._range = value; + this.draw() + } + + modifyFlagList(type: string, flag: any = {}) { + if (type == "amend") { + if (flag.text && this.flagListIdx !== null) { + this.flagList[this.flagListIdx].text = flag.text + } + if (flag.color && this.flagListIdx !== null) { + this.flagList[this.flagListIdx].color = flag.color + } + } else if (type == "remove") { + if (this.flagListIdx !== null) { + this.flagList.splice(this.flagListIdx, 1) + } + } + this.draw() + } + + draw(): void { + this.ruler_w = this.frame.width; + this.c.clearRect(this.frame.x, this.frame.y, this.frame.width, this.frame.height) + this.c.beginPath(); + this.lineColor = "#dadada"; + this.c.strokeStyle = this.lineColor //"#dadada" + this.c.lineWidth = 1; + this.c.moveTo(this.frame.x, this.frame.y) + this.c.lineTo(this.frame.x + this.frame.width, this.frame.y) + this.c.stroke(); + this.c.closePath(); + this.c.beginPath(); + this.c.lineWidth = 3; + this.c.strokeStyle = "#999999" + this.c.moveTo(this.frame.x, this.frame.y) + this.c.lineTo(this.frame.x, this.frame.y + this.frame.height) + this.c.stroke(); + this.c.closePath(); + this.c.beginPath(); + this.c.lineWidth = 1; + this.c.strokeStyle = this.lineColor;//"#999999" + this.c.fillStyle = '#999999' + this.c.font = '8px sans-serif' + this.range.xs?.forEach((it, i) => { + this.c.moveTo(it, this.frame.y) + this.c.lineTo(it, this.frame.y + this.frame.height) + this.c.fillText(`+${this.range.xsTxt[i]}`, it + 3, this.frame.y + 12) + }) + + this.c.stroke(); + this.c.closePath(); + } + + // drawTheFlag + drawTheFlag(x: number, color: string = "#999999", isFill: boolean = false, text: string = "") { + this.c.beginPath(); + this.c.fillStyle = color; + this.c.strokeStyle = color; + this.c.moveTo(x, 125); + this.c.lineTo(x + 10, 125); + this.c.lineTo(x + 10, 127); + this.c.lineTo(x + 18, 127); + this.c.lineTo(x + 18, 137); + this.c.lineTo(x + 10, 137); + this.c.lineTo(x + 10, 135); + this.c.lineTo(x + 2, 135); + this.c.lineTo(x + 2, 143); + this.c.lineTo(x, 143); + this.c.closePath() + if (isFill) { + this.c.fill() + } + this.c.stroke(); + + + if (text !== "") { + this.c.font = "10px Microsoft YaHei" + const {width} = this.c.measureText(text); + this.c.fillStyle = 'rgba(255, 255, 255, 0.8)'; // + this.c.fillRect(x + 21, 132, width + 4, 12); + this.c.fillStyle = "black"; + this.c.fillText(text, x + 23, 142); + this.c.stroke(); + } + } + + //随机生成十六位进制颜色 + randomRgbColor() { + const letters = '0123456789ABCDEF'; + let color = '#'; + for (let i = 0; i < 6; i++) { + color += letters[Math.floor(Math.random() * 16)] + } + return color; + } + + //鼠标点击绘画旗子、点击旗子 + mouseUp(ev: MouseEvent) { + } + + //选中的旗子 + onFlagRangeEvent(flagObj: Flag, idx: number) { + SportRuler.rulerFlagObj = flagObj; + this.flagListIdx = idx; + } + + //鼠标移动 绘画旗子 + mouseMove(ev: MouseEvent) { + let x = ev.offsetX - (offsetLeft || 0) + let y = ev.offsetY - (offsetTop || 0) + if (y >= 50 && y < 200) { + this.draw() + if (y >= 123 && y < 142 && x > 0) { + let onFlagRange = this.flagList.findIndex((flagObj: Flag) => { + let flag_x = Math.round(this.ruler_w * (flagObj.time - this.range.startNS) / (this.range.endNS - this.range.startNS)); + return (x >= flag_x && x <= flag_x + 18) + }); + } + } + } +} + +const markPadding = 5; + +export class Mark extends Graph { + name: string | undefined + inspectionFrame: Rect + private _isHover: boolean = false + + // @ts-ignore + constructor(canvas: OffscreenCanvas | undefined | null, name: string, c: OffscreenCanvasRenderingContext2D, frame: Rect) { + super(canvas, c, frame); + this.name = name; + this.inspectionFrame = new Rect(frame.x - markPadding, frame.y, frame.width + markPadding * 2, frame.height) + } + + get isHover(): boolean { + return this._isHover; + } + + set isHover(value: boolean) { + this._isHover = value; + } + + draw(): void { + this.c.beginPath(); + this.c.lineWidth = 7 + this.c.strokeStyle = '#999999' + this.c.moveTo(this.frame.x, this.frame.y); + this.c.lineTo(this.frame.x, this.frame.y + this.frame.height / 3) + this.c.stroke(); + this.c.lineWidth = 1 + this.c.strokeStyle = '#999999' + this.c.moveTo(this.frame.x, this.frame.y); + this.c.lineTo(this.frame.x, this.frame.y + this.frame.height) + this.c.stroke(); + this.c.closePath(); + } +} + +export interface TimeRange { + totalNS: number + startX: number + endX: number + startNS: number + endNS: number + xs: Array + xsTxt: Array +} + +export class RangeRuler extends Graph { + public rangeRect: Rect + public markA: Mark + public markB: Mark + public range: TimeRange; + mouseDownOffsetX = 0 + mouseDownMovingMarkX = 0 + movingMark: Mark | undefined | null; + isMouseDown: boolean = false; + isMovingRange: boolean = false; + isNewRange: boolean = false; + markAX: number = 0; + markBX: number = 0; + isPress: boolean = false + pressFrameId: number = -1 + currentDuration: number = 0 + centerXPercentage: number = 0; + animaStartTime: number | undefined + animTime: number = 100; + p: number = 800; + private readonly notifyHandler: (r: TimeRange) => void; + private scale: number = 0; + //缩放级别 + private scales: Array = [50, 100, 200, 500, 1_000, 2_000, 5_000, 10_000, 20_000, 50_000, 100_000, 200_000, 500_000, + 1_000_000, 2_000_000, 5_000_000, 10_000_000, 20_000_000, 50_000_000, 100_000_000, 200_000_000, 500_000_000, + 1_000_000_000, 2_000_000_000, 5_000_000_000, 10_000_000_000, 20_000_000_000, 50_000_000_000, + 100_000_000_000, 200_000_000_000, 500_000_000_000]; + private _cpuUsage: Array<{ cpu: number, ro: number, rate: number }> = [] + + // @ts-ignore + constructor(canvas: OffscreenCanvas | undefined | null, c: OffscreenCanvasRenderingContext2D, frame: Rect, range: TimeRange, notifyHandler: (r: TimeRange) => void) { + super(canvas, c, frame) + this.range = range; + this.notifyHandler = notifyHandler; + this.markA = new Mark(canvas, 'A', c, new Rect(range.startX, frame.y, 1, frame.height)) + this.markB = new Mark(canvas, 'B', c, new Rect(range.endX, frame.y, 1, frame.height)) + this.rangeRect = new Rect(range.startX, frame.y, range.endX - range.startX, frame.height) + } + + set cpuUsage(value: Array<{ cpu: number, ro: number, rate: number }>) { + this._cpuUsage = value + this.draw(); + } + + drawCpuUsage() { + let maxNum = Math.round(this._cpuUsage.length / 100) + let miniHeight = Math.round(this.frame.height / CpuStruct.cpuCount);//每格高度 + let miniWidth = Math.ceil(this.frame.width / 100);//每格宽度 + for (let i = 0; i < this._cpuUsage.length; i++) { + //cpu: 0, ro: 0, rate: 0.987620037556431 + let it = this._cpuUsage[i] + this.c.fillStyle = ColorUtils.MD_PALETTE[it.cpu] + this.c.globalAlpha = it.rate + this.c.fillRect(this.frame.x + miniWidth * it.ro, this.frame.y + it.cpu * miniHeight, miniWidth, miniHeight) + } + } + + draw(discardNotify: boolean = false): void { + this.c.clearRect(this.frame.x - markPadding, this.frame.y, this.frame.width + markPadding * 2, this.frame.height) + this.c.beginPath(); + if (this._cpuUsage.length > 0) { + this.drawCpuUsage() + this.c.globalAlpha = 0; + } else { + this.c.globalAlpha = 1; + } + //绘制选中区域 + this.c.fillStyle = "#ffffff"; + this.rangeRect.x = this.markA.frame.x < this.markB.frame.x ? this.markA.frame.x : this.markB.frame.x + this.rangeRect.width = Math.abs(this.markB.frame.x - this.markA.frame.x) + this.c.fillRect(this.rangeRect.x, this.rangeRect.y, this.rangeRect.width, this.rangeRect.height) + this.c.globalAlpha = 1; + this.c.globalAlpha = .5; + this.c.fillStyle = "#999999" + this.c.fillRect(this.frame.x, this.frame.y, this.rangeRect.x, this.rangeRect.height) + this.c.fillRect(this.rangeRect.x + this.rangeRect.width, this.frame.y, this.frame.width - this.rangeRect.width, this.rangeRect.height) + this.c.globalAlpha = 1; + this.c.closePath(); + this.markA.draw(); + this.markB.draw(); + if (this.notifyHandler) { + this.range.startX = this.rangeRect.x + this.range.endX = this.rangeRect.x + this.rangeRect.width + this.range.startNS = this.range.startX * this.range.totalNS / (this.frame.width || 0) + this.range.endNS = this.range.endX * this.range.totalNS / (this.frame.width || 0) + let l20 = (this.range.endNS - this.range.startNS) / 20; + let min = 0; + let max = 0; + let weight = 0; + for (let index = 0; index < this.scales.length; index++) { + if (this.scales[index] > l20) { + if (index > 0) { + min = this.scales[index - 1]; + } else { + min = 0; + } + max = this.scales[index]; + weight = (l20 - min) * 1.0 / (max - min); + if (weight > 0.243) { + this.scale = max; + } else { + this.scale = min; + } + break; + } + } + if (this.scale == 0) { + this.scale = this.scales[0]; + } + let tmpNs = 0; + let yu = this.range.startNS % this.scale; + let realW = (this.scale * this.frame.width) / (this.range.endNS - this.range.startNS); + let startX = 0; + if (this.range.xs) { + this.range.xs.length = 0 + } else { + this.range.xs = [] + } + if (this.range.xsTxt) { + this.range.xsTxt.length = 0 + } else { + this.range.xsTxt = [] + } + if (yu != 0) { + let firstNodeWidth = ((this.scale - yu) / this.scale * realW); + startX += firstNodeWidth; + tmpNs += yu; + this.range.xs.push(startX) + this.range.xsTxt.push(ns2s(tmpNs)) + } + while (tmpNs < this.range.endNS - this.range.startNS) { + startX += realW; + tmpNs += this.scale; + this.range.xs.push(startX) + this.range.xsTxt.push(ns2s(tmpNs)) + } + if (!discardNotify) { + this.notifyHandler(this.range) + } + } + } + + mouseDown(ev: MouseEvent) { + let x = ev.offsetX - (offsetLeft || 0) + let y = ev.offsetY - (offsetTop || 0) + this.isMouseDown = true; + this.mouseDownOffsetX = x; + if (this.markA.isHover) { + this.movingMark = this.markA; + this.mouseDownMovingMarkX = this.movingMark.frame.x || 0 + } else if (this.markB.isHover) { + this.movingMark = this.markB; + this.mouseDownMovingMarkX = this.movingMark.frame.x || 0 + } else { + this.movingMark = null; + } + if (this.rangeRect.containsWithPadding(x, y, 5, 0)) { + this.isMovingRange = true; + this.markAX = this.markA.frame.x; + this.markBX = this.markB.frame.x; + } else if (this.frame.containsWithMargin(x, y, 20, 0, 0, 0) && !this.rangeRect.containsWithMargin(x, y, 0, markPadding, 0, markPadding)) { + this.isNewRange = true; + } + } + + mouseUp(ev: MouseEvent) { + this.isMouseDown = false; + this.isMovingRange = false; + this.isNewRange = false; + this.movingMark = null; + } + + mouseMove(ev: MouseEvent) { + let x = ev.offsetX - (offsetLeft || 0); + let y = ev.offsetY - (offsetTop || 0) + this.centerXPercentage = x / (this.frame.width || 0) + if (this.centerXPercentage <= 0) { + this.centerXPercentage = 0 + } else if (this.centerXPercentage >= 1) { + this.centerXPercentage = 1 + } + let maxX = this.frame.width || 0 + if (this.markA.inspectionFrame.contains(x, y)) { + this.markA.isHover = true + } else if (this.markB.inspectionFrame.contains(x, y)) { + this.markB.isHover = true; + } else { + this.markA.isHover = false; + this.markB.isHover = false; + } + if (this.movingMark) { + let result = x - this.mouseDownOffsetX + this.mouseDownMovingMarkX; + if (result >= 0 && result <= maxX) { + this.movingMark.frame.x = result + } else if (result < 0) { + this.movingMark.frame.x = 0 + } else { + this.movingMark.frame.x = maxX + } + this.movingMark.inspectionFrame.x = this.movingMark.frame.x - markPadding + requestAnimationFrame(() => this.draw()); + } + if (this.isMovingRange && this.isMouseDown) { + let result = x - this.mouseDownOffsetX; + let mA = result + this.markAX + let mB = result + this.markBX + if (mA >= 0 && mA <= maxX) { + this.markA.frame.x = mA + } else if (mA < 0) { + this.markA.frame.x = 0 + } else { + this.markA.frame.x = maxX + } + this.markA.inspectionFrame.x = this.markA.frame.x - markPadding + if (mB >= 0 && mB <= maxX) { + this.markB.frame.x = mB; + } else if (mB < 0) { + this.markB.frame.x = 0 + } else { + this.markB.frame.x = maxX + } + this.markB.inspectionFrame.x = this.markB.frame.x - markPadding + requestAnimationFrame(() => this.draw()); + } else if (this.isNewRange) { + this.markA.frame.x = this.mouseDownOffsetX; + this.markA.inspectionFrame.x = this.mouseDownOffsetX - markPadding; + if (x >= 0 && x <= maxX) { + this.markB.frame.x = x; + } else if (x < 0) { + this.markB.frame.x = 0; + } else { + this.markB.frame.x = maxX; + } + this.markB.inspectionFrame.x = this.markB.frame.x - markPadding; + requestAnimationFrame(() => this.draw()); + } + } + + mouseOut(ev: MouseEvent) { + this.movingMark = null; + } + + fillX() { + if (this.range.startNS < 0) this.range.startNS = 0; + if (this.range.endNS < 0) this.range.endNS = 0; + if (this.range.endNS > this.range.totalNS) this.range.endNS = this.range.totalNS; + if (this.range.startNS > this.range.totalNS) this.range.startNS = this.range.totalNS; + this.range.startX = this.range.startNS * (this.frame.width || 0) / this.range.totalNS + this.range.endX = this.range.endNS * (this.frame.width || 0) / this.range.totalNS + this.markA.frame.x = this.range.startX + this.markA.inspectionFrame.x = this.markA.frame.x - markPadding + this.markB.frame.x = this.range.endX + this.markB.inspectionFrame.x = this.markB.frame.x - markPadding + } + + keyPress(ev: KeyboardEvent) { + if (this.animaStartTime === undefined) { + this.animaStartTime = new Date().getTime(); + } + let startTime = new Date().getTime(); + let duration = (startTime - this.animaStartTime); + if (duration < this.animTime) duration = this.animTime + this.currentDuration = duration + if (this.isPress) return + this.isPress = true + switch (ev.key.toLocaleLowerCase()) { + case "w": + let animW = () => { + if (this.scale === 50) return; + this.range.startNS += (this.centerXPercentage * this.currentDuration * 2 * this.scale / this.p); + this.range.endNS -= ((1 - this.centerXPercentage) * this.currentDuration * 2 * this.scale / this.p); + this.fillX(); + this.draw(); + this.pressFrameId = requestAnimationFrame(animW) + } + this.pressFrameId = requestAnimationFrame(animW) + break; + case "s": + let animS = () => { + if (this.range.startNS <= 0 && this.range.endNS >= this.range.totalNS) return; + this.range.startNS -= (this.centerXPercentage * this.currentDuration * 2 * this.scale / this.p); + this.range.endNS += ((1 - this.centerXPercentage) * this.currentDuration * 2 * this.scale / this.p); + this.fillX(); + this.draw(); + this.pressFrameId = requestAnimationFrame(animS) + } + this.pressFrameId = requestAnimationFrame(animS) + break; + case "a": + let animA = () => { + if (this.range.startNS == 0) return; + let s = this.scale / this.p * this.currentDuration; + this.range.startNS -= s; + this.range.endNS -= s; + this.fillX(); + this.draw(); + this.pressFrameId = requestAnimationFrame(animA) + } + this.pressFrameId = requestAnimationFrame(animA) + break; + case "d": + let animD = () => { + if (this.range.endNS >= this.range.totalNS) return; + this.range.startNS += this.scale / this.p * this.currentDuration; + this.range.endNS += this.scale / this.p * this.currentDuration; + this.fillX(); + this.draw(); + this.pressFrameId = requestAnimationFrame(animD) + } + this.pressFrameId = requestAnimationFrame(animD) + break; + } + } + + keyUp(ev: KeyboardEvent) { + this.animaStartTime = undefined; + this.isPress = false + if (this.pressFrameId != -1) { + cancelAnimationFrame(this.pressFrameId) + } + let startTime = new Date().getTime(); + switch (ev.key) { + case "w": + let animW = () => { + if (this.scale === 50) return; + let dur = (new Date().getTime() - startTime); + this.range.startNS += (this.centerXPercentage * 100 * this.scale / this.p); + this.range.endNS -= ((1 - this.centerXPercentage) * 100 * this.scale / this.p); + this.fillX(); + this.draw(); + if (dur < 300) { + requestAnimationFrame(animW) + } + } + requestAnimationFrame(animW) + break; + case "s": + let animS = () => { + if (this.range.startNS <= 0 && this.range.endNS >= this.range.totalNS) return; + let dur = (new Date().getTime() - startTime); + this.range.startNS -= (this.centerXPercentage * 100 * this.scale / this.p); + this.range.endNS += ((1 - this.centerXPercentage) * 100 * this.scale / this.p); + this.fillX(); + this.draw(); + if (dur < 300) { + requestAnimationFrame(animS) + } + } + requestAnimationFrame(animS) + break; + case "a": + let animA = () => { + if (this.range.startNS <= 0) return + let dur = (new Date().getTime() - startTime); + let s = this.scale * 80 / this.p; + this.range.startNS -= s; + this.range.endNS -= s; + this.fillX(); + this.draw(); + if (dur < 300) { + requestAnimationFrame(animA) + } + } + animA(); + break; + case "d": + let animD = () => { + if (this.range.endNS >= this.range.totalNS) return; + let dur = (new Date().getTime() - startTime); + let s = this.scale * 80 / this.p; + this.range.startNS += s; + this.range.endNS += s; + this.fillX(); + this.draw(); + if (dur < 300) { + requestAnimationFrame(animD) + } + } + animD(); + break; + } + } +} + +export class Flag { + x: number = 0 + y: number = 0 + width: number = 0 + height: number = 0 + time: number = 0 + color: string = "" + selected: boolean = false + text: string = "" + + constructor(x: number, y: number, width: number, height: number, time: number, color: string = "#999999", selected = false) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + this.time = time; + this.color = color; + this.selected = selected; + } +} \ No newline at end of file diff --git a/host/ide/src/trace/database/SqlLite.ts b/host/ide/src/trace/database/SqlLite.ts new file mode 100644 index 0000000000000000000000000000000000000000..3e49266ed2312ad5ec66644a424bc3683a278de2 --- /dev/null +++ b/host/ide/src/trace/database/SqlLite.ts @@ -0,0 +1,874 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import './sql-wasm.js' +import {CpuStruct} from "../bean/CpuStruct.js"; +import {CpuFreqStruct} from "../bean/CpuFreqStruct.js"; +import {ThreadStruct} from "../bean/ThreadStruct.js"; +import {ProcessMemStruct} from "../bean/ProcessMemStruct.js"; +import {Counter, Fps, SelectionData} from "../bean/BoxSelection.js"; +import {FuncStruct} from "../bean/FuncStruct.js"; +import {WakeUpTimeBean} from "../bean/WakeUpTimeBean.js"; +import {WakeupBean} from "../bean/WakeupBean.js"; +import {BinderArgBean} from "../bean/BinderArgBean.js"; +import {FpsStruct} from "../bean/FpsStruct.js"; +import {HeapBean} from "../bean/HeapBean.js"; +import {SPT, SPTChild, StateProcessThread} from "../bean/StateProcessThread.js"; +import {CpuUsage, Freq} from "../bean/CpuUsage.js"; +import {HeapStruct} from "../bean/HeapStruct.js"; +import {HeapTreeDataBean} from "../bean/HeapTreeDataBean.js"; +import { + NativeEventHeap, NativeHookMalloc, + NativeHookProcess, + NativeHookSampleQueryInfo, + NativeHookStatistics +} from "../bean/NativeHook.js"; + +class DbThread extends Worker { + busy: boolean = false; + isCancelled: boolean = false; + id: number = -1; + taskMap: any = {}; + cacheArray: Array = []; + + uuid(): string { + // @ts-ignore + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)); + } + + queryFunc(name: string, sql: string, args: any, handler: Function) { + this.busy = true; + let id = this.uuid(); + this.taskMap[id] = handler + this.postMessage({ + id: id, + name: name, + action: "exec", + sql: sql, + params: args, + }) + } + + dbOpen = async (): Promise<{ status: boolean, msg: string }> => { + return new Promise((resolve, reject) => { + let id = this.uuid(); + this.taskMap[id] = (res: any) => { + if (res.init) { + resolve({status: res.init, msg: res.msg}); + } else { + resolve({status: res.init, msg: res.msg}); + } + } + this.postMessage({ + id: id, + action: "open", + buffer: DbPool.sharedBuffer!, /*Optional. An ArrayBuffer representing an SQLite Database file*/ + }, [DbPool.sharedBuffer!]); + }) + } +} + +export class DbPool { + static sharedBuffer: ArrayBuffer | null = null; + maxThreadNumber: number = 0; + works: Array = []; + progress: Function | undefined | null; + num = Math.floor(Math.random() * 10 + 1) + 20; + init = async (type: string, threadBuild: (() => DbThread) | undefined = undefined) => { // wasm | server | sqlite + await this.close(); + if (type === "wasm") { + this.maxThreadNumber = 1; + } else if (type === "server") { + this.maxThreadNumber = 1; + } else if (type === "sqlite") { + this.maxThreadNumber = 1; + } else if (type === "duck") { + this.maxThreadNumber = 1; + } + for (let i = 0; i < this.maxThreadNumber; i++) { + let thread: DbThread + if (threadBuild) { + thread = threadBuild() + } else { + if (type === "wasm") { + thread = new DbThread("trace/database/TraceWorker.js") + } else if (type === "server") { + thread = new DbThread("trace/database/SqlLiteWorker.js") + } else if (type === "sqlite") { + thread = new DbThread("trace/database/SqlLiteWorker.js") + } + } + thread!.onmessage = (event: MessageEvent) => { + thread.busy = false; + if (Reflect.has(thread.taskMap, event.data.id)) { + if (event.data.results) { + let fun = thread.taskMap[event.data.id]; + if (fun) { + fun(event.data.results); + } + Reflect.deleteProperty(thread.taskMap, event.data.id); + } else if (Reflect.has(event.data, 'ready')) { + this.progress!("database opened", this.num + event.data.index) + } else if (Reflect.has(event.data, 'init')) { + this.progress!("database ready", 40) + let fun = thread.taskMap[event.data.id]; + if (fun) { + fun(event.data) + } + Reflect.deleteProperty(thread.taskMap, event.data.id) + } else { + let fun = thread.taskMap[event.data.id]; + if (fun) { + fun([]) + } + Reflect.deleteProperty(thread.taskMap, event.data.id) + } + + } + } + thread!.onmessageerror = e => { + } + thread!.onerror = e => { + } + thread!.id = i; + thread!.busy = false; + this.works?.push(thread!); + } + } + + initServer = async (url: string, progress: Function) => { + this.progress = progress; + progress("database loaded", 15) + let buf = await fetch(url).then(res => res.arrayBuffer()); + DbPool.sharedBuffer = buf; + progress("open database", 20) + for (let i = 0; i < this.works.length; i++) { + let thread = this.works[i]; + let {status, msg} = await thread.dbOpen() + if (!status) { + return {status, msg} + } + } + return {status: true, msg: "ok"}; + } + initSqlite = async (buf: ArrayBuffer, progress: Function) => { + this.progress = progress; + progress("database loaded", 15) + DbPool.sharedBuffer = buf; + progress("parse database", 20) + for (let i = 0; i < this.works.length; i++) { + let thread = this.works[i]; + let {status, msg} = await thread.dbOpen() + if (!status) { + return {status, msg} + } + } + return {status: true, msg: "ok"}; + } + + close = async () => { + for (let i = 0; i < this.works.length; i++) { + let thread = this.works[i]; + thread.terminate(); + } + this.works.length = 0; + } + + submit(name: string, sql: string, args: any, handler: Function) { + let noBusyThreads = this.works.filter(it => !it.busy); + let thread: DbThread + if (noBusyThreads.length > 0) { //取第一个空闲的线程进行任务 + thread = noBusyThreads[0]; + thread.queryFunc(name, sql, args, handler) + } else { // 随机插入一个线程中 + thread = this.works[Math.floor(Math.random() * this.works.length)] + thread.queryFunc(name, sql, args, handler) + } + } +} + +export const threadPool = new DbPool() + +function query(name: string, sql: string, args: any = null): Promise> { + return new Promise>((resolve, reject) => { + threadPool.submit(name, sql, args, (res: any) => { + resolve(res) + }) + }) +} + +export const querySql = (sql: string): Promise> => query("queryProcess", sql) +/*-------------------------------------------------------------------------------------*/ +export const queryProcess = (): Promise> => + query("queryProcess", `SELECT pid,processName FROM temp_query_process`) +/*-------------------------------------------------------------------------------------*/ +export const queryTotalTime = (): Promise> => + query("queryTotalTime", `select end_ts-start_ts as total from trace_section;`) +/*-------------------------------------------------------------------------------------*/ +export const queryCpu = async (): Promise> => + query("queryCpu", `select cpu from cpu_measure_filter where name='cpu_idle' order by cpu;`) +/*-------------------------------------------------------------------------------------*/ +export const getAsyncEvents = (): Promise> => + query("getAsyncEvents", `select *,p.pid as pid,c.ts - t.start_ts as "startTime" from callstack c,trace_section t +left join process p on c.callid = p.id where cookie is not null;`) + +export const getCpuUtilizationRate = (startNS: number, endNS: number): Promise> => + query("getCpuUtilizationRate", `select * from temp_get_cpu_rate;`, {}) +/*-------------------------------------------------------------------------------------*/ +export const getFps = () => + query("getFps", `select distinct(ts-tb.start_ts) as startNS,fps +from hidump c ,trace_section tb +where startNS >= 0 +order by startNS;`, {}) + +/*-------------------------------------------------------------------------------------*/ +export const getFunDataByTid = (tid: number): Promise> => + query("getFunDataByTid", `select * from temp_query_thread_function where tid = $tid`, {$tid: tid}) +/*-------------------------------------------------------------------------------------*/ +export const getStatesProcessThreadDataCount = (): Promise> => + query("getStatesProcessThreadData", `select count(1) as count from (select IP.name as process, + IP.pid as processId, + A.name as thread, + B.state as state, + A.tid as threadId, + B.dur, + (B.ts - TR.start_ts + B.dur) as end_ts, + (B.ts - TR.start_ts) as start_ts, + B.cpu, + C.priority, + '-' as note +from thread_state as B + left join thread as A on B.itid = A.id + left join process as IP on A.ipid = IP.id + left join trace_section as TR + left join sched_slice as C on B.itid = C.itid and C.ts = B.ts +where + B.dur > 0 and IP.pid not null and (B.ts - TR.start_ts) >= 0); +`, {}); +export const getStatesProcessThreadData = (limit:number,offset:number): Promise> => + query("getStatesProcessThreadData", `select IP.name as process, + IP.pid as processId, + A.name as thread, + B.state as state, + A.tid as threadId, + B.dur, + (B.ts - TR.start_ts + B.dur) as end_ts, + (B.ts - TR.start_ts) as start_ts, + B.cpu, + C.priority, + '-' as note +from thread_state as B + left join thread as A on B.itid = A.id + left join process as IP on A.ipid = IP.id + left join trace_section as TR + left join sched_slice as C on B.itid = C.itid and C.ts = B.ts +where + B.dur > 0 and IP.pid not null and (B.ts - TR.start_ts) >= 0 limit $limit offset $offset; +`, {$limit: limit, $offset: offset}); + +export const getTabStatesGroupByProcessThread = (leftNs: number, rightNs: number): Promise> => + query("getTabStatesGroupByProcessThread", `select process, + processId, + thread, + threadId, + sum(dur) as wallDuration, + round(avg(dur),2) as avgDuration, + min(dur) as minDuration, + max(dur) as maxDuration, + count(threadId) as count +from temp_get_process_thread_state_data +where not (end_ts < $leftNS or start_ts > $rightNS) +group by process, processId,thread,threadId`, {$leftNS: leftNs, $rightNS: rightNs}); + +export const getTabStatesGroupByProcess = (leftNs: number, rightNs: number): Promise> => + query("getTabStatesGroupByProcess", `select process, processId, + sum(dur) as wallDuration, + round(avg(dur),2) as avgDuration, + min(dur) as minDuration, + max(dur) as maxDuration, + count(processId) as count +from temp_get_process_thread_state_data +where not (end_ts < $leftNS or start_ts > $rightNS) +group by process,processId`, {$leftNS: leftNs, $rightNS: rightNs}); + +// todo wasm模式报错 +export const getTabStatesGroupByState = (leftNs: number, rightNs: number): Promise> => + query("getTabStatesGroupByState", `select state, + sum(dur) as wallDuration, + round(avg(dur),2) as avgDuration, + min(dur) as minDuration, + max(dur) as maxDuration, + count(state) as count +from temp_get_process_thread_state_data +where not (end_ts < $leftNS or start_ts > $rightNS) +group by state`, {$leftNS: leftNs, $rightNS: rightNs}); + +export const getTabStatesGroupByStatePid = (leftNs: number, rightNs: number): Promise> => + query("getTabStatesGroupByStatePid", `select process, + processId, + state, + sum(dur) as wallDuration, + round(avg(dur),2) as avgDuration, + min(dur) as minDuration, + max(dur) as maxDuration, + count(processId) as count +from temp_get_process_thread_state_data +where not (end_ts < $leftNS or start_ts > $rightNS) +group by process,processId,state`, {$leftNS: leftNs, $rightNS: rightNs}); + +export const getTabStatesGroupByStatePidTid = (leftNs: number, rightNs: number): Promise> => + query("getTabStatesGroupByStatePidTid", `select process, + processId, + thread, + state, + threadId, + sum(dur) as wallDuration, + round(avg(dur),2) as avgDuration, + min(dur) as minDuration, + max(dur) as maxDuration, + count(threadId) as count +from temp_get_process_thread_state_data +where not (end_ts < $leftNS or start_ts > $rightNS) +group by process, processId, thread, threadId,state`, {$leftNS: leftNs, $rightNS: rightNs}); + +export const getTabBoxChildData = (leftNs: number, rightNs: number, state: string | undefined, processId: number | undefined, threadId: number | undefined): Promise> => + query("getTabBoxChildData", `select IP.name as process, + IP.pid as processId, + A.name as thread, + B.state as state, + A.tid as threadId, + B.dur as duration, + B.ts - TR.start_ts as startNs, + B.cpu, + C.priority, + '-' as note +from thread_state AS B + left join thread as A on B.itid = A.id + left join process AS IP on A.ipid = IP.id + left join trace_section AS TR + left join sched_slice as C on B.itid = C.itid and C.ts = B.ts +where + B.dur > 0 and IP.pid not null + and not ((B.ts - TR.start_ts + B.dur < $leftNS) or (B.ts - TR.start_ts > $rightNS)) + ${state != undefined && state != '' ? 'and B.state = $state' : ''} + ${processId != undefined && processId != -1 ? 'and IP.pid = $processID' : ''} + ${threadId != undefined && threadId != -1 ? 'and A.tid = $threadID' : ''} + `, {$leftNS: leftNs, $rightNS: rightNs, $state: state, $processID: processId, $threadID: threadId}) + +/*-------------------------------------------------------------------------------------*/ +export const getTabCpuUsage = (cpus: Array, leftNs: number, rightNs: number): Promise> => + query("getTabCpuUsage", `select cpu, + sum(case + when (A.ts - B.start_ts) < $leftNS then (A.ts - B.start_ts + A.dur - $leftNS) + when (A.ts - B.start_ts) >= $leftNS and (A.ts - B.start_ts + A.dur) <= $rightNS then A.dur + when (A.ts - B.start_ts + A.dur) > $rightNS then ($rightNS - (A.ts - B.start_ts)) end) / cast($rightNS - $leftNS as float) as usage +from thread_state A ,trace_section B +where (A.ts - B.start_ts) > 0 and A.dur > 0 + and cpu in (${cpus.join(",")}) + and (A.ts - B.start_ts + A.dur) > $leftNS and (A.ts - B.start_ts) < $rightNS +group by cpu`, {$leftNS: leftNs, $rightNS: rightNs}) + +export const getTabCpuFreq = (cpus: Array, leftNs: number, rightNs: number): Promise> => + query("getTabCpuFreq", `select cpu,value,(ts - tb.start_ts) as startNs +from measure c ,trace_section tb +inner join cpu_measure_filter t on c.filter_id = t.id +where (name = 'cpufreq' or name='cpu_frequency') + and cpu in (${cpus.join(",")}) + and startNs > 0 + and startNs < $rightNS + order by startNs`, {$leftNS: leftNs, $rightNS: rightNs}) +/*-------------------------------------------------------------------------------------*/ +export const getTabFps = (leftNs: number, rightNs: number): Promise> => + query("getTabFps", `select distinct(ts-tb.start_ts) as startNS,fps +from hidump c ,trace_section tb +where startNS <= $rightNS and startNS >= 0 +order by startNS;`, {$leftNS: leftNs, $rightNS: rightNs}) +/*-------------------------------------------------------------------------------------*/ +export const getTabCounters = (filterIds: Array, startTime: number) => + query("getTabCounters", `select t1.filter_id as trackId,t2.name,value, t1.ts - t3.start_ts as startTime +from measure t1 +left join process_measure_filter t2 on t1.filter_id = t2.id +left join trace_section t3 where filter_id in (${filterIds.join(",")}) +and startTime <= $startTime +order by startTime asc;`, {$startTime: startTime}) +/*-------------------------------------------------------------------------------------*/ +export const getTabCpuByProcess = (cpus: Array, leftNS: number, rightNS: number) => + query("getTabCpuByProcess", `select IP.name as process, + IP.pid as pid, + sum(B.dur) as wallDuration, + avg(B.dur) as avgDuration, + count(A.tid) as occurrences +from thread_state AS B + left join thread as A on B.itid = A.id + left join trace_section AS TR + left join process AS IP on A.ipid = IP.id +where B.cpu in (${cpus.join(",")}) + and not ((B.ts - TR.start_ts + B.dur < $leftNS) or (B.ts - TR.start_ts > $rightNS )) +group by IP.name, IP.pid +order by wallDuration desc;`, {$rightNS: rightNS, $leftNS: leftNS}) +/*-------------------------------------------------------------------------------------*/ +export const getTabCpuByThread = (cpus: Array, leftNS: number, rightNS: number) => + query("getTabCpuByThread", `select IP.name as process, + IP.pid as pid, + A.name as thread, + A.tid as tid, + sum(B.dur) as wallDuration, + avg(B.dur) as avgDuration, + count(A.tid) as occurrences +from thread_state AS B + left join thread as A on B.itid = A.id + left join trace_section AS TR + left join process AS IP on A.ipid = IP.id +where B.cpu in (${cpus.join(",")}) + and not ((B.ts - TR.start_ts + B.dur < $leftNS) or (B.ts - TR.start_ts > $rightNS)) +group by IP.name, IP.pid, A.name, A.tid +order by wallDuration desc;`, {$rightNS: rightNS, $leftNS: leftNS}) +/*-------------------------------------------------------------------------------------*/ +export const getTabSlices = (funTids: Array, leftNS: number, rightNS: number): Promise> => + query("getTabSlices", `select + c.name as name, + sum(c.dur) as wallDuration, + avg(c.dur) as avgDuration, + count(c.name) as occurrences +from thread A,trace_section D +left join callstack C on A.id = C.callid +where C.ts not null + and c.dur >= 0 + and A.tid in (${funTids.join(",")}) + and c.name not like 'binder%' + and not ((C.ts - D.start_ts + C.dur < $leftNS) or (C.ts - D.start_ts > $rightNS)) +group by c.name +order by wallDuration desc;`, {$leftNS: leftNS, $rightNS: rightNS}) +/*-------------------------------------------------------------------------------------*/ +export const getTabThreadStates = (tIds: Array, leftNS: number, rightNS: number): Promise> => + query("getTabThreadStates", `select + IP.name as process, + IP.pid, + A.name as thread, + A.tid, + B.state, + sum(B.dur) as wallDuration, + avg(ifnull(B.dur,0)) as avgDuration, + count(A.tid) as occurrences +from thread_state AS B +left join thread as A on A.id = B.itid +left join trace_section AS TR +left join process AS IP on IP.id=ipid +where A.tid in (${tIds.join(",")}) +and not ((B.ts - TR.start_ts + ifnull(B.dur,0) < $leftNS) or (B.ts - TR.start_ts > $rightNS)) +group by IP.name, IP.pid, A.name, A.tid, B.state +order by wallDuration desc;`, {$leftNS: leftNS, $rightNS: rightNS}) +/*-------------------------------------------------------------------------------------*/ +export const getThreadFuncData = (tId: number): Promise> => + query("getThreadFuncData", `select tid, + A.start_ts, + A.end_ts, + A.name as threadName, + is_main_thread, + c.callid as track_id, + c.ts-D.start_ts as startTs, + c.ts + c.dur as endTs, + c.dur, + c.name as funName, + c.depth, + c.parent_id, + c.id +from thread A,trace_section D +left join callstack C on A.id = C.callid +where startTs not null and A.tid = $tid;`, {$tid: tId}) +/*-------------------------------------------------------------------------------------*/ +export const queryBinderArgsByArgset = (argset: number): Promise> => + query("queryBinderArgsByArgset", `select * from args_view where argset = $argset;`, {$argset: argset}) +/*-------------------------------------------------------------------------------------*/ +export const queryClockFrequency = (): Promise> => + query("queryClockFrequency", `with freq as ( select measure.filter_id, measure.ts, measure.type, measure.value from clock_event_filter +left join measure +where clock_event_filter.name = '%s' and clock_event_filter.type = 'clock_set_rate' and clock_event_filter.id = measure.filter_id +order by measure.ts) +select freq.filter_id,freq.ts - r.start_ts as ts,freq.type,freq.value from freq,trace_section r;`, {}) +/*-------------------------------------------------------------------------------------*/ +export const queryClockList = (): Promise> => + query("queryClockList", `with list as ( + select distinct name from clock_event_filter + where clock_event_filter.type = 'clock_set_rate' order by name +),freq as( + select measure.filter_id, measure.ts, measure.type, measure.value , clock_event_filter.name from clock_event_filter + left join measure + where clock_event_filter.type = 'clock_set_rate' and clock_event_filter.id = measure.filter_id + order by measure.ts +),state as ( + select filter_id, ts, endts, endts-ts as dur, type, value,name from + (select measure.filter_id, measure.ts, lead(ts, 1, null) over( order by measure.ts) endts, measure.type, measure.value,clock_event_filter.name from clock_event_filter,trace_section + left join measure + where clock_event_filter.type != 'clock_set_rate' and clock_event_filter.id = measure.filter_id + order by measure.ts) +),count_freq as ( + select COUNT(*) num,name srcname from freq group by name +),count_state as ( + select COUNT(*) num,name srcname from state group by name +) +select count_freq.srcname||' Frequency' as name,* from count_freq union select count_state.srcname||' State' as name,* from count_state order by name;`) +/*-------------------------------------------------------------------------------------*/ +export const queryClockState = (): Promise> => + query("queryClockState", `with state as ( +select filter_id, ts, endts, endts-ts as dur, type, value from +(select measure.filter_id, measure.ts, lead(ts, 1, null) over( order by measure.ts) endts, measure.type, measure.value from clock_event_filter,trace_section +left join measure +where clock_event_filter.name = '%s' and clock_event_filter.type != 'clock_set_rate' and clock_event_filter.id = measure.filter_id +order by measure.ts)) +-- select * from state; +select s.filter_id,s.ts-r.start_ts as ts,s.type,s.value,s.dur from state s,trace_section r;`) +/*-------------------------------------------------------------------------------------*/ +export const queryCpuData = (cpu: number, startNS: number, endNS: number): Promise> => + query("queryCpuData", `select * from temp_query_cpu_data where cpu = $cpu and startTime between $startNS and $endNS;`, { + $cpu: cpu, + $startNS: startNS, + $endNS: endNS + }) +/*-------------------------------------------------------------------------------------*/ +export const queryCpuFreq = (): Promise> => +query("queryCpuFreq", `select cpu from cpu_measure_filter where (name='cpufreq' or name='cpu_frequency') order by cpu;`) +/*-------------------------------------------------------------------------------------*/ +export const queryCpuFreqData = (cpu: number): Promise> => + query("queryCpuFreqData", `select cpu,value,ts-tb.start_ts as startNS +from measure c ,trace_section tb +inner join cpu_measure_filter t on c.filter_id = t.id +where (name = 'cpufreq' or name='cpu_frequency') and cpu= $cpu +order by ts;`, {$cpu: cpu}); +/*-------------------------------------------------------------------------------------*/ +export const queryCpuMax = (): Promise> => + query("queryCpuMax", `select cpu from sched_slice order by cpu desc limit 1;`) +/*-------------------------------------------------------------------------------------*/ +export const queryCpuMaxFreq = (): Promise> => +query("queryCpuMaxFreq", `select max(value) as maxFreq +from measure c +inner join cpu_measure_filter t on c.filter_id = t.id +where (name = 'cpufreq' or name='cpu_frequency');`) +// /*-------------------------------------------------------------------------------------*/ +export const queryLogs = (): Promise> => + query("queryLogs", `select l.*,l.ts-t.start_ts as "startTime" from log as l left join trace_section AS t + where "startTime" between %s and %s order by "startTime" + limit %s offset %s;`) +/*-------------------------------------------------------------------------------------*/ +export const queryLogsCount = (): Promise> => + query("queryLogsCount", `select l.*,l.ts-t.start_ts as "startTime" from log as l left join trace_section AS t + where "startTime" between %s and %s;`) +/*-------------------------------------------------------------------------------------*/ +export const queryProcessData = (pid: number, startNS: number, endNS: number): Promise> => + query("queryProcessData", `select * from temp_query_process_data where tid != 0 and pid = $pid and startTime between $startNS and $endNS;`, { + $pid: pid, + $startNS: startNS, + $endNS: endNS + }) +/*-------------------------------------------------------------------------------------*/ +export const queryProcessDataCount = (): Promise> => + query("queryProcessDataCount", `select ta.id,type, ts, dur, ta.cpu, itid as utid, state + ,ts-tb.start_ts as startTime,tc.tid,tc.pid,tc.process,tc.thread +from thread_state ta,trace_section tb +left join ( + select it.id,tid,pid,ip.name as process,it.name as thread from thread as it left join process ip on it.ipid = ip.id + ) tc on ta.itid = tc.id +where tc.pid = %d + and startTime between %s and %s +and ta.cpu is not null +order by startTime;`) +/*-------------------------------------------------------------------------------------*/ +export const queryProcessDataLimit = (pid: number, startNS: number, endNS: number, limit: number): Promise> => + query("queryProcessDataLimit", `with list as (select ta.id,type, ts, dur, ta.cpu, itid as utid, state + ,ts-tb.start_ts as startTime,tc.tid,tc.pid,tc.process,tc.thread +from thread_state ta,trace_section tb +left join ( + select it.id,tid,pid,ip.name as process,it.name as thread from thread as it left join process ip on it.ipid = ip.id + ) tc on ta.itid = tc.id +where tc.pid = $pid + and startTime between $startNS and $endNS +and ta.cpu is not null +order by startTime ) +select * from list order by random() limit $limit;`, {$pid: pid, $startNS: startNS, $endNS: endNS, $limit: limit}) +/*-------------------------------------------------------------------------------------*/ +export const queryProcessMem = (): Promise> => + query("queryProcessMem", `select process_measure_filter.id as trackId, + process_measure_filter.name as trackName, + ipid as upid, + process_view.pid, + process_view.name as processName +from process_measure_filter join process_view using (ipid) +order by trackName;`) +/*-------------------------------------------------------------------------------------*/ +export const queryProcessMemData = (trackId: number): Promise> => + query("queryProcessMemData", `select c.type, + ts, value, + filter_id as track_id, + c.ts-tb.start_ts startTime +from measure c,trace_section tb where filter_id = $id;`, {$id: trackId}) +/*-------------------------------------------------------------------------------------*/ +export const queryProcessNOrder = (): Promise> => + query("queryProcessNOrder", `select pid,name as processName from process;`) +/*-------------------------------------------------------------------------------------*/ +export const queryProcessThreads = (): Promise> => + query("queryProcessThreads", `select + the_tracks.ipid as upid, + the_tracks.itid as utid, + total_dur as hasSched, + process_view.pid as pid, + thread_view.tid as tid, + process_view.name as processName, + thread_view.name as threadName +from ( + select ipid, itid from sched_view join thread_view using(itid) group by itid +) the_tracks +left join (select ipid, sum(dur) as total_dur + from sched_view join thread_view using(itid) + group by ipid +) using(ipid) +left join thread_view using(itid) +left join process_view using(ipid) +order by + total_dur desc, + the_tracks.ipid, + the_tracks.itid;`, {}) +/*-------------------------------------------------------------------------------------*/ +export const queryProcessThreadsNOrder = (): Promise> => + query("queryProcessThreadsNOrder", `select p.id as upid, + t.id as utid, + p.pid, + t.tid, + p.name as processName, + t.name as threadName + from thread t left join process p on t.ipid = p.id;`) +/*-------------------------------------------------------------------------------------*/ +export const queryScreenState = (): Promise> => + query("queryScreenState", `select m.type, m.ts-r.start_ts as ts, value, filter_id from measure m,trace_section r where filter_id in (select id from process_measure_filter where name = 'ScreenState');`) +/*-------------------------------------------------------------------------------------*/ +export const queryThreadData = (tid: number): Promise> => + query("queryThreadData", `select * from temp_query_thread_data where tid = $tid;`, {$tid: tid}) +/*-------------------------------------------------------------------------------------*/ +export const queryWakeUpThread_Desc = (): Promise> => + query("queryWakeUpThread_Desc", `This is the interval from when the task became eligible to run +(e.g.because of notifying a wait queue it was a suspended on) to when it started running.`) +/*-------------------------------------------------------------------------------------*/ +export const queryWakeUpThread_WakeThread = (wakets: number): Promise> => + query("queryWakeUpThread_WakeThread", `select TB.tid,TB.name as thread,TA.cpu,TC.pid,TC.name as process +from sched_view TA +left join thread TB on TA.itid = TB.id +left join process TC on TB.ipid = TC.id +where itid = (select itid from raw where name = 'sched_waking' and ts = $wakets ) + and TA.ts < $wakets + and Ta.ts + Ta.dur >= $wakets`, {$wakets: wakets}) +/*-------------------------------------------------------------------------------------*/ +export const queryWakeUpThread_WakeTime = (tid: number, startTime: number): Promise> => + query("queryWakeUpThread_WakeTime", `select * from + ( select ts as wakeTs,start_ts as startTs from instants_view,trace_section + where name = 'sched_waking' + and ref = $tid + and ts < start_ts + $startTime + order by ts desc limit 1) TA + left join + (select ts as preRow from sched_view,trace_section + where itid = $tid + and ts < start_ts + $startTime + order by ts desc limit 1) TB`, {$tid: tid, $startTime: startTime}) +/*-------------------------------------------------------------------------------------*/ +export const queryThreadsByPid = (pid: number): Promise> => + query("queryThreadsByPid", `select + the_tracks.ipid as upid, + the_tracks.itid as utid, + total_dur as hasSched, + process_view.pid as pid, + thread_view.tid as tid, + process_view.name as processName, + thread_view.name as threadName + from ( + select ipid, itid from sched_view join thread_view using(itid) group by itid + ) the_tracks + left join (select ipid, sum(dur) as total_dur + from sched_view join thread_view using(itid) + group by ipid + ) using(ipid) + left join thread_view using(itid) + left join process_view using(ipid) + where pid = $pid + order by + total_dur desc, + the_tracks.ipid, + the_tracks.itid`, {$pid: pid}) +/*-------------------------------------------------------------------------------------*/ +export const queryHeapByPid = (startTs: number, endTs: number, ipid: number): Promise> => + query("queryHeapByPid", `select a.maxheap maxHeapSize,current_size_dur as dur,h.all_heap_size heapsize,h.start_ts - t.start_ts as startTime,h.end_ts - t.start_ts as endTime +from native_hook h left join trace_section t left join (select max(all_heap_size) maxheap from native_hook) a where ipid = ${ipid} and startTime between ${startTs} and ${endTs}; +`, {$ipid: ipid, $startTs: startTs, $endTs: endTs}) + +export const queryHeapGroupByEvent = (): Promise> => + query("queryHeapGroupByEvent", `select event_type as eventType,sum(heap_size) as sumHeapSize from native_hook group by event_type`, {}) + +export const queryHeapByEventType = (startTs: number, endTs: number, arg1: string,arg2: string): Promise> => + query("queryHeapByEventType", ` +select a.maxHeap maxHeapSize, + current_size_dur as dur, + h.all_heap_size heapsize, + h.start_ts - t.start_ts as startTime, + h.end_ts - t.start_ts as endTime, + h.event_type as eventType +from native_hook h +left join trace_section t +left join ( +select max(all_heap_size) maxHeap +from native_hook ${arg1}) a +where startTime between ${startTs} and ${endTs} ${arg2} +`, {$startTs: startTs, $endTs: endTs,$arg1:arg1,$arg2:arg2}) +/*-------------------------------------------------------------------------------------*/ +export const queryHeapPid = (): Promise> => + query("queryHeapPid", `select ipid,pid from native_hook h left join process p on h.ipid = p.id group by ipid,pid`, {}) +/*-------------------------------------------------------------------------------------*/ +export const queryHeapTable = (startTs: number, endTs: number, ipids: Array): Promise> => + query("queryHeapTable", `select *,Allocations - Deallocations Total,AllocationSize - DeAllocationSize RemainingSize from (select f.file_path MoudleName, + sum(case when h.event_type = 'AllocEvent' then 1 else 0 end) Allocations, + sum(case when h.event_type = 'FreeEvent' then 1 else 0 end) Deallocations, + sum(case when h.event_type = 'AllocEvent' then heap_size else 0 end) AllocationSize, + sum(case when h.event_type = 'FreeEvent' then heap_size else 0 end) DeAllocationSize, + f.symbol_name AllocationFunction + from (select native_hook.start_ts - t.start_ts as startTime,* from native_hook + left join trace_range t where ipid in (${ipids.join(",")}) and startTime between ${startTs} and ${endTs}) h + left join (select * from native_hook_frame where depth = 0) f + on f.eventId = h.eventId group by f.file_path)`, + {ipids: ipids, $startTs: startTs, $endTs: endTs}) +export const queryHeapTreeTable = (startTs: number, endTs: number, ipids: Array): Promise> => + query("queryHeapTable", ` + select h.start_ts - t.start_ts as startTs, + h.end_ts - t.start_ts as endTs, + h.heap_size as heapSize, + h.event_type as eventType, + f.symbol_name as AllocationFunction, + f.file_path as MoudleName, + f.depth, + f.eventId + from native_hook h + inner join trace_range t + inner join native_hook_frame f on h.eventId = f.eventId where event_type = 'AllocEvent' + and ipid in (${ipids.join(",")}) + and (h.start_ts - t.start_ts between ${startTs} and ${endTs} or h.end_ts - t.start_ts between ${startTs} and ${endTs})`, + {ipids: ipids, $startTs: startTs, $endTs: endTs}) +export const queryHeapAllTable = (limit: number, offset: number): Promise> => + query("queryHeapAllTable", ` + select + h.symbol_name as AllocationFunction, + h.file_path as MoudleName, + h.depth, + h.eventId + from native_hook_frame h limit $limit offset $offset`, + { $limit: limit, $offset: offset}) +export const queryHeapAllData = (startTs: number, endTs: number, ipids: Array): Promise> => + query("queryHeapAllData", ` + select h.start_ts - t.start_ts as startTs, + h.end_ts - t.start_ts as endTs, + h.heap_size as heapSize, + h.event_type as eventType, + h.eventId + from native_hook h + inner join trace_range t + where event_type = 'AllocEvent' + and ipid in (${ipids.join(",")}) + and (h.start_ts - t.start_ts between ${startTs} and ${endTs} or h.end_ts - t.start_ts between ${startTs} and ${endTs})`, + {ipids: ipids, $startTs: startTs, $endTs: endTs}) +export const queryHeapFrameCount = (): Promise> => + query("queryHeapAllTable", ` + select + count(*) as count + from native_hook_frame `, + {}) + +export const queryNativeHookStatistics = (leftNs:number,rightNs:number): Promise> => + query("queryNativeHookStatistics",` + select event_type as eventType,sub_type as subType,max(all_heap_size) as max,sum(heap_size) as sumHeapSize,count(event_type) as count +from native_hook A,trace_range B +where (A.start_ts - B.start_ts) between ${leftNs} and ${rightNs} +--not ((A.start_ts - B.start_ts + ifnull(A.dur,0)) < ${leftNs} or (A.start_ts - B.start_ts) > ${rightNs}) +group by event_type, sub_type`,{$leftNs:leftNs,$rightNs:rightNs}) + +export const queryNativeHookStatisticsMalloc = (leftNs:number,rightNs:number):Promise> => + query('queryNativeHookStatisticsMalloc', + `select event_type as eventType, + heap_size as heapSize, + sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then heap_size else 0 end) as allocByte, + sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then 1 else 0 end) as allocCount, + sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then heap_size else 0 end) as freeByte, + sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then 1 else 0 end) as freeCount +from native_hook A,trace_range B +where ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs} + or (A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) + and (event_type = 'AllocEvent') +group by event_type,heap_size; + `,{$leftNs:leftNs,$rightNs:rightNs}) + +export const queryNativeHookStatisticsSubType = (leftNs:number,rightNs:number):Promise> => + query('queryNativeHookStatisticsSubType', + `select event_type as eventType, + sub_type as subType, + max(heap_size) as heapSize, + sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then heap_size else 0 end) as allocByte, + sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then 1 else 0 end) as allocCount, + sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then heap_size else 0 end) as freeByte, + sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then 1 else 0 end) as freeCount +from native_hook A,trace_range B +where ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs} + or (A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) + and (event_type = 'MmapEvent') +group by event_type,sub_type; + `,{$leftNs:leftNs,$rightNs:rightNs}) + +export const queryNativeHookEventId = (leftNs:number,rightNs:number,types:Array): Promise> => + query("queryNativeHookEventId",` + select eventId,event_type as eventType,sub_type as subType,heap_size as heapSize,addr,(A.start_ts - B.start_ts) as startTs,(A.end_ts - B.start_ts) as endTs +from native_hook A, trace_range B +where A.start_ts - B.start_ts between ${leftNs} and ${rightNs} and A.event_type in (${types.join(",")})`,{$leftNs:leftNs,$rightNs:rightNs,$types:types}) + +export const queryNativeHookEventTid = (leftNs:number,rightNs:number,types:Array): Promise> => + query("queryNativeHookEventTid",` + select eventId, + event_type as eventType, + sub_type as subType, + heap_size as heapSize, + addr, + (A.start_ts - B.start_ts) as startTs, + (A.end_ts - B.start_ts) as endTs, + tid +from native_hook A, trace_range B +left join thread t on A.itid = t.id +where A.start_ts - B.start_ts between ${leftNs} and ${rightNs} and A.event_type in (${types.join(",")})`,{$leftNs:leftNs,$rightNs:rightNs,$types:types}) + +export const queryNativeHookProcess = ():Promise> => + query("queryNativeHookProcess",`select distinct ipid,pid,name from native_hook left join process p on native_hook.ipid = p.id`,{}) + +export const queryNativeHookSnapshot = (rightNs:number):Promise> => + query("queryNativeHookSnapshot",`select event_type as eventType,sub_type as subType,sum(heap_size) as growth,count(*) as existing from native_hook n, trace_range t +where (event_type = 'AllocEvent' or event_type = 'MmapEvent') + and n.start_ts between 0 and ${rightNs} + t.start_ts + and n.end_ts > ${rightNs} + t.start_ts +group by event_type,sub_type`,{$rightNs:rightNs}) + +export const queryNativeHookSnapshotTypes = ():Promise> => + query("queryNativeHookSnapshotTypes",`select event_type as eventType,sub_type as subType from native_hook where (event_type = 'AllocEvent' or event_type = 'MmapEvent') group by event_type,sub_type;`,{}) + +export const queryAllHookData = (rightNs:number):Promise> => + query("queryAllHookData",`select eventId,event_type as eventType,sub_type as subType,addr,heap_size as growth,(n.start_ts - t.start_ts) as startTs,(n.end_ts - t.start_ts) as endTs from native_hook n, trace_range t +where (event_type = 'AllocEvent' or event_type = 'MmapEvent') + and n.start_ts between t.start_ts and ${rightNs} + t.start_ts`,{$rightNs:rightNs}) \ No newline at end of file diff --git a/host/ide/src/trace/database/SqlLiteWorker.ts b/host/ide/src/trace/database/SqlLiteWorker.ts new file mode 100644 index 0000000000000000000000000000000000000000..f39a1d2fcbb29c3acf4406c524f3c4383cac0be9 --- /dev/null +++ b/host/ide/src/trace/database/SqlLiteWorker.ts @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +importScripts('sql-wasm.js', "TempSql.js"); +let conn: any = null; + +function initIndexedDB() { + return new Promise((resolve, reject) => { + let request = indexedDB.open("systrace"); + request.onerror = function (event) { + }; + request.onsuccess = function (event) { + let db = request.result; + resolve(db); + }; + request.onupgradeneeded = function (event) { + // @ts-ignore + let db = event!.target!.result; + if (!db.objectStoreNames.contains("connection")) { + db.createObjectStore("connection", {autoIncrement: true}); + } + }; + }) +} + +function readConnection(store: IDBObjectStore) { + return new Promise((resolve, reject) => { + let request = store.get(1); + request.onsuccess = function (event) { + // @ts-ignore + resolve(event.target.result); + }; + request.onerror = function (event) { + // @ts-ignore + reject(event.target.result); + }; + }) +} + +function deleteConnection(store: IDBObjectStore, id: number) { + return new Promise((resolve, reject) => { + let request = store.delete(id); + request.onsuccess = function (event) { + // @ts-ignore + resolve(event.target.result); + }; + request.onerror = function (event) { + // @ts-ignore + reject(event.target.result); + }; + }) +} + +self.onerror = function (error) { +} + + +self.onmessage = async (e: any) => { + if (e.data.action === "open") { + let array = new Uint8Array(e.data.buffer); + // @ts-ignore + initSqlJs({locateFile: filename => `${filename}`}).then((SQL: any) => { + conn = new SQL.Database(array); + // @ts-ignore + self.postMessage({id: e.data.id, ready: true, index: 0}); + temp_init_sql_list.forEach((item, index) => { + let r = conn.exec(item); + // @ts-ignore + self.postMessage({id: e.data.id, ready: true, index: index + 1}); + }); + // @ts-ignore + self.postMessage({id: e.data.id, init: true}); + }); + } else if (e.data.action === "close") { + } else if (e.data.action === "exec") { + try { + let action = e.data.action; //: "exec" + let sql = e.data.sql; + let params = e.data.params; + const stmt = conn.prepare(sql); + stmt.bind(params); + let res = []; + while (stmt.step()) { // + res.push(stmt.getAsObject()); + } + stmt.free(); + // @ts-ignore + self.postMessage({id: e.data.id, results: res}); + } catch (err: any) { + // @ts-ignore + self.postMessage({id: e.data.id, results: [], error: err.message}); + } + } +} \ No newline at end of file diff --git a/host/ide/src/trace/database/TempSql.ts b/host/ide/src/trace/database/TempSql.ts new file mode 100644 index 0000000000000000000000000000000000000000..a04efb3e417a807ccc651392d55c947ccf305923 --- /dev/null +++ b/host/ide/src/trace/database/TempSql.ts @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +let temp_query_process = `create table temp_query_process as select + distinct process_view.pid as pid, + process_view.name as processName +from ( + select ipid, itid from sched_slice join thread_view using(itid) group by itid +) the_tracks +left join (select ipid, sum(dur) as total_dur + from sched_view join thread_view using(itid) + group by ipid +) using(ipid) +left join process_view using(ipid) +where pid is not null +order by + total_dur desc, + the_tracks.ipid, + processName, + the_tracks.itid; +` +let temp_query_cpu_data = `create table temp_query_cpu_data as with list as (SELECT + IP.name as processName, + IP.name processCmdLine, + IP.pid as processId,B.cpu, + A.name, + C.id as schedId, + A.tid, + A.id, + A.type, + B.dur, + B.ts - TR.start_ts AS startTime, + C.priority, + C.end_state +from thread_state AS B + left join thread as A on B.itid = A.id + left join sched_slice AS C on B.itid = C.itid and B.ts = C.ts + left join trace_section AS TR + left join process AS IP on A.ipid = IP.id +where C.itid is not null +order by B.id) +select * from list; +create index temp_query_cpu_data_idx on temp_query_cpu_data(cpu,startTime); +` + +let temp_query_freq_data = `create table temp_query_freq_data as select cpu,value,ts-tb.start_ts as startNS +from measure c ,trace_section tb +inner join cpu_measure_filter t on c.filter_id = t.id +where (name = 'cpufreq' or name='cpu_frequency') +order by ts; +create index temp_query_freq_data_idx on temp_query_freq_data(cpu); +` + +let temp_query_process_data = `create table temp_query_process_data as select ta.id,type, ts, dur, ta.cpu, itid as utid, state + ,ts-tb.start_ts as startTime,tc.tid,tc.pid,tc.process,tc.thread +from thread_state ta,trace_section tb +left join ( + select it.id,tid,pid,ip.name as process,it.name as thread from thread as it left join process ip on it.ipid = ip.id + ) tc on ta.itid = tc.id +where ta.cpu is not null +order by startTime; +create index temp_query_process_data_idx on temp_query_process_data(pid,startTime); +` +let temp_query_thread_function = `create table temp_query_thread_function as select tid, + A.name as threadName, + is_main_thread, + c.callid as track_id, + c.ts-D.start_ts as startTs, + c.dur, + c.name as funName, + c.parent_id, + c.id, + c.depth, + c.argsetid +from thread A,trace_section D +left join callstack C on A.id = C.callid +where startTs not null and c.cookie is null; +create index temp_query_thread_function_idx on temp_query_thread_function(tid); +`; + +let temp_query_thread_data = `create table temp_query_thread_data as select A.id, A.type, A.tid, A.name, A.start_ts, A.end_ts, A.ipid as upid, A.is_main_thread + , B.cpu, B.ts-TR.start_ts AS startTime,B.dur,B.state,IP.pid,IP.name as processName + from thread_state AS B + left join thread as A on A.id=B.itid + left join trace_section AS TR + left join process AS IP on IP.id=ipid; + create index temp_query_thread_data_idx on temp_query_thread_data(tid);` + +let temp_view = `CREATE VIEW IF NOT EXISTS thread_view AS SELECT id as itid, * FROM thread; +CREATE VIEW IF NOT EXISTS process_view AS SELECT id as ipid, * FROM process; +CREATE VIEW IF NOT EXISTS sched_view AS SELECT *, ts + dur as ts_end FROM sched_slice; +CREATE VIEW IF NOT EXISTS instants_view AS SELECT *, 0.0 as value FROM instant; +CREATE VIEW IF NOT EXISTS trace_section AS select start_ts, end_ts from trace_range;` + +let temp_query_cpu_freq = `create table temp_query_cpu_freq as select cpu from cpu_measure_filter where (name='cpufreq' or name='cpu_frequency') order by cpu;` +let temp_query_cpu_max_freq = `create table temp_query_cpu_max_freq as select max(value) as maxFreq +from measure c +inner join cpu_measure_filter t on c.filter_id = t.id +where (name = 'cpufreq' or name='cpu_frequency');` + +let temp_get_tab_states_group_by_process = `create table temp_get_tab_states_group_by_process as +select IP.name as process,IP.pid as processId, + dur, + Ip.id as id, + (ts - B.start_ts + dur) as end_ts, + (ts - B.start_ts) as start_ts +from thread_state as A,trace_section as B + left join thread as C on A.itid = C.id + left join process AS IP on C.ipid = IP.id +where A.dur > 0 and processId not null and (ts - B.start_ts)>0; +create index temp_get_tab_states_group_by_process_idx on temp_get_tab_states_group_by_process(end_ts,start_ts); +` + +let temp_get_process_thread_state_data = ` create table temp_get_process_thread_state_data as + select IP.name as process, + IP.pid as processId, + A.name as thread, + B.state as state, + A.tid as threadId, + B.dur, + (B.ts - TR.start_ts + B.dur) as end_ts, + (B.ts - TR.start_ts) as start_ts, + B.cpu, + C.priority, + '-' as note +from thread_state as B + left join thread as A on B.itid = A.id + left join process as IP on A.ipid = IP.id + left join trace_section as TR + left join sched_slice as C on B.itid = C.itid and C.ts = B.ts +where + B.dur > 0 and IP.pid not null and (B.ts - TR.start_ts) >= 0; +create index temp_get_process_thread_state_data_idx on temp_get_process_thread_state_data(end_ts,start_ts); +` + +let temp_get_tab_states_group_by_state_pid_tid = ` create table temp_get_tab_states_group_by_state_pid_tid as +select IP.name as process, + IP.pid as processId, + A.name as thread, + B.state as state, + A.tid as threadId, + B.dur as dur, + A.tid as tid, + (B.ts - TR.start_ts + B.dur) as end_ts, + (B.ts - TR.start_ts) as start_ts +from thread_state AS B + left join thread as A on B.itid = A.id + left join process AS IP on A.ipid = IP.id + left join trace_section AS TR +where + B.dur > 0 and IP.pid not null and (B.ts - TR.start_ts > 0); +create index temp_get_tab_states_group_by_state_pid_tid_idx0 on temp_get_tab_states_group_by_state_pid_tid(process,processId,thread,threadId,state); +create index temp_get_tab_states_group_by_state_pid_tid_idx1 on temp_get_tab_states_group_by_state_pid_tid(end_ts,start_ts); +create index temp_get_tab_states_group_by_state_pid_tid_idx3 on temp_get_tab_states_group_by_state_pid_tid(end_ts,start_ts,process,processId,thread,threadId,state); +` +let temp_get_tab_states_group_by_state_pid = `create table temp_get_tab_states_group_by_state_pid as +select IP.name as process, + IP.pid as processId, + B.state as state, + B.dur as dur, + A.tid as tid, + (ts - TR.start_ts + dur) as end_ts, + (ts - TR.start_ts) as start_ts +from thread_state AS B + left join thread as A on B.itid = A.id + left join process AS IP on A.ipid = IP.id + left join trace_section AS TR +where pid not null and + B.dur > 0 and (ts - TR.start_ts > 0); + create index temp_get_tab_states_group_by_state_pid_idx0 on temp_get_tab_states_group_by_state_pid(process,processId,state); + create index temp_get_tab_states_group_by_state_pid_idx1 on temp_get_tab_states_group_by_state_pid(start_ts,end_ts); +` +let temp_get_tab_states_group_by_state = `create table temp_get_tab_states_group_by_state as +select state, + dur, + (ts - B.start_ts + dur) as end_ts, + (ts - B.start_ts) as start_ts + from thread_state as A,trace_section as B + left join thread as C on A.itid = C.id + left join process AS IP on C.ipid = IP.id + where A.dur > 0 and IP.pid not null and (ts - B.start_ts > 0); + create index temp_get_tab_states_group_by_state_idx0 on temp_get_tab_states_group_by_state(state); + create index temp_get_tab_states_group_by_state_idx1 on temp_get_tab_states_group_by_state(start_ts,end_ts); + ` +let temp_get_tab_states_group_by_process_thread = `create table temp_get_tab_states_group_by_process_thread as +select IP.name as process, + IP.pid as processId, + A.name as thread, + a.tid as threadId, + B.dur as dur, + A.tid as tid, + (ts - TR.start_ts + dur) as end_ts, + (ts - TR.start_ts) as start_ts + from thread_state AS B + left join thread as A on B.itid = A.id + left join process AS IP on A.ipid = IP.id + left join trace_section AS TR + where pid not null and + B.dur > 0 and (ts - TR.start_ts)>0; + create index temp_get_tab_states_group_by_process_thread_idx0 on temp_get_tab_states_group_by_process_thread(process,processId,thread,threadId); + create index temp_get_tab_states_group_by_process_thread_idx1 on temp_get_tab_states_group_by_process_thread(start_ts,end_ts); +` + +let temp_get_cpu_rate = `create table temp_get_cpu_rate as +with cpu as ( + select cpu,ts,dur,(case when ro < 99 then ro else 99 end) as ro , + (case when ro < 99 then stime+ro*cell else stime + 99 * cell end) as st, + (case when ro < 99 then stime + (ro+1)*cell else etime end) as et + from ( + select cpu,ts,A.dur,((ts+A.dur)-D.start_ts)/((D.end_ts-D.start_ts)/100) as ro,D.start_ts as stime,D.end_ts etime,(D.end_ts-D.start_ts)/100 as cell + from sched_slice A + left join trace_section D + left join thread B on A.itid = B.id + left join process C on B.ipid = C.id + where tid != 0 and (A.ts) between D.start_ts and D.end_ts)) +select cpu,ro, + sum(case + when ts <= st and ts + dur <= et then (ts + dur - st) + when ts <= st and ts + dur > et then et-st + when ts > st and ts + dur <= et then dur + when ts > st and ts + dur > et then et - ts end)/cast(et-st as float) as rate +from cpu +group by cpu,ro; +` + +let temp_get_tab_thread_states = `create table temp_get_tab_thread_states as + select + IP.name as process, + IP.pid as pid, + A.name as thread, + A.tid as tid, + B.state as state, + B.dur as dur, + (B.ts - TR.start_ts + ifnull(B.dur,0)) as end_ts, + (B.ts - TR.start_ts) as start_ts +from thread_state AS B +left join thread as A on A.id = B.itid +left join trace_section AS TR +left join process AS IP on IP.id=ipid +where (B.ts - TR.start_ts > 0); +create index temp_get_tab_thread_states_idx0 on temp_get_tab_thread_states(process,pid,thread,tid,state); +create index temp_get_tab_thread_states_idx1 on temp_get_tab_thread_states(start_ts,end_ts); +`; + +let temp_get_tab_slices = `create table temp_get_tab_slices as + select + c.name as name, + c.dur as dur, + A.tid as tid, + (C.ts - D.start_ts + C.dur) as end_ts, + (C.ts - D.start_ts) as start_ts +from thread A,trace_section D +left join callstack C on A.id = C.callid +where C.ts not null + and c.dur >= 0 + and (C.ts - D.start_ts > 0); +create index temp_get_tab_slices_idx0 on temp_get_tab_slices(name); +`; + +let delete_callstack_binder_data = `DELETE FROM callstack WHERE dur<0 or name like 'binder%';`; +let temp_init_sql_list = [ + temp_view, + delete_callstack_binder_data, + temp_query_process, + temp_query_cpu_data, + temp_query_process_data, + temp_query_thread_function, + temp_query_thread_data, + temp_get_cpu_rate, +]; diff --git a/host/ide/src/trace/database/TraceWorker.ts b/host/ide/src/trace/database/TraceWorker.ts new file mode 100644 index 0000000000000000000000000000000000000000..559550f62e06790b67669355d34972462b653df6 --- /dev/null +++ b/host/ide/src/trace/database/TraceWorker.ts @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +importScripts("trace_streamer_builtin.js", "TempSql.js"); +self.onerror = function (error: any) { +} +let Module: any = null; + +function initWASM() { + return new Promise((resolve, reject) => { + // @ts-ignore + let wasm = trace_streamer_builtin_wasm + Module = wasm({ + locateFile: (s: any) => { + return s + }, + print: (line: any) => { + }, + printErr: (line: any) => { + }, + onRuntimeInitialized: () => { + resolve("ok"); + }, + onAbort: () => { + reject("on abort"); + } + }); + }) +} + +const REQ_BUF_SIZE = 64 * 1024 * 1024; +self.onmessage = async (e: MessageEvent) => { + if (e.data.action === "open") { + await initWASM(); + // @ts-ignore + self.postMessage({id: e.data.id, action: "open", ready: true, index: 0}); + let uint8Array = new Uint8Array(e.data.buffer); + let p = Module._malloc(uint8Array.length); + Module.HEAPU8.set(uint8Array, p); + let r1 = Module._TraceStreamerParseData(p, uint8Array.length); + let r2 = Module._TraceStreamerParseDataOver(); + Module._free(p); + if (r1 == -1) { + // @ts-ignore + self.postMessage({id: e.data.id, action: "open", init: false, msg: "parse data error"}); + return; + } + // @ts-ignore + temp_init_sql_list.forEach((item, index) => { + let r = createView(item); + // @ts-ignore + self.postMessage({id: e.data.id, ready: true, index: index + 1}); + }); + // @ts-ignore + self.postMessage({id: e.data.id, action: "open", init: true, msg: "ok"}); + } else if (e.data.action === "exec") { + let arr = query(e.data.name, e.data.sql, e.data.params); + // @ts-ignore + self.postMessage({id: e.data.id, action: "exec", results: arr}); + } +} + +function createView(sql: string) { + let enc = new TextEncoder(); + let dec = new TextDecoder(); + let sqlPtr = Module._malloc(sql.length); + Module.HEAPU8.set(enc.encode(sql), sqlPtr); + let res = Module._TraceStreamerSqlOperate(sqlPtr, sql.length); + return res; +} + +function query(name: string, sql: string, params: any) { + if (params) { + Reflect.ownKeys(params).forEach((key: any) => { + if (typeof params[key] === "string") { + sql = sql.replace(new RegExp(`\\${key}`, "g"), `'${params[key]}'`); + } else { + sql = sql.replace(new RegExp(`\\${key}`, "g"), params[key]); + } + }); + } + let arr: Array = [] + let enc = new TextEncoder(); + let dec = new TextDecoder(); + let sqlPtr = Module._malloc(sql.length); + let outPtr = Module._malloc(REQ_BUF_SIZE); + Module.HEAPU8.set(enc.encode(sql), sqlPtr); + let a = new Date().getTime(); + let res = Module._TraceStreamerSqlQuery(sqlPtr, sql.length, outPtr, REQ_BUF_SIZE); + let out = Module.HEAPU8.subarray(outPtr, outPtr + res); + let str = dec.decode(out); + Module._free(sqlPtr); + Module._free(outPtr); + str = str.substring(str.indexOf("\n") + 1); + let parse = JSON.parse(str); + let columns = parse.columns; + let values = parse.values; + for (let i = 0; i < values.length; i++) { + let obj: any = {} + for (let j = 0; j < columns.length; j++) { + obj[columns[j]] = values[i][j] + } + arr.push(obj) + } + return arr +} \ No newline at end of file diff --git a/host/ide/src/trace/grpc/HiProfilerClient.ts b/host/ide/src/trace/grpc/HiProfilerClient.ts new file mode 100644 index 0000000000000000000000000000000000000000..c4bbdb0672dee199ec09b4ac0285b01da95362fa --- /dev/null +++ b/host/ide/src/trace/grpc/HiProfilerClient.ts @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import {Address, ProfilerClient} from "./ProfilerClient.js"; + +export class HiProfilerClient { + private _client: ProfilerClient; + private _address: Address; + + get client(): ProfilerClient { + return this._client; + } + + set client(value: ProfilerClient) { + this._client = value; + } + + get address(): Address { + return this._address; + } + + set address(value: Address) { + this._address = value; + } + + public constructor(clients: ProfilerClient, addr: Address) { + this._client = clients; + this._address = addr; + }; + + public getProfilerClient(): ProfilerClient{ + return this._client; + } + + public getCapabilities() { + // this.client.start() + // this.client.getCapabilities( + } + + public createSession() { + // this.client.createSession( + } + + public startSession() { + // this.client.startSession( + } + + public stopSession() { + // this.client.stopSession( + } + + public destroySession() { + // this.client.destroySession( + } + + public keepSession() { + // this.client.keepSession( + } +} \ No newline at end of file diff --git a/host/ide/src/trace/grpc/ProfilerClient.ts b/host/ide/src/trace/grpc/ProfilerClient.ts new file mode 100644 index 0000000000000000000000000000000000000000..73f01998fa2ae0acd0723ca47055d33d614c2060 --- /dev/null +++ b/host/ide/src/trace/grpc/ProfilerClient.ts @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import * as path from 'path'; + +const profilerServicePath = path.join(__dirname,'../proto', 'profiler_service.proto'); + +export class ProfilerClient { + // proto filePaths + private _filePaths: Array | undefined; + // client + private _client: any; + // profiler_proto + private _profiler_proto: any; + // ProfilerClient constructor + public constructor(address: Address) { + // load client port + let clientPort = this.loadAddress(address); + // load proto file + this.start(clientPort, profilerServicePath); + }; + + get filePaths(): Array | undefined { + return this._filePaths; + } + + set filePaths(value: Array | undefined) { + this._filePaths = value; + } + + get client(): any { + return this._client; + } + + set client(value: any) { + this._client = value; + } + + get profiler_proto(): any { + return this._profiler_proto; + } + + set profiler_proto(value: any) { + this._profiler_proto = value; + } + + start(address: string, filePath: string){ + // let loadPackage = proto_load.loadSync( + // filePath, + // { + // keepCase: true, + // longs: String, + // enums: String, + // defaults: true, + // oneofs: true + // } + // ); + // // profiler Proto + // this._profiler_proto = rpc.loadPackageDefinition(loadPackage); + // // get profilerProto service + // let profilerProto = this._profiler_proto.profiler; + // // client + // this._client = new profilerProto.IProfilerService('127.0.0.1:5555', rpc.credentials.createInsecure()); + } + + // Address + loadAddress(clientAddress: Address): string{ + return clientAddress.host + ':' + clientAddress.port; + }; + + public getProfilerClient(callback: any): any{ + return this._client; + }; + + public getCapabilities(callback: any) { + this._client. + this._client.getCapabilities(callback); + callback(); + }; + + public createSession(callback: any) { + this._client.createSession(callback); + callback(); + }; + + public startSession(callback: any) { + this._client.startSession(callback); + callback(); + }; + + public stopSession(callback: any) { + this._client.stopSession(callback); + callback(); + }; + + public destroySession(callback: any) { + this._client.destroySession(callback); + callback(); + }; + + public keepSession(callback: any) { + this._client.keepSession(callback); + callback(); + }; + + public shutdown(): void { + + }; + + public getChannel() { + return this._client.channelInterpretation; + }; + +} + +export interface Address { + // port + port: string | number; + + // host + host?: string | number; +} diff --git a/host/ide/src/trace/grpc/ProfilerController.ts b/host/ide/src/trace/grpc/ProfilerController.ts new file mode 100644 index 0000000000000000000000000000000000000000..bbc186a0c4b0dcccbba554244a326c6db99b5c85 --- /dev/null +++ b/host/ide/src/trace/grpc/ProfilerController.ts @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export class ClientContainer { + // private _credentials: rpc.ChannelCredentials | undefined; + // private _clients: { service: any, client?: rpc.Client, target: any }[] = []; + private _port: string | number | undefined; + private _host: string | undefined; + + /* get clients(): { service: any; client?: rpc.Client; target: any }[] { + return this._clients; + } + + set clients(value: { service: any; client?: rpc.Client; target: any }[]) { + this._clients = value; + }*/ + + /* get credentials(): rpc.ChannelCredentials | undefined { + return this._credentials; + } + + set credentials(value: rpc.ChannelCredentials | undefined) { + this._credentials = value; + }*/ + + get port(): string | number | undefined { + return this._port; + } + + set port(value: string | number | undefined) { + this._port = value; + } + + get host(): string | undefined { + return this._host; + } + + set host(value: string | undefined) { + this._host = value; + } + + public registryClient(target: any, path: string) { + // let packageDefinition = proto_load.loadSync(path, { + // keepCase: true, + // longs: String, + // enums: String, + // defaults: true, + // oneofs: true + // }); + // let protoDescriptor = rpc.loadPackageDefinition(packageDefinition); + // + // const packages = Object.keys(protoDescriptor); + // for (let packageKey of packages) { + // for (let key in protoDescriptor[packageKey]) { + // + // } + // } + }; + + public start() { + this.loadSettings(); + this._registryClient(); + } + + private loadSettings() { + let { host, port} = SettingRegistry.settings; + this._host = host; + this._port = port; + } + + private _registryClient() { + // for (let clientContainer of this._clients) { + // let client: rpc.Client = new clientContainer.service( + // `${this.host}:${this.port}`, + // this.credentials + // ); + // clientContainer.client = client; + // } + } +} + + +export class SettingRegistry { + static settings: Settings; + + static registry(settings: Settings) { + this.settings = settings; + } +} + +export interface Settings { + port: string | number; + + host?: string; +} \ No newline at end of file diff --git a/host/ide/src/trace/proto/common_types.proto b/host/ide/src/trace/proto/common_types.proto new file mode 100644 index 0000000000000000000000000000000000000000..b78ca892ac9972c5d55fadfbf8ce6083efe2e729 --- /dev/null +++ b/host/ide/src/trace/proto/common_types.proto @@ -0,0 +1,58 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +// option java_package = "ohos.devtools.datasources.transport.grpc.service"; + +// Common message define for profiler tools, imported by profiler and plugin proto file. +message ProfilerPluginConfig { + string name = 1; + string plugin_sha256 = 2; + uint32 sample_interval = 3; + bytes config_data = 4; +} + +message ProfilerPluginState { + string name = 1; + enum State { + INITED = 0; + REGISTERED = 1; // registered to plugin service. + LOADED = 2; // have created session. + IN_SESSION = 3; // have started session. + }; + State state = 2; +} + +// for FetchDataResponse +message ProfilerPluginData { + string name = 1; + uint32 status = 2; + bytes data = 3; + enum ClockId { + CLOCKID_REALTIME = 0; + CLOCKID_REALTIME_ALARM = 1; // since Linux 3.0; Linux-specific + CLOCKID_REALTIME_COARSE = 2; // since Linux 2.6.32; Linux-specific + CLOCKID_TAI = 3; // since Linux 3.10; Linux-specific + CLOCKID_MONOTONIC = 4; + CLOCKID_MONOTONIC_COARSE = 5; // since Linux 2.6.32; Linux-specific + CLOCKID_MONOTONIC_RAW = 6; // since Linux 2.6.28; Linux-specific + CLOCKID_BOOTTIME = 7; // since Linux 2.6.39; Linux-specific + CLOCKID_BOOTTIME_ALARM = 8; // since Linux 3.0; Linux-specific + CLOCKID_PROCESS_CPUTIME_ID = 9; // since Linux 2.6.12 + CLOCKID_THREAD_CPUTIME_ID = 10; // since Linux 2.6.12 + }; + ClockId clock_id = 4; + uint64 tv_sec = 5; + uint64 tv_nsec = 6; +} diff --git a/host/ide/src/trace/proto/profiler_service.proto b/host/ide/src/trace/proto/profiler_service.proto new file mode 100644 index 0000000000000000000000000000000000000000..b46d7f235406ca1c91bfe3bdd68c00fb1170567f --- /dev/null +++ b/host/ide/src/trace/proto/profiler_service.proto @@ -0,0 +1,47 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +// option java_package = "ohos.devtools.datasources.transport.grpc.service"; + +import "profiler_service_types.proto"; + +// RPC interface between profiler service and host service +// Use protobuf plug-ins to convert proto define to +// source and header files during the build process. + +package profiler; + +service IProfilerService { + // get all plugin infos and capabilities. + rpc GetCapabilities(GetCapabilitiesRequest) returns (GetCapabilitiesResponse); + + // create tracing sesion and pass tracing config to plugins. + rpc CreateSession(CreateSessionRequest) returns (CreateSessionResponse); + + // start tracing session, active server side tracing triggers. + rpc StartSession(StartSessionRequest) returns (StartSessionResponse); + + // get server-side cached tracing data since current session started. + rpc FetchData(FetchDataRequest) returns (stream FetchDataResponse); + + // stop tracing session, deactivate server side tracing triggers. + rpc StopSession(StopSessionRequest) returns (StopSessionResponse); + + // destroy tracing session. + rpc DestroySession(DestroySessionRequest) returns (DestroySessionResponse); + + // keep tracing session alive, call this interface will restart session expire count down task. + rpc KeepSession(KeepSessionRequest) returns (KeepSessionResponse); +} diff --git a/host/ide/src/trace/proto/profiler_service_types.proto b/host/ide/src/trace/proto/profiler_service_types.proto new file mode 100644 index 0000000000000000000000000000000000000000..8273ace2f4f33e4708c58c1cf38e39cdf06c7f47 --- /dev/null +++ b/host/ide/src/trace/proto/profiler_service_types.proto @@ -0,0 +1,129 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +// option java_package = "ohos.devtools.datasources.transport.grpc.service"; + +import "common_types.proto"; + +// Message define for profiler service, imported by profiler service proto file. +// for GetCapabilities +message GetCapabilitiesRequest { + uint32 request_id = 1; +} + +message ProfilerPluginCapability { + string path = 1; + string name = 2; +} + +message GetCapabilitiesResponse { + uint32 status = 1; + repeated ProfilerPluginCapability capabilities = 2; +} + + +// for CreateSessionRequest +message ProfilerSessionConfig { + message BufferConfig { + enum Policy { + RECYCLE = 0; + FLATTEN = 1; + }; + uint32 pages = 1; + Policy policy = 2; + } + repeated BufferConfig buffers = 1; + + enum Mode { + OFFLINE = 0; // save all plugin results to result file. + ONLINE = 1; // push all plugin results to host PC with streamed FetchDataResponse. + }; + Mode session_mode = 2; + string result_file = 3; // for OFFLINE mode, result file path + uint32 result_max_size = 4; // for OFFLINE mode, result file max size in KB + uint32 sample_duration = 5; // for OFFLINE mode, sample duration in ms + uint32 keep_alive_time = 6; // if set to non-zero value, session will auto-destroyed after CreateSession in ms +} + +message CreateSessionRequest { + uint32 request_id = 1; + ProfilerSessionConfig session_config = 2; + repeated ProfilerPluginConfig plugin_configs = 3; +} + +message CreateSessionResponse { + uint32 status = 1; + uint32 session_id = 2; + repeated ProfilerPluginState plugin_status = 3; +} + +// for StartSession +message StartSessionRequest { + uint32 request_id = 1; + uint32 session_id = 2; + repeated ProfilerPluginConfig update_configs = 3; +} + +message StartSessionResponse { + uint32 status = 1; + repeated ProfilerPluginState plugin_status = 3; +} + +// for FetchData +message FetchDataRequest { + uint32 request_id = 1; + uint32 session_id = 2; + bytes addtion_data = 3; +} + +message FetchDataResponse { + uint32 status = 1; + uint32 response_id = 2; + bool has_more = 3; + repeated ProfilerPluginData plugin_data = 4; +} + +// for StopSession +message StopSessionRequest { + uint32 request_id = 1; + uint32 session_id = 2; +} + +message StopSessionResponse { + uint32 status = 1; + repeated ProfilerPluginState plugin_status = 3; +} + +// for DestroySession +message DestroySessionRequest { + uint32 request_id = 1; + uint32 session_id = 2; +} + +message DestroySessionResponse { + uint32 status = 1; + repeated ProfilerPluginState plugin_status = 3; +} + +// for KeepSession +message KeepSessionRequest { + uint32 request_id = 1; + uint32 session_id = 2; + uint32 keep_alive_time = 3; +} + +message KeepSessionResponse { + uint32 status = 1; +} diff --git a/host/ide/test/base-ui/button/LitButton.test.ts b/host/ide/test/base-ui/button/LitButton.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..cf05686eba2d3082e14fc1d6d32c604c0dcc49b8 --- /dev/null +++ b/host/ide/test/base-ui/button/LitButton.test.ts @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitButton} from "../../../dist/base-ui/button/LitButton.js"; + +describe('button Test', ()=>{ + + it('buttonTest01', function () { + let litButton = new LitButton(); + expect(litButton).not.toBeUndefined() + }); +}) diff --git a/host/ide/test/base-ui/checkbox/LitCheckBox.test.ts b/host/ide/test/base-ui/checkbox/LitCheckBox.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..3512ce08425f9a10ee6a9330ff3b4779a247025e --- /dev/null +++ b/host/ide/test/base-ui/checkbox/LitCheckBox.test.ts @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitCheckBox} from "../../../dist/base-ui/checkbox/LitCheckBox.js"; + +describe('checkBox Test', ()=>{ + + it('checkBoxTest01', function () { + let litCheckBox = new LitCheckBox(); + expect(litCheckBox).not.toBeUndefined() + expect(litCheckBox).not.toBeNull() + }); + + + it('checkBoxTest02', function () { + let litCheckBox = new LitCheckBox(); + expect(litCheckBox.checked).toBeFalsy(); + }); + + it('checkBoxTest03', function () { + let litCheckBox = new LitCheckBox(); + litCheckBox.checked = true + expect(litCheckBox.checked).toBeTruthy(); + }); + + + it('checkBoxTest04', function () { + let litCheckBox = new LitCheckBox(); + expect(litCheckBox.value).toEqual(""); + }); + + + it('checkBoxTest04', function () { + let litCheckBox = new LitCheckBox(); + litCheckBox.value = "test" + expect(litCheckBox.value).toEqual("test"); + }); + + + it('checkBoxTest05', function () { + document.body.innerHTML = ` + ` + let litCheckBox = new LitCheckBox(); + litCheckBox.checked = false + expect(litCheckBox.checked).toBeFalsy(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/base-ui/checkbox/LitCheckBoxWithText.test.ts b/host/ide/test/base-ui/checkbox/LitCheckBoxWithText.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..271b2437f6cf61c15a193536602f04da7df598dc --- /dev/null +++ b/host/ide/test/base-ui/checkbox/LitCheckBoxWithText.test.ts @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitCheckBoxWithText} from "../../../dist/base-ui/checkbox/LitCheckBoxWithText.js"; + +describe('checkBoxWithText Test', ()=>{ + + it('checkBoxWithTextTest01', function () { + let litCheckBoxWithText = new LitCheckBoxWithText(); + expect(litCheckBoxWithText).not.toBeUndefined() + expect(litCheckBoxWithText).not.toBeNull() + }); + + + it('checkBoxWithTextTest02', function () { + let litCheckBoxWithText = new LitCheckBoxWithText(); + expect(litCheckBoxWithText.checked).toBeFalsy(); + }); + + it('checkBoxWithTextTest03', function () { + let litCheckBoxWithText = new LitCheckBoxWithText(); + litCheckBoxWithText.checked = true + expect(litCheckBoxWithText.checked).toBeTruthy(); + }); + + it('checkBoxWithTextTest03', function () { + let litCheckBoxWithText = new LitCheckBoxWithText(); + litCheckBoxWithText.checked = false + expect(litCheckBoxWithText.checked).toBeFalsy(); + }); + + it('checkBoxWithTextTest04', function () { + let litCheckBoxWithText = new LitCheckBoxWithText(); + expect(litCheckBoxWithText.text).toEqual(""); + }); + + it('checkBoxWithTextTest05', function () { + let litCheckBoxWithText = new LitCheckBoxWithText(); + litCheckBoxWithText.text = "test" + expect(litCheckBoxWithText.text).toEqual("test"); + }); + + it('checkBoxWithTextTest05', function () { + let litCheckBoxWithText = new LitCheckBoxWithText(); + expect(litCheckBoxWithText.lowerlimit).toEqual(undefined); + }); + + it('checkBoxWithTextTest05', function () { + let litCheckBoxWithText = new LitCheckBoxWithText(); + litCheckBoxWithText.lowerlimit = "111" + expect(litCheckBoxWithText.lowerlimit).toEqual("111"); + }); + + it('checkBoxWithTextTest05', function () { + let litCheckBoxWithText = new LitCheckBoxWithText(); + litCheckBoxWithText.uplimit = "111" + expect(litCheckBoxWithText.uplimit).toEqual("111"); + }); +}) \ No newline at end of file diff --git a/host/ide/test/base-ui/checkbox/LitCheckGroup.test.ts b/host/ide/test/base-ui/checkbox/LitCheckGroup.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..57bd9df3cf91d8dfbdc5d6208844b4f485058142 --- /dev/null +++ b/host/ide/test/base-ui/checkbox/LitCheckGroup.test.ts @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +// @ts-ignore +import {LitCheckGroup} from "../../../dist/base-ui/checkbox/LitCheckGroup.js"; + +describe('LitCheckGroup Test', ()=>{ + + it('LitCheckGroupTest01', function () { + let litCheckGroup = new LitCheckGroup(); + expect(litCheckGroup).not.toBeUndefined() + expect(litCheckGroup).not.toBeNull() + }); + + + it('LitCheckGroupTest02', function () { + let litCheckGroup = new LitCheckGroup(); + expect(litCheckGroup.direction).toBeNull(); + }); + + it('LitCheckGroupTest03', function () { + let litCheckGroup = new LitCheckGroup(); + expect(litCheckGroup.value).toEqual([]); + }); + +}) \ No newline at end of file diff --git a/host/ide/test/base-ui/icon/LitIcon.test.ts b/host/ide/test/base-ui/icon/LitIcon.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..dd3ab13755303d49378248bf0e2ab9c11efbf49b --- /dev/null +++ b/host/ide/test/base-ui/icon/LitIcon.test.ts @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitIcon} from "../../../dist/base-ui/icon/LitIcon.js"; + +describe("testLitIcon Test", () => { + + it('testLitIcon01', () => { + let litIcon = new LitIcon(); + expect(litIcon).not.toBeUndefined() + expect(litIcon).not.toBeNull() + }); + + it('testLitIcon02', () => { + let litIcon = new LitIcon(); + expect(litIcon.path).toBeUndefined() + }); + + it('testLitIcon03', () => { + let litIcon = new LitIcon(); + litIcon.path ="ss" + expect(litIcon.path).toBeUndefined() + }); + + it('testLitIcon04', () => { + let litIcon = new LitIcon(); + expect(litIcon.size).toBe(0) + }); + + it('testLitIcon05', () => { + let litIcon = new LitIcon(); + litIcon.size = 1024 + expect(litIcon.size).toBe(1024) + }); + + it('testLitIcon06', () => { + let litIcon = new LitIcon(); + expect(litIcon.name).toBe("") + }); + + it('testLitIcon07', () => { + let litIcon = new LitIcon(); + litIcon.name = "sss" + expect(litIcon.name).toBe("sss") + }); +}) diff --git a/host/ide/test/base-ui/menu/LitMainMenu.test.ts b/host/ide/test/base-ui/menu/LitMainMenu.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..dc0fc181d802969b974befe9817ab6548afb2e17 --- /dev/null +++ b/host/ide/test/base-ui/menu/LitMainMenu.test.ts @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitMainMenu} from "../../../dist/base-ui/menu/LitMainMenu.js"; +import {MenuItem} from "../../../src/base-ui/menu/LitMainMenu.js"; + +describe("LitMainMenu Test", () => { + + it('LitMainMenu01', () => { + let litMainMenu = new LitMainMenu(); + expect(litMainMenu).not.toBeUndefined() + expect(litMainMenu).not.toBeNull() + }); + + it('LitMainMenu01', () => { + let litMainMenu = new LitMainMenu(); + expect(litMainMenu).not.toBeUndefined() + expect(litMainMenu).not.toBeNull() + }); + + it('LitMainMenu02', () => { + let litMainMenu = new LitMainMenu(); + litMainMenu.menus = [ + { + collapsed: false, + title: 'Navigation', + describe: 'Open or record a new trace', + children: [ + { + title: "Open trace file", + icon: "folder", + fileChoose: true, + fileHandler: function (ev: InputEvent) { + } + + }, + { + title: "Record new trace", icon: "copyhovered", clickHandler: function (item: MenuItem) { + } + } + ] + } + ] + expect(litMainMenu.menus.length).toBe(1) + }); +}) diff --git a/host/ide/test/base-ui/menu/LitMainMenuGroup.test.ts b/host/ide/test/base-ui/menu/LitMainMenuGroup.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..5c870524864714552a9681c2eb18b4afe5ae838c --- /dev/null +++ b/host/ide/test/base-ui/menu/LitMainMenuGroup.test.ts @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitMainMenuGroup} from "../../../dist/base-ui/menu/LitMainMenuGroup.js"; + +describe("litMainMenuGroup Test", () => { + + it('litMainMenuGroup01', () => { + let litMainMenuGroup = new LitMainMenuGroup(); + expect(litMainMenuGroup).not.toBeUndefined() + expect(litMainMenuGroup).not.toBeNull() + }); + + it('litMainMenuGroup02', () => { + let litMainMenuGroup = new LitMainMenuGroup(); + expect(litMainMenuGroup.collapsed).toBeFalsy() + }); + + + it('litMainMenuGroup03', () => { + let litMainMenuGroup = new LitMainMenuGroup(); + litMainMenuGroup.collapsed = true + expect(litMainMenuGroup.collapsed).toBeTruthy() + }); + + it('litMainMenuGroup03', () => { + let litMainMenuGroup = new LitMainMenuGroup(); + litMainMenuGroup.collapsed = false + expect(litMainMenuGroup.collapsed).toBeFalsy() + }); +}) diff --git a/host/ide/test/base-ui/menu/LitMainMenuItem.test.ts b/host/ide/test/base-ui/menu/LitMainMenuItem.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..4dc93a17147dad3337b1f7d8715777aa0d0ac8d7 --- /dev/null +++ b/host/ide/test/base-ui/menu/LitMainMenuItem.test.ts @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitMainMenuItem} from "../../../dist/base-ui/menu/LitMainMenuItem.js"; + +describe("litMainMenuItem Test", () => { + + it('litMainMenuItem01', () => { + let litMainMenuItem = new LitMainMenuItem(); + expect(litMainMenuItem).not.toBeUndefined() + expect(litMainMenuItem).not.toBeNull() + }); + + it('litMainMenuItem02', () => { + let litMainMenuItem = new LitMainMenuItem(); + expect(litMainMenuItem.title).toEqual("") + }); + + it('litMainMenuItem03', () => { + let litMainMenuItem = new LitMainMenuItem(); + litMainMenuItem.title ="test" + expect(litMainMenuItem.title).toEqual("test") + }); + + + it('litMainMenuItem04', () => { + document.body.innerHTML = ` + ` + let litMainMenuItem = new LitMainMenuItem(); + litMainMenuItem.title ="test02" + expect(litMainMenuItem.title).toEqual("test02") + }); + + it('litMainMenuItem05', () => { + document.body.innerHTML = ` + ` + let litMainMenuItem = new LitMainMenuItem(); + litMainMenuItem.title ="test03" + expect(litMainMenuItem.title).toEqual("test03") + }); +}) diff --git a/host/ide/test/base-ui/popover/LitPopContent.test.ts b/host/ide/test/base-ui/popover/LitPopContent.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..b21ca9bbe6a7ab54ae05c5436ca6089a976a999a --- /dev/null +++ b/host/ide/test/base-ui/popover/LitPopContent.test.ts @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore + +import {LitPopContent} from "../../../dist/base-ui/popover/LitPopContent.js"; + +describe("LitPopCont Test", () => { + + it('LitPopCont01', () => { + let litPopContent = new LitPopContent(); + expect(litPopContent).not.toBeUndefined() + expect(litPopContent).not.toBeNull() + }); + + it('LitPopCont02', () => { + let litPopContent = new LitPopContent(); + expect(litPopContent.open).toBeFalsy() + }); + + + it('LitPopCont03', () => { + let litPopContent = new LitPopContent(); + litPopContent.open = false + expect(litPopContent.open).toBeFalsy() + }); + + + it('LitPopCont04', () => { + let litPopContent = new LitPopContent(); + litPopContent.open = true + expect(litPopContent.open).toBeTruthy() + }); + + it('LitPopCont04', () => { + let litPopContent = new LitPopContent(); + litPopContent.name = "11" + expect(litPopContent.name).toEqual("11") + }); +}) diff --git a/host/ide/test/base-ui/popover/LitPopover.test.ts b/host/ide/test/base-ui/popover/LitPopover.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..a8be4f48cc2a9b0df11221286b0572cfc5be2e2c --- /dev/null +++ b/host/ide/test/base-ui/popover/LitPopover.test.ts @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitPopover} from "../../../dist/base-ui/popover/LitPopover.js"; + +describe("LitPopover Test", () => { + it('LitPopover01', () => { + let litPopover = new LitPopover(); + expect(litPopover).not.toBeUndefined() + expect(litPopover).not.toBeNull() + }); + + it('LitPopover02', () => { + let litPopover = new LitPopover(); + expect(litPopover.open).toBeFalsy() + }); + + it('LitPopover03', () => { + let litPopover = new LitPopover(); + litPopover.open = true + expect(litPopover.open).toBeTruthy() + }); + + it('LitPopover04', () => { + let litPopover = new LitPopover(); + litPopover.open = false + expect(litPopover.open).toBeFalsy() + }); + + + it('LitPopover05', () => { + let litPopover = new LitPopover(); + litPopover.direction = "topleft" + expect(litPopover.direction).toEqual("topleft") + }); + + it('LitPopover06', () => { + let litPopover = new LitPopover(); + expect(litPopover.direction).toEqual("topright") + }); + + it('LitPopover07', () => { + let litPopover = new LitPopover(); + litPopover.type = "multiple" + litPopover.dataSource = [{ + text: "# Samples", + isSelected: true + }] + expect(litPopover.select).toEqual(["# Samples"]) + }); + + it('LitPopover07', () => { + let litPopover = new LitPopover(); + litPopover.type = "radio" + litPopover.dataSource = [{ + text: "# Samples", + isSelected: true + }] + expect(litPopover.select).toEqual(["# Samples"]) + }); + + it('LitPopover08', () => { + let litPopover = new LitPopover(); + litPopover.type = "multiple-text" + litPopover.dataSource = [{ + text: "# Samples", + isSelected: true + }] + expect(litPopover.select).toEqual(["# Samples"]) + }); + + + it('LitPopover09', () => { + let litPopover = new LitPopover(); + litPopover.type = "radio" + litPopover.title = "tee" + litPopover.dataSource = [{ + text: "# Samples", + isSelected: true + }] + expect(litPopover.select).toEqual(["# Samples"]) + }); +}) diff --git a/host/ide/test/base-ui/progress-bar/LitProgressBar.test.ts b/host/ide/test/base-ui/progress-bar/LitProgressBar.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0f2f37d313c34438c46b524784c12b6e177b0e64 --- /dev/null +++ b/host/ide/test/base-ui/progress-bar/LitProgressBar.test.ts @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitProgressBar} from "../../../dist/base-ui/progress-bar/LitProgressBar.js"; + +describe('LitProgressBar Test', ()=>{ + let litProgressBar = new LitProgressBar(); + litProgressBar.loading = '' + litProgressBar.loading = 'load' + + it('LitProgressBarTest03', ()=>{ + expect(litProgressBar.loading).toBeTruthy(); + }) +}) diff --git a/host/ide/test/base-ui/radiobox/LitRadioBox.test.ts b/host/ide/test/base-ui/radiobox/LitRadioBox.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..7bd211a9d4b35cc0ba2c08f92e8e3127c4112739 --- /dev/null +++ b/host/ide/test/base-ui/radiobox/LitRadioBox.test.ts @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitRadioBox} from "../../../dist/base-ui/radiobox/LitRadioBox.js"; + +// @ts-ignore +import {LitRadioGroup} from "../../../dist/base-ui/radiobox/LitRadioGroup.js"; + +describe('LitRadioBox Test', ()=>{ + let litRadioBox = new LitRadioBox(); + let litRadioGroup = new LitRadioGroup() + + litRadioGroup.layout = 'layout' + + litRadioBox.checked = true + litRadioBox.checked = false + litRadioBox.value = 'value' + litRadioBox.dis = 'dis' + it('LitRadioBoxTest01', ()=>{ + expect(litRadioBox.name).toBeNull(); + }) + + it('LitRadioBoxTest02', ()=>{ + expect(litRadioBox.value).toBe('value'); + }) + + it('litRadioGroupTest01', ()=>{ + let isReturn = litRadioGroup.value.length == 0 + expect(isReturn).toBeTruthy(); + }) +}) diff --git a/host/ide/test/base-ui/slider/LitSlider.test.ts b/host/ide/test/base-ui/slider/LitSlider.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d05e457757270f7c444a7ffd859e5cffc1e9120a --- /dev/null +++ b/host/ide/test/base-ui/slider/LitSlider.test.ts @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitSlider} from "../../../dist/base-ui/slider/LitSlider.js"; + +describe('LitSlider Test', ()=>{ + let litSliderPanel = new LitSlider(); + + litSliderPanel.disabledX = 'disabledX' + litSliderPanel.customSlider = 'customSlider' + litSliderPanel.customLine = 'customLine' + litSliderPanel.customButton = 'customButton' + litSliderPanel.percent = 'percent' + litSliderPanel.resultUnit = 'resultUnit' + + litSliderPanel.litSlider = jest.fn(()=> true) + + litSliderPanel.sliderStyle = 'sliderStyle' + + it('LitSliderTest01', ()=>{ + expect(litSliderPanel.disabledX).toEqual(''); + }) + + it('LitSliderTest02', ()=>{ + expect(litSliderPanel.customSlider).toEqual(''); + }) + + it('LitSliderTest03', ()=>{ + expect(litSliderPanel.customLine).toEqual('customLine'); + }) + + it('LitSliderTest04', ()=>{ + expect(litSliderPanel.customButton).toEqual('customButton'); + }) + + it('LitSliderTest05', ()=>{ + expect(litSliderPanel.percent).toEqual('percent'); + }) + + it('LitSliderTest06', ()=>{ + expect(litSliderPanel.resultUnit).toEqual('resultUnit'); + }) + + it('LitSliderTest07', ()=>{ + expect(litSliderPanel.formatSeconds(10)).toBe('00:00:10'); + }) + + it('LitSliderTest08', ()=>{ + expect(litSliderPanel.renderDefaultSlider()).toBeUndefined(); + }) + + it('LitSliderTest9', ()=>{ + expect(litSliderPanel.adoptedCallback()).toBeUndefined(); + }) + + it('LitSliderTest10', ()=>{ + litSliderPanel.litSlider.removeEventListener = jest.fn(()=> true) + litSliderPanel.litSlider.removeEventListener = jest.fn(()=> true) + litSliderPanel.litSliderButton = jest.fn(()=> true) + litSliderPanel.litSliderButton.removeEventListener = jest.fn(()=> true) + expect(litSliderPanel.disconnectedCallback()).toBeUndefined(); + }) +}) diff --git a/host/ide/test/base-ui/switch/LitSwitch.test.ts b/host/ide/test/base-ui/switch/LitSwitch.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..c0094b0a5583cee0b5d49cc45190e01327af11fa --- /dev/null +++ b/host/ide/test/base-ui/switch/LitSwitch.test.ts @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import LitSwitch from "../../../dist/base-ui/switch/lit-switch"; + +describe('LitSwitch Test', ()=>{ + let litSwitch = new LitSwitch(); + litSwitch.checked = true + litSwitch.checked = false + + it('LitSwitchTest01', ()=>{ + expect(litSwitch.name).toBeNull(); + }) + + it('LitSwitchTest02', ()=>{ + expect(litSwitch.disabled).toBeFalsy(); + }) + + it('LitSwitchTest03', ()=>{ + expect(litSwitch.checked).toBeFalsy(); + }) + + it('LitSwitchTest04', ()=>{ + LitSwitch.switch = document.querySelector("#switch") as HTMLInputElement; + expect(litSwitch.connectedCallback()).toBeUndefined() + }) + + it('LitSwitchTest05', ()=>{ + expect(litSwitch.attributeChangedCallback('disabled', 'disabled', '')).toBeUndefined() + }) + + it('LitSwitchTest06', ()=>{ + expect(litSwitch.attributeChangedCallback('disabled', 'disabled', null)).toBeUndefined() + }) + + it('LitSwitchTest07', ()=>{ + expect(litSwitch.attributeChangedCallback('checked', 'disabled', '')).toBeUndefined() + }) + + it('LitSwitchTest08', ()=>{ + expect(litSwitch.attributeChangedCallback('checked', 'disabled', null)).toBeUndefined() + }) +}) diff --git a/host/ide/test/base-ui/table/LitTable.test.ts b/host/ide/test/base-ui/table/LitTable.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..b011898ce8c6729a0412d1ca8bdc8553e204cd3c --- /dev/null +++ b/host/ide/test/base-ui/table/LitTable.test.ts @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitTable} from "../../../dist/base-ui/table/lit-table.js"; + +describe('LitTable Test', ()=>{ + let litTable = new LitTable(); + litTable.selectable = true + litTable.selectable = false + litTable.scrollY = 'scrollY' + + litTable.dataSource = [] + + litTable.dataSource = [{ + id: 1, + name: 'name' + },{ + id: 2, + name: 'nameValue' + }] + + JSON.parse = jest.fn(()=>[['children', 'father'], ['children', 'father']]) + + litTable.columns = litTable.columns || jest.fn(()=>true) + litTable.ds = jest.fn(()=>[{ + id: 1, + name: 'name' + },{ + id: 2, + name: 'nameValue' + }]) + + litTable.tbodyElement = jest.fn(()=> ({ + innerHTML: '' + })) + + litTable.tableColumns = jest.fn(()=>[]) + + litTable.tableColumns.forEach = jest.fn(()=>[]) + + + it('LitTableTest01', ()=>{ + expect(litTable.adoptedCallback()).toBeUndefined(); + }) + + it('LitTableTest02', ()=>{ + litTable.ds.forEach = jest.fn(()=> true) + expect(litTable.renderTable()).toBeUndefined(); + }) + + // it('LitTableTest03', ()=>{ + // litTable.parentNode = jest.fn(()=> true) + // litTable.parentNode.append = jest.fn(()=> true) + // expect(litTable.renderTreeTable()).toBeUndefined(); + // }) + + it('LitTableTest04', ()=>{ + litTable.switch = document.querySelector("#switch") as HTMLInputElement; + expect(litTable.connectedCallback()).toBeUndefined() + }) + + it('LitTableTest05', ()=>{ + let rowLength = litTable.getCheckRows().length == 0; + expect(rowLength).toBeTruthy() + }) + + it('LitTableTest06', ()=>{ + expect(litTable.deleteRowsCondition(()=>{ + return true + })).toBeUndefined() + }) +}) diff --git a/host/ide/test/base-ui/table/LitTableColumn.test.ts b/host/ide/test/base-ui/table/LitTableColumn.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..6a1fc57dc499056ffd0f3af004f74369215f7ef8 --- /dev/null +++ b/host/ide/test/base-ui/table/LitTableColumn.test.ts @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitTableColumn} from "../../../dist/base-ui/table/lit-table-column.js"; + +describe('LitTableGroup Test', ()=>{ + let litTableColumn = new LitTableColumn(); + litTableColumn.title = 'title' + + it('LitTableGroupTest01', ()=>{ + expect(litTableColumn.adoptedCallback()).toBeUndefined(); + }) + + it('LitTableGroupTest02', ()=>{ + expect(litTableColumn.connectedCallback()).toBeUndefined(); + }) +}) diff --git a/host/ide/test/base-ui/table/LitTableGroup.test.ts b/host/ide/test/base-ui/table/LitTableGroup.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..64ce85e320da07b7b950c46573f75cf6f71c57e3 --- /dev/null +++ b/host/ide/test/base-ui/table/LitTableGroup.test.ts @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitTableGroup} from "../../../dist/base-ui/table/lit-table-group.js"; + +describe('LitTableGroup Test', ()=>{ + let litTableGroup = new LitTableGroup(); + litTableGroup.title = 'title' + + it('LitTableGroupTest01', ()=>{ + expect(litTableGroup.adoptedCallback()).toBeUndefined(); + }) + + it('LitTableGroupTest02', ()=>{ + expect(litTableGroup.title).toBe('title'); + }) +}) diff --git a/host/ide/test/base-ui/tabs/LitTabpane.test.ts b/host/ide/test/base-ui/tabs/LitTabpane.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..2094ef94c137d232e6a4d97626bc9ba32cd70a96 --- /dev/null +++ b/host/ide/test/base-ui/tabs/LitTabpane.test.ts @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitTabpane} from "../../../dist/base-ui/tabs/lit-tabpane.js"; + +describe('LitTabPane Test', ()=>{ + let litTabPane = new LitTabpane(); + + litTabPane.tab = 'tab' + litTabPane.disabled = 'disabled' + litTabPane.hidden = 'hidden' + litTabPane.closeable = false + litTabPane.key = 'key' + + it('LitTabPaneTest1', ()=>{ + expect(litTabPane.attributeChangedCallback('disabled', 'disabled', '')).toBeUndefined() + }) + + it('LitTabPaneTest2', ()=>{ + expect(litTabPane.tab).toBe('tab'); + }) + + it('LitTabPaneTest3', ()=>{ + expect(litTabPane.icon).toBeNull(); + }) + + it('LitTabPaneTest4', ()=>{ + expect(litTabPane.disabled).toBeTruthy(); + }) + it('LitTabPaneTest5', ()=>{ + expect(litTabPane.hidden).toBeTruthy(); + }) + it('LitTabPaneTest6', ()=>{ + litTabPane.closeable = 'closeable' + expect(litTabPane.closeable).toBeTruthy(); + }) + it('LitTabPaneTest7', ()=>{ + expect(litTabPane.key).toBe('key'); + }) +}) diff --git a/host/ide/test/base-ui/tabs/LitTabs.test.ts b/host/ide/test/base-ui/tabs/LitTabs.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..06a740dbf6c48fc33908084313e0dbd1ed2b2385 --- /dev/null +++ b/host/ide/test/base-ui/tabs/LitTabs.test.ts @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {LitTabs} from "../../../dist/base-ui/tabs/lit-tabs.js"; + +describe('LitSwitch Test', ()=>{ + let litTabs = new LitTabs(); + + litTabs.position = 'position' + litTabs.mode = 'mode' + litTabs.activekey = 'activekey' + + litTabs.nav = jest.fn(()=>{ + let el = document.createElement('div'); + let htmlDivElement = document.createElement('div'); + htmlDivElement.setAttribute('class', 'nav-item[data-key=\'${key}\']') + + el.appendChild(htmlDivElement) + return el + }) + + LitTabs.nav = jest.fn(()=>{ + return document.createElement('div') as HTMLDivElement + }) + + LitTabs.nav.querySelectorAll = jest.fn(()=>{ + return ['fd'] + }) + + // it('litTabsTest01', ()=>{ + // litTabs.nav = jest.fn(()=> true) + // litTabs.nav.querySelector = jest.fn(()=> { + // return document.createElement('div') as HTMLDivElement + // }) + // litTabs.nav.querySelectorAll = jest.fn(()=> true) + // expect(litTabs.updateLabel('key', 'value')).toBeUndefined(); + // }) + + it('litTabsTest1', ()=>{ + expect(litTabs.activekey).toBe('activekey'); + }) + + it('litTabsTest02', ()=>{ + litTabs.nav = jest.fn(()=> true) + litTabs.nav.querySelector = jest.fn(()=> { + return document.createElement('div') as HTMLDivElement + }) + litTabs.nav.querySelectorAll = jest.fn(()=> true) + expect(litTabs.updateDisabled('key', 'value')).toBeUndefined(); + }) + + it('litTabsTest03', ()=>{ + litTabs.nav = jest.fn(()=> true) + litTabs.nav.querySelector = jest.fn(()=> { + return document.createElement('div') as HTMLDivElement + }) + litTabs.nav.querySelectorAll = jest.fn(()=> true) + expect(litTabs.updateCloseable('key', 'value')).toBeUndefined(); + }) + + it('litTabsTest04', ()=>{ + litTabs.nav = jest.fn(()=> true) + litTabs.nav.querySelector = jest.fn(()=> { + return document.createElement('div') as HTMLDivElement + }) + litTabs.nav.querySelectorAll = jest.fn(()=> true) + + expect(litTabs.updateHidden('key', 'value')).toBeUndefined(); + }) + + it('litTabsTest05', ()=>{ + expect(litTabs.initTabPos()).toBeUndefined(); + }) + + // it('litTabsTest07', ()=>{ + // litTabs.nav.querySelectorAll = jest.fn(()=> true) + // litTabs.nav.querySelectorAll.forEach = jest.fn(()=> true) + // expect(litTabs.activeByKey('newKey')).toBeNull(); + // }) + + it('litTabsTest06', ()=>{ + expect(litTabs.activePane('Key')).toBeFalsy(); + }) + + it('litTabsTest07', ()=>{ + expect(litTabs.connectedCallback()).toBeUndefined() + }) + it('litTabsTest8', ()=>{ + expect(litTabs.attributeChangedCallback('disabled', 'disabled', '')).toBeUndefined() + }) + + it('litTabsTest9', ()=>{ + expect(litTabs.adoptedCallback()).toBeUndefined(); + }) + + it('litTabsTest10', ()=>{ + expect(litTabs.position).toBe('position'); + }) + + it('litTabsTest11', ()=>{ + expect(litTabs.mode).toBe('mode'); + }) +}) diff --git a/host/ide/test/trace/SpApplication.test.ts b/host/ide/test/trace/SpApplication.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..c4817f6962f420c00f8a6cceecb5136120d1cfbb --- /dev/null +++ b/host/ide/test/trace/SpApplication.test.ts @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpApplication} from "../../dist/trace/SpApplication.js"; +import {LitMainMenu} from "../../src/base-ui/menu/LitMainMenu"; + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('spApplication Test', ()=>{ + it('spApplicationTest01', function () { + let spApplication = new SpApplication(); + expect(spApplication).not.toBeUndefined() + }); + + + it('spApplicationTest02', function () { + let spApplication = new SpApplication(); + expect(spApplication.sqlite).toBeFalsy() + }); + + + it('spApplicationTest03', function () { + let spApplication = new SpApplication(); + expect(spApplication.wasm).toBeFalsy() + }); + + it('spApplicationTest04', function () { + let spApplication = new SpApplication(); + expect(spApplication.server).toBeFalsy() + }); + + + it('spApplicationTest05', function () { + let spApplication = new SpApplication(); + spApplication.server = true; + expect(spApplication.server).toBeTruthy() + }); + + it('spApplicationTest06', function () { + let spApplication = new SpApplication(); + spApplication.server = false; + expect(spApplication.server).toBeFalsy() + }); + + it('spApplicationTest07', function () { + let spApplication = new SpApplication(); + spApplication.search = false; + expect(spApplication.search).toBeFalsy() + }); + + it('spApplicationTest08', function () { + let spApplication = new SpApplication(); + spApplication.search = true; + expect(spApplication.search).toBeUndefined() + }); + + it('spApplicationTest09', function () { + let spApplication = new SpApplication(); + expect(spApplication.dark).toBeFalsy() + }); + it('spApplicationTest010', function () { + let spApplication = new SpApplication(); + spApplication.dark = true; + expect(spApplication.dark).toBeTruthy() + }); + + it('spApplicationTest11', function () { + let spApplication = new SpApplication(); + spApplication.dark = false; + expect(spApplication.dark).toBeFalsy() + }); + + it('spApplicationTest12', function () { + let spApplication = new SpApplication(); + expect(spApplication.vs).toBeFalsy() + }); + it('spApplicationTest013', function () { + let spApplication = new SpApplication(); + spApplication.vs = true; + expect(spApplication.vs).toBeTruthy() + }); + + it('spApplicationTest14', function () { + let spApplication = new SpApplication(); + spApplication.vs = false; + expect(spApplication.vs).toBeFalsy() + }); + + it('spApplicationTest15',function (){ + let spApplication = new SpApplication(); + expect(spApplication.freshMenuDisable).toBeTruthy() + }) + + +}) diff --git a/host/ide/test/trace/bean/BoxSelection.test.ts b/host/ide/test/trace/bean/BoxSelection.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..1171184d06f232b293efcfd624c81a8f81ae8d38 --- /dev/null +++ b/host/ide/test/trace/bean/BoxSelection.test.ts @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SelectionParam, SelectionData, Counter, Fps} from "../../../dist/trace/bean/BoxSelection.js" + +describe('BoxSelection Test', ()=>{ + let selectionParam = new SelectionParam(); + let selectionData = new SelectionData(); + let counter = new Counter(); + let fps = new Fps(); + + it('BoxSelectionTest01', function () { + expect(selectionParam).not.toBeUndefined() + }); + + it('BoxSelectionTest02', function () { + expect(selectionData).not.toBeUndefined() + }); + + it('BoxSelectionTest03', function () { + expect(counter).not.toBeUndefined() + }); + + it('BoxSelectionTest04', function () { + expect(fps).not.toBeUndefined() + }); +}) diff --git a/host/ide/test/trace/bean/CpuFreqStruct.test.ts b/host/ide/test/trace/bean/CpuFreqStruct.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..1d716aa3fac33d601e13cb05705be1d3e5e9964c --- /dev/null +++ b/host/ide/test/trace/bean/CpuFreqStruct.test.ts @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {CpuFreqStruct} from "../../../dist/trace/bean/CpuFreqStruct.js" + +describe('CpuFreqStruct Test', ()=>{ + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + CpuFreqStruct.hoverCpuFreqStruct = void 0 + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + it('CpuFreqStructTest01', function () { + expect(CpuFreqStruct.draw(ctx, data)).toBeUndefined() + }); +}) diff --git a/host/ide/test/trace/bean/CpuStruct.test.ts b/host/ide/test/trace/bean/CpuStruct.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..266521c88c77e39de3dcf8a160b414c70d014684 --- /dev/null +++ b/host/ide/test/trace/bean/CpuStruct.test.ts @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {CpuStruct} from "../../../dist/trace/bean/CpuStruct.js" + +describe('CpuStruct Test', ()=>{ + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + it('CpuStructTest01', function () { + expect(CpuStruct.draw(ctx, data)).toBeUndefined() + }); + + it('CpuStructTest02', function () { + expect(CpuStruct.equals({}, data)).toBeTruthy(); + }); +}) diff --git a/host/ide/test/trace/bean/CpuUsage.test.ts b/host/ide/test/trace/bean/CpuUsage.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..920f4fcddf86c3b7706fe3bb8130a89d007ab6e1 --- /dev/null +++ b/host/ide/test/trace/bean/CpuUsage.test.ts @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {CpuUsage, Freq} from "../../../dist/trace/bean/CpuUsage.js" + +describe('CpuUsage Test', ()=>{ + let cpuUsage = new CpuUsage(); + let freq = new Freq(); + + it('CpuUsageTest01', function () { + expect(cpuUsage).not.toBeUndefined() + }); + + it('CpuUsageTest02', function () { + expect(freq).not.toBeUndefined() + }); +}) diff --git a/host/ide/test/trace/bean/FpsStruct.test.ts b/host/ide/test/trace/bean/FpsStruct.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..568a5a581dda243ccc47b271f99675f1c47a0b79 --- /dev/null +++ b/host/ide/test/trace/bean/FpsStruct.test.ts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {FpsStruct} from "../../../dist/trace/bean/FpsStruct.js" + +describe('FpsStruct Test', ()=>{ + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + it('FpsStructTest01', function () { + expect(FpsStruct.draw(ctx, data)).toBeUndefined() + }); +}) diff --git a/host/ide/test/trace/bean/FuncStruct.test.ts b/host/ide/test/trace/bean/FuncStruct.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..f2ac0d789322ff2fcd2a9a5df709d3db805074ac --- /dev/null +++ b/host/ide/test/trace/bean/FuncStruct.test.ts @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {FuncStruct} from "../../../dist/trace/bean/FuncStruct.js" + +describe('FuncStruct Test', ()=>{ + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const dataResource = { + frame: { + x: 20, + y: 20 + } + } + + const durData = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + dur: 5 + } + + FuncStruct.isSelected = jest.fn(()=> true) + + it('FuncStructTest01', function () { + expect(FuncStruct.draw(ctx, dataResource)).toBeUndefined() + }); + + it('FuncStructTest02', function () { + expect(FuncStruct.draw(ctx, durData)).toBeUndefined() + }); + it('FuncStructTest03', function () { + expect(FuncStruct.drawString(ctx, 2, durData, durData.frame)).toBeUndefined() + }); + + it('FuncStructTest04', function () { + expect(FuncStruct.isSelected({ + startTs: 10, + dur: 10, + funName: '' + })).toBeTruthy(); + }); + + it('FuncStructTest05', function () { + expect(FuncStruct.isBinder({ + startTs: 10, + dur: 10, + funName: '' + })).toBeFalsy(); + }); +}) diff --git a/host/ide/test/trace/bean/HeapStruct.test.ts b/host/ide/test/trace/bean/HeapStruct.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..bf92ccfd2af34ef3bd23f00868bd1819de871449 --- /dev/null +++ b/host/ide/test/trace/bean/HeapStruct.test.ts @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {HeapStruct} from "../../../dist/trace/bean/HeapStruct.js" + +describe('HeapStruct Test', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const dataSource = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + value: 50, + maxHeapSize: 50, + heapsize: 10 + } + + const reachData = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + value: 50, + startTime: 1 + } + + const nodeSource = { + startTime: 10, + dur: 10, + endTime: 20, + frame: { + width: 20 + } + } + + const heapStruct = new HeapStruct(); + + it('HeapStructTest01', function () { + expect(HeapStruct.draw(ctx, dataSource)).toBeUndefined() + }); + + it('HeapStructTest02', function () { + expect(HeapStruct.draw(ctx, reachData)).toBeUndefined() + }); + + it('HeapStructTest03', function () { + expect(HeapStruct.setFrame(nodeSource, 1, 10, 15, 30, nodeSource.frame)).toBeUndefined() + }); + + it('HeapStructTest04', function () { + expect(HeapStruct.setFrame(nodeSource, 1, 15, 20, 30, nodeSource.frame)).toBeUndefined() + }); + + it('HeapStructTest05', function () { + expect(HeapStruct.setFrame(nodeSource, 1, 10, 20, 30, nodeSource.frame)).toBeUndefined() + }); +}) diff --git a/host/ide/test/trace/bean/ProcessMemStruct.test.ts b/host/ide/test/trace/bean/ProcessMemStruct.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0dbb4abb45de837793399eb6a02d75431787b5a0 --- /dev/null +++ b/host/ide/test/trace/bean/ProcessMemStruct.test.ts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {ProcessMemStruct} from "../../../dist/trace/bean/ProcessMemStruct.js" + +describe('ProcessMemStruct Test', ()=>{ + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + it('ProcessMemStructTest01', function () { + expect(ProcessMemStruct.draw(ctx, data)).toBeUndefined() + }); +}) diff --git a/host/ide/test/trace/bean/ProcessStruct.test.ts b/host/ide/test/trace/bean/ProcessStruct.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..5128692940aa7ce1c205769f63d657dc9bba51ea --- /dev/null +++ b/host/ide/test/trace/bean/ProcessStruct.test.ts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {ProcessStruct} from "../../../dist/trace/bean/ProcessStruct.js" + +describe('ProcessStruct Test', ()=>{ + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + const data = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + value: 50 + } + it('ProcessStructTest01', function () { + expect(ProcessStruct.draw(ctx, data)).toBeUndefined() + }); +}) diff --git a/host/ide/test/trace/bean/StateProcessThread.test.ts b/host/ide/test/trace/bean/StateProcessThread.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..83be7ef5a9ace39a36da8cc01383120961303f10 --- /dev/null +++ b/host/ide/test/trace/bean/StateProcessThread.test.ts @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {StateProcessThread} from "../../../dist/trace/bean/StateProcessThread.js" + +describe('StateProcessThread Test', ()=>{ + let stateProcessThread = new StateProcessThread(); + + it('StateProcessThreadTest01', function () { + expect(stateProcessThread).not.toBeUndefined() + }); +}) diff --git a/host/ide/test/trace/bean/ThreadStruct.test.ts b/host/ide/test/trace/bean/ThreadStruct.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..82c8abf9ed4164162e67b154a48d2b0a5588ccb0 --- /dev/null +++ b/host/ide/test/trace/bean/ThreadStruct.test.ts @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {ThreadStruct} from "../../../dist/trace/bean/ThreadStruct.js" + +describe('ThreadStruct Test', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + const dataSource = { + frame: { + x: 20, + y: 20, + width: 100, + height: 100 + }, + startNS: 200, + state: '' + } + const equalsData = { + value: 50, + cpu: 1, + tid: 1, + state: 1, + startTime: 1, + dur: 1 + } + + it('ThreadStructTest01', function () { + expect(ThreadStruct.draw(ctx, dataSource)).toBeUndefined() + }); + + it('ThreadStructTest02', function () { + dataSource.state = "S" + expect(ThreadStruct.draw(ctx, dataSource)).toBeUndefined() + }); + + it('ThreadStructTest03', function () { + dataSource.state = "R" + expect(ThreadStruct.draw(ctx, dataSource)).toBeUndefined() + }); + + it('ThreadStructTest04', function () { + dataSource.state = "D" + expect(ThreadStruct.draw(ctx, dataSource)).toBeUndefined() + }); + + it('ThreadStructTest05', function () { + dataSource.state = "Running" + expect(ThreadStruct.draw(ctx, dataSource)).toBeUndefined() + }); + + it('ThreadStructTest06', function () { + expect(ThreadStruct.drawString(ctx, '', 2, dataSource.frame)).toBeUndefined() + }); + + it('ThreadStructTest07', function () { + dataSource.frame.width = 10000000000000000; + expect(ThreadStruct.drawString(ctx, 'ThreadStructTest07', 1, dataSource.frame)).toBeUndefined() + }); + + it('ThreadStructTest08', function () { + expect(ThreadStruct.equals(equalsData, equalsData)).toBeTruthy() + }); + + it('ThreadStructTest09', function () { + expect(ThreadStruct.equals([], dataSource)).toBeFalsy() + }); + + it('ThreadStructTest10', function () { + dataSource.state = 'ThreadStructTest10' + expect(ThreadStruct.getEndState(1)).toBe('') + }); +}) diff --git a/host/ide/test/trace/component/FrameChart.test.ts b/host/ide/test/trace/component/FrameChart.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..71c0410c77dad47efb71e64efd3353b9633dfbc9 --- /dev/null +++ b/host/ide/test/trace/component/FrameChart.test.ts @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {FrameChart} from "../../../dist/trace/component/FrameChart.js" + + +describe('FrameChart Test', () => { + + let node= [ + {children: ''}, + {children:{length:1}} + ] + + + it('FrameChartTest01', function () { + let frameChart = new FrameChart(); + frameChart.data = false; + expect(frameChart.data).toBeFalsy(); + }); + + it('FrameChartTest02', function () { + let frameChart = new FrameChart(); + expect(frameChart.data).toBeUndefined(); + }); + + it('FrameChartTest03', function () { + let frameChart = new FrameChart(); + frameChart.selectTotalSize = true; + expect(frameChart.selectTotalSize).toBeUndefined(); + }); + + it('FrameChartTest04', function () { + let frameChart = new FrameChart(); + frameChart.maxDepth = true; + expect(frameChart.maxDepth).toBeUndefined(); + }); + + it('FrameChartTest05',function () { + let frameChart = new FrameChart(); + let result = frameChart.cavasContext.lineWidth ; + expect(result).toBe(1); + }) + + it('FrameChartTest06', function () { + let frameChart = new FrameChart(); + expect(frameChart.drawScale()).toBeUndefined(); + }); + + it('FrameChartTest07', function () { + let frameChart = new FrameChart(); + expect(frameChart.calculateChartData()).toBeUndefined(); + }); + + it('FrameChartTest08', function () { + let frameChart = new FrameChart(); + expect(frameChart.darwTypeChart(node)).toBeUndefined(); + }); + + it('FrameChartTest09', function () { + let frameChart = new FrameChart(); + frameChart.mode = true; + expect(frameChart.mode).toBeTruthy(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/SpRecordTrace.test.ts b/host/ide/test/trace/component/SpRecordTrace.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0a396a7c47eca687b40fa3795f2dae74337996f8 --- /dev/null +++ b/host/ide/test/trace/component/SpRecordTrace.test.ts @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpRecordTrace} from "../../../dist/trace/component/SpRecordTrace.js" +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); +describe('SpRecordTrace Test', () => { + + let spRecordTrace = new SpRecordTrace(); + + it('SpRecordTraceTest01', function () { + expect(spRecordTrace.initHtml()).not.toBe('') + }); + it('SpRecordTraceTest02', function () { + expect(spRecordTrace.initElements()).toBeUndefined() + }); + it('SpRecordTraceTest03', function () { + let toReturnWith = spRecordTrace.createFpsPluginConfig(); + expect(toReturnWith.sampleInterval).toBe(1000); + }); + it('SpRecordTraceTest04', function () { + let traceEvents = spRecordTrace.createTraceEvents(['Scheduling details', 'CPU Frequency and idle states', + 'High frequency memory', 'Advanced ftrace config', 'Syscalls']); + expect(traceEvents[0].indexOf('binder/binder_lock')).toBe(-1) + }); + +}) diff --git a/host/ide/test/trace/component/SpRecyclerSystemTrace.test.ts b/host/ide/test/trace/component/SpRecyclerSystemTrace.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..140f8b6feb64ac239e6f89165e67da4bf2f6d15f --- /dev/null +++ b/host/ide/test/trace/component/SpRecyclerSystemTrace.test.ts @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +// @ts-ignore +import {SpRecyclerSystemTrace} from "../../../dist/trace/component/SpRecyclerSystemTrace.js" + +describe('SpRecyclerSystemTrace Test', ()=>{ + + let spRecyclerSystemTrace = new SpRecyclerSystemTrace(); + + spRecyclerSystemTrace.initElements = jest.fn(()=> true) + + + it('SpRecyclerSystemTraceTest01', function () { + expect(spRecyclerSystemTrace.getScrollWidth()).toBe(1) + }); + + it('SpRecyclerSystemTraceTest02', function () { + let resultLength = spRecyclerSystemTrace.getVisibleRows([{}]).length; + expect(resultLength).toBe(0) + }); + + it('SpRecyclerSystemTraceTest03', function () { + expect(spRecyclerSystemTrace.timerShaftELRangeChange('')).toBeUndefined() + }); + + it('SpRecyclerSystemTraceTest04', function () { + expect(spRecyclerSystemTrace.rowsElOnScroll('Scroll')).toBeUndefined() + }); + + it('SpRecyclerSystemTraceTest05', function () { + expect(spRecyclerSystemTrace.documentOnMouseDown('MouseDown')).toBeUndefined() + }); + + it('SpRecyclerSystemTraceTest06', function () { + expect(spRecyclerSystemTrace.documentOnMouseUp('MouseUp')).toBeUndefined() + }); + + it('SpRecyclerSystemTraceTest07', function () { + spRecyclerSystemTrace.rangeSelec = jest.fn(()=>true) + spRecyclerSystemTrace.rangeSelect.mouseMove = jest.fn(()=>true) + expect(spRecyclerSystemTrace.documentOnMouseMove('MouseMove')).toBeUndefined() + }); + + it('SpRecyclerSystemTraceTest08', function () { + expect(spRecyclerSystemTrace.hoverStructNull('')).toBeUndefined() + }); + + it('SpRecyclerSystemTraceTest09', function () { + expect(spRecyclerSystemTrace.selectStructNull('')).toBeUndefined() + }); + + it('SpRecyclerSystemTraceTest10', function () { + spRecyclerSystemTrace.rangeSelec = jest.fn(()=>true) + spRecyclerSystemTrace.rangeSelect.mouseMove = jest.fn(()=>true) + expect(spRecyclerSystemTrace.documentOnClick('OnClick')).toBeUndefined() + }); + + it('SpRecyclerSystemTraceTest11', function () { + expect(spRecyclerSystemTrace.connectedCallback()).toBeUndefined() + }); + + it('SpRecyclerSystemTraceTest12', function () { + expect(spRecyclerSystemTrace.disconnectedCallback()).toBeUndefined() + }); + + it('SpRecyclerSystemTraceTest13', function () { + expect(spRecyclerSystemTrace.init).toBeTruthy() + }); + it('SpRecyclerSystemTraceTest14', function () { + let spRecyclerSystemTrace = new SpRecyclerSystemTrace; + expect(spRecyclerSystemTrace.insertAfter).toBeTruthy() + }); + +}) diff --git a/host/ide/test/trace/component/SpSystemTrace.test.ts b/host/ide/test/trace/component/SpSystemTrace.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..10e6d112b616d9d9264835265295381da3f926a9 --- /dev/null +++ b/host/ide/test/trace/component/SpSystemTrace.test.ts @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpSystemTrace} from "../../../dist/trace/component/SpSystemTrace.js" + +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe('SpSystemTrace Test', ()=>{ + let spSystemTrace = new SpSystemTrace(); + + spSystemTrace.initElements = jest.fn(()=> true) + + + it('SpSystemTraceTest01', function () { + expect(spSystemTrace.getScrollWidth()).toBe(0) + }); + + it('SpSystemTraceTest02', function () { + let resultLength = spSystemTrace.getVisibleRows([{}]).length; + expect(resultLength).toBe(0) + }); + + it('SpSystemTraceTest03', function () { + expect(spSystemTrace.timerShaftELRangeChange('')).toBeUndefined() + }); + + it('SpSystemTraceTest04', function () { + expect(spSystemTrace.rowsElOnScroll('Scroll')).toBeUndefined() + }); + + it('SpSystemTraceTest05', function () { + expect(spSystemTrace.documentOnMouseDown('MouseDown')).toBeUndefined() + }); + + it('SpSystemTraceTest06', function () { + expect(spSystemTrace.documentOnMouseUp('MouseUp')).toBeUndefined() + }); + + it('SpSystemTraceTest07', function () { + spSystemTrace.rangeSelect = jest.fn(()=>true) + spSystemTrace.rangeSelect.mouseMove = jest.fn(()=>true) + expect(spSystemTrace.documentOnMouseMove('MouseMove')).toBeUndefined() + }); + + it('SpSystemTraceTest08', function () { + expect(spSystemTrace.hoverStructNull('')).toBeUndefined() + }); + + it('SpSystemTraceTest09', function () { + expect(spSystemTrace.selectStructNull('')).toBeUndefined() + }); + + it('SpSystemTraceTest10', function () { + expect(spSystemTrace.documentOnClick('OnClick')).toBeUndefined() + }); + + it('SpSystemTraceTest11', function () { + expect(spSystemTrace.connectedCallback()).toBeUndefined() + }); + + it('SpSystemTraceTest12', function () { + expect(spSystemTrace.disconnectedCallback()).toBeUndefined() + }); + + it('SpSystemTraceTest13', function () { + expect(spSystemTrace.goProcess).toBeTruthy() + }); + + it('SpSystemTraceTest14', function () { + expect(spSystemTrace.loadDatabaseUrl).toBeTruthy() + }); +}) diff --git a/host/ide/test/trace/component/StackBar.test.ts b/host/ide/test/trace/component/StackBar.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..271c3b5bea68a6f3933b32b1e54f6980e30fc74c --- /dev/null +++ b/host/ide/test/trace/component/StackBar.test.ts @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {StackBar} from "../../../dist/trace/component/StackBar.js" + +describe('StackBar Test', () => { + + let stackBar = new StackBar(); + + it('StackBarTest01', function () { + expect(stackBar.initHtml()).not.toBe('') + }); + it('StackBarTest02', function () { + expect(stackBar.initElements()).toBeUndefined() + }); + it('StackBarTest03', function () { + let stateWidth = stackBar.getStateWidth('state'); + let hasWidth = stateWidth > 0; + expect(hasWidth).toBeTruthy(); + }); + it('StackBarTest04', function () { + let htmlDivElement = stackBar.createBarElement({ + state: "", + color: "", + value: 0, + }, 5); + let hasDivEl = htmlDivElement.toLocaleString().length > 5; + expect(hasDivEl).toBeTruthy(); + }); +}) diff --git a/host/ide/test/trace/component/setting/SpAllocations.test.ts b/host/ide/test/trace/component/setting/SpAllocations.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..b4de0f617d6ef4167b895eae2bef99f4de28a2ed --- /dev/null +++ b/host/ide/test/trace/component/setting/SpAllocations.test.ts @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpAllocations} from "../../../../dist/trace/component/setting/SpAllocations.js"; + +describe('SpAllocations Test', ()=>{ + beforeAll(() => { + document.body.innerHTML = ` + + ` + }) + it('new SpAllocations', function () { + expect(new SpAllocations()).not.toBeUndefined(); + }); + + it(' SpAllocations get Default attrValue', function () { + let spEle = document.querySelector("#sp") as SpAllocations + expect(spEle.pid).toEqual(undefined) + expect(spEle.unwind).toEqual(10) + expect(spEle.shared).toEqual(2048) + expect(spEle.filter).toEqual(0) + }); + + it(' SpAllocations set attrValue', function () { + let spEle = document.querySelector("#sp") as SpAllocations + spEle.processId.value ="2" + spEle.unwindEL.value = "111" + spEle.shareMemory.value = "222" + spEle.shareMemoryUnit.value = "MB" + spEle.filterMemory.value = "111" + spEle.filterMemoryUnit.value = "MB" + expect(spEle.pid).toEqual(undefined) + expect(spEle.unwind).toEqual(111) + expect(spEle.shared).toEqual(0) + expect(spEle.filter).toEqual(28416) + }); + + it(' SpAllocations set attrValue', function () { + let spEle = document.querySelector("#sp") as SpAllocations + spEle.processId.value ="3" + spEle.unwindEL.value = "1121" + spEle.shareMemory.value = "222" + spEle.shareMemoryUnit.value = "KB" + spEle.filterMemory.value = "111" + spEle.filterMemoryUnit.value = "KB" + expect(spEle.pid).toEqual(undefined) + expect(spEle.unwind).toEqual(1121) + expect(spEle.shared).toEqual(55) + expect(spEle.filter).toEqual(111) + }); + + it(' SpAllocations set attrValue03', function () { + let spEle = document.querySelector("#sp") as SpAllocations + spEle.processId.value ="3" + spEle.unwindEL.value = "1121" + spEle.shareMemory.value = "222" + spEle.shareMemoryUnit.value = "G" + spEle.filterMemory.value = "111" + spEle.filterMemoryUnit.value = "G" + expect(spEle.pid).toEqual(undefined) + expect(spEle.unwind).toEqual(1121) + expect(spEle.shared).toEqual(0) + expect(spEle.filter).toEqual(111) + }); + // it('CpuStructTest02', function () { + // expect(FpsStruct.equals({}, data)).toBeTruthy(); + // }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/setting/SpProbesConfig.test.ts b/host/ide/test/trace/component/setting/SpProbesConfig.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..c105faf75f0266e24e02009f3d4533841cec92c4 --- /dev/null +++ b/host/ide/test/trace/component/setting/SpProbesConfig.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpProbesConfig} from "../../../../dist/trace/component/setting/SpProbesConfig.js"; + +describe('SpProbesConfig Test', ()=>{ + beforeAll(() => { + document.body.innerHTML = ` + + ` + }) + it('new SpProbesConfig', function () { + expect(new SpProbesConfig()).not.toBeNull(); + }); + + it(' SpProbesConfig get Default attrValue', function () { + let spEle = document.querySelector("#spconfig") as SpProbesConfig + expect(spEle.traceConfig).toEqual([]) + expect(spEle.traceEvents).toEqual([]) + expect(spEle.memoryConfig).toEqual([]) + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/setting/SpRecordSetting.test.ts b/host/ide/test/trace/component/setting/SpRecordSetting.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0832660f298291cf038c54b4fb6e119c663fbd7d --- /dev/null +++ b/host/ide/test/trace/component/setting/SpRecordSetting.test.ts @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SpRecordSetting} from "../../../../dist/trace/component/setting/SpRecordSetting.js"; + +describe('SpRecordSetting Test', ()=>{ + beforeAll(() => { + document.body.innerHTML = ` + + ` + }) + it('new SpRecordSetting', function () { + expect(new SpRecordSetting()).not.toBeNull(); + }); + + it(' SpAllocations get Default attrValue', function () { + let spEle = document.querySelector("#setting") as SpRecordSetting + expect(spEle.recordMod).toBeTruthy(); + expect(spEle.bufferSize).toEqual(64) + expect(spEle.maxDur).toEqual(50) + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/setting/SpTraceCommand.test.ts b/host/ide/test/trace/component/setting/SpTraceCommand.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..6695556c535da9b7b54fa06e4d7c27a0426e4d1e --- /dev/null +++ b/host/ide/test/trace/component/setting/SpTraceCommand.test.ts @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore + +import {SpTraceCommand} from "../../../../dist/trace/component/setting/SpTraceCommand.js"; + +describe('SPTraceCommand Test', ()=>{ + beforeAll(() => { + document.body.innerHTML = ` + + ` + }) + it('new SPTraceCommand', function () { + expect(new SpTraceCommand()).not.toBeNull(); + }); + + it(' SpAllocations get Default attrValue', function () { + let spEle = document.querySelector("#command") as SpTraceCommand + expect(spEle.hdcCommon).toEqual(""); + }); + + it(' SpAllocations set attrValue', function () { + let spEle = document.querySelector("#command") as SpTraceCommand + spEle.hdcCommon = "aaaaaaaaaa" + expect(spEle.hdcCommon).toEqual("aaaaaaaaaa"); + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/setting/utils/PluginConvertUtils.test.ts b/host/ide/test/trace/component/setting/utils/PluginConvertUtils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..1a3a73a3f2eacde8d1e88cfda66355d4962914ee --- /dev/null +++ b/host/ide/test/trace/component/setting/utils/PluginConvertUtils.test.ts @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {PluginConvertUtils} from "../../../../../dist/trace/component/setting/utils/PluginConvertUtils.js"; +// @ts-ignore +import {ProfilerSessionConfigMode} from "../../../../../dist/trace/component/setting/bean/ProfilerServiceTypes"; + +import { + ProfilerSessionConfigBufferConfig, + ProfilerSessionConfigBufferConfigPolicy, TracePluginConfig + // @ts-ignore +} from "../../../../../dist/trace/component/setting/bean/ProfilerServiceTypes.js"; +import { + HilogConfig, + levelFromJSON, + Type + // @ts-ignore +} from "../../../../../dist/trace/component/setting/bean/ProfilerServiceTypes.js"; +import { + MemoryConfig, + sysMeminfoTypeFromJSON, sysVMeminfoTypeFromJSON + // @ts-ignore +} from "../../../../../dist/trace/component/setting/bean/ProfilerServiceTypes.js"; +// @ts-ignore +import {SpRecordTrace} from "../../../../../dist/trace/component/SpRecordTrace.js"; + +describe('PlugConvertUtils Test', ()=>{ + let bufferConfig: ProfilerSessionConfigBufferConfig = { + pages: 1000, + policy: ProfilerSessionConfigBufferConfigPolicy.RECYCLE + } + let sessionConfig = { + buffers: [bufferConfig], + sessionMode: ProfilerSessionConfigMode.OFFLINE, + resultFile: "/data/local/tmp/hiprofiler_data.htrace", + resultMaxSize: 0, + sampleDuration: 1000, + keepAliveTime: 0 + }; + let tracePluginConfig: TracePluginConfig = { + ftraceEvents: [], + bytraceCategories: [], + bytraceApps: [], + bufferSizeKb: 1024, + flushIntervalMs: 1000, + flushThresholdKb: 4096, + parseKsyms: true, + clock: "mono", + tracePeriodMs: 200, + rawDataPrefix: "", + traceDurationMs: 0, + debugOn: false, + } + let hilogConfig: HilogConfig = { + deviceType: Type.HI3516, + logLevel: levelFromJSON("Info"), + needClear: true + } + let memoryconfig: MemoryConfig = { + reportProcessTree: true, + reportSysmemMemInfo: true, + sysMeminfoCounters: [], + reportSysmemVmemInfo: true, + sysVmeminfoCounters: [], + reportProcessMemInfo: true, + reportAppMemInfo: false, + reportAppMemByMemoryService: false, + pid: [] + } + + SpRecordTrace.MEM_INFO.forEach((va: any) => { + memoryconfig.sysMeminfoCounters.push(sysMeminfoTypeFromJSON(va)); + }) + SpRecordTrace.VMEM_INFO.forEach(((me: any) => { + memoryconfig.sysVmeminfoCounters.push(sysVMeminfoTypeFromJSON(me)) + })) + SpRecordTrace.VMEM_INFO_SECOND.forEach(((me: any) => { + memoryconfig.sysVmeminfoCounters.push(sysVMeminfoTypeFromJSON(me)) + })) + SpRecordTrace.VMEM_INFO_THIRD.forEach(((me: any) => { + memoryconfig.sysVmeminfoCounters.push(sysVMeminfoTypeFromJSON(me)) + })) + + let request = { + requestId: 1, + sessionConfig: sessionConfig, + pluginConfigs: [tracePluginConfig, hilogConfig,memoryconfig] + }; + + it('PlugConvertUtils01', function () { + expect(PluginConvertUtils.createHdcCmd("aaaa", 11)).not.toBeNull() + }); + + it('PlugConvertUtils02', function () { + expect(PluginConvertUtils.BeanToCmdTxt(request, true)).not.toBeNull() + }); + + it('PlugConvertUtils03', function () { + expect(PluginConvertUtils.BeanToCmdTxt(request, false)).not.toBeNull() + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/TimerShaftElement.test.ts b/host/ide/test/trace/component/trace/TimerShaftElement.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d4f37f42f5e1a117a70e7e0d7f99616367aded3e --- /dev/null +++ b/host/ide/test/trace/component/trace/TimerShaftElement.test.ts @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TimerShaftElement} from "../../../../dist/trace/component/trace/TimerShaftElement.js" + + +describe('TimerShaftElement Test', () => { + let timerShaftElement = new TimerShaftElement(); + + timerShaftElement.cpuUsage = 'cpuUsage' + + it('TimerShaftElementTest01', function () { + timerShaftElement.rangeRuler = jest.fn(() => true) + timerShaftElement.rangeRuler.cpuUsage = jest.fn(() => true) + expect(timerShaftElement.cpuUsage).toBeUndefined(); + }); + + it('TimerShaftElementTest02', function () { + timerShaftElement.rangeRuler = jest.fn(() => false) + timerShaftElement.loadComplete = jest.fn(() => false) + timerShaftElement.rangeRuler.markA = jest.fn(() => true) + timerShaftElement.rangeRuler.markB = jest.fn(() => true) + timerShaftElement.rangeRuler.markA.frame = jest.fn(() => true) + timerShaftElement.rangeRuler.markB.frame = jest.fn(() => true) + timerShaftElement.rangeRuler.markA.frame.x = jest.fn(() => 0) + timerShaftElement.rangeRuler.markB.frame.x = jest.fn(() => true) + timerShaftElement.rangeRuler.frame = jest.fn(() => true) + timerShaftElement.rangeRuler.frame.width = jest.fn(() => 8) + timerShaftElement.rangeRuler.cpuUsage = jest.fn(() => []) + timerShaftElement.sportRuler = jest.fn(() => true) + timerShaftElement.sportRuler.flagList = jest.fn(() => false) + timerShaftElement.sportRuler.flagList.length = jest.fn(() =>0) + timerShaftElement.totalNS =jest.fn(()=>false); + timerShaftElement.sportRuler.isRangeSelect = jest.fn(() => false) + expect(timerShaftElement.reset()).toBeUndefined(); + }); + + it('spApplicationTest10',function (){ + expect(timerShaftElement.reset()).not.toBeUndefined() + }); + + + it('TimerShaftElementTest03', function () { + timerShaftElement.timeRuler = jest.fn(() => false) + timerShaftElement.sportRuler = jest.fn(() => false) + timerShaftElement.rangeRuler = jest.fn(() => false) + timerShaftElement.timeRuler.frame = jest.fn(() => { + return document.createElement('canvas') as HTMLCanvasElement + }) + + timerShaftElement.sportRuler.frame = jest.fn(() => { + return document.createElement('canvas') as HTMLCanvasElement + }) + + timerShaftElement.rangeRuler.frame = jest.fn(() => { + return document.createElement('canvas') as HTMLCanvasElement + }) + expect(timerShaftElement.connectedCallback()).toBeUndefined(); + }); + + it('TimerShaftElementTest04', function () { + timerShaftElement.canvas = jest.fn(()=> { + return { + width: 20, + height: 20, + style: { + width: 30, + height: 30, + } + } + }) + timerShaftElement.canvas.style = jest.fn(() => true) + timerShaftElement.rangeRuler.fillX = jest.fn(() => true) + timerShaftElement.timeRuler.draw = jest.fn(() => true) + timerShaftElement.rangeRuler.draw = jest.fn(() => true) + timerShaftElement.sportRuler.draw = jest.fn(() => true) + expect(timerShaftElement.updateWidth(2)).toBeUndefined(); + }); + + it('TimerShaftElementTest05', function () { + expect(timerShaftElement.disconnectedCallback()).toBeUndefined(); + }); + + it('TimerShaftElementTest06', function () { + expect(timerShaftElement.totalNS).toBe(10000000000); + }); + it('TimerShaftElementTest10', function () { + timerShaftElement.totalNS = 10000000000; + expect(timerShaftElement.totalNS).toBe(10000000000); + }); + + it('TimerShaftElementTest07', function () { + // timerShaftElement._sportRuler.modifyFlagList = jest.fn(() => true) + expect(timerShaftElement.modifyFlagList()).toBeUndefined(); + }); + + it('TimerShaftElementTest08', function () { + timerShaftElement.startNS = 'startNS' + expect(timerShaftElement.startNS).toBe('startNS'); + }); + + it('TimerShaftElementTest09', function () { + timerShaftElement.endNS = 'endNS' + expect(timerShaftElement.endNS).toBe('endNS'); + }); + + it('TimerShaftElementTest11', function () { + expect(timerShaftElement.render()).toBe(undefined); + }); + + it('TimerShaftElementTest12', function () { + timerShaftElement.ctx = jest.fn(()=>true) + timerShaftElement.ctx.fillStyle = jest.fn(()=>'transparent') + timerShaftElement.ctx.fillRect = jest.fn(()=>true) + expect(timerShaftElement.render()).toBe(undefined); + }); +}) diff --git a/host/ide/test/trace/component/trace/base/ColorUtils.test.ts b/host/ide/test/trace/component/trace/base/ColorUtils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..5b49ac2c6099513e26f2016ea82fc40a4a4ad9bf --- /dev/null +++ b/host/ide/test/trace/component/trace/base/ColorUtils.test.ts @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {ColorUtils} from "../../../../../dist/trace/component/trace/base/ColorUtils.js"; + +describe("testColorUtils Test", () => { + beforeAll(() => { + }) + it('testColorUtils01', () => { + expect(ColorUtils.hash("mm",ColorUtils.MD_PALETTE.length)).toBe(6); + }); + it('testColorUtils02', () => { + // @ts-ignore + expect(ColorUtils.colorForThread(null)).toEqual("#f0f0f0"); + }); + + it('testColorUtils03', () => { + // @ts-ignore + let thread = {processId:1} + expect(ColorUtils.colorForThread(thread)).toEqual("#fbbf00"); + }); + + it('testColorUtils03', () => { + // @ts-ignore + let thread = { + processId:0, + tid:1 + } + expect(ColorUtils.colorForThread(thread)).toEqual("#fbbf00"); + }); + + it('testColorUtils04', () => { + expect(ColorUtils.formatNumberComma(2)).toEqual("2"); + }); + + afterAll(() => { + }) +}) + + diff --git a/host/ide/test/trace/component/trace/base/RangeSelect.test.ts b/host/ide/test/trace/component/trace/base/RangeSelect.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..2e84cc0e2f9869470581840a4a1c3709c38a392c --- /dev/null +++ b/host/ide/test/trace/component/trace/base/RangeSelect.test.ts @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore + + +import {RangeSelect} from "../../../../../dist/trace/component/trace/base/RangeSelect.js"; + +describe("RangeSelect Test", () => { + beforeAll(() => { + }) + + it('Utils Test01', () => { + let rangeSelect = new RangeSelect(); + expect(rangeSelect).not.toBeUndefined(); + }); + + it('Utils Test02', () => { + let rangeSelect = new RangeSelect(); + rangeSelect.rowsEL= document.createElement('div') + let mouseEvent = new MouseEvent("mousedown",{ + button: 0, + buttons: 0, + clientX: 2, + clientY: 100, + screenX: 255, + screenY: 325, + }); + rangeSelect.timerShaftDragEL = jest.fn(()=>true) + rangeSelect.timerShaftDragEL.timerShaftDragEL = jest.fn(()=>true) + expect(rangeSelect.isInRowsEl(mouseEvent)).toBeFalsy(); + }); + it('Utils Test09', () => { + let rangeSelect = new RangeSelect(); + rangeSelect.rowsEL= document.createElement('div') + let mouseEvent = new MouseEvent("mousedown",{ + button: 0, + buttons: 0, + clientX: 2, + clientY: 100, + screenX: 255, + screenY: 325, + }); + rangeSelect.spacerEL = jest.fn(()=>true) + rangeSelect.spacerEL.offsetTop = jest.fn(()=>1) + expect(rangeSelect.isInSpacerEL(mouseEvent)).toBeFalsy(); + }); + + it('Utils Test05', () => { + let rangeSelect = new RangeSelect(); + rangeSelect.isInRowsEl = jest.fn(()=>true) + rangeSelect.rowsEL= { + // offsetTop: 100, + offsetHeight:200, + offsetLeft:0, + offsetWidth:100 + } + let mouseEvent = new MouseEvent("mousedown",{ + // @ts-ignore + offsetY:1, + offsetX:1, + button: 0, + buttons: 0, + clientX: 2, + clientY: 100, + screenX: 255, + screenY: 325 + }); + rangeSelect.spacerEL = jest.fn(()=>true) + rangeSelect.spacerEL.offsetTop = jest.fn(()=>true) + expect(rangeSelect.mouseDown(mouseEvent)).toBeUndefined() + }); + + it('Utils Test07', () => { + let rangeSelect = new RangeSelect(); + rangeSelect.isInRowsEl = jest.fn(()=>true) + rangeSelect.isDrag = jest.fn(()=>true) + + rangeSelect.rowsEL= { + offsetTop: 100, + offsetHeight:200, + offsetLeft:0, + offsetWidth:100 + } + let mouseEvent = new MouseEvent("mousedown",{ + // @ts-ignore + offsetY:1, + offsetX:1, + button: 0, + buttons: 0, + clientX: 2, + clientY: 100, + screenX: 255, + screenY: 325 + }); + rangeSelect.spacerEL = jest.fn(()=>true) + rangeSelect.spacerEL.offsetTop = jest.fn(()=>1) + expect(rangeSelect.mouseUp(mouseEvent)).toBeUndefined(); + }); + + it('Utils Test08', () => { + let rangeSelect = new RangeSelect(); + rangeSelect.isInRowsEl = jest.fn(()=>true) + rangeSelect.isDrag = jest.fn(()=>true) + rangeSelect.isMouseDown = true + let rowsEL= [{ + frame: { + x:1, + width:10, + y:2, + height:10 + }, + offsetTop: 100, + offsetHeight:200, + offsetLeft:0, + offsetWidth:100, + }] + rangeSelect.rowsEL = rowsEL; + let mouseEvent = new MouseEvent("mousedown",{ + // @ts-ignore + offsetY:1, + offsetX:1, + button: 0, + buttons: 0, + clientX: 2, + clientY: 100, + screenX: 255, + screenY: 325 + }); + rangeSelect.timerShaftDragEL = jest.fn(()=>true) + rangeSelect.timerShaftEL= jest.fn(()=>true) + rangeSelect.timerShaftEL.sportRuler = jest.fn(()=>true) + rangeSelect.timerShaftEL.sportRuler.isRangeSelect = jest.fn(()=>true) + rangeSelect.timerShaftEL.sportRuler.draw = jest.fn(()=>true) + rangeSelect.timerShaftDragEL.timerShaftDragEL = jest.fn(()=>0) + rangeSelect.spacerEL = jest.fn(()=>true) + rangeSelect.spacerEL.offsetTop = jest.fn(()=>1) + expect(rangeSelect.mouseMove(rowsEL,mouseEvent)).toBeUndefined(); + }); + + it('Utils Test10', () => { + let rangeSelect = new RangeSelect(); + rangeSelect.isInRowsEl = jest.fn(()=>true) + rangeSelect.isDrag = jest.fn(()=>true) + + rangeSelect.rowsEL= { + offsetTop: 100, + offsetHeight:200, + offsetLeft:0, + offsetWidth:100 + } + let mouseEvent = new MouseEvent("mousedown",{ + // @ts-ignore + offsetY:1, + offsetX:1, + button: 0, + buttons: 0, + clientX: 2, + clientY: 100, + screenX: 255, + screenY: 325 + }); + rangeSelect.timerShaftDragEL = jest.fn(()=>true) + rangeSelect.timerShaftDragEL.timerShaftDragEL = jest.fn(()=>0) + expect(rangeSelect.isTouchMark(mouseEvent)).toBeFalsy(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/base/TraceRow.test.ts b/host/ide/test/trace/component/trace/base/TraceRow.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..da8ecac2169bd0b124c37c7d2f216c7cc568cb7b --- /dev/null +++ b/host/ide/test/trace/component/trace/base/TraceRow.test.ts @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TraceRow} from "../../../../../dist/trace/component/trace/base/TraceRow.js"; +describe("TraceRow Test", () => { + + beforeAll(() => { + }) + it('TraceRow Test01', () => { + let traceRow = new TraceRow(); + expect(traceRow).not.toBeUndefined(); + }); + + it('TraceRow Test02', () => { + let traceRow = new TraceRow(); + expect(traceRow.sleeping).toBeFalsy(); + }); + + it('TraceRow Test03', () => { + let traceRow = new TraceRow(); + traceRow.sleeping = true + expect(traceRow.sleeping).toBeTruthy(); + }); + + it('TraceRow Test04', () => { + let traceRow = new TraceRow(); + traceRow.sleeping = false + expect(traceRow.sleeping).toBeFalsy(); + }); + + it('TraceRow Test05', () => { + let traceRow = new TraceRow(); + expect(traceRow.rangeSelect).toBeFalsy(); + }); + + it('TraceRow Test06', () => { + let traceRow = new TraceRow(); + traceRow.rangeSelect = true + expect(traceRow.rangeSelect).toBeTruthy(); + }); + it('TraceRow Test07', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + let traceRow = new TraceRow(); + //transferControlToOffscreen() + traceRow.canvas = jest.fn(()=>true) + traceRow.args = jest.fn(()=>true) + traceRow.args.isOffScreen = jest.fn(()=>true) + // @ts-ignore + traceRow.canvas.transferControlToOffscreen = jest.fn(()=>true) + traceRow.dataList = { + supplier:true, + isLoading:false, + } + traceRow.args={ + isOffScreen:true, + } + traceRow.supplier = true; + traceRow.isLoading = false; + traceRow.name = "111" + traceRow.height = 20 + traceRow.height = 30 + expect(traceRow.initCanvas()).toBeUndefined(); + }); + + it('TraceRow Test08', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + let traceRow = new TraceRow(); + traceRow.dataList = { + supplier:true, + isLoading:false, + } + traceRow.supplier = true; + traceRow.isLoading = false; + traceRow.name = "111" + traceRow.height = 20 + traceRow.height = 30 + expect(traceRow.drawObject()).toBeUndefined(); + }); + + it('TraceRow Test09', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + let traceRow = new TraceRow(); + traceRow.dataList = { + supplier:true, + isLoading:false, + } + traceRow.supplier = true; + traceRow.isLoading = false; + traceRow.name = "111" + traceRow.height = 20 + traceRow.height = 30 + expect(traceRow.drawObject()).toBeUndefined(); + }); + + it('TraceRow Test10', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + let traceRow = new TraceRow(); + traceRow.dataList = { + supplier:true, + isLoading:false, + } + traceRow.supplier = true; + traceRow.isLoading = false; + traceRow.name = "111" + traceRow.height = 20 + traceRow.height = 30 + expect(traceRow.clearCanvas()).toBeUndefined(); + }); + + it('TraceRow Test11', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + let traceRow = new TraceRow(); + traceRow.dataList = { + supplier:true, + isLoading:false, + } + traceRow.supplier = true; + traceRow.isLoading = false; + traceRow.name = "111" + traceRow.height = 20 + traceRow.height = 30 + expect(traceRow.drawLines()).toBeUndefined(); + }); + + it('TraceRow Test12', () => { + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + let traceRow = new TraceRow(); + traceRow.dataList = { + supplier:true, + isLoading:false, + } + traceRow.supplier = true; + traceRow.isLoading = false; + traceRow.name = "111" + traceRow.height = 20 + traceRow.height = 30 + expect(traceRow.drawSelection()).toBeUndefined(); + }); + + it('TraceRow Test13', () => { + let traceRow = new TraceRow(); + expect(traceRow.collect).toBeFalsy(); + }); + + it('TraceRow Test14', () => { + let traceRow = new TraceRow(); + traceRow.collect = true; + expect(traceRow.collect).toBeTruthy(); + }); + + it('TraceRow Test15', () => { + let traceRow = new TraceRow(); + expect(traceRow.rowType).toBeFalsy(); + }); + + it('TraceRow Test16', () => { + let traceRow = new TraceRow(); + traceRow.rowType = true; + expect(traceRow.rowType).toBeTruthy(); + }); + + it('TraceRow Test17', () => { + let traceRow = new TraceRow(); + expect(traceRow.rowId).toBeFalsy(); + }); + + it('TraceRow Test18', () => { + let traceRow = new TraceRow(); + traceRow.rowId = true; + expect(traceRow.rowId).toBeTruthy(); + }); + + it('TraceRow Test19', () => { + let traceRow = new TraceRow(); + expect(traceRow.rowParentId).toBeFalsy(); + }); + + it('TraceRow Test20', () => { + let traceRow = new TraceRow(); + traceRow.rowParentId = true; + expect(traceRow.rowParentId).toBeTruthy(); + }); + + it('TraceRow Test21', () => { + let traceRow = new TraceRow(); + traceRow.rowHidden = true; + expect(traceRow.rowHidden).toBeUndefined(); + }); + + it('TraceRow Test22', () => { + let traceRow = new TraceRow(); + expect(traceRow.name).toBeFalsy(); + }); + + it('TraceRow Test23', () => { + let traceRow = new TraceRow(); + expect(traceRow.folder).toBeFalsy(); + }); + + it('TraceRow Test24', () => { + let traceRow = new TraceRow(); + traceRow.folder = true; + expect(traceRow.folder).toBeTruthy(); + }); + + it('TraceRow Test25', () => { + let traceRow = new TraceRow(); + expect(traceRow.expansion).toBeFalsy(); + }); + + it('TraceRow Test26', () => { + let traceRow = new TraceRow(); + traceRow.expansion = true; + expect(traceRow.expansion).toBeTruthy(); + }); + + it('TraceRow Test27', () => { + let traceRow = new TraceRow(); + traceRow.tip = true; + expect(traceRow.tip).toBeUndefined(); + }); + + it('TraceRow Test28', () => { + let traceRow = new TraceRow(); + expect(traceRow.frame).not.toBeUndefined(); + }); + + it('TraceRow Test29', () => { + let traceRow = new TraceRow(); + traceRow.frame = [0,0,0]; + expect(traceRow.frame).toBeTruthy(); + }); + + it('TraceRow Test30', () => { + let traceRow = new TraceRow(); + expect(traceRow.checkType).not.toBeUndefined(); + }); + + it('TraceRow Test31', () => { + let traceRow = new TraceRow(); + traceRow.checkType = true; + expect(traceRow.checkType).toBeTruthy(); + }); + + it('TraceRow Test32', () => { + let traceRow = new TraceRow(); + expect(traceRow.drawType).toBeUndefined(); + }); + + it('TraceRow Test33', () => { + let traceRow = new TraceRow(); + traceRow.drawType = true; + expect(traceRow.drawType).toBeTruthy(); + }); + + it('TraceRow Test34', () => { + let traceRow = new TraceRow(); + traceRow.args = jest.fn(()=>true) + traceRow.args.isOffScreen = jest.fn(()=>null) + expect(traceRow.updateWidth(1)).toBeUndefined(); + }); + + it('TraceRow Test35', () => { + let traceRow = new TraceRow(); + expect(traceRow.setCheckBox()).toBeUndefined(); + }); + + it('TraceRow Test36', () => { + let traceRow = new TraceRow(); + expect(traceRow.onMouseHover()).toBeFalsy(); + }); + + it('TraceRow Test37', () => { + let traceRow = new TraceRow(); + expect(traceRow.setTipLeft(1,null)).toBeFalsy(); + }); + + it('TraceRow Test38', () => { + let traceRow = new TraceRow(); + expect(traceRow.onMouseLeave(1,1)).toBeFalsy(); + }); + + it('TraceRow Test39', () => { + let traceRow = new TraceRow(); + expect(traceRow.draw(false)).toBeFalsy(); + }); + + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/base/TraceRowObject.test.ts b/host/ide/test/trace/component/trace/base/TraceRowObject.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..5014d62e2b7a89ac27d7a221c8900f2ed683f56a --- /dev/null +++ b/host/ide/test/trace/component/trace/base/TraceRowObject.test.ts @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TraceRowObject} from "../../../../../dist/trace/component/trace/base/TraceRowObject.js"; + +describe("TraceRow Test", () => { + beforeAll(() => { + }) + + it('Utils Test01', () => { + let traceRow = new TraceRowObject(); + expect(traceRow) + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/base/TraceRowRecyclerView.test.ts b/host/ide/test/trace/component/trace/base/TraceRowRecyclerView.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..6aa8c61cb54897f6a729de2ada5607dc10c3fd6c --- /dev/null +++ b/host/ide/test/trace/component/trace/base/TraceRowRecyclerView.test.ts @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TraceRowRecyclerView} from "../../../../../dist/trace/component/trace/base/TraceRowRecyclerView.js"; + +describe("TraceRow Test", () => { + beforeAll(() => { + }) + + it('Utils Test01', () => { + let traceRow = new TraceRowRecyclerView(); + expect(traceRow) + }); + + it('Test02', function () { + let traceRow = new TraceRowRecyclerView(); + expect(traceRow.dataSource).toBeTruthy(); + }); + + it('Test03', function () { + let traceRow = new TraceRowRecyclerView(); + traceRow.dataSource=false + expect(traceRow.dataSource).toBeTruthy(); + }); + + it('Test04', function () { + let traceRow = new TraceRowRecyclerView(); + expect(traceRow.renderType).toBeTruthy(); + }); + + it('Test05', function () { + let traceRow = new TraceRowRecyclerView(); + traceRow.renderType=false + expect(traceRow.renderType).toBeFalsy(); + }); + + it('Test06', function () { + let traceRow = new TraceRowRecyclerView(); + expect(traceRow.refreshRow()).toBeUndefined(); + }); + + it('Test07', function () { + let traceRow = new TraceRowRecyclerView(); + traceRow.dataSource = jest.fn(()=>true) + traceRow.dataSource.filter = jest.fn(()=>true) + expect(traceRow.measureHeight()).toBeUndefined(); + }); + + it('Test08', function () { + let traceRow = new TraceRowRecyclerView(); + expect(traceRow.initUI()).toBeUndefined(); + }); + it('Test09', function () { + let traceRow = new TraceRowRecyclerView(); + expect(traceRow.initUI()).toBeUndefined(); + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/base/TraceSheet.test.ts b/host/ide/test/trace/component/trace/base/TraceSheet.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..39ef4ca48217c030d92e11aed1bf6d7a1e8fe608 --- /dev/null +++ b/host/ide/test/trace/component/trace/base/TraceSheet.test.ts @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TraceSheet} from "../../../../../dist/trace/component/trace/base/TraceSheet.js"; +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + +describe("TraceSheet Test", () => { + beforeAll(() => { + }) +let val=[{ + cpus:{length:1,}, + threadIds:{length: 2}, + funTids:{length: 2}, + trackIds:{length: 2}, + hasFps:0, + heapIds:{length: 0}, + nativeMemory:{length: 1} +}] + it('TraceSheet Test01', () => { + let traceRow = new TraceSheet(); + expect(traceRow).not.toBeUndefined() + }); + + it('TraceSheet Test02', () => { + let traceRow = new TraceSheet(); + expect(traceRow.recoveryBoxSelection).not.toBeUndefined() + }); + + + + it('TraceSheet Test03', () => { + let traceRow = new TraceSheet(); + expect(traceRow.hideBoxTab()).toBeUndefined() + }); + + /* it('TraceSheet Test04', () => { + let traceRow = new TraceSheet(); + expect(traceRow.hideOtherBoxTab("11")).not.toBeUndefined() + }); + + + it('TraceSheet Test05', () => { + let traceRow = new TraceSheet(); + expect(traceRow.hideOtherBoxTab("12")).not.toBeUndefined() + }); + + + it('TraceSheet Test06', () => { + let traceRow = new TraceSheet(); + expect(traceRow.hideOtherBoxTab("13")).not.toBeUndefined() + }); + + it('TraceSheet Test07', () => { + let traceRow = new TraceSheet(); + expect(traceRow.hideOtherBoxTab("14")).not.toBeUndefined() + });*/ + + it('TraceSheet Test08', () => { + let traceRow = new TraceSheet(); + expect(traceRow.connectedCallback()).toBeUndefined() + }); + it('TraceSheet Test09', () => { + let traceRow = new TraceSheet(); + expect(traceRow.loadTabPaneData()).toBeUndefined() + }); + + it('TraceSheet Test10', () => { + let traceRow = new TraceSheet(); + expect(traceRow.clear()).toBeUndefined() + }); + + it('TraceSheet Test11', () => { + let traceRow = new TraceSheet(); + expect(traceRow.boxSelection(val)).toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/base/Utils.test.ts b/host/ide/test/trace/component/trace/base/Utils.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0b70b4d7124f07fc83df773fcada772b0bad0614 --- /dev/null +++ b/host/ide/test/trace/component/trace/base/Utils.test.ts @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {Utils} from "../../../../../dist/trace/component/trace/base/Utils.js"; + +describe("Utils Test", () => { + beforeAll(() => { + }) + + it('Utils Test01', () => { + let instance = Utils.getInstance(); + let instance2 = Utils.getInstance(); + expect(instance).toBe(instance2) + }); + + it('Utils Test02', () => { + let instance = Utils.getInstance(); + expect(instance.getStatusMap().get("D")).toBe("Uninterruptible Sleep") + }); + + it('Utils Test03', () => { + expect(Utils.getEndState("D")).toBe("Uninterruptible Sleep") + }); + + it('Utils Test04', () => { + expect(Utils.getEndState("")).toBe("") + }); + + it('Utils Test05', () => { + expect(Utils.getEndState("ggg")).toBe("Unknown State") + }); + + it('Utils Test06', () => { + expect(Utils.getStateColor("D")).toBe("#f19b38") + }); + + it('Utils Test07', () => { + expect(Utils.getStateColor("R")).toBe("#a0b84d") + }); + it('Utils Test08', () => { + expect(Utils.getStateColor("I")).toBe("#673ab7") + }); + + it('Utils Test09', () => { + expect(Utils.getStateColor("Running")).toBe("#467b3b") + }); + + it('Utils Test09', () => { + expect(Utils.getStateColor("S")).toBe("#e0e0e0") + }); + + + it('Utils Test10', () => { + expect(Utils.getTimeString(5900_000_000_000)).toBe("1h 38m ") + }); + + it('Utils Test11', () => { + expect(Utils.getByteWithUnit(1_000_000_001)).toBe("1.00 Gb") + }); + + it('Utils Test12', () => { + expect(Utils.getByteWithUnit(1_000_000_000)).toBe("1000.00 Mb") + }); + + it('Utils Test14', () => { + expect(Utils.getByteWithUnit(1000_000)).toBe("1000.00 kb") + }); + + it('Utils Test13', () => { + expect(Utils.getTimeStringHMS(5900_000_000_000)).toBe("1:38:") + }); + + + afterAll(() => { + // 后处理操作 + }) +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneBoxChild.test.ts b/host/ide/test/trace/component/trace/sheet/TabPaneBoxChild.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..8304782e909c6005ba933a5ec7000dfada5e64d3 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/TabPaneBoxChild.test.ts @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +// import { it } from "mocha" +import {TabPaneBoxChild} from "../../../../../dist/trace/component/trace/sheet/TabPaneBoxChild.js" +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + + })); +describe('TabPaneBoxChild Test', () => { + let tabPaneBoxChild = new TabPaneBoxChild(); + tabPaneBoxChild.parentElement= jest.fn(()=> { + return {clientHeight:56} + }) + tabPaneBoxChild.parentElement.clientHeight= jest.fn(()=>100) + tabPaneBoxChild.data = { + cpus: [], + threadIds: [], + trackIds: [], + funTids: [], + heapIds:[], + leftNs: 0, + rightNs: 0, + hasFps: false, + // parentElement:{ + // clientHeight:0, + // } + } + // tabPaneBoxChild.parentElement = { + // clientHeight:0, + // } + + it('TabPaneBoxChildTest01', function () { + + expect(tabPaneBoxChild.sortByColumn({ + key: 'name', + sort: () => { + } + })).toBeUndefined(); + }); + // it('TabPaneBoxChildTest02',function(){ + // TabPaneBoxChild.parentElement= jest.fn(()=> { + // return {clientHeight:56} + // }) + // // TabPaneBoxChild.parentElement.clientHeight= jest.fn(()=>100) + // expect(tabPaneBoxChild.data).toBeUndefined(); + // }) + +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneContextSwitch.test.ts b/host/ide/test/trace/component/trace/sheet/TabPaneContextSwitch.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..3d3b8e73d2e302cfb792f9a080e45fe6d3b79186 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/TabPaneContextSwitch.test.ts @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneContextSwitch} from "../../../../../dist/trace/component/trace/sheet/TabPaneContextSwitch.js" +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); +describe('TabPaneContextSwitch Test', () => { + let tabPaneContextSwitch = new TabPaneContextSwitch(); + let dataArray = [{ + id: "", + pid: "", + title: "", + children: [], + process: "", + processId: 0, + thread: "", + threadId: 0, + state: "", + wallDuration: 0, + avgDuration: "", + count: 0, + minDuration: 0, + maxDuration: 0, + stdDuration: "", + }] + + it('TabPaneContextSwitchTest01', function () { + let result = tabPaneContextSwitch.groupByProcessThreadToMap(dataArray); + expect(result.get(0).length).toBeUndefined(); + }); + + it('TabPaneContextSwitchTest02', function () { + let result = tabPaneContextSwitch.groupByProcessToMap(dataArray) + expect(result.get(0).length).toBe(1); + }); + + it('TabPaneContextSwitchTest03', function () { + let result = tabPaneContextSwitch.groupByThreadToMap(dataArray) + expect(result.get(0).length).toBe(1); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneCounter.test.ts b/host/ide/test/trace/component/trace/sheet/TabPaneCounter.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d7206491353087ba6a80996160e1f10a0c48096c --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/TabPaneCounter.test.ts @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneCounter} from "../../../../../dist/trace/component/trace/sheet/TabPaneCounter.js" + +const sqlit = require("../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../dist/trace/database/SqlLite.js"); +describe('TabPaneCounter Test', () => { + let tabPaneCounter = new TabPaneCounter(); + it('TabPaneCounterTest01', function () { + expect(tabPaneCounter.groupByTrackIdToMap([{ + id: 0, + trackId: 0, + name: "", + value: 0, + startTime: 0, + }])) + }); + + it('TabPaneCounterTest02', function () { + expect(tabPaneCounter.createSelectCounterData([{ + id: 0, + trackId: 0, + name: "", + value: 0, + startTime: 0, + }], 0, 1)) + }); + + it('TabPaneCounterTest03', function () { + expect(tabPaneCounter.sortByColumn({ + key: 'name', + sort: () => { + } + })) + }); + + + it('TabPaneCounterTest04', function () { + let mockgetTabCounters = sqlit.getTabCounters + mockgetTabCounters.mockResolvedValue( + {trackId : 11, + name: "test", + value:111, + startTime:142445, + },{trackId : 11, + name: "test", + value:222, + startTime:142446, + }) + let a = {rightNs: 1, trackIds: [11, 12, 13]} + expect(tabPaneCounter.data = a).toBeTruthy(); + }); + + + it('TabPaneCounterTest05', function () { + let mockgetTabCounters = sqlit.getTabCounters + mockgetTabCounters.mockResolvedValue([] + ) + let a = {rightNs: 1, trackIds: [11, 12, 13]} + expect(tabPaneCounter.data = a).toBeTruthy(); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneCpu.test.ts b/host/ide/test/trace/component/trace/sheet/TabPaneCpu.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..fed58e89359ecf027e3cd11f8481d1f21840ac8d --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/TabPaneCpu.test.ts @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneCpu} from "../../../../../dist/trace/component/trace/sheet/TabPaneCpu.js" + +describe('TabPaneCpu Test', ()=>{ + + let tabPaneCpu = new TabPaneCpu(); + + it('TabPaneCpuTest01', function () { + expect(tabPaneCpu.initHtml()).not.toBe('') + }); + it('TabPaneCpuTest02', function () { + expect(tabPaneCpu.initElements()).toBeUndefined() + }); +}) \ No newline at end of file diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneCpuByProcess.test.ts b/host/ide/test/trace/component/trace/sheet/TabPaneCpuByProcess.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..94fb290f37b9f2728598024db51d122228852d31 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/TabPaneCpuByProcess.test.ts @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneCpuByProcess} from "../../../../../dist/trace/component/trace/sheet/TabPaneCpuByProcess.js" +const sqlit = require("../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../dist/trace/database/SqlLite.js"); +describe('TabPaneCpuByProcess Test', () => { + let tabPaneCpuByProcess = new TabPaneCpuByProcess(); + tabPaneCpuByProcess.sortByColumn = jest.fn(()=> true) + + it('TabPaneCpuByProcessTest01', function () { + expect(tabPaneCpuByProcess.sortByColumn({ + key: 'name', + sort: () => { + } + })).toBeTruthy(); + }); + + it('TabPaneCpuByProcessTest02', function () { + let mockgetTabCpuByProcess = sqlit.getTabCpuByProcess + mockgetTabCpuByProcess.mockResolvedValue([{process : "test", + wallDuration: 10, + occurrences: 10 + }, + {process : "test2", + wallDuration: 11, + occurrences: 11 + }] + ) + let a = {rightNs: 1, cpus: [11, 12, 13]} + expect(tabPaneCpuByProcess.data = a).toBeTruthy(); + }); + + it('TabPaneCpuByProcessTest03', function () { + let mockgetTabCpuByProcess = sqlit.getTabCpuByProcess + mockgetTabCpuByProcess.mockResolvedValue([]) + let a = {rightNs: 1, cpus: [11, 12, 13]} + expect(tabPaneCpuByProcess.data = a).toBeTruthy(); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneCpuByThread.test.ts b/host/ide/test/trace/component/trace/sheet/TabPaneCpuByThread.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d01b6ecce862afb4924bb6de15024a4edd9d46a8 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/TabPaneCpuByThread.test.ts @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneCpuByThread} from "../../../../../dist/trace/component/trace/sheet/TabPaneCpuByThread.js" + +describe('TabPaneCpuByThread Test', () => { + let tabPaneCpuByThread = new TabPaneCpuByThread(); + + it('TabPaneCpuByThreadTest01', function () { + expect(tabPaneCpuByThread.sortByColumn({ + key: 'name', + sort: () => { + } + })).toBeUndefined(); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneCpuUsage.test.ts b/host/ide/test/trace/component/trace/sheet/TabPaneCpuUsage.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d70e77feda656ac03d080bf3159592143e2bf2a5 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/TabPaneCpuUsage.test.ts @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneCpuUsage} from "../../../../../dist/trace/component/trace/sheet/TabPaneCpuUsage.js" + +describe('TabPaneCpuUsage Test', () => { + let tabPaneCpuUsage = new TabPaneCpuUsage(); + + it('TabPaneCpuUsageTest02', function () { + expect(tabPaneCpuUsage.sortTable([[1,2,3,9,6,4],[5,2,1,4,9,6]],1,true)).toBeUndefined(); + }); + + it('TabPaneCpuUsageTest03', function () { + expect(tabPaneCpuUsage.sortTable([[1,2,3,9,6,4],[5,2,1,4,9,6]],1,false)).toBeUndefined(); + }); + it('TabPaneCpuUsageTest04', function () { + let result = tabPaneCpuUsage.sortFreq([{ + cpu: 0, + value: 0, + startNs: 0, + dur: 0, + },{ + cpu: 1, + value: 2, + startNs: 2, + dur: 4, + }]); + expect(result[0][0]).toBe(2); + }); + it('TabPaneCpuUsageTest05', function () { + expect(tabPaneCpuUsage.getFreqTop3({ + cpu: 0, + usage: 0, + usageStr: "usage", + top1: 1, + top2: 2, + top3: 3, + top1Percent: 11, + top1PercentStr: "Str1", + top2Percent: 22, + top2PercentStr: "Str2", + top3Percent: 33, + top3PercentStr: "Str3", + }, undefined, undefined, undefined, 1)).toBeUndefined(); + }); + it('TabPaneCpuUsageTest06', function () { + let result = tabPaneCpuUsage.groupByCpuToMap([{ + cpu: 0, + value: 0, + startNs: 0, + dur: 0, + },{ + cpu: 1, + value: 2, + startNs: 2, + dur: 4, + }]) + expect(result.get(0).length).toBe(1); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneCurrentSelection.test.ts b/host/ide/test/trace/component/trace/sheet/TabPaneCurrentSelection.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..5ecf5f1719d90fc6ba210676b7daa274b8f6afba --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/TabPaneCurrentSelection.test.ts @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneCurrentSelection, getTimeString} from "../../../../../dist/trace/component/trace/sheet/TabPaneCurrentSelection.js" +import {SpApplication} from "../../../../../src/trace/SpApplication"; +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + + })); +describe('TabPaneCurrentSelection Test', () => { + let tabPaneCurrentSelection = new TabPaneCurrentSelection(); + + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + + let cpuData = [{ + cpu: 1, + dur: 1, + end_state: 'string', + id: 12, + name: 'name', + priority: 11, + processCmdLine: 'processCmdLine', + processId: 111, + processName: 'processName', + schedId: 22, + startTime: 0, + tid: 100, + type: 'type', + }] + let functionData = [{ + argsetid: 53161, + depth: 0, + dur: 570000, + funName: "binder transaction", + id: 92749, + is_main_thread: 0, + parent_id: null, + startTs: 9729867000, + threadName: "Thread-15", + tid: 2785, + }] + let memData = [{ + trackId: 100, + processName:'processName', + pid: 11, + upid:1, + trackName:'trackName', + type:'type', + track_id: 'track_id', + value: 111, + startTime:0, + duration:1000, + maxValue:4000, + delta: 2, + }] + let threadData = [{ + hasSched: 14724852000, + pid: 2519, + processName: null, + threadName: "ACCS0", + tid: 2716, + upid: 1, + utid: 1, + cpu: null, + dur: 405000, + end_ts: null, + id: 1, + is_main_thread: 0, + name: "ACCS0", + startTime: 58000, + start_ts: null, + state: "S", + type: "thread", + }] + let wakeupBean = [{ + wakeupTime:0, + cpu:1, + process:'process', + pid:11, + thread:'thread', + tid:22, + schedulingLatency:33, + schedulingDesc:'schedulingDesc', + + }] + + let queryData = [{ + id:1, + startTime:0, + hasSched: 14724852000, + pid: 2519, + processName: null, + threadName: "ACCS0", + tid: 2716, + upid: 1, + utid: 1, + cpu: null, + dur: 405000, + end_ts: null, + is_main_thread: 0, + name: "ACCS0", + start_ts: null, + state: "S", + type: "thread", + + }] + + tabPaneCurrentSelection.queryWakeUpData = jest.fn(()=> 'WakeUpData') + tabPaneCurrentSelection.queryWakeUpData.wb = jest.fn(()=>null) + + + + it('TabPaneCurrentSelectionTest01', function () { + let result = tabPaneCurrentSelection.setFunctionData(functionData) + expect(result).toBeUndefined(); + }); + + it('TabPaneCurrentSelectionTest02', function () { + let result = tabPaneCurrentSelection.setMemData(memData) + expect(result).toBeUndefined(); + }); + + it('TabPaneCurrentSelectionTest12', function () { + let result = tabPaneCurrentSelection.queryWakeUpData(queryData) + expect(result).toBeTruthy(); + }); + + it('TabPaneCurrentSelectionTest03', function () { + let result = tabPaneCurrentSelection.setThreadData(threadData) + expect(result).toBeUndefined(); + }); + + it('TabPaneCurrentSelectionTest04', function () { + let result = tabPaneCurrentSelection.drawRight(canvas, wakeupBean) + expect(result).toBeUndefined(); + }); + + it('TabPaneCurrentSelectionTest06', function () { + let result = getTimeString(3600000000001) + expect(result).toBe('1h 1ns '); + }); + + it('TabPaneCurrentSelectionTest07', function () { + let result = getTimeString(60000000001) + expect(result).toBe('1m 1ns '); + }); + + it('TabPaneCurrentSelectionTest08', function () { + let result = getTimeString(1000000001) + expect(result).toBe('1s 1ns '); + }); + + it('TabPaneCurrentSelectionTest9', function () { + let result = getTimeString(1000001) + expect(result).toBe('1ms 1ns '); + }); + + it('TabPaneCurrentSelectionTest10', function () { + let result = getTimeString(1001) + expect(result).toBe('1μs 1ns '); + }); + + it('TabPaneCurrentSelectionTest11', function () { + let result = getTimeString(101) + expect(result).toBe('101ns '); + }); + +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPanePTS.test.ts b/host/ide/test/trace/component/trace/sheet/TabPanePTS.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..76a843cc06432f87b75151cf38e95e87fa000bbd --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/TabPanePTS.test.ts @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPanePTS} from "../../../../../dist/trace/component/trace/sheet/TabPanePTS.js" +window.ResizeObserver = window.ResizeObserver ||jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), +})); +describe('TabPanePTS Test', () => { + let tabPanePTS = new TabPanePTS(); + + + let dataArray = [{ + id: "", + pid: "", + title: "", + children: [], + process: "", + processId: 0, + thread: "", + threadId: 0, + state: "", + wallDuration: 0, + avgDuration: "", + count: 0, + minDuration: 0, + maxDuration: 0, + stdDuration: "", + }] + + it('TabPanePTSTest01', function () { + let result = tabPanePTS.groupByProcessThreadToMap(dataArray); + expect(result.get(0).length).toBeUndefined(); + }); + + it('TabPanePTSTest02', function () { + let result = tabPanePTS.groupByProcessToMap(dataArray) + expect(result.get(0).length).toBe(1); + }); + + it('TabPanePTSTest03', function () { + let result = tabPanePTS.groupByThreadToMap(dataArray) + expect(result.get(0).length).toBe(1); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneSPT.test.ts b/host/ide/test/trace/component/trace/sheet/TabPaneSPT.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..e6cdc3d1fc75a223c21db98f3c5717008e79b77d --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/TabPaneSPT.test.ts @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneSPT} from "../../../../../dist/trace/component/trace/sheet/TabPaneSPT.js" +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); +describe('TabPaneSPT Test', () => { + let tabPaneSPT = new TabPaneSPT(); + + let dataArray = [{ + id: "", + pid: "", + title: "", + children: [], + process: "", + processId: 0, + thread: "", + threadId: 0, + state: "", + wallDuration: 0, + avgDuration: "", + count: 0, + minDuration: 0, + maxDuration: 0, + stdDuration: "", + }] + + it('TabPaneSPTTest01', function () { + let result = tabPaneSPT.groupByStateToMap(dataArray); + expect(result.get('').length).toBe(1); + }); + + it('TabPaneSPTTest02', function () { + let result = tabPaneSPT.groupByProcessToMap(dataArray) + expect(result.get(0).length).toBe(1); + }); + + it('TabPaneSPTTest03', function () { + let result = tabPaneSPT.groupByStateProcessToMap(dataArray) + expect(result.get('').get(0).length).toBe(1); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneSlices.test.ts b/host/ide/test/trace/component/trace/sheet/TabPaneSlices.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..d00e3b5b9e5a65982037ec7fa77aae610f9be59a --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/TabPaneSlices.test.ts @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneSlices} from "../../../../../dist/trace/component/trace/sheet/TabPaneSlices.js" + +const sqlit = require("../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../dist/trace/database/SqlLite.js"); +describe('TabPaneSlices Test', () => { + let tabPaneSlices = new TabPaneSlices(); + + tabPaneSlices.sortByColumn = jest.fn(()=> true) + + it('TabPaneSlicesTest01', function () { + expect(tabPaneSlices.sortByColumn({ + key: 'name', + sort: () => { + } + })).toBeTruthy(); + }); + + it('TabPaneSlicesTest02', function () { + let mockgetTabThreadStates = sqlit.getTabSlices + mockgetTabThreadStates.mockResolvedValue([{name : "11", + wallDuration: 10, + occurrences: 10, + },{name : "22", + wallDuration: 20, + occurrences: 20, + }] + ) + let a = {rightNs: 1, leftNs: 0, funTids: [11, 12, 13]} + expect(tabPaneSlices.data = a).toBeTruthy(); + }); + + it('TabPaneSlicesTest03', function () { + let mockgetTabThreadStates = sqlit.getTabSlices + mockgetTabThreadStates.mockResolvedValue([]) + let a = {rightNs: 1, leftNs: 0, funTids: [11, 12, 13]} + expect(tabPaneSlices.data = a).toBeTruthy(); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneThreadStates.test.ts b/host/ide/test/trace/component/trace/sheet/TabPaneThreadStates.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..e2dcc099a1cc0b51909d5da77044a3f024601246 --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/TabPaneThreadStates.test.ts @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneThreadStates} from "../../../../../dist/trace/component/trace/sheet/TabPaneThreadStates.js" + +const sqlit = require("../../../../../dist/trace/database/SqlLite.js") +jest.mock("../../../../../dist/trace/database/SqlLite.js"); +describe('TabPaneThreadStates Test', () => { + let tabPaneThreadStates = new TabPaneThreadStates(); + + tabPaneThreadStates.sortByColumn = jest.fn(() => true) + + it('TabPaneThreadStatesTest01', function () { + expect(tabPaneThreadStates.sortByColumn({ + key: 'name', + sort: () => { + } + })).toBeTruthy(); + }); + + + it('TabPaneThreadStatesTest02', function () { + // @ts-ignore + let mockgetTabThreadStates = sqlit.getTabThreadStates + mockgetTabThreadStates.mockResolvedValue( + [{process: "11", + thread: "222", + wallDuration: 10, + occurrences: 10, + state: "sss", + stateJX: "mm" + },{process: "11", + thread: "222", + wallDuration: 10, + occurrences: 10, + state: "sss", + stateJX: "mm" + }] + ) + let a = {rightNs: 1, leftNs: 0, threadIds: [11, 12, 13]} + expect(tabPaneThreadStates.data = a).toBeTruthy(); + }); + + it('TabPaneThreadStatesTest03', function () { + // @ts-ignore + let mockgetTabThreadStates = sqlit.getTabThreadStates + mockgetTabThreadStates.mockResolvedValue([]) + let a = {rightNs: 1, leftNs: 0, threadIds: [11, 12, 13]} + expect(tabPaneThreadStates.data = a).toBeTruthy(); + }); +}) diff --git a/host/ide/test/trace/component/trace/sheet/TabPaneThreadSwitch.test.ts b/host/ide/test/trace/component/trace/sheet/TabPaneThreadSwitch.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..cd1fce51cad6516ad122f5e263728871d066dbfa --- /dev/null +++ b/host/ide/test/trace/component/trace/sheet/TabPaneThreadSwitch.test.ts @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneThreadSwitch} from "../../../../../dist/trace/component/trace/sheet/TabPaneThreadSwitch.js" +window.ResizeObserver = window.ResizeObserver || + jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); +describe('TabPaneContextSwitch Test', () => { + let tabPaneThreadSwitch = new TabPaneThreadSwitch(); + let dataArray = [{ + id: "", + pid: "", + title: "", + children: [], + process: "", + processId: 0, + thread: "", + threadId: 0, + state: "", + wallDuration: 0, + avgDuration: "", + count: 0, + minDuration: 0, + maxDuration: 0, + stdDuration: "", + }] +let val={ + leftNs:1, + rightNs:1, + +} + it('TabPaneThreadSwitchTest01', function () { + let result = tabPaneThreadSwitch.groupByStateToMap(dataArray); + expect(result.get('').length).toBe(1); + }); + + it('TabPaneThreadSwitchTest02', function () { + let result = tabPaneThreadSwitch.groupByProcessToMap(dataArray) + expect(result.get(0).length).toBe(1); + }); + + it('TabPaneThreadSwitchTest03', function () { + let result = tabPaneThreadSwitch.groupByStateProcessToMap(dataArray) + expect(result.get('').get(0).length).toBe(1); + }); + + it('TabPaneThreadSwitchTest04', function () { + expect(tabPaneThreadSwitch.data).toBeUndefined(); + }); + + it('TabPaneThreadSwitchTest05', function () { + expect(tabPaneThreadSwitch.queryDataByCacheData(val)).toBeUndefined(); + }); + + + +}) diff --git a/host/ide/test/trace/component/trace/timer-shaft/RangeRuler.test.ts b/host/ide/test/trace/component/trace/timer-shaft/RangeRuler.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..99775c99538cd8e4f44aab9dc3baca4773796fcb --- /dev/null +++ b/host/ide/test/trace/component/trace/timer-shaft/RangeRuler.test.ts @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {RangeRuler} from "../../../../../dist/trace/component/trace/timer-shaft/RangeRuler.js" +// @ts-ignore +import {Mark} from "../../../../../dist/trace/component/trace/timer-shaft/RangeRuler.js"; + +describe('RangeRuler Test', ()=>{ + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + let rangeRuler = new RangeRuler(canvas , ctx, { + x: 20, + y: 20, + width: 100, + height: 100 + }, { + startX: 10, + endX: 30 + }); + let mark = new Mark(canvas , ctx, '', { + x: 20, + y: 20, + width: 100, + height: 100 + }); + + rangeRuler.cpuUsage = ([{ + cpu: 1, + ro: 2, + rate: 2 + }]) + + mark.isHover = true + + it('RangeRulerTest01', function () { + expect(rangeRuler.drawCpuUsage()).toBeUndefined(); + }); + + it('RangeRulerTest02', function () { + expect(rangeRuler.fillX()).toBeUndefined(); + }); + + it('RangeRulerTest03', function () { + expect(rangeRuler.keyPress({ + key: 'w' + })).toBeUndefined(); + }); + + it('RangeRulerTest04', function () { + expect(rangeRuler.keyPress({ + key: 's' + })).toBeUndefined(); + }); + + it('RangeRulerTest05', function () { + expect(rangeRuler.keyPress({ + key: 'a' + })).toBeUndefined(); + }); + + it('RangeRulerTest06', function () { + expect(rangeRuler.keyPress({ + key: 'd' + })).toBeUndefined(); + }); + + it('RangeRulerTest07', function () { + expect(rangeRuler.keyUp({ + key: 'w' + })).toBeUndefined(); + }); + + it('RangeRulerTest08', function () { + expect(rangeRuler.keyUp({ + key: 's' + })).toBeUndefined(); + }); + + it('RangeRulerTest09', function () { + expect(rangeRuler.keyUp({ + key: 'a' + })).toBeUndefined(); + }); + + it('RangeRulerTest10', function () { + expect(rangeRuler.keyUp({ + key: 'd' + })).toBeUndefined(); + }); + + it('RangeRulerTest11', function () { + expect(rangeRuler.mouseUp({ + key: '' + })).toBeUndefined(); + }); + + it('RangeRulerTest12', function () { + expect(rangeRuler.mouseOut({ + key: '' + })).toBeUndefined(); + }); + + it('RangeRulerTest13', function () { + rangeRuler.markA = jest.fn(()=>true) + rangeRuler.rangeRect = jest.fn(()=>true) + rangeRuler.rangeRect.containsWithPadding = jest.fn(()=>true) + + rangeRuler.markA = jest.fn(()=> { + return { + frame: { + x: 20 + } + } + }) + rangeRuler.markA.isHover = jest.fn(()=> true) + rangeRuler.markA.frame = jest.fn(()=> []) + rangeRuler.markA.frame.x = jest.fn(()=>true) + + expect(rangeRuler.mouseDown({ + key: '' + })).toBeUndefined(); + }); + + it('RangeRulerTest14', function () { + rangeRuler.markA = jest.fn(()=>true) + rangeRuler.rangeRect = jest.fn(()=>true) + rangeRuler.rangeRect.containsWithPadding = jest.fn(()=>false) + rangeRuler.frame = jest.fn(()=>false) + rangeRuler.frame.containsWithMargin = jest.fn(()=> true) + rangeRuler.rangeRect.containsWithMargin = jest.fn(()=> false) + rangeRuler.markB.isHover = jest.fn(()=> true) + rangeRuler.markB.frame = jest.fn(()=> true) + rangeRuler.markB.frame.x = jest.fn(()=>true) + expect(rangeRuler.mouseDown({ + key: '' + })).toBeUndefined(); + }); + + it('RangeRulerTest15', function () { + rangeRuler.markA = jest.fn(()=>true) + rangeRuler.markA.inspectionFrame = jest.fn(()=>true) + rangeRuler.markA.inspectionFrame.contains = jest.fn(()=>true) + rangeRuler.markA.frame = jest.fn(()=> true) + rangeRuler.markA.frame.x = jest.fn(()=>true) + rangeRuler.markA.draw = jest.fn(()=>true) + expect(rangeRuler.mouseMove({ + key: '' + })).toBeUndefined(); + }); + + it('RangeRulerTest16', ()=> { + rangeRuler.markA = jest.fn(()=>false) + rangeRuler.markA.draw = jest.fn(()=>true) + rangeRuler.markA.frame = jest.fn(()=> true) + rangeRuler.markA.frame.x = jest.fn(()=>true) + rangeRuler.markA.inspectionFrame = jest.fn(()=>false) + rangeRuler.markA.inspectionFrame.contains = jest.fn(()=>false) + rangeRuler.movingMark = jest.fn(()=>false) + rangeRuler.movingMark.frame = jest.fn(()=> false) + rangeRuler.movingMark.frame.x = jest.fn(()=>false) + rangeRuler.rangeRect = jest.fn(()=>true) + rangeRuler.rangeRect.containsWithPadding = jest.fn(()=>true) + rangeRuler.movingMark.inspectionFrame = jest.fn(()=>false) + rangeRuler.movingMark.inspectionFrame.x = jest.fn(()=>false) + expect(rangeRuler.mouseMove({ + key: '' + })).toBeUndefined(); + }); + it('RangeRulerTest17', ()=> { + rangeRuler.notifyHandler = jest.fn(()=>true) + rangeRuler.movingMark.inspectionFrame.x = jest.fn(()=>false) + rangeRuler.c = jest.fn(()=>true) + rangeRuler.frame = jest.fn(()=>true) + rangeRuler.frame.x = jest.fn(()=>true) + rangeRuler.frame.y = jest.fn(()=>true) + rangeRuler.c.clearRect = jest.fn(()=>true) + expect(rangeRuler.draw()).toBeUndefined(); + }); + + it('RangeRulerTest18', function () { + expect(mark.isHover).toBeTruthy(); + }); +}) diff --git a/host/ide/test/trace/component/trace/timer-shaft/Rect.test.ts b/host/ide/test/trace/component/trace/timer-shaft/Rect.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..82d7175a38f01635b15947f8fbc1b508ed72cd78 --- /dev/null +++ b/host/ide/test/trace/component/trace/timer-shaft/Rect.test.ts @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {Rect, Point} from "../../../../../dist/trace/component/trace/timer-shaft/Rect.js" + +describe('Rect Test', ()=>{ + let rect = new Rect(20, 20, 100, 100); + let point = new Point() + + it('RectTest01', function () { + expect(rect.contains(4,5)).toBeFalsy(); + }); + + it('RectTest02', function () { + expect(Rect.contains(rect, 4, 4)).toBeFalsy(); + }); + + it('RectTest03', function () { + expect(rect.containsWithPadding(4,5, 2, 2)).toBeFalsy(); + }); + + it('RectTest04', function () { + expect(Rect.containsWithPadding(rect, 4, 4, 2, 2)).toBeFalsy(); + }); + + it('RectTest05', function () { + expect(rect.containsWithMargin(1,2,1,2,4,5,)).toBeFalsy(); + }); + + it('RectTest06', function () { + expect(Rect.containsWithMargin(1,2,1,2,4,5,)).toBeFalsy(); + }); + + it('RectTest07', function () { + expect(rect.intersect([])).toBeFalsy(); + }); +}) diff --git a/host/ide/test/trace/component/trace/timer-shaft/SportRuler.test.ts b/host/ide/test/trace/component/trace/timer-shaft/SportRuler.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..41d3e8338cfab12b07b2b86f45ff640415871dcd --- /dev/null +++ b/host/ide/test/trace/component/trace/timer-shaft/SportRuler.test.ts @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {SportRuler} from "../../../../../dist/trace/component/trace/timer-shaft/SportRuler.js" + +describe('SportRuler Test', ()=>{ + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + let sportRuler = new SportRuler(canvas, ctx, { + x: 20, + y: 20, + width: 100, + height: 100, + }); + + sportRuler.range = { + totalNS: 20, + startX: 0, + endX: 10, + startNS: 10, + endNS: 20, + xs: [], + xsTxt: [], + } + + it('SportRulerTest01', function () { + expect(sportRuler.drawTheFlag(2, '#999999', false, 'text')).toBeUndefined(); + }); + + it('SportRulerTest02', function () { + let randomRgbColor = sportRuler.randomRgbColor(); + let isColor = randomRgbColor.length > 4; + expect(isColor).toBeTruthy() + }); + + it('SportRulerTest03', function () { + expect(sportRuler.onFlagRangeEvent({ + x: 0, + y: 0, + width: 0, + height: 0, + time: 0, + color: "", + selected: false, + text: "", + }, 2)).toBeUndefined(); + }); + + it('SportRulerTest04', function () { + expect(sportRuler.mouseMove({ + offsetY: 20, + offsetX: 20, + })).toBeUndefined(); + }); + + it('SportRulerTest05', function () { + let ranges = sportRuler.range; + expect(ranges.endNS).toBe(20); + }) + + it('SportRulerTest06', function () { + sportRuler.flagListIdx = jest.fn(()=>"flagListIdx") + sportRuler.flagList = jest.fn(()=>true) + expect(sportRuler.modifyFlagList('amend', {})).toBeUndefined(); + }) + + it('SportRulerTest07', function () { + sportRuler.flagList.splice = jest.fn(()=>true) + expect(sportRuler.modifyFlagList('remove', {})).toBeUndefined(); + }) + + it('SportRulerTest08', function () { + expect(sportRuler.draw()).toBeUndefined(); + }) + + it('SportRulerTest09', function () { + expect(sportRuler.mouseUp()).toBeUndefined(); + }) + + it('SportRulerTest10', function () { + sportRuler.draw = jest.fn(()=>true) + expect(sportRuler.mouseMove({ + offsetX: 10000, + offsetY: 10000 + })).toBeUndefined(); + }); + +}) diff --git a/host/ide/test/trace/component/trace/timer-shaft/TabPaneFlag.test.ts b/host/ide/test/trace/component/trace/timer-shaft/TabPaneFlag.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..88198fa1f5bb856f9a54d18c55be597b1af29b7f --- /dev/null +++ b/host/ide/test/trace/component/trace/timer-shaft/TabPaneFlag.test.ts @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TabPaneFlag} from "../../../../../dist/trace/component/trace/timer-shaft/TabPaneFlag.js" + +describe('TabPaneFlag Test', ()=>{ + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + let tabPaneFlag = new TabPaneFlag(canvas , ctx, { + x: 20, + y: 20, + width: 100, + height: 100 + }, 10000000000); + + it('TabPaneFlagTest01', function () { + expect(tabPaneFlag.initElements()).toBeUndefined(); + }); + + it('TabPaneFlagTest01', function () { + expect(tabPaneFlag.initHtml()).not.toBe('') + }); + + it('TabPaneFlagTest01', function () { + expect(tabPaneFlag.setFlagObj({ + x: 0, + y: 0, + width: 0, + height: 0, + time: 0, + color: "", + selected: false, + text: "", + }, 5)).toBeUndefined(); + }); +}) diff --git a/host/ide/test/trace/component/trace/timer-shaft/TimeRuler.test.ts b/host/ide/test/trace/component/trace/timer-shaft/TimeRuler.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..cb3ae26ea93cedbc8bbf821b0757d47c2bf1d080 --- /dev/null +++ b/host/ide/test/trace/component/trace/timer-shaft/TimeRuler.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {TimeRuler} from "../../../../../dist/trace/component/trace/timer-shaft/TimeRuler.js" + +describe('TimeRuler Test', ()=>{ + const canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext('2d'); + + let timeRuler = new TimeRuler(canvas , ctx, { + x: 20, + y: 20, + width: 100, + height: 100 + }, 10000000000); + + it('TimeRulerTest01', function () { + expect(timeRuler.draw()).toBeUndefined(); + }); +}) diff --git a/host/ide/test/trace/database/Procedure.test.ts b/host/ide/test/trace/database/Procedure.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..c3cb4c95993cfc4840c0068f96a92307c1897c4c --- /dev/null +++ b/host/ide/test/trace/database/Procedure.test.ts @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// @ts-ignore +import {procedurePool} from "../../../dist/trace/database/Procedure.js" + +describe('procedure Test', () => { + // let procedure = new procedurePool(); + it('ProfilerClientTest01', function () { + expect(procedurePool.uuid).toBeUndefined(); + }); + + }) diff --git a/host/ide/test/trace/grpc/HiProfilerClient.test.ts b/host/ide/test/trace/grpc/HiProfilerClient.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..cfe9dcee069dd66c11c03f7bdb44d0631124da53 --- /dev/null +++ b/host/ide/test/trace/grpc/HiProfilerClient.test.ts @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {HiProfilerClient} from "../../../dist/trace/grpc/HiProfilerClient.js" + +describe('HiProfilerClient Test', ()=>{ + let hiProfilerClient = new HiProfilerClient(); + it('HiProfilerClientTest01', function () { + expect(hiProfilerClient.address).toBeUndefined(); + }); + + it('HiProfilerClientTest02', function () { + hiProfilerClient.address=true; + expect(hiProfilerClient.address).toBeTruthy(); + }); + + it('HiProfilerClientTest03', function () { + expect(hiProfilerClient.client).toBeUndefined(); + }); + + it('HiProfilerClientTest04', function () { + hiProfilerClient.client=true; + expect(hiProfilerClient.client).toBeTruthy(); + }); + + it('HiProfilerClientTest05', function () { + expect(hiProfilerClient.getProfilerClient()).toBeUndefined(); + }); + +}) \ No newline at end of file diff --git a/host/ide/test/trace/grpc/ProfilerClient.test.ts b/host/ide/test/trace/grpc/ProfilerClient.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..a4e00e769e34b03384a98e71ce12369508ca8cfb --- /dev/null +++ b/host/ide/test/trace/grpc/ProfilerClient.test.ts @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-ignore +import {ProfilerClient} from "../../../dist/trace/grpc/ProfilerClient.js" + +describe('HiProfilerClient Test', ()=>{ + + + it('ProfilerClientTest01', function () { + expect(ProfilerClient.client).toBeUndefined(); + }); + it('ProfilerClientTest01', function () { + ProfilerClient.client = true; + expect(ProfilerClient.client).toBeTruthy(); + }); + +}) \ No newline at end of file diff --git a/host/ide/tsconfig.json b/host/ide/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..57e2db39f93c0524745586404c81c2c5b2b28aeb --- /dev/null +++ b/host/ide/tsconfig.json @@ -0,0 +1,71 @@ +{ + "compilerOptions": { + "experimentalDecorators": true, + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "ES2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "es2015", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + // "lib": [], /* Specify library files to be included in the compilation. */ +// "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./dist", /* Redirect output structure to the directory. */ + "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true, /* Skip type checking of declaration files. */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "include": ["src"] +} diff --git a/host/trace_streamer/.gn b/host/trace_streamer/.gn new file mode 100644 index 0000000000000000000000000000000000000000..814190914c15108ecabbd3f4413d318a85ba09d0 --- /dev/null +++ b/host/trace_streamer/.gn @@ -0,0 +1,14 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +buildconfig = "//gn/CONFIG.gn" diff --git a/host/trace_streamer/BUILD.gn b/host/trace_streamer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..092bb98c46e3328169c387349de1c53cf88bb3d3 --- /dev/null +++ b/host/trace_streamer/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +group("trace_streamer") { + if (use_wasm) { + deps = [ "src:trace_streamer_builtin" ] + } else if (is_test) { + deps = [ "test:unittest" ] + testonly = true + } else { + deps = [ "src:trace_streamer" ] + } +} diff --git a/host/trace_streamer/README.md b/host/trace_streamer/README.md new file mode 100644 index 0000000000000000000000000000000000000000..eb0deec07b8f4c55fed4152454f49cad6d721cb9 --- /dev/null +++ b/host/trace_streamer/README.md @@ -0,0 +1,309 @@ +# trace_streamer工具说明 +trace_streamer工具可以2种方式使用 +1. 可以将系统离线trace文件解析并转为db,此工具支持基于文本的trace和基于proto的trace。 +2. trace_streamer工具还可以WebAssembly的方式在浏览器中运行,需暴露相关接口给js文件。 + +## 关于trace解析工具的使用说明: +### 导出db模式 +在导出db模式下,trace_streamer.exe trace文件路径名 -e 导出db路径名.db +此命令可以将trace文件转为db +本应用支持在ohos, linux, windows, mac使用。 +关于db文件的说明: +使用db查看工具查看stat表,可以浏览当前数据一共有多少类数据,各类数据都收到多少条,数据是否正常等情况。在meta表会记录数据库导出时的一些系统信息,比如导入和导出的文件全路径,解析时间等信息。 +meta表可以选择不导出(有些情况下会暴露系统敏感信息),在导出时添加 -nm选项即可。 +在数据导出之后,会在本地目录下生成一个trace_streamer.log文件,在导出db的目录下生成一个数据库文件同名,.db.ohos.ts后缀的文件 +文件内容如下: +时间戳:执行结果(数字) +应用运行时间 + +执行结果解释如下:0 代表执行成功 1 表示输入文件不匹配, 2 表示解析错误, 3其他错误 +### 内置浏览器方式 +trace_streamer可以WebAssembly方式在浏览器中运行,暴露如下接口给js +``` +extern "C" { +/* 上传trace数据 + * + * @data: 数据的缓冲区 + * @dataLen: 数据长度 + * + * return: 0:成功; -1:失败 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerParseData(const uint8_t* data, int dataLen); + +/* 通知TS上传trace数据结束 + * + * return: 0:成功; -1:失败 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerParseDataOver(); + +/* 通过sql语句操作数据库 + * + * @sql: sql语句 + * @sqlLen: sql语句长度 + * + * return: 0:成功; -1:失败 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlOperate(const uint8_t* sql, int sqlLen); + +/* 通过sql语句查询数据库 + * + * @sql: sql语句 + * @sqlLen: sql语句长度 + * @out: 查询结果的缓冲区,查询结果为json + * @outLen: 缓冲区长度 + * + * return: >0:查询成功,返回查询结果数据长度; -1:失败 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlQuery(const uint8_t* sql, int sqlLen, uint8_t* out, int outLen); + +} // extern "C" +``` + +### 你也可以执行如下命令查看应用帮助 +./trace_streamer --help +-i 选项可查看应用支持的事件源和具体的事件名列表 + +#### trace_streamer支持的事件解析 +本工具支持基于文本的trace(# TRACE)和基于proto的二进制日志文件的解析,支持的事件列表如下: +##### ftrace事件 +``` +binder_transaction +binder_transaction_received +binder_transaction_alloc_buf +binder_transaction_lock +binder_transaction_locked +binder_transaction_unlock +sched_switch +task_rename +task_newtask +tracing_mark_write +print +sched_wakeup +sched_waking +cpu_idle +cpu_frequency +suspend_resume +workqueue_execute_start +workqueue_execute_end +clock_set_rate +clock_enable +clock_disable +clk_set_rate +clk_enable +clk_disable +sys_enter +sys_exit +regulator_set_voltage +regulator_set_voltage_complete +regulator_disable +regulator_disable_complete +ipi_entry +ipi_exit +irq_handler_entry +irq_handler_exit +softirq_raise +softirq_entry +softirq_exit +sched_wakeup_new +sched_process_exit +trace_event_clock_sync +``` +##### 内存事件 +``` +mem.vm.size +mem.rss +mem.rss.anon +mem.rss.file +mem.rss.schem +mem.swap +mem.locked +mem.hwm +mem.oom_score_adj +``` +##### 系统内存事件 +``` +sys.mem.unspecified +sys.mem.total +sys.mem.free +sys.mem.avaiable +sys.mem.buffers +sys.mem.cached +sys.mem.swap.chard +sys.mem.active +sys.mem.inactive +sys.mem.active.anon +sys.mem.inactive.anon +sys.mem.active_file +sys.mem.inactive_file +sys.mem.unevictable +sys.mem.mlocked +sys.mem.swap.total +sys.mem.swap.free +sys.mem.dirty +sys.mem.writeback +sys.mem.anon.pages +sys.mem.mapped +sys.mem.shmem +sys.mem.slab +sys.mem.slab.reclaimable +sys.mem.slab.unreclaimable +sys.mem.kernel.stack +sys.mem.page.tables +sys.mem.commit.limit +sys.mem.commited.as +sys.mem.vmalloc.total +sys.mem.vmalloc.used +sys.mem.vmalloc.chunk +sys.mem.cma.total +sys.mem.cma.free +``` +##### 系统虚拟内存事件 +``` +sys.virtual.mem.unspecified +sys.virtual.mem.nr.free.pages +sys.virtual.mem.nr.alloc.batch +sys.virtual.mem.nr.inactive.anon +sys.virtual.mem.nr.active_anon +sys.virtual.mem.nr.inactive.file +sys.virtual.mem.nr.active_file +sys.virtual.mem.nr.unevictable +sys.virtual.mem.nr.mlock +sys.virtual.mem.anon.pages +sys.virtual.mem.nr.mapped +sys.virtual.mem.nr.file.pages +sys.virtual.mem.nr.dirty +sys.virtual.mem.nr.writeback +sys.virtual.mem.nr.slab.reclaimable +sys.virtual.mem.nr.slab.unreclaimable +sys.virtual.mem.nr.page_table.pages +sys.virtual.mem.nr_kernel.stack +sys.virtual.mem.nr.overhead +sys.virtual.mem.nr.unstable +sys.virtual.mem.nr.bounce +sys.virtual.mem.nr.vmscan.write +sys.virtual.mem.nr.vmscan.immediate.reclaim +sys.virtual.mem.nr.writeback_temp +sys.virtual.mem.nr.isolated_anon +sys.virtual.mem.nr.isolated_file +sys.virtual.mem.nr.shmem +sys.virtual.mem.nr.dirtied +sys.virtual.mem.nr.written +sys.virtual.mem.nr.pages.scanned +sys.virtual.mem.workingset.refault +sys.virtual.mem.workingset.activate +sys.virtual.mem.workingset_nodereclaim +sys.virtual.mem.nr_anon.transparent.hugepages +sys.virtual.mem.nr.free_cma +sys.virtual.mem.nr.swapcache +sys.virtual.mem.nr.dirty.threshold +sys.virtual.mem.nr.dirty.background.threshold +sys.virtual.mem.vmeminfo.pgpgin +sys.virtual.mem.pgpgout +sys.virtual.mem.pgpgoutclean +sys.virtual.mem.pswpin +sys.virtual.mem.pswpout +sys.virtual.mem.pgalloc.dma +sys.virtual.mem.pgalloc.normal +sys.virtual.mem.pgalloc.movable +sys.virtual.mem.pgfree +sys.virtual.mem.pgactivate +sys.virtual.mem.pgdeactivate +sys.virtual.mem.pgfault +sys.virtual.mem.pgmajfault +sys.virtual.mem.pgrefill.dma +sys.virtual.mem.pgrefill.normal +sys.virtual.mem.pgrefill.movable +sys.virtual.mem.pgsteal.kswapd.dma +sys.virtual.mem.pgsteal.kswapd.normal +sys.virtual.mem.pgsteal.kswapd.movable +sys.virtual.mem.pgsteal.direct.dma +sys.virtual.mem.pgsteal.direct.normal +sys.virtual.mem.pgsteal_direct.movable +sys.virtual.mem.pgscan.kswapd.dma +sys.virtual.mem.pgscan_kswapd.normal +sys.virtual.mem.pgscan.kswapd.movable +sys.virtual.mem.pgscan.direct.dma +sys.virtual.mem.pgscan.direct.normal +sys.virtual.mem.pgscan.direct.movable +sys.virtual.mem.pgscan.direct.throttle +sys.virtual.mem.pginodesteal +sys.virtual.mem.slabs_scanned +sys.virtual.mem.kswapd.inodesteal +sys.virtual.mem.kswapd.low.wmark.hit.quickly +sys.virtual.mem.high.wmark.hit.quickly +sys.virtual.mem.pageoutrun +sys.virtual.mem.allocstall +sys.virtual.mem.pgrotated +sys.virtual.mem.drop.pagecache +sys.virtual.mem.drop.slab +sys.virtual.mem.pgmigrate.success +sys.virtual.mem.pgmigrate.fail +sys.virtual.mem.compact.migrate.scanned +sys.virtual.mem.compact.free.scanned +sys.virtual.mem.compact.isolated +sys.virtual.mem.compact.stall +sys.virtual.mem.compact.fail +sys.virtual.mem.compact.success +sys.virtual.mem.compact.daemon.wake +sys.virtual.mem.unevictable.pgs.culled +sys.virtual.mem.unevictable.pgs.scanned +sys.virtual.mem.unevictable.pgs.rescued +sys.virtual.mem.unevictable.pgs.mlocked +sys.virtual.mem.unevictable.pgs.munlocked +sys.virtual.mem.unevictable.pgs.cleared +sys.virtual.mem.unevictable.pgs.stranded +sys.virtual.mem.nr.zspages +sys.virtual.mem.nr.ion.heap +sys.virtual.mem.nr.gpu.heap +sys.virtual.mem.allocstall.dma +sys.virtual.mem.allocstall.movable +sys.virtual.mem.allocstall.normal +sys.virtual.mem.compact_daemon.free.scanned +sys.virtual.mem.compact.daemon.migrate.scanned +sys.virtual.mem.nr.fastrpc +sys.virtual.mem.nr.indirectly.reclaimable +sys.virtual.mem.nr_ion_heap_pool +sys.virtual.mem.nr.kernel_misc.reclaimable +sys.virtual.mem.nr.shadow_call.stack_bytes +sys.virtual.mem.nr.shmem.hugepages +sys.virtual.mem.nr.shmem.pmdmapped +sys.virtual.mem.nr.unreclaimable.pages +sys.virtual.mem.nr.zone.active.anon +sys.virtual.mem.nr.zone.active.file +ys.virtual.mem.nr.zone.inactive_anon +sys.virtual.mem.nr.zone.inactive_file +sys.virtual.mem.nr.zone.unevictable +sys.virtual.mem.nr.zone.write_pending +sys.virtual.mem.oom.kill +sys.virtual.mem.pglazyfree +sys.virtual.mem.pglazyfreed +sys.virtual.mem.pgrefill +sys.virtual.mem.pgscan.direct +sys.virtual.mem.pgscan.kswapd +sys.virtual.mem.pgskip.dma +sys.virtual.mem.pgskip.movable +sys.virtual.mem.pgskip.normal +sys.virtual.mem.pgsteal.direct +sys.virtual.mem.pgsteal.kswapd +sys.virtual.mem.swap.ra +sys.virtual.mem.swap.ra.hit +``` + +## trace_streamer开发环境搭建和编译运行指引 + +本应用使用gn作为构建工具,支持在linux环境同时编译linux,windows和mac使用QtCreator作为开发IDE +### 1、开发环境 +ubuntu使用vscode,windows和mac使用QtCreator +# 对外部的依赖 +本应用依赖与sqlite,protobuf(htrace解析部分依赖) + +本应用同时依赖于src/protos目录下文件来生成相关pb.h,pb.cc文件 + +### 2.1、 编译linux版应用 +在根目录下执行相关命令进行编译 + +### 2.2、编译Windows版和Mac应用 +在项目目录下有pro文件,为QtCreator的工程文件,但部分内容赖在于上面所添加的外部依赖,如果要编译相关平台应用,开发者需自行补充相关工程文件,或者在论坛留言 + +### 2.3、开始编译 +具体方法可参考《compile_trace_streamer.md》 \ No newline at end of file diff --git a/host/trace_streamer/build.sh b/host/trace_streamer/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..9e183eeac90d0bd477bbe47f73d14a24b5a55d3c --- /dev/null +++ b/host/trace_streamer/build.sh @@ -0,0 +1,119 @@ +#! /bin/bash +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +PARAMS=$* +echo $PARAMS +echo "begin to check input" +target_os='linux' +is_debug='false' +is_clean='false' +if [ "$#" -ne "0" ];then + if [ $1 == "wasm" ];then + if [ ! -d "prebuilts/emsdk" ];then + echo "you need emsdk to compile wasm" + mv emsdk.tar.gz prebuilts/ + mv ../emsdk.tar.gz prebuilts/ + if [ ! -f "prebuilts/emsdk.tar.gz" ];then + # consider + # you need to get emsdk.tar.gz some where + mv emsdk.tar.gz prebuilts/ + tar -zxvf prebuilts/emsdk.tar.gz -C prebuilts/ + else + tar -zxvf prebuilts/emsdk.tar.gz -C prebuilts/ + fi + fi + target_os='wasm' + fi + if [ $1 == "test" ];then + target_os='test' + fi +fi +if [ "$#" -eq "2" ];then + if [ "$1" != 'windows' ] && [ $1 != "linux" ] && [ $1 != "wasm" ] && [ $1 != "test" ];then + echo "failed" + echo "Usage: `basename $0` windows/linux/wasm/test debug/release/clean" + exit + fi + if [ $2 != "debug" -a $2 != "release" -a $2 != "clean" ];then + echo "failed" + echo "Usage: `basename $0` windows/linux debug/release/clean" + exit + fi + if [ $2 == "debug" ];then + is_debug='true' + elif [ $2 == "clean" ];then + is_clean='true' + else + is_debug='false' + fi + target_os=$1 + if [ $target_os == "windows" ];then + echo "gn only support linux and wasm build currently" + mkdir out/windows + touch out/windows/trace_streamer.exe + exit + fi + echo "platform is $target_os" + echo "isdebug: $is_debug" +else + echo "Usage: `basename $0` windows/linux/wasm debug/release wasm[optional]" + echo "You provided $# parameters,but 2 are required." + echo "use default input paramter" + echo "platform is $target_os" + echo "is_debug:$is_debug" +fi +echo "gen ..." +ext="" +if [ "$is_debug" != 'false' ];then + ext="_debug" +fi +#exec "protogen.sh" +echo "the output file will be at ""$prefix""$target_os" +echo "" +echo "" +echo "-------------tips-------------" +echo "" +echo "if you are compiling first time, or your proto has changed, you need to run ./src/protos/protogen.sh" +echo "" +echo "" +echo +#./src/protos/protogen.sh +mkdir prebuilts/$target_os +if [ ! -f "prebuilts/$target_os/gn" ];then + echo "you may get gn for $target_os and place it in prebuilts/$target_os" + ehco "the file can be get at https://gitee.com/su_fu/public_tools/raw/master/gn/$target_os/gn, you need to download it manually" + #wget https://gitee.com/su_fu/public_tools/raw/master/gn/$target_os/gn + #mv gn prebuilts/$target_os/ + #chmod +x prebuilts/$target_os/gn + exit +fi +if [ ! -f "prebuilts/$target_os/ninja" ];then + echo "you may get ninja for $target_os and place it in prebuilts/$target_os" + ehco "the file can be get at https://gitee.com/su_fu/public_tools/raw/master/gn/$target_os/ninja, you need to download it manually" + #wget "https://gitee.com/su_fu/public_tools/raw/master/gn/$target_os/ninja" + #wget https://gitee.com/su_fu/public_tools/raw/master/gn/$target_os/ninja + #mv ninja prebuilts/$target_os/ + #chmod +x prebuilts/$target_os/* + exit +fi +echo "$is_clean" +if [ "$is_clean" == 'true' ];then + prebuilts/$target_os/gn gen out/"$target_os""$ext" --clean + prebuilts/$target_os/ninja -C out/"$target_os""$ext" -t clean +else + prebuilts/$target_os/gn gen out/"$target_os""$ext" --args='is_debug='"$is_debug"' target_os="'"$target_os"'"' + echo "begin to build ..." + mkdir -p out/windows + touch out/windows/trace_streamer.exe + prebuilts/$target_os/ninja -v -C out/"$target_os""$ext" +fi diff --git a/host/trace_streamer/build/ohos.gni b/host/trace_streamer/build/ohos.gni new file mode 100644 index 0000000000000000000000000000000000000000..2f3a1d5b211b92195156f845e220a066bbb4546f --- /dev/null +++ b/host/trace_streamer/build/ohos.gni @@ -0,0 +1,118 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +template("ohos_source_set") { + source_set(target_name) { + sources = invoker.sources + if (defined(invoker.configs)) { + configs = invoker.configs + } + if (defined(invoker.cflags)) { + cflags = invoker.cflags + } + if (defined(invoker.include_dirs)) { + include_dirs = invoker.include_dirs + } + if (defined(invoker.deps)) { + deps = invoker.deps + } + if (defined(invoker.cflags_cc)) { + cflags_cc = invoker.cflags_cc + } + if (defined(invoker.ldflags)) { + ldflags = invoker.ldflags + } + if (defined(invoker.public_deps)) { + public_deps = invoker.public_deps + } + if (defined(invoker.public_configs)) { + public_configs = invoker.public_configs + } + } +} +template("ohos_shared_library") { + shared_library(target_name) { + sources = invoker.sources + if (defined(invoker.configs)) { + configs = invoker.configs + } + public_configs = invoker.public_configs + if (defined(invoker.defines)) { + defines = invoker.defines + } + if (defined(invoker.cflags)) { + cflags = invoker.cflags + } + if (defined(invoker.include_dirs)) { + include_dirs = invoker.include_dirs + } + if (defined(invoker.cflags_cc)) { + cflags_cc = invoker.cflags_cc + } + if (defined(invoker.deps)) { + deps = invoker.deps + } + } +} +template("ohos_static_library") { + static_library(target_name) { + sources = invoker.sources + if (defined(invoker.configs)) { + configs = invoker.configs + } + public_configs = invoker.public_configs + if (defined(invoker.defines)) { + defines = invoker.defines + } + if (defined(invoker.cflags)) { + cflags = invoker.cflags + } + if (defined(invoker.include_dirs)) { + include_dirs = invoker.include_dirs + } + if (defined(invoker.cflags_cc)) { + cflags_cc = invoker.cflags_cc + } + if (defined(invoker.deps)) { + deps = invoker.deps + } + } +} +template("ohos_executable") { + executable(target_name) { + if (defined(invoker.include_dirs)) { + include_dirs = invoker.include_dirs + } + sources = invoker.sources + if (defined(invoker.defines)) { + defines = invoker.defines + } + if (defined(invoker.cflags)) { + cflags = invoker.cflags + } + if (defined(invoker.deps)) { + deps = invoker.deps + } + if (defined(invoker.cflags_cc)) { + cflags_cc = invoker.cflags_cc + } + if (defined(invoker.output_name)) { + output_name = invoker.output_name + } + if (defined(invoker.testonly)) { + testonly = invoker.testonly + } + if (defined(invoker.ohos_test)) { + ohos_test = invoker.ohos_test + } + } +} diff --git a/host/trace_streamer/build/protoc.sh b/host/trace_streamer/build/protoc.sh new file mode 100644 index 0000000000000000000000000000000000000000..8012b221cce151b4a22d5f1e417d5dc1b4771799 --- /dev/null +++ b/host/trace_streamer/build/protoc.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e +#echo "begin to protoc--------------" +LIBCXX_X64_OUT="//out/linux" +PROTOC="//out/linux/protoc" +PARAMS=$* +PARAMS_FILTER="$1 $2" +#echo "EXEC: LD_LIBRARY_PATH=$LIBCXX_X64_OUT:$PROTOC ${PARAMS[@]:${#PARAMS_FILTER}}" +LD_LIBRARY_PATH=$LIBCXX_X64_OUT exec $PROTOC ${PARAMS[@]:${#PARAMS_FILTER}} diff --git a/host/trace_streamer/build/test.gni b/host/trace_streamer/build/test.gni new file mode 100644 index 0000000000000000000000000000000000000000..6912354f710b31f32341dfbd16e51f3d78cef2be --- /dev/null +++ b/host/trace_streamer/build/test.gni @@ -0,0 +1,25 @@ +#!/bin/bash +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +template("ohos_unittest") { + if (defined(invoker.ldflags)) { + print(invoker.ldflags) + } + executable(target_name) { + forward_variables_from(invoker, "*") + testonly = true + if (defined(invoker.ldflags)) { + print(invoker.ldflags) + } + } +} diff --git a/host/trace_streamer/doc/README.md b/host/trace_streamer/doc/README.md new file mode 100644 index 0000000000000000000000000000000000000000..eb0deec07b8f4c55fed4152454f49cad6d721cb9 --- /dev/null +++ b/host/trace_streamer/doc/README.md @@ -0,0 +1,309 @@ +# trace_streamer工具说明 +trace_streamer工具可以2种方式使用 +1. 可以将系统离线trace文件解析并转为db,此工具支持基于文本的trace和基于proto的trace。 +2. trace_streamer工具还可以WebAssembly的方式在浏览器中运行,需暴露相关接口给js文件。 + +## 关于trace解析工具的使用说明: +### 导出db模式 +在导出db模式下,trace_streamer.exe trace文件路径名 -e 导出db路径名.db +此命令可以将trace文件转为db +本应用支持在ohos, linux, windows, mac使用。 +关于db文件的说明: +使用db查看工具查看stat表,可以浏览当前数据一共有多少类数据,各类数据都收到多少条,数据是否正常等情况。在meta表会记录数据库导出时的一些系统信息,比如导入和导出的文件全路径,解析时间等信息。 +meta表可以选择不导出(有些情况下会暴露系统敏感信息),在导出时添加 -nm选项即可。 +在数据导出之后,会在本地目录下生成一个trace_streamer.log文件,在导出db的目录下生成一个数据库文件同名,.db.ohos.ts后缀的文件 +文件内容如下: +时间戳:执行结果(数字) +应用运行时间 + +执行结果解释如下:0 代表执行成功 1 表示输入文件不匹配, 2 表示解析错误, 3其他错误 +### 内置浏览器方式 +trace_streamer可以WebAssembly方式在浏览器中运行,暴露如下接口给js +``` +extern "C" { +/* 上传trace数据 + * + * @data: 数据的缓冲区 + * @dataLen: 数据长度 + * + * return: 0:成功; -1:失败 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerParseData(const uint8_t* data, int dataLen); + +/* 通知TS上传trace数据结束 + * + * return: 0:成功; -1:失败 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerParseDataOver(); + +/* 通过sql语句操作数据库 + * + * @sql: sql语句 + * @sqlLen: sql语句长度 + * + * return: 0:成功; -1:失败 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlOperate(const uint8_t* sql, int sqlLen); + +/* 通过sql语句查询数据库 + * + * @sql: sql语句 + * @sqlLen: sql语句长度 + * @out: 查询结果的缓冲区,查询结果为json + * @outLen: 缓冲区长度 + * + * return: >0:查询成功,返回查询结果数据长度; -1:失败 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlQuery(const uint8_t* sql, int sqlLen, uint8_t* out, int outLen); + +} // extern "C" +``` + +### 你也可以执行如下命令查看应用帮助 +./trace_streamer --help +-i 选项可查看应用支持的事件源和具体的事件名列表 + +#### trace_streamer支持的事件解析 +本工具支持基于文本的trace(# TRACE)和基于proto的二进制日志文件的解析,支持的事件列表如下: +##### ftrace事件 +``` +binder_transaction +binder_transaction_received +binder_transaction_alloc_buf +binder_transaction_lock +binder_transaction_locked +binder_transaction_unlock +sched_switch +task_rename +task_newtask +tracing_mark_write +print +sched_wakeup +sched_waking +cpu_idle +cpu_frequency +suspend_resume +workqueue_execute_start +workqueue_execute_end +clock_set_rate +clock_enable +clock_disable +clk_set_rate +clk_enable +clk_disable +sys_enter +sys_exit +regulator_set_voltage +regulator_set_voltage_complete +regulator_disable +regulator_disable_complete +ipi_entry +ipi_exit +irq_handler_entry +irq_handler_exit +softirq_raise +softirq_entry +softirq_exit +sched_wakeup_new +sched_process_exit +trace_event_clock_sync +``` +##### 内存事件 +``` +mem.vm.size +mem.rss +mem.rss.anon +mem.rss.file +mem.rss.schem +mem.swap +mem.locked +mem.hwm +mem.oom_score_adj +``` +##### 系统内存事件 +``` +sys.mem.unspecified +sys.mem.total +sys.mem.free +sys.mem.avaiable +sys.mem.buffers +sys.mem.cached +sys.mem.swap.chard +sys.mem.active +sys.mem.inactive +sys.mem.active.anon +sys.mem.inactive.anon +sys.mem.active_file +sys.mem.inactive_file +sys.mem.unevictable +sys.mem.mlocked +sys.mem.swap.total +sys.mem.swap.free +sys.mem.dirty +sys.mem.writeback +sys.mem.anon.pages +sys.mem.mapped +sys.mem.shmem +sys.mem.slab +sys.mem.slab.reclaimable +sys.mem.slab.unreclaimable +sys.mem.kernel.stack +sys.mem.page.tables +sys.mem.commit.limit +sys.mem.commited.as +sys.mem.vmalloc.total +sys.mem.vmalloc.used +sys.mem.vmalloc.chunk +sys.mem.cma.total +sys.mem.cma.free +``` +##### 系统虚拟内存事件 +``` +sys.virtual.mem.unspecified +sys.virtual.mem.nr.free.pages +sys.virtual.mem.nr.alloc.batch +sys.virtual.mem.nr.inactive.anon +sys.virtual.mem.nr.active_anon +sys.virtual.mem.nr.inactive.file +sys.virtual.mem.nr.active_file +sys.virtual.mem.nr.unevictable +sys.virtual.mem.nr.mlock +sys.virtual.mem.anon.pages +sys.virtual.mem.nr.mapped +sys.virtual.mem.nr.file.pages +sys.virtual.mem.nr.dirty +sys.virtual.mem.nr.writeback +sys.virtual.mem.nr.slab.reclaimable +sys.virtual.mem.nr.slab.unreclaimable +sys.virtual.mem.nr.page_table.pages +sys.virtual.mem.nr_kernel.stack +sys.virtual.mem.nr.overhead +sys.virtual.mem.nr.unstable +sys.virtual.mem.nr.bounce +sys.virtual.mem.nr.vmscan.write +sys.virtual.mem.nr.vmscan.immediate.reclaim +sys.virtual.mem.nr.writeback_temp +sys.virtual.mem.nr.isolated_anon +sys.virtual.mem.nr.isolated_file +sys.virtual.mem.nr.shmem +sys.virtual.mem.nr.dirtied +sys.virtual.mem.nr.written +sys.virtual.mem.nr.pages.scanned +sys.virtual.mem.workingset.refault +sys.virtual.mem.workingset.activate +sys.virtual.mem.workingset_nodereclaim +sys.virtual.mem.nr_anon.transparent.hugepages +sys.virtual.mem.nr.free_cma +sys.virtual.mem.nr.swapcache +sys.virtual.mem.nr.dirty.threshold +sys.virtual.mem.nr.dirty.background.threshold +sys.virtual.mem.vmeminfo.pgpgin +sys.virtual.mem.pgpgout +sys.virtual.mem.pgpgoutclean +sys.virtual.mem.pswpin +sys.virtual.mem.pswpout +sys.virtual.mem.pgalloc.dma +sys.virtual.mem.pgalloc.normal +sys.virtual.mem.pgalloc.movable +sys.virtual.mem.pgfree +sys.virtual.mem.pgactivate +sys.virtual.mem.pgdeactivate +sys.virtual.mem.pgfault +sys.virtual.mem.pgmajfault +sys.virtual.mem.pgrefill.dma +sys.virtual.mem.pgrefill.normal +sys.virtual.mem.pgrefill.movable +sys.virtual.mem.pgsteal.kswapd.dma +sys.virtual.mem.pgsteal.kswapd.normal +sys.virtual.mem.pgsteal.kswapd.movable +sys.virtual.mem.pgsteal.direct.dma +sys.virtual.mem.pgsteal.direct.normal +sys.virtual.mem.pgsteal_direct.movable +sys.virtual.mem.pgscan.kswapd.dma +sys.virtual.mem.pgscan_kswapd.normal +sys.virtual.mem.pgscan.kswapd.movable +sys.virtual.mem.pgscan.direct.dma +sys.virtual.mem.pgscan.direct.normal +sys.virtual.mem.pgscan.direct.movable +sys.virtual.mem.pgscan.direct.throttle +sys.virtual.mem.pginodesteal +sys.virtual.mem.slabs_scanned +sys.virtual.mem.kswapd.inodesteal +sys.virtual.mem.kswapd.low.wmark.hit.quickly +sys.virtual.mem.high.wmark.hit.quickly +sys.virtual.mem.pageoutrun +sys.virtual.mem.allocstall +sys.virtual.mem.pgrotated +sys.virtual.mem.drop.pagecache +sys.virtual.mem.drop.slab +sys.virtual.mem.pgmigrate.success +sys.virtual.mem.pgmigrate.fail +sys.virtual.mem.compact.migrate.scanned +sys.virtual.mem.compact.free.scanned +sys.virtual.mem.compact.isolated +sys.virtual.mem.compact.stall +sys.virtual.mem.compact.fail +sys.virtual.mem.compact.success +sys.virtual.mem.compact.daemon.wake +sys.virtual.mem.unevictable.pgs.culled +sys.virtual.mem.unevictable.pgs.scanned +sys.virtual.mem.unevictable.pgs.rescued +sys.virtual.mem.unevictable.pgs.mlocked +sys.virtual.mem.unevictable.pgs.munlocked +sys.virtual.mem.unevictable.pgs.cleared +sys.virtual.mem.unevictable.pgs.stranded +sys.virtual.mem.nr.zspages +sys.virtual.mem.nr.ion.heap +sys.virtual.mem.nr.gpu.heap +sys.virtual.mem.allocstall.dma +sys.virtual.mem.allocstall.movable +sys.virtual.mem.allocstall.normal +sys.virtual.mem.compact_daemon.free.scanned +sys.virtual.mem.compact.daemon.migrate.scanned +sys.virtual.mem.nr.fastrpc +sys.virtual.mem.nr.indirectly.reclaimable +sys.virtual.mem.nr_ion_heap_pool +sys.virtual.mem.nr.kernel_misc.reclaimable +sys.virtual.mem.nr.shadow_call.stack_bytes +sys.virtual.mem.nr.shmem.hugepages +sys.virtual.mem.nr.shmem.pmdmapped +sys.virtual.mem.nr.unreclaimable.pages +sys.virtual.mem.nr.zone.active.anon +sys.virtual.mem.nr.zone.active.file +ys.virtual.mem.nr.zone.inactive_anon +sys.virtual.mem.nr.zone.inactive_file +sys.virtual.mem.nr.zone.unevictable +sys.virtual.mem.nr.zone.write_pending +sys.virtual.mem.oom.kill +sys.virtual.mem.pglazyfree +sys.virtual.mem.pglazyfreed +sys.virtual.mem.pgrefill +sys.virtual.mem.pgscan.direct +sys.virtual.mem.pgscan.kswapd +sys.virtual.mem.pgskip.dma +sys.virtual.mem.pgskip.movable +sys.virtual.mem.pgskip.normal +sys.virtual.mem.pgsteal.direct +sys.virtual.mem.pgsteal.kswapd +sys.virtual.mem.swap.ra +sys.virtual.mem.swap.ra.hit +``` + +## trace_streamer开发环境搭建和编译运行指引 + +本应用使用gn作为构建工具,支持在linux环境同时编译linux,windows和mac使用QtCreator作为开发IDE +### 1、开发环境 +ubuntu使用vscode,windows和mac使用QtCreator +# 对外部的依赖 +本应用依赖与sqlite,protobuf(htrace解析部分依赖) + +本应用同时依赖于src/protos目录下文件来生成相关pb.h,pb.cc文件 + +### 2.1、 编译linux版应用 +在根目录下执行相关命令进行编译 + +### 2.2、编译Windows版和Mac应用 +在项目目录下有pro文件,为QtCreator的工程文件,但部分内容赖在于上面所添加的外部依赖,如果要编译相关平台应用,开发者需自行补充相关工程文件,或者在论坛留言 + +### 2.3、开始编译 +具体方法可参考《compile_trace_streamer.md》 \ No newline at end of file diff --git a/host/trace_streamer/doc/des_compile_trace_streamer.md b/host/trace_streamer/doc/des_compile_trace_streamer.md new file mode 100644 index 0000000000000000000000000000000000000000..dd1f00ff4a9805c45a94254c90ca3e4069accf21 --- /dev/null +++ b/host/trace_streamer/doc/des_compile_trace_streamer.md @@ -0,0 +1,133 @@ +# 如何独立编译Trace_streamer +尽管本工具(trace_streamer)是在ohos工具箱中的一员,但你依然可以独立编译此工具。 + +本工具可以编译linux, mac, windows, WebAssembly版本。 + +本工具默认编译方式是使用gn ++ 编译方式 +``` +./build.sh linux/wasm +``` +如果需要编译WebAssembly版本,您需要在prebuilts/目录下安装emsdk +``` +git clone https://github.com/juj/emsdk.git --depth=1 +cd emsdk +git pull +./emsdk update # this may not work, ignore it +./emsdk install latest +./emsdk activate latest +安装之后,您需要将upstream目录复制到prebuilts/emsdk/emsdk,node复制到prebuilts/emsdk/node +``` +安装之后,目录结构当如: +``` +prebuilts/emsdk +├── prebuilts/emsdk/emsdk +│ ├── prebuilts/emsdk/emsdk/bin +│ ├── prebuilts/emsdk/emsdk/emscripten +│ │ ├── prebuilts/emsdk/emsdk/emscripten/cache +│ │ ├── prebuilts/emsdk/emsdk/emscripten/cmake +│ │ ├── prebuilts/emsdk/emsdk/emscripten/docs +│ │ ├── prebuilts/emsdk/emsdk/emscripten/media +│ │ ├── prebuilts/emsdk/emsdk/emscripten/node_modules +│ │ ├── prebuilts/emsdk/emsdk/emscripten/__pycache__ +│ │ ├── prebuilts/emsdk/emsdk/emscripten/src +│ │ ├── prebuilts/emsdk/emsdk/emscripten/system +│ │ ├── prebuilts/emsdk/emsdk/emscripten/tests +│ │ ├── prebuilts/emsdk/emsdk/emscripten/third_party +│ │ └── prebuilts/emsdk/emsdk/emscripten/tools +│ ├── prebuilts/emsdk/emsdk/include +│ │ └── prebuilts/emsdk/emsdk/include/c++ +│ └── prebuilts/emsdk/emsdk/lib +│ └── prebuilts/emsdk/emsdk/lib/clang +└── prebuilts/emsdk/node + └── prebuilts/emsdk/node/14.18.2_64bit + ├── prebuilts/emsdk/node/14.18.2_64bit/bin + ├── prebuilts/emsdk/node/14.18.2_64bit/include + ├── prebuilts/emsdk/node/14.18.2_64bit/lib + └── prebuilts/emsdk/node/14.18.2_64bit/share +``` +之后调用 +``` +./build.sh wasm进行编译,您需要将sh脚本进行部分修改,因为这个脚本内置了一些库的下载和解析方式 +``` +本工具还支持使用QtCreator来编译。 + +src/trace_streamer.pro 是工程文件,编译本工具需要依赖Sqlite库和一些基于proto的pb.h文件 +## 2 准备工程 +### 2.1 基于proto文件生成pb文件 +您需要自行下载并编译一个当前系统(linux)可用的proobuf/protoc程序,此全路径为位于out/linux/protoc +src/protos目录下有一个protogen.sh文件,运行该文件可以在third_party/protogen目录下生成项目需要的pb相关文件 +序列化二进制的解析依赖于基于proto生成的.pb.cc文件。 +在执行protogen.sh脚本之后 +你的目录结构当类似如下结构: +``` +third_party/protogen/types/plugins/ftrace_data/*.pb.cc +third_party/sqlite/*. +third_party/protobuf/* +``` +### 2.2 获取第三方依赖库 +从 +https://gitee.com/openharmony/third_party_sqlite +获取sqlite3目录到代码根目录的third_party目录 +从 +https://gitee.com/openharmony/third_party_protobuf +获取protobuf目录到代码根目录的third_party目录 +之后,你的目录当如下所示 +trace_streamer/third_party/protobuf +trace_streamer/third_party/sqlite +# 3 (linux和ohos平台)使用gn编译TraceStreamer +在编译WebAssembly目标时,需要将sqlite3和protobuf里面相关的ohos_xxx_library统一修改为source_set +## 3.2 准备gn +在自己的项目中使用gn,必须遵循以下要求: +在根目录创建.gn文件,该文件用于指定CONFIG.gn文件的位置; +在BUILDCONFIG.gn中指定编译时使用的编译工具链; +在独立的gn文件中定义编译使用的工具链; +在项目根目录下创建BUILD.gn文件,指定编译的目标。 +``` +cp prebuilts/gn ./ +``` +不同的操作系统下,你需要获取不同的gn +## 3.3 执行编译 +./build.sh linux debug +或./build.sh linux debug +./build.sh将直接编译linux的release版本 +build.sh wasm 命令将可以编译WebAssembly版本 +特别说明:编译WebAssembly版本需要emSDK支持,你需要将build.sh里面的相关路径做更改,以保证编译时必须的文件是存在的 +# 4 编译Windows版本或Mac版本 +## 4.1 编译依赖文件 +### 4.1.1 编译SqliteLib +使用QtCreator打开prebuiltsprebuilts/buildprotobuf/sqlite.pro +### 4.1.2 编译ProtobufLib +使用QtCreator打开prebuilts/buildprotobuf/protobuf.pro +编译之后,文件结构当如下所示: +``` +lib +├── linux +│ ├── libdl.so +│ └── libsqlite.a +├── linux_debug +│ ├── libprotobuf.a +│ └── libsqlite.a +├── macx +│ ├── libprotobuf.a +│ └── libsqlite.a +├── macx_debug +│ ├── libprotobuf.a +│ └── libsqlite.a +├── windows +│ ├── libprotobuf.a +│ └── libsqlite.a +└── windows_debug + ├── libprotobuf.a + └── libsqlite.a +``` +## 4.2 编译TraceStreamer +之后,使用QtCreator打开src/trace_streamer.pro,选择合适的构建工具,执行 Ctrl + b 即可编译 + +编译之后的可执行文件位于out目录 +``` +- out +---- linux (Linux平台下QtCreator或gn生成) +---- macx (mac平台下QtCreator或gn生成) +---- windows (windows平台下QtCreator或gn生成) +``` \ No newline at end of file diff --git a/host/trace_streamer/doc/des_stat.md b/host/trace_streamer/doc/des_stat.md new file mode 100644 index 0000000000000000000000000000000000000000..e1048f51e1dbb4e9fbe08a809856d2bba903a5d2 --- /dev/null +++ b/host/trace_streamer/doc/des_stat.md @@ -0,0 +1,413 @@ +# TraceStreamer 解析数据状态表 +TraceStreamer使用stat表统计解析trace数据源过程遇到的重要事件状态。通过stat表可以对trace数据源中各个类型事件的数据有一个基本了解。 +## stat表支持统计的事件列表如下: +|event_name | +| ---- | +|binder_transaction | +|binder_transaction_alloc_buf | +|binder_transaction_lock | +|binder_transaction_locked | +|binder_transaction_received | +|binder_transaction_unlock | +|clk_disable | +|clk_enable | +|clk_set_rate | +|clock_disable | +|clock_enable | +|clock_set_rate | +|cpu_frequency | +|cpu_idle | +|hidump_fps | +|hilog | +|ipi_entry | +|ipi_exit | +|irq_handler_entry | +|irq_handler_exit | +|memory | +|native_hook_free | +|native_hook_malloc | +|oom_score_adj_update | +|other | +|print | +|regulator_disable | +|regulator_disable_complete | +|regulator_set_voltage | +|regulator_set_voltage_complete | +|sched_process_exit | +|sched_process_free | +|sched_switch | +|sched_wakeup | +|sched_wakeup_new | +|sched_waking | +|signal_deliver | +|signal_generate | +|softirq_entry | +|softirq_exit | +|softirq_raise | +|suspend_resume | +|sys_enter | +|sys_exit | +|sys_memory | +|sys_virtual_memory | +|task_newtask | +|task_rename | +|trace_bblock_bio_queue | +|trace_block_bio_backmerge | +|trace_block_bio_bounce | +|trace_block_bio_complete | +|trace_block_bio_frontmerge | +|trace_block_bio_remap | +|trace_block_dirty_buffer | +|trace_block_getrq | +|trace_block_plug | +|trace_block_rq_complete | +|trace_block_rq_insert | +|trace_block_rq_issue | +|trace_block_rq_remap | +|trace_event_clock_sync | +|tracing_mark_write | +|workqueue_execute_end | +|workqueue_execute_start | + +## 事件对应解析状态: +每种事件解析数据都有5种状态,描述如下表: +|stat_type|description| +|---- |---- | +|received | 统计trace数据源中总共有多少该事件。| +|data_lost | 统计TraceStreamer解析过程中发现丢失数据条数。 | +|not_match | 统计有多少数据与上下文其他数据不匹配。 | +|not_supported | 统计有多少暂不支持解析该事件(一个事件可能包含多种类型的子事件, TraceStreamer可能支持该事件的一部分子事件)。| +|invalid_data | 统计收到多少条该事件的非法数据。| + +## 数据状态级别 +数据状态级别总共有4种,分别是:info, warn, error,fatal。由于数据的重要性不同,不同事件的同一种状态可能对应不同的级别。 +例如binder_transaction_received的 not_supported状态的数据为info级别,而binder_transaction_alloc_buf的not_supported状态数据为warn级别。 + +## 事件,状态与级别对应关系 +| event_name | stat_type | serverity | +|---- |---- |---- | +| binder_transaction | received | info | +| binder_transaction | data_lost | error | +| binder_transaction | not_match | info | +| binder_transaction | not_supported | info | +| binder_transaction | invalid_data | error | +| binder_transaction_received | received | info | +| binder_transaction_received | data_lost | error | +| binder_transaction_received | not_match | info | +| binder_transaction_received | not_supported | info | +| binder_transaction_received | invalid_data | error | +| binder_transaction_alloc_buf | received | info | +| binder_transaction_alloc_buf | data_lost | error | +| binder_transaction_alloc_buf | not_match | info | +| binder_transaction_alloc_buf | not_supported | warn | +| binder_transaction_alloc_buf | invalid_data | error | +| binder_transaction_lock | received | info | +| binder_transaction_lock | data_lost | error | +| binder_transaction_lock | not_match | info | +| binder_transaction_lock | not_supported | warn | +| binder_transaction_lock | invalid_data | error | +| binder_transaction_locked | received | info | +| binder_transaction_locked | data_lost | error | +| binder_transaction_locked | not_match | info | +| binder_transaction_locked | not_supported | warn | +| binder_transaction_locked | invalid_data | error | +| binder_transaction_unlock | received | info | +| binder_transaction_unlock | data_lost | error | +| binder_transaction_unlock | not_match | info | +| binder_transaction_unlock | not_supported | warn | +| binder_transaction_unlock | invalid_data | error | +| sched_switch | received | info | +| sched_switch | data_lost | error | +| sched_switch | not_match | info | +| sched_switch | not_supported | info | +| sched_switch | invalid_data | error | +| task_rename | received | info | +| task_rename | data_lost | error | +| task_rename | not_match | info | +| task_rename | not_supported | info | +| task_rename | invalid_data | error | +| task_newtask | received | info | +| task_newtask | data_lost | error | +| task_newtask | not_match | info | +| task_newtask | not_supported | info | +| task_newtask | invalid_data | error | +| tracing_mark_write | received | info | +| tracing_mark_write | data_lost | error | +| tracing_mark_write | not_match | info | +| tracing_mark_write | not_supported | info | +| tracing_mark_write | invalid_data | error | +| print | received | info | +| print | data_lost | error | +| print | not_match | info | +| print | not_supported | info | +| print | invalid_data | error | +| sched_wakeup | received | info | +| sched_wakeup | data_lost | error | +| sched_wakeup | not_match | info | +| sched_wakeup | not_supported | info | +| sched_wakeup | invalid_data | error | +| sched_waking | received | info | +| sched_waking | data_lost | error | +| sched_waking | not_match | info | +| sched_waking | not_supported | info | +| sched_waking | invalid_data | error | +| cpu_idle | received | info | +| cpu_idle | data_lost | error | +| cpu_idle | not_match | info | +| cpu_idle | not_supported | info | +| cpu_idle | invalid_data | error | +| cpu_frequency | received | info | +| cpu_frequency | data_lost | error | +| cpu_frequency | not_match | info | +| cpu_frequency | not_supported | info | +| cpu_frequency | invalid_data | error | +| suspend_resume | received | info | +| suspend_resume | data_lost | error | +| suspend_resume | not_match | info | +| suspend_resume | not_supported | info | +| suspend_resume | invalid_data | error | +| workqueue_execute_start | received | info | +| workqueue_execute_start | data_lost | error | +| workqueue_execute_start | not_match | info | +| workqueue_execute_start | not_supported | info | +| workqueue_execute_start | invalid_data | error | +| workqueue_execute_end | received | info | +| workqueue_execute_end | data_lost | error | +| workqueue_execute_end | not_match | info | +| workqueue_execute_end | not_supported | warn | +| workqueue_execute_end | invalid_data | error | +| clock_set_rate | received | info | +| clock_set_rate | data_lost | error | +| clock_set_rate | not_match | info | +| clock_set_rate | not_supported | warn | +| clock_set_rate | invalid_data | error | +| clock_enable | received | info | +| clock_enable | data_lost | error | +| clock_enable | not_match | info | +| clock_enable | not_supported | warn | +| clock_enable | invalid_data | error | +| clock_disable | received | info | +| clock_disable | data_lost | error | +| clock_disable | not_match | info | +| clock_disable | not_supported | warn | +| clock_disable | invalid_data | error | +| clk_set_rate | received | info | +| clk_set_rate | data_lost | error | +| clk_set_rate | not_match | info | +| clk_set_rate | not_supported | warn | +| clk_set_rate | invalid_data | error | +| clk_enable | received | info | +| clk_enable | data_lost | error | +| clk_enable | not_match | info | +| clk_enable | not_supported | warn | +| clk_enable | invalid_data | error | +| clk_disable | received | info | +| clk_disable | data_lost | error | +| clk_disable | not_match | info | +| clk_disable | not_supported | warn | +| clk_disable | invalid_data | error | +| sys_enter | received | info | +| sys_enter | data_lost | error | +| sys_enter | not_match | info | +| sys_enter | not_supported | warn | +| sys_enter | invalid_data | error | +| sys_exit | received | info | +| sys_exit | data_lost | error | +| sys_exit | not_match | info | +| sys_exit | not_supported | warn | +| sys_exit | invalid_data | error | +| regulator_set_voltage | received | info | +| regulator_set_voltage | data_lost | error | +| regulator_set_voltage | not_match | info | +| regulator_set_voltage | not_supported | warn | +| regulator_set_voltage | invalid_data | error | +| regulator_set_voltage_complete | received | info | +| regulator_set_voltage_complete | data_lost | error | +| regulator_set_voltage_complete | not_match | info | +| regulator_set_voltage_complete | not_supported | warn | +| regulator_set_voltage_complete | invalid_data | error | +| regulator_disable | received | info | +| regulator_disable | data_lost | error | +| regulator_disable | not_match | info | +| regulator_disable | not_supported | warn | +| regulator_disable | invalid_data | error | +| regulator_disable_complete | received | info | +| regulator_disable_complete | data_lost | error | +| regulator_disable_complete | not_match | info | +| regulator_disable_complete | not_supported | warn | +| regulator_disable_complete | invalid_data | error | +| ipi_entry | received | info | +| ipi_entry | data_lost | error | +| ipi_entry | not_match | info | +| ipi_entry | not_supported | warn | +| ipi_entry | invalid_data | error | +| ipi_exit | received | info | +| ipi_exit | data_lost | error | +| ipi_exit | not_match | info | +| ipi_exit | not_supported | warn | +| ipi_exit | invalid_data | error | +| irq_handler_entry | received | info | +| irq_handler_entry | data_lost | error | +| irq_handler_entry | not_match | info | +| irq_handler_entry | not_supported | warn | +| irq_handler_entry | invalid_data | error | +| irq_handler_exit | received | info | +| irq_handler_exit | data_lost | error | +| irq_handler_exit | not_match | info | +| irq_handler_exit | not_supported | warn | +| irq_handler_exit | invalid_data | error | +| softirq_raise | received | info | +| softirq_raise | data_lost | error | +| softirq_raise | not_match | info | +| softirq_raise | not_supported | warn | +| softirq_raise | invalid_data | error | +| softirq_entry | received | info | +| softirq_entry | data_lost | error | +| softirq_entry | not_match | info | +| softirq_entry | not_supported | warn | +| softirq_entry | invalid_data | error | +| softirq_exit | received | info | +| softirq_exit | data_lost | error | +| softirq_exit | not_match | info | +| softirq_exit | not_supported | warn | +| softirq_exit | invalid_data | error | +| oom_score_adj_update | received | info | +| oom_score_adj_update | data_lost | error | +| oom_score_adj_update | not_match | info | +| oom_score_adj_update | not_supported | warn | +| oom_score_adj_update | invalid_data | error | +| sched_wakeup_new | received | info | +| sched_wakeup_new | data_lost | error | +| sched_wakeup_new | not_match | info | +| sched_wakeup_new | not_supported | warn | +| sched_wakeup_new | invalid_data | error | +| sched_process_exit | received | info | +| sched_process_exit | data_lost | error | +| sched_process_exit | not_match | info | +| sched_process_exit | not_supported | warn | +| sched_process_exit | invalid_data | error | +| sched_process_free | received | info | +| sched_process_free | data_lost | error | +| sched_process_free | not_match | info | +| sched_process_free | not_supported | warn | +| sched_process_free | invalid_data | error | +| trace_event_clock_sync | received | info | +| trace_event_clock_sync | data_lost | error | +| trace_event_clock_sync | not_match | info | +| trace_event_clock_sync | not_supported | warn | +| trace_event_clock_sync | invalid_data | error | +| memory | received | info | +| memory | data_lost | error | +| memory | not_match | info | +| memory | not_supported | warn | +| memory | invalid_data | error | +| hilog | received | info | +| hilog | data_lost | error | +| hilog | not_match | info | +| hilog | not_supported | warn | +| hilog | invalid_data | error | +| hidump_fps | received | info | +| hidump_fps | data_lost | error | +| hidump_fps | not_match | info | +| hidump_fps | not_supported | warn | +| hidump_fps | invalid_data | error | +| native_hook_malloc | received | info | +| native_hook_malloc | data_lost | error | +| native_hook_malloc | not_match | info | +| native_hook_malloc | not_supported | warn | +| native_hook_malloc | invalid_data | error | +| native_hook_free | received | info | +| native_hook_free | data_lost | error | +| native_hook_free | not_match | info | +| native_hook_free | not_supported | warn | +| native_hook_free | invalid_data | error | +| sys_memory | received | info | +| sys_memory | data_lost | error | +| sys_memory | not_match | info | +| sys_memory | not_supported | warn | +| sys_memory | invalid_data | error | +| sys_virtual_memory | received | info | +| sys_virtual_memory | data_lost | error | +| sys_virtual_memory | not_match | info | +| sys_virtual_memory | not_supported | warn | +| sys_virtual_memory | invalid_data | error | +| signal_generate | received | info | +| signal_generate | data_lost | error | +| signal_generate | not_match | info | +| signal_generate | not_supported | warn | +| signal_generate | invalid_data | error | +| signal_deliver | received | info | +| signal_deliver | data_lost | error | +| signal_deliver | not_match | info | +| signal_deliver | not_supported | warn | +| signal_deliver | invalid_data | error | +| trace_block_bio_backmerge | received | info | +| trace_block_bio_backmerge | data_lost | error | +| trace_block_bio_backmerge | not_match | info | +| trace_block_bio_backmerge | not_supported | warn | +| trace_block_bio_backmerge | invalid_data | error | +| trace_block_bio_bounce | received | info | +| trace_block_bio_bounce | data_lost | error | +| trace_block_bio_bounce | not_match | info | +| trace_block_bio_bounce | not_supported | warn | +| trace_block_bio_bounce | invalid_data | error | +| trace_block_bio_complete | received | info | +| trace_block_bio_complete | data_lost | error | +| trace_block_bio_complete | not_match | info | +| trace_block_bio_complete | not_supported | warn | +| trace_block_bio_complete | invalid_data | error | +| trace_block_bio_frontmerge | received | info | +| trace_block_bio_frontmerge | data_lost | error | +| trace_block_bio_frontmerge | not_match | info | +| trace_block_bio_frontmerge | not_supported | warn | +| trace_block_bio_frontmerge | invalid_data | error | +| trace_bblock_bio_queue | received | info | +| trace_bblock_bio_queue | data_lost | error | +| trace_bblock_bio_queue | not_match | info | +| trace_bblock_bio_queue | not_supported | warn | +| trace_bblock_bio_queue | invalid_data | error | +| trace_block_bio_remap | received | info | +| trace_block_bio_remap | data_lost | error | +| trace_block_bio_remap | not_match | info | +| trace_block_bio_remap | not_supported | warn | +| trace_block_bio_remap | invalid_data | error | +| trace_block_dirty_buffer | received | info | +| trace_block_dirty_buffer | data_lost | error | +| trace_block_dirty_buffer | not_match | info | +| trace_block_dirty_buffer | not_supported | warn | +| trace_block_dirty_buffer | invalid_data | error | +| trace_block_getrq | received | info | +| trace_block_getrq | data_lost | error | +| trace_block_getrq | not_match | info | +| trace_block_getrq | not_supported | warn | +| trace_block_getrq | invalid_data | error | +| trace_block_plug | received | info | +| trace_block_plug | data_lost | error | +| trace_block_plug | not_match | info | +| trace_block_plug | not_supported | warn | +| trace_block_plug | invalid_data | error | +| trace_block_rq_complete | received | info | +| trace_block_rq_complete | data_lost | error | +| trace_block_rq_complete | not_match | info | +| trace_block_rq_complete | not_supported | warn | +| trace_block_rq_complete | invalid_data | error | +| trace_block_rq_insert | received | info | +| trace_block_rq_insert | data_lost | error | +| trace_block_rq_insert | not_match | info | +| trace_block_rq_insert | not_supported | warn | +| trace_block_rq_insert | invalid_data | error | +| trace_block_rq_remap | received | info | +| trace_block_rq_remap | data_lost | error | +| trace_block_rq_remap | not_match | info | +| trace_block_rq_remap | not_supported | warn | +| trace_block_rq_remap | invalid_data | error | +| trace_block_rq_issue | received | info | +| trace_block_rq_issue | data_lost | error | +| trace_block_rq_issue | not_match | info | +| trace_block_rq_issue | not_supported | warn | +| trace_block_rq_issue | invalid_data | error | +| other | received | info | +| other | data_lost | error | +| other | not_match | info | +| other | not_supported | warn | +| other | invalid_data | error | diff --git a/host/trace_streamer/doc/des_support_eventlist.md b/host/trace_streamer/doc/des_support_eventlist.md new file mode 100644 index 0000000000000000000000000000000000000000..bde55dce0c0d849fdf69f5ed882f6d12c9037228 --- /dev/null +++ b/host/trace_streamer/doc/des_support_eventlist.md @@ -0,0 +1,224 @@ +# TraceStreamer支持解析事件列表 +## ftrace事件 +``` +binder_transaction +binder_transaction_received +binder_transaction_alloc_buf +binder_transaction_lock +binder_transaction_locked +binder_transaction_unlock +sched_switch +task_rename +task_newtask +tracing_mark_write +print +sched_wakeup +sched_waking +cpu_idle +cpu_frequency +suspend_resume +workqueue_execute_start +workqueue_execute_end +clock_set_rate +clock_enable +clock_disable +clk_set_rate +clk_enable +clk_disable +sys_enter +sys_exit +regulator_set_voltage +regulator_set_voltage_complete +regulator_disable +regulator_disable_complete +ipi_entry +ipi_exit +irq_handler_entry +irq_handler_exit +softirq_raise +softirq_entry +softirq_exit +sched_wakeup_new +sched_process_exit +trace_event_clock_sync +``` +## 内存事件 +``` +mem.vm.size +mem.rss +mem.rss.anon +mem.rss.file +mem.rss.schem +mem.swap +mem.locked +mem.hwm +mem.oom_score_adj +``` +## 系统内存事件 +``` +sys.mem.unspecified +sys.mem.total +sys.mem.free +sys.mem.avaiable +sys.mem.buffers +sys.mem.cached +sys.mem.swap.chard +sys.mem.active +sys.mem.inactive +sys.mem.active.anon +sys.mem.inactive.anon +sys.mem.active_file +sys.mem.inactive_file +sys.mem.unevictable +sys.mem.mlocked +sys.mem.swap.total +sys.mem.swap.free +sys.mem.dirty +sys.mem.writeback +sys.mem.anon.pages +sys.mem.mapped +sys.mem.shmem +sys.mem.slab +sys.mem.slab.reclaimable +sys.mem.slab.unreclaimable +sys.mem.kernel.stack +sys.mem.page.tables +sys.mem.commit.limit +sys.mem.commited.as +sys.mem.vmalloc.total +sys.mem.vmalloc.used +sys.mem.vmalloc.chunk +sys.mem.cma.total +sys.mem.cma.free +``` +## 系统虚拟内存事件 +``` +sys.virtual.mem.unspecified +sys.virtual.mem.nr.free.pages +sys.virtual.mem.nr.alloc.batch +sys.virtual.mem.nr.inactive.anon +sys.virtual.mem.nr.active_anon +sys.virtual.mem.nr.inactive.file +sys.virtual.mem.nr.active_file +sys.virtual.mem.nr.unevictable +sys.virtual.mem.nr.mlock +sys.virtual.mem.anon.pages +sys.virtual.mem.nr.mapped +sys.virtual.mem.nr.file.pages +sys.virtual.mem.nr.dirty +sys.virtual.mem.nr.writeback +sys.virtual.mem.nr.slab.reclaimable +sys.virtual.mem.nr.slab.unreclaimable +sys.virtual.mem.nr.page_table.pages +sys.virtual.mem.nr_kernel.stack +sys.virtual.mem.nr.overhead +sys.virtual.mem.nr.unstable +sys.virtual.mem.nr.bounce +sys.virtual.mem.nr.vmscan.write +sys.virtual.mem.nr.vmscan.immediate.reclaim +sys.virtual.mem.nr.writeback_temp +sys.virtual.mem.nr.isolated_anon +sys.virtual.mem.nr.isolated_file +sys.virtual.mem.nr.shmem +sys.virtual.mem.nr.dirtied +sys.virtual.mem.nr.written +sys.virtual.mem.nr.pages.scanned +sys.virtual.mem.workingset.refault +sys.virtual.mem.workingset.activate +sys.virtual.mem.workingset_nodereclaim +sys.virtual.mem.nr_anon.transparent.hugepages +sys.virtual.mem.nr.free_cma +sys.virtual.mem.nr.swapcache +sys.virtual.mem.nr.dirty.threshold +sys.virtual.mem.nr.dirty.background.threshold +sys.virtual.mem.vmeminfo.pgpgin +sys.virtual.mem.pgpgout +sys.virtual.mem.pgpgoutclean +sys.virtual.mem.pswpin +sys.virtual.mem.pswpout +sys.virtual.mem.pgalloc.dma +sys.virtual.mem.pgalloc.normal +sys.virtual.mem.pgalloc.movable +sys.virtual.mem.pgfree +sys.virtual.mem.pgactivate +sys.virtual.mem.pgdeactivate +sys.virtual.mem.pgfault +sys.virtual.mem.pgmajfault +sys.virtual.mem.pgrefill.dma +sys.virtual.mem.pgrefill.normal +sys.virtual.mem.pgrefill.movable +sys.virtual.mem.pgsteal.kswapd.dma +sys.virtual.mem.pgsteal.kswapd.normal +sys.virtual.mem.pgsteal.kswapd.movable +sys.virtual.mem.pgsteal.direct.dma +sys.virtual.mem.pgsteal.direct.normal +sys.virtual.mem.pgsteal_direct.movable +sys.virtual.mem.pgscan.kswapd.dma +sys.virtual.mem.pgscan_kswapd.normal +sys.virtual.mem.pgscan.kswapd.movable +sys.virtual.mem.pgscan.direct.dma +sys.virtual.mem.pgscan.direct.normal +sys.virtual.mem.pgscan.direct.movable +sys.virtual.mem.pgscan.direct.throttle +sys.virtual.mem.pginodesteal +sys.virtual.mem.slabs_scanned +sys.virtual.mem.kswapd.inodesteal +sys.virtual.mem.kswapd.low.wmark.hit.quickly +sys.virtual.mem.high.wmark.hit.quickly +sys.virtual.mem.pageoutrun +sys.virtual.mem.allocstall +sys.virtual.mem.pgrotated +sys.virtual.mem.drop.pagecache +sys.virtual.mem.drop.slab +sys.virtual.mem.pgmigrate.success +sys.virtual.mem.pgmigrate.fail +sys.virtual.mem.compact.migrate.scanned +sys.virtual.mem.compact.free.scanned +sys.virtual.mem.compact.isolated +sys.virtual.mem.compact.stall +sys.virtual.mem.compact.fail +sys.virtual.mem.compact.success +sys.virtual.mem.compact.daemon.wake +sys.virtual.mem.unevictable.pgs.culled +sys.virtual.mem.unevictable.pgs.scanned +sys.virtual.mem.unevictable.pgs.rescued +sys.virtual.mem.unevictable.pgs.mlocked +sys.virtual.mem.unevictable.pgs.munlocked +sys.virtual.mem.unevictable.pgs.cleared +sys.virtual.mem.unevictable.pgs.stranded +sys.virtual.mem.nr.zspages +sys.virtual.mem.nr.ion.heap +sys.virtual.mem.nr.gpu.heap +sys.virtual.mem.allocstall.dma +sys.virtual.mem.allocstall.movable +sys.virtual.mem.allocstall.normal +sys.virtual.mem.compact_daemon.free.scanned +sys.virtual.mem.compact.daemon.migrate.scanned +sys.virtual.mem.nr.fastrpc +sys.virtual.mem.nr.indirectly.reclaimable +sys.virtual.mem.nr_ion_heap_pool +sys.virtual.mem.nr.kernel_misc.reclaimable +sys.virtual.mem.nr.shadow_call.stack_bytes +sys.virtual.mem.nr.shmem.hugepages +sys.virtual.mem.nr.shmem.pmdmapped +sys.virtual.mem.nr.unreclaimable.pages +sys.virtual.mem.nr.zone.active.anon +sys.virtual.mem.nr.zone.active.file +ys.virtual.mem.nr.zone.inactive_anon +sys.virtual.mem.nr.zone.inactive_file +sys.virtual.mem.nr.zone.unevictable +sys.virtual.mem.nr.zone.write_pending +sys.virtual.mem.oom.kill +sys.virtual.mem.pglazyfree +sys.virtual.mem.pglazyfreed +sys.virtual.mem.pgrefill +sys.virtual.mem.pgscan.direct +sys.virtual.mem.pgscan.kswapd +sys.virtual.mem.pgskip.dma +sys.virtual.mem.pgskip.movable +sys.virtual.mem.pgskip.normal +sys.virtual.mem.pgsteal.direct +sys.virtual.mem.pgsteal.kswapd +sys.virtual.mem.swap.ra +sys.virtual.mem.swap.ra.hit +``` \ No newline at end of file diff --git a/host/trace_streamer/doc/des_tables.md b/host/trace_streamer/doc/des_tables.md new file mode 100644 index 0000000000000000000000000000000000000000..efe0a6f7b4ab4352fc1a9cce82963d86293d8a4e --- /dev/null +++ b/host/trace_streamer/doc/des_tables.md @@ -0,0 +1,306 @@ +# ___概述TraceStreamer生成的数据库___ +``` + TraceStreamer虽然对外提供了各种各样的使用方式,但核心的业务仍是将trace数据源转化为易于理解和使用的数据库。用户可以通过SmartPerf界面直观的研究系统跟踪数据,也可在理解TraceStreamer生成的数据库的基础上,在TraceStreamer的交互模式或者Smartperf的数据库查询模式下,使用SQL查询语句自由组装查看用户关心的数据。 下文将对TraceStreamer生成的数据库进行详细描述,给用户使用SQL查询系统跟踪数据提供帮助。 +``` + +## ___TraceStreamer输出数据库包含以下表格___ +* trace_range : 记录ftrace数据与其他类型数据的时间交集,供前端展示数据时使用。 +* process : 记录进程信息。 +* thread : 记录线程信息。 +* thread_state : 记录线程状态信息。 +* instant : 记录Sched_waking, sched_wakeup事件, 用作ThreadState表的上下文使用。 +* raw : 此数据结构主要作为ThreadState的上下文使用,这张表是sched_waking,sched_wakup, cpu_idle事件的原始记录。 +* callstack : 记录调用堆栈和异步调用,其中depth,stack_id和parent_stack_id仅在非异步调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,否则为线程唯一号。 +* irq : 记录中断相关事件。 +* measure : 记录所有的计量值。 +* log : 记录hilog打印日志数据。 +* heap : 记录堆内存申请与释放相关的数据。 +* heap_frame : 记录堆内存申请与释放相关的调用栈。 +* hidump : 记录FPS(Frame Per Second)数据。 +* symbols : 记录系统调用名称和其函数指针的对应关系,trace中用addr来映射function_name来节省存储空间 +* syscall : 记录用户空间函数与内核空间函数相互调用记录 +* args : 记录方法参数集合 +* sys_event_filter : 记录所有的filter +* clk_event_filter : 记录时钟事件 +* cpu_measure_filter : cpu事件过滤器表。 +* measure_filter : 记录一个递增的filterid队列,所有其他的filter类型在获取过程中,均从此数据列表中获取下一个可用的filter_id并做记录。 +* process_measure_filter : 将进程ID作为key1,进程的内存,界面刷新,屏幕亮度等信息作为key2,唯一确定一个filter_id +* data_type : 记录数据类型和typeId的关联关系。 +* data_dict : 记录常用的字符串,将字符串和索引关联,降低程序运行的内存占用,用作辅助数据。 +* meta : 记录执行解析操作相关的基本信息。 + +## ___表格关系图___ + +### 进程表与线程表关系图: +![GitHub Logo](../figures/process_thread.png) +### 描述: +当一个进程或者线程结束后,系统可能再次将该进程号或者线程号分配给其他进程或者线程,造成一个进程号或线程号代表多个进程或线程的情况。 +Process和Thread表中的id字段可以唯一标识进程和线程。process表中的id在其他表中用作ipid字段。thread表中的id在其他表中用作itid字段。 +thread表通过ipid字段关联process表的id字段,可以查询线程归属进程。 +### 举例: +已知pid = 123,查看当前进程下的所有线程信息,可以使用如下SQL语句: +select thread.* from thread, process where process.pid = 123 and thread.ipid = process.id + +### 线程表与线程运行状态表关系图 +![GitHub Logo](../figures/thread_state.png) +### 描述: +thread_state表记录所有线程的运行状态信息,包含ts(状态起始时间),dur(状态持续时间),cpu, itid, state(线程状态)。 thread表的id字段与thread_state表的itid字段相关联。 +### 举例: +已知tid = 123, 查看当前线程的所有运行状态信息,可以使用如下SQL语句: +select thread_state.* from thread, thread_state where thread.tid = 123 and thread.id = thread_state.itid + +### 堆内存数据变化表关系图 +![GitHub Logo](../figures/dump_and_mem.png) +### 描述: +heap表记录堆内存申请(AllocEvent)和释放(FreeEvent)数据。heap表通过ipid和itid字段分别与process和thread表的id字段关联,通过eventId与heap_frame表的eventId字段相关联。 +heap表字段解释如下: + eventId: 唯一标识一次堆内存申请或释放, 通过与heap_frame表关联可以拿到当前申请或释放的函数调用堆栈。 + addr: 堆内存申请/释放的地址 + heap_size: 堆内存申请/释放的大小 +heap_frame表记录内存申请/释放的调用堆栈。通过eventId区分一组调用堆栈,depth为堆栈深度,depth为0时,表示当前行为栈顶数据。 +### 举例: +已知tid = 123, 查看当前线程的所有堆内存变化信息,可以使用如下SQL语句: +select heap.* from thread, heap where thread.tid = 123 and thread.id = heap.itid +已知eventid = 0, 查看当前内存变化调用堆栈 +select * from heap_frame where eventId = 0 + +### 日志表与进程线程表关系图 +![GitHub Logo](../figures/log.png) +### 描述: +log表记录日志信息。可以根据seq字段的连续性,来判断是否存在日志丢失的情况。 +### 举例: +已知tid = 123, 查看当前线程的所有error级别的日志,可以使用如下SQL语句: +select * from log where tid = 123 and level = "error" + + +## TraceStreamer输出数据库表格详细介绍 +### trace_range表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|start_ts |NUM | +|end_ts |INT | +#### 关键字段描述: +start_ts: trace的开始时间,纳秒为单位 +end_ts: trace的结束时间,纳秒为单位 +### process表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |NUM | +|type |INT | +|pid |NUM | +|name |INT | +|start_ts |NUM | +#### 关键字段描述: +id: 进程在数据库重新重新定义的id,从0开始序列增长 +pid: 进程的真实id +name: 进程名字 +### thread表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |NUM | +|tid |INT | +|name |NUM | +|start_ts |INT | +|end_ts |INT | +|ipid |INT | +|is_main_thread|INT | +#### 字段详细描述: +id: 线程在数据库重新重新定义的id,从0开始序列增长 +ipid: 线程所属的进程id, 关联进程表中的ID +name: 线程名字 +is_main_thread: 是否主线程,主线程即该线程实际就是进程本身 + +### thread_state表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |NUM | +|ts |INT | +|dur |INT | +|cpu |INT | +|itid |INT | +|state |NUM | +#### 字段详细描述: +id: 线程状态在数据库中的id,从0开始序列增长 +ts: 该线程状态的起始时间 +dur: 该线程状态的持续时间 +cpu: 该线程在哪个cpu上执行(针对running状态的线程) +itid: 该状态所属的线程所属的进程id, 关联进程表中的ID +state: 线程实际的的状态值 +``` +'R', Runnable状态 +'S', interruptible sleep +'D', uninterruptible sleep +'T', Stoped +'t', Traced +'X', ExitedDead +'Z', ExitZombie +'x', TaskDead +'I', TaskDead +'K', WakeKill +'P', Parked +'N', NoLoad +``` +### instant表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|ts |INT | +|name |NUM | +|ref |INT | +|ref_type |NUM | +#### 表描述: +记录了系统中的waking和wakeup事件。 +### raw表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |NUM | +|ts |INT | +|name |NUM | +|cpu |INT | +|itid |INT | +#### 表描述: +记录了系统中的waking、wakup、cpu_idel、cpu_frequency数据。 + +### callstack表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|ts |INT | +|dur |INT | +|callid |INT | +|cat |NUM | +|name |NUM | +|depth |INT | +|cookie |INT | +|parent_id |INT | +|argsetid |INT | +|chainId |NUM | +|spanId |NUM | +|parentSpanId |NUM | +|flag |NUM | +|args |NUM | +#### 字段详细描述: +dur: 调用时长 +callid: 调用者的ID,比如针对线程表里面的id +name: 调用名称 +depth: 调用深度 +parent_id: 父调用的id + +### measure表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|type |NUM | +|ts |INT | +|value |INT | +|filter_id |INT | +#### 字段详细描述: + +### heap表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|eventId |INT | +|ipid |INT | +|itid |INT | +|event_type |NUM | +|start_ts |INT | +|end_ts |INT | +|dur |INT | +|addr |INT | +|heap_size |INT | +|all_heap_size |INT | +#### 字段详细描述: + +### heap_frame表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|eventId |INT | +|depth |INT | +|ip |INT | +|sp |INT | +|symbol_name |NUM | +|file_path |NUM | +|offset |INT | +|symbol_offset |INT | +#### 表描述: +记录了内存的申请和释放的堆栈。 +### hidump表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|ts |INT | +|fps |INT | +#### 表描述: +此表记录了设备的帧率信息,fps。 +### symbols表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|funcname |NUM | +|addr |INT | +#### 表描述: +此表记录了数值和函数调用名称的映射关系。 + +### measure_filter表 +记录一个递增的filterid队列,所有其他的filter类型在获取过程中,均从此数据列表中获取下一个可用的filter_id并做记录。 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |NUM | +|type |NUM | +|name |INT | +|source_arg_set_id |INT | + +#### 字段详细描述: +过滤分类(type),过滤名称(key2),数据ID(key1)。 +数据ID在process_measure_filter, sys_event_filter中作为id。 +### process_measure_filter表 +将进程ID作为key1,进程的内存,界面刷新,屏幕亮度等信息作为key2,唯一确定一个filter_id, filter_id同时被记录在measure_filter表中。 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |NUM | +|name |NUM | +|ipid |INT | +#### 字段详细描述: +filterid: 来自measure_filter表 +name: cpu状态名 +ipid: 进程内部编号 +### data_type表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|typeId |INT | +|desc |NUM | +#### 表描述: +此表记录了一个数据类型ID和数据描述的映射。 +### data_dict表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|data |NUM | +#### 表描述: +此表记录了一个数据类型ID和字符串的映射。 +### meta表 +#### 表结构: +| Columns Name | SQL TYPE | +|---- |---- | +|name |NUM | +|value |NUM | +#### 表描述: +此表记录了数据解析或导出时的一些现场数据,比如使用的trace_streamer版本, 工具的发布时间,数据解析的时间,数据的持续时长,以及原始数据的格式。 diff --git a/host/trace_streamer/figures/cpu_frequency.png b/host/trace_streamer/figures/cpu_frequency.png new file mode 100644 index 0000000000000000000000000000000000000000..a18715fc696b3231b94425e4acd6aaf319bf399f Binary files /dev/null and b/host/trace_streamer/figures/cpu_frequency.png differ diff --git a/host/trace_streamer/figures/dump_and_mem.png b/host/trace_streamer/figures/dump_and_mem.png new file mode 100644 index 0000000000000000000000000000000000000000..b7e3cc26ca286702c9ca9869fc203aff34a8da39 Binary files /dev/null and b/host/trace_streamer/figures/dump_and_mem.png differ diff --git a/host/trace_streamer/figures/filters.png b/host/trace_streamer/figures/filters.png new file mode 100644 index 0000000000000000000000000000000000000000..a02d9416f08382ff7a03e176e37e6479f5922c08 Binary files /dev/null and b/host/trace_streamer/figures/filters.png differ diff --git a/host/trace_streamer/figures/log.png b/host/trace_streamer/figures/log.png new file mode 100644 index 0000000000000000000000000000000000000000..dbe3780eb647493dec252d69f23e71cf66ac15a8 Binary files /dev/null and b/host/trace_streamer/figures/log.png differ diff --git a/host/trace_streamer/figures/mem_usage.png b/host/trace_streamer/figures/mem_usage.png new file mode 100644 index 0000000000000000000000000000000000000000..f4ebd6e272c424d6861e2e8150c72c1f4de9802a Binary files /dev/null and b/host/trace_streamer/figures/mem_usage.png differ diff --git a/host/trace_streamer/figures/process_thread.png b/host/trace_streamer/figures/process_thread.png new file mode 100644 index 0000000000000000000000000000000000000000..abc3867130c10413197482d0156ce0ee00aca255 Binary files /dev/null and b/host/trace_streamer/figures/process_thread.png differ diff --git a/host/trace_streamer/figures/thread_state.png b/host/trace_streamer/figures/thread_state.png new file mode 100644 index 0000000000000000000000000000000000000000..186ffb16905c7cfa0178f7c14a0189223f6c9e22 Binary files /dev/null and b/host/trace_streamer/figures/thread_state.png differ diff --git a/host/trace_streamer/figures/trace_streamer_stream.png b/host/trace_streamer/figures/trace_streamer_stream.png new file mode 100644 index 0000000000000000000000000000000000000000..d36687d164a32bcb07f8f8bd699f0fb0b37e63bd Binary files /dev/null and b/host/trace_streamer/figures/trace_streamer_stream.png differ diff --git a/host/trace_streamer/gn/.emscripten b/host/trace_streamer/gn/.emscripten new file mode 100644 index 0000000000000000000000000000000000000000..0ed7e1dd1a0e50b80ac895e5911c4b1adc2b8da6 --- /dev/null +++ b/host/trace_streamer/gn/.emscripten @@ -0,0 +1,32 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from platform import system +import os +import sys + +thisFile = os.getenv('EM_CONFIG') +if thisFile is None: + sys.stderr.write('No EM_CONFIG in .emscripten file\n') + sys.exit(-1) + +rootDir = os.path.dirname(os.path.dirname(thisFile)) +emsdkPath = os.path.join(rootDir, 'prebuilts/emsdk/emsdk') +nodePath = os.path.join(rootDir, 'prebuilts/emsdk/node/14.18.2_64bit') + +LLVM_ROOT = os.path.join(emsdkPath, 'bin') +NODE_JS = os.path.join(nodePath, 'bin/node') +EMSCRIPTEN_ROOT = os.path.join(emsdkPath, 'emscripten') +COMPILER_ENGINE = NODE_JS +JS_ENGINES = [NODE_JS] +BINARYEN_ROOT = emsdkPath diff --git a/host/trace_streamer/gn/BUILD.gn b/host/trace_streamer/gn/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..a44389bdd809eccfeeb146bb62d42242f4a1c6ae --- /dev/null +++ b/host/trace_streamer/gn/BUILD.gn @@ -0,0 +1,126 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +print("target_os", target_os) +group("default_deps") { + public_configs = [ ":default_config" ] + public_deps = [] +} +config("default_config") { + include_dirs = [ + "..", + "../include", + ] +} +config("trace_cfg") { + cflags_cc = [ + "-std=c++17", + "-fno-rtti", + "-fno-exceptions", + "-fvisibility=hidden", + ] +} + +config("visibility_hidden") { + cflags = [ "-fvisibility=hidden" ] +} + +config("default") { + cflags_c = [] + cflags_cc = [] + libs = [] + + cflags = [ + "-fstrict-aliasing", + "-fPIC", + "-g", + "-Wformat", + ] + + if (is_linux) { + cflags += [ + "-Wa,--noexecstack", + "-fcolor-diagnostics", + "-fdiagnostics-show-template-tree", + "-ftrapv", + ] + if (!use_wasm) { + cflags += [ + "-fPIE", + "-fstack-protector-strong", + "-fstack-protector-all", + "-D_FORTIFY_SOURCE=2 -O2", + ] + } + libs += [ + "pthread", + "rt", + ] + if (is_debug) { + libs += [ "dl" ] + } + } +} + +config("symbols") { + cflags = [ "-O0" ] + if (is_linux) { + cflags += [ "-funwind-tables" ] + } +} + +config("release") { + cflags = [ + "-fdata-sections", + "-ffunction-sections", + ] + + cflags += [ "-O3" ] + ldflags = [ + "-fuse-ld=gold", + "-fstack-protector", + "-Wl,--gc-sections", + "-Wl,-O1", + "-fpie", + "-pie", + ] + defines = [ "NDEBUG" ] +} + +config("shared_library") { + ldflags = [ "-fPIC" ] +} + +config("executable") { + print("use_wasm", use_wasm) + ldflags = [] + + if (is_linux && !use_wasm) { + ldflags += [ + # "-Wl,-rpath=\$ORIGIN/.", + "-Wl,-z,now", + + # "-Wl,-rpath-link=.", + "-Wl,-z,relro", + "-lrt", + "-fpie", + "-pie", + "-Wl,-z,noexecstack", + "-Wl,--disable-new-dtags", + + # "-s", # delete sambols + ] + } + if (!is_debug) { + ldflags += [ "-s" ] + } +} diff --git a/host/trace_streamer/gn/CONFIG.gn b/host/trace_streamer/gn/CONFIG.gn new file mode 100644 index 0000000000000000000000000000000000000000..babf9755e98d0478a5f2d895668a9d296c026c0d --- /dev/null +++ b/host/trace_streamer/gn/CONFIG.gn @@ -0,0 +1,72 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +is_win = false +is_linux = false +declare_args() { + ar = "ar" + is_debug = true + use_wasm = false + is_test = false +} +if (target_os == "linux") { + is_win = false + is_linux = true + is_test = false +} else if (target_os == "windows") { + is_win = true + is_linux = false + is_test = false +} else if (target_os == "wasm") { + is_win = false + is_linux = true + use_wasm = true + is_test = false +} else if (target_os == "test") { + is_win = false + is_linux = true + use_wasm = false + is_test = true +} else { + print("unknown platform " + target_os) + exit(-1) +} + +print("platform " + target_os) +default_configs = [ + "//gn:symbols", + "//gn:default", + "//gn:trace_cfg", +] + +set_defaults("static_library") { + configs = default_configs +} +if (!is_debug) { + default_configs -= [ "//gn:symbols" ] + default_configs += [ "//gn:release" ] +} + +set_defaults("ohos_source_set") { + configs = default_configs +} + +set_defaults("executable") { + configs = default_configs + configs += [ "//gn:executable" ] +} +if (use_wasm) { + set_default_toolchain("//gn/toolchain:wasm") +} else { + print(use_wasm) + set_default_toolchain("//gn/toolchain:gcc_like") +} diff --git a/host/trace_streamer/gn/toolchain/BUILD.gn b/host/trace_streamer/gn/toolchain/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..e1b24fd43144cd73b0ff6dfff19499fef1b9f63c --- /dev/null +++ b/host/trace_streamer/gn/toolchain/BUILD.gn @@ -0,0 +1,178 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//gn/wasm.gni") +declare_args() { + if (target_os == "linux" || target_os == "wasm" || target_os == "test") { + cc = "/usr/bin/clang" + cxx = "/usr/bin/clang++" + } else if (target_os == "windows") { + cc = "~/mingw-w64/ohos/linux-x86_64/clang-mingw/bin/clang" + cxx = "~/mingw-w64/ohos/linux-x86_64/clang-mingw/bin/clang++" + } + if (use_wasm == true) { + print("make_wasm") + } else if (use_wasm == false) { + print("no make_wasm") + } + cc_wrapper = "" + is_mac = false +} +toolchain("wasm") { + # emsdk_dir and em_config are defined in wasm.gni. + print("use gcc_like_chain wasm") + ar = "$emsdk_dir/emscripten/emar --em-config $em_config" + cc = "$emsdk_dir/emscripten/emcc --em-config $em_config" + cxx = "$emsdk_dir/emscripten/em++ --em-config $em_config" + + lib_switch = "-l" + ld_arg = "" + lib_dir_switch = "-L" + external_cxxflags = "" + external_cflags = "" + external_ldflags = "" + if (defined(linker) && linker != "") { + ld_arg = "-fuse-ld=$_invoker_linker" + _invoker_linker = linker + } + if (defined(sysroot) && sysroot != "") { + _invoker_sysroot = sysroot + cxx = "$cxx --sysroot=$_invoker_sysroot" + cc = "$cc --sysroot=$_invoker_sysroot" + } + if (defined(gcc_toolchain) && gcc_toolchain != "") { + ld_arg = "$ld_arg --gcc-toolchain=$gcc_toolchain" + } + if (defined(external_cxxflags)) { + print("defined external_cxxflags") + external_cxxflags = external_cxxflags + } + if (defined(external_cflags)) { + external_cflags = external_cflags + } + + tool("cc") { + depfiles = "{{output}}.d" + command = "$cc_wrapper $cc -MMD -MF $depfiles {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} ${external_cflags} -c {{source}} -o {{output}}" + outputfiles = + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" + outputs = [ outputfiles ] + description = "step: compile {{source}}" + } + + tool("cxx") { + depfiles = "{{output}}.d" # must be defined + command = "$cc_wrapper $cxx -MMD -MF $depfiles {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} ${external_cflags} ${external_cxxflags} -c {{source}} -o {{output}}" + + outputfiles = + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" + outputs = [ outputfiles ] + description = "step: compile {{source}}" + } + tool("alink") { + rspfile = "{{output}}.rsp" # must be defined + rspfile_content = "{{inputs}}" + command = "rm -rf {{output}} && $ar rcsD {{output}} @$rspfile" + outputfiles = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" + outputs = [ outputfiles ] + output_prefix = "lib" + default_output_extension = ".a" + description = "step: link {{output}}" + } + tool("solink") { + sonames = "{{target_output_name}}{{output_extension}}" + outputfiles = "{{root_out_dir}}/$sonames" + unstripped_so = outputfiles + rpath = "" + outputs = [ outputfiles ] + command = "$cc_wrapper $cxx $ld_arg -shared {{ldflags}} ${external_ldflags} {{inputs}} {{solibs}} {{libs}} $rpath -o {{output}}" + output_prefix = "lib" + description = "step: link $unstripped_so" + default_output_extension = ".so" + } + + tool("link") { + outputfiles = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" + outputs = [ outputfiles ] + command = "$cc_wrapper $cxx $ld_arg {{ldflags}} ${external_ldflags} {{inputs}} {{solibs}} {{libs}} -o {{output}}" + description = "step:link {{output}}" + } + + tool("stamp") { + description = "step: stamp {{output}}" + command = "touch {{output}}" + } + + tool("copy") { + description = "step: COPY files from {{source}} to {{output}}" + command = "cp -arf {{source}} {{output}}" + } +} +toolchain("gcc_like") { + lib_switch = "-l" + lib_dir_switch = "-L" + + tool("cxx") { + depfile = "{{output}}.d" # must be defined + command = "$cxx -o {{output}} -MMD -MF $depfile {{defines}} -fPIC {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}}" + outputfiles = + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" + outputs = [ outputfiles ] + description = "step: compile {{source}}" + } + + tool("cc") { + depfile = "{{output}}.d" + command = "$cc -o {{output}} -MMD -MF $depfile {{defines}} -fPIC {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}}" + outputfiles = + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" + outputs = [ outputfiles ] + description = "step: compile {{source}}" + } + tool("alink") { + rspfile = "{{output}}.rsp" # this must be defined + rspfile_content = "{{inputs}}" # this must be defined + command = "rm -f {{output}} && $ar rcsD {{output}} @$rspfile" + outputsfiles = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" + outputs = [ outputsfiles ] + default_output_extension = ".a" + output_prefix = "lib" + description = "step: link {{output}}" + } + + tool("link") { + command = "$cxx -o {{output}} {{ldflags}} {{inputs}} {{solibs}} {{libs}}" + outputsfiles = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" + outputs = [ outputsfiles ] + description = "step: link {{output}}" + } + tool("solink") { + default_output_extension = ".so" + command = + "$cxx -o {{output}} {{ldflags}} {{inputs}} {{solibs}} {{libs}} -shared" + outputsfiles = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" + outputs = [ outputsfiles ] + description = "step: solink {{output}}" + } + + tool("stamp") { + print("need do nothing") + description = "step: touch {{output}}" + command = "touch {{output}}" + } + + tool("copy") { + description = "COPY files from {{source}} to {{output}}" + command = "cp -arf {{source}} {{output}}" + } +} diff --git a/host/trace_streamer/gn/wasm.gni b/host/trace_streamer/gn/wasm.gni new file mode 100644 index 0000000000000000000000000000000000000000..7209ff6666891129c98ee7cce901d63564e7bd88 --- /dev/null +++ b/host/trace_streamer/gn/wasm.gni @@ -0,0 +1,78 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("./wasm_vars.gni") + +em_config = rebase_path(".emscripten", "") +emsdk_dir = rebase_path("//prebuilts/emsdk/emsdk", "") + +template("wasm_lib") { + _exports = "['ccall', 'callMain', 'addFunction', 'FS']" + print(invoker.name) + assert(defined(invoker.name)) + + # If the name is trace_sreamer the target_name must be trace_sreamer_wasm. + assert(invoker.name + "_wasm" == target_name) + _target_ldflags = [ + "-s", + "DISABLE_EXCEPTION_CATCHING=1", + "-s", + "WASM=1", + "-s", + "NO_DYNAMIC_EXECUTION=1", + "-s", + "ALLOW_MEMORY_GROWTH=1", + "-s", + "INITIAL_MEMORY=33554432", + "-s", + "ALLOW_TABLE_GROWTH=1", + "-s", + "MEMFS_APPEND_TO_TYPED_ARRAYS=1", + "-s", + "WASM_ASYNC_COMPILATION=0", + "-s", + "EXPORTED_RUNTIME_METHODS=" + _exports, + "-s", + "EXPORT_NAME=${target_name}", + "-s", + "MODULARIZE=1", + ] + _lib_name = invoker.name + if (is_debug) { + _target_ldflags += [ + "-s", + "ASSERTIONS=2", + "-s", + "STACK_OVERFLOW_CHECK=1", + "-s", + "SAFE_HEAP=1", + "-g4", + "-O0", + ] + } else { + _target_ldflags += [ + "-g2", # Required for getting C++ symbol names. + "-O3", + "-s", + "ASSERTIONS=1", + ] + } + + _vars_to_forward = [ "deps" ] + + executable("${_lib_name}.js") { + ldflags = _target_ldflags + output_extension = "" + forward_variables_from(invoker, _vars_to_forward) + } +} diff --git a/host/trace_streamer/gn/wasm_vars.gni b/host/trace_streamer/gn/wasm_vars.gni new file mode 100644 index 0000000000000000000000000000000000000000..8b858fda7329eb8466b6975a0fefa7945532a5e4 --- /dev/null +++ b/host/trace_streamer/gn/wasm_vars.gni @@ -0,0 +1,15 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +wasm_toolchain = "//gn/toolchain:wasm" +is_wasm = current_toolchain == wasm_toolchain diff --git a/host/trace_streamer/prebuilts/buildprotobuf/libprotobuf_lite_la_SOURCES.pri b/host/trace_streamer/prebuilts/buildprotobuf/libprotobuf_lite_la_SOURCES.pri new file mode 100644 index 0000000000000000000000000000000000000000..39c051faf41b82d7cf1e62dda7c147eeb95d9494 --- /dev/null +++ b/host/trace_streamer/prebuilts/buildprotobuf/libprotobuf_lite_la_SOURCES.pri @@ -0,0 +1,64 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + message("qmake" $${PROTOBUDIR}"/src") +win32 { +SOURCES += $${PROTOBUDIR}/src/google/protobuf/io/io_win32.cc +} +SOURCES += \ + $${PROTOBUDIR}/src/google/protobuf/stubs/bytestream.cc \ + $${PROTOBUDIR}/src/google/protobuf/stubs/common.cc \ + $${PROTOBUDIR}/src/google/protobuf/stubs/int128.cc \ +# $${PROTOBUDIR}/src/google/protobuf/stubs/once.cc \ + $${PROTOBUDIR}/src/google/protobuf/stubs/int128.h \ +# $${PROTOBUDIR}/src/google/protobuf/io/io_win32.cc \ + $${PROTOBUDIR}/src/google/protobuf/stubs/status.cc \ + $${PROTOBUDIR}/src/google/protobuf/stubs/statusor.cc \ + $${PROTOBUDIR}/src/google/protobuf/stubs/statusor.h \ + $${PROTOBUDIR}/src/google/protobuf/stubs/stringpiece.cc \ + $${PROTOBUDIR}/src/google/protobuf/stubs/stringprintf.cc \ + $${PROTOBUDIR}/src/google/protobuf/stubs/structurally_valid.cc \ + $${PROTOBUDIR}/src/google/protobuf/stubs/strutil.cc \ + $${PROTOBUDIR}/src/google/protobuf/stubs/time.cc \ +# $${PROTOBUDIR}/src/google/protobuf/any_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/arena.cc \ +# $${PROTOBUDIR}/src/google/protobuf/arenastring.cc \ + $${PROTOBUDIR}/src/google/protobuf/extension_set.cc \ + $${PROTOBUDIR}/src/google/protobuf/generated_enum_util.cc \ + $${PROTOBUDIR}/src/google/protobuf/generated_message_util.cc \ +# $${PROTOBUDIR}/src/google/protobuf/generated_message_table_driven_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/implicit_weak_message.cc \ + $${PROTOBUDIR}/src/google/protobuf/message_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/parse_context.cc \ + $${PROTOBUDIR}/src/google/protobuf/repeated_field.cc \ +# $${PROTOBUDIR}/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc \ +# $${PROTOBUDIR}/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc \ + $${PROTOBUDIR}/src/google/protobuf/wire_format_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/io/coded_stream.cc \ + $${PROTOBUDIR}/src/google/protobuf/io/strtod.cc \ + $${PROTOBUDIR}/src/google/protobuf/io/zero_copy_stream.cc \ + $${PROTOBUDIR}/src/google/protobuf/io/zero_copy_stream_impl.cc \ + $${PROTOBUDIR}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc + +HEADERS += \ + $${PROTOBUDIR}/src/google/protobuf/stubs/bytestream.h \ + $${PROTOBUDIR}/src/google/protobuf/stubs/hash.h \ + $${PROTOBUDIR}/src/google/protobuf/io/coded_stream_inl.h \ +# $${PROTOBUDIR}/src/google/protobuf/generated_message_table_driven_lite.h \ + $${PROTOBUDIR}/src/google/protobuf/stubs/time.h \ + $${PROTOBUDIR}/src/google/protobuf/stubs/stringprintf.h \ + $${PROTOBUDIR}/src/google/protobuf/stubs/stringpiece.h \ + $${PROTOBUDIR}/src/google/protobuf/stubs/status.h \ + $${PROTOBUDIR}/src/google/protobuf/stubs/status_macros.h \ +# $${PROTOBUDIR}/src/google/protobuf/io/io_win32.h \ + $${PROTOBUDIR}/src/google/protobuf/stubs/map_util.h \ + $${PROTOBUDIR}/src/google/protobuf/stubs/mathutil.h diff --git a/host/trace_streamer/prebuilts/buildprotobuf/libprotoc_la_SOURCES.pri b/host/trace_streamer/prebuilts/buildprotobuf/libprotoc_la_SOURCES.pri new file mode 100644 index 0000000000000000000000000000000000000000..ed1da78266e36cf066115d956dfe442f8c2743d2 --- /dev/null +++ b/host/trace_streamer/prebuilts/buildprotobuf/libprotoc_la_SOURCES.pri @@ -0,0 +1,173 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + message("qmake" $${PROTOBUDIR}"/src/google/protobuf/compiler/") +SOURCES += \ + $${PROTOBUDIR}/src/google/protobuf/compiler/code_generator.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/command_line_interface.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/plugin.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/plugin.pb.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/subprocess.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/zip_writer.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_enum.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_enum_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_extension.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_file.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_generator.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_helpers.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_map_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_message.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_message_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_service.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_string_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_context.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum_field_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_extension.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_extension_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_file.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_generator.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_generator_factory.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_helpers.cc \ +# $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_lazy_message_field.cc \ +# $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_map_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_map_field_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_builder.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_builder_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_field_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_name_resolver.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_primitive_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_primitive_field_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_shared_code_generator.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_service.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_string_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_string_field_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_doc_comment.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/js/js_generator.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/js/well_known_types_embed.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_enum.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_extension.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_file.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_generator.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_message.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc \ +# $${PROTOBUDIR}/src/google/protobuf/compiler/php/php_generator.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/python/python_generator.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/ruby/ruby_generator.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_enum.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_enum_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_field_base.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_generator.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_helpers.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_map_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_message.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_message_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc \ + +HEADERS += \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_primitive_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_options.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_service.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_string_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum_field_lite.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_context.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum_lite.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_extension.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_map_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_map_field_lite.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_helpers.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_file.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_generator_factory.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_extension_lite.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_field_lite.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_lite.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_builder.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_builder_lite.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_name_resolver.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_options.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_primitive_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_primitive_field_lite.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_shared_code_generator.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_service.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_string_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_enum.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_string_field_lite.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/scc.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/subprocess.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/zip_writer.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_enum.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_enum_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_extension.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_file.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_helpers.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_map_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_message.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_message_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_doc_comment.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_extension.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_file.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_helpers.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_map_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_message.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_message_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_oneof.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_doc_comment.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_message_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_options.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_primitive_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_reflection_class.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_enum.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_enum_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_field_base.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_helpers.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_map_field.h \ + $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_message.h \ diff --git a/host/trace_streamer/prebuilts/buildprotobuf/protobuf.pri b/host/trace_streamer/prebuilts/buildprotobuf/protobuf.pri new file mode 100644 index 0000000000000000000000000000000000000000..1bfc0847435faaf99b4e88841f30d67c37d65530 --- /dev/null +++ b/host/trace_streamer/prebuilts/buildprotobuf/protobuf.pri @@ -0,0 +1,69 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +PROTOBUDIR = $$PWD/../../third_party/protobuf + message("qmake" $${PROTOBUDIR}"/src/google/protobuf/") +SOURCES += \ +$${PROTOBUDIR}/src/google/protobuf/any.cc \ +$${PROTOBUDIR}/src/google/protobuf/any_lite.cc \ + $${PROTOBUDIR}/src/google/protobuf/any.pb.cc \ + $${PROTOBUDIR}/src/google/protobuf/api.pb.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/importer.cc \ + $${PROTOBUDIR}/src/google/protobuf/compiler/parser.cc \ + $${PROTOBUDIR}/src/google/protobuf/descriptor.cc \ + $${PROTOBUDIR}/src/google/protobuf/descriptor.pb.cc \ + $${PROTOBUDIR}/src/google/protobuf/descriptor_database.cc \ + $${PROTOBUDIR}/src/google/protobuf/duration.pb.cc \ + $${PROTOBUDIR}/src/google/protobuf/dynamic_message.cc \ + $${PROTOBUDIR}/src/google/protobuf/empty.pb.cc \ + $${PROTOBUDIR}/src/google/protobuf/extension_set_heavy.cc \ + $${PROTOBUDIR}/src/google/protobuf/field_mask.pb.cc \ + $${PROTOBUDIR}/src/google/protobuf/generated_message_reflection.cc \ + $${PROTOBUDIR}/src/google/protobuf/generated_message_table_driven.cc \ + $${PROTOBUDIR}/src/google/protobuf/io/gzip_stream.cc \ + $${PROTOBUDIR}/src/google/protobuf/io/printer.cc \ + $${PROTOBUDIR}/src/google/protobuf/io/tokenizer.cc \ + $${PROTOBUDIR}/src/google/protobuf/map_field.cc \ + $${PROTOBUDIR}/src/google/protobuf/message.cc \ + $${PROTOBUDIR}/src/google/protobuf/reflection_ops.cc \ + $${PROTOBUDIR}/src/google/protobuf/service.cc \ + $${PROTOBUDIR}/src/google/protobuf/source_context.pb.cc \ + $${PROTOBUDIR}/src/google/protobuf/struct.pb.cc \ +# $${PROTOBUDIR}/src/google/protobuf/stubs/mathlimits.cc \ + $${PROTOBUDIR}/src/google/protobuf/stubs/substitute.cc \ + $${PROTOBUDIR}/src/google/protobuf/text_format.cc \ + $${PROTOBUDIR}/src/google/protobuf/timestamp.pb.cc \ + $${PROTOBUDIR}/src/google/protobuf/type.pb.cc \ + $${PROTOBUDIR}/src/google/protobuf/unknown_field_set.cc \ +# $${PROTOBUDIR}/src/google/protobuf/util/delimited_message_util.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/field_comparator.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/field_mask_util.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/internal/datapiece.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/internal/default_value_objectwriter.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/internal/error_listener.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/internal/field_mask_utility.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/internal/json_escaping.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/internal/json_objectwriter.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/internal/json_stream_parser.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/internal/object_writer.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/internal/proto_writer.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/internal/protostream_objectsource.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/internal/protostream_objectwriter.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/internal/type_info.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/internal/type_info_test_helper.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/internal/utility.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/json_util.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/message_differencer.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/time_util.cc \ + $${PROTOBUDIR}/src/google/protobuf/util/type_resolver_util.cc \ + $${PROTOBUDIR}/src/google/protobuf/wire_format.cc \ + $${PROTOBUDIR}/src/google/protobuf/wrappers.pb.cc diff --git a/host/trace_streamer/prebuilts/buildprotobuf/protobuf.pro b/host/trace_streamer/prebuilts/buildprotobuf/protobuf.pro new file mode 100644 index 0000000000000000000000000000000000000000..16afcce35f9128fe4cda5635837e2d5709de561a --- /dev/null +++ b/host/trace_streamer/prebuilts/buildprotobuf/protobuf.pro @@ -0,0 +1,35 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +QT -= gui core +TEMPLATE = lib +#TEMPLATE = app +CONFIG += c++14 lib +#CONFIG += c++14 +TARGET = protobuf + +DEFINES += HAVE_PTHREAD + +DEFINES += HAVE_PTHREAD +PROTOBUDIR = $$PWD/../../third_party/protobuf +ROOTSRCDIR = $$PWD/../../src/ +include($$PWD/../../src/multi_platform/global.pri) + +LIBS += -L$$DESTDIR/ -lstdc++ + +#INCLUDEPATH += $$PWD/$${PROTOBUDIR}/src +INCLUDEPATH += $$PWD/../../third_party/protobuf/src + +message("includepath is:"$$INCLUDEPATH) +include($$PWD/protobuf.pri) +include($$PWD/libprotobuf_lite_la_SOURCES.pri) +include($$PWD/libprotoc_la_SOURCES.pri) diff --git a/host/trace_streamer/prebuilts/buildsqlite/sqlite.pro b/host/trace_streamer/prebuilts/buildsqlite/sqlite.pro new file mode 100644 index 0000000000000000000000000000000000000000..50d80823e05b0cec037bc7efd38601b13f277508 --- /dev/null +++ b/host/trace_streamer/prebuilts/buildsqlite/sqlite.pro @@ -0,0 +1,31 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +QT -= gui core +TEMPLATE = lib +#TEMPLATE = app +CONFIG += c++14 lib +#CONFIG += c++14 +TARGET = sqlite + +DEFINES += HAVE_PTHREAD +LIBDIR = $$PWD/../../third_party/sqlite +ROOTSRCDIR = $$PWD/../../src/ +include($$PWD/../../src/multi_platform/global.pri) + +LIBS += -L$$DESTDIR/ -lstdc++ + +#INCLUDEPATH += $$PWD/$${PROTOBUDIR}/src +INCLUDEPATH += $$PWD/../../third_party/sqlite/include + +message("includepath is:"$$INCLUDEPATH) +SOURCES += $${LIBDIR}/src/sqlite3.c diff --git a/host/trace_streamer/prebuilts/protos/BUILD.gn b/host/trace_streamer/prebuilts/protos/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..760af44d8dc6aec956d492d366aaa61bbc1b4a66 --- /dev/null +++ b/host/trace_streamer/prebuilts/protos/BUILD.gn @@ -0,0 +1,100 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR = "//third_party/protobuf" +proto_dir = "//third_party/protogen" +services_dir = "$proto_dir/services" +ftrace_data_dir = "$proto_dir/types/plugins/ftrace_data" +memory_data_dir = "$proto_dir/types/plugins/memory_data" +hilog_data_dir = "$proto_dir/types/plugins/hilog_data" +native_hook_dir = "$proto_dir/types/plugins/native_hook" +hidump_data_dir = "$proto_dir/types/plugins/hidump_data" + +config("ts_proto_include_config") { + include_dirs = [ + "$ftrace_data_dir", + "$memory_data_dir", + "$hilog_data_dir", + "$native_hook_dir", + "$hidump_data_dir", + ] +} +source_set("ts_proto_data_cpp") { + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + cflags = [ + "-fPIC", + "-ftrapv", + "-fPIE", + "-D_FORTIFY_SOURCE=2 -O2", + "-Wno-zero-length-array", + + # "-Wl,--disable-new-dtags,--rpath,/libpath1:/libpath2" + ] + if (!use_wasm) { + cflags += [ + "-fstack-protector-strong", # + "-fstack-protector-all", + ] + } + + public_configs = [ ":ts_proto_include_config" ] + sources = [ + "$ftrace_data_dir/binder.pb.cc", + "$ftrace_data_dir/block.pb.cc", + "$ftrace_data_dir/cgroup.pb.cc", + "$ftrace_data_dir/clk.pb.cc", + "$ftrace_data_dir/compaction.pb.cc", + "$ftrace_data_dir/cpuhp.pb.cc", + "$ftrace_data_dir/dma_fence.pb.cc", + "$ftrace_data_dir/ext4.pb.cc", + "$ftrace_data_dir/filelock.pb.cc", + "$ftrace_data_dir/filemap.pb.cc", + "$ftrace_data_dir/ftrace.pb.cc", + "$ftrace_data_dir/ftrace_event.pb.cc", + "$ftrace_data_dir/gpio.pb.cc", + "$ftrace_data_dir/i2c.pb.cc", + "$ftrace_data_dir/ipi.pb.cc", + "$ftrace_data_dir/irq.pb.cc", + "$ftrace_data_dir/kmem.pb.cc", + "$ftrace_data_dir/net.pb.cc", + "$ftrace_data_dir/oom.pb.cc", + "$ftrace_data_dir/pagemap.pb.cc", + "$ftrace_data_dir/power.pb.cc", + "$ftrace_data_dir/printk.pb.cc", + "$ftrace_data_dir/raw_syscalls.pb.cc", + "$ftrace_data_dir/rcu.pb.cc", + "$ftrace_data_dir/sched.pb.cc", + "$ftrace_data_dir/signal.pb.cc", + "$ftrace_data_dir/sunrpc.pb.cc", + "$ftrace_data_dir/task.pb.cc", + "$ftrace_data_dir/timer.pb.cc", + "$ftrace_data_dir/trace_plugin_result.pb.cc", + "$ftrace_data_dir/v4l2.pb.cc", + "$ftrace_data_dir/vmscan.pb.cc", + "$ftrace_data_dir/workqueue.pb.cc", + "$ftrace_data_dir/writeback.pb.cc", + "$hidump_data_dir/hidump_plugin_config.pb.cc", + "$hidump_data_dir/hidump_plugin_result.pb.cc", + "$hilog_data_dir/hilog_plugin_result.pb.cc", + "$memory_data_dir/memory_plugin_common.pb.cc", + "$memory_data_dir/memory_plugin_config.pb.cc", + "$memory_data_dir/memory_plugin_result.pb.cc", + "$native_hook_dir/native_hook_config.pb.cc", + "$native_hook_dir/native_hook_result.pb.cc", + "${services_dir}/common_types.pb.cc", + ] +} diff --git a/host/trace_streamer/src/BUILD.gn b/host/trace_streamer/src/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3abb1454fb5c04175f128905a9c978899c3d58ef --- /dev/null +++ b/host/trace_streamer/src/BUILD.gn @@ -0,0 +1,228 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("ts.gni") +if (use_wasm) { + import("//gn/wasm.gni") +} +if (use_wasm) { + ohos_source_set("trace_streamer_builtin") { + sources = [] + include_dirs = [] + deps = [] + public_deps = [] + } +} +ohos_source_set("lib") { + sources = [ "main.cpp" ] + deps = [ ":trace_streamer_source" ] + include_dirs = [ + "base", + "..", + "trace_streamer", + "filter", + "table", + "trace_data", + "include", + "rpc", + "./", + "parser", + "cfg", + "parser/htrace_parser", + "parser/htrace_parser/htrace_event_parser", + "parser/htrace_parser/htrace_cpu_parser", + "//third_party/sqlite/include", + "${OHOS_PROTO_GEN}/types/plugins/memory_data", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data", + "${OHOS_PROTO_GEN}/types/plugins/hilog_data", + "${OHOS_PROTO_GEN}/types/plugins/native_hook", + "${OHOS_PROTO_GEN}/types/plugins/hidump_data", + "${OHOS_PROTO_GEN}", + "//third_party/protobuf/src", + ] + public_deps = [] +} +ohos_source_set("trace_streamer_source") { + sources = [ + "cfg/trace_streamer_config.cpp", + "cfg/trace_streamer_config.h", + "filter/args_filter.cpp", + "filter/args_filter.h", + "filter/binder_filter.cpp", + "filter/binder_filter.h", + "filter/clock_filter.cpp", + "filter/clock_filter.h", + "filter/cpu_filter.cpp", + "filter/filter_base.cpp", + "filter/filter_base.h", + "filter/filter_filter.cpp", + "filter/filter_filter.h", + "filter/irq_filter.cpp", + "filter/irq_filter.h", + "filter/measure_filter.cpp", + "filter/measure_filter.h", + "filter/process_filter.cpp", + "filter/process_filter.h", + "filter/slice_filter.cpp", + "filter/slice_filter.h", + "filter/stat_filter.cpp", + "filter/stat_filter.h", + "filter/symbols_filter.cpp", + "filter/symbols_filter.h", + "filter/system_event_measure_filter.cpp", + "filter/system_event_measure_filter.h", + "parser/bytrace_parser/bytrace_event_parser.cpp", + "parser/bytrace_parser/bytrace_event_parser.h", + "parser/bytrace_parser/bytrace_parser.cpp", + "parser/bytrace_parser/bytrace_parser.h", + "parser/common_types.h", + "parser/event_parser_base.cpp", + "parser/event_parser_base.h", + "parser/print_event_parser.cpp", + "parser/print_event_parser.h", + "parser/thread_state.cpp", + "parser/thread_state.h", + "rpc/http_server.cpp", + "rpc/http_socket.cpp", + "rpc/rpc_server.cpp", + "table/args_table.cpp", + "table/args_table.h", + "table/callstack_table.cpp", + "table/callstack_table.h", + "table/clk_event_filter_table.cpp", + "table/clk_event_filter_table.h", + "table/clock_event_filter_table.cpp", + "table/clock_event_filter_table.h", + "table/cpu_measure_filter_table.cpp", + "table/cpu_measure_filter_table.h", + "table/data_dict_table.cpp", + "table/data_dict_table.h", + "table/data_type_table.cpp", + "table/data_type_table.h", + "table/filter_table.cpp", + "table/filter_table.h", + "table/heap_frame_table.cpp", + "table/heap_frame_table.h", + "table/heap_table.cpp", + "table/heap_table.h", + "table/hidump_table.cpp", + "table/hidump_table.h", + "table/instants_table.cpp", + "table/instants_table.h", + "table/irq_table.cpp", + "table/log_table.cpp", + "table/log_table.h", + "table/measure_filter_table.cpp", + "table/measure_filter_table.h", + "table/measure_table.cpp", + "table/measure_table.h", + "table/meta_table.cpp", + "table/meta_table.h", + "table/process_filter_table.cpp", + "table/process_filter_table.h", + "table/process_measure_filter_table.cpp", + "table/process_measure_filter_table.h", + "table/process_table.cpp", + "table/process_table.h", + "table/range_table.cpp", + "table/raw_table.cpp", + "table/raw_table.h", + "table/sched_slice_table.cpp", + "table/sched_slice_table.h", + "table/stat_table.cpp", + "table/stat_table.h", + "table/symbols_table.cpp", + "table/symbols_table.h", + "table/system_call_table.cpp", + "table/system_call_table.h", + "table/system_event_filter_table.cpp", + "table/table_base.cpp", + "table/thread_filter_table.cpp", + "table/thread_state_table.cpp", + "table/thread_table.cpp", + "trace_data/trace_data_cache.cpp", + "trace_data/trace_data_cache.h", + "trace_data/trace_data_cache_base.cpp", + "trace_data/trace_data_cache_base.h", + "trace_data/trace_data_cache_reader.cpp", + "trace_data/trace_data_cache_reader.h", + "trace_data/trace_data_cache_writer.cpp", + "trace_data/trace_data_cache_writer.h", + "trace_data/trace_data_db.cpp", + "trace_data/trace_data_db.h", + "trace_data/trace_stdtype.cpp", + "trace_data/trace_stdtype.h", + "trace_streamer/trace_streamer_filters.cpp", + "trace_streamer/trace_streamer_filters.h", + "trace_streamer/trace_streamer_selector.cpp", + "trace_streamer/trace_streamer_selector.h", + ] + include_dirs = [ + "base", + "..", + "trace_streamer", + "filter", + "table", + "trace_data", + "include", + "rpc", + "./", + "parser", + "cfg", + "parser/htrace_parser", + "parser/htrace_parser/htrace_event_parser", + "parser/htrace_parser/htrace_cpu_parser", + "//third_party/sqlite/include", + "${OHOS_PROTO_GEN}/types/plugins/memory_data", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data", + "${OHOS_PROTO_GEN}/types/plugins/hilog_data", + "${OHOS_PROTO_GEN}/types/plugins/native_hook", + "${OHOS_PROTO_GEN}/types/plugins/hidump_data", + "${OHOS_PROTO_GEN}", + "//third_party/protobuf/src", + ] + deps = [ + "base:base", + "ext:sqliteext", + "include:ibase", + "parser/htrace_parser:htrace_parser", + "//third_party/sqlite:sqlite", + ] + + if (use_wasm) { + sources += [ "rpc/wasm_func.cpp" ] + } + if (enable_ts_utest && !use_wasm) { + cflags = [ + "-fprofile-arcs", + "-ftest-coverage", + ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + } + public_deps = [] +} +if (use_wasm) { + wasm_lib("trace_streamer_builtin_wasm") { + name = "trace_streamer_builtin" + deps = [ ":lib" ] + } +} else { + executable("trace_streamer") { + deps = [ ":lib" ] + } +} diff --git a/host/trace_streamer/src/base/BUILD.gn b/host/trace_streamer/src/base/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..110bed46b652bdc52ea836da59bd8c2dc114baf7 --- /dev/null +++ b/host/trace_streamer/src/base/BUILD.gn @@ -0,0 +1,37 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../ts.gni") +ohos_source_set("base") { + deps = [] + public_deps = [ "../include:ibase" ] + include_dirs = [ "../include" ] + sources = [ + "codec_cov.cpp", + "file.cpp", + "log.cpp", + "parting_string.cpp", + ] + if (enable_ts_utest && !use_wasm) { + cflags = [ + "-fprofile-arcs", + "-ftest-coverage", + ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + } +} diff --git a/host/trace_streamer/src/base/args_set.h b/host/trace_streamer/src/base/args_set.h new file mode 100644 index 0000000000000000000000000000000000000000..9a506be0534bbff7af525d1c498001c95ac5f640 --- /dev/null +++ b/host/trace_streamer/src/base/args_set.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_TRACE_BASE_ARGS_SET_H +#define SRC_TRACE_BASE_ARGS_SET_H + +#include +#include +#include "ts_common.h" +namespace SysTuning { +namespace TraceStreamer { +class ArgsSet { +public: + ArgsSet() {} + ~ArgsSet() {} + ArgsSet& operator=(const ArgsSet& other) + { + this->valuesMap_ = other.valuesMap_; + return *this; + } + void AppendArg(DataIndex dataIndex, BaseDataType datatype, uint64_t value) + { + ArgsData data; + data.type = datatype; + data.value = value; + valuesMap_.emplace(dataIndex, data); + } + std::map valuesMap_; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif diff --git a/host/trace_streamer/src/base/base.pri b/host/trace_streamer/src/base/base.pri new file mode 100644 index 0000000000000000000000000000000000000000..e972a9228132e178c5b570e684b8fe7860f11f54 --- /dev/null +++ b/host/trace_streamer/src/base/base.pri @@ -0,0 +1,23 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +INCLUDEPATH +=$$PWD +HEADERS += \ + $$PWD/ts_common.h \ + $$PWD/double_map.h + +SOURCES += \ + $$PWD/codec_cov.cpp \ + $$PWD/file.cpp \ + $$PWD/parting_string.cpp \ + $$PWD/log.cpp diff --git a/host/trace_streamer/src/base/codec_cov.cpp b/host/trace_streamer/src/base/codec_cov.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a1251c9010f32b91bf34b389819496dea2ad390 --- /dev/null +++ b/host/trace_streamer/src/base/codec_cov.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "codec_cov.h" + +#include +#ifdef _WIN32 +#include +#endif + +namespace SysTuning { +namespace base { +int PreNum(unsigned char byte) +{ + constexpr uint32_t BITS = 8; + unsigned char mask = 0x80; + int num = 0; + for (uint32_t i = 0; i < BITS; i++) { + if ((byte & mask) == mask) { + mask = mask >> 1; + num++; + } else { + break; + } + } + return num; +} + +bool IsUTF8(const uint8_t* data, int len) +{ + constexpr uint8_t MASK = 0x80; + constexpr uint8_t FIRST_BYTE = 0xc0; + constexpr int TARGET = 2; + int num = 0; + int i = 0; + while (i < len) { + if ((data[i] & MASK) == 0x00) { + i++; + continue; + } + if ((num = PreNum(data[i])) <= TARGET) { + return false; + } + i++; + for (int j = 0; j < num - 1; j++) { + if ((data[i] & FIRST_BYTE) != MASK) { + return false; + } + i++; + } + } + return true; +} + +bool IsGBK(const uint8_t* data, int len) +{ + constexpr int STEP = 2; + constexpr uint8_t ASCII_END = 0x7f; + constexpr uint8_t FIRST_BYTE = 0x81; + constexpr uint8_t FIRST_BYTE_END = 0xfe; + constexpr uint8_t SECOND_BYTE_ONE = 0x40; + constexpr uint8_t SECOND_BYTE_TWO_END = 0xfe; + constexpr uint8_t GBK_MASK = 0xf7; + int i = 0; + while (i < len) { + if (data[i] <= ASCII_END) { + i++; + continue; + } else { + if (data[i] >= FIRST_BYTE && data[i] <= FIRST_BYTE_END && data[i + 1] >= SECOND_BYTE_ONE && + data[i + 1] <= SECOND_BYTE_TWO_END && data[i + 1] != GBK_MASK) { + i += STEP; + continue; + } else { + return false; + } + } + } + return true; +} + +CODING GetCoding(const uint8_t* data, int len) +{ + CODING coding; + if (IsUTF8(data, len)) { + coding = UTF8; + } else if (IsGBK(data, len)) { + coding = GBK; + } else { + coding = UNKOWN; + } + return coding; +} + +#ifdef _WIN32 +std::string GbkToUtf8(const char* srcStr) +{ + int len = MultiByteToWideChar(CP_ACP, 0, srcStr, -1, NULL, 0); + std::unique_ptr wstr = std::make_unique(len + 1); + MultiByteToWideChar(CP_ACP, 0, srcStr, -1, wstr.get(), len); + len = WideCharToMultiByte(CP_UTF8, 0, wstr.get(), -1, NULL, 0, NULL, NULL); + std::unique_ptr str = std::make_unique(len + 1); + WideCharToMultiByte(CP_UTF8, 0, wstr.get(), -1, str.get(), len, NULL, NULL); + return std::string(str.get()); +} +#endif +} // namespace base +} // namespace SysTuning diff --git a/host/trace_streamer/src/base/double_map.h b/host/trace_streamer/src/base/double_map.h new file mode 100644 index 0000000000000000000000000000000000000000..921a10c484e645b1ca5c79488aeeb27268b4afca --- /dev/null +++ b/host/trace_streamer/src/base/double_map.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_TRACE_BASE_DOUBLEMAP_H +#define SRC_TRACE_BASE_DOUBLEMAP_H + +#include + +template +class DoubleMap { +public: + DoubleMap(T3 invalidValue) + { + invalidValue_ = invalidValue; + } + void SetInvalidRet(T3 invalidValue) + { + invalidValue_ = invalidValue; + } + void Insert(T1 t1, T2 t2, T3 t3) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + auto hookId = (*streamIdHookidMap).second.find(t2); + if (hookId == (*streamIdHookidMap).second.end()) { + (*streamIdHookidMap).second.insert(std::make_pair(t2, t3)); + } else { + (*streamIdHookidMap).second.at(t2) = t3; + } + } else { + std::map mm = { + {t2, t3} + }; + internalMap_.insert(std::make_pair(t1, mm)); + } + } + T3 Find(T1 t1, T2 t2) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + auto hookId = (*streamIdHookidMap).second.find(t2); + if (hookId == (*streamIdHookidMap).second.end()) { + return invalidValue_; + } else { + return hookId->second; + } + } else { + return invalidValue_; + } + } + void Erase(T1 t1) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + internalMap_.erase(streamIdHookidMap); + } + } + void Erase(T1 t1, T2 t2) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + auto hookId = (*streamIdHookidMap).second.find(t2); + if (hookId != (*streamIdHookidMap).second.end()) { + (*streamIdHookidMap).second.erase(hookId); + } + } + } + +private: + std::map> internalMap_; + T3 invalidValue_; +}; + +#endif // DOUBLEMAP_H diff --git a/host/trace_streamer/src/base/file.cpp b/host/trace_streamer/src/base/file.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d8bd187e7ce47d97caee6f59db4956cd8c9c3b3 --- /dev/null +++ b/host/trace_streamer/src/base/file.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "file.h" +#include +#include +#include +#include +#include + +#include "log.h" +#if defined(_WIN32) +#include +#include +#include +#endif + +namespace SysTuning { +namespace base { +static TraceParserStatus g_status = TRACE_PARSER_ABNORMAL; + +void SetAnalysisResult(TraceParserStatus stat) +{ + g_status = stat; +} +TraceParserStatus GetAnalysisResult() +{ + return g_status; +} + +ssize_t Read(int fd, uint8_t* dst, size_t dstSize) +{ +#if defined(_WIN32) + return _read(fd, dst, static_cast(dstSize)); +#else + ssize_t ret = -1; + do { + ret = read(fd, dst, dstSize); + } while (ret == -1 && errno == EINTR); + return ret; +#endif +} +int OpenFile(const std::string& path, int flags, uint32_t mode) +{ + TS_ASSERT((flags & O_CREAT) == 0 || mode != kFileModeInvalid); +#if defined(_WIN32) + int fd(_open(path.c_str(), flags | O_BINARY, mode)); +#else + int fd(open(path.c_str(), flags | O_CLOEXEC, mode)); +#endif + return fd; +} + +std::string GetExecutionDirectoryPath() +{ + char currPath[1024] = {0}; +#if defined(_WIN32) + ::GetModuleFileNameA(NULL, currPath, MAX_PATH); + (strrchr(currPath, '\\'))[1] = 0; +#else + readlink("/proc/self/exe", currPath, sizeof(currPath) - 1); +#endif + std::string str(currPath); + str = str.substr(0, str.find_last_of('/')); + return str; +} +} // namespace base +} // namespace SysTuning diff --git a/host/trace_streamer/src/base/log.cpp b/host/trace_streamer/src/base/log.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a751c899f3153b7fa520bd4e1e89eaec591a078 --- /dev/null +++ b/host/trace_streamer/src/base/log.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "log.h" + +// namespace SysTuning { +// namespace base { +bool g_cleanMode = false; +// } // namespace base +// } // namespace SysTuning diff --git a/host/trace_streamer/src/base/parting_string.cpp b/host/trace_streamer/src/base/parting_string.cpp new file mode 100644 index 0000000000000000000000000000000000000000..adff0f934288b77422809453d176a5906ff3cff2 --- /dev/null +++ b/host/trace_streamer/src/base/parting_string.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "parting_string.h" +namespace SysTuning { +namespace base { +PartingString::PartingString(std::string str, char delimiter) : str_(std::move(str)), delimiter_(delimiter) +{ + begin_ = str_.begin(); + end_ = str_.end(); + cur_ = nullptr; +} + +bool PartingString::Next() +{ + while (begin_ != end_) { + if (*begin_ == delimiter_) { + begin_++; + continue; + } + + cur_ = begin_.base(); + do { + if (*begin_ == delimiter_) { + *(begin_++) = '\0'; + break; + } + if (*begin_ == '\0') { + begin_ = end_; + break; + } + } while (begin_++ != end_); + + if (*cur_) { + return true; + } + + begin_++; + } + + cur_ = nullptr; + return false; +} +} // namespace base +} // namespace SysTuning diff --git a/host/trace_streamer/src/base/triple_map.h b/host/trace_streamer/src/base/triple_map.h new file mode 100644 index 0000000000000000000000000000000000000000..c856d73223a0cccd8c622c9a300368107f3c35fe --- /dev/null +++ b/host/trace_streamer/src/base/triple_map.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_TRACE_BASE_TRIPLEMAP_H +#define SRC_TRACE_BASE_TRIPLEMAP_H + +#include "double_map.h" + +template +class TripleMap { +public: + TripleMap(T4 invalidValue) + { + invalidValue_ = invalidValue; + } + void SetInvalidRet(T4 invalidValue) + { + invalidValue_ = invalidValue; + } + void Insert(T1 t1, T2 t2, T3 t3, T4 t4) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + (*streamIdHookidMap).second.Insert(t2, t3, t4); + } else { + DoubleMap mm(invalidValue_); + mm.Insert(t2, t3, t4); + internalMap_.insert(std::make_pair(t1, mm)); + } + } + T4 Find(T1 t1, T2 t2, T3 t3) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + return (*streamIdHookidMap).second.Find(t2, t3); + } else { + return invalidValue_; + } + } + void Erase(T1 t1) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + internalMap_.erase(streamIdHookidMap); + } + } + void Erase(T1 t1, T2 t2) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + (*streamIdHookidMap).second.Erase(t2); + } + } + void Erase(T1 t1, T2 t2, T3 t3) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + (*streamIdHookidMap).second.Erase(t2, t3); + } + } + +private: + std::map> internalMap_; + T4 invalidValue_; +}; + +#endif // SRC_TRACE_BASE_TRIPLEMAP_H diff --git a/host/trace_streamer/src/base/ts_common.h b/host/trace_streamer/src/base/ts_common.h new file mode 100644 index 0000000000000000000000000000000000000000..57ada7286e98a2074d96da60135f7a432e62426c --- /dev/null +++ b/host/trace_streamer/src/base/ts_common.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_TRACE_BASE_TS_COMMON_H +#define SRC_TRACE_BASE_TS_COMMON_H + +#include +#include +#include +#include + +const uint64_t INVALID_UTID = std::numeric_limits::max(); +const uint64_t INVALID_UINT64 = std::numeric_limits::max(); +const uint64_t MAX_UINT32 = std::numeric_limits::max(); +const uint64_t MAX_UINT64 = std::numeric_limits::max(); +const uint32_t INVALID_UINT32 = std::numeric_limits::max(); +const uint32_t INVALID_INT32 = std::numeric_limits::max(); +const uint64_t INVALID_DATAINDEX = std::numeric_limits::max(); +const size_t MAX_SIZE_T = std::numeric_limits::max(); +const uint32_t INVALID_ID = std::numeric_limits::max(); +const uint64_t SEC_TO_NS = 1000 * 1000 * 1000; +const int STR_DEFAULT_LEN = -1; +enum BuiltinClocks { + TS_CLOCK_UNKNOW = 0, + TS_CLOCK_BOOTTIME = 1, + TS_CLOCK_REALTIME = 2, + TS_CLOCK_REALTIME_COARSE = 3, + TS_MONOTONIC = 4, + TS_MONOTONIC_COARSE = 5, + TS_MONOTONIC_RAW = 6, +}; + +enum RefType { + K_REF_NO_REF = 0, + K_REF_ITID = 1, + K_REF_CPUID = 2, + K_REF_IRQ = 3, + K_REF_SOFT_IRQ = 4, + K_REF_IPID = 5, + K_REF_ITID_LOOKUP_IPID = 6, + K_REF_MAX +}; + +enum EndState { + // (R) ready state or running state, the process is ready to run, but not necessarily occupying the CPU + TASK_RUNNABLE = 0, + // (S) Indicates that the process is in light sleep, waiting for the resource state, and can respond to the signal. + // Generally, the process actively sleeps into 'S' state. + TASK_INTERRUPTIBLE = 1, + // (D) Indicates that the process is in deep sleep, waiting for resources, and does not respond to signals. + // Typical scenario: process acquisition semaphore blocking. + TASK_UNINTERRUPTIBLE = 2, + // (Running) Indicates that the thread is running + TASK_RUNNING = 3, + // (I) Thread in interrupt state + TASK_INTERRUPTED = 4, + // (T) Task being traced + TASK_TRACED = 8, + // (X) Exit status, the process is about to be destroyed. + TASK_EXIT_DEAD = 16, + // (Z) Zombie state + TASK_ZOMBIE = 32, + // (I) clone thread + TASK_CLONE = 64, + // (K) Process killed + TASK_KILLED = 128, + // (DK) + TASK_DK = 130, + // the process is being debug now + TASK_TRACED_KILL = 136, + // (W) The process is in a deep sleep state and will be killed directly after waking up + TASK_WAKEKILL = 256, + // (R+) Process groups in the foreground + TASK_FOREGROUND = 2048, + TASK_MAX = 4096, + TASK_INVALID = 9999 +}; +enum TSLogLevel { + TS_DEBUG = 68, // Debug + TS_ERROR = 69, // Error + TS_INFO = 73, // Info + TS_VERBOSE = 86, // Verbose + TS_WARN = 87 // Warn +}; +enum SchedWakeType { + SCHED_WAKING = 0, // sched_waking + SCHED_WAKEUP = 1, // sched_wakeup +}; +using DataIndex = uint64_t; +using TableRowId = uint64_t; +using InternalPid = uint32_t; +using InternalTid = uint32_t; +using InternalTime = uint64_t; +using FilterId = uint32_t; + +enum BaseDataType { + BASE_DATA_TYPE_INT, + BASE_DATA_TYPE_STRING, + BASE_DATA_TYPE_DOUBLE, + BASE_DATA_TYPE_BOOLEAN +}; +namespace SysTuning { +namespace TraceStreamer { +struct ArgsData { + BaseDataType type; + int64_t value; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif diff --git a/host/trace_streamer/src/cfg/cfg.pri b/host/trace_streamer/src/cfg/cfg.pri new file mode 100644 index 0000000000000000000000000000000000000000..7833002efccdde1f36fe5cd2730085e4a687c623 --- /dev/null +++ b/host/trace_streamer/src/cfg/cfg.pri @@ -0,0 +1,19 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +INCLUDEPATH +=$$PWD +HEADERS += \ + $$PWD/trace_streamer_config.h + +SOURCES += \ + $$PWD/trace_streamer_config.cpp diff --git a/host/trace_streamer/src/cfg/trace_streamer_config.cpp b/host/trace_streamer/src/cfg/trace_streamer_config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e72cf60d218d31458c62c45f2f6dea8548cccd6b --- /dev/null +++ b/host/trace_streamer/src/cfg/trace_streamer_config.cpp @@ -0,0 +1,989 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "trace_streamer_config.h" +#include "log.h" +namespace SysTuning { +namespace TraceCfg { +TraceStreamerConfig::TraceStreamerConfig() +{ + InitEventNameMap(); + eventErrorDescMap_ = { + {STAT_EVENT_RECEIVED, TRACE_STAT_TYPE_RECEIVED_DESC}, + {STAT_EVENT_DATA_LOST, TRACE_STAT_TYPE_LOST_DESC}, + {STAT_EVENT_NOTMATCH, TRACE_STAT_TYPE_NOTMATCH_DESC}, + {STAT_EVENT_NOTSUPPORTED, TRACE_STAT_TYPE_NOTSUPPORTED_DESC}, + {STAT_EVENT_DATA_INVALID, TRACE_STAT_TYPE_DATA_INVALID_DESC}, + }; + serverityLevelDescMap_ = { + {STAT_SEVERITY_LEVEL_INFO, STAT_SEVERITY_LEVEL_INFO_DESC}, + {STAT_SEVERITY_LEVEL_WARN, STAT_SEVERITY_LEVEL_WARN_DESC}, + {STAT_SEVERITY_LEVEL_ERROR, STAT_SEVERITY_LEVEL_ERROR_DESC}, + {STAT_SEVERITY_LEVEL_FATAL, STAT_SEVERITY_LEVEL_FATAL_DESC}, + }; + memNameMap_ = { + {MEM_VM_SIZE, MEM_INFO_VM_SIZE_DESC}, {MEM_VM_LOCKED, MEM_INFO_LOCKED_DESC}, + {MEM_VM_RSS, MEM_INFO_RSS_DESC}, {MEM_VM_ANON, MEM_INFO_RSS_ANON_DESC}, + {MEM_RSS_FILE, MEM_INFO_RSS_FILE_DESC}, {MEM_RSS_SHMEM, MEM_INFO_RSS_SCHEM_DESC}, + {MEM_VM_SWAP, MEM_INFO_SWAP_DESC}, {MEM_VM_LOCKED, MEM_INFO_VIRT_DESC}, + {MEM_VM_HWM, MEM_INFO_HWM_DESC}, {MEM_OOM_SCORE_ADJ, MEM_INFO_SCORE_ADJ_DESC}, + }; + + InitSysMemMap(); + InitSysVmemMap(); + InitSecurityMap(); + if (eventNameMap_.size() != TRACE_EVENT_MAX) { + TS_LOGF("eventNameMap_.size() max be %d, logic error", TRACE_EVENT_MAX); + } + if (eventErrorDescMap_.size() != STAT_EVENT_MAX) { + TS_LOGF("eventErrorDescMap_.size() max be %d, logic error", STAT_EVENT_MAX); + } + if (serverityLevelDescMap_.size() != STAT_SEVERITY_LEVEL_MAX) { + TS_LOGF("serverityLevelDescMap_.size() max be %d, logic error", STAT_SEVERITY_LEVEL_MAX); + } + if (eventParserStatSeverityDescMap_.size() != TRACE_EVENT_MAX) { + TS_LOGF("eventParserStatSeverityDescMap_.size() max be %d, logic error", TRACE_EVENT_MAX); + } + if (memNameMap_.size() != MEM_MAX) { + TS_LOGF("memNameMap_.size() max be %d, logic error", MEM_MAX); + } + for (int i = TRACE_EVENT_START; i < TRACE_EVENT_MAX; i++) { + if (eventParserStatSeverityDescMap_.at(static_cast(i)).size() != STAT_EVENT_MAX) { + TS_LOGF("every item in eventParserStatSeverityDescMap_ max be %d, logic error", STAT_EVENT_MAX); + } + } +} + +void TraceStreamerConfig::PrintInfo() const +{ + printf("---all kind of trace event info---\n"); + for (auto itor = eventNameMap_.begin(); itor != eventNameMap_.end(); itor++) { + printf("%s\n", itor->second.c_str()); + } + printf("\n"); + printf("---subdir of process mem info---\n"); + for (auto itor = memNameMap_.begin(); itor != memNameMap_.end(); itor++) { + printf("%s\n", itor->second.c_str()); + } + printf("\n"); + printf("---subdir of sys mem info---\n"); + for (auto itor = sysMemNameMap_.begin(); itor != sysMemNameMap_.end(); itor++) { + printf("%s\n", itor->second.c_str()); + } + printf("\n"); + printf("---subdir of sys vmem info---\n"); + for (auto itor = sysVirtualMemNameMap_.begin(); itor != sysVirtualMemNameMap_.end(); itor++) { + printf("%s\n", itor->second.c_str()); + } + printf("\n"); +} +void TraceStreamerConfig::InitEventNameMap() +{ + eventNameMap_ = {{TRACE_EVENT_BINDER_TRANSACTION, TRACE_ACTION_BINDER_TRANSACTION}, + {TRACE_EVENT_BINDER_TRANSACTION_RECEIVED, TRACE_ACTION_BINDER_TRANSACTION_RECEIVED}, + {TRACE_EVENT_BINDER_TRANSACTION_ALLOC_BUF, TRACE_ACTION_BINDER_TRANSACTION_ALLOC_BUF}, + {TRACE_EVENT_BINDER_TRANSACTION_LOCK, TRACE_ACTION_BINDER_TRANSACTION_LOCK}, + {TRACE_EVENT_BINDER_TRANSACTION_LOCKED, TRACE_ACTION_BINDER_TRANSACTION_LOCKED}, + {TRACE_EVENT_BINDER_TRANSACTION_UNLOCK, TRACE_ACTION_BINDER_TRANSACTION_UNLOCK}, + {TRACE_EVENT_SCHED_SWITCH, TRACE_ACTION_SCHED_SWITCH}, + {TRACE_EVENT_TASK_RENAME, TRACE_ACTION_TASK_RENAME}, + {TRACE_EVENT_TASK_NEWTASK, TRACE_ACTION_TASK_NEWTASK}, + {TRACE_EVENT_TRACING_MARK_WRITE, TRACE_ACTION_TRACING_MARK_WRITE}, + {TRACE_EVENT_PRINT, TRACE_ACTION_PRINT}, + {TRACE_EVENT_SCHED_WAKEUP, TRACE_ACTION_SCHED_WAKEUP}, + {TRACE_EVENT_SCHED_WAKING, TRACE_ACTION_SCHED_WAKING}, + {TRACE_EVENT_CPU_IDLE, TRACE_ACTION_CPU_IDLE}, + {TRACE_EVENT_CPU_FREQUENCY, TRACE_ACTION_CPU_FREQUENCY}, + {TRACE_EVENT_SUSPEND_RESUME, TRACE_ACTION_SUSPEND_RESUME}, + {TRACE_EVENT_WORKQUEUE_EXECUTE_START, TRACE_ACTION_WORKQUEUE_EXECUTE_START}, + {TRACE_EVENT_WORKQUEUE_EXECUTE_END, TRACE_ACTION_WORKQUEUE_EXECUTE_END}, + {TRACE_EVENT_CLOCK_SET_RATE, TRACE_ACTION_CLOCK_SET_RATE}, + {TRACE_EVENT_CLOCK_ENABLE, TRACE_ACTION_CLOCK_ENABLE}, + {TRACE_EVENT_CLOCK_DISABLE, TRACE_ACTION_CLOCK_DISABLE}, + {TRACE_EVENT_CLK_SET_RATE, TRACE_ACTION_CLK_SET_RATE}, + {TRACE_EVENT_CLK_ENABLE, TRACE_ACTION_CLK_ENABLE}, + {TRACE_EVENT_CLK_DISABLE, TRACE_ACTION_CLK_DISABLE}, + {TRACE_EVENT_SYS_ENTRY, TRACE_ACTION_SYS_ENTRY}, + {TRACE_EVENT_SYS_EXIT, TRACE_ACTION_SYS_EXIT}, + {TRACE_EVENT_OOM_SCORE_ADJ_UPDATE, TRACE_ACTION_OOM_SCORE_ADJ_UPDATE}, + {TRACE_EVENT_REGULATOR_SET_VOLTAGE, TRACE_ACTION_REGULATOR_SET_VOLTAGE}, + {TRACE_EVENT_REGULATOR_SET_VOLTAGE_COMPLETE, TRACE_ACTION_REGULATOR_SET_VOLTAGE_COMPLETE}, + {TRACE_EVENT_REGULATOR_DISABLE, TRACE_ACTION_REGULATOR_DISABLE}, + {TRACE_EVENT_REGULATOR_DISABLE_COMPLETE, TRACE_ACTION_REGULATOR_DISABLE_COMPLETE}, + {TRACE_EVENT_IPI_ENTRY, TRACE_ACTION_IPI_ENTRY}, + {TRACE_EVENT_IPI_EXIT, TRACE_ACTION_IPI_EXIT}, + {TRACE_EVENT_IRQ_HANDLER_ENTRY, TRACE_ACTION_IRQ_HANDLER_ENTRY}, + {TRACE_EVENT_IRQ_HANDLER_EXIT, TRACE_ACTION_IRQ_HANDLER_EXIT}, + {TRACE_EVENT_SOFTIRQ_RAISE, TRACE_ACTION_SOFTIRQ_RAISE}, + {TRACE_EVENT_SOFTIRQ_ENTRY, TRACE_ACTION_SOFTIRQ_ENTRY}, + {TRACE_EVENT_SOFTIRQ_EXIT, TRACE_ACTION_SOFTIRQ_EXIT}, + {TRACE_EVENT_SCHED_WAKEUP_NEW, TRACE_ACTION_SCHED_WAKEUP_NEW}, + {TRACE_EVENT_PROCESS_EXIT, TRACE_ACTION_PROCESS_EXIT}, + {TRACE_EVENT_PROCESS_FREE, TRACE_ACTION_PROCESS_FREE}, + {TRACE_EVENT_CLOCK_SYNC, TRACE_ACTION_CLOCK_SYNC}, + {TRACE_MEMORY, TRACE_ACTION_MEMORY}, + {TRACE_SYS_MEMORY, TRACE_ACTION_SYS_MEMORY}, + {TRACE_SYS_VIRTUAL_MEMORY, TRACE_ACTION_SYS_VIRTUAL_MEMORY}, + {TRACE_EVENT_SIGNAL_GENERATE, TRACE_ACTION_SIGNAL_GENERATE}, + {TRACE_EVENT_SIGNAL_DELIVER, TRACE_ACTION_SIGNAL_DELIVER}, + {TRACE_EVENT_BLOCK_BIO_BACKMERGE, TRACE_ACTION_BLOCK_BIO_BACKMERGE}, + {TRACE_EVENT_BLOCK_BIO_BOUNCE, TRACE_ACTION_BLOCK_BIO_BOUNCE}, + {TRACE_EVENT_BLOCK_BIO_COMPLETE, TRACE_ACTION_BLOCK_BIO_COMPLETE}, + {TRACE_EVENT_BLOCK_BIO_FRONTMERGE, TRACE_ACTION_BLOCK_BIO_FRONTMERGE}, + {TRACE_EVENT_BLOCK_BIO_QUEUE, TRACE_ACTION_BLOCK_BIO_QUEUE}, + {TRACE_EVENT_BLOCK_BIO_REMAP, TRACE_ACTION_BLOCK_BIO_REMAP}, + {TRACE_EVENT_BLOCK_DIRTY_BUFFER, TRACE_ACTION_BLOCK_DIRTY_BUFFER}, + {TRACE_EVENT_BLOCK_GETRQ, TRACE_ACTION_BLOCK_GETRQ}, + {TRACE_EVENT_BLOCK_PLUG, TRACE_ACTION_BLOCK_PLUG}, + {TRACE_EVENT_BLOCK_RQ_COMPLETE, TRACE_ACTION_BLOCK_RQ_COMPLETE}, + {TRACE_EVENT_BLOCK_RQ_INSERT, TRACE_ACTION_BLOCK_RQ_INSERT}, + {TRACE_EVENT_BLOCK_RQ_REMAP, TRACE_ACTION_BLOCK_RQ_REMAP}, + {TRACE_EVENT_BLOCK_RQ_ISSUE, TRACE_ACTION_BLOCK_RQ_ISSUE}, + {TRACE_EVENT_OTHER, TRACE_ACTION_OTHER}, + {TRACE_HILOG, TRACE_ACTION_HILOG}, + {TRACE_HIDUMP_FPS, TRACE_ACTION_HIDUMP_FPS}, + {TRACE_NATIVE_HOOK_MALLOC, TRACE_ACTION_NATIVE_HOOK_MALLOC}, + {TRACE_NATIVE_HOOK_FREE, TRACE_ACTION_NATIVE_HOOK_FREE}}; +} +void TraceStreamerConfig::InitSysMemMap() +{ + sysMemNameMap_ = { + {SysMeminfoType::PMEM_UNSPECIFIED, SYS_MEMINFO_UNSPECIFIED_DESC}, + {SysMeminfoType::PMEM_MEM_TOTAL, SYS_MEMINFO_MEM_TOTAL_DESC}, + {SysMeminfoType::PMEM_MEM_FREE, SYS_MEMINFO_MEM_FREE_DESC}, + {SysMeminfoType::PMEM_MEM_AVAILABLE, SYS_MEMINFO_MEM_AVAILABLE_DESC}, + {SysMeminfoType::PMEM_BUFFERS, SYS_MEMINFO_BUFFERS_DESC}, + {SysMeminfoType::PMEM_CACHED, SYS_MEMINFO_CACHED_DESC}, + {SysMeminfoType::PMEM_SWAP_CACHED, SYS_MEMINFO_SWAP_CACHED_DESC}, + {SysMeminfoType::PMEM_ACTIVE, SYS_MEMINFO_ACTIVE_DESC}, + {SysMeminfoType::PMEM_INACTIVE, SYS_MEMINFO_INACTIVE_DESC}, + {SysMeminfoType::PMEM_ACTIVE_ANON, SYS_MEMINFO_ACTIVE_ANON_DESC}, + {SysMeminfoType::PMEM_INACTIVE_ANON, SYS_MEMINFO_INACTIVE_ANON_DESC}, + {SysMeminfoType::PMEM_ACTIVE_FILE, SYS_MEMINFO_ACTIVE_FILE_DESC}, + {SysMeminfoType::PMEM_INACTIVE_FILE, SYS_MEMINFO_INACTIVE_FILE_DESC}, + {SysMeminfoType::PMEM_UNEVICTABLE, SYS_MEMINFO_UNEVICTABLE_DESC}, + {SysMeminfoType::PMEM_MLOCKED, SYS_MEMINFO_MLOCKED_DESC}, + {SysMeminfoType::PMEM_SWAP_TOTAL, SYS_MEMINFO_SWAP_TOTAL_DESC}, + {SysMeminfoType::PMEM_SWAP_FREE, SYS_MEMINFO_SWAP_FREE_DESC}, + {SysMeminfoType::PMEM_DIRTY, SYS_MEMINFO_DIRTY_DESC}, + {SysMeminfoType::PMEM_WRITEBACK, SYS_MEMINFO_WRITEBACK_DESC}, + {SysMeminfoType::PMEM_ANON_PAGES, SYS_MEMINFO_ANON_PAGES_DESC}, + {SysMeminfoType::PMEM_MAPPED, SYS_MEMINFO_MAPPED_DESC}, + {SysMeminfoType::PMEM_SHMEM, SYS_MEMINFO_SHMEM_DESC}, + {SysMeminfoType::PMEM_SLAB, SYS_MEMINFO_SLAB_DESC}, + {SysMeminfoType::PMEM_SLAB_RECLAIMABLE, SYS_MEMINFO_SLAB_RECLAIMABLE_DESC}, + {SysMeminfoType::PMEM_SLAB_UNRECLAIMABLE, SYS_MEMINFO_SLAB_UNRECLAIMABLE_DESC}, + {SysMeminfoType::PMEM_KERNEL_STACK, SYS_MEMINFO_KERNEL_STACK_DESC}, + {SysMeminfoType::PMEM_PAGE_TABLES, SYS_MEMINFO_PAGE_TABLES_DESC}, + {SysMeminfoType::PMEM_COMMIT_LIMIT, SYS_MEMINFO_COMMIT_LIMIT_DESC}, + {SysMeminfoType::PMEM_COMMITED_AS, SYS_MEMINFO_COMMITED_AS_DESC}, + {SysMeminfoType::PMEM_VMALLOC_TOTAL, SYS_MEMINFO_VMALLOC_TOTAL_DESC}, + {SysMeminfoType::PMEM_VMALLOC_USED, SYS_MEMINFO_VMALLOC_USED_DESC}, + {SysMeminfoType::PMEM_VMALLOC_CHUNK, SYS_MEMINFO_VMALLOC_CHUNK_DESC}, + {SysMeminfoType::PMEM_CMA_TOTAL, SYS_MEMINFO_CMA_TOTAL_DESC}, + {SysMeminfoType::PMEM_CMA_FREE, SYS_MEMINFO_CMA_FREE_DESC}, + }; +} + +void TraceStreamerConfig::InitSysVmemMap() +{ + sysVirtualMemNameMap_ = { + {SysVMeminfoType::VMEMINFO_UNSPECIFIED, SYS_VMEMINFO_UNSPECIFIED_DESC}, + {SysVMeminfoType::VMEMINFO_NR_FREE_PAGES, SYS_VMEMINFO_NR_FREE_PAGES_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ALLOC_BATCH, SYS_VMEMINFO_NR_ALLOC_BATCH_DESC}, + {SysVMeminfoType::VMEMINFO_NR_INACTIVE_ANON, SYS_VMEMINFO_NR_INACTIVE_ANON_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ACTIVE_ANON, SYS_VMEMINFO_NR_ACTIVE_ANON_DESC}, + {SysVMeminfoType::VMEMINFO_NR_INACTIVE_FILE, SYS_VMEMINFO_NR_INACTIVE_FILE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ACTIVE_FILE, SYS_VMEMINFO_NR_ACTIVE_FILE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_UNEVICTABLE, SYS_VMEMINFO_NR_UNEVICTABLE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_MLOCK, SYS_VMEMINFO_NR_MLOCK_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ANON_PAGES, SYS_VMEMINFO_NR_ANON_PAGES_DESC}, + {SysVMeminfoType::VMEMINFO_NR_MAPPED, SYS_VMEMINFO_NR_MAPPED_DESC}, + {SysVMeminfoType::VMEMINFO_NR_FILE_PAGES, SYS_VMEMINFO_NR_FILE_PAGES_DESC}, + {SysVMeminfoType::VMEMINFO_NR_DIRTY, SYS_VMEMINFO_NR_DIRTY_DESC}, + {SysVMeminfoType::VMEMINFO_NR_WRITEBACK, SYS_VMEMINFO_NR_WRITEBACK_DESC}, + {SysVMeminfoType::VMEMINFO_NR_SLAB_RECLAIMABLE, SYS_VMEMINFO_NR_SLAB_RECLAIMABLE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_SLAB_UNRECLAIMABLE, SYS_VMEMINFO_NR_SLAB_UNRECLAIMABLE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_PAGE_TABLE_PAGES, SYS_VMEMINFO_NR_PAGE_TABLE_PAGES_DESC}, + {SysVMeminfoType::VMEMINFO_NR_KERNEL_STACK, SYS_VMEMINFO_NR_KERNEL_STACK_DESC}, + {SysVMeminfoType::VMEMINFO_NR_OVERHEAD, SYS_VMEMINFO_NR_OVERHEAD_DESC}, + {SysVMeminfoType::VMEMINFO_NR_UNSTABLE, SYS_VMEMINFO_NR_UNSTABLE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_BOUNCE, SYS_VMEMINFO_NR_BOUNCE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_VMSCAN_WRITE, SYS_VMEMINFO_NR_VMSCAN_WRITE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_VMSCAN_IMMEDIATE_RECLAIM, SYS_VMEMINFO_NR_VMSCAN_IMMEDIATE_RECLAIM_DESC}, + {SysVMeminfoType::VMEMINFO_NR_WRITEBACK_TEMP, SYS_VMEMINFO_NR_WRITEBACK_TEMP_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ISOLATED_ANON, SYS_VMEMINFO_NR_ISOLATED_ANON_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ISOLATED_FILE, SYS_VMEMINFO_NR_ISOLATED_FILE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_SHMEM, SYS_VMEMINFO_NR_SHMEM_DESC}, + {SysVMeminfoType::VMEMINFO_NR_DIRTIED, SYS_VMEMINFO_NR_DIRTIED_DESC}, + {SysVMeminfoType::VMEMINFO_NR_WRITTEN, SYS_VMEMINFO_NR_WRITTEN_DESC}, + {SysVMeminfoType::VMEMINFO_NR_PAGES_SCANNED, SYS_VMEMINFO_NR_PAGES_SCANNED_DESC}, + {SysVMeminfoType::VMEMINFO_WORKINGSET_REFAULT, SYS_VMEMINFO_WORKINGSET_REFAULT_DESC}, + {SysVMeminfoType::VMEMINFO_WORKINGSET_ACTIVATE, SYS_VMEMINFO_WORKINGSET_ACTIVATE_DESC}, + {SysVMeminfoType::VMEMINFO_WORKINGSET_NODERECLAIM, SYS_VMEMINFO_WORKINGSET_NODERECLAIM_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ANON_TRANSPARENT_HUGEPAGES, SYS_VMEMINFO_NR_ANON_TRANSPARENT_HUGEPAGES_DESC}, + {SysVMeminfoType::VMEMINFO_NR_FREE_CMA, SYS_VMEMINFO_NR_FREE_CMA_DESC}, + {SysVMeminfoType::VMEMINFO_NR_SWAPCACHE, SYS_VMEMINFO_NR_SWAPCACHE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_DIRTY_THRESHOLD, SYS_VMEMINFO_NR_DIRTY_THRESHOLD_DESC}, + {SysVMeminfoType::VMEMINFO_NR_DIRTY_BACKGROUND_THRESHOLD, SYS_VMEMINFO_NR_DIRTY_BACKGROUND_THRESHOLD_DESC}, + {SysVMeminfoType::VMEMINFO_PGPGIN, SYS_VMEMINFO_PGPGIN_DESC}, + {SysVMeminfoType::VMEMINFO_PGPGOUT, SYS_VMEMINFO_PGPGOUT_DESC}, + {SysVMeminfoType::VMEMINFO_PGPGOUTCLEAN, SYS_VMEMINFO_PGPGOUTCLEAN_DESC}, + {SysVMeminfoType::VMEMINFO_PSWPIN, SYS_VMEMINFO_PSWPIN_DESC}, + {SysVMeminfoType::VMEMINFO_PSWPOUT, SYS_VMEMINFO_PSWPOUT_DESC}, + {SysVMeminfoType::VMEMINFO_PGALLOC_DMA, SYS_VMEMINFO_PGALLOC_DMA_DESC}, + {SysVMeminfoType::VMEMINFO_PGALLOC_NORMAL, SYS_VMEMINFO_PGALLOC_NORMAL_DESC}, + {SysVMeminfoType::VMEMINFO_PGALLOC_MOVABLE, SYS_VMEMINFO_PGALLOC_MOVABLE_DESC}, + {SysVMeminfoType::VMEMINFO_PGFREE, SYS_VMEMINFO_PGFREE_DESC}, + {SysVMeminfoType::VMEMINFO_PGACTIVATE, SYS_VMEMINFO_PGACTIVATE_DESC}, + {SysVMeminfoType::VMEMINFO_PGDEACTIVATE, SYS_VMEMINFO_PGDEACTIVATE_DESC}, + {SysVMeminfoType::VMEMINFO_PGFAULT, SYS_VMEMINFO_PGFAULT_DESC}, + {SysVMeminfoType::VMEMINFO_PGMAJFAULT, SYS_VMEMINFO_PGMAJFAULT_DESC}, + {SysVMeminfoType::VMEMINFO_PGREFILL_DMA, SYS_VMEMINFO_PGREFILL_DMA_DESC}, + {SysVMeminfoType::VMEMINFO_PGREFILL_NORMAL, SYS_VMEMINFO_PGREFILL_NORMAL_DESC}, + {SysVMeminfoType::VMEMINFO_PGREFILL_MOVABLE, SYS_VMEMINFO_PGREFILL_MOVABLE_DESC}, + {SysVMeminfoType::VMEMINFO_PGSTEAL_KSWAPD_DMA, SYS_VMEMINFO_PGSTEAL_KSWAPD_DMA_DESC}, + {SysVMeminfoType::VMEMINFO_PGSTEAL_KSWAPD_NORMAL, SYS_VMEMINFO_PGSTEAL_KSWAPD_NORMAL_DESC}, + {SysVMeminfoType::VMEMINFO_PGSTEAL_KSWAPD_MOVABLE, SYS_VMEMINFO_PGSTEAL_KSWAPD_MOVABLE_DESC}, + {SysVMeminfoType::VMEMINFO_PGSTEAL_DIRECT_DMA, SYS_VMEMINFO_PGSTEAL_DIRECT_DMA_DESC}, + {SysVMeminfoType::VMEMINFO_PGSTEAL_DIRECT_NORMAL, SYS_VMEMINFO_PGSTEAL_DIRECT_NORMAL_DESC}, + {SysVMeminfoType::VMEMINFO_PGSTEAL_DIRECT_MOVABLE, SYS_VMEMINFO_PGSTEAL_DIRECT_MOVABLE_DESC}, + {SysVMeminfoType::VMEMINFO_PGSCAN_KSWAPD_DMA, SYS_VMEMINFO_PGSCAN_KSWAPD_DMA_DESC}, + {SysVMeminfoType::VMEMINFO_PGSCAN_KSWAPD_NORMAL, SYS_VMEMINFO_PGSCAN_KSWAPD_NORMAL_DESC}, + {SysVMeminfoType::VMEMINFO_PGSCAN_KSWAPD_MOVABLE, SYS_VMEMINFO_PGSCAN_KSWAPD_MOVABLE_DESC}, + {SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT_DMA, SYS_VMEMINFO_PGSCAN_DIRECT_DMA_DESC}, + {SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT_NORMAL, SYS_VMEMINFO_PGSCAN_DIRECT_NORMAL_DESC}, + {SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT_MOVABLE, SYS_VMEMINFO_PGSCAN_DIRECT_MOVABLE_DESC}, + {SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT_THROTTLE, SYS_VMEMINFO_PGSCAN_DIRECT_THROTTLE_DESC}, + {SysVMeminfoType::VMEMINFO_PGINODESTEAL, SYS_VMEMINFO_PGINODESTEAL_DESC}, + {SysVMeminfoType::VMEMINFO_SLABS_SCANNED, SYS_VMEMINFO_SLABS_SCANNED_DESC}, + {SysVMeminfoType::VMEMINFO_KSWAPD_INODESTEAL, SYS_VMEMINFO_KSWAPD_INODESTEAL_DESC}, + {SysVMeminfoType::VMEMINFO_KSWAPD_LOW_WMARK_HIT_QUICKLY, SYS_VMEMINFO_KSWAPD_LOW_WMARK_HIT_QUICKLY_DESC}, + {SysVMeminfoType::VMEMINFO_KSWAPD_HIGH_WMARK_HIT_QUICKLY, SYS_VMEMINFO_KSWAPD_HIGH_WMARK_HIT_QUICKLY_DESC}, + {SysVMeminfoType::VMEMINFO_PAGEOUTRUN, SYS_VMEMINFO_PAGEOUTRUN_DESC}, + {SysVMeminfoType::VMEMINFO_ALLOCSTALL, SYS_VMEMINFO_ALLOCSTALL_DESC}, + {SysVMeminfoType::VMEMINFO_PGROTATED, SYS_VMEMINFO_PGROTATED_DESC}, + {SysVMeminfoType::VMEMINFO_DROP_PAGECACHE, SYS_VMEMINFO_DROP_PAGECACHE_DESC}, + {SysVMeminfoType::VMEMINFO_DROP_SLAB, SYS_VMEMINFO_DROP_SLAB_DESC}, + {SysVMeminfoType::VMEMINFO_PGMIGRATE_SUCCESS, SYS_VMEMINFO_PGMIGRATE_SUCCESS_DESC}, + {SysVMeminfoType::VMEMINFO_PGMIGRATE_FAIL, SYS_VMEMINFO_PGMIGRATE_FAIL_DESC}, + {SysVMeminfoType::VMEMINFO_COMPACT_MIGRATE_SCANNED, SYS_VMEMINFO_COMPACT_MIGRATE_SCANNED_DESC}, + {SysVMeminfoType::VMEMINFO_COMPACT_FREE_SCANNED, SYS_VMEMINFO_COMPACT_FREE_SCANNED_DESC}, + {SysVMeminfoType::VMEMINFO_COMPACT_ISOLATED, SYS_VMEMINFO_COMPACT_ISOLATED_DESC}, + {SysVMeminfoType::VMEMINFO_COMPACT_STALL, SYS_VMEMINFO_COMPACT_STALL_DESC}, + {SysVMeminfoType::VMEMINFO_COMPACT_FAIL, SYS_VMEMINFO_COMPACT_FAIL_DESC}, + {SysVMeminfoType::VMEMINFO_COMPACT_SUCCESS, SYS_VMEMINFO_COMPACT_SUCCESS_DESC}, + {SysVMeminfoType::VMEMINFO_COMPACT_DAEMON_WAKE, SYS_VMEMINFO_COMPACT_DAEMON_WAKE_DESC}, + {SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_CULLED, SYS_VMEMINFO_UNEVICTABLE_PGS_CULLED_DESC}, + {SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_SCANNED, SYS_VMEMINFO_UNEVICTABLE_PGS_SCANNED_DESC}, + {SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_RESCUED, SYS_VMEMINFO_UNEVICTABLE_PGS_RESCUED_DESC}, + {SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_MLOCKED, SYS_VMEMINFO_UNEVICTABLE_PGS_MLOCKED_DESC}, + {SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_MUNLOCKED, SYS_VMEMINFO_UNEVICTABLE_PGS_MUNLOCKED_DESC}, + {SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_CLEARED, SYS_VMEMINFO_UNEVICTABLE_PGS_CLEARED_DESC}, + {SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_STRANDED, SYS_VMEMINFO_UNEVICTABLE_PGS_STRANDED_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ZSPAGES, SYS_VMEMINFO_NR_ZSPAGES_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ION_HEAP, SYS_VMEMINFO_NR_ION_HEAP_DESC}, + {SysVMeminfoType::VMEMINFO_NR_GPU_HEAP, SYS_VMEMINFO_NR_GPU_HEAP_DESC}, + {SysVMeminfoType::VMEMINFO_ALLOCSTALL_DMA, SYS_VMEMINFO_ALLOCSTALL_DMA_DESC}, + {SysVMeminfoType::VMEMINFO_ALLOCSTALL_MOVABLE, SYS_VMEMINFO_ALLOCSTALL_MOVABLE_DESC}, + {SysVMeminfoType::VMEMINFO_ALLOCSTALL_NORMAL, SYS_VMEMINFO_ALLOCSTALL_NORMAL_DESC}, + {SysVMeminfoType::VMEMINFO_COMPACT_DAEMON_FREE_SCANNED, SYS_VMEMINFO_COMPACT_DAEMON_FREE_SCANNED_DESC}, + {SysVMeminfoType::VMEMINFO_COMPACT_DAEMON_MIGRATE_SCANNED, SYS_VMEMINFO_COMPACT_DAEMON_MIGRATE_SCANNED_DESC}, + {SysVMeminfoType::VMEMINFO_NR_FASTRPC, SYS_VMEMINFO_NR_FASTRPC_DESC}, + {SysVMeminfoType::VMEMINFO_NR_INDIRECTLY_RECLAIMABLE, SYS_VMEMINFO_NR_INDIRECTLY_RECLAIMABLE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ION_HEAP_POOL, SYS_VMEMINFO_NR_ION_HEAP_POOL_DESC}, + {SysVMeminfoType::VMEMINFO_NR_KERNEL_MISC_RECLAIMABLE, SYS_VMEMINFO_NR_KERNEL_MISC_RECLAIMABLE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_SHADOW_CALL_STACK_BYTES, SYS_VMEMINFO_NR_SHADOW_CALL_STACK_BYTES_DESC}, + {SysVMeminfoType::VMEMINFO_NR_SHMEM_HUGEPAGES, SYS_VMEMINFO_NR_SHMEM_HUGEPAGES_DESC}, + {SysVMeminfoType::VMEMINFO_NR_SHMEM_PMDMAPPED, SYS_VMEMINFO_NR_SHMEM_PMDMAPPED_DESC}, + {SysVMeminfoType::VMEMINFO_NR_UNRECLAIMABLE_PAGES, SYS_VMEMINFO_NR_UNRECLAIMABLE_PAGES_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ZONE_ACTIVE_ANON, SYS_VMEMINFO_NR_ZONE_ACTIVE_ANON_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ZONE_ACTIVE_FILE, SYS_VMEMINFO_NR_ZONE_ACTIVE_FILE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ZONE_INACTIVE_ANON, SYS_VMEMINFO_NR_ZONE_INACTIVE_ANON_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ZONE_INACTIVE_FILE, SYS_VMEMINFO_NR_ZONE_INACTIVE_FILE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ZONE_UNEVICTABLE, SYS_VMEMINFO_NR_ZONE_UNEVICTABLE_DESC}, + {SysVMeminfoType::VMEMINFO_NR_ZONE_WRITE_PENDING, SYS_VMEMINFO_NR_ZONE_WRITE_PENDING_DESC}, + {SysVMeminfoType::VMEMINFO_OOM_KILL, SYS_VMEMINFO_OOM_KILL_DESC}, + {SysVMeminfoType::VMEMINFO_PGLAZYFREE, SYS_VMEMINFO_PGLAZYFREE_DESC}, + {SysVMeminfoType::VMEMINFO_PGLAZYFREED, SYS_VMEMINFO_PGLAZYFREED_DESC}, + {SysVMeminfoType::VMEMINFO_PGREFILL, SYS_VMEMINFO_PGREFILL_DESC}, + {SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT, SYS_VMEMINFO_PGSCAN_DIRECT_DESC}, + {SysVMeminfoType::VMEMINFO_PGSCAN_KSWAPD, SYS_VMEMINFO_PGSCAN_KSWAPD_DESC}, + {SysVMeminfoType::VMEMINFO_PGSKIP_DMA, SYS_VMEMINFO_PGSKIP_DMA_DESC}, + {SysVMeminfoType::VMEMINFO_PGSKIP_MOVABLE, SYS_VMEMINFO_PGSKIP_MOVABLE_DESC}, + {SysVMeminfoType::VMEMINFO_PGSKIP_NORMAL, SYS_VMEMINFO_PGSKIP_NORMAL_DESC}, + {SysVMeminfoType::VMEMINFO_PGSTEAL_DIRECT, SYS_VMEMINFO_PGSTEAL_DIRECT_DESC}, + {SysVMeminfoType::VMEMINFO_PGSTEAL_KSWAPD, SYS_VMEMINFO_PGSTEAL_KSWAPD_DESC}, + {SysVMeminfoType::VMEMINFO_SWAP_RA, SYS_VMEMINFO_SWAP_RA_DESC}, + {SysVMeminfoType::VMEMINFO_SWAP_RA_HIT, SYS_VMEMINFO_SWAP_RA_HIT_DESC}, + {SysVMeminfoType::VMEMINFO_WORKINGSET_RESTORE, SYS_VMEMINFO_WORKINGSET_RESTORE_DESC}}; +} +void TraceStreamerConfig::InitSecurityMap() +{ + eventParserStatSeverityDescMap_ = { + { + TRACE_EVENT_BINDER_TRANSACTION, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BINDER_TRANSACTION_RECEIVED, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BINDER_TRANSACTION_ALLOC_BUF, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BINDER_TRANSACTION_LOCK, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BINDER_TRANSACTION_LOCKED, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BINDER_TRANSACTION_UNLOCK, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_SCHED_SWITCH, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_TASK_RENAME, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_TASK_NEWTASK, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_TRACING_MARK_WRITE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_PRINT, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_SCHED_WAKEUP, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_SCHED_WAKING, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_CPU_IDLE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_CPU_FREQUENCY, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_SUSPEND_RESUME, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_WORKQUEUE_EXECUTE_START, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_WORKQUEUE_EXECUTE_END, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_CLOCK_SET_RATE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_CLOCK_ENABLE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_CLOCK_DISABLE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_CLK_SET_RATE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_CLK_ENABLE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_CLK_DISABLE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_REGULATOR_SET_VOLTAGE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_REGULATOR_SET_VOLTAGE_COMPLETE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_REGULATOR_DISABLE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_REGULATOR_DISABLE_COMPLETE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_IPI_ENTRY, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_IPI_EXIT, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_IRQ_HANDLER_ENTRY, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_IRQ_HANDLER_EXIT, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_SOFTIRQ_RAISE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_SOFTIRQ_ENTRY, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_SOFTIRQ_EXIT, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_SCHED_WAKEUP_NEW, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_PROCESS_EXIT, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_PROCESS_FREE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_CLOCK_SYNC, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_SYS_ENTRY, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_OOM_SCORE_ADJ_UPDATE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_SYS_EXIT, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_MEMORY, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_HILOG, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_HIDUMP_FPS, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_NATIVE_HOOK_MALLOC, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_NATIVE_HOOK_FREE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_SYS_MEMORY, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_SYS_VIRTUAL_MEMORY, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_SIGNAL_GENERATE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_SIGNAL_DELIVER, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BLOCK_BIO_BACKMERGE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BLOCK_BIO_BOUNCE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BLOCK_BIO_COMPLETE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BLOCK_BIO_FRONTMERGE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BLOCK_BIO_QUEUE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BLOCK_BIO_REMAP, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BLOCK_DIRTY_BUFFER, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BLOCK_GETRQ, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BLOCK_PLUG, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BLOCK_RQ_COMPLETE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BLOCK_RQ_INSERT, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BLOCK_RQ_REMAP, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_BLOCK_RQ_ISSUE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_OTHER, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + }; +} +} // namespace TraceCfg +} // namespace SysTuning diff --git a/host/trace_streamer/src/cfg/trace_streamer_config.h b/host/trace_streamer/src/cfg/trace_streamer_config.h new file mode 100644 index 0000000000000000000000000000000000000000..3e71a1a1f669c5ad8910b2867bf04c0e54df2fbf --- /dev/null +++ b/host/trace_streamer/src/cfg/trace_streamer_config.h @@ -0,0 +1,423 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TRACE_STREAMER_CONFIG_H +#define TRACE_STREAMER_CONFIG_H +#include +#include +#include "memory_plugin_common.pb.h" +namespace SysTuning { +namespace TraceCfg { +// all supported events should be defined here +enum SupportedTraceEventType { + TRACE_EVENT_START = 0, + TRACE_EVENT_BINDER_TRANSACTION = TRACE_EVENT_START, + TRACE_EVENT_BINDER_TRANSACTION_RECEIVED, + TRACE_EVENT_BINDER_TRANSACTION_ALLOC_BUF, + TRACE_EVENT_BINDER_TRANSACTION_LOCK, + TRACE_EVENT_BINDER_TRANSACTION_LOCKED, + TRACE_EVENT_BINDER_TRANSACTION_UNLOCK, + TRACE_EVENT_SCHED_SWITCH, + TRACE_EVENT_TASK_RENAME, + TRACE_EVENT_TASK_NEWTASK, + TRACE_EVENT_TRACING_MARK_WRITE, + TRACE_EVENT_PRINT, + TRACE_EVENT_SCHED_WAKEUP, + TRACE_EVENT_SCHED_WAKING, + TRACE_EVENT_CPU_IDLE, + TRACE_EVENT_CPU_FREQUENCY, + TRACE_EVENT_SUSPEND_RESUME, + TRACE_EVENT_WORKQUEUE_EXECUTE_START, + TRACE_EVENT_WORKQUEUE_EXECUTE_END, + TRACE_EVENT_CLOCK_SET_RATE, + TRACE_EVENT_CLOCK_ENABLE, + TRACE_EVENT_CLOCK_DISABLE, + TRACE_EVENT_CLK_SET_RATE, + TRACE_EVENT_CLK_ENABLE, + TRACE_EVENT_CLK_DISABLE, + TRACE_EVENT_SYS_ENTRY, + TRACE_EVENT_SYS_EXIT, + TRACE_EVENT_REGULATOR_SET_VOLTAGE, + TRACE_EVENT_REGULATOR_SET_VOLTAGE_COMPLETE, + TRACE_EVENT_REGULATOR_DISABLE, + TRACE_EVENT_REGULATOR_DISABLE_COMPLETE, + TRACE_EVENT_IPI_ENTRY, + TRACE_EVENT_IPI_EXIT, + TRACE_EVENT_IRQ_HANDLER_ENTRY, + TRACE_EVENT_IRQ_HANDLER_EXIT, + TRACE_EVENT_SOFTIRQ_RAISE, + TRACE_EVENT_SOFTIRQ_ENTRY, + TRACE_EVENT_SOFTIRQ_EXIT, + TRACE_EVENT_OOM_SCORE_ADJ_UPDATE, + TRACE_EVENT_SCHED_WAKEUP_NEW, + TRACE_EVENT_PROCESS_EXIT, + TRACE_EVENT_PROCESS_FREE, + TRACE_EVENT_CLOCK_SYNC, + TRACE_MEMORY, + TRACE_HILOG, + TRACE_HIDUMP_FPS, + TRACE_NATIVE_HOOK_MALLOC, + TRACE_NATIVE_HOOK_FREE, + TRACE_SYS_MEMORY, + TRACE_SYS_VIRTUAL_MEMORY, + TRACE_EVENT_SIGNAL_GENERATE, + TRACE_EVENT_SIGNAL_DELIVER, + TRACE_EVENT_BLOCK_BIO_BACKMERGE, + TRACE_EVENT_BLOCK_BIO_BOUNCE, + TRACE_EVENT_BLOCK_BIO_COMPLETE, + TRACE_EVENT_BLOCK_BIO_FRONTMERGE, + TRACE_EVENT_BLOCK_BIO_QUEUE, + TRACE_EVENT_BLOCK_BIO_REMAP, + TRACE_EVENT_BLOCK_DIRTY_BUFFER, + TRACE_EVENT_BLOCK_GETRQ, + TRACE_EVENT_BLOCK_PLUG, + TRACE_EVENT_BLOCK_RQ_COMPLETE, + TRACE_EVENT_BLOCK_RQ_INSERT, + TRACE_EVENT_BLOCK_RQ_REMAP, + TRACE_EVENT_BLOCK_RQ_ISSUE, + TRACE_EVENT_OTHER, + TRACE_EVENT_MAX +}; +enum MemInfoType { + MEM_VM_SIZE, + MEM_VM_RSS, + MEM_VM_ANON, + MEM_RSS_FILE, + MEM_RSS_SHMEM, + MEM_VM_SWAP, + MEM_VM_LOCKED, + MEM_VM_HWM, + MEM_OOM_SCORE_ADJ, + MEM_MAX +}; +enum StatType { + STAT_EVENT_START = 0, + STAT_EVENT_RECEIVED = STAT_EVENT_START, + STAT_EVENT_DATA_LOST, + STAT_EVENT_NOTMATCH, + STAT_EVENT_NOTSUPPORTED, + STAT_EVENT_DATA_INVALID, + STAT_EVENT_MAX +}; + +// there maybe some error while parser trace msgs, here defined the error levels +enum StatSeverityLevel { + STAT_SEVERITY_LEVEL_START = 0, + STAT_SEVERITY_LEVEL_INFO = STAT_SEVERITY_LEVEL_START, + STAT_SEVERITY_LEVEL_WARN, + STAT_SEVERITY_LEVEL_ERROR, + STAT_SEVERITY_LEVEL_FATAL, + STAT_SEVERITY_LEVEL_MAX +}; + +// the supported metadata +enum MetaDataItem { + METADATA_ITEM_START = 0, + METADATA_ITEM_DATASIZE = METADATA_ITEM_START, + METADATA_ITEM_PARSETOOL_NAME, + METADATA_ITEM_PARSERTOOL_VERSION, + METADATA_ITEM_PARSERTOOL_PUBLISH_DATETIME, + METADATA_ITEM_SOURCE_FILENAME, + METADATA_ITEM_OUTPUT_FILENAME, + METADATA_ITEM_PARSERTIME, // the data time while the data parsed + METADATA_ITEM_TRACE_DURATION, + METADATA_ITEM_SOURCE_DATETYPE, // proto-based-trace or txt-based-trace + METADATA_ITEM_MAX +}; + +class TraceStreamerConfig { +public: + TraceStreamerConfig(); + ~TraceStreamerConfig() = default; + void PrintInfo() const; + +public: + std::map eventNameMap_ = {}; + std::map eventErrorDescMap_ = {}; + std::map serverityLevelDescMap_ = {}; + // different msg may have STAT_EVENT_MAX types of exception when parse, and they have different error level + // if you think some error level should be improve or depress, you can edit this map + std::map> eventParserStatSeverityDescMap_ = {}; + // process mem info desc + std::map memNameMap_ = {}; + // sys memorty info desc + std::map sysMemNameMap_ = {}; + // sys virtual memorty info desc + std::map sysVirtualMemNameMap_ = {}; + +private: + void InitEventNameMap(); + void InitSysMemMap(); + void InitSysVmemMap(); + void InitSecurityMap(); + // all supported events should be defined here, these str can be find in text-based trace + const std::string TRACE_ACTION_BINDER_TRANSACTION = "binder_transaction"; + const std::string TRACE_ACTION_BINDER_TRANSACTION_RECEIVED = "binder_transaction_received"; + const std::string TRACE_ACTION_SCHED_SWITCH = "sched_switch"; + const std::string TRACE_ACTION_TASK_RENAME = "task_rename"; + const std::string TRACE_ACTION_TASK_NEWTASK = "task_newtask"; + const std::string TRACE_ACTION_TRACING_MARK_WRITE = "tracing_mark_write"; + const std::string TRACE_ACTION_PRINT = "print"; + const std::string TRACE_ACTION_SCHED_WAKEUP = "sched_wakeup"; + const std::string TRACE_ACTION_SCHED_WAKING = "sched_waking"; + const std::string TRACE_ACTION_CPU_IDLE = "cpu_idle"; + const std::string TRACE_ACTION_CPU_FREQUENCY = "cpu_frequency"; + const std::string TRACE_ACTION_SUSPEND_RESUME = "suspend_resume"; + const std::string TRACE_ACTION_WORKQUEUE_EXECUTE_START = "workqueue_execute_start"; + const std::string TRACE_ACTION_WORKQUEUE_EXECUTE_END = "workqueue_execute_end"; + + const std::string TRACE_ACTION_CLOCK_SET_RATE = "clock_set_rate"; + const std::string TRACE_ACTION_CLOCK_ENABLE = "clock_enable"; + const std::string TRACE_ACTION_CLOCK_DISABLE = "clock_disable"; + const std::string TRACE_ACTION_CLK_SET_RATE = "clk_set_rate"; + const std::string TRACE_ACTION_CLK_ENABLE = "clk_enable"; + const std::string TRACE_ACTION_CLK_DISABLE = "clk_disable"; + const std::string TRACE_ACTION_SYS_ENTRY = "sys_enter"; + const std::string TRACE_ACTION_SYS_EXIT = "sys_exit"; + const std::string TRACE_ACTION_OOM_SCORE_ADJ_UPDATE = "oom_score_adj_update"; + const std::string TRACE_ACTION_REGULATOR_SET_VOLTAGE = "regulator_set_voltage"; + const std::string TRACE_ACTION_REGULATOR_SET_VOLTAGE_COMPLETE = "regulator_set_voltage_complete"; + const std::string TRACE_ACTION_REGULATOR_DISABLE = "regulator_disable"; + const std::string TRACE_ACTION_REGULATOR_DISABLE_COMPLETE = "regulator_disable_complete"; + const std::string TRACE_ACTION_IPI_ENTRY = "ipi_entry"; + const std::string TRACE_ACTION_IPI_EXIT = "ipi_exit"; + const std::string TRACE_ACTION_IRQ_HANDLER_ENTRY = "irq_handler_entry"; + const std::string TRACE_ACTION_IRQ_HANDLER_EXIT = "irq_handler_exit"; + const std::string TRACE_ACTION_SOFTIRQ_RAISE = "softirq_raise"; + const std::string TRACE_ACTION_SOFTIRQ_ENTRY = "softirq_entry"; + const std::string TRACE_ACTION_SOFTIRQ_EXIT = "softirq_exit"; + const std::string TRACE_ACTION_BINDER_TRANSACTION_ALLOC_BUF = "binder_transaction_alloc_buf"; + const std::string TRACE_ACTION_BINDER_TRANSACTION_LOCK = "binder_transaction_lock"; + const std::string TRACE_ACTION_BINDER_TRANSACTION_LOCKED = "binder_transaction_locked"; + const std::string TRACE_ACTION_BINDER_TRANSACTION_UNLOCK = "binder_transaction_unlock"; + const std::string TRACE_ACTION_SCHED_WAKEUP_NEW = "sched_wakeup_new"; + const std::string TRACE_ACTION_PROCESS_EXIT = "sched_process_exit"; + const std::string TRACE_ACTION_PROCESS_FREE = "sched_process_free"; + const std::string TRACE_ACTION_CLOCK_SYNC = "trace_event_clock_sync"; + const std::string TRACE_ACTION_MEMORY = "memory"; + const std::string TRACE_ACTION_HILOG = "hilog"; + const std::string TRACE_ACTION_HIDUMP_FPS = "hidump_fps"; + const std::string TRACE_ACTION_NATIVE_HOOK_MALLOC = "native_hook_malloc"; + const std::string TRACE_ACTION_NATIVE_HOOK_FREE = "native_hook_free"; + const std::string TRACE_ACTION_SIGNAL_GENERATE = "signal_generate"; + const std::string TRACE_ACTION_SIGNAL_DELIVER = "signal_deliver"; + const std::string TRACE_ACTION_BLOCK_BIO_BACKMERGE = "trace_block_bio_backmerge"; + const std::string TRACE_ACTION_BLOCK_BIO_BOUNCE = "trace_block_bio_bounce"; + const std::string TRACE_ACTION_BLOCK_BIO_COMPLETE = "trace_block_bio_complete"; + const std::string TRACE_ACTION_BLOCK_BIO_FRONTMERGE = "trace_block_bio_frontmerge"; + const std::string TRACE_ACTION_BLOCK_BIO_QUEUE = "trace_bblock_bio_queue"; + const std::string TRACE_ACTION_BLOCK_BIO_REMAP = "trace_block_bio_remap"; + const std::string TRACE_ACTION_BLOCK_DIRTY_BUFFER = "trace_block_dirty_buffer"; + const std::string TRACE_ACTION_BLOCK_GETRQ = "trace_block_getrq"; + const std::string TRACE_ACTION_BLOCK_PLUG = "trace_block_plug"; + const std::string TRACE_ACTION_BLOCK_RQ_COMPLETE = "trace_block_rq_complete"; + const std::string TRACE_ACTION_BLOCK_RQ_INSERT = "trace_block_rq_insert"; + const std::string TRACE_ACTION_BLOCK_RQ_REMAP = "trace_block_rq_remap"; + const std::string TRACE_ACTION_BLOCK_RQ_ISSUE = "trace_block_rq_issue"; + + const std::string TRACE_ACTION_SYS_MEMORY = "sys_memory"; + const std::string TRACE_ACTION_SYS_VIRTUAL_MEMORY = "sys_virtual_memory"; + const std::string TRACE_ACTION_OTHER = "other"; + + const std::string MEM_INFO_VM_SIZE_DESC = "mem.vm.size"; + const std::string MEM_INFO_LOCKED_DESC = "mem.locked"; + const std::string MEM_INFO_RSS_DESC = "mem.rss"; + const std::string MEM_INFO_RSS_ANON_DESC = "mem.rss.anon"; + const std::string MEM_INFO_RSS_FILE_DESC = "mem.rss.file"; + const std::string MEM_INFO_RSS_SCHEM_DESC = "mem.rss.schem"; + const std::string MEM_INFO_SWAP_DESC = "mem.swap"; + const std::string MEM_INFO_VIRT_DESC = "mem.virt"; + const std::string MEM_INFO_HWM_DESC = "mem.hwm"; + const std::string MEM_INFO_SCORE_ADJ_DESC = "mm.oom_score_adj"; + + const std::string SYS_MEMINFO_UNSPECIFIED_DESC = "sys.mem.unspecified"; + const std::string SYS_MEMINFO_MEM_TOTAL_DESC = "sys.mem.total"; + const std::string SYS_MEMINFO_MEM_FREE_DESC = "sys.mem.free"; + const std::string SYS_MEMINFO_MEM_AVAILABLE_DESC = "sys.mem.avaiable"; + const std::string SYS_MEMINFO_BUFFERS_DESC = "sys.mem.buffers"; + const std::string SYS_MEMINFO_CACHED_DESC = "sys.mem.cached"; + const std::string SYS_MEMINFO_SWAP_CACHED_DESC = "sys.mem.swap.chard"; + const std::string SYS_MEMINFO_ACTIVE_DESC = "sys.mem.active"; + const std::string SYS_MEMINFO_INACTIVE_DESC = "sys.mem.inactive"; + const std::string SYS_MEMINFO_ACTIVE_ANON_DESC = "sys.mem.active.anon"; + const std::string SYS_MEMINFO_INACTIVE_ANON_DESC = "sys.mem.inactive.anon"; + const std::string SYS_MEMINFO_ACTIVE_FILE_DESC = "sys.mem.active_file"; + const std::string SYS_MEMINFO_INACTIVE_FILE_DESC = "sys.mem.inactive_file"; + const std::string SYS_MEMINFO_UNEVICTABLE_DESC = "sys.mem.unevictable"; + const std::string SYS_MEMINFO_MLOCKED_DESC = "sys.mem.mlocked"; + const std::string SYS_MEMINFO_SWAP_TOTAL_DESC = "sys.mem.swap.total"; + const std::string SYS_MEMINFO_SWAP_FREE_DESC = "sys.mem.swap.free"; + const std::string SYS_MEMINFO_DIRTY_DESC = "sys.mem.dirty"; + const std::string SYS_MEMINFO_WRITEBACK_DESC = "sys.mem.writeback"; + const std::string SYS_MEMINFO_ANON_PAGES_DESC = "sys.mem.anon.pages"; + const std::string SYS_MEMINFO_MAPPED_DESC = "sys.mem.mapped"; + const std::string SYS_MEMINFO_SHMEM_DESC = "sys.mem.shmem"; + const std::string SYS_MEMINFO_SLAB_DESC = "sys.mem.slab"; + const std::string SYS_MEMINFO_SLAB_RECLAIMABLE_DESC = "sys.mem.slab.reclaimable"; + const std::string SYS_MEMINFO_SLAB_UNRECLAIMABLE_DESC = "sys.mem.slab.unreclaimable"; + const std::string SYS_MEMINFO_KERNEL_STACK_DESC = "sys.mem.kernel.stack"; + const std::string SYS_MEMINFO_PAGE_TABLES_DESC = "sys.mem.page.tables"; + const std::string SYS_MEMINFO_COMMIT_LIMIT_DESC = "sys.mem.commit.limit"; + const std::string SYS_MEMINFO_COMMITED_AS_DESC = "sys.mem.commited.as"; + const std::string SYS_MEMINFO_VMALLOC_TOTAL_DESC = "sys.mem.vmalloc.total"; + const std::string SYS_MEMINFO_VMALLOC_USED_DESC = "sys.mem.vmalloc.used"; + const std::string SYS_MEMINFO_VMALLOC_CHUNK_DESC = "sys.mem.vmalloc.chunk"; + const std::string SYS_MEMINFO_CMA_TOTAL_DESC = "sys.mem.cma.total"; + const std::string SYS_MEMINFO_CMA_FREE_DESC = "sys.mem.cma.free"; + const std::string SYS_VMEMINFO_UNSPECIFIED_DESC = "sys.virtual.mem.unspecified"; + const std::string SYS_VMEMINFO_NR_FREE_PAGES_DESC = "sys.virtual.mem.nr.free.pages"; + const std::string SYS_VMEMINFO_NR_ALLOC_BATCH_DESC = "sys.virtual.mem.nr.alloc.batch"; + const std::string SYS_VMEMINFO_NR_INACTIVE_ANON_DESC = "sys.virtual.mem.nr.inactive.anon"; + const std::string SYS_VMEMINFO_NR_ACTIVE_ANON_DESC = "sys.virtual.mem.nr.active_anon"; + const std::string SYS_VMEMINFO_NR_INACTIVE_FILE_DESC = "sys.virtual.mem.nr.inactive.file"; + const std::string SYS_VMEMINFO_NR_ACTIVE_FILE_DESC = "sys.virtual.mem.nr.active_file"; + const std::string SYS_VMEMINFO_NR_UNEVICTABLE_DESC = "sys.virtual.mem.nr.unevictable"; + const std::string SYS_VMEMINFO_NR_MLOCK_DESC = "sys.virtual.mem.nr.mlock"; + const std::string SYS_VMEMINFO_NR_ANON_PAGES_DESC = "sys.virtual.mem.anon.pages"; + const std::string SYS_VMEMINFO_NR_MAPPED_DESC = "sys.virtual.mem.nr.mapped"; + const std::string SYS_VMEMINFO_NR_FILE_PAGES_DESC = "sys.virtual.mem.nr.file.pages"; + const std::string SYS_VMEMINFO_NR_DIRTY_DESC = "sys.virtual.mem.nr.dirty"; + const std::string SYS_VMEMINFO_NR_WRITEBACK_DESC = "sys.virtual.mem.nr.writeback"; + const std::string SYS_VMEMINFO_NR_SLAB_RECLAIMABLE_DESC = "sys.virtual.mem.nr.slab.reclaimable"; + const std::string SYS_VMEMINFO_NR_SLAB_UNRECLAIMABLE_DESC = "sys.virtual.mem.nr.slab.unreclaimable"; + const std::string SYS_VMEMINFO_NR_PAGE_TABLE_PAGES_DESC = "sys.virtual.mem.nr.page_table.pages"; + const std::string SYS_VMEMINFO_NR_KERNEL_STACK_DESC = "sys.virtual.mem.nr_kernel.stack"; + const std::string SYS_VMEMINFO_NR_OVERHEAD_DESC = "sys.virtual.mem.nr.overhead"; + const std::string SYS_VMEMINFO_NR_UNSTABLE_DESC = "sys.virtual.mem.nr.unstable"; + const std::string SYS_VMEMINFO_NR_BOUNCE_DESC = "sys.virtual.mem.nr.bounce"; + const std::string SYS_VMEMINFO_NR_VMSCAN_WRITE_DESC = "sys.virtual.mem.nr.vmscan.write"; + const std::string SYS_VMEMINFO_NR_VMSCAN_IMMEDIATE_RECLAIM_DESC = "sys.virtual.mem.nr.vmscan.immediate.reclaim"; + const std::string SYS_VMEMINFO_NR_WRITEBACK_TEMP_DESC = "sys.virtual.mem.nr.writeback_temp"; + const std::string SYS_VMEMINFO_NR_ISOLATED_ANON_DESC = "sys.virtual.mem.nr.isolated_anon"; + const std::string SYS_VMEMINFO_NR_ISOLATED_FILE_DESC = "sys.virtual.mem.nr.isolated_file"; + const std::string SYS_VMEMINFO_NR_SHMEM_DESC = "sys.virtual.mem.nr.shmem"; + const std::string SYS_VMEMINFO_NR_DIRTIED_DESC = "sys.virtual.mem.nr.dirtied"; + const std::string SYS_VMEMINFO_NR_WRITTEN_DESC = "sys.virtual.mem.nr.written"; + const std::string SYS_VMEMINFO_NR_PAGES_SCANNED_DESC = "sys.virtual.mem.nr.pages.scanned"; + const std::string SYS_VMEMINFO_WORKINGSET_REFAULT_DESC = "sys.virtual.mem.workingset.refault"; + const std::string SYS_VMEMINFO_WORKINGSET_ACTIVATE_DESC = "sys.virtual.mem.workingset.activate"; + const std::string SYS_VMEMINFO_WORKINGSET_NODERECLAIM_DESC = "sys.virtual.mem.workingset_nodereclaim"; + const std::string SYS_VMEMINFO_NR_ANON_TRANSPARENT_HUGEPAGES_DESC = "sys.virtual.mem.nr_anon.transparent.hugepages"; + const std::string SYS_VMEMINFO_NR_FREE_CMA_DESC = "sys.virtual.mem.nr.free_cma"; + const std::string SYS_VMEMINFO_NR_SWAPCACHE_DESC = "sys.virtual.mem.nr.swapcache"; + const std::string SYS_VMEMINFO_NR_DIRTY_THRESHOLD_DESC = "sys.virtual.mem.nr.dirty.threshold"; + const std::string SYS_VMEMINFO_NR_DIRTY_BACKGROUND_THRESHOLD_DESC = "sys.virtual.mem.nr.dirty.background.threshold"; + const std::string SYS_VMEMINFO_PGPGIN_DESC = "sys.virtual.mem.vmeminfo.pgpgin"; + const std::string SYS_VMEMINFO_PGPGOUT_DESC = "sys.virtual.mem.pgpgout"; + const std::string SYS_VMEMINFO_PGPGOUTCLEAN_DESC = "sys.virtual.mem.pgpgoutclean"; + const std::string SYS_VMEMINFO_PSWPIN_DESC = "sys.virtual.mem.pswpin"; + const std::string SYS_VMEMINFO_PSWPOUT_DESC = "sys.virtual.mem.pswpout"; + const std::string SYS_VMEMINFO_PGALLOC_DMA_DESC = "sys.virtual.mem.pgalloc.dma"; + const std::string SYS_VMEMINFO_PGALLOC_NORMAL_DESC = "sys.virtual.mem.pgalloc.normal"; + const std::string SYS_VMEMINFO_PGALLOC_MOVABLE_DESC = "sys.virtual.mem.pgalloc.movable"; + const std::string SYS_VMEMINFO_PGFREE_DESC = "sys.virtual.mem.pgfree"; + const std::string SYS_VMEMINFO_PGACTIVATE_DESC = "sys.virtual.mem.pgactivate"; + const std::string SYS_VMEMINFO_PGDEACTIVATE_DESC = "sys.virtual.mem.pgdeactivate"; + const std::string SYS_VMEMINFO_PGFAULT_DESC = "sys.virtual.mem.pgfault"; + const std::string SYS_VMEMINFO_PGMAJFAULT_DESC = "sys.virtual.mem.pgmajfault"; + const std::string SYS_VMEMINFO_PGREFILL_DMA_DESC = "sys.virtual.mem.pgrefill.dma"; + const std::string SYS_VMEMINFO_PGREFILL_NORMAL_DESC = "sys.virtual.mem.pgrefill.normal"; + const std::string SYS_VMEMINFO_PGREFILL_MOVABLE_DESC = "sys.virtual.mem.pgrefill.movable"; + const std::string SYS_VMEMINFO_PGSTEAL_KSWAPD_DMA_DESC = "sys.virtual.mem.pgsteal.kswapd.dma"; + const std::string SYS_VMEMINFO_PGSTEAL_KSWAPD_NORMAL_DESC = "sys.virtual.mem.pgsteal.kswapd.normal"; + const std::string SYS_VMEMINFO_PGSTEAL_KSWAPD_MOVABLE_DESC = "sys.virtual.mem.pgsteal.kswapd.movable"; + const std::string SYS_VMEMINFO_PGSTEAL_DIRECT_DMA_DESC = "sys.virtual.mem.pgsteal.direct.dma"; + const std::string SYS_VMEMINFO_PGSTEAL_DIRECT_NORMAL_DESC = "sys.virtual.mem.pgsteal.direct.normal"; + const std::string SYS_VMEMINFO_PGSTEAL_DIRECT_MOVABLE_DESC = "sys.virtual.mem.pgsteal_direct.movable"; + const std::string SYS_VMEMINFO_PGSCAN_KSWAPD_DMA_DESC = "sys.virtual.mem.pgscan.kswapd.dma"; + const std::string SYS_VMEMINFO_PGSCAN_KSWAPD_NORMAL_DESC = "sys.virtual.mem.pgscan_kswapd.normal"; + const std::string SYS_VMEMINFO_PGSCAN_KSWAPD_MOVABLE_DESC = "sys.virtual.mem.pgscan.kswapd.movable"; + const std::string SYS_VMEMINFO_PGSCAN_DIRECT_DMA_DESC = "sys.virtual.mem.pgscan.direct.dma"; + const std::string SYS_VMEMINFO_PGSCAN_DIRECT_NORMAL_DESC = "sys.virtual.mem.pgscan.direct.normal"; + const std::string SYS_VMEMINFO_PGSCAN_DIRECT_MOVABLE_DESC = "sys.virtual.mem.pgscan.direct.movable"; + const std::string SYS_VMEMINFO_PGSCAN_DIRECT_THROTTLE_DESC = "sys.virtual.mem.pgscan.direct.throttle"; + const std::string SYS_VMEMINFO_PGINODESTEAL_DESC = "sys.virtual.mem.pginodesteal"; + const std::string SYS_VMEMINFO_SLABS_SCANNED_DESC = "sys.virtual.mem.slabs_scanned"; + const std::string SYS_VMEMINFO_KSWAPD_INODESTEAL_DESC = "sys.virtual.mem.kswapd.inodesteal"; + const std::string SYS_VMEMINFO_KSWAPD_LOW_WMARK_HIT_QUICKLY_DESC = "sys.virtual.mem.kswapd.low.wmark.hit.quickly"; + const std::string SYS_VMEMINFO_KSWAPD_HIGH_WMARK_HIT_QUICKLY_DESC = "sys.virtual.mem.high.wmark.hit.quickly"; + const std::string SYS_VMEMINFO_PAGEOUTRUN_DESC = "sys.virtual.mem.pageoutrun"; + const std::string SYS_VMEMINFO_ALLOCSTALL_DESC = "sys.virtual.mem.allocstall"; + const std::string SYS_VMEMINFO_PGROTATED_DESC = "sys.virtual.mem.pgrotated"; + const std::string SYS_VMEMINFO_DROP_PAGECACHE_DESC = "sys.virtual.mem.drop.pagecache"; + const std::string SYS_VMEMINFO_DROP_SLAB_DESC = "sys.virtual.mem.drop.slab"; + const std::string SYS_VMEMINFO_PGMIGRATE_SUCCESS_DESC = "sys.virtual.mem.pgmigrate.success"; + const std::string SYS_VMEMINFO_PGMIGRATE_FAIL_DESC = "sys.virtual.mem.pgmigrate.fail"; + const std::string SYS_VMEMINFO_COMPACT_MIGRATE_SCANNED_DESC = "sys.virtual.mem.compact.migrate.scanned"; + const std::string SYS_VMEMINFO_COMPACT_FREE_SCANNED_DESC = "sys.virtual.mem.compact.free.scanned"; + const std::string SYS_VMEMINFO_COMPACT_ISOLATED_DESC = "sys.virtual.mem.compact.isolated"; + const std::string SYS_VMEMINFO_COMPACT_STALL_DESC = "sys.virtual.mem.compact.stall"; + const std::string SYS_VMEMINFO_COMPACT_FAIL_DESC = "sys.virtual.mem.compact.fail"; + const std::string SYS_VMEMINFO_COMPACT_SUCCESS_DESC = "sys.virtual.mem.compact.success"; + const std::string SYS_VMEMINFO_COMPACT_DAEMON_WAKE_DESC = "sys.virtual.mem.compact.daemon.wake"; + const std::string SYS_VMEMINFO_UNEVICTABLE_PGS_CULLED_DESC = "sys.virtual.mem.unevictable.pgs.culled"; + const std::string SYS_VMEMINFO_UNEVICTABLE_PGS_SCANNED_DESC = "sys.virtual.mem.unevictable.pgs.scanned"; + const std::string SYS_VMEMINFO_UNEVICTABLE_PGS_RESCUED_DESC = "sys.virtual.mem.unevictable.pgs.rescued"; + const std::string SYS_VMEMINFO_UNEVICTABLE_PGS_MLOCKED_DESC = "sys.virtual.mem.unevictable.pgs.mlocked"; + const std::string SYS_VMEMINFO_UNEVICTABLE_PGS_MUNLOCKED_DESC = "sys.virtual.mem.unevictable.pgs.munlocked"; + const std::string SYS_VMEMINFO_UNEVICTABLE_PGS_CLEARED_DESC = "sys.virtual.mem.unevictable.pgs.cleared"; + const std::string SYS_VMEMINFO_UNEVICTABLE_PGS_STRANDED_DESC = "sys.virtual.mem.unevictable.pgs.stranded"; + const std::string SYS_VMEMINFO_NR_ZSPAGES_DESC = "sys.virtual.mem.nr.zspages"; + const std::string SYS_VMEMINFO_NR_ION_HEAP_DESC = "sys.virtual.mem.nr.ion.heap"; + const std::string SYS_VMEMINFO_NR_GPU_HEAP_DESC = "sys.virtual.mem.nr.gpu.heap"; + const std::string SYS_VMEMINFO_ALLOCSTALL_DMA_DESC = "sys.virtual.mem.allocstall.dma"; + const std::string SYS_VMEMINFO_ALLOCSTALL_MOVABLE_DESC = "sys.virtual.mem.allocstall.movable"; + const std::string SYS_VMEMINFO_ALLOCSTALL_NORMAL_DESC = "sys.virtual.mem.allocstall.normal"; + const std::string SYS_VMEMINFO_COMPACT_DAEMON_FREE_SCANNED_DESC = "sys.virtual.mem.compact_daemon.free.scanned"; + const std::string SYS_VMEMINFO_COMPACT_DAEMON_MIGRATE_SCANNED_DESC = + "sys.virtual.mem.compact.daemon.migrate.scanned"; + const std::string SYS_VMEMINFO_NR_FASTRPC_DESC = "sys.virtual.mem.nr.fastrpc"; + const std::string SYS_VMEMINFO_NR_INDIRECTLY_RECLAIMABLE_DESC = "sys.virtual.mem.nr.indirectly.reclaimable"; + const std::string SYS_VMEMINFO_NR_ION_HEAP_POOL_DESC = "sys.virtual.mem.nr_ion_heap_pool"; + const std::string SYS_VMEMINFO_NR_KERNEL_MISC_RECLAIMABLE_DESC = "sys.virtual.mem.nr.kernel_misc.reclaimable"; + const std::string SYS_VMEMINFO_NR_SHADOW_CALL_STACK_BYTES_DESC = "sys.virtual.mem.nr.shadow_call.stack_bytes"; + const std::string SYS_VMEMINFO_NR_SHMEM_HUGEPAGES_DESC = "sys.virtual.mem.nr.shmem.hugepages"; + const std::string SYS_VMEMINFO_NR_SHMEM_PMDMAPPED_DESC = "sys.virtual.mem.nr.shmem.pmdmapped"; + const std::string SYS_VMEMINFO_NR_UNRECLAIMABLE_PAGES_DESC = "sys.virtual.mem.nr.unreclaimable.pages"; + const std::string SYS_VMEMINFO_NR_ZONE_ACTIVE_ANON_DESC = "sys.virtual.mem.nr.zone.active.anon"; + const std::string SYS_VMEMINFO_NR_ZONE_ACTIVE_FILE_DESC = "sys.virtual.mem.nr.zone.active.file"; + const std::string SYS_VMEMINFO_NR_ZONE_INACTIVE_ANON_DESC = "sys.virtual.mem.nr.zone.inactive_anon"; + const std::string SYS_VMEMINFO_NR_ZONE_INACTIVE_FILE_DESC = "sys.virtual.mem.nr.zone.inactive_file"; + const std::string SYS_VMEMINFO_NR_ZONE_UNEVICTABLE_DESC = "sys.virtual.mem.nr.zone.unevictable"; + const std::string SYS_VMEMINFO_NR_ZONE_WRITE_PENDING_DESC = "sys.virtual.mem.nr.zone.write_pending"; + const std::string SYS_VMEMINFO_OOM_KILL_DESC = "sys.virtual.mem.oom.kill"; + const std::string SYS_VMEMINFO_PGLAZYFREE_DESC = "sys.virtual.mem.pglazyfree"; + const std::string SYS_VMEMINFO_PGLAZYFREED_DESC = "sys.virtual.mem.pglazyfreed"; + const std::string SYS_VMEMINFO_PGREFILL_DESC = "sys.virtual.mem.pgrefill"; + const std::string SYS_VMEMINFO_PGSCAN_DIRECT_DESC = "sys.virtual.mem.pgscan.direct"; + const std::string SYS_VMEMINFO_PGSCAN_KSWAPD_DESC = "sys.virtual.mem.pgscan.kswapd"; + const std::string SYS_VMEMINFO_PGSKIP_DMA_DESC = "sys.virtual.mem.pgskip.dma"; + const std::string SYS_VMEMINFO_PGSKIP_MOVABLE_DESC = "sys.virtual.mem.pgskip.movable"; + const std::string SYS_VMEMINFO_PGSKIP_NORMAL_DESC = "sys.virtual.mem.pgskip.normal"; + const std::string SYS_VMEMINFO_PGSTEAL_DIRECT_DESC = "sys.virtual.mem.pgsteal.direct"; + const std::string SYS_VMEMINFO_PGSTEAL_KSWAPD_DESC = "sys.virtual.mem.pgsteal.kswapd"; + const std::string SYS_VMEMINFO_SWAP_RA_DESC = "sys.virtual.mem.swap.ra"; + const std::string SYS_VMEMINFO_SWAP_RA_HIT_DESC = "sys.virtual.mem.swap.ra.hit"; + const std::string SYS_VMEMINFO_WORKINGSET_RESTORE_DESC = "sys.virtual.mem.workingset.restore"; + + const std::string TRACE_STAT_TYPE_RECEIVED_DESC = "received"; + const std::string TRACE_STAT_TYPE_LOST_DESC = "data_lost"; + const std::string TRACE_STAT_TYPE_NOTMATCH_DESC = "not_match"; + const std::string TRACE_STAT_TYPE_NOTSUPPORTED_DESC = "not_supported"; + const std::string TRACE_STAT_TYPE_DATA_INVALID_DESC = "invalid_data"; + + const std::string STAT_SEVERITY_LEVEL_INFO_DESC = "info"; + const std::string STAT_SEVERITY_LEVEL_WARN_DESC = "warn"; + const std::string STAT_SEVERITY_LEVEL_ERROR_DESC = "error"; + const std::string STAT_SEVERITY_LEVEL_FATAL_DESC = "fatal"; +}; +} // namespace TRACE_STREAMER_CONFIG_H +} // namespace SysTuning +#endif diff --git a/host/trace_streamer/src/ext/BUILD.gn b/host/trace_streamer/src/ext/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..09643024743e6ad5e9a3aa9cb7d33317d975534d --- /dev/null +++ b/host/trace_streamer/src/ext/BUILD.gn @@ -0,0 +1,25 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +config("sqlite_config") { + include_dirs = [ + "../../third_party/sqlite/include", + "../include", + ] + cflags = [ "-Wno-writable-strings" ] +} +source_set("sqliteext") { + sources = [ "sqlite_ext_funcs.cpp" ] + public_configs = [ ":sqlite_config" ] +} diff --git a/host/trace_streamer/src/ext/sqlite_ext.pri b/host/trace_streamer/src/ext/sqlite_ext.pri new file mode 100644 index 0000000000000000000000000000000000000000..6d1a82c69bc447f9b6b9260de2aaa6a427c8a0cb --- /dev/null +++ b/host/trace_streamer/src/ext/sqlite_ext.pri @@ -0,0 +1,16 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +SOURCES += $$PWD/sqlite_ext_funcs.cpp +HEADERS += $$PWD/sqlite_ext_funcs.h +INCLUDEPATH += $$PWD/../../third_party/sqlite/include, + $$PWD/../include \ No newline at end of file diff --git a/host/trace_streamer/src/ext/sqlite_ext_funcs.cpp b/host/trace_streamer/src/ext/sqlite_ext_funcs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..680e61e625ebd95022bf552d6a88a255f345e76d --- /dev/null +++ b/host/trace_streamer/src/ext/sqlite_ext_funcs.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "sqlite_ext_funcs.h" +#include +#include "log.h" +#include "sqlite3.h" +/* +** Return a stdev value +*/ +static void sqliteExtStdevFinalize(sqlite3_context* context) +{ + StdevCtx* ptr = static_cast(sqlite3_aggregate_context(context, 0)); + if (ptr && ptr->cntValue > 1) { + sqlite3_result_double(context, sqrt(ptr->rSValue / (ptr->cntValue - 1))); + } else { + sqlite3_result_double(context, 0.0); + } +} +/* +** called each value received during a calculation of stdev or variance +*/ +static void sqliteExtStdevNextStep(sqlite3_context* context, int argc, sqlite3_value** argv) +{ + double deltaValue; + double x; + + TS_ASSERT(argc == 1); + StdevCtx* ptr = static_cast(sqlite3_aggregate_context(context, sizeof(StdevCtx))); + if (SQLITE_NULL != sqlite3_value_numeric_type(argv[0])) { + ptr->cntValue++; + x = sqlite3_value_double(argv[0]); + deltaValue = (x - ptr->rMValue); + ptr->rMValue += deltaValue / ptr->cntValue; + ptr->rSValue += deltaValue * (x - ptr->rMValue); + } +} + +void CreateExtendFunction(sqlite3* db) +{ + sqlite3_create_function(db, "stdev", 1, SQLITE_UTF8, nullptr, 0, sqliteExtStdevNextStep, + sqliteExtStdevFinalize); +} \ No newline at end of file diff --git a/host/trace_streamer/src/ext/sqlite_ext_funcs.h b/host/trace_streamer/src/ext/sqlite_ext_funcs.h new file mode 100644 index 0000000000000000000000000000000000000000..b75925f45b8234e7a7c6c5770e202196e0ce5ca2 --- /dev/null +++ b/host/trace_streamer/src/ext/sqlite_ext_funcs.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SQLITE_EXT_FUNCS_H +#define SQLITE_EXT_FUNCS_H 1 +#include +#include "sqlite3.h" + +typedef struct StdevCtx StdevCtx; +struct StdevCtx { + double rMValue; + double rSValue; + int64_t cntValue; +}; +void CreateExtendFunction(sqlite3* db); +#endif diff --git a/host/trace_streamer/src/filter/args_filter.cpp b/host/trace_streamer/src/filter/args_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ad2e2edd2be3587caf31d51796d54800a058afe --- /dev/null +++ b/host/trace_streamer/src/filter/args_filter.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "args_filter.h" +#include "filter_filter.h" +#include "log.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +ArgsFilter::ArgsFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) : FilterBase(dataCache, filter) +{ + traceDataCache_->GetDataTypeData()->AppendNewDataType(BASE_DATA_TYPE_INT, traceDataCache_->GetDataIndex("int")); + traceDataCache_->GetDataTypeData()->AppendNewDataType(BASE_DATA_TYPE_STRING, + traceDataCache_->GetDataIndex("string")); + traceDataCache_->GetDataTypeData()->AppendNewDataType(BASE_DATA_TYPE_DOUBLE, + traceDataCache_->GetDataIndex("double")); + traceDataCache_->GetDataTypeData()->AppendNewDataType(BASE_DATA_TYPE_BOOLEAN, + traceDataCache_->GetDataIndex("boolean")); +} + +ArgsFilter::~ArgsFilter() {} + +uint32_t ArgsFilter::NewArgs(const ArgsSet& args) +{ + auto argSet = traceDataCache_->GetArgSetData(); + for (auto it = args.valuesMap_.begin(); it != args.valuesMap_.end(); it++) { + argSet->AppendNewArg(it->first, it->second.type, it->second.value, count_); + } + count_++; + return count_ - 1; +} +uint32_t ArgsFilter::AppendArgs(const ArgsSet& args, const size_t argSetId) +{ + auto argSet = traceDataCache_->GetArgSetData(); + for (auto it = args.valuesMap_.begin(); it != args.valuesMap_.end(); it++) { + argSet->AppendNewArg(it->first, it->second.type, it->second.value, argSetId); + } + return count_ - 1; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/args_filter.h b/host/trace_streamer/src/filter/args_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..1b87d43b43fd230d6c3e00c961728c3732f98358 --- /dev/null +++ b/host/trace_streamer/src/filter/args_filter.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ARGS_FILTER_H +#define ARGS_FILTER_H + +#include +#include +#include + +#include "args_set.h" +#include "double_map.h" +#include "filter_base.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +class ArgsFilter : private FilterBase { +public: + ArgsFilter(TraceDataCache*, const TraceStreamerFilters*); + ArgsFilter(const ArgsFilter&) = delete; + ArgsFilter& operator=(const ArgsFilter&) = delete; + ~ArgsFilter() override; + uint32_t NewArgs(const ArgsSet& args); + uint32_t AppendArgs(const ArgsSet& args, const size_t argSetId); + int count_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // ARGS_FILTER_H diff --git a/host/trace_streamer/src/filter/binder_filter.cpp b/host/trace_streamer/src/filter/binder_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b13ad8edea336e800a48b66de7adfefd88222d7a --- /dev/null +++ b/host/trace_streamer/src/filter/binder_filter.cpp @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "binder_filter.h" +#include "measure_filter.h" +#include "process_filter.h" +#include "slice_filter.h" +#include "stat_filter.h" +#include "string_to_numerical.h" +namespace SysTuning { +namespace TraceStreamer { +BinderFilter::BinderFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : FilterBase(dataCache, filter) +{ + binderFlagDescs_ = {{noReturnMsgFlag_, " this is a one-way call: async, no return; "}, + {rootObjectMsgFlag_, " contents are the components root object; "}, + {statusCodeMsgFlag_, " contents are a 32-bit status code; "}, + {acceptFdsMsgFlag_, " allow replies with file descriptors; "}, + {noFlagsMsgFlag_, " No Flags Set"}}; +} +BinderFilter::~BinderFilter() = default; + +std::string BinderFilter::GetBinderFlagsDesc(uint32_t flag) +{ + std::string str; + if (flag & noReturnMsgFlag_) { + str += binderFlagDescs_.at(noReturnMsgFlag_); + } + if (flag & rootObjectMsgFlag_) { + str += binderFlagDescs_.at(rootObjectMsgFlag_); + } + if (flag & statusCodeMsgFlag_) { + str += binderFlagDescs_.at(statusCodeMsgFlag_); + } + if (flag & acceptFdsMsgFlag_) { + str += binderFlagDescs_.at(acceptFdsMsgFlag_); + } + if (flag == noFlagsMsgFlag_) { + str += binderFlagDescs_.at(noFlagsMsgFlag_); + } + return str; +} +void BinderFilter::MaybeDealEvent() +{ + if (tsBinderEventQueue_.size() > MAX_CACHE_SIZE) { + DealEvent(tsBinderEventQueue_.begin()->second.get()); + tsBinderEventQueue_.erase(tsBinderEventQueue_.begin()); + } +} + +void BinderFilter::FinishBinderEvent() +{ + for (auto it = tsBinderEventQueue_.begin(); it != tsBinderEventQueue_.end(); it++) { + DealEvent(it->second.get()); + } + tsBinderEventQueue_.clear(); +} + +void BinderFilter::SendTraction(int64_t ts, + uint32_t tid, + uint64_t transactionId, + int32_t destNode, + int32_t destTgid, + int32_t destTid, + bool isReply, + int32_t flags, + int32_t code) +{ + auto sendTractionEvent = std::make_unique(ts, tid, transactionId, destNode, + destTgid, destTid, isReply, flags, code); + auto binderEvent = std::make_unique(); + binderEvent->type_ = TS_EVENT_BINDER_SEND; + binderEvent->senderBinderEvent_ = std::move(sendTractionEvent); + tsBinderEventQueue_.insert(std::make_pair(ts, std::move(binderEvent))); + MaybeDealEvent(); +} +void BinderFilter::ReceiveTraction(int64_t ts, uint32_t pid, uint64_t transactionId) +{ + auto receiveTractionEvent = std::make_unique(ts, pid, transactionId); + auto binderEvent = std::make_unique(); + binderEvent->type_ = TS_EVENT_BINDER_RECIVED; + binderEvent->receivedBinderEvent_ = std::move(receiveTractionEvent); + tsBinderEventQueue_.insert(std::make_pair(ts, + std::move(binderEvent))); + MaybeDealEvent(); +} +void BinderFilter::TransactionAllocBuf(int64_t ts, uint32_t pid, uint64_t dataSize, uint64_t offsetsSize) +{ + auto tractionAllocBufEvent = std::make_unique(ts, pid, dataSize, offsetsSize); + auto binderEvent = std::make_unique(); + binderEvent->type_ = TS_EVENT_BINDER_ALLOC_BUF; + binderEvent->binderAllocBufEvent_ = std::move(tractionAllocBufEvent); + tsBinderEventQueue_.insert(std::make_pair(ts, + std::move(binderEvent))); + MaybeDealEvent(); +} +void BinderFilter::TractionLock(int64_t ts, uint32_t pid, const std::string& tag) +{ + auto tractionLockEvent = std::make_unique(ts, pid, tag); + auto binderEvent = std::make_unique(); + binderEvent->type_ = TS_EVENT_BINDER_LOCK; + binderEvent->binderLockEvent_ = std::move(tractionLockEvent); + tsBinderEventQueue_.insert(std::make_pair(ts, + std::move(binderEvent))); + MaybeDealEvent(); +} +void BinderFilter::TractionLocked(int64_t ts, uint32_t pid, const std::string& tag) +{ + auto tractionLockedEvent = std::make_unique(ts, pid, tag); + auto binderEvent = std::make_unique(); + binderEvent->type_ = TS_EVENT_BINDER_LOCKED; + binderEvent->binderLockedEvent_ = std::move(tractionLockedEvent); + tsBinderEventQueue_.insert(std::make_pair(ts, + std::move(binderEvent))); + MaybeDealEvent(); +} +void BinderFilter::TractionUnlock(int64_t ts, uint32_t pid, const std::string& tag) +{ + auto tractionUnlockEvent = std::make_unique(ts, pid, tag); + auto binderEvent = std::make_unique(); + binderEvent->type_ = TS_EVENT_BINDER_UNLOCK; + binderEvent->binderUnlockEvent_ = std::move(tractionUnlockEvent); + tsBinderEventQueue_.insert(std::make_pair(ts, + std::move(binderEvent))); + MaybeDealEvent(); +} +void BinderFilter::DealEvent(const TSBinderEvent* event) +{ + switch (static_cast(event->type_)) { + case TS_EVENT_BINDER_SEND: + ExecSendTraction(event->senderBinderEvent_->ts_, event->senderBinderEvent_->tid_, + event->senderBinderEvent_->transactionId_, event->senderBinderEvent_->destNode_, + event->senderBinderEvent_->destTgid_, event->senderBinderEvent_->destTid_, + event->senderBinderEvent_->isReply_, event->senderBinderEvent_->flags_, + event->senderBinderEvent_->code_); + break; + case TS_EVENT_BINDER_RECIVED: + ExecReceiveTraction(event->receivedBinderEvent_->ts_, event->receivedBinderEvent_->pid_, + event->receivedBinderEvent_->transactionId_); + break; + case TS_EVENT_BINDER_ALLOC_BUF: + ExecTransactionAllocBuf(event->binderAllocBufEvent_->ts_, event->binderAllocBufEvent_->pid_, + event->binderAllocBufEvent_->dataSize_, event->binderAllocBufEvent_->offsetsSize_); + break; + case TS_EVENT_BINDER_LOCK: + ExecTractionLock(event->binderLockEvent_->ts_, event->binderLockEvent_->pid_, + event->binderLockEvent_->tag_); + break; + case TS_EVENT_BINDER_LOCKED: + ExecTractionLocked(event->binderLockedEvent_->ts_, event->binderLockedEvent_->pid_, + event->binderLockedEvent_->tag_); + break; + case TS_EVENT_BINDER_UNLOCK: + ExecTractionUnlock(event->binderUnlockEvent_->ts_, event->binderUnlockEvent_->pid_, + event->binderUnlockEvent_->tag_); + break; + default: + break; + } +} +void BinderFilter::ExecSendTraction(int64_t ts, + uint32_t tid, + uint64_t transactionId, + int32_t destNode, + int32_t destTgid, + int32_t destTid, + bool isReply, + int32_t flags, + int32_t code) +{ + auto flagsStr = traceDataCache_->GetDataIndex("0x" + base::number(flags, base::INTEGER_RADIX_TYPE_HEX) + + GetBinderFlagsDesc(flags)); + DataIndex codeStr = traceDataCache_->GetDataIndex("0x" + base::number(code, base::INTEGER_RADIX_TYPE_HEX) + + " Java Layer Dependent"); + ArgsSet argsSend; + argsSend.AppendArg(transId_, BASE_DATA_TYPE_INT, transactionId); + argsSend.AppendArg(destNodeId_, BASE_DATA_TYPE_INT, destNode); + argsSend.AppendArg(destProcessId_, BASE_DATA_TYPE_INT, destTgid); + argsSend.AppendArg(isReplayId_, BASE_DATA_TYPE_BOOLEAN, isReply); + argsSend.AppendArg(flagsId_, BASE_DATA_TYPE_STRING, flagsStr); + argsSend.AppendArg(codeId_, BASE_DATA_TYPE_STRING, codeStr); + argsSend.AppendArg(callingTid_, BASE_DATA_TYPE_INT, tid); + + if (isReply) { + // Add dest information to Reply slices, the Begin msg is from TAG-2 + InternalTid dstItid = streamFilters_->processFilter_->UpdateOrCreateThread(ts, destTid); + const auto destThreadName = traceDataCache_->GetConstThreadData(dstItid).nameIndex_; + argsSend.AppendArg(destThreadId_, BASE_DATA_TYPE_INT, destTid); + argsSend.AppendArg(destThreadNameId_, BASE_DATA_TYPE_STRING, destThreadName); + streamFilters_->sliceFilter_->EndBinder(ts, tid, nullStringId_, nullStringId_, argsSend); + transReplyWaitingReply_.insert(transactionId); + return; + } else { + bool needReply = !isReply && !(flags & noReturnMsgFlag_); + if (needReply) { + // transaction needs reply TAG-1 + streamFilters_->sliceFilter_->BeginBinder(ts, tid, binderCatalogId_, transSliceId_, argsSend); + transWaitingRcv_[transactionId] = tid; + } else { + // transaction not need reply + streamFilters_->sliceFilter_->BeginAsyncBinder(ts, tid, binderCatalogId_, transAsyncId_, argsSend); + transNoNeedReply_[transactionId] = argsSend; + } + } +} +void BinderFilter::ExecReceiveTraction(int64_t ts, uint32_t pid, uint64_t transactionId) +{ + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(ts, pid); + const auto threadName = traceDataCache_->GetConstThreadData(internalTid).nameIndex_; + if (transReplyWaitingReply_.count(transactionId)) { + streamFilters_->sliceFilter_->EndBinder(ts, pid); + transReplyWaitingReply_.erase(transactionId); + return; + } + + if (transWaitingRcv_.count(transactionId)) { + // First, begin the reply, the reply will be end in "SendTraction" func, and the isReply will be true, TAG-2 + auto replySliceid = streamFilters_->sliceFilter_->BeginBinder(ts, pid, binderCatalogId_, replyId_); + // Add dest info to the reply + ArgsSet args; + args.AppendArg(destThreadId_, BASE_DATA_TYPE_INT, pid); + args.AppendArg(destThreadNameId_, BASE_DATA_TYPE_STRING, threadName); + if (IsValidUint32(static_cast(replySliceid))) { + args.AppendArg(destSliceId_, BASE_DATA_TYPE_INT, replySliceid); + } + // Add dest args + auto transSliceId = streamFilters_->sliceFilter_->AddArgs(transWaitingRcv_[transactionId], binderCatalogId_, + transSliceId_, args); + + // remeber dest slice-id to the argset form "SendTraction" TAG-1 + ArgsSet replyDestInserter; + if (IsValidUint32(transSliceId)) { + replyDestInserter.AppendArg(destSliceId_, BASE_DATA_TYPE_INT, transSliceId); + } + streamFilters_->sliceFilter_->AddArgs(pid, binderCatalogId_, replyId_, replyDestInserter); + transWaitingRcv_.erase(transactionId); + return; + } + // the code below can be hard to understand, may be a EndBinder will be better + // this problem cna be test after the IDE is finished + if (transNoNeedReply_.count(transactionId)) { + auto args = transNoNeedReply_[transactionId]; + streamFilters_->sliceFilter_->BeginAsyncBinder(ts, pid, binderCatalogId_, asyncRcvId_, args); + transNoNeedReply_.erase(transactionId); + return; + } +} +void BinderFilter::ExecTransactionAllocBuf(int64_t ts, uint32_t pid, uint64_t dataSize, uint64_t offsetsSize) +{ + ArgsSet args; + args.AppendArg(dataSizeId_, BASE_DATA_TYPE_INT, dataSize); + args.AppendArg(dataOffsetSizeId_, BASE_DATA_TYPE_INT, offsetsSize); + streamFilters_->sliceFilter_->AddArgs(pid, binderCatalogId_, transSliceId_, args); + UNUSED(ts); +} +void BinderFilter::ExecTractionLock(int64_t ts, uint32_t pid, const std::string& tag) +{ + lastEventTs_[pid] = ts; + streamFilters_->sliceFilter_->BeginBinder(ts, pid, binderCatalogId_, lockTryId_); +} +void BinderFilter::ExecTractionLocked(int64_t ts, uint32_t pid, const std::string& tag) +{ + if (!lastEventTs_.count(pid)) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_LOCKED, STAT_EVENT_NOTMATCH); + return; + } + streamFilters_->sliceFilter_->EndBinder(ts, pid); + streamFilters_->sliceFilter_->BeginBinder(ts, pid, binderCatalogId_, lockHoldId_); + lastEventTs_.erase(pid); + lastEventTs_[pid] = ts; +} +void BinderFilter::ExecTractionUnlock(int64_t ts, uint32_t pid, const std::string& tag) +{ + if (!lastEventTs_.count(pid)) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_UNLOCK, STAT_EVENT_NOTMATCH); + return; + } + streamFilters_->sliceFilter_->EndBinder(ts, pid); + lastEventTs_.erase(pid); + lastEventTs_[pid] = ts; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/binder_filter.h b/host/trace_streamer/src/filter/binder_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..183338494d511467e6d7cd10076746af57ae281d --- /dev/null +++ b/host/trace_streamer/src/filter/binder_filter.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BINDER_FILTER_H +#define BINDER_FILTER_H + +#include +#include "args_set.h" +#include "filter_base.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" +namespace SysTuning { +namespace TraceStreamer { +class BinderFilter : private FilterBase { +public: + BinderFilter(TraceDataCache*, const TraceStreamerFilters*); + BinderFilter(const BinderFilter&) = delete; + BinderFilter& operator=(const BinderFilter&) = delete; + ~BinderFilter() override; + +public: + void SendTraction(int64_t ts, + uint32_t tid, + uint64_t transactionId, + int32_t destNode, + int32_t destTgid, + int32_t destTid, + bool isReply, + int32_t flags, + int32_t code); + void ReceiveTraction(int64_t ts, uint32_t pid, uint64_t transactionId); + void TransactionAllocBuf(int64_t ts, uint32_t pid, uint64_t dataSize, uint64_t offsetsSize); + void TractionLock(int64_t ts, uint32_t pid, const std::string& tag); + void TractionLocked(int64_t ts, uint32_t pid, const std::string& tag); + void TractionUnlock(int64_t ts, uint32_t pid, const std::string& tag); + void FinishBinderEvent(); + +private: + void MaybeDealEvent(); + + class TSSendTractionEvent { + public: + TSSendTractionEvent(int64_t ts, + uint32_t tid, + uint64_t transactionId, + int32_t destNode, + int32_t destTgid, + int32_t destTid, + bool isReply, + int32_t flags, + int32_t code) + : ts_(ts), + tid_(tid), + transactionId_(transactionId), + destNode_(destNode), + destTgid_(destTgid), + destTid_(destTid), + isReply_(isReply), + flags_(flags), + code_(code) + { + } + ~TSSendTractionEvent() {} + int64_t ts_; + uint32_t tid_; + uint64_t transactionId_; + int32_t destNode_; + int32_t destTgid_; + int32_t destTid_; + bool isReply_; + int32_t flags_; + int32_t code_; + }; + class TSReceiveTractionEvent { + public: + TSReceiveTractionEvent(int64_t ts, uint32_t pid, uint64_t transactionId) + : ts_(ts), pid_(pid), transactionId_(transactionId) + { + } + ~TSReceiveTractionEvent() {} + uint64_t ts_; + uint32_t pid_; + uint64_t transactionId_; + }; + class TSTractionLockEvent { + public: + TSTractionLockEvent(int64_t ts, uint32_t pid, const std::string& tag) : ts_(ts), pid_(pid), tag_(tag) {} + ~TSTractionLockEvent() {} + uint64_t ts_; + uint32_t pid_; + const std::string tag_; + }; + class TSTransactionAllocBufEvent { + public: + TSTransactionAllocBufEvent(int64_t ts, uint32_t pid, uint64_t dataSize, uint64_t offsetsSize) + : ts_(ts), pid_(pid), dataSize_(dataSize), offsetsSize_(offsetsSize) + { + } + ~TSTransactionAllocBufEvent() {} + uint64_t ts_; + uint32_t pid_; + uint64_t dataSize_; + uint64_t offsetsSize_; + }; + enum TSBinderEventType { + TS_EVENT_BINDER_SEND, + TS_EVENT_BINDER_RECIVED, + TS_EVENT_BINDER_ALLOC_BUF, + TS_EVENT_BINDER_LOCK, + TS_EVENT_BINDER_LOCKED, + TS_EVENT_BINDER_UNLOCK + }; + class TSBinderEvent { + public: + TSBinderEvent() {} + ~TSBinderEvent() {} + TSBinderEventType type_; + // us union below will be a good choice + // but union with unique_ptr can bring about runtime error on windows and mac,only work well on linux + std::unique_ptr senderBinderEvent_ = {}; + std::unique_ptr receivedBinderEvent_ = {}; + std::unique_ptr binderAllocBufEvent_ = {}; + std::unique_ptr binderLockEvent_ = {}; + std::unique_ptr binderLockedEvent_ = {}; + std::unique_ptr binderUnlockEvent_ = {}; + }; + void DealEvent(const TSBinderEvent* event); + + void ExecSendTraction(int64_t ts, + uint32_t tid, + uint64_t transactionId, + int32_t destNode, + int32_t destTgid, + int32_t destTid, + bool isReply, + int32_t flags, + int32_t code); + void ExecReceiveTraction(int64_t ts, uint32_t pid, uint64_t transactionId); + void ExecTransactionAllocBuf(int64_t ts, uint32_t pid, uint64_t dataSize, uint64_t offsetsSize); + void ExecTractionLock(int64_t ts, uint32_t pid, const std::string& tag); + void ExecTractionLocked(int64_t ts, uint32_t pid, const std::string& tag); + void ExecTractionUnlock(int64_t ts, uint32_t pid, const std::string& tag); + std::string GetBinderFlagsDesc(uint32_t flag); + bool IsValidUint32(uint32_t value) const + { + return (value != INVALID_UINT32); + } + uint32_t noReturnMsgFlag_ = 0x01; + uint32_t rootObjectMsgFlag_ = 0x04; + uint32_t statusCodeMsgFlag_ = 0x08; + uint32_t acceptFdsMsgFlag_ = 0x10; + uint32_t noFlagsMsgFlag_ = 0; + DataIndex binderCatalogId_ = traceDataCache_->GetDataIndex("binder"); + DataIndex replyId_ = traceDataCache_->GetDataIndex("binder reply"); + DataIndex isReplayId_ = traceDataCache_->GetDataIndex("reply transaction?"); + DataIndex flagsId_ = traceDataCache_->GetDataIndex("flags"); + DataIndex transSliceId_ = traceDataCache_->GetDataIndex("binder transaction"); + DataIndex transId_ = traceDataCache_->GetDataIndex("transaction id"); + DataIndex asyncRcvId_ = traceDataCache_->GetDataIndex("binder async rcv"); + DataIndex codeId_ = traceDataCache_->GetDataIndex("code"); + DataIndex callingTid_ = traceDataCache_->GetDataIndex("calling tid"); + DataIndex destNodeId_ = traceDataCache_->GetDataIndex("destination node"); + DataIndex destThreadId_ = traceDataCache_->GetDataIndex("destination thread"); + DataIndex destThreadNameId_ = traceDataCache_->GetDataIndex("destination name"); + DataIndex destSliceId_ = traceDataCache_->GetDataIndex("destination slice id"); + DataIndex destProcessId_ = traceDataCache_->GetDataIndex("destination process"); + DataIndex transAsyncId_ = traceDataCache_->GetDataIndex("binder transaction async"); + DataIndex lockTryId_ = traceDataCache_->GetDataIndex("binder lock waiting"); + DataIndex lockHoldId_ = traceDataCache_->GetDataIndex("binder lock held"); + DataIndex dataSizeId_ = traceDataCache_->GetDataIndex("data size"); + DataIndex dataOffsetSizeId_ = traceDataCache_->GetDataIndex("offsets size"); + DataIndex nullStringId_ = traceDataCache_->GetDataIndex("null"); + std::unordered_map lastEventTs_ = {}; + std::unordered_set transReplyWaitingReply_ = {}; + std::unordered_map transWaitingRcv_ = {}; + std::unordered_map transNoNeedReply_ = {}; + std::unordered_map binderFlagDescs_ = {}; + std::multimap> tsBinderEventQueue_; + // timestamp of ftrace events from different cpu can be outof order + // keep a cache of ftrace events in memory and keep msg in order + // the value below is the count of msg, maybe you can change it + const size_t MAX_CACHE_SIZE = 10000; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // BINDER_FILTER_H diff --git a/host/trace_streamer/src/filter/clock_filter.cpp b/host/trace_streamer/src/filter/clock_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..392bae50f27a479286229b3d1459d67d879d6127 --- /dev/null +++ b/host/trace_streamer/src/filter/clock_filter.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "clock_filter.h" +#include +#include + +namespace SysTuning { +namespace TraceStreamer { +ClockFilter::ClockFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : FilterBase(dataCache, filter), primaryClock_(BuiltinClocks::TS_CLOCK_BOOTTIME) +{ +} + +ClockFilter::~ClockFilter() {} + +std::string ClockFilter::GenClockKey(ClockId srcClockId, ClockId desClockId) const +{ + std::string ret; + ret += std::to_string(srcClockId); + ret += ","; + ret += std::to_string(desClockId); + return ret; +} + +uint64_t ClockFilter::ToPrimaryTraceTime(ClockId srcClockId, uint64_t srcTs) const +{ + if (srcClockId == primaryClock_) { + return srcTs; + } + return Convert(srcClockId, srcTs, primaryClock_); +} + +uint64_t ClockFilter::Convert(ClockId srcClockId, uint64_t srcTs, ClockId desClockId) const +{ + std::string&& clockKey = GenClockKey(srcClockId, desClockId); + auto keyIt = clockMaps_.find(clockKey); + if (keyIt == clockMaps_.end()) { + return srcTs; + } + + auto tsIt = keyIt->second.upper_bound(srcTs); + if (tsIt != keyIt->second.begin()) { + tsIt--; + } + + if (tsIt->second >= 0) { + return srcTs + static_cast(tsIt->second); + } else { + return srcTs - static_cast(0 - tsIt->second); + } +} + +void ClockFilter::AddConvertClockMap(ClockId srcClockId, ClockId dstClockId, uint64_t srcTs, uint64_t dstTs) +{ + std::string&& clockKey = GenClockKey(srcClockId, dstClockId); + auto keyIt = clockMaps_.find(clockKey); + if (keyIt == clockMaps_.end()) { + ConvertClockMap newConvertMap = {{srcTs, dstTs - srcTs}}; + clockMaps_[clockKey] = newConvertMap; + } else { + clockMaps_[clockKey].insert(std::make_pair(srcTs, dstTs - srcTs)); + } +} + +void ClockFilter::AddClockSnapshot(const std::vector& snapShot) +{ + ClockId srcId, desId; + for (srcId = 0; srcId < snapShot.size() - 1; srcId++) { + for (desId = srcId + 1; desId < snapShot.size(); desId++) { + ClockId srcClockId = snapShot[srcId].clockId; + ClockId desClockId = snapShot[desId].clockId; + uint64_t srcTs = snapShot[srcId].ts; + uint64_t desTs = snapShot[desId].ts; + + AddConvertClockMap(srcClockId, desClockId, srcTs, desTs); + AddConvertClockMap(desClockId, srcClockId, desTs, srcTs); + } + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/clock_filter.h b/host/trace_streamer/src/filter/clock_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..6d8e29db686a76fc0d45e8e75048c224da7851a3 --- /dev/null +++ b/host/trace_streamer/src/filter/clock_filter.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CLOCK_FILTER_H +#define CLOCK_FILTER_H + +#include +#include +#include +#include +#include "filter_base.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +/* + * TS_REALTIME: A settable system-wide clock that measures real time. Its time represents seconds and nanoseconds + * since the Epoch. + * TS_REALTIME_COARSE: A faster but less precise version of TS_REALTIME. This clock is not settable. + * TS_MONOTONIC: The number of seconds that the system has been running since it was booted.The CLOCK_MONOTONIC + * clock is not affected by discontinuous jumps in the system time ,but is affected by the incremental adjustments + * performed by adjtime(3) and NTP. This clock does not count time that the system is suspended. + * TS_MONOTONIC_COARSE: A faster but less precise version of TS_MONOTONIC. + * TS_MONOTONIC_RAW: Similar to TS_MONOTONIC, but provides access to a raw hardware-based time that is not subject + * to NTP adjustments or the incremental adjustments performed by adjtime(3). This clock does not count time that the + * system is suspended. + * TS_BOOTTIME: A nonsettable system-wide clock that is identical to TS_MONOTONIC, except that it also includes + * any time that the system is suspended. + */ + +using ClockId = uint32_t; +struct SnapShot { + ClockId clockId; + uint64_t ts; +}; +class ClockFilter : private FilterBase { +public: + using ConvertClockMap = std::map; + + ClockFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + ~ClockFilter() override; + + void SetPrimaryClock(ClockId primary) + { + primaryClock_ = primary; + } + uint64_t ToPrimaryTraceTime(ClockId srcClockId, uint64_t srcTs) const; + uint64_t Convert(ClockId srcClockId, uint64_t srcTs, ClockId desClockId) const; + void AddClockSnapshot(const std::vector& snapShot); + +private: + std::string GenClockKey(ClockId srcClockId, ClockId desClockId) const; + void AddConvertClockMap(ClockId srcClockId, ClockId dstClockId, uint64_t srcTs, uint64_t dstTs); + +private: + std::unordered_map clockMaps_ = {}; + + ClockId primaryClock_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // CLOCK_FILTER_H diff --git a/host/trace_streamer/src/filter/cpu_filter.cpp b/host/trace_streamer/src/filter/cpu_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ce228345836a20d9669d0721a9aac8695de6d62 --- /dev/null +++ b/host/trace_streamer/src/filter/cpu_filter.cpp @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cpu_filter.h" + +namespace SysTuning { +namespace TraceStreamer { +CpuFilter::CpuFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) : FilterBase(dataCache, filter) {} +CpuFilter::~CpuFilter() = default; +void CpuFilter::InsertSwitchEvent(uint64_t ts, + uint64_t cpu, + uint64_t prevPid, + uint64_t prevPior, + uint64_t prevState, + uint64_t nextPid, + uint64_t nextPior) +{ + auto switchEvent = std::make_unique(ts, cpu, prevPid, prevPior, prevState, nextPid, nextPior); + auto cpuEvent = std::make_unique(); + cpuEvent->type_ = TS_EVENT_THREAD_SWITCH; + cpuEvent->switchEvent_ = std::move(switchEvent); + tsCpuEventQueue_.insert(std::make_pair(ts, std::move(cpuEvent))); + MaybeDealEvent(); +} +bool CpuFilter::InsertProcessExitEvent(uint64_t ts, uint64_t cpu, uint64_t pid) +{ + auto processExitEvent = std::make_unique(ts, cpu, pid); + auto cpuEvent = std::make_unique(); + cpuEvent->type_ = TS_EVENT_PROCESS_EXIT; + cpuEvent->processExitEvent_ = std::move(processExitEvent); + tsCpuEventQueue_.insert(std::make_pair(ts, + std::move(cpuEvent))); + MaybeDealEvent(); + return true; +} + +bool CpuFilter::InsertProcessFreeEvent(uint64_t ts, uint64_t pid) +{ + auto processExitEvent = std::make_unique(ts, 0, pid); + auto cpuEvent = std::make_unique(); + cpuEvent->type_ = TS_EVENT_PROCESS_FREE; + cpuEvent->processExitEvent_ = std::move(processExitEvent); + tsCpuEventQueue_.insert(std::make_pair(ts, + std::move(cpuEvent))); + MaybeDealEvent(); + return true; +} +void CpuFilter::InsertWakeupEvent(uint64_t ts, uint64_t internalTid) +{ + auto wakeupEvent = std::make_unique(TSWakeupEvent(ts, internalTid)); + auto cpuEvent = std::make_unique(); + cpuEvent->type_ = TS_EVENT_THREAD_WAKING; + cpuEvent->wakeupEvent_ = std::move(wakeupEvent); + tsCpuEventQueue_.insert(std::make_pair(ts, + std::move(cpuEvent))); + MaybeDealEvent(); +} +uint64_t CpuFilter::RemberInternalTidInStateTable(uint64_t uid, uint64_t row, uint64_t state) +{ + if (internalTidToRowThreadState_.find(uid) != internalTidToRowThreadState_.end()) { + internalTidToRowThreadState_.at(uid) = TPthread{row, state}; + } else { + internalTidToRowThreadState_.insert(std::make_pair(uid, TPthread{row, state})); + } + return 0; +} + +void CpuFilter::MaybeDealEvent() +{ + if (tsCpuEventQueue_.size() > MAX_CACHE_SIZE) { + DealEvent(tsCpuEventQueue_.begin()->second.get()); + tsCpuEventQueue_.erase(tsCpuEventQueue_.begin()); + } +} + +void CpuFilter::DealEvent(const TSCpuEvent* event) +{ + switch (static_cast(event->type_)) { + case TS_EVENT_THREAD_SWITCH: + ExecInsertSwitchEvent(event->switchEvent_->ts_, event->switchEvent_->cpu_, event->switchEvent_->prevPid_, + event->switchEvent_->prevPior_, event->switchEvent_->prevState_, + event->switchEvent_->nextPid_, event->switchEvent_->nextPior_); + break; + case TS_EVENT_THREAD_WAKING: + ExecInsertWakeupEvent(event->wakeupEvent_->ts_, event->wakeupEvent_->pid_); + break; + case TS_EVENT_PROCESS_EXIT: + case TS_EVENT_PROCESS_FREE: + ExecInsertProcessExitEvent(event->processExitEvent_->ts_, event->processExitEvent_->cpu_, + event->processExitEvent_->pid_); + break; + default: + break; + } +} +void CpuFilter::FinishCpuEvent() +{ + for (auto it = tsCpuEventQueue_.begin(); it != tsCpuEventQueue_.end(); it++) { + DealEvent(it->second.get()); + } + tsCpuEventQueue_.clear(); +} +void CpuFilter::ExecInsertSwitchEvent(uint64_t ts, + uint64_t cpu, + uint64_t prevPid, + uint64_t prevPior, + uint64_t prevState, + uint64_t nextPid, + uint64_t nextPior) +{ + auto index = traceDataCache_->GetSchedSliceData()->AppendSchedSlice(ts, 0, cpu, nextPid, 0, nextPior); + + auto prevTidOnCpu = cpuToRowSched_.find(cpu); + if (prevTidOnCpu != cpuToRowSched_.end()) { + traceDataCache_->GetSchedSliceData()->Update(prevTidOnCpu->second, ts, prevState, prevPior); + cpuToRowSched_.at(cpu) = index; + } else { + cpuToRowSched_.insert(std::make_pair(cpu, index)); + } + + if (nextPid) { + CheckWakeupEvent(nextPid); + auto lastRow = RowOfInternalTidInStateTable(nextPid); + if (lastRow != INVALID_UINT64) { + traceDataCache_->GetThreadStateData()->UpdateDuration(lastRow, ts); + } + index = + traceDataCache_->GetThreadStateData()->AppendThreadState(ts, INVALID_UINT64, cpu, nextPid, TASK_RUNNING); + RemberInternalTidInStateTable(nextPid, index, TASK_RUNNING); + if (cpuToRowThreadState_.find(cpu) == cpuToRowThreadState_.end()) { + cpuToRowThreadState_.insert(std::make_pair(cpu, index)); + } else { + cpuToRowThreadState_.at(cpu) = index; + } + } + + if (prevPid) { + CheckWakeupEvent(prevPid); + auto lastRow = RowOfInternalTidInStateTable(prevPid); + if (lastRow != INVALID_UINT64) { + traceDataCache_->GetThreadStateData()->UpdateDuration(lastRow, ts); + } + auto temp = traceDataCache_->GetThreadStateData()->AppendThreadState(ts, INVALID_UINT64, INVALID_UINT64, + prevPid, prevState); + RemberInternalTidInStateTable(prevPid, temp, prevState); + } +} +void CpuFilter::ExecInsertWakeupEvent(uint64_t ts, uint64_t internalTid) +{ + /* repeated wakeup msg may come, we only record last wakeupmsg, and + the wakeup will only insert to DataCache when a sched_switch comes + */ + if (lastWakeUpMsg.find(internalTid) != lastWakeUpMsg.end()) { + lastWakeUpMsg.at(internalTid) = ts; + } else { + lastWakeUpMsg.insert(std::make_pair(internalTid, ts)); + } +} +bool CpuFilter::ExecInsertProcessExitEvent(uint64_t ts, uint64_t cpu, uint64_t pid) +{ + UNUSED(cpu); + auto thread = traceDataCache_->GetThreadData(static_cast(pid)); + if (thread) { + thread->endT_ = ts; + return true; + } + return false; +} +uint64_t CpuFilter::RowOfInternalTidInStateTable(uint64_t uid) const +{ + auto row = internalTidToRowThreadState_.find(uid); + if (row != internalTidToRowThreadState_.end()) { + return (*row).second.row_; + } + return INVALID_UINT64; +} + +uint64_t CpuFilter::StateOfInternalTidInStateTable(uint64_t uid) const +{ + auto row = internalTidToRowThreadState_.find(uid); + if (row != internalTidToRowThreadState_.end()) { + return (*row).second.state_; + } + return TASK_INVALID; +} + +void CpuFilter::CheckWakeupEvent(uint64_t internalTid) +{ + if (lastWakeUpMsg.find(internalTid) == lastWakeUpMsg.end()) { + return; + } + auto ts = lastWakeUpMsg.at(internalTid); + lastWakeUpMsg.erase(internalTid); + uint64_t lastrow = RowOfInternalTidInStateTable(internalTid); + auto lastState = StateOfInternalTidInStateTable(internalTid); + if (lastState == TASK_RUNNING) { + return; + } + if (lastrow != INVALID_UINT64) { + traceDataCache_->GetThreadStateData()->UpdateDuration(lastrow, ts); + } + auto index = traceDataCache_->GetThreadStateData()->AppendThreadState(ts, INVALID_UINT64, INVALID_UINT64, + internalTid, TASK_RUNNABLE); + RemberInternalTidInStateTable(internalTid, index, TASK_RUNNABLE); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/cpu_filter.h b/host/trace_streamer/src/filter/cpu_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..a798a11664ec875ab258bb85f40e24752d228a05 --- /dev/null +++ b/host/trace_streamer/src/filter/cpu_filter.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CPU_FILTER_H +#define CPU_FILTER_H + +#include +#include +#include +#include +#include + +#include "filter_base.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +class TraceStreamerFilters; +class CpuFilter : private FilterBase { +public: + CpuFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + CpuFilter(const CpuFilter&) = delete; + CpuFilter& operator=(const CpuFilter&) = delete; + ~CpuFilter() override; + +public: + void InsertSwitchEvent(uint64_t ts, + uint64_t cpu, + uint64_t prevPid, + uint64_t prevPior, + uint64_t prevState, + uint64_t nextPid, + uint64_t nextPior); + void InsertWakeupEvent(uint64_t ts, uint64_t internalTid); + bool InsertProcessExitEvent(uint64_t ts, uint64_t cpu, uint64_t pid); + bool InsertProcessFreeEvent(uint64_t ts, uint64_t pid); + void FinishCpuEvent(); + +private: + void MaybeDealEvent(); + + class TSSwitchEvent { + public: + TSSwitchEvent(uint64_t ts, + uint64_t cpu, + uint64_t prevPid, + uint64_t prevPior, + uint64_t prevState, + uint64_t nextPid, + uint64_t nextPior) + : ts_(ts), + cpu_(cpu), + prevPid_(prevPid), + prevPior_(prevPior), + prevState_(prevState), + nextPid_(nextPid), + nextPior_(nextPior) + + { + } + ~TSSwitchEvent() {} + uint64_t ts_; + uint64_t cpu_; + uint64_t prevPid_; + uint64_t prevPior_; + uint64_t prevState_; + uint64_t nextPid_; + uint64_t nextPior_; + }; + class TSWakeupEvent { + public: + TSWakeupEvent(uint64_t ts, uint64_t pid) : ts_(ts), pid_(pid) {} + ~TSWakeupEvent() {} + uint64_t ts_; + uint64_t pid_; + }; + class TSProcessExitEvent { + public: + TSProcessExitEvent(uint64_t ts, uint64_t cpu, uint64_t pid) : ts_(ts), cpu_(cpu), pid_(pid) {} + ~TSProcessExitEvent() {} + uint64_t ts_; + uint64_t cpu_; + uint64_t pid_; + }; + enum TSCpuEventType { + TS_EVENT_THREAD_SWITCH, + TS_EVENT_THREAD_WAKING, + TS_EVENT_PROCESS_EXIT, + TS_EVENT_PROCESS_FREE + }; + class TSCpuEvent { + public: + TSCpuEvent() {} + ~TSCpuEvent() {} + TSCpuEventType type_; + // us union below will be a good choice + // but union with unique_ptr can bring about runtime error on windows and mac,only work well on linux + std::unique_ptr switchEvent_ = {}; + std::unique_ptr wakeupEvent_ = {}; + std::unique_ptr processExitEvent_ = {}; + }; + void DealEvent(const TSCpuEvent* event); + void ExecInsertSwitchEvent(uint64_t ts, + uint64_t cpu, + uint64_t prevPid, + uint64_t prevPior, + uint64_t prevState, + uint64_t nextPid, + uint64_t nextPior); + void ExecInsertWakeupEvent(uint64_t ts, uint64_t internalTid); + bool ExecInsertProcessExitEvent(uint64_t ts, uint64_t cpu, uint64_t pid); + void CheckWakeupEvent(uint64_t internalTid); + uint64_t RemberInternalTidInStateTable(uint64_t uid, uint64_t row, uint64_t state = TASK_INVALID); + uint64_t RowOfInternalTidInStateTable(uint64_t uid) const; + uint64_t StateOfInternalTidInStateTable(uint64_t uid) const; + std::multimap> tsCpuEventQueue_; + std::map cpuToRowThreadState_ = {}; + std::map cpuToRowSched_ = {}; + std::map lastWakeUpMsg = {}; + + struct TPthread { + uint64_t row_; + uint64_t state_; + }; + std::map internalTidToRowThreadState_ = {}; + // timestamp of ftrace events from different cpu can be outof order + // keep a cache of ftrace events in memory and keep msg in order + // the value below is the count of msg, maybe you can change it + const size_t MAX_CACHE_SIZE = 10000; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // CPU_FILTER_H diff --git a/host/trace_streamer/src/filter/filter.pri b/host/trace_streamer/src/filter/filter.pri new file mode 100644 index 0000000000000000000000000000000000000000..1de2180993eaf1e2197e3f0ae56f0d02a212d70f --- /dev/null +++ b/host/trace_streamer/src/filter/filter.pri @@ -0,0 +1,43 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +INCLUDEPATH +=$$PWD \ + $$PWD/../cfg +HEADERS += \ + $$PWD/clock_filter.h \ + $$PWD/cpu_filter.h \ + $$PWD/filter_base.h \ + $$PWD/filter_filter.h \ + $$PWD/measure_filter.h \ + $$PWD/process_filter.h \ + $$PWD/slice_filter.h \ + $$PWD/symbols_filter.h \ + $$PWD/stat_filter.h \ + $$PWD/binder_filter.h \ + $$PWD/args_filter.h \ + $$PWD/irq_filter.h \ + $$PWD/system_event_measure_filter.h +SOURCES += \ + $$PWD/clock_filter.cpp \ + $$PWD/cpu_filter.cpp \ + $$PWD/filter_base.cpp \ + $$PWD/filter_filter.cpp \ + $$PWD/measure_filter.cpp \ + $$PWD/process_filter.cpp \ + $$PWD/slice_filter.cpp \ + $$PWD/symbols_filter.cpp \ + $$PWD/stat_filter.cpp \ + $$PWD/binder_filter.cpp \ + $$PWD/args_filter.cpp \ + $$PWD/irq_filter.cpp \ + $$PWD/system_event_measure_filter.cpp diff --git a/host/trace_streamer/src/filter/filter_base.cpp b/host/trace_streamer/src/filter/filter_base.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d3bbcd5b42879f975af15193fce3d312721a2724 --- /dev/null +++ b/host/trace_streamer/src/filter/filter_base.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "filter_base.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +FilterBase::FilterBase(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : streamFilters_(filter), traceDataCache_(dataCache) +{ +} +FilterBase::~FilterBase() = default; +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/filter_base.h b/host/trace_streamer/src/filter/filter_base.h new file mode 100644 index 0000000000000000000000000000000000000000..9704b1ab1e684264ece39b1f1ba16cdc9f1a4b75 --- /dev/null +++ b/host/trace_streamer/src/filter/filter_base.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FILTER_BASE_H +#define FILTER_BASE_H +#include +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" + +#define UNUSED(expr) \ + do { \ + static_cast(expr); \ + } while (0) + +namespace SysTuning { +namespace TraceStreamer { +class FilterBase { +public: + FilterBase(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + FilterBase(const FilterBase&) = delete; + FilterBase& operator=(const FilterBase&) = delete; + virtual ~FilterBase(); + +public: + const TraceStreamerFilters* streamFilters_ = {}; + TraceDataCache* traceDataCache_ = {}; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // FILTER_BASE_H diff --git a/host/trace_streamer/src/filter/filter_filter.cpp b/host/trace_streamer/src/filter/filter_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9d2f4e625ff0a0007f412f4fd35781a2c5030416 --- /dev/null +++ b/host/trace_streamer/src/filter/filter_filter.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "filter_filter.h" + +#include "process_filter.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +FilterFilter::FilterFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : FilterBase(dataCache, filter) {} + +FilterFilter::~FilterFilter() = default; + +uint32_t FilterFilter::AddFilter(std::string type, std::string name, uint64_t arg) +{ + auto filter = traceDataCache_->GetFilterData(); + size_t id = filter->AppendNewFilterData(type, name, arg); + return static_cast(id); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/filter_filter.h b/host/trace_streamer/src/filter/filter_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..cef929bb0a378faa79f4a97cc828ee68e7d56299 --- /dev/null +++ b/host/trace_streamer/src/filter/filter_filter.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FILTER_FILTER_H +#define FILTER_FILTER_H + +#include "filter_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class TraceStreamerFilters; +class FilterFilter : private FilterBase { +public: + FilterFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + FilterFilter(const FilterFilter&) = delete; + FilterFilter& operator=(const FilterFilter&) = delete; + ~FilterFilter() override; + + uint32_t AddFilter(std::string type, std::string name, uint64_t arg); +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // FILTER_FILTER_H diff --git a/host/trace_streamer/src/filter/irq_filter.cpp b/host/trace_streamer/src/filter/irq_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aef7b3cdbf6064334f8baa6eadabcf751788106d --- /dev/null +++ b/host/trace_streamer/src/filter/irq_filter.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "irq_filter.h" +#include "measure_filter.h" +#include "process_filter.h" +#include "slice_filter.h" +#include "string_to_numerical.h" +namespace SysTuning { +namespace TraceStreamer { +IrqFilter::IrqFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) : FilterBase(dataCache, filter) +{ + for (size_t i = 0; i < irqActionNames_.size(); i++) { + irqActionNameIds_.push_back(traceDataCache_->GetDataIndex(irqActionNames_[i])); + } +} +IrqFilter::~IrqFilter() = default; + +void IrqFilter::IrqHandlerEntry(int64_t ts, uint32_t cpu, DataIndex nameId) +{ + streamFilters_->sliceFilter_->IrqHandlerEntry(ts, cpu, irqCatalog_, nameId); +} +void IrqFilter::IrqHandlerExit(int64_t ts, uint32_t cpu, uint32_t ret) +{ + DataIndex irqRet = INVALID_DATAINDEX; + if (ret == 1) { + irqRet = irqHandled_; + } else { + irqRet = irqUnHandled_; + } + ArgsSet args; + args.AppendArg(irqRet_, BASE_DATA_TYPE_STRING, irqRet); + streamFilters_->sliceFilter_->IrqHandlerExit(ts, cpu, args); +} +void IrqFilter::SoftIrqEntry(int64_t ts, uint32_t cpu, uint32_t vec) +{ + if (vec >= irqActionNames_.size()) { + return; + } + streamFilters_->sliceFilter_->SoftIrqEntry(ts, cpu, softIrqCatalog_, irqActionNameIds_[vec]); +} +void IrqFilter::SoftIrqExit(int64_t ts, uint32_t cpu, uint32_t vec) +{ + if (vec >= irqActionNames_.size()) { + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_NOTMATCH); + return; + } + ArgsSet args; + args.AppendArg(irqRet_, BASE_DATA_TYPE_STRING, irqActionNameIds_[vec]); + streamFilters_->sliceFilter_->SoftIrqExit(ts, cpu, args); + return; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/irq_filter.h b/host/trace_streamer/src/filter/irq_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..d13c9b34216721c3f7529b97e58eb2c8402fe239 --- /dev/null +++ b/host/trace_streamer/src/filter/irq_filter.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IRQ_FILTER_H +#define IRQ_FILTER_H + +#include +#include "args_set.h" +#include "filter_base.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" +namespace SysTuning { +namespace TraceStreamer { +class IrqFilter : private FilterBase { +public: + IrqFilter(TraceDataCache*, const TraceStreamerFilters*); + IrqFilter(const IrqFilter&) = delete; + IrqFilter& operator=(const IrqFilter&) = delete; + ~IrqFilter() override; + +public: + void IrqHandlerEntry(int64_t ts, uint32_t cpu, DataIndex nameId); + void IrqHandlerExit(int64_t ts, uint32_t cpu, uint32_t ret); + void SoftIrqEntry(int64_t ts, uint32_t cpu, uint32_t vec); + void SoftIrqExit(int64_t ts, uint32_t cpu, uint32_t vec); + +private: + DataIndex irqId_ = traceDataCache_->GetDataIndex("irq_id"); + DataIndex irqRet_ = traceDataCache_->GetDataIndex("irq_ret"); + DataIndex irqHandled_ = traceDataCache_->GetDataIndex("handled"); + DataIndex irqUnHandled_ = traceDataCache_->GetDataIndex("unhandled"); + DataIndex irqCatalog_ = traceDataCache_->GetDataIndex("irq"); + DataIndex softIrqCatalog_ = traceDataCache_->GetDataIndex("softirq"); + std::unordered_map lastEventTs_ = {}; + std::unordered_set transReplyWaitingReply_ = {}; + std::unordered_map transWaitingRcv_ = {}; + std::unordered_map transNoNeedReply_ = {}; + std::unordered_map binderFlagDescs_ = {}; + std::vector irqActionNames_ = {"HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", + "BLOCK_IOPOLL", "TASKLET", "SCHED", "HRTIMER", "RCU"}; + std::vector irqActionNameIds_ = {}; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // IRQ_FILTER_H diff --git a/host/trace_streamer/src/filter/measure_filter.cpp b/host/trace_streamer/src/filter/measure_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad723fa3c6221a91aa8aaba3407b649d7cb43bb1 --- /dev/null +++ b/host/trace_streamer/src/filter/measure_filter.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "measure_filter.h" +#include "filter_filter.h" +#include "log.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +MeasureFilter::MeasureFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter, FilterType e) + : FilterBase(dataCache, filter), + tidStreamIdFilterIdMap_(INVALID_UINT64), + filterType_(e) +{ +} + +MeasureFilter::~MeasureFilter() {} + +void MeasureFilter::AppendNewMeasureData(uint64_t internalTid, DataIndex nameIndex, uint64_t timestamp, int64_t value) +{ + auto filterId = GetOrCreateFilterId(internalTid, nameIndex); + traceDataCache_->GetMeasureData()->AppendMeasureData(0, timestamp, value, filterId); +} +uint32_t MeasureFilter::GetOrCreateFilterId(uint64_t internalTid, DataIndex nameIndex) +{ + auto filterId = tidStreamIdFilterIdMap_.Find(internalTid, nameIndex); + if (filterId != INVALID_UINT64) { + return static_cast(filterId); + } + + uint32_t newFilterId = streamFilters_->filterFilter_->AddFilter( + filterTypeValue.at(filterType_), traceDataCache_->GetDataFromDict(nameIndex), internalTid); + AddCertainFilterId(internalTid, nameIndex, newFilterId); + return newFilterId; +} + +void MeasureFilter::AddCertainFilterId(uint64_t internalTid, DataIndex nameIndex, uint64_t filterId) +{ + tidStreamIdFilterIdMap_.Insert(internalTid, nameIndex, filterId); + + if (filterType_ == E_THREADMEASURE_FILTER) { + traceDataCache_->GetThreadMeasureFilterData()->AppendNewFilter(filterId, static_cast(nameIndex), + internalTid); + } else if (filterType_ == E_THREAD_FILTER) { + traceDataCache_->GetThreadFilterData()->AppendNewFilter(filterId, static_cast(nameIndex), + internalTid); + } else if (filterType_ == E_PROCESS_MEASURE_FILTER) { + traceDataCache_->GetProcessMeasureFilterData()->AppendNewFilter( + static_cast(filterId), static_cast(nameIndex), static_cast(internalTid)); + } else if (filterType_ == E_PROCESS_FILTER_FILTER) { + traceDataCache_->GetProcessFilterData()->AppendNewFilter( + static_cast(filterId), static_cast(nameIndex), static_cast(internalTid)); + } else if (filterType_ == E_CPU_MEASURE_FILTER) { + traceDataCache_->GetCpuMeasuresData()->AppendNewFilter(filterId, static_cast(nameIndex), internalTid); + } else if (filterType_ == E_CLOCK_RATE_FILTER) { + traceDataCache_->GetClockEventFilterData()->AppendNewFilter(filterId, clockSetRateDataIndex_, + static_cast(nameIndex), internalTid); + } else if (filterType_ == E_CLOCK_ENABLE_FILTER) { + traceDataCache_->GetClockEventFilterData()->AppendNewFilter(filterId, clockEnableDataIndex_, + static_cast(nameIndex), internalTid); + } else if (filterType_ == E_CLOCK_DISABLE_FILTER) { + traceDataCache_->GetClockEventFilterData()->AppendNewFilter(filterId, clockDisableDataIndex_, + static_cast(nameIndex), internalTid); + } else if (filterType_ == E_CLK_RATE_FILTER) { + traceDataCache_->GetClkEventFilterData()->AppendNewFilter(filterId, clkSetRateDataIndex_, + static_cast(nameIndex), internalTid); + } else if (filterType_ == E_CLK_ENABLE_FILTER) { + traceDataCache_->GetClkEventFilterData()->AppendNewFilter(filterId, clkEnableDataIndex_, + static_cast(nameIndex), internalTid); + } else if (filterType_ == E_CLK_DISABLE_FILTER) { + traceDataCache_->GetClkEventFilterData()->AppendNewFilter(filterId, clkDisableDataIndex_, + static_cast(nameIndex), internalTid); + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/measure_filter.h b/host/trace_streamer/src/filter/measure_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..ef8efeb43c229171506b0ef7250786241c2714dc --- /dev/null +++ b/host/trace_streamer/src/filter/measure_filter.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_MEASURE_FILTER_H +#define THREAD_MEASURE_FILTER_H + +#include +#include +#include + +#include "double_map.h" +#include "filter_base.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +enum FilterType { + E_THREADMEASURE_FILTER, + E_THREAD_FILTER, + E_PROCESS_MEASURE_FILTER, + E_PROCESS_FILTER_FILTER, + E_CPU_MEASURE_FILTER, + E_CLOCK_RATE_FILTER, + E_CLOCK_ENABLE_FILTER, + E_CLOCK_DISABLE_FILTER, + E_CLK_RATE_FILTER, + E_CLK_ENABLE_FILTER, + E_CLK_DISABLE_FILTER +}; + +class MeasureFilter : private FilterBase { +public: + MeasureFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter, FilterType); + MeasureFilter(const MeasureFilter&) = delete; + MeasureFilter& operator=(const MeasureFilter&) = delete; + ~MeasureFilter() override; + void AppendNewMeasureData(uint64_t internalTid, DataIndex nameIndex, uint64_t timestamp, int64_t value); + uint32_t GetOrCreateFilterId(uint64_t internalTid, DataIndex nameIndex); +private: + void AddCertainFilterId(uint64_t internalTid, DataIndex nameIndex, uint64_t filterId); + DoubleMap tidStreamIdFilterIdMap_; + FilterType filterType_; + + const std::map filterTypeValue = { + { E_THREADMEASURE_FILTER, "thread_measure_filter" }, + { E_THREAD_FILTER, "thread_measure" }, + { E_PROCESS_MEASURE_FILTER, "process_measure_filter" }, + { E_PROCESS_FILTER_FILTER, "process_filter" }, + { E_CPU_MEASURE_FILTER, "cpu_measure_filter" }, + { E_CLOCK_RATE_FILTER, "clock_rate_filter" }, + { E_CLOCK_ENABLE_FILTER, "clock_enable_filter" }, + { E_CLOCK_DISABLE_FILTER, "clock_disable_filter" }, + { E_CLK_RATE_FILTER, "clk_rate_filter" }, + { E_CLK_ENABLE_FILTER, "clk_enable_filter" }, + { E_CLK_DISABLE_FILTER, "clk_disable_filter" } + }; + DataIndex clockSetRateDataIndex_ = traceDataCache_->GetDataIndex("clock_set_rate"); + DataIndex clockEnableDataIndex_ = traceDataCache_->GetDataIndex("clock_enable"); + DataIndex clockDisableDataIndex_ = traceDataCache_->GetDataIndex("clock_disable"); + DataIndex clkSetRateDataIndex_ = traceDataCache_->GetDataIndex("clk_set_rate"); + DataIndex clkEnableDataIndex_ = traceDataCache_->GetDataIndex("clk_enable"); + DataIndex clkDisableDataIndex_ = traceDataCache_->GetDataIndex("clk_disable"); +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // THREAD_MEASURE_FILTER_H diff --git a/host/trace_streamer/src/filter/process_filter.cpp b/host/trace_streamer/src/filter/process_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0c941f317f02255d214a2b70b272060d08ce64a9 --- /dev/null +++ b/host/trace_streamer/src/filter/process_filter.cpp @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "process_filter.h" +#include +#include +#include +#include + +using CustomPair = std::pair; +namespace SysTuning { +namespace TraceStreamer { +namespace { +const uint32_t INVALID_ID = std::numeric_limits::max(); +} +ProcessFilter::ProcessFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : FilterBase(dataCache, filter) +{ + tidMappingSet_.insert(CustomPair(0, 0)); + pidToInternalPidMap_.insert(CustomPair(0, 0)); +} + +ProcessFilter::~ProcessFilter() {} + +uint32_t ProcessFilter::UpdateOrCreateThreadWithName(uint64_t timeStamp, uint32_t tid, std::string_view name) +{ + DataIndex nameIndex = traceDataCache_->GetDataIndex(name); + return UpdateOrCreateThreadWithNameIndex(timeStamp, tid, nameIndex); +} + +uint32_t ProcessFilter::UpdateOrCreateThread(uint64_t timestamp, uint32_t tid) +{ + return UpdateOrCreateThreadWithNameIndex(timestamp, tid, 0); +} +void ProcessFilter::UpdateOrCreateThreadWithPidAndName(uint32_t tid, uint32_t pid, std::string_view name) +{ + uint32_t internalTid = GetOrCreateThreadWithPid(tid, pid); + auto thread = traceDataCache_->GetThreadData(internalTid); + auto nameIndex = traceDataCache_->GetDataIndex(name); + thread->nameIndex_ = nameIndex; + // When the process ID is equal to the thread ID, the process name is also equal to the thread name + if (tid == pid) { + UpdateOrCreateProcessWithName(pid, name); + } +} + +uint32_t ProcessFilter::GetOrCreateThreadWithPid(uint32_t tid, uint32_t pid) +{ + TraceStdtype::Thread* thread = nullptr; + uint32_t internalTid = INVALID_ID; + if (pid == 0) { + internalTid = GetInternalTid(tid); + } else { + internalTid = GetInternalTid(tid, pid); + } + if (internalTid != INVALID_ID) { + thread = traceDataCache_->GetThreadData(internalTid); + } else { + std::tie(internalTid, thread) = NewThread(tid); + } + + if (!thread->internalPid_ && pid != 0) { + std::tie(thread->internalPid_, std::ignore) = CreateProcessMaybe(pid, thread->startT_); + } + + return internalTid; +} + +uint32_t ProcessFilter::UpdateOrCreateProcessWithName(uint32_t pid, std::string_view name) +{ + uint32_t internalPid = 0; + TraceStdtype::Process* process = nullptr; + std::tie(internalPid, process) = CreateProcessMaybe(pid, 0); + if (process && process->cmdLine_ != name) { + process->cmdLine_ = std::string(name); + } + // update main thread name + auto internalTid = GetInternalTid(pid, pid); + if (internalTid != INVALID_ID) { + auto thread = traceDataCache_->GetThreadData(internalTid); + thread->nameIndex_ = traceDataCache_->GetDataIndex(name); + } + return internalPid; +} + +uint32_t ProcessFilter::UpdateOrCreateThreadWithNameIndex(uint64_t timeStamp, uint32_t tid, DataIndex threadNameIndex) +{ + TraceStdtype::Thread* thread = nullptr; + uint32_t internalTid = GetInternalTid(tid); + if (internalTid != INVALID_ID) { + if (threadNameIndex) { + thread = traceDataCache_->GetThreadData(internalTid); + thread->nameIndex_ = threadNameIndex; + } + } else { + std::tie(internalTid, thread) = NewThread(tid); + thread->nameIndex_ = threadNameIndex; + if (timeStamp < thread->startT_) { + thread->startT_ = timeStamp; + } + } + return internalTid; +} +uint32_t ProcessFilter::GetInternalTid(uint32_t tid, uint32_t pid) const +{ + uint32_t internalTid = INVALID_ID; + auto tidsPair = tidMappingSet_.equal_range(tid); + for (auto it = tidsPair.first; it != tidsPair.second; it++) { + uint32_t iterItid = it->second; + auto iterThread = traceDataCache_->GetThreadData(iterItid); + if (!iterThread->internalPid_) { + internalTid = iterItid; + continue; + } + + const auto& iterProcess = traceDataCache_->GetConstProcessData(iterThread->internalPid_); + if (iterProcess.pid_ == pid) { + internalTid = iterItid; + break; + } + } + + return internalTid; +} + +uint32_t ProcessFilter::GetInternalTid(uint32_t tid) const +{ + auto itRange = tidMappingSet_.equal_range(tid); + if (itRange.first != itRange.second) { + auto internalTid = std::prev(itRange.second)->second; + return internalTid; + } + return INVALID_ID; +} + +bool ProcessFilter::isThreadNameEmpty(uint32_t tid) const +{ + auto internalTid = GetInternalTid(tid); + if (internalTid != INVALID_ID) { + auto thread = traceDataCache_->GetThreadData(internalTid); + if (thread->nameIndex_) { + return false; + } + } + return true; +} + +InternalPid ProcessFilter::GetInternalPid(uint32_t pid) const +{ + auto it = pidToInternalPidMap_.find(pid); + if (it != pidToInternalPidMap_.end()) { + return it->second; + } + return INVALID_ID; +} + +InternalTid ProcessFilter::GetOrCreateInternalPid(uint64_t timestamp, uint32_t pid) +{ + auto ipid = GetInternalPid(pid); + if (ipid != INVALID_ID) { + return ipid; + } + + uint32_t internalPid = 0; + TraceStdtype::Process* process = nullptr; + std::tie(internalPid, process) = CreateProcessMaybe(pid, timestamp); + return internalPid; +} +std::tuple ProcessFilter::NewThread(uint32_t tid) +{ + uint32_t internalTid = traceDataCache_->NewInternalThread(tid); + tidMappingSet_.emplace(tid, internalTid); + auto thread = traceDataCache_->GetThreadData(internalTid); + + return std::make_tuple(internalTid, thread); +} + +std::tuple ProcessFilter::NewProcess(uint32_t pid) +{ + uint32_t internalPid = traceDataCache_->GetProcessInternalPid(pid); + pidToInternalPidMap_.emplace(pid, internalPid); + auto process = traceDataCache_->GetProcessData(internalPid); + + return std::make_tuple(internalPid, process); +} + +std::tuple ProcessFilter::CreateProcessMaybe(uint32_t pid, uint64_t startT) +{ + uint32_t internalPid = INVALID_ID; + TraceStdtype::Process* process = nullptr; + auto it = pidToInternalPidMap_.find(pid); + if (it != pidToInternalPidMap_.end()) { + internalPid = it->second; + process = traceDataCache_->GetProcessData(internalPid); + } else { + std::tie(internalPid, process) = NewProcess(pid); + void(GetOrCreateThreadWithPid(pid, pid)); + } + + if (process->startT_ == 0) { + process->startT_ = startT; + } + + return std::make_tuple(internalPid, process); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/process_filter.h b/host/trace_streamer/src/filter/process_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..a3e04e7ef3a65682fc38d3fb7a3dc4d5c5db38e3 --- /dev/null +++ b/host/trace_streamer/src/filter/process_filter.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PROCESS_FILTER_H +#define PROCESS_FILTER_H + +#include + +#include "filter_base.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +class ProcessFilter : private FilterBase { +public: + ProcessFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + ~ProcessFilter() override; + + uint32_t UpdateOrCreateProcessWithName(uint32_t pid, std::string_view name); + uint32_t UpdateOrCreateThreadWithName(uint64_t timestamp, uint32_t tid, std::string_view name); + void UpdateOrCreateThreadWithPidAndName(uint32_t tid, uint32_t pid, std::string_view name); + uint32_t GetOrCreateThreadWithPid(uint32_t tid, uint32_t pid); + uint32_t UpdateOrCreateThread(uint64_t timestamp, uint32_t tid); + InternalPid GetInternalPid(uint32_t pid) const; + InternalTid GetOrCreateInternalPid(uint64_t timestamp, uint32_t pid); + bool isThreadNameEmpty(uint32_t tid) const; + uint32_t UpdateOrCreateThreadWithNameIndex(uint64_t timestamp, uint32_t tid, DataIndex threadNameIndex); +private: + std::tuple CreateProcessMaybe(uint32_t pid, uint64_t start_ns); + std::tuple NewThread(uint32_t tid); + std::tuple NewProcess(uint32_t pid); + + InternalTid GetInternalTid(uint32_t tid) const; + InternalTid GetInternalTid(uint32_t tid, uint32_t pid) const; +private: + std::multimap tidMappingSet_ = {}; + std::map pidToInternalPidMap_ = {}; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // PROCESS_FILTER_H diff --git a/host/trace_streamer/src/filter/slice_filter.cpp b/host/trace_streamer/src/filter/slice_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ae3854fea33cd9ae923fdedea937a2179e806e7 --- /dev/null +++ b/host/trace_streamer/src/filter/slice_filter.cpp @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "slice_filter.h" +#include +#include +#include + +#include "args_filter.h" +#include "log.h" +#include "measure_filter.h" +#include "process_filter.h" +#include "stat_filter.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +SliceFilter::SliceFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : FilterBase(dataCache, filter), asyncEventMap_(INVALID_UINT64) +{ +} + +SliceFilter::~SliceFilter() = default; + +bool SliceFilter::BeginSlice(uint64_t timestamp, + uint32_t pid, + uint32_t threadGroupId, + DataIndex cat, + DataIndex nameIndex) +{ + InternalTid internalTid = INVALID_UTID; + if (threadGroupId > 0) { + internalTid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(pid, threadGroupId); + pidTothreadGroupId_[pid] = threadGroupId; + } else { + internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timestamp, pid); + } + // make a SliceData DataItem, {timestamp, dur, internalTid, cat, nameIndex} + struct SliceData sliceData = {timestamp, 0, internalTid, cat, nameIndex}; + return BeginSliceInternal(sliceData); +} + +void SliceFilter::IrqHandlerEntry(uint64_t timestamp, uint32_t cpu, DataIndex catalog, DataIndex nameIndex) +{ + struct SliceData sliceData = {timestamp, 0, cpu, catalog, nameIndex}; + auto slices = traceDataCache_->GetIrqData(); + size_t index = slices->AppendInternalSlice(sliceData.timestamp, sliceData.duration, sliceData.internalTid, + sliceData.cat, sliceData.name, 0, std::nullopt); + if (irqEventMap_.count(cpu)) { + // not match + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_IRQ_HANDLER_ENTRY, STAT_EVENT_DATA_LOST); + irqEventMap_.at(cpu) = {timestamp, index}; + } else { + irqEventMap_[cpu] = {timestamp, index}; + } + slices->AppendDistributeInfo(); + return; +} + +void SliceFilter::IrqHandlerExit(uint64_t timestamp, uint32_t cpu, ArgsSet args) +{ + if (!irqEventMap_.count(cpu)) { + // not match + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_IRQ_HANDLER_EXIT, STAT_EVENT_NOTMATCH); + return; + } + uint32_t argSetId = INVALID_UINT32; + auto slices = traceDataCache_->GetIrqData(); + argSetId = streamFilters_->argsFilter_->NewArgs(args); + slices->SetDurationAndArg(irqEventMap_.at(cpu).row, timestamp, argSetId); + irqEventMap_.erase(cpu); + return; +} + +void SliceFilter::SoftIrqEntry(uint64_t timestamp, uint32_t cpu, DataIndex catalog, DataIndex nameIndex) +{ + struct SliceData sliceData = {timestamp, 0, cpu, catalog, nameIndex}; + auto slices = traceDataCache_->GetIrqData(); + size_t index = slices->AppendInternalSlice(sliceData.timestamp, sliceData.duration, sliceData.internalTid, + sliceData.cat, sliceData.name, 0, std::nullopt); + if (softIrqEventMap_.count(cpu)) { + // not match + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SOFTIRQ_ENTRY, STAT_EVENT_DATA_LOST); + softIrqEventMap_.at(cpu) = {timestamp, index}; + } else { + softIrqEventMap_[cpu] = {timestamp, index}; + } + slices->AppendDistributeInfo(); + return; +} + +void SliceFilter::SoftIrqExit(uint64_t timestamp, uint32_t cpu, ArgsSet args) +{ + if (!softIrqEventMap_.count(cpu)) { + // not match + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST); + return; + } + uint32_t argSetId = INVALID_UINT32; + auto slices = traceDataCache_->GetIrqData(); + argSetId = streamFilters_->argsFilter_->NewArgs(args); + slices->SetDurationAndArg(softIrqEventMap_.at(cpu).row, timestamp, argSetId); + softIrqEventMap_.erase(cpu); + return; +} + +size_t SliceFilter::BeginAsyncBinder(uint64_t timestamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, ArgsSet args) +{ + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timestamp, pid); + struct SliceData sliceData = {timestamp, 0, internalTid, cat, nameIndex}; + auto slices = traceDataCache_->GetInternalSlicesData(); + + auto sliceStack = &sliceStackMap_[sliceData.internalTid]; + if (sliceStack->size() >= std::numeric_limits::max()) { + TS_LOGW("stack depth out of range."); + } + const uint8_t depth = static_cast(sliceStack->size()); + size_t index = slices->AppendInternalSlice(sliceData.timestamp, sliceData.duration, sliceData.internalTid, + sliceData.cat, sliceData.name, depth, std::nullopt); + + uint32_t argSetId = INVALID_INT32; + if (args.valuesMap_.size()) { + argSetId = streamFilters_->argsFilter_->NewArgs(args); + slices->AppendArgSet(argSetId); + binderQueue_[pid] = argSetId; + } else { + argSetId = streamFilters_->argsFilter_->NewArgs(args); + slices->AppendArgSet(argSetId); + binderQueue_[pid] = argSetId; + } + argsToSliceQueue_[argSetId] = static_cast(index); + return index; +} +size_t SliceFilter::BeginBinder(uint64_t timestamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, + ArgsSet args) +{ + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timestamp, pid); + struct SliceData sliceData = {timestamp, 0, internalTid, cat, nameIndex}; + auto slices = traceDataCache_->GetInternalSlicesData(); + + auto sliceStack = &sliceStackMap_[sliceData.internalTid]; + if (sliceStack->size() >= std::numeric_limits::max()) { + TS_LOGW("stack depth out of range."); + } + const uint8_t depth = static_cast(sliceStack->size()); + size_t index = slices->AppendInternalSlice(sliceData.timestamp, sliceData.duration, sliceData.internalTid, + sliceData.cat, sliceData.name, depth, std::nullopt); + + sliceStack->push_back(index); + + uint32_t argSetId = INVALID_INT32; + if (args.valuesMap_.size()) { + argSetId = streamFilters_->argsFilter_->NewArgs(args); + slices->AppendArgSet(argSetId); + binderQueue_[pid] = argSetId; + } else { + argSetId = streamFilters_->argsFilter_->NewArgs(args); + slices->AppendArgSet(argSetId); + binderQueue_[pid] = argSetId; + } + argsToSliceQueue_[argSetId] = static_cast(index); + return index; +} + +uint32_t SliceFilter::AddArgs(uint32_t tid, DataIndex key1, DataIndex key2, ArgsSet &args) +{ + if (!binderQueue_.count(tid)) { + return INVALID_UINT32; + } + streamFilters_->argsFilter_->AppendArgs(args, binderQueue_[tid]); + return argsToSliceQueue_[binderQueue_[tid]]; +} +bool SliceFilter::EndBinder(uint64_t timestamp, uint32_t pid, DataIndex category, DataIndex name, ArgsSet args) +{ + if (!binderQueue_.count(pid)) { + return false; + } + auto lastRow = argsToSliceQueue_[binderQueue_[pid]]; + auto slices = traceDataCache_->GetInternalSlicesData(); + slices->SetDuration(lastRow, timestamp); + streamFilters_->argsFilter_->AppendArgs(args, binderQueue_[pid]); + argsToSliceQueue_.erase(binderQueue_[pid]); + + binderQueue_.erase(pid); + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timestamp, pid); + + const auto& stack = sliceStackMap_[internalTid]; + if (stack.empty()) { + TS_LOGE("a slice end do not match a slice start event"); + callEventDisMatchCount++; + return false; + } + sliceStackMap_[internalTid].pop_back(); + return true; +} + +void SliceFilter::StartAsyncSlice(uint64_t timestamp, + uint32_t pid, + uint32_t threadGroupId, + int64_t cookie, + DataIndex nameIndex) +{ + InternalPid internalPid = streamFilters_->processFilter_->GetOrCreateInternalPid(timestamp, threadGroupId); + auto lastFilterId = asyncEventMap_.Find(internalPid, cookie, nameIndex); + auto slices = traceDataCache_->GetInternalSlicesData(); + if (lastFilterId != INVALID_UINT64) { + asyncEventDisMatchCount++; + FinishAsyncSlice(timestamp, pid, threadGroupId, cookie, nameIndex); + } + asyncEventSize_++; + // a pid, cookie and function name determain a callstack + asyncEventMap_.Insert(internalPid, cookie, nameIndex, asyncEventSize_); + // the IDE need a depth to paint call slice in different position of the canvas, the depth of async call + // do not mean the parent-to-child relationship, it is different from no-async call + uint8_t depth = 0; + if (asyncNoEndingEventMap_.find(internalPid) == asyncNoEndingEventMap_.end()) { + depth = 0; + asyncNoEndingEventMap_.insert(std::make_pair(internalPid, 1)); + } else { + depth = asyncNoEndingEventMap_.at(internalPid); + asyncNoEndingEventMap_.at(internalPid)++; + } + size_t index = slices->AppendInternalAsyncSlice(timestamp, 0, internalPid, INVALID_UINT64, nameIndex, depth, cookie, + std::nullopt); + asyncEventFilterMap_.insert(std::make_pair(asyncEventSize_, AsyncEvent{timestamp, index})); +} + +void SliceFilter::FinishAsyncSlice(uint64_t timestamp, + uint32_t pid, + uint32_t threadGroupId, + int64_t cookie, + DataIndex nameIndex) +{ + UNUSED(pid); + InternalPid internalPid = streamFilters_->processFilter_->GetOrCreateInternalPid(timestamp, threadGroupId); + auto lastFilterId = asyncEventMap_.Find(internalPid, cookie, nameIndex); + auto slices = traceDataCache_->GetInternalSlicesData(); + if (lastFilterId == INVALID_UINT64) { // if failed + asyncEventDisMatchCount++; + return; + } + if (asyncEventFilterMap_.find(lastFilterId) == asyncEventFilterMap_.end()) { + TS_LOGE("logic error"); + asyncEventDisMatchCount++; + return; + } + // update timestamp + asyncEventFilterMap_.at(lastFilterId).timestamp = timestamp; + slices->SetDuration(asyncEventFilterMap_.at(lastFilterId).row, timestamp); + asyncEventFilterMap_.erase(lastFilterId); + asyncEventMap_.Erase(internalPid, cookie, nameIndex); + + if (asyncNoEndingEventMap_.find(internalPid) == asyncNoEndingEventMap_.end()) { + asyncNoEndingEventMap_.insert(std::make_pair(internalPid, 1)); + } else { + asyncNoEndingEventMap_.at(internalPid)--; + if (!asyncNoEndingEventMap_.at(internalPid)) { + asyncNoEndingEventMap_.erase(internalPid); + } + } +} + +bool SliceFilter::BeginSliceInternal(const SliceData& sliceData) +{ + // the call stack belongs to thread, so we keep a call-tree for the thread + auto sliceStack = &sliceStackMap_[sliceData.internalTid]; // this can be a empty call, but it does not matter + auto slices = traceDataCache_->GetInternalSlicesData(); + if (sliceStack->size() >= std::numeric_limits::max()) { + TS_LOGW("stack depth out of range."); + } + const uint8_t depth = static_cast(sliceStack->size()); + std::optional parentId = std::nullopt; + if (depth != 0) { + size_t lastDepth = sliceStack->back(); + parentId = std::make_optional(slices->IdsData()[lastDepth]); // get the depth here + } + + size_t index = slices->AppendInternalSlice(sliceData.timestamp, sliceData.duration, sliceData.internalTid, + sliceData.cat, sliceData.name, depth, parentId); + sliceStack->push_back(index); + return true; +} + +bool SliceFilter::EndSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId) +{ + InternalTid internalTid = INVALID_UTID; + if (threadGroupId) { + auto actThreadGroupIdIter = pidTothreadGroupId_.find(pid); + if (actThreadGroupIdIter == pidTothreadGroupId_.end()) { + callEventDisMatchCount++; + return false; + } + uint32_t actThreadGroupId = actThreadGroupIdIter->second; + if (threadGroupId != actThreadGroupId) { + TS_LOGD("pid %u mismatched thread group id %u", pid, actThreadGroupId); + } + internalTid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(pid, actThreadGroupId); + } else { + internalTid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(pid, 0); + } + + const auto& stack = sliceStackMap_[internalTid]; + if (stack.empty()) { + TS_LOGW("a slice end do not match a slice start event"); + callEventDisMatchCount++; + return false; + } + + auto slices = traceDataCache_->GetInternalSlicesData(); + size_t index = stack.back(); + slices->SetDuration(index, timestamp); + sliceStackMap_[internalTid].pop_back(); + // update dur of parent slice maybe + auto parentId = slices->ParentIdData()[index]; + if (parentId.has_value()) { + slices->SetDuration(parentId.value(), timestamp); + } + return true; +} + +uint64_t SliceFilter::GenHashByStack(const StackOfSlices& sliceStack) const +{ + std::string hashStr; + const auto& sliceSet = traceDataCache_->GetConstInternalSlicesData(); + for (size_t i = 0; i < sliceStack.size(); i++) { + size_t index = sliceStack[i]; + hashStr += "cat"; + hashStr += std::to_string(sliceSet.CatsData()[index]); + hashStr += "name"; + hashStr += std::to_string(sliceSet.NamesData()[index]); + } + + const uint64_t stackHashMask = uint64_t(-1) >> 1; + return (std::hash{}(hashStr)) & stackHashMask; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/slice_filter.h b/host/trace_streamer/src/filter/slice_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..c2cb7ad83412c26916311ad332e13ed654a0d6bb --- /dev/null +++ b/host/trace_streamer/src/filter/slice_filter.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SLICE_FILTER_H +#define SLICE_FILTER_H + +#include +#include +#include "args_set.h" +#include "filter_base.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" +#include "triple_map.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +struct SliceData { + uint64_t timestamp; + uint64_t duration; + InternalTid internalTid; + DataIndex cat; + DataIndex name; +}; +struct AsyncEvent { + uint64_t timestamp; + size_t row; +}; +class SliceFilter : private FilterBase { +public: + SliceFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + ~SliceFilter() override; + + bool BeginSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId, DataIndex cat, DataIndex nameIndex); + size_t BeginBinder(uint64_t timestamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, ArgsSet args = ArgsSet()); + size_t BeginAsyncBinder(uint64_t timestamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, + ArgsSet args = ArgsSet()); + bool EndBinder(uint64_t timestamp, uint32_t pid, DataIndex category = {}, DataIndex name = {}, ArgsSet args = {}); + bool EndSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId); + void StartAsyncSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId, int64_t cookie, DataIndex nameIndex); + void + FinishAsyncSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId, int64_t cookie, DataIndex nameIndex); + uint32_t AddArgs(FilterId, DataIndex key1, DataIndex key2, ArgsSet& args); + void IrqHandlerEntry(uint64_t timestamp, uint32_t cpu, DataIndex catalog, DataIndex nameIndex); + void IrqHandlerExit(uint64_t timestamp, uint32_t cpu, ArgsSet args); + void SoftIrqEntry(uint64_t timestamp, uint32_t cpu, DataIndex catalog, DataIndex nameIndex); + void SoftIrqExit(uint64_t timestamp, uint32_t cpu, ArgsSet args); +private: + using StackOfSlices = std::vector; + uint64_t GenHashByStack(const StackOfSlices& sliceStack) const; + bool BeginSliceInternal(const SliceData& sliceData); +private: + // The parameter list is tid, cookid, functionName, asyncCallId. + TripleMap asyncEventMap_; + // this is only used to calc the layer of the async event in same time range + std::map asyncNoEndingEventMap_ = {}; + // irq map, key1 is cpu, key2 + struct IrqRecords { + uint64_t ts; + size_t row; + }; + std::unordered_map irqEventMap_ = {}; + // irq map, key1 is cpu, key2 + std::unordered_map softIrqEventMap_ = {}; + std::map asyncEventFilterMap_ = {}; + std::unordered_map sliceStackMap_ = {}; + std::unordered_map binderStackMap_ = {}; + std::unordered_map pidTothreadGroupId_ = {}; + uint64_t asyncEventSize_ = 0; + uint64_t asyncEventDisMatchCount = 0; + uint64_t callEventDisMatchCount = 0; + std::unordered_map binderQueue_ = {}; + std::unordered_map argsToSliceQueue_ = {}; + struct SliceInfo { + uint32_t row; + ArgsSet args_tracker; + }; + std::unordered_map> argsSet_ = {}; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // SLICE_FILTER_H diff --git a/host/trace_streamer/src/filter/stat_filter.cpp b/host/trace_streamer/src/filter/stat_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8afbb22e3818797d5c594cffd6ee6911e8df555b --- /dev/null +++ b/host/trace_streamer/src/filter/stat_filter.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stat_filter.h" +#include "filter_filter.h" +#include "log.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +StatFilter::StatFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) : FilterBase(dataCache, filter) {} + +StatFilter::~StatFilter() {} + +void StatFilter::IncreaseStat(SupportedTraceEventType eventType, StatType type) +{ + traceDataCache_->GetStatAndInfo()->IncreaseStat(eventType, type); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/stat_filter.h b/host/trace_streamer/src/filter/stat_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..2f05116ea1df454df17944c133aae3a25bfa48af --- /dev/null +++ b/host/trace_streamer/src/filter/stat_filter.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STAT_FILTER_H +#define STAT_FILTER_H + +#include +#include +#include + +#include "double_map.h" +#include "filter_base.h" +#include "trace_data_cache.h" +#include "trace_streamer_config.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::TraceCfg; +class StatFilter : private FilterBase { +public: + StatFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + StatFilter(const StatFilter&) = delete; + StatFilter& operator=(const StatFilter&) = delete; + ~StatFilter() override; + void IncreaseStat(SupportedTraceEventType eventType, StatType type); +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // THREAD_MEASURE_FILTER_H diff --git a/host/trace_streamer/src/filter/symbols_filter.cpp b/host/trace_streamer/src/filter/symbols_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..277272595945140881a65b699fff7e33a67f0797 --- /dev/null +++ b/host/trace_streamer/src/filter/symbols_filter.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "symbols_filter.h" +#include +#include +#include + +#include "log.h" +#include "measure_filter.h" +#include "process_filter.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +SymbolsFilter::SymbolsFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : FilterBase(dataCache, filter) +{ +} + +SymbolsFilter::~SymbolsFilter() = default; +void SymbolsFilter::RegisterFunc(uint64_t addr, DataIndex funcNameDictIndex) +{ + if (symbolsMap_.find(addr) == symbolsMap_.end()) { + symbolsMap_.insert(std::make_pair(addr, funcNameDictIndex)); + traceDataCache_->GetSymbolsData()->InsertSymbol(funcNameDictIndex, addr); + } else { + symbolsMap_.at(addr) = funcNameDictIndex; + } +} + +const DataIndex& SymbolsFilter::GetFunc(uint64_t addr) const +{ + if (symbolsMap_.find(addr) == symbolsMap_.end()) { + auto lastAddr = symbolsMap_.lower_bound(addr); + if (lastAddr == symbolsMap_.end()) { + return INVALID_UINT64; + } + return lastAddr->second; + } else { + return symbolsMap_.at(addr); + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/symbols_filter.h b/host/trace_streamer/src/filter/symbols_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..4814c86c47e83e855734142a9af11741d7968b1e --- /dev/null +++ b/host/trace_streamer/src/filter/symbols_filter.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SYMBOLS_FILTER_H +#define SYMBOLS_FILTER_H + +#include +#include "filter_base.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +class SymbolsFilter : private FilterBase { +public: + SymbolsFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + ~SymbolsFilter() override; + + void RegisterFunc(uint64_t addr, DataIndex funcNameDictIndex); + + const DataIndex& GetFunc(uint64_t addr) const; +private: + std::map symbolsMap_ = {}; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // SLICE_FILTER_H diff --git a/host/trace_streamer/src/filter/system_event_measure_filter.cpp b/host/trace_streamer/src/filter/system_event_measure_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7f79deac42dc2feaddf40ec86cf3454ae6be01e9 --- /dev/null +++ b/host/trace_streamer/src/filter/system_event_measure_filter.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "system_event_measure_filter.h" +#include "filter_filter.h" +#include "log.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +SystemEventMeasureFilter::SystemEventMeasureFilter(TraceDataCache* dataCache, + const TraceStreamerFilters* filter, + SysEventType e) + : FilterBase(dataCache, filter), filterType_(e) +{ +} + +SystemEventMeasureFilter::~SystemEventMeasureFilter() {} + +void SystemEventMeasureFilter::AppendNewMeasureData(DataIndex nameIndex, uint64_t timestamp, int64_t value) +{ + auto filterId = GetOrCreateFilterId(nameIndex); + traceDataCache_->GetMeasureData()->AppendMeasureData(0, timestamp, value, filterId); +} +uint32_t SystemEventMeasureFilter::GetOrCreateFilterId(DataIndex nameIndex) +{ + auto filterId = tidStreamIdFilterIdMap_.find(nameIndex); + if (filterId != tidStreamIdFilterIdMap_.end()) { + return static_cast((tidStreamIdFilterIdMap_.at(nameIndex))); + } + + uint32_t newFilterId = streamFilters_->filterFilter_->AddFilter( + filterTypeValue.at(filterType_), traceDataCache_->GetDataFromDict(nameIndex), INVALID_UINT64); + AddCertainFilterId(nameIndex, newFilterId); + return newFilterId; +} + +void SystemEventMeasureFilter::AddCertainFilterId(DataIndex nameIndex, uint64_t filterId) +{ + tidStreamIdFilterIdMap_.insert(std::make_pair(nameIndex, filterId)); + + if (filterType_ == E_SYS_MEMORY_FILTER) { + traceDataCache_->GetSysMeasureFilterData()->AppendNewFilter(filterId, sysMemoryFilterId_, + static_cast(nameIndex)); + } else if (filterType_ == E_SYS_VIRTUAL_MEMORY_FILTER) { + traceDataCache_->GetSysMeasureFilterData()->AppendNewFilter(filterId, sysVMemoryFilterId_, + static_cast(nameIndex)); + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/system_event_measure_filter.h b/host/trace_streamer/src/filter/system_event_measure_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..8baf4a62e347794b193d9dd721ae7d47738b4749 --- /dev/null +++ b/host/trace_streamer/src/filter/system_event_measure_filter.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SYS_EVENT_MEASURE_FILTER_H +#define SYS_EVENT_MEASURE_FILTER_H + +#include +#include +#include + +#include "double_map.h" +#include "filter_base.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +enum SysEventType { E_SYS_MEMORY_FILTER, E_SYS_VIRTUAL_MEMORY_FILTER }; + +class SystemEventMeasureFilter : private FilterBase { +public: + SystemEventMeasureFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter, SysEventType); + SystemEventMeasureFilter(const SystemEventMeasureFilter&) = delete; + SystemEventMeasureFilter& operator=(const SystemEventMeasureFilter&) = delete; + ~SystemEventMeasureFilter() override; + void AppendNewMeasureData(DataIndex nameIndex, uint64_t timestamp, int64_t value); + +private: + uint32_t GetOrCreateFilterId(DataIndex nameIndex); + void AddCertainFilterId(DataIndex nameIndex, uint64_t filterId); + std::map tidStreamIdFilterIdMap_ = {}; + SysEventType filterType_; + + const std::map filterTypeValue = { + {E_SYS_MEMORY_FILTER, "sys_memory_filter"}, + {E_SYS_VIRTUAL_MEMORY_FILTER, "sys_virtual_memory_filter"}}; + const DataIndex sysMemoryFilterId_ = traceDataCache_->GetDataIndex("sys_memory_filter"); + const DataIndex sysVMemoryFilterId_ = traceDataCache_->GetDataIndex("sys_virtual_memory_filter"); +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // SYS_EVENT_MEASURE_FILTER_H diff --git a/host/trace_streamer/src/include/BUILD.gn b/host/trace_streamer/src/include/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..e0f6aa748092c12737d8357c20351724f4c3a677 --- /dev/null +++ b/host/trace_streamer/src/include/BUILD.gn @@ -0,0 +1,26 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import("//build/ohos.gni") +ohos_source_set("ibase") { + sources = [ + "codec_cov.h", + "file.h", + "log.h", + "parting_string.h", + "string_to_numerical.h", + ] + include_dirs = [] + public_deps = [] + deps = [] + sources += [ "/usr/x86_64-w64-mingw32/include/windows.h" ] +} diff --git a/host/trace_streamer/src/include/codec_cov.h b/host/trace_streamer/src/include/codec_cov.h new file mode 100644 index 0000000000000000000000000000000000000000..0bc0ccef9a9e2cefe55fb8c40cf2ba84ef194ee6 --- /dev/null +++ b/host/trace_streamer/src/include/codec_cov.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_TUNING_BASE_CODEC_COV_H_ +#define INCLUDE_TUNING_BASE_CODEC_COV_H_ + +#include + +namespace SysTuning { +namespace base { +int PreNum(unsigned char byte); + +bool IsUTF8(const uint8_t* data, int len); + +bool IsGBK(const uint8_t* data, int len); + +typedef enum { GBK, UTF8, UNKOWN } CODING; + +CODING GetCoding(const uint8_t* data, int len); + +#ifdef _WIN32 +std::string GbkToUtf8(const char* srcStr); +#endif +} // namespace base +} // namespace SysTuning + +#endif diff --git a/host/trace_streamer/src/include/file.h b/host/trace_streamer/src/include/file.h new file mode 100644 index 0000000000000000000000000000000000000000..97be5664c8497e15aaa1d121bc77b9778a8a3131 --- /dev/null +++ b/host/trace_streamer/src/include/file.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_TUNING_BASE_FILE_UTILS_H_ +#define INCLUDE_TUNING_BASE_FILE_UTILS_H_ + +#include + +namespace SysTuning { +namespace base { +constexpr uint32_t kFileModeInvalid = 0xFFFFFFFF; +enum TraceParserStatus { + TRACE_PARSER_NORMAL = 0, + TRACE_PARSER_FILE_TYPE_ERROR = 1, + TRACE_PARSE_ERROR = 2, + TRACE_PARSER_ABNORMAL = 3 +}; + +void SetAnalysisResult(TraceParserStatus stat); + +TraceParserStatus GetAnalysisResult(); + +ssize_t Read(int fd, uint8_t* dst, size_t dstSize); + +int OpenFile(const std::string& path, int flags, uint32_t mode = kFileModeInvalid); + +std::string GetExecutionDirectoryPath(); +} // namespace base +} // namespace SysTuning +#endif // INCLUDE_TUNING_BASE_FILE_UTILS_H_ diff --git a/host/trace_streamer/src/include/log.h b/host/trace_streamer/src/include/log.h new file mode 100644 index 0000000000000000000000000000000000000000..fef94e664b845cb7715e4c7df202da47efad1789 --- /dev/null +++ b/host/trace_streamer/src/include/log.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_TS_BASE_LOGGING_H_ +#define INCLUDE_TS_BASE_LOGGING_H_ + +#include +#include + +// namespace SysTuning { +// namespace base { +#define TS_CRASH \ + do { \ + __builtin_trap(); \ + __builtin_unreachable(); \ + } while (0) +enum LogLevel {LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL}; +const enum LogLevel g_currentLogLevel = LOG_DEBUG; +extern bool g_cleanMode; +#define LOGWITHLEVEL(level, motify, fmt, ...) \ + do { \ + if (level >= g_currentLogLevel) { \ + if (!g_cleanMode) { \ + fprintf(stdout, "[-%c][%s][%d]: " fmt "\n", motify, __FUNCTION__, \ + __LINE__, ##__VA_ARGS__); \ + } \ + if (level == LOG_FATAL) { \ + TS_CRASH; \ + } \ + } \ + } while (0) +#define TS_LOGE(fmt, ...) LOGWITHLEVEL(LOG_ERROR, 'E', fmt, ##__VA_ARGS__) +#define TS_LOGF(fmt, ...) LOGWITHLEVEL(LOG_FATAL, 'F', fmt, ##__VA_ARGS__) +#define TS_LOGI(fmt, ...) LOGWITHLEVEL(LOG_INFO, 'I', fmt, ##__VA_ARGS__) +#ifdef NDEBUG +#define TS_LOGD(format, ...) +#define TS_LOGW(format, ...) +#define TS_ASSERT(x) +#else +#define TS_LOGD(fmt, ...) LOGWITHLEVEL(LOG_DEBUG, 'D', fmt, ##__VA_ARGS__) +#define TS_LOGW(fmt, ...) LOGWITHLEVEL(LOG_WARN, 'W', fmt, ##__VA_ARGS__) + +#define TS_ASSERT(x) \ + do { \ + if (!(x)) { \ + TS_CRASH; \ + } \ + } while (0) + +#endif +// } // namespace base +// } // namespace SysTuning + +#endif // INCLUDE_TS_BASE_LOGGING_H_ diff --git a/host/trace_streamer/src/include/parting_string.h b/host/trace_streamer/src/include/parting_string.h new file mode 100644 index 0000000000000000000000000000000000000000..91a56bfc587a54edb7c261442e7aafe6f128d4ae --- /dev/null +++ b/host/trace_streamer/src/include/parting_string.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_BASE_STRING_SPLITTER_H_ +#define INCLUDE_BASE_STRING_SPLITTER_H_ + +#include + +namespace SysTuning { +namespace base { +class PartingString { +public: + PartingString(std::string, char delimiter); + + bool Next(); + + char* GetCur() + { + return cur_; + } + +private: + PartingString(const PartingString&) = delete; + PartingString& operator=(const PartingString&) = delete; + + std::string str_; + char* cur_ = nullptr; + std::string::iterator begin_; + std::string::iterator end_; + const char delimiter_; +}; +} // namespace base +} // namespace SysTuning + +#endif diff --git a/host/trace_streamer/src/include/string_to_numerical.h b/host/trace_streamer/src/include/string_to_numerical.h new file mode 100644 index 0000000000000000000000000000000000000000..3340f5009fabbb38351458ddf3710da1e735399a --- /dev/null +++ b/host/trace_streamer/src/include/string_to_numerical.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_BASE_STRING_TO_NUMERICAL_H_ +#define INCLUDE_BASE_STRING_TO_NUMERICAL_H_ + +#include +#include +#include + +namespace SysTuning { +namespace base { +enum IntegerRadixType { + INTEGER_RADIX_TYPE_DEC = 10, + INTEGER_RADIX_TYPE_HEX = 16 +}; +inline std::optional StrToUInt32(const std::string& str, int base = INTEGER_RADIX_TYPE_DEC) +{ + if (!str.empty()) { + uint32_t value = static_cast(std::stoul(str, nullptr, base)); + return std::make_optional(value); + } + + return std::nullopt; +} + +inline std::string number(int value, int base = INTEGER_RADIX_TYPE_DEC) +{ + std::stringstream ss; + if (base == INTEGER_RADIX_TYPE_DEC) { + ss << std::oct << value; + } else if (base == INTEGER_RADIX_TYPE_HEX) { + ss << std::hex << value; + } + return ss.str(); +} + +inline std::optional StrToInt32(const std::string& str, int base = INTEGER_RADIX_TYPE_DEC) +{ + if (!str.empty()) { + int32_t value = static_cast(std::stol(str, nullptr, base)); + return std::make_optional(value); + } + + return std::nullopt; +} + +inline std::optional StrToUInt64(const std::string& str, int base = INTEGER_RADIX_TYPE_DEC) +{ + if (!str.empty()) { + uint64_t value = static_cast(std::stoull(str, nullptr, base)); + return std::make_optional(value); + } + + return std::nullopt; +} + +inline std::optional StrToInt64(const std::string& str, int base = INTEGER_RADIX_TYPE_DEC) +{ + if (!str.empty()) { + int64_t value = static_cast(std::stoll(str, nullptr, base)); + return std::make_optional(value); + } + return std::nullopt; +} + +inline std::optional StrToDouble(const std::string& str) +{ + if (!str.empty()) { + double value = std::stod(str); + return std::make_optional(value); + } + + return std::nullopt; +} +} // namespace base +} // namespace SysTuning + +#endif // INCLUDE_TUNING_EXT_BASE_STRING_UTILS_H_ diff --git a/host/trace_streamer/src/main.cpp b/host/trace_streamer/src/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b16b5a49261b986e9e698e39ed993ad0b42a5c8 --- /dev/null +++ b/host/trace_streamer/src/main.cpp @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "codec_cov.h" +#include "file.h" +#include "filter/slice_filter.h" +#include "http_server.h" +#include "log.h" +#include "parser/bytrace_parser/bytrace_event_parser.h" +#include "parser/bytrace_parser/bytrace_parser.h" +#include "parting_string.h" +#include "rpc_server.h" + +#include "thread_state.h" +#include "trace_streamer/trace_streamer_selector.h" +#include "trace_streamer_filters.h" +using namespace SysTuning::TraceStreamer; +using namespace SysTuning; +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::TraceStreamer; +using namespace SysTuning::base; +constexpr size_t G_CHUNK_SIZE = 1024 * 1024; +constexpr int G_MIN_PARAM_NUM = 2; +constexpr size_t G_FILE_PERMISSION = 664; +size_t g_loadSize = 0; +const char* TRACE_STREAM_VERSION = "2.3.118"; // version +const char* TRACE_STREAM_PUBLISHVERSION = "2022/3/29"; // publish datetime +void ExportStatusToLog(const std::string& dbPath, TraceParserStatus status) +{ + std::string path = dbPath + ".ohos.ts"; + std::ofstream out(path, std::ios_base::trunc); + out << (std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch())) + .count() + << ":" << status << std::endl; + using std::chrono::system_clock; + + system_clock::time_point today = system_clock::now(); + + std::time_t tt = system_clock::to_time_t(today); + out << "last running time is: " << ctime(&tt); + out << "last running status is: " << status; + out.close(); +} +void ShowHelpInfo(const char* argv) +{ + TS_LOGI( + "trace analyze tool, it can transfer a bytrace/htrace file into a " + "SQLite database and save result to a local file trace_streamer.log.\n" + "Usage: %s FILE -e sqlite_out.pb\n" + " or %s FILE -c\n" + "Options:\n" + " -e transfer a bytrace file into a SQLiteBased DB. with -nm to except meta table\n" + " -c command line mode.\n" + " -h start HTTP server.\n" + " -p Specify the port of HTTP server, default is 9001.\n" + " -i show information.\n" + " -v show version.", + argv, argv); +} +void PrintInformation() +{ + TraceStreamerConfig cfg; + cfg.PrintInfo(); +} +void PrintVersion() +{ + fprintf(stderr, "version %s\n", TRACE_STREAM_VERSION); +} + +bool ReadAndParser(SysTuning::TraceStreamer::TraceStreamerSelector& ta, int fd) +{ + auto startTime = + (std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch())) + .count(); + g_loadSize = 0; + while (true) { + std::unique_ptr buf = std::make_unique(G_CHUNK_SIZE); + auto rsize = Read(fd, buf.get(), G_CHUNK_SIZE); + if (rsize == 0) { + break; + } + + if (rsize < 0) { + TS_LOGE("Reading trace file failed (errno: %d, %s)", errno, strerror(errno)); + return false; + } + g_loadSize += rsize; + if (!ta.ParseTraceDataSegment(std::move(buf), static_cast(rsize))) { + return false; + }; + printf("\rLoadingFile:\t%.2f MB\r", static_cast(g_loadSize) / 1E6); + } + ta.WaitForParserEnd(); + auto endTime = + (std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch())) + .count(); + fprintf(stdout, "\nParserDuration:\t%u ms\n", static_cast(endTime - startTime)); + fprintf(stdout, "ParserSpeed:\t%.2f MB/s\n", (g_loadSize / (endTime - startTime) / 1E3)); + return true; +} +int OpenAndParserFile(TraceStreamerSelector& ts, const std::string& traceFilePath) +{ + int fd(OpenFile(traceFilePath, O_RDONLY, G_FILE_PERMISSION)); + if (fd < 0) { + TS_LOGE("%s does not exist", traceFilePath.c_str()); + SetAnalysisResult(TRACE_PARSER_ABNORMAL); + return 1; + } + if (!ReadAndParser(ts, fd)) { + close(fd); + SetAnalysisResult(TRACE_PARSER_ABNORMAL); + return 1; + } + MetaData* metaData = ts.GetMetaData(); + + std::string fileNameTmp = traceFilePath; +#ifdef _WIN32 + if (!base::GetCoding(reinterpret_cast(fileNameTmp.c_str()), fileNameTmp.length())) { + fileNameTmp = base::GbkToUtf8(fileNameTmp.c_str()); + } +#endif + metaData->SetSourceFileName(fileNameTmp); + metaData->SetTraceType((ts.DataType() == TRACE_FILETYPE_H_TRACE) ? "proto-based-trace" : "txt-based-trace"); + + close(fd); + return 0; +} +int ExportDatabase(TraceStreamerSelector& ts, const std::string& sqliteFilePath) +{ + auto startTime = + (std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch())) + .count(); + if (!sqliteFilePath.empty()) { + MetaData* metaData = ts.GetMetaData(); + std::string fileNameTmp = sqliteFilePath; +#ifdef _WIN32 + if (!base::GetCoding(reinterpret_cast(fileNameTmp.c_str()), fileNameTmp.length())) { + fileNameTmp = base::GbkToUtf8(fileNameTmp.c_str()); + } +#endif + metaData->SetOutputFileName(fileNameTmp); + metaData->SetParserToolVersion(TRACE_STREAM_VERSION); + metaData->SetParserToolPublishDateTime(TRACE_STREAM_PUBLISHVERSION); + metaData->SetTraceDataSize(g_loadSize); + fprintf(stdout, "ExportDatabase begin...\n"); + if (ts.ExportDatabase(sqliteFilePath)) { + fprintf(stdout, "ExportDatabase failed\n"); + ExportStatusToLog(sqliteFilePath, TRACE_PARSER_ABNORMAL); + return 1; + } + fprintf(stdout, "ExportDatabase end\n"); + } + auto endTime = + (std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch())) + .count(); + endTime += 1; // for any exception of endTime == startTime + fprintf(stdout, "ExportDuration:\t%u ms\n", static_cast(endTime - startTime)); + fprintf(stdout, "ExportSpeed:\t%.2f MB/s\n", (g_loadSize / (endTime - startTime)) / 1E3); + return 0; +} + +struct HttpOption { + bool enable = false; + int port = 9001; +}; + +int CheckArgs(int argc, + char** argv, + bool& interactiveState, + bool& exportMetaTable, + std::string& traceFilePath, + std::string& sqliteFilePath, + HttpOption& httpOption) +{ + for (int i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-e")) { + if (++i == argc) { + ShowHelpInfo(argv[0]); + return 1; + } + sqliteFilePath = std::string(argv[i]); + continue; + } else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--command")) { + interactiveState = true; + continue; + } else if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "--info")) { + PrintInformation(); + } else if (!strcmp(argv[i], "-nm") || !strcmp(argv[i], "--nometa")) { + exportMetaTable = false; + continue; + } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--v") || !strcmp(argv[i], "-version") || + !strcmp(argv[i], "--version")) { + PrintVersion(); + return 1; + } else if (!strcmp(argv[i], "-h")) { + httpOption.enable = true; + continue; + } else if (!strcmp(argv[i], "-p")) { + if (++i == argc) { + ShowHelpInfo(argv[0]); + return 1; + } + httpOption.port = std::stoi(argv[i]); + continue; + } + traceFilePath = std::string(argv[i]); + } + if ((traceFilePath.empty() || (!interactiveState && sqliteFilePath.empty())) + && !httpOption.enable) { + ShowHelpInfo(argv[0]); + return 1; + } + return 0; +} +} // namespace TraceStreamer +} // namespace SysTuning + +int main(int argc, char** argv) +{ + if (argc < G_MIN_PARAM_NUM) { + ShowHelpInfo(argv[0]); + return 1; + } + std::string traceFilePath; + std::string sqliteFilePath; + bool interactiveState = false; + bool exportMetaTable = true; + HttpOption httpOption; + int ret = CheckArgs(argc, argv, interactiveState, exportMetaTable, traceFilePath, sqliteFilePath, httpOption); + if (ret) { + if (!sqliteFilePath.empty()) { + ExportStatusToLog(sqliteFilePath, GetAnalysisResult()); + } + return 0; + } + + if (httpOption.enable) { + RpcServer rpcServer; + HttpServer httpServer; + httpServer.RegisterRpcFunction(&rpcServer); + httpServer.Run(httpOption.port); + return 0; + } + TraceStreamerSelector ts; + ts.EnableMetaTable(exportMetaTable); + if (OpenAndParserFile(ts, traceFilePath)) { + if (!sqliteFilePath.empty()) { + ExportStatusToLog(sqliteFilePath, GetAnalysisResult()); + } + return 1; + } + if (interactiveState) { + ts.SearchData(); + return 0; + } + if (ExportDatabase(ts, sqliteFilePath)) { + ExportStatusToLog(sqliteFilePath, GetAnalysisResult()); + return 1; + } + if (!sqliteFilePath.empty()) { + ExportStatusToLog(sqliteFilePath, GetAnalysisResult()); + } + return 0; +} diff --git a/host/trace_streamer/src/multi_platform/BUILD.gn b/host/trace_streamer/src/multi_platform/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..35da1afb016d016c274e973b3089cff451e5daa3 --- /dev/null +++ b/host/trace_streamer/src/multi_platform/BUILD.gn @@ -0,0 +1,305 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import("//build/ohos.gni") +import("../ts.gni") +if (use_wasm) { +} else { +} +if (use_wasm) { + source_set("proto_services_cpp") { + sources = [ + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/compaction.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/compaction.pb.h", + ] + include_dirs = [ + "//third_party/protobuf/src", + "//src/include", + ] + } +} else { + shared_library("proto_services_cpp") { + sources = [ + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/compaction.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/compaction.pb.h", + ] + include_dirs = [ + "//third_party/protobuf/src", + "//src/include", + ] + } +} +if (use_wasm) { + source_set("ftrace_data_cpp") { + sources = [ + "${OHOS_PROTO_GEN}/services/common_types.pb.cc", + "${OHOS_PROTO_GEN}/services/common_types.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/binder.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/binder.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/block.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/block.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cgroup.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cgroup.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/clk.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/clk.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cpuhp.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cpuhp.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/dma_fence.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/dma_fence.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ext4.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ext4.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filelock.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filelock.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filemap.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filemap.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace_event.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace_event.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/gpio.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/gpio.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/i2c.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/i2c.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ipi.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ipi.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/irq.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/irq.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/kmem.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/kmem.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/net.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/net.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/oom.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/oom.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/pagemap.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/pagemap.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/power.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/power.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/printk.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/printk.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/raw_syscalls.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/raw_syscalls.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/rcu.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/rcu.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sched.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sched.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/signal.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/signal.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sunrpc.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sunrpc.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/task.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/task.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/timer.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/timer.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/trace_plugin_result.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/trace_plugin_result.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/v4l2.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/v4l2.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/vmscan.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/vmscan.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/workqueue.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/workqueue.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/writeback.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/writeback.pb.h", + ] + include_dirs = [ + "//third_party/protobuf/src", + "//src/include", + ] + } +} else { + shared_library("ftrace_data_cpp") { + sources = [ + "${OHOS_PROTO_GEN}/services/common_types.pb.cc", + "${OHOS_PROTO_GEN}/services/common_types.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/binder.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/binder.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/block.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/block.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cgroup.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cgroup.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/clk.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/clk.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cpuhp.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cpuhp.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/dma_fence.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/dma_fence.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ext4.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ext4.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filelock.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filelock.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filemap.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filemap.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace_event.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace_event.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/gpio.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/gpio.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/i2c.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/i2c.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ipi.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ipi.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/irq.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/irq.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/kmem.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/kmem.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/net.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/net.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/oom.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/oom.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/pagemap.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/pagemap.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/power.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/power.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/printk.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/printk.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/raw_syscalls.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/raw_syscalls.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/rcu.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/rcu.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sched.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sched.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/signal.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/signal.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sunrpc.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sunrpc.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/task.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/task.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/timer.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/timer.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/trace_plugin_result.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/trace_plugin_result.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/v4l2.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/v4l2.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/vmscan.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/vmscan.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/workqueue.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/workqueue.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/writeback.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/writeback.pb.h", + ] + include_dirs = [ + "//third_party/protobuf/src", + "//src/include", + ] + } +} +if (use_wasm) { + source_set("memory_data_cpp") { + sources = [ + "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_common.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_common.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_config.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_config.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_result.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_result.pb.h", + ] + include_dirs = [ + "//third_party/protobuf/src", + "//src/include", + ] + } +} else { + shared_library("memory_data_cpp") { + sources = [ + "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_common.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_common.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_config.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_config.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_result.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_result.pb.h", + ] + include_dirs = [ + "//third_party/protobuf/src", + "//src/include", + ] + } +} +if (use_wasm) { + source_set("hilog_data_cpp") { + sources = [ + "${OHOS_PROTO_GEN}/types/plugins/hilog_data/hilog_plugin_result.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/hilog_data/hilog_plugin_result.pb.h", + ] + include_dirs = [ + "//third_party/protobuf/src", + "//src/include", + ] + } +} else { + shared_library("hilog_data_cpp") { + sources = [ + "${OHOS_PROTO_GEN}/types/plugins/hilog_data/hilog_plugin_result.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/hilog_data/hilog_plugin_result.pb.h", + ] + include_dirs = [ + "//third_party/protobuf/src", + "//src/include", + ] + } +} + +if (use_wasm) { + source_set("native_hook_cpp") { + sources = [ + "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_config.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_config.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_result.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_result.pb.h", + ] + include_dirs = [ + "//third_party/protobuf/src", + "//src/include", + ] + } +} else { + shared_library("native_hook_cpp") { + sources = [ + "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_config.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_config.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_result.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_result.pb.h", + ] + include_dirs = [ + "//third_party/protobuf/src", + "//src/include", + ] + } +} + +if (use_wasm) { + source_set("hidump_data_cpp") { + sources = [ + "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_config.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_config.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_result.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_result.pb.h", + ] + include_dirs = [ + "//third_party/protobuf/src", + "//src/include", + ] + } +} else { + shared_library("hidump_data_cpp") { + sources = [ + "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_config.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_config.pb.h", + "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_result.pb.cc", + "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_result.pb.h", + ] + include_dirs = [ + "//third_party/protobuf/src", + "//src/include", + ] + } +} diff --git a/host/trace_streamer/src/multi_platform/global.pri b/host/trace_streamer/src/multi_platform/global.pri new file mode 100644 index 0000000000000000000000000000000000000000..a1dab5b59f50c843ae3cc438c38b50bcd8f23ae8 --- /dev/null +++ b/host/trace_streamer/src/multi_platform/global.pri @@ -0,0 +1,75 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#DEFINES +=_AIX +#DEFINES +=_GLIBCXX_BITS_STD_ABS_H +#DEFINES +=__CORRECT_ISO_CPP_STDLIB_H_PROTO +#DEFINES += __CORRECT_ISO_CPP11_MATH_H_PROTO_FP +#DEFINES +=__CORRECT_ISO_CPP_MATH_H_PROTO +#DEFINES +=_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC + +INCLUDEPATH +=$${ROOTSRCDIR}/include +INCLUDEPATH +=$${ROOTSRCDIR}/ +CONFIG(debug, debug|release){ + BUILDVERSION = _debug + message("debug") +}else{ + message("release") + BUILDVERSION = + DEFINES += NDEBUG +} +contains(QT_ARCH, i386) { + message("qmake" $$TARGET "32-bit") + BIT = x32 +} else { + message("qmake" $$TARGET "64-bit") + BIT = +} +macx{ + PLATFORM = macx + TOOL = + BIT = +} +unix:!macx { + PLATFORM = linux + TOOL = + BIT = +} +win32 { + PLATFORM = windows + TOOL = +} +DESTFOLDER =$${PLATFORM}$${BIT}$${TOOL}$${BUILDVERSION} +islib{ +message("this is for lib") +DESTDIR = $${ROOTSRCDIR}/lib/$${DESTFOLDER} +} else { +message("this is for app") +DESTDIR = $${ROOTSRCDIR}/out/$${DESTFOLDER} +} +unix{ +QMAKE_CXXFLAGS += -BigObj +INCLUDEPATH += $$DESTDIR/gen/build_config +INCLUDEPATH += $$DESTDIR/gen +INCLUDEPATH +=/usr/include/c++/7 +INCLUDEPATH +=/usr/include/x86_64-linux-gnu/ +} else { +INCLUDEPATH += $${GENDIR}/gen/build_config +INCLUDEPATH += $${GENDIR}/gen +DEFINES += WIN32 +QMAKE_CXXFLAGS += -BigObj +staticlib{ +QMAKE_CXXFLAGS += -Ofast -flto +} +} +OBJECTS_DIR = $${ROOTSRCDIR}/tmp_$${TARGET}_$${DESTFOLDER} diff --git a/host/trace_streamer/src/multi_platform/protogen.pri b/host/trace_streamer/src/multi_platform/protogen.pri new file mode 100644 index 0000000000000000000000000000000000000000..72da7fded06058c7c2aeef807a04ab35f2d50fdc --- /dev/null +++ b/host/trace_streamer/src/multi_platform/protogen.pri @@ -0,0 +1,107 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +PROTOGEN = $$PWD/../../third_party/protogen +INCLUDEPATH += $${PROTOGEN}/types/plugins/ftrace_data \ + $${PROTOGEN}/types/plugins/memory_data \ + $${PROTOGEN}/types/plugins/hilog_data \ + $${PROTOGEN}/types/plugins/native_hook \ + $${PROTOGEN}/types/plugins/hidump_data \ + $${PROTOGEN} +SOURCES +=$${PROTOGEN}/services/common_types.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/trace_plugin_result.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/ftrace_event.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/irq.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/vmscan.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/workqueue.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/task.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/power.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/sched.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/filemap.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/i2c.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/kmem.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/block.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/ipi.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/ftrace.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/ext4.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/oom.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/compaction.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/clk.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/cgroup.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/binder.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/signal.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/sunrpc.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/net.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/cpuhp.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/writeback.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/v4l2.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/pagemap.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/dma_fence.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/printk.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/filelock.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/gpio.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/timer.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/raw_syscalls.pb.cc \ + $${PROTOGEN}/types/plugins/ftrace_data/rcu.pb.cc \ + \ + $${PROTOGEN}/types/plugins/memory_data/memory_plugin_common.pb.cc \ + $${PROTOGEN}/types/plugins/memory_data/memory_plugin_config.pb.cc \ + $${PROTOGEN}/types/plugins/memory_data/memory_plugin_result.pb.cc \ + $${PROTOGEN}/types/plugins/hilog_data/hilog_plugin_result.pb.cc \ + $${PROTOGEN}/types/plugins/native_hook/native_hook_result.pb.cc \ + $${PROTOGEN}/types/plugins/native_hook/native_hook_config.pb.cc \ + $${PROTOGEN}/types/plugins/hidump_data/hidump_plugin_result.pb.cc \ + $${PROTOGEN}/types/plugins/hidump_data/hidump_plugin_config.pb.cc + +HEADERS += $${PROTOGEN}/services/common_types.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/trace_plugin_result.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/ftrace_event.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/irq.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/vmscan.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/workqueue.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/task.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/power.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/sched.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/filemap.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/i2c.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/kmem.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/block.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/ipi.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/ftrace.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/ext4.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/oom.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/compaction.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/clk.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/cgroup.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/signal.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/binder.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/net.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/v4l2.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/writeback.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/cpuhp.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/pagemap.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/dma_fence.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/printk.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/filelock.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/gpio.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/timer.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/raw_syscalls.pb.h \ + $${PROTOGEN}/types/plugins/ftrace_data/rcu.pb.h \ + \ + $${PROTOGEN}/types/plugins/memory_data/memory_plugin_common.pb.h \ + $${PROTOGEN}/types/plugins/memory_data/memory_plugin_config.pb.h \ + $${PROTOGEN}/types/plugins/memory_data/memory_plugin_result.pb.h \ + $${PROTOGEN}/types/plugins/hilog_data/hilog_plugin_result.pb.h \ + $${PROTOGEN}/types/plugins/native_hook/native_hook_result.pb.h \ + $${PROTOGEN}/types/plugins/native_hook/native_hook_config.pb.h \ + $${PROTOGEN}/types/plugins/hidump_data/hidump_plugin_result.pb.h \ + $${PROTOGEN}/types/plugins/hidump_data/hidump_plugin_config.pb.h diff --git a/host/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp b/host/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ab3d13df46530c63811a7380019de3f8045de94 --- /dev/null +++ b/host/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bytrace_event_parser.h" +#include "binder_filter.h" +#include "cpu_filter.h" +#include "filter_filter.h" +#include "irq_filter.h" +#include "measure_filter.h" +#include "parting_string.h" +#include "process_filter.h" +#include "slice_filter.h" +#include "stat_filter.h" +#include "string_to_numerical.h" +#include "thread_state.h" +#include "ts_common.h" +namespace SysTuning { +namespace TraceStreamer { +namespace { +std::string GetFunctionName(const std::string_view& text, const std::string_view& delimiter) +{ + std::string str(""); + if (delimiter.empty()) { + return str; + } + + std::size_t foundIndex = text.find(delimiter); + if (foundIndex != std::string::npos) { + std::size_t funIndex = foundIndex + delimiter.size(); + str = std::string(text.substr(funIndex, text.size() - funIndex)); + } + return str; +} +} // namespace + +BytraceEventParser::BytraceEventParser(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : EventParserBase(dataCache, filter), + ioWaitId_(const_cast(dataCache)->GetDataIndex("io_wait")), + workQueueId_(const_cast(dataCache)->GetDataIndex("workqueue")), + schedWakeupId_(const_cast(dataCache)->GetDataIndex("sched_wakeup")), + schedBlockedReasonId_(const_cast(dataCache)->GetDataIndex("sched_blocked_reason")), + printEventParser_(traceDataCache_, streamFilters_) +{ + eventToFunctionMap_ = { + {config_.eventNameMap_.at(TRACE_EVENT_SCHED_SWITCH), + bind(&BytraceEventParser::SchedSwitchEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_TASK_RENAME), + bind(&BytraceEventParser::TaskRenameEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_TASK_NEWTASK), + bind(&BytraceEventParser::TaskNewtaskEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_TRACING_MARK_WRITE), + bind(&BytraceEventParser::TracingMarkWriteEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_SCHED_WAKEUP), + bind(&BytraceEventParser::SchedWakeupEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_SCHED_WAKING), + bind(&BytraceEventParser::SchedWakingEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_CPU_IDLE), + bind(&BytraceEventParser::CpuIdleEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_CPU_FREQUENCY), + bind(&BytraceEventParser::CpuFrequencyEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_WORKQUEUE_EXECUTE_START), + bind(&BytraceEventParser::WorkqueueExecuteStartEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_WORKQUEUE_EXECUTE_END), + bind(&BytraceEventParser::WorkqueueExecuteEndEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_CLOCK_SET_RATE), + bind(&BytraceEventParser::SetRateEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_CLOCK_ENABLE), + bind(&BytraceEventParser::ClockEnableEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_CLOCK_DISABLE), + bind(&BytraceEventParser::ClockDisableEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_REGULATOR_SET_VOLTAGE), + bind(&BytraceEventParser::RegulatorSetVoltageEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_REGULATOR_SET_VOLTAGE_COMPLETE), + bind(&BytraceEventParser::RegulatorSetVoltageCompleteEvent, this, std::placeholders::_1, + std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_REGULATOR_DISABLE), + bind(&BytraceEventParser::RegulatorDisableEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_REGULATOR_DISABLE_COMPLETE), + bind(&BytraceEventParser::RegulatorDisableCompleteEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_IPI_ENTRY), + bind(&BytraceEventParser::IpiEntryEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_IPI_EXIT), + bind(&BytraceEventParser::IpiExitEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_IRQ_HANDLER_ENTRY), + bind(&BytraceEventParser::IrqHandlerEntryEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_IRQ_HANDLER_EXIT), + bind(&BytraceEventParser::IrqHandlerExitEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_SOFTIRQ_RAISE), + bind(&BytraceEventParser::SoftIrqRaiseEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_SOFTIRQ_ENTRY), + bind(&BytraceEventParser::SoftIrqEntryEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_SOFTIRQ_EXIT), + bind(&BytraceEventParser::SoftIrqExitEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_BINDER_TRANSACTION), + bind(&BytraceEventParser::BinderTransaction, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_BINDER_TRANSACTION_RECEIVED), + bind(&BytraceEventParser::BinderTransactionReceived, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_BINDER_TRANSACTION_ALLOC_BUF), + bind(&BytraceEventParser::BinderTransactionAllocBufEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_SCHED_WAKEUP_NEW), + bind(&BytraceEventParser::SchedWakeupEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_PROCESS_EXIT), + bind(&BytraceEventParser::ProcessExitEvent, this, std::placeholders::_1, std::placeholders::_2)}}; +} + +bool BytraceEventParser::SchedSwitchEvent(const ArgsMap& args, const BytraceLine& line) const +{ + if (args.empty() || args.size() < MIN_SCHED_ARGS_COUNT) { + TS_LOGD("Failed to parse sched_switch event, no args or args size < 6"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_SWITCH, STAT_EVENT_DATA_INVALID); + return false; + } + auto prevCommStr = std::string_view(args.at("prev_comm")); + auto nextCommStr = std::string_view(args.at("next_comm")); + auto prevPrioValue = base::StrToInt32(args.at("prev_prio")); + auto nextPrioValue = base::StrToInt32(args.at("next_prio")); + auto prevPidValue = base::StrToUInt32(args.at("prev_pid")); + auto nextPidValue = base::StrToUInt32(args.at("next_pid")); + if (!(!prevCommStr.empty() && prevPidValue.has_value() && prevPrioValue.has_value() && nextPidValue.has_value() && + nextPrioValue.has_value())) { + TS_LOGD("Failed to parse sched_switch event"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_SWITCH, STAT_EVENT_DATA_INVALID); + return false; + } + auto prevStateStr = args.at("prev_state"); + auto threadState = ThreadState(prevStateStr.c_str()); + uint64_t prevState = threadState.State(); + if (!threadState.IsValid()) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_SWITCH, STAT_EVENT_DATA_INVALID); + } + auto nextInternalTid = 0; + auto uprevtid = 0; + if (streamFilters_->processFilter_->isThreadNameEmpty(nextPidValue.value())) { + nextInternalTid = + streamFilters_->processFilter_->UpdateOrCreateThreadWithName(line.ts, nextPidValue.value(), nextCommStr); + } else { + nextInternalTid = streamFilters_->processFilter_->UpdateOrCreateThread(line.ts, nextPidValue.value()); + } + if (streamFilters_->processFilter_->isThreadNameEmpty(prevPidValue.value())) { + uprevtid = + streamFilters_->processFilter_->UpdateOrCreateThreadWithName(line.ts, prevPidValue.value(), prevCommStr); + } else { + uprevtid = streamFilters_->processFilter_->UpdateOrCreateThread(line.ts, prevPidValue.value()); + } + streamFilters_->cpuFilter_->InsertSwitchEvent(line.ts, line.cpu, uprevtid, + static_cast(prevPrioValue.value()), prevState, + nextInternalTid, static_cast(nextPrioValue.value())); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_SWITCH, STAT_EVENT_RECEIVED); + return true; +} + +bool BytraceEventParser::TaskRenameEvent(const ArgsMap& args, const BytraceLine& line) const +{ + auto prevCommStr = std::string_view(args.at("newcomm")); + auto pidValue = base::StrToUInt32(args.at("pid")); + streamFilters_->processFilter_->UpdateOrCreateThreadWithName(line.ts, pidValue.value(), prevCommStr); + return true; +} + +bool BytraceEventParser::TaskNewtaskEvent(const ArgsMap& args, const BytraceLine& line) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TASK_NEWTASK, STAT_EVENT_RECEIVED); + // the clone flag from txt trace from kernel original is HEX, but when it is converted from proto + // based trace, it will be OCT number, it is not stable, so we decide to ignore it + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TASK_NEWTASK, STAT_EVENT_NOTSUPPORTED); + return true; +} + +bool BytraceEventParser::TracingMarkWriteEvent(const ArgsMap& args, const BytraceLine& line) const +{ + UNUSED(args); + printEventParser_.ParsePrintEvent(line.ts, line.pid, line.argsStr.c_str()); + return true; +} + +bool BytraceEventParser::SchedWakeupEvent(const ArgsMap& args, const BytraceLine& line) const +{ + if (args.size() < MIN_SCHED_WAKEUP_ARGS_COUNT) { + TS_LOGD("Failed to parse SchedWakeupEvent event, no args or args size < 2"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKEUP, STAT_EVENT_DATA_INVALID); + return false; + } + std::optional wakePidValue = base::StrToUInt32(args.at("pid")); + if (!wakePidValue.has_value()) { + TS_LOGD("Failed to convert wake_pid"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKEUP, STAT_EVENT_DATA_INVALID); + return false; + } + DataIndex name = traceDataCache_->GetDataIndex(std::string_view("sched_wakeup")); + auto instants = traceDataCache_->GetInstantsData(); + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(line.ts, wakePidValue.value()); + instants->AppendInstantEventData(line.ts, name, internalTid); + std::optional targetCpu = base::StrToUInt32(args.at("target_cpu")); + if (targetCpu.has_value()) { + traceDataCache_->GetRawData()->AppendRawData(0, line.ts, RAW_SCHED_WAKEUP, targetCpu.value(), internalTid); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKEUP, STAT_EVENT_RECEIVED); + } + return true; +} + +bool BytraceEventParser::SchedWakingEvent(const ArgsMap& args, const BytraceLine& line) const +{ + std::optional wakePidValue = base::StrToUInt32(args.at("pid")); + auto wakePidStr = std::string_view(args.at("comm")); + if (!wakePidValue.has_value()) { + TS_LOGD("Failed to convert wake_pid"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKING, STAT_EVENT_DATA_INVALID); + return false; + } + DataIndex name = traceDataCache_->GetDataIndex(std::string_view("sched_waking")); + auto instants = traceDataCache_->GetInstantsData(); + DataIndex wakePidStrIndex = traceDataCache_->GetDataIndex(wakePidStr); + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThreadWithNameIndex(line.ts, + wakePidValue.value(), + wakePidStrIndex); + streamFilters_->cpuFilter_->InsertWakeupEvent(line.ts, internalTid); + instants->AppendInstantEventData(line.ts, name, internalTid); + std::optional targetCpu = base::StrToUInt32(args.at("target_cpu")); + if (targetCpu.has_value()) { + traceDataCache_->GetRawData()->AppendRawData(0, line.ts, RAW_SCHED_WAKING, targetCpu.value(), internalTid); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKING, STAT_EVENT_RECEIVED); + } + + return true; +} + +bool BytraceEventParser::CpuIdleEvent(const ArgsMap& args, const BytraceLine& line) const +{ + std::optional eventCpuValue = base::StrToUInt32(args.at("cpu_id")); + std::optional newStateValue = base::StrToInt64(args.at("state")); + if (!eventCpuValue.has_value()) { + TS_LOGD("Failed to convert event cpu"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_IDLE, STAT_EVENT_DATA_INVALID); + return false; + } + if (!newStateValue.has_value()) { + TS_LOGD("Failed to convert state"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_IDLE, STAT_EVENT_DATA_INVALID); + return false; + } + auto cpuIdleNameIndex = traceDataCache_->GetDataIndex(line.eventName.c_str()); + streamFilters_->cpuMeasureFilter_->AppendNewMeasureData(eventCpuValue.value(), cpuIdleNameIndex, line.ts, + newStateValue.value()); + // Add cpu_idle event to raw_data_table + traceDataCache_->GetRawData()->AppendRawData(0, line.ts, RAW_CPU_IDLE, eventCpuValue.value(), 0); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_IDLE, STAT_EVENT_RECEIVED); + return true; +} + +bool BytraceEventParser::CpuFrequencyEvent(const ArgsMap& args, const BytraceLine& line) const +{ + std::optional eventCpuValue = base::StrToUInt32(args.at("cpu_id")); + std::optional newStateValue = base::StrToInt64(args.at("state")); + + if (!newStateValue.has_value()) { + TS_LOGD("Failed to convert state"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_FREQUENCY, STAT_EVENT_DATA_INVALID); + return false; + } + if (!eventCpuValue.has_value()) { + TS_LOGD("Failed to convert event cpu"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_FREQUENCY, STAT_EVENT_DATA_INVALID); + return false; + } + + auto cpuidleNameIndex = traceDataCache_->GetDataIndex(line.eventName.c_str()); + streamFilters_->cpuMeasureFilter_->AppendNewMeasureData(eventCpuValue.value(), cpuidleNameIndex, line.ts, + newStateValue.value()); + return true; +} + +bool BytraceEventParser::WorkqueueExecuteStartEvent(const ArgsMap& args, const BytraceLine& line) const +{ + UNUSED(args); + auto splitStr = GetFunctionName(line.argsStr, "function "); + auto splitStrIndex = traceDataCache_->GetDataIndex(splitStr); + bool result = streamFilters_->sliceFilter_->BeginSlice(line.ts, line.pid, 0, workQueueId_, splitStrIndex); + traceDataCache_->GetInternalSlicesData()->AppendDistributeInfo(); + if (result) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_WORKQUEUE_EXECUTE_START, STAT_EVENT_RECEIVED); + return true; + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_WORKQUEUE_EXECUTE_START, STAT_EVENT_DATA_LOST); + return false; + } +} + +bool BytraceEventParser::WorkqueueExecuteEndEvent(const ArgsMap& args, const BytraceLine& line) const +{ + UNUSED(args); + if (streamFilters_->sliceFilter_->EndSlice(line.ts, line.pid, 0)) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_WORKQUEUE_EXECUTE_END, STAT_EVENT_RECEIVED); + return true; + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_WORKQUEUE_EXECUTE_END, STAT_EVENT_NOTMATCH); + return false; + } +} + +bool BytraceEventParser::ProcessExitEvent(const ArgsMap& args, const BytraceLine& line) const +{ + auto comm = std::string_view(args.at("comm")); + auto pid = base::StrToUInt32(args.at("pid")); + if (!pid.has_value()) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_PROCESS_EXIT, STAT_EVENT_DATA_INVALID); + return false; + } + auto itid = streamFilters_->processFilter_->UpdateOrCreateThreadWithName(line.ts, pid.value(), comm); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_PROCESS_EXIT, STAT_EVENT_RECEIVED); + if (streamFilters_->cpuFilter_->InsertProcessExitEvent(line.ts, line.cpu, itid)) { + return true; + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_PROCESS_EXIT, STAT_EVENT_NOTMATCH); + return false; + } +} + +bool BytraceEventParser::SetRateEvent(const ArgsMap& args, const BytraceLine& line) const +{ + auto name = std::string_view(args.at("name")); + auto state = base::StrToInt64(args.at("state")); + auto cpu = base::StrToUInt64(args.at("cpu_id")); + DataIndex nameIndex = traceDataCache_->GetDataIndex(name); + streamFilters_->clockRateFilter_->AppendNewMeasureData(cpu.value(), nameIndex, line.ts, state.value()); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLOCK_SET_RATE, STAT_EVENT_RECEIVED); + return true; +} + +bool BytraceEventParser::ClockEnableEvent(const ArgsMap& args, const BytraceLine& line) const +{ + auto name = std::string_view(args.at("name")); + auto state = base::StrToInt64(args.at("state")); + auto cpuId = base::StrToUInt64(args.at("cpu_id")); + DataIndex nameIndex = traceDataCache_->GetDataIndex(name); + streamFilters_->clockEnableFilter_->AppendNewMeasureData(cpuId.value(), nameIndex, line.ts, state.value()); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLOCK_ENABLE, STAT_EVENT_RECEIVED); + return true; +} +bool BytraceEventParser::ClockDisableEvent(const ArgsMap& args, const BytraceLine& line) const +{ + auto name = std::string_view(args.at("name")); + auto state = base::StrToInt64(args.at("state")); + auto cpuId = base::StrToUInt64(args.at("cpu_id")); + DataIndex nameIndex = traceDataCache_->GetDataIndex(name); + streamFilters_->clockDisableFilter_->AppendNewMeasureData(cpuId.value(), nameIndex, line.ts, state.value()); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLOCK_DISABLE, STAT_EVENT_RECEIVED); + return true; +} + +bool BytraceEventParser::RegulatorSetVoltageEvent(const ArgsMap& args, const BytraceLine& line) const +{ + UNUSED(args); + UNUSED(line); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_REGULATOR_SET_VOLTAGE, STAT_EVENT_RECEIVED); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_REGULATOR_SET_VOLTAGE, STAT_EVENT_NOTSUPPORTED); + return true; +} +bool BytraceEventParser::RegulatorSetVoltageCompleteEvent(const ArgsMap& args, const BytraceLine& line) const +{ + UNUSED(args); + UNUSED(line); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_REGULATOR_SET_VOLTAGE_COMPLETE, STAT_EVENT_RECEIVED); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_REGULATOR_SET_VOLTAGE_COMPLETE, + STAT_EVENT_NOTSUPPORTED); + return true; +} +bool BytraceEventParser::RegulatorDisableEvent(const ArgsMap& args, const BytraceLine& line) const +{ + UNUSED(args); + UNUSED(line); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_REGULATOR_DISABLE, STAT_EVENT_RECEIVED); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_REGULATOR_DISABLE, STAT_EVENT_NOTSUPPORTED); + return true; +} +bool BytraceEventParser::RegulatorDisableCompleteEvent(const ArgsMap& args, const BytraceLine& line) const +{ + UNUSED(args); + UNUSED(line); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_REGULATOR_DISABLE_COMPLETE, STAT_EVENT_RECEIVED); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_REGULATOR_DISABLE_COMPLETE, STAT_EVENT_NOTSUPPORTED); + return true; +} + +bool BytraceEventParser::IpiEntryEvent(const ArgsMap& args, const BytraceLine& line) const +{ + UNUSED(args); + UNUSED(line); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_IPI_ENTRY, STAT_EVENT_RECEIVED); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_IPI_ENTRY, STAT_EVENT_NOTSUPPORTED); + return true; +} +bool BytraceEventParser::IpiExitEvent(const ArgsMap& args, const BytraceLine& line) const +{ + UNUSED(args); + UNUSED(line); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_IPI_EXIT, STAT_EVENT_RECEIVED); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_IPI_EXIT, STAT_EVENT_NOTSUPPORTED); + return true; +} +bool BytraceEventParser::IrqHandlerEntryEvent(const ArgsMap& args, const BytraceLine& line) const +{ + UNUSED(args); + UNUSED(line); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_IRQ_HANDLER_ENTRY, STAT_EVENT_RECEIVED); + auto name = std::string_view(args.at("name")); + streamFilters_->irqFilter_->IrqHandlerEntry(line.ts, line.cpu, traceDataCache_->GetDataIndex(name)); + return true; +} +bool BytraceEventParser::IrqHandlerExitEvent(const ArgsMap& args, const BytraceLine& line) const +{ + UNUSED(args); + UNUSED(line); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_IRQ_HANDLER_EXIT, STAT_EVENT_RECEIVED); + uint32_t ret = (args.at("ret") == "handled") ? 1 : 0; + streamFilters_->irqFilter_->IrqHandlerExit(line.ts, line.cpu, ret); + return true; +} +bool BytraceEventParser::SoftIrqRaiseEvent(const ArgsMap& args, const BytraceLine& line) const +{ + UNUSED(args); + UNUSED(line); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_SOFTIRQ_RAISE, STAT_EVENT_RECEIVED); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_SOFTIRQ_RAISE, STAT_EVENT_NOTSUPPORTED); + return true; +} +bool BytraceEventParser::SoftIrqEntryEvent(const ArgsMap& args, const BytraceLine& line) const +{ + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_SOFTIRQ_ENTRY, STAT_EVENT_RECEIVED); + auto vec = base::StrToUInt32(args.at("vec")); + streamFilters_->irqFilter_->SoftIrqEntry(line.ts, line.cpu, vec.value()); + return true; +} +bool BytraceEventParser::SoftIrqExitEvent(const ArgsMap& args, const BytraceLine& line) const +{ + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_RECEIVED); + auto vec = base::StrToUInt32(args.at("vec")); + streamFilters_->irqFilter_->SoftIrqExit(line.ts, line.cpu, vec.value()); + return true; +} + +bool BytraceEventParser::BinderTransaction(const ArgsMap& args, const BytraceLine& line) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION, STAT_EVENT_RECEIVED); + auto transactionId = base::StrToInt64(args.at("transaction")); + auto destNode = base::StrToUInt32(args.at("dest_node")); + auto destProc = base::StrToUInt32(args.at("dest_proc")); + auto destThread = base::StrToUInt32(args.at("dest_thread")); + auto isReply = base::StrToUInt32(args.at("reply")); + auto flags = base::StrToUInt32(args.at("flags"), base::INTEGER_RADIX_TYPE_HEX); + auto codeStr = base::StrToUInt32(args.at("code"), base::INTEGER_RADIX_TYPE_HEX); + TS_LOGD("ts:%lu, pid:%u, destNode:%u, destTgid:%u, destTid:%u, transactionId:%lu, isReply:%u flags:%u, code:%u", + line.ts, line.pid, destNode.value(), destProc.value(), destThread.value(), transactionId.value(), + isReply.value(), flags.value(), codeStr.value()); + streamFilters_->binderFilter_->SendTraction(line.ts, line.pid, transactionId.value(), destNode.value(), + destProc.value(), destThread.value(), isReply.value(), flags.value(), + codeStr.value()); + return true; +} +bool BytraceEventParser::BinderTransactionReceived(const ArgsMap& args, const BytraceLine& line) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_RECEIVED, STAT_EVENT_RECEIVED); + auto transactionId = base::StrToInt64(args.at("transaction")); + streamFilters_->binderFilter_->ReceiveTraction(line.ts, line.pid, transactionId.value()); + TS_LOGD("ts:%lu, pid:%u, transactionId:%lu", line.ts, line.pid, transactionId.value()); + return true; +} +bool BytraceEventParser::BinderTransactionAllocBufEvent(const ArgsMap& args, const BytraceLine& line) const +{ + UNUSED(args); + UNUSED(line); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_ALLOC_BUF, STAT_EVENT_RECEIVED); + auto dataSize = base::StrToUInt64(args.at("data_size")); + auto offsetsSize = base::StrToUInt64(args.at("offsets_size")); + streamFilters_->binderFilter_->TransactionAllocBuf(line.ts, line.pid, dataSize.value(), offsetsSize.value()); + TS_LOGD("dataSize:%lu, offsetSize:%lu", dataSize.value(), offsetsSize.value()); + return true; +} +bool BytraceEventParser::ParseDataItem(const BytraceLine& line, const ArgsMap& args, uint32_t tgid) const +{ + traceDataCache_->UpdateTraceTime(line.ts); + if (tgid) { + streamFilters_->processFilter_->UpdateOrCreateThreadWithPidAndName(line.pid, tgid, line.task); + } else { + // When tgid is zero, only use tid create thread + streamFilters_->processFilter_->GetOrCreateThreadWithPid(line.pid, tgid); + } + + auto it = eventToFunctionMap_.find(line.eventName); + if (it != eventToFunctionMap_.end()) { + return it->second(args, line); + } + TS_LOGW("UnRecognizable event name:%s", line.eventName.c_str()); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_NOTSUPPORTED); + return false; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.h b/host/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..6f3aee89862234506890581037458f4f38b5d244 --- /dev/null +++ b/host/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_BYTRACE_EVENT_PARSER_H +#define SRC_BYTRACE_EVENT_PARSER_H + +#include + +#include "common_types.h" +#include "event_parser_base.h" +#include "print_event_parser.h" +#include "trace_data_cache.h" +#include "trace_streamer_config.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +using ArgsMap = std::unordered_map; +class BytraceEventParser : private EventParserBase { +public: + BytraceEventParser(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + bool ParseDataItem(const BytraceLine& line, const ArgsMap& args, uint32_t tgid) const; + +private: + using FuncCall = std::function; + bool SchedSwitchEvent(const ArgsMap& args, const BytraceLine& line) const; + bool TaskRenameEvent(const ArgsMap& args, const BytraceLine& line) const; + bool TaskNewtaskEvent(const ArgsMap& args, const BytraceLine& line) const; + bool TracingMarkWriteEvent(const ArgsMap& args, const BytraceLine& line) const; + bool SchedWakeupEvent(const ArgsMap& args, const BytraceLine& line) const; + bool SchedWakingEvent(const ArgsMap& args, const BytraceLine& line) const; + bool CpuIdleEvent(const ArgsMap& args, const BytraceLine& line) const; + bool CpuFrequencyEvent(const ArgsMap& args, const BytraceLine& line) const; + bool WorkqueueExecuteStartEvent(const ArgsMap& args, const BytraceLine& line) const; + bool WorkqueueExecuteEndEvent(const ArgsMap& args, const BytraceLine& line) const; + bool ProcessExitEvent(const ArgsMap& args, const BytraceLine& line) const; + bool SetRateEvent(const ArgsMap& args, const BytraceLine& line) const; + bool ClockEnableEvent(const ArgsMap& args, const BytraceLine& line) const; + bool ClockDisableEvent(const ArgsMap& args, const BytraceLine& line) const; + bool RegulatorSetVoltageEvent(const ArgsMap& args, const BytraceLine& line) const; + bool RegulatorSetVoltageCompleteEvent(const ArgsMap& args, const BytraceLine& line) const; + bool RegulatorDisableEvent(const ArgsMap& args, const BytraceLine& line) const; + bool RegulatorDisableCompleteEvent(const ArgsMap& args, const BytraceLine& line) const; + bool IpiEntryEvent(const ArgsMap& args, const BytraceLine& line) const; + bool IpiExitEvent(const ArgsMap& args, const BytraceLine& line) const; + bool IrqHandlerEntryEvent(const ArgsMap& args, const BytraceLine& line) const; + bool IrqHandlerExitEvent(const ArgsMap& args, const BytraceLine& line) const; + bool SoftIrqRaiseEvent(const ArgsMap& args, const BytraceLine& line) const; + bool SoftIrqEntryEvent(const ArgsMap& args, const BytraceLine& line) const; + bool SoftIrqExitEvent(const ArgsMap& args, const BytraceLine& line) const; + bool BinderTransaction(const ArgsMap& args, const BytraceLine& line) const; + bool BinderTransactionReceived(const ArgsMap& args, const BytraceLine& line) const; + bool BinderTransactionAllocBufEvent(const ArgsMap& args, const BytraceLine& line) const; +private: + const DataIndex ioWaitId_; + const DataIndex workQueueId_; + const DataIndex schedWakeupId_; + const DataIndex schedBlockedReasonId_; + std::map eventToFunctionMap_ = {}; + const unsigned int MIN_SCHED_ARGS_COUNT = 6; + const unsigned int MIN_SCHED_WAKEUP_ARGS_COUNT = 2; + PrintEventParser printEventParser_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // SRC_BYTRACE_EVENT_PARSER_H diff --git a/host/trace_streamer/src/parser/bytrace_parser/bytrace_parser.cpp b/host/trace_streamer/src/parser/bytrace_parser/bytrace_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cdf20e3f9f6ed331b57e73d40fe715be32665c6f --- /dev/null +++ b/host/trace_streamer/src/parser/bytrace_parser/bytrace_parser.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bytrace_parser.h" +#include +#include "binder_filter.h" +#include "cpu_filter.h" +#include "parting_string.h" +#include "stat_filter.h" +namespace SysTuning { +namespace TraceStreamer { +BytraceParser::BytraceParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters) + : ParserBase(filters), + eventParser_(std::make_unique(dataCache, filters)), + dataSegArray(new DataSegment[MAX_SEG_ARRAY_SIZE]) +{ +#ifdef SUPPORTTHREAD + noThread_ = false; +#endif +} + +BytraceParser::~BytraceParser() = default; + +void BytraceParser::WaitForParserEnd() +{ + if (parseThreadStarted_ || filterThreadStarted_) { + toExit_ = true; + while (!exited_) { + usleep(sleepDur_ * sleepDur_); + } + } + streamFilters_->cpuFilter_->FinishCpuEvent(); + streamFilters_->binderFilter_->FinishBinderEvent(); +} +void BytraceParser::ParseTraceDataSegment(std::unique_ptr bufferStr, size_t size) +{ + if (isParsingOver_) { + return; + } + packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]); + auto packagesBegin = packagesBuffer_.begin(); + + while (1) { + auto packagesLine = std::find(packagesBegin, packagesBuffer_.end(), '\n'); + if (packagesLine == packagesBuffer_.end()) { + break; + } + + std::string bufferLine(packagesBegin, packagesLine); + + if (IsTraceComment(bufferLine)) { + traceCommentLines_++; + goto NEXT_LINE; + } + if (bufferLine.empty()) { + parsedTraceInvalidLines_++; + goto NEXT_LINE; + } + + if (bufferLine.find(script_.c_str()) != std::string::npos) { + isParsingOver_ = true; + break; + } + ParseTraceDataItem(bufferLine); + + NEXT_LINE: + packagesBegin = packagesLine + 1; + continue; + } + + if (isParsingOver_) { + packagesBuffer_.clear(); + } else { + packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin); + } + return; +} + +void BytraceParser::ParseTraceDataItem(const std::string& buffer) +{ + int head = rawDataHead_; + while (!toExit_) { + if (dataSegArray[head].status.load() != TS_PARSE_STATUS_INIT) { + TS_LOGD("rawDataHead_:\t%d, parseHead_:\t%d, filterHead_:\t%d\n", rawDataHead_, parseHead_, filterHead_); + usleep(sleepDur_); + continue; + } + dataSegArray[head].seg = std::move(buffer); + dataSegArray[head].status = TS_PARSE_STATUS_SEPRATED; + if (!noThread_) { + rawDataHead_ = (rawDataHead_ + 1) % MAX_SEG_ARRAY_SIZE; + } + break; + } + if (!parseThreadStarted_ && !noThread_) { + parseThreadStarted_ = true; + int tmp = maxThread_; + while (tmp--) { + parserThreadCount_++; + std::thread MatchLineThread(&BytraceParser::ParseThread, this); + MatchLineThread.detach(); + TS_LOGI("parser Thread:%d/%d start working ...\n", maxThread_ - tmp, maxThread_); + } + } + if (noThread_) { + ParserData(dataSegArray[head]); + } + return; +} +int BytraceParser::GetNextSegment() +{ + int head; + dataSegMux_.lock(); + head = parseHead_; + DataSegment& seg = dataSegArray[head]; + if (seg.status.load() != TS_PARSE_STATUS_SEPRATED) { + if (toExit_) { + parserThreadCount_--; + TS_LOGI("exiting parser, parserThread Count:%d\n", parserThreadCount_); + dataSegMux_.unlock(); + if (!parserThreadCount_ && !filterThreadStarted_) { + exited_ = true; + } + return ERROR_CODE_EXIT; + } + if (seg.status == TS_PARSE_STATUS_PARSING) { + dataSegMux_.unlock(); + usleep(sleepDur_); + return ERROR_CODE_NODATA; + } + dataSegMux_.unlock(); + TS_LOGD("ParseThread watting:\t%d, parseHead_:\t%d, filterHead_:\t%d\n", rawDataHead_, parseHead_, filterHead_); + usleep(sleepDur_); + return ERROR_CODE_NODATA; + } + parseHead_ = (parseHead_ + 1) % MAX_SEG_ARRAY_SIZE; + seg.status = TS_PARSE_STATUS_PARSING; + dataSegMux_.unlock(); + return head; +} + +void BytraceParser::GetDataSegAttr(DataSegment& seg, const std::smatch& matcheLine) const +{ + size_t index = 0; + std::string pidStr = matcheLine[++index].str(); + std::optional optionalPid = base::StrToUInt32(pidStr); + if (!optionalPid.has_value()) { + TS_LOGD("Illegal pid: %s", pidStr.c_str()); + seg.status = TS_PARSE_STATUS_INVALID; + return; + } + + std::string tGidStr = matcheLine[++index].str(); + std::string cpuStr = matcheLine[++index].str(); + std::optional optionalCpu = base::StrToUInt32(cpuStr); + if (!optionalCpu.has_value()) { + TS_LOGD("Illegal cpu %s", cpuStr.c_str()); + seg.status = TS_PARSE_STATUS_INVALID; + return; + } + std::string timeStr = matcheLine[++index].str(); + std::optional optionalTime = base::StrToDouble(timeStr); + if (!optionalTime.has_value()) { + TS_LOGD("Illegal ts %s", timeStr.c_str()); + seg.status = TS_PARSE_STATUS_INVALID; + return; + } + std::string eventName = matcheLine[++index].str(); + seg.bufLine.task = StrTrim(matcheLine.prefix()); + if (seg.bufLine.task == "<...>") { + seg.bufLine.task = ""; + } + seg.bufLine.argsStr = StrTrim(matcheLine.suffix()); + seg.bufLine.pid = optionalPid.value(); + seg.bufLine.cpu = optionalCpu.value(); + seg.bufLine.ts = static_cast(optionalTime.value() * 1e9); + seg.bufLine.tGidStr = tGidStr; + seg.bufLine.eventName = eventName; + GetDataSegArgs(seg); + seg.status = TS_PARSE_STATUS_PARSED; +} + +void BytraceParser::GetDataSegArgs(DataSegment& seg) const +{ + seg.args.clear(); + if (seg.bufLine.tGidStr != "-----") { + seg.tgid = base::StrToUInt32(seg.bufLine.tGidStr).value_or(0); + } else { + seg.tgid = 0; + } + + for (base::PartingString ss(seg.bufLine.argsStr, ' '); ss.Next();) { + std::string key; + std::string value; + if (!(std::string(ss.GetCur()).find("=") != std::string::npos)) { + key = "name"; + value = ss.GetCur(); + seg.args.emplace(std::move(key), std::move(value)); + continue; + } + for (base::PartingString inner(ss.GetCur(), '='); inner.Next();) { + if (key.empty()) { + key = inner.GetCur(); + } else { + value = inner.GetCur(); + } + } + seg.args.emplace(std::move(key), std::move(value)); + } +} +void BytraceParser::ParseThread() +{ + while (1) { + int head = GetNextSegment(); + if (head < 0) { + if (head == ERROR_CODE_NODATA) { + continue; + } + if (!filterThreadStarted_) { + exited_ = true; + } + return; + } + DataSegment& seg = dataSegArray[head]; + ParserData(seg); + } +} + +void BytraceParser::ParserData(DataSegment& seg) +{ + std::smatch matcheLine; + if (!std::regex_search(seg.seg, matcheLine, bytraceMatcher_)) { + TS_LOGD("Not support this event (line: %s)", seg.seg.c_str()); + seg.status = TS_PARSE_STATUS_INVALID; + parsedTraceInvalidLines_++; + FilterData(seg); + return; + } else { + parsedTraceValidLines_++; + } + GetDataSegAttr(seg, matcheLine); + if (!filterThreadStarted_ && !noThread_) { + filterThreadStarted_ = true; + std::thread ParserThread(&BytraceParser::FilterThread, this); + ParserThread.detach(); + } + if (noThread_) { + FilterData(seg); + } +} +void BytraceParser::FilterThread() +{ + while (1) { + DataSegment& seg = dataSegArray[filterHead_]; + if (!FilterData(seg)) { + return; + } + } +} +bool BytraceParser::FilterData(DataSegment& seg) +{ + if (seg.status.load() == TS_PARSE_STATUS_INVALID) { + seg.status = TS_PARSE_STATUS_INIT; + if (!noThread_) { + filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE; + } + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID); + return true; + } + if (seg.status.load() != TS_PARSE_STATUS_PARSED) { + if (toExit_ && !parserThreadCount_) { + TS_LOGI("exiting FilterThread Thread\n"); + exited_ = true; + filterThreadStarted_ = false; + return false; + } + if (!noThread_) { // wasm do not allow thread + usleep(sleepDur_); + } + return true; + } + BytraceLine line = seg.bufLine; + uint32_t tgid = seg.tgid; + eventParser_->ParseDataItem(line, seg.args, tgid); + if (!noThread_) { + filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE; + } + seg.status = TS_PARSE_STATUS_INIT; + return true; +} +// Remove space at the beginning and end of the string +std::string BytraceParser::StrTrim(const std::string& input) const +{ + std::string str = input; + auto posBegin = std::find_if(str.begin(), str.end(), IsNotSpace); + str.erase(str.begin(), posBegin); + + auto posEnd = std::find_if(str.rbegin(), str.rend(), IsNotSpace); + str.erase(posEnd.base(), str.end()); + + return str; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/bytrace_parser/bytrace_parser.h b/host/trace_streamer/src/parser/bytrace_parser/bytrace_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..95c552efed3e2370db24ac3847c9b2cbfab451d8 --- /dev/null +++ b/host/trace_streamer/src/parser/bytrace_parser/bytrace_parser.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BYTRACE_PARSER_H +#define BYTRACE_PARSER_H + +#include +#include +#include +#include + +#include "bytrace_event_parser.h" +#include "log.h" +#include "parser_base.h" +#include "string_to_numerical.h" +#include "trace_data/trace_data_cache.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +class BytraceParser : public ParserBase { +public: + BytraceParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters); + ~BytraceParser(); + + void ParseTraceDataSegment(std::unique_ptr bufferStr, size_t size) override; + size_t ParsedTraceValidLines() const + { + return parsedTraceValidLines_; + } + size_t ParsedTraceInvalidLines() const + { + return parsedTraceInvalidLines_; + } + size_t TraceCommentLines() const + { + return traceCommentLines_; + } + void WaitForParserEnd(); + +private: + enum ErrorCode { ERROR_CODE_EXIT = -2, ERROR_CODE_NODATA = -1 }; + int GetNextSegment(); + void GetDataSegAttr(DataSegment& seg, const std::smatch& matcheLine) const; + void GetDataSegArgs(DataSegment& seg) const; + void FilterThread(); + inline static bool IsNotSpace(char c) + { + return !std::isspace(c); + } + inline static bool IsTraceComment(const std::string& buffer) + { + return ((buffer[0] == '#') || buffer.find("TASK-PID") != std::string::npos); + } + + void ParseTraceDataItem(const std::string& buffer) override; + std::string StrTrim(const std::string& input) const; + void ParseThread(); + void ParserData(DataSegment& seg); + bool FilterData(DataSegment& seg); + +private: + using ArgsMap = std::unordered_map; + bool isParsingOver_ = false; + std::unique_ptr eventParser_; + const std::regex bytraceMatcher_ = std::regex(R"(-(\d+)\s+\(?\s*(\d+|-+)?\)?\s?\[(\d+)\]\s*)" + R"([a-zA-Z0-9.]{0,5}\s+(\d+\.\d+):\s+(\S+):)"); + + const std::string script_ = R"()"; + + size_t parsedTraceValidLines_ = 0; + size_t parsedTraceInvalidLines_ = 0; + size_t traceCommentLines_ = 0; + std::mutex dataSegMux_; + int parseHead_ = 0; + std::atomic filterThreadStarted_{false}; + bool parseThreadStarted_ = false; + const int MAX_SEG_ARRAY_SIZE = 5000; + const int maxThread_ = 4; // 4 is the best on ubuntu 113MB/s, max 138MB/s, 6 is best on mac m1 21MB/s, + int parserThreadCount_ = 0; + bool toExit_ = false; + bool exited_ = false; + std::unique_ptr dataSegArray; + int rawDataHead_ = 0; + int filterHead_ = 0; + const int sleepDur_ = 100; + bool noThread_ = true; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // _BYTRACE_PARSER_H_ diff --git a/host/trace_streamer/src/parser/common_types.h b/host/trace_streamer/src/parser/common_types.h new file mode 100644 index 0000000000000000000000000000000000000000..5d7c0a416ad3c77523cc5b4a16cadd8842947ae7 --- /dev/null +++ b/host/trace_streamer/src/parser/common_types.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BYTRACE_COMMON_TYPES_H +#define BYTRACE_COMMON_TYPES_H + +#include +#include +#include +#include "hidump_plugin_result.pb.h" +#include "hilog_plugin_result.pb.h" +#include "memory_plugin_result.pb.h" +#include "native_hook_result.pb.h" +#include "services/common_types.pb.h" +#include "trace_plugin_result.pb.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +enum ParseResult { ERROR = 0, SUCCESS }; +enum RawType { RAW_CPU_IDLE = 1, RAW_SCHED_WAKEUP = 2, RAW_SCHED_WAKING = 3 }; + +enum Stat : uint32_t { + RUNNABLE = 0, + INTERRUPTABLESLEEP = 1, + UNINTERRUPTIBLESLEEP = 2, + STOPPED = 4, + TRACED = 8, // the process is being debug + EXITDEAD = 16, + EXITZOMBIE = 32, + TASKDEAD = 64, + WAKEKILL = 128, + WAKING = 256, + PARKED = 512, + NOLOAD = 1024, + TASKNEW = 2048, + VALID = 0X8000, +}; + +struct BytraceLine { + uint64_t ts = 0; + uint32_t pid = 0; + uint32_t cpu = 0; + + std::string task; // thread name + std::string pidStr; // thread str + std::string tGidStr; // process thread_group + std::string eventName; + std::string argsStr; +}; +enum ParseStatus { + TS_PARSE_STATUS_INIT = 0, + TS_PARSE_STATUS_SEPRATED = 1, + TS_PARSE_STATUS_PARSING = 2, + TS_PARSE_STATUS_PARSED = 3, + TS_PARSE_STATUS_INVALID = 4 +}; +struct DataSegment { + std::string seg; + BytraceLine bufLine; + std::unordered_map args; + uint32_t tgid; + std::atomic status{TS_PARSE_STATUS_INIT}; +}; +enum DataSourceType { + DATA_SOURCE_TYPE_TRACE, + DATA_SOURCE_TYPE_MEM, + DATA_SOURCE_TYPE_HILOG, + DATA_SOURCE_TYPE_HEAP, + DATA_SOURCE_TYPE_FPS +}; +// 注意使用完之后恢复初始化状态,保证下次使用不会出现数据混乱。 +struct HtraceDataSegment { + std::string seg; + MemoryData memData; + HilogInfo logData; + BatchNativeHookData batchNativeHookData; + HidumpInfo hidumpInfo; + uint64_t timeStamp; + TracePluginResult traceData; + BuiltinClocks clockId; + DataSourceType dataType; + std::atomic status{TS_PARSE_STATUS_INIT}; +}; + +struct TracePoint { + char phase_ = '\0'; + uint32_t tgid_ = 0; + std::string name_ = ""; + uint64_t value_ = 0; + std::string categoryGroup_ = ""; + // Distributed Data + std::string chainId_ = ""; + std::string spanId_ = ""; + std::string parentSpanId_ = ""; + std::string flag_ = ""; + std::string args_ = ""; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // _BYTRACE_COMMON_TYPES_H_ diff --git a/host/trace_streamer/src/parser/event_parser_base.cpp b/host/trace_streamer/src/parser/event_parser_base.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a4bdbf4f5e4e7ac919ecf6af18f1fe7b6e680f3d --- /dev/null +++ b/host/trace_streamer/src/parser/event_parser_base.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "event_parser_base.h" +namespace SysTuning { +namespace TraceStreamer { +EventParserBase::EventParserBase(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : streamFilters_(filter), traceDataCache_(dataCache) +{ +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/event_parser_base.h b/host/trace_streamer/src/parser/event_parser_base.h new file mode 100644 index 0000000000000000000000000000000000000000..2df1e46da189ba8b03ad393e4f0d8498d81babcf --- /dev/null +++ b/host/trace_streamer/src/parser/event_parser_base.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_EVENT_PARSER_BASE_H +#define SRC_EVENT_PARSER_BASE_H +#include "trace_data_cache.h" +#include "trace_streamer_config.h" +#include "trace_streamer_filters.h" +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::TraceCfg; +class EventParserBase { +public: + EventParserBase(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + virtual ~EventParserBase() = default; + +public: + const TraceStreamerFilters* streamFilters_; + TraceDataCache* traceDataCache_; +protected: + TraceStreamerConfig config_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // SRC_PARSER_BASE_H diff --git a/host/trace_streamer/src/parser/htrace_parser/BUILD.gn b/host/trace_streamer/src/parser/htrace_parser/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..17f81c4ca59502ee62eaccedc4ab5850fa51c7af --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/BUILD.gn @@ -0,0 +1,78 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import("//build/ohos.gni") +import("../../ts.gni") +ohos_source_set("htrace_parser_src") { + sources = [ + "../parser_base.cpp", + "htrace_clock_detail_parser.cpp", + "htrace_clock_detail_parser.h", + "htrace_cpu_parser/htrace_cpu_detail_parser.cpp", + "htrace_cpu_parser/htrace_cpu_detail_parser.h", + "htrace_event_parser/htrace_event_parser.cpp", + "htrace_event_parser/htrace_event_parser.h", + "htrace_hidump_parser.cpp", + "htrace_hidump_parser.h", + "htrace_hilog_parser.cpp", + "htrace_hilog_parser.h", + "htrace_mem_parser.cpp", + "htrace_mem_parser.h", + "htrace_native_hook_parser.cpp", + "htrace_native_hook_parser.h", + "htrace_parser.cpp", + "htrace_symbols_detail_parser.cpp", + "htrace_symbols_detail_parser.h", + ] + include_dirs = [ + "htrace_event_parser", + "htrace_cpu_parser", + ".", + "${OHOS_PROTO_GEN}", + "${OHOS_PROTO_GEN}/types/plugins/memory_data", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data", + "${OHOS_PROTO_GEN}/types/plugins/hilog_data", + "${OHOS_PROTO_GEN}/types/plugins/native_hook", + "${OHOS_PROTO_GEN}/types/plugins/hidump_data", + "../../include", + "../../", + "../", + "../../trace_data", + "../../cfg", + "../../trace_streamer", + "//third_party/protobuf/src", + "//third_party/sqlite/include", + "../../filter", + "../../base", + ] + if (enable_ts_utest && !use_wasm) { + cflags = [ + "-fprofile-arcs", + "-ftest-coverage", + ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + } + public_deps = [] + deps = [] +} +group("htrace_parser") { + deps = [ + ":htrace_parser_src", + "//prebuilts/protos:ts_proto_data_cpp", + "//third_party/protobuf:protobuf", + "//third_party/protobuf:protobuf_lite", + ] +} diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_clock_detail_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_clock_detail_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc4158b5729945ff9274a810339d437bed092461 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_clock_detail_parser.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "htrace_clock_detail_parser.h" +#include "clock_filter.h" +#include "htrace_event_parser.h" +#include "measure_filter.h" +#include "process_filter.h" +#include "stat_filter.h" +#include "symbols_filter.h" +namespace SysTuning { +namespace TraceStreamer { +HtraceClockDetailParser::HtraceClockDetailParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : streamFilters_(ctx), traceDataCache_(dataCache) +{ + for (auto i = 0; i < MEM_MAX; i++) { + memNameDictMap_.insert(std::make_pair(static_cast(i), + traceDataCache_->GetDataIndex(config_.memNameMap_.at(static_cast(i))))); + } +} + +HtraceClockDetailParser::~HtraceClockDetailParser() = default; +void HtraceClockDetailParser::Parse(TracePluginResult& tracePacket) const +{ + if (!tracePacket.clocks_detail_size()) { + return; + } + std::vector snapShot; + TS_LOGI("got clock snapshot"); + for (int i = 0; i < tracePacket.clocks_detail_size(); i++) { + auto clockInfo = tracePacket.mutable_clocks_detail(i); + TS_LOGI("clockid:%d, ts:%llu", clockInfo->id(), + static_cast(clockInfo->time().tv_nsec() + clockInfo->time().tv_sec() * SEC_TO_NS)); + snapShot.push_back(SnapShot{static_cast(clockInfo->id()), + clockInfo->time().tv_nsec() + clockInfo->time().tv_sec() * SEC_TO_NS}); + streamFilters_->clockFilter_->AddClockSnapshot(snapShot); + } + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLOCK_SYNC, STAT_EVENT_RECEIVED); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_clock_detail_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_clock_detail_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..c36c73d675696cef9c455094ee484202513fa391 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_clock_detail_parser.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HTRACE_CLOCKDETAIL_PARSER_H +#define HTRACE_CLOCKDETAIL_PARSER_H +#include +#include +#include +#include +#include +#include "trace_data/trace_data_cache.h" +#include "trace_plugin_result.pb.h" +#include "trace_streamer_config.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +class HtraceClockDetailParser { +public: + HtraceClockDetailParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters); + ~HtraceClockDetailParser(); + void Parse(TracePluginResult& tracePacket) const; + +private: + const TraceStreamerFilters* streamFilters_; + TraceDataCache* traceDataCache_; + TraceStreamerConfig config_ = {}; + std::map memNameDictMap_ = {}; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_CLOCKDETAIL_PARSER_H diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb37c7c707ad4528c20dd3bbf8cf2364c67203ee --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "htrace_cpu_detail_parser.h" +#include "htrace_event_parser.h" +#include "stat_filter.h" +namespace SysTuning { +namespace TraceStreamer { +HtraceCpuDetailParser::HtraceCpuDetailParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : eventParser_(std::make_unique(dataCache, ctx)) +{ +} + +HtraceCpuDetailParser::~HtraceCpuDetailParser() = default; +void HtraceCpuDetailParser::Parse(TracePluginResult& tracePacket, BuiltinClocks clock) +{ + if (!tracePacket.ftrace_cpu_detail_size()) { + return; + } + + for (int i = 0; i < tracePacket.ftrace_cpu_detail_size(); i++) { + FtraceCpuDetailMsg* cpuDetail = tracePacket.mutable_ftrace_cpu_detail(i); + eventParser_->ParseDataItem(cpuDetail, clock); + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..f422770ff6887a0c8f9ed4baa533b90238d530d4 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HTRACE_CPU_DETAIL_PARSER_H +#define HTRACE_CPU_DETAIL_PARSER_H +#include +#include +#include +#include +#include +#include "event_parser_base.h" +#include "htrace_event_parser.h" +#include "log.h" +#include "parser_base.h" +#include "trace_data/trace_data_cache.h" +#include "trace_plugin_result.pb.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +class HtraceCpuDetailParser { +public: + HtraceCpuDetailParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~HtraceCpuDetailParser(); + void Parse(TracePluginResult& tracePacket, BuiltinClocks clock); + +private: + std::unique_ptr eventParser_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_CPU_DETAIL_PARSER_H_ diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_event_parser/htrace_event_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_event_parser/htrace_event_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..20055374ced5ef04fd9bcb4fb57fec5728bb8e45 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_event_parser/htrace_event_parser.cpp @@ -0,0 +1,671 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "htrace_event_parser.h" +#include +#include "binder_filter.h" +#include "binder.pb.h" +#include "clock_filter.h" +#include "cpu_filter.h" +#include "irq_filter.h" +#include "irq.pb.h" +#include "log.h" +#include "measure_filter.h" +#include "process_filter.h" +#include "slice_filter.h" +#include "stat_filter.h" +#include "symbols_filter.h" +#include "thread_state.h" +namespace SysTuning { +namespace TraceStreamer { +HtraceEventParser::HtraceEventParser(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : EventParserBase(dataCache, filter), + workQueueId_(dataCache->dataDict_.GetStringIndex("workqueue")), + printEventParser_(traceDataCache_, streamFilters_) +{ + eventToFunctionMap_ = {{config_.eventNameMap_.at(TRACE_EVENT_BINDER_TRANSACTION), + std::bind(&HtraceEventParser::BinderTractionEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_BINDER_TRANSACTION_RECEIVED), + std::bind(&HtraceEventParser::BinderTractionReceivedEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_BINDER_TRANSACTION_ALLOC_BUF), + std::bind(&HtraceEventParser::BinderTractionAllocBufEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_BINDER_TRANSACTION_LOCK), + std::bind(&HtraceEventParser::BinderTractionLockEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_BINDER_TRANSACTION_LOCKED), + std::bind(&HtraceEventParser::BinderTractionLockedEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_BINDER_TRANSACTION_UNLOCK), + std::bind(&HtraceEventParser::BinderTractionUnLockEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_SCHED_SWITCH), + std::bind(&HtraceEventParser::SchedSwitchEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_TASK_RENAME), + std::bind(&HtraceEventParser::TaskRenameEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_TASK_NEWTASK), + std::bind(&HtraceEventParser::TaskNewtaskEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_PRINT), + std::bind(&HtraceEventParser::ParsePrintEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_SCHED_WAKEUP), + std::bind(&HtraceEventParser::SchedWakeupEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_SCHED_WAKEUP_NEW), + std::bind(&HtraceEventParser::SchedWakeupNewEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_PROCESS_EXIT), + std::bind(&HtraceEventParser::ProcessExitEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_PROCESS_FREE), + std::bind(&HtraceEventParser::ProcessFreeEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_SCHED_WAKING), + std::bind(&HtraceEventParser::SchedWakingEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_CPU_IDLE), + std::bind(&HtraceEventParser::CpuIdleEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_CPU_FREQUENCY), + std::bind(&HtraceEventParser::CpuFrequencyEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_SUSPEND_RESUME), + std::bind(&HtraceEventParser::SuspendResumeEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_WORKQUEUE_EXECUTE_START), + std::bind(&HtraceEventParser::WorkqueueExecuteStartEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_WORKQUEUE_EXECUTE_END), + std::bind(&HtraceEventParser::WorkqueueExecuteEndEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_CLOCK_SET_RATE), + std::bind(&HtraceEventParser::ClockSetRateEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_CLOCK_ENABLE), + std::bind(&HtraceEventParser::ClockEnableEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_CLOCK_DISABLE), + std::bind(&HtraceEventParser::ClockDisableEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_CLK_SET_RATE), + std::bind(&HtraceEventParser::ClkSetRateEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_CLK_ENABLE), + std::bind(&HtraceEventParser::ClkEnableEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_CLK_DISABLE), + std::bind(&HtraceEventParser::ClkDisableEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_IRQ_HANDLER_ENTRY), + std::bind(&HtraceEventParser::IrqHandlerEntryEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_IRQ_HANDLER_EXIT), + std::bind(&HtraceEventParser::IrqHandlerExitEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_SOFTIRQ_ENTRY), + std::bind(&HtraceEventParser::SoftIrqEntryEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_SOFTIRQ_RAISE), + std::bind(&HtraceEventParser::SoftIrqRaiseEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_SOFTIRQ_EXIT), + std::bind(&HtraceEventParser::SoftIrqExitEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_SYS_ENTRY), + std::bind(&HtraceEventParser::SysEnterEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_SYS_EXIT), + std::bind(&HtraceEventParser::SysExitEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_OOM_SCORE_ADJ_UPDATE), + std::bind(&HtraceEventParser::OomScoreAdjUdate, this, std::placeholders::_1)}}; +} + +HtraceEventParser::~HtraceEventParser() +{ + TS_LOGI("thread count:%u", static_cast(tids_.size())); + TS_LOGI("process count:%u", static_cast(pids_.size())); + TS_LOGI("ftrace ts MIN:%llu, MAX:%llu", static_cast(traceStartTime_), + static_cast(traceEndTime_)); +} +void HtraceEventParser::ParseDataItem(const FtraceCpuDetailMsg* cpuDetail, BuiltinClocks clock) +{ + eventCpu_ = cpuDetail->cpu(); + auto events = cpuDetail->event(); + if (!events.size()) { + return; + } + if (cpuDetail->overwrite()) { + if (!lastOverwrite_) { + lastOverwrite_ = cpuDetail->overwrite(); + } + if (lastOverwrite_ != cpuDetail->overwrite()) { + TS_LOGW("lost events:%lu", cpuDetail->overwrite() - lastOverwrite_); + lastOverwrite_ = cpuDetail->overwrite(); + } + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_LOST); + } + // parser cpu event + for (auto i = 0; i < events.size(); i++) { + auto event = cpuDetail->event(i); + eventTimestamp_ = event.timestamp(); + traceStartTime_ = std::min(traceStartTime_, eventTimestamp_); + traceEndTime_ = std::max(traceEndTime_, eventTimestamp_); + eventTimestamp_ = streamFilters_->clockFilter_->ToPrimaryTraceTime(clock, eventTimestamp_); + traceDataCache_->UpdateTraceTime(eventTimestamp_); + if (event.tgid() != INVALID_INT32) { + eventPid_ = event.tgid(); + if (!pids_.count(eventPid_)) { + pids_.insert(eventPid_); + } + streamFilters_->processFilter_->GetOrCreateThreadWithPid(eventPid_, eventPid_); + } + if (event.has_sched_switch_format()) { + InvokeFunc(TRACE_EVENT_SCHED_SWITCH, event.sched_switch_format()); + } else if (event.has_task_rename_format()) { + InvokeFunc(TRACE_EVENT_TASK_RENAME, event.task_rename_format()); + } else if (event.has_task_newtask_format()) { + InvokeFunc(TRACE_EVENT_TASK_NEWTASK, event.task_newtask_format()); + } else if (event.has_sched_wakeup_format()) { + InvokeFunc(TRACE_EVENT_SCHED_WAKEUP, event.sched_wakeup_format()); + } else if (event.has_sched_wakeup_new_format()) { + InvokeFunc(TRACE_EVENT_SCHED_WAKEUP, event.sched_wakeup_new_format()); + } else if (event.has_sched_process_exit_format()) { + InvokeFunc(TRACE_EVENT_PROCESS_EXIT, event.sched_process_exit_format()); + } else if (event.has_sched_process_free_format()) { + InvokeFunc(TRACE_EVENT_PROCESS_FREE, event.sched_process_free_format()); + } else if (event.has_sched_waking_format()) { + InvokeFunc(TRACE_EVENT_SCHED_WAKING, event.sched_waking_format()); + } else if (event.has_cpu_idle_format()) { + InvokeFunc(TRACE_EVENT_CPU_IDLE, event.cpu_idle_format()); + } else if (event.has_cpu_frequency_format()) { + InvokeFunc(TRACE_EVENT_CPU_FREQUENCY, event.cpu_frequency_format()); + } else if (event.has_print_format()) { + InvokeFunc(TRACE_EVENT_PRINT, event.print_format()); + } else if (event.has_suspend_resume_format()) { + InvokeFunc(TRACE_EVENT_SUSPEND_RESUME, event.suspend_resume_format()); + } else if (event.has_workqueue_execute_start_format()) { + InvokeFunc(TRACE_EVENT_WORKQUEUE_EXECUTE_START, event.workqueue_execute_start_format()); + } else if (event.has_workqueue_execute_end_format()) { + InvokeFunc(TRACE_EVENT_WORKQUEUE_EXECUTE_END, event.workqueue_execute_end_format()); + } else if (event.has_clock_disable_format()) { + InvokeFunc(TRACE_EVENT_CLOCK_DISABLE, event.clock_disable_format()); + } else if (event.has_clock_enable_format()) { + InvokeFunc(TRACE_EVENT_CLOCK_ENABLE, event.clock_enable_format()); + } else if (event.has_clock_set_rate_format()) { + InvokeFunc(TRACE_EVENT_CLOCK_SET_RATE, event.clock_set_rate_format()); + } else if (event.has_clk_disable_format()) { + InvokeFunc(TRACE_EVENT_CLK_DISABLE, event.clk_disable_format()); + } else if (event.has_clk_enable_format()) { + InvokeFunc(TRACE_EVENT_CLK_ENABLE, event.clk_enable_format()); + } else if (event.has_clk_set_rate_format()) { + InvokeFunc(TRACE_EVENT_CLK_SET_RATE, event.clk_set_rate_format()); + } else if (event.has_sys_enter_format()) { + InvokeFunc(TRACE_EVENT_SYS_ENTRY, event.sys_enter_format()); + } else if (event.has_sys_exit_format()) { + InvokeFunc(TRACE_EVENT_SYS_EXIT, event.sys_exit_format()); + } else if (event.has_binder_transaction_format()) { + InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION, event.binder_transaction_format()); + } else if (event.has_binder_transaction_received_format()) { + InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_RECEIVED, event.binder_transaction_received_format()); + } else if (event.has_binder_transaction_alloc_buf_format()) { + InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_ALLOC_BUF, event.binder_transaction_alloc_buf_format()); + } else if (event.has_binder_lock_format()) { + InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_LOCK, event.binder_lock_format()); + } else if (event.has_binder_unlock_format()) { + InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_UNLOCK, event.binder_unlock_format()); + } else if (event.has_binder_locked_format()) { + InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_LOCKED, event.binder_locked_format()); + } else if (event.has_irq_handler_entry_format()) { + InvokeFunc(TRACE_EVENT_IRQ_HANDLER_ENTRY, event.irq_handler_entry_format()); + } else if (event.has_irq_handler_exit_format()) { + InvokeFunc(TRACE_EVENT_IRQ_HANDLER_EXIT, event.irq_handler_exit_format()); + } else if (event.has_softirq_entry_format()) { + InvokeFunc(TRACE_EVENT_SOFTIRQ_ENTRY, event.softirq_entry_format()); + } else if (event.has_softirq_exit_format()) { + InvokeFunc(TRACE_EVENT_SOFTIRQ_EXIT, event.softirq_exit_format()); + } else if (event.has_oom_score_adj_update_format()) { + InvokeFunc(TRACE_EVENT_OOM_SCORE_ADJ_UPDATE, event.softirq_exit_format()); + } else if (event.has_signal_generate_format()) { + InvokeFunc(TRACE_EVENT_SIGNAL_GENERATE, event.signal_generate_format()); + } else if (event.has_signal_deliver_format()) { + InvokeFunc(TRACE_EVENT_SIGNAL_DELIVER, event.signal_deliver_format()); + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, + STAT_EVENT_NOTSUPPORTED); + TS_LOGD("has_rpc_socket_shutdown_format\n"); + } + } +} + +bool HtraceEventParser::BinderTractionAllocBufEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_ALLOC_BUF, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + uint64_t dataSize = msg.data_size(); + uint64_t offsetsSize = msg.offsets_size(); + streamFilters_->binderFilter_->TransactionAllocBuf(eventTimestamp_, eventPid_, dataSize, offsetsSize); + TS_LOGD("dataSize:%lu, offsetSize:%lu", dataSize, offsetsSize); + return true; +} +bool HtraceEventParser::BinderTractionEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + int32_t destNode = msg.target_node(); + int32_t destTgid = msg.to_proc(); + int32_t destTid = msg.to_thread(); + int32_t transactionId = msg.debug_id(); + bool isReply = msg.reply() == 1; + uint32_t flags = msg.flags(); + TS_LOGD("destNode:%d, destTgid:%d, destTid:%d, transactionId:%d, isReply:%d flags:%d, code:%d", destNode, destTgid, + destTid, transactionId, isReply, flags, msg.code()); + streamFilters_->binderFilter_->SendTraction(eventTimestamp_, eventPid_, transactionId, destNode, destTgid, destTid, + isReply, flags, msg.code()); + return true; +} +bool HtraceEventParser::BinderTractionReceivedEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_RECEIVED, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + int32_t transactionId = msg.debug_id(); + streamFilters_->binderFilter_->ReceiveTraction(eventTimestamp_, eventPid_, transactionId); + TS_LOGD("transactionId:%d", transactionId); + return true; +} +bool HtraceEventParser::BinderTractionLockEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_LOCK, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + std::string tag = msg.tag(); + streamFilters_->binderFilter_->TractionLock(eventTimestamp_, eventPid_, tag); + TS_LOGD("tag:%s", tag.c_str()); + return true; +} +bool HtraceEventParser::BinderTractionLockedEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_LOCKED, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + std::string tag = msg.tag(); + streamFilters_->binderFilter_->TractionLocked(eventTimestamp_, eventPid_, tag); + return true; +} +bool HtraceEventParser::BinderTractionUnLockEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_UNLOCK, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + std::string tag = msg.tag(); + TS_LOGD("tag:%s", tag.c_str()); + streamFilters_->binderFilter_->TractionUnlock(eventTimestamp_, eventPid_, tag); + return true; +} +bool HtraceEventParser::SchedSwitchEvent(const MessageLite& event) +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_SWITCH, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + uint32_t prevPrioValue = msg.prev_prio(); + uint32_t nextPrioValue = msg.next_prio(); + uint32_t prevPidValue = msg.prev_pid(); + uint32_t nextPidValue = msg.next_pid(); + if (!tids_.count(prevPidValue)) { + tids_.insert(prevPidValue); + } + if (!tids_.count(nextPidValue)) { + tids_.insert(nextPidValue); + } + std::string prevCommStr = msg.prev_comm(); + std::string nextCommStr = msg.next_comm(); + auto prevState = msg.prev_state(); + + auto nextInternalTid = + streamFilters_->processFilter_->UpdateOrCreateThreadWithName(eventTimestamp_, nextPidValue, nextCommStr); + auto uprevtid = + streamFilters_->processFilter_->UpdateOrCreateThreadWithName(eventTimestamp_, prevPidValue, prevCommStr); + streamFilters_->cpuFilter_->InsertSwitchEvent(eventTimestamp_, eventCpu_, uprevtid, + static_cast(prevPrioValue), prevState, nextInternalTid, + static_cast(nextPrioValue)); + return true; +} +bool HtraceEventParser::ProcessExitEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_PROCESS_EXIT, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + uint32_t pidValue = msg.pid(); + std::string commStr = msg.comm(); + auto iTid = streamFilters_->processFilter_->UpdateOrCreateThreadWithName(eventTimestamp_, pidValue, commStr); + if (streamFilters_->cpuFilter_->InsertProcessExitEvent(eventTimestamp_, eventCpu_, iTid)) { + return true; + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_PROCESS_EXIT, STAT_EVENT_NOTMATCH); + return false; + } +} +bool HtraceEventParser::ProcessFreeEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_PROCESS_FREE, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + uint32_t pidValue = msg.pid(); + std::string commStr = msg.comm(); + auto iTid = streamFilters_->processFilter_->UpdateOrCreateThreadWithName(eventTimestamp_, pidValue, commStr); + if (streamFilters_->cpuFilter_->InsertProcessFreeEvent(eventTimestamp_, iTid)) { + return true; + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_PROCESS_FREE, STAT_EVENT_NOTMATCH); + return false; + } +} +bool HtraceEventParser::TaskRenameEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TASK_RENAME, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + auto prevCommStr = msg.newcomm(); + auto pidValue = msg.pid(); + streamFilters_->processFilter_->UpdateOrCreateProcessWithName(pidValue, prevCommStr); + return true; +} +bool HtraceEventParser::TaskNewtaskEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TASK_NEWTASK, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + auto commonStr = msg.comm(); + auto pidValue = msg.pid(); + + uint32_t ftracePid = 0; + if (eventPid_ != INVALID_UINT32) { + ftracePid = eventPid_; + } + + static const uint32_t threadPid = 2; + static const uint32_t cloneThread = 0x00010000; + auto cloneFlags = msg.clone_flags(); + if ((cloneFlags & cloneThread) == 0 && ftracePid != threadPid) { + streamFilters_->processFilter_->UpdateOrCreateProcessWithName(pidValue, commonStr); + } else if (ftracePid == threadPid) { + streamFilters_->processFilter_->GetOrCreateThreadWithPid(pidValue, threadPid); + } + return true; +} +bool HtraceEventParser::ParsePrintEvent(const MessageLite& event) +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_PRINT, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + printEventParser_.ParsePrintEvent(eventTimestamp_, eventPid_, msg.buf().c_str()); + if (!pids_.count(eventPid_)) { + pids_.insert(eventPid_); + } + return true; +} +bool HtraceEventParser::SchedWakeupEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKEUP, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + DataIndex name = traceDataCache_->GetDataIndex(std::string_view("sched_wakeup")); + auto instants = traceDataCache_->GetInstantsData(); + + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, msg.pid()); + instants->AppendInstantEventData(eventTimestamp_, name, internalTid); + + std::optional targetCpu = msg.target_cpu(); + if (targetCpu.has_value()) { + traceDataCache_->GetRawData()->AppendRawData(0, eventTimestamp_, RAW_SCHED_WAKEUP, targetCpu.value(), + internalTid); + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKEUP, STAT_EVENT_DATA_INVALID); + } + return true; +} +bool HtraceEventParser::SchedWakeupNewEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKEUP_NEW, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + DataIndex name = traceDataCache_->GetDataIndex(std::string_view("sched_wakeup_new")); + auto instants = traceDataCache_->GetInstantsData(); + + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, msg.pid()); + instants->AppendInstantEventData(eventTimestamp_, name, internalTid); + + std::optional targetCpu = msg.target_cpu(); + if (targetCpu.has_value()) { + traceDataCache_->GetRawData()->AppendRawData(0, eventTimestamp_, RAW_SCHED_WAKEUP, targetCpu.value(), + internalTid); + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKEUP_NEW, STAT_EVENT_DATA_INVALID); + } + return true; +} +bool HtraceEventParser::SchedWakingEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKING, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + std::optional wakePidValue = msg.pid(); + if (!wakePidValue.has_value()) { + TS_LOGD("Failed to convert wake_pid"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKING, STAT_EVENT_DATA_INVALID); + return false; + } + DataIndex name = traceDataCache_->GetDataIndex(std::string_view("sched_waking")); + auto instants = traceDataCache_->GetInstantsData(); + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, eventPid_); + instants->AppendInstantEventData(eventTimestamp_, name, internalTid); + streamFilters_->cpuFilter_->InsertWakeupEvent(eventTimestamp_, internalTid); + std::optional targetCpu = msg.target_cpu(); + if (targetCpu.has_value()) { + traceDataCache_->GetRawData()->AppendRawData(0, eventTimestamp_, RAW_SCHED_WAKING, targetCpu.value(), + internalTid); + } + return true; +} +bool HtraceEventParser::CpuIdleEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_IDLE, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + std::optional eventCpuValue = msg.cpu_id(); + std::optional newStateValue = msg.state(); + if (!eventCpuValue.has_value()) { + TS_LOGW("Failed to convert event cpu"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_IDLE, STAT_EVENT_DATA_INVALID); + return false; + } + if (!newStateValue.has_value()) { + TS_LOGW("Failed to convert state"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_IDLE, STAT_EVENT_DATA_INVALID); + return false; + } + auto cpuIdleNameIndex = traceDataCache_->GetDataIndex(std::string_view("cpu_idle")); + + streamFilters_->cpuMeasureFilter_->AppendNewMeasureData(eventCpuValue.value(), cpuIdleNameIndex, eventTimestamp_, + newStateValue.value()); + + // Add cpu_idle event to raw_data_table + traceDataCache_->GetRawData()->AppendRawData(0, eventTimestamp_, RAW_CPU_IDLE, eventCpuValue.value(), 0); + return true; +} +bool HtraceEventParser::CpuFrequencyEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_FREQUENCY, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + std::optional newStateValue = msg.state(); + std::optional eventCpuValue = msg.cpu_id(); + + if (!newStateValue.has_value()) { + TS_LOGW("Failed to convert state"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_FREQUENCY, STAT_EVENT_DATA_INVALID); + return false; + } + if (!eventCpuValue.has_value()) { + TS_LOGW("Failed to convert event cpu"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_FREQUENCY, STAT_EVENT_DATA_INVALID); + return false; + } + auto cpuidleNameIndex = traceDataCache_->GetDataIndex(std::string_view("cpu_frequency")); + + streamFilters_->cpuMeasureFilter_->AppendNewMeasureData(eventCpuValue.value(), cpuidleNameIndex, eventTimestamp_, + newStateValue.value()); + return true; +} +bool HtraceEventParser::SuspendResumeEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SUSPEND_RESUME, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + int32_t val = msg.val(); + uint32_t start = msg.start(); + std::string action = msg.action(); + UNUSED(val); + UNUSED(start); + UNUSED(action); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SUSPEND_RESUME, STAT_EVENT_NOTSUPPORTED); + return true; +} +bool HtraceEventParser::WorkqueueExecuteStartEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_WORKQUEUE_EXECUTE_START, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + auto result = streamFilters_->sliceFilter_->BeginSlice(eventTimestamp_, eventPid_, eventPid_, workQueueId_, + streamFilters_->symbolsFilter_->GetFunc(msg.function())); + + traceDataCache_->GetInternalSlicesData()->AppendDistributeInfo(); + UNUSED(result); + return true; +} +bool HtraceEventParser::WorkqueueExecuteEndEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_WORKQUEUE_EXECUTE_END, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + if (streamFilters_->sliceFilter_->EndSlice(eventTimestamp_, eventPid_, eventPid_)) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_WORKQUEUE_EXECUTE_END, STAT_EVENT_NOTMATCH); + } + return true; +} +bool HtraceEventParser::ClockSetRateEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLOCK_SET_RATE, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + DataIndex nameIndex = traceDataCache_->GetDataIndex(msg.name()); + streamFilters_->clockRateFilter_->AppendNewMeasureData(msg.cpu_id(), nameIndex, eventTimestamp_, msg.state()); + return true; +} +bool HtraceEventParser::ClockEnableEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLOCK_ENABLE, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + DataIndex nameIndex = traceDataCache_->GetDataIndex(msg.name()); + streamFilters_->clockEnableFilter_->AppendNewMeasureData(msg.cpu_id(), nameIndex, eventTimestamp_, msg.state()); + return true; +} +bool HtraceEventParser::ClockDisableEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLOCK_DISABLE, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + DataIndex nameIndex = traceDataCache_->GetDataIndex(msg.name()); + streamFilters_->clockDisableFilter_->AppendNewMeasureData(msg.cpu_id(), nameIndex, eventTimestamp_, msg.state()); + return true; +} +bool HtraceEventParser::ClkSetRateEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLK_SET_RATE, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + DataIndex nameIndex = traceDataCache_->GetDataIndex(msg.name()); + streamFilters_->clkRateFilter_->AppendNewMeasureData(eventCpu_, nameIndex, eventTimestamp_, msg.rate()); + return true; +} +bool HtraceEventParser::ClkEnableEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLK_ENABLE, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + DataIndex nameIndex = traceDataCache_->GetDataIndex(msg.name()); + streamFilters_->clkEnableFilter_->AppendNewMeasureData(eventCpu_, nameIndex, eventTimestamp_, 1); + return true; +} +bool HtraceEventParser::ClkDisableEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLK_DISABLE, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + DataIndex nameIndex = traceDataCache_->GetDataIndex(msg.name()); + streamFilters_->clkDisableFilter_->AppendNewMeasureData(eventCpu_, nameIndex, eventTimestamp_, 0); + return true; +} + +bool HtraceEventParser::IrqHandlerEntryEvent(const MessageLite& event) const +{ + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_IRQ_HANDLER_ENTRY, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + auto name = std::string_view(msg.name()); + streamFilters_->irqFilter_->IrqHandlerEntry(eventTimestamp_, eventCpu_, traceDataCache_->GetDataIndex(name)); + return true; +} +bool HtraceEventParser::IrqHandlerExitEvent(const MessageLite& event) const +{ + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_IRQ_HANDLER_EXIT, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + streamFilters_->irqFilter_->IrqHandlerExit(eventTimestamp_, eventCpu_, static_cast(msg.ret())); + return true; +} +bool HtraceEventParser::SoftIrqEntryEvent(const MessageLite& event) const +{ + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_SOFTIRQ_ENTRY, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + streamFilters_->irqFilter_->SoftIrqEntry(eventTimestamp_, eventCpu_, static_cast(msg.vec())); + return true; +} +bool HtraceEventParser::SoftIrqRaiseEvent(const MessageLite& event) const +{ + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_SOFTIRQ_RAISE, STAT_EVENT_RECEIVED); + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_SOFTIRQ_RAISE, STAT_EVENT_NOTSUPPORTED); + return true; +} +bool HtraceEventParser::SoftIrqExitEvent(const MessageLite& event) const +{ + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + streamFilters_->irqFilter_->SoftIrqExit(eventTimestamp_, eventCpu_, static_cast(msg.vec())); + return true; +} +bool HtraceEventParser::SysEnterEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_ENTRY, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + DataIndex nameIndex = traceDataCache_->GetDataIndex("sys_enter"); + auto ipid = streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, eventPid_); + traceDataCache_->GetSysCallData()->AppendSysCallData(msg.id(), nameIndex, ipid, eventTimestamp_, 0); + return true; +} +bool HtraceEventParser::SysExitEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_EXIT, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + DataIndex nameIndex = traceDataCache_->GetDataIndex("sys_exit"); + auto ipid = streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, eventPid_); + traceDataCache_->GetSysCallData()->AppendSysCallData(msg.id(), nameIndex, ipid, eventTimestamp_, msg.ret()); + return true; +} + +bool HtraceEventParser::OomScoreAdjUdate(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OOM_SCORE_ADJ_UPDATE, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + DataIndex nameIndex = traceDataCache_->GetDataIndex("oom_score_adj"); + streamFilters_->processMeasureFilter_->AppendNewMeasureData(msg.pid(), nameIndex, eventTimestamp_, + msg.oom_score_adj()); + return true; +} + +bool HtraceEventParser::SignalGenerateEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BLOCK_BIO_BACKMERGE, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThreadWithName(eventTimestamp_, msg.pid(), + msg.comm()); + streamFilters_->threadFilter_->AppendNewMeasureData(internalTid, signalGenerateId_, eventTimestamp_, msg.sig()); + return true; +} +bool HtraceEventParser::SignalDeleverEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BLOCK_BIO_BACKMERGE, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, eventPid_); + streamFilters_->threadFilter_->AppendNewMeasureData(internalTid, signalDeliverId_, eventTimestamp_, msg.sig()); + return true; +} +bool HtraceEventParser::InvokeFunc(const SupportedTraceEventType& eventType, + const MessageLite& msgBase) +{ + auto eventName = config_.eventNameMap_.find(eventType); + if (eventName == config_.eventNameMap_.end()) { + // log warn + streamFilters_->statFilter_->IncreaseStat(eventType, STAT_EVENT_NOTSUPPORTED); + return false; + } + auto it = eventToFunctionMap_.find(eventName->second); + if (it == eventToFunctionMap_.end()) { + // log warn + streamFilters_->statFilter_->IncreaseStat(eventType, STAT_EVENT_NOTSUPPORTED); + return false; + } + it->second(msgBase); + return true; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_event_parser/htrace_event_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_event_parser/htrace_event_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..05ca103a2ed079c563f8d4073c08d36a94b32e7d --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_event_parser/htrace_event_parser.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HTRACE_EVENT_PARSER_H +#define HTRACE_EVENT_PARSER_H +#include +#include +#include +#include +#include +#include +#include + +#include "event_parser_base.h" +#include "google/protobuf/message_lite.h" +#include "log.h" +#include "print_event_parser.h" +#include "trace_data/trace_data_cache.h" +#include "trace_plugin_result.pb.h" +#include "trace_streamer_filters.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace google::protobuf; +class HtraceEventParser : private EventParserBase { +public: + HtraceEventParser(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + ~HtraceEventParser(); + void ParseDataItem(const FtraceCpuDetailMsg* cpuDetail, BuiltinClocks clock); +private: + bool BinderTractionEvent(const MessageLite& event) const; + bool BinderTractionReceivedEvent(const MessageLite& event) const; + bool BinderTractionAllocBufEvent(const MessageLite& event) const; + bool BinderTractionLockEvent(const MessageLite& event) const; + bool BinderTractionLockedEvent(const MessageLite& event) const; + bool BinderTractionUnLockEvent(const MessageLite& event) const; + bool SchedSwitchEvent(const MessageLite& event); + bool ProcessExitEvent(const MessageLite& event) const; + bool ProcessFreeEvent(const MessageLite& event) const; + bool TaskRenameEvent(const MessageLite& event) const; + bool TaskNewtaskEvent(const MessageLite& event) const; + bool ParsePrintEvent(const MessageLite& event); + bool SchedWakeupEvent(const MessageLite& event) const; + bool SchedWakeupNewEvent(const MessageLite& event) const; + bool SchedWakingEvent(const MessageLite& event) const; + bool CpuIdleEvent(const MessageLite& event) const; + bool CpuFrequencyEvent(const MessageLite& event) const; + bool SuspendResumeEvent(const MessageLite& event) const; + bool WorkqueueExecuteStartEvent(const MessageLite& event) const; + bool WorkqueueExecuteEndEvent(const MessageLite& event) const; + bool ClockSetRateEvent(const MessageLite& event) const; + bool ClockEnableEvent(const MessageLite& event) const; + bool ClockDisableEvent(const MessageLite& event) const; + bool ClkSetRateEvent(const MessageLite& event) const; + bool ClkEnableEvent(const MessageLite& event) const; + bool ClkDisableEvent(const MessageLite& event) const; + bool IrqHandlerEntryEvent(const MessageLite& event) const; + bool IrqHandlerExitEvent(const MessageLite& event) const; + bool SoftIrqEntryEvent(const MessageLite& event) const; + bool SoftIrqRaiseEvent(const MessageLite& event) const; + bool SoftIrqExitEvent(const MessageLite& event) const; + bool SysEnterEvent(const MessageLite& event) const; + bool SysExitEvent(const MessageLite& event) const; + bool OomScoreAdjUdate(const MessageLite& event) const; + bool SignalGenerateEvent(const MessageLite& event) const; + bool SignalDeleverEvent(const MessageLite& event) const; + bool InvokeFunc(const SupportedTraceEventType& eventType, const MessageLite& msgBase); + using FuncCall = std::function; + uint32_t eventCpu_ = INVALID_UINT32; + uint64_t eventTimestamp_ = INVALID_UINT64; + uint32_t eventPid_ = INVALID_UINT32; + std::map eventToFunctionMap_ = {}; + std::unordered_set tids_ = {}; + std::unordered_set pids_ = {}; + DataIndex workQueueId_ = 0; + PrintEventParser printEventParser_; + uint64_t lastOverwrite_ = 0; + DataIndex signalGenerateId_ = traceDataCache_->GetDataIndex("signal_generate"); + DataIndex signalDeliverId_ = traceDataCache_->GetDataIndex("signal_deliver"); + uint64_t traceStartTime_ = std::numeric_limits::max(); + uint64_t traceEndTime_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_EVENT_PARSER_H_ diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_hidump_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_hidump_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7742db963bfbc788ad21ede638179e6c67cc4e69 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_hidump_parser.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "clock_filter.h" +#include "hidump_plugin_result.pb.h" +#include "htrace_event_parser.h" +#include "process_filter.h" +#include "stat_filter.h" +#include "htrace_hidump_parser.h" +namespace SysTuning { +namespace TraceStreamer { +HtraceHidumpParser::HtraceHidumpParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : streamFilters_(ctx), traceDataCache_(dataCache) +{ + if (!traceDataCache_) { + TS_LOGE("traceDataCache_ should not be null"); + return; + } + if (!streamFilters_) { + TS_LOGE("streamFilters_ should not be null"); + return; + } +} + +HtraceHidumpParser::~HtraceHidumpParser() +{ + TS_LOGI("FPS data ts MIN:%llu, MAX:%llu", + static_cast(traceStartTime_), static_cast(traceEndTime_)); +} +void HtraceHidumpParser::Parse(HidumpInfo& tracePacket) +{ + if (!tracePacket.fps_event_size()) { + return; + } + if (!traceDataCache_) { + TS_LOGE("traceDataCache_ should not be null"); + return; + } + if (!streamFilters_) { + TS_LOGE("streamFilters_ should not be null"); + return; + } + for (int i = 0; i < tracePacket.fps_event_size(); i++) { + streamFilters_->statFilter_->IncreaseStat(TRACE_HIDUMP_FPS, STAT_EVENT_RECEIVED); + auto hidumpData = tracePacket.mutable_fps_event(i); + auto timeStamp = hidumpData->time().tv_nsec() + hidumpData->time().tv_sec() * SEC_TO_NS; + auto newTimeStamp = streamFilters_->clockFilter_->ToPrimaryTraceTime(hidumpData->id(), timeStamp); + if (newTimeStamp != timeStamp) { // record the time only when the time is valid + traceStartTime_ = std::min(traceStartTime_, newTimeStamp); + traceEndTime_ = std::max(traceEndTime_, newTimeStamp); + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_HIDUMP_FPS, STAT_EVENT_DATA_INVALID); + } + auto fps = hidumpData->fps(); + traceDataCache_->GetHidumpData()->AppendNewHidumpInfo(newTimeStamp, fps); + } +} +void HtraceHidumpParser::Finish() +{ + traceDataCache_->MixTraceTime(traceStartTime_, traceEndTime_); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_hidump_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_hidump_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..dc4cf21e82d2033d587efc75532c02ab76b4575b --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_hidump_parser.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HTRACE_HIDUMP_PARSER_H +#define HTRACE_HIDUMP_PARSER_H +#include +#include +#include +#include "trace_data/trace_data_cache.h" +#include "trace_streamer_config.h" +#include "trace_streamer_filters.h" + + +namespace SysTuning { +namespace TraceStreamer { +class HtraceHidumpParser { +public: + HtraceHidumpParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~HtraceHidumpParser(); + void Parse(HidumpInfo& tracePacket); + void Finish(); + +private: + const TraceStreamerFilters* streamFilters_; + TraceDataCache* traceDataCache_; + TraceStreamerConfig config_ = {}; + uint64_t traceStartTime_ = std::numeric_limits::max(); + uint64_t traceEndTime_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_HIDUMP_PARSER_H diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_hilog_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_hilog_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad3e12f4d73b27139517ea4c31cd4756434708ed --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_hilog_parser.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "htrace_hilog_parser.h" +#include "clock_filter.h" +#include "htrace_event_parser.h" +#include "process_filter.h" +#include "stat_filter.h" +namespace SysTuning { +namespace TraceStreamer { +HtraceHiLogParser::HtraceHiLogParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : streamFilters_(ctx), traceDataCache_(dataCache) +{ + if (!traceDataCache_) { + TS_LOGE("traceDataCache_ should not be null"); + return; + } + if (!streamFilters_) { + TS_LOGE("streamFilters_ should not be null"); + return; + } +} + +HtraceHiLogParser::~HtraceHiLogParser() +{ + TS_LOGI("hilog ts MIN:%llu, MAX:%llu", + static_cast(traceStartTime_), static_cast(traceEndTime_)); +} +void HtraceHiLogParser::Parse(HilogInfo& tracePacket) +{ + if (!tracePacket.info_size()) { + return; + } + if (!traceDataCache_) { + TS_LOGE("traceDataCache_ should not be null"); + return; + } + if (!streamFilters_) { + TS_LOGE("streamFilters_ should not be null"); + return; + } + for (int i = 0; i < tracePacket.info_size(); i++) { + auto hilogLine = tracePacket.mutable_info(i); + uint64_t curLineSeq = hilogLine->id(); + streamFilters_->statFilter_->IncreaseStat(TRACE_HILOG, STAT_EVENT_RECEIVED); + if (curLineSeq < lastLineSeq_ + 1) { + streamFilters_->statFilter_->IncreaseStat(TRACE_HILOG, STAT_EVENT_NOTMATCH); + } else if (curLineSeq > lastLineSeq_ + 1) { + streamFilters_->statFilter_->IncreaseStat(TRACE_HILOG, STAT_EVENT_DATA_LOST); + } + lastLineSeq_ = curLineSeq; + auto logData = traceDataCache_->GetDataIndex(hilogLine->context().c_str()); + auto logDetails = hilogLine->detail(); + + streamFilters_->processFilter_->GetOrCreateThreadWithPid(logDetails.tid(), logDetails.pid()); + auto iter = logLevelString_.find(logDetails.level()); + if (iter == logLevelString_.end()) { + streamFilters_->statFilter_->IncreaseStat(TRACE_HILOG, STAT_EVENT_DATA_INVALID); + TS_LOGD("log level do not exit!!!"); + continue; + } + + auto timeStamp = logDetails.tv_nsec() + logDetails.tv_sec() * SEC_TO_NS; + auto newTimeStamp = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, timeStamp); + if (newTimeStamp != timeStamp) { // record the time only when the time is valid + traceStartTime_ = std::min(traceStartTime_, newTimeStamp); + traceEndTime_ = std::max(traceEndTime_, newTimeStamp); + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_HILOG, STAT_EVENT_DATA_INVALID); + } + + DataIndex levelData = traceDataCache_->dataDict_.GetStringIndex(iter->second.c_str()); + DataIndex logTag = traceDataCache_->dataDict_.GetStringIndex(logDetails.tag().c_str()); + traceDataCache_->GetHilogData()->AppendNewLogInfo(curLineSeq, newTimeStamp, logDetails.pid(), logDetails.tid(), + levelData, logTag, logData, timeStamp); + } +} +void HtraceHiLogParser::Finish() +{ + traceDataCache_->MixTraceTime(traceStartTime_, traceEndTime_); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_hilog_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_hilog_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..e889f9554848f802dd9004b93adad2832766184d --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_hilog_parser.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HTRACE_HILOG_PARSER_H +#define HTRACE_HILOG_PARSER_H +#include +#include +#include +#include "trace_data/trace_data_cache.h" +#include "hilog_plugin_result.pb.h" +#include "trace_streamer_config.h" +#include "trace_streamer_filters.h" + + +namespace SysTuning { +namespace TraceStreamer { +class HtraceHiLogParser { +public: + HtraceHiLogParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~HtraceHiLogParser(); + void Parse(HilogInfo& tracePacket); + std::map logLevelString_ = {{TS_DEBUG, "D"}, + {TS_ERROR, "E"}, + {TS_INFO, "I"}, + {TS_VERBOSE, "V"}, + {TS_WARN, "W"}}; + void Finish(); + +private: + const TraceStreamerFilters* streamFilters_; + TraceDataCache* traceDataCache_; + TraceStreamerConfig config_ = {}; + uint64_t lastLineSeq_ = 0; + uint64_t traceStartTime_ = std::numeric_limits::max(); + uint64_t traceEndTime_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_HILOG_PARSER_H diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_mem_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_mem_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55ebfb07c295a260997cbbb4f6edecd1c3cd0cdb --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_mem_parser.cpp @@ -0,0 +1,863 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "htrace_mem_parser.h" +#include "clock_filter.h" +#include "htrace_event_parser.h" +#include "measure_filter.h" +#include "process_filter.h" +#include "stat_filter.h" +#include "symbols_filter.h" +#include "system_event_measure_filter.h" +namespace SysTuning { +namespace TraceStreamer { +HtraceMemParser::HtraceMemParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : streamFilters_(ctx), traceDataCache_(dataCache) +{ + if (!traceDataCache_) { + TS_LOGE("traceDataCache_ should not be null"); + return; + } + if (!streamFilters_) { + TS_LOGE("streamFilters_ should not be null"); + return; + } + for (auto i = 0; i < MEM_MAX; i++) { + memNameDictMap_.insert( + std::make_pair(static_cast(i), + traceDataCache_->GetDataIndex(config_.memNameMap_.at(static_cast(i))))); + } + for (auto i = 0; i < SysMeminfoType::PMEM_CMA_FREE + 1; i++) { + sysMemNameDictMap_.insert( + std::make_pair(static_cast(i), + traceDataCache_->GetDataIndex(config_.sysMemNameMap_.at(static_cast(i))))); + } + for (auto i = 0; i < SysVMeminfoType::VMEMINFO_WORKINGSET_RESTORE + 1; i++) { + sysVMemNameDictMap_.insert(std::make_pair( + static_cast(i), + traceDataCache_->GetDataIndex(config_.sysVirtualMemNameMap_.at(static_cast(i))))); + } +} + +HtraceMemParser::~HtraceMemParser() +{ + TS_LOGI("mem ts MIN:%llu, MAX:%llu", static_cast(traceStartTime_), + static_cast(traceEndTime_)); +} +void HtraceMemParser::Parse(const MemoryData& tracePacket, uint64_t timeStamp, BuiltinClocks clock) +{ + if (!traceDataCache_) { + TS_LOGE("traceDataCache_ should not be null"); + return; + } + if (!streamFilters_) { + TS_LOGE("streamFilters_ should not be null"); + return; + } + auto newTimeStamp = streamFilters_->clockFilter_->ToPrimaryTraceTime(clock, timeStamp); + if (newTimeStamp != timeStamp) { // record the time only when the time is valid + traceStartTime_ = std::min(traceStartTime_, newTimeStamp); + traceEndTime_ = std::max(traceEndTime_, newTimeStamp); + } + if (tracePacket.processesinfo_size()) { + ParseProcessInfo(tracePacket, newTimeStamp); + } + if (tracePacket.meminfo_size()) { + ParseMemInfo(tracePacket, newTimeStamp); + } + if (tracePacket.vmeminfo_size()) { + ParseVMemInfo(tracePacket, newTimeStamp); + } +} +void HtraceMemParser::ParseProcessInfo(const MemoryData& tracePacket, uint64_t timeStamp) const +{ + if (tracePacket.processesinfo_size()) { + streamFilters_->statFilter_->IncreaseStat(TRACE_MEMORY, STAT_EVENT_RECEIVED); + } + for (int i = 0; i < tracePacket.processesinfo_size(); i++) { + auto memInfo = tracePacket.processesinfo(i); + auto ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(memInfo.pid(), memInfo.name()); + streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_SIZE), timeStamp, + memInfo.vm_size_kb()); + streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_RSS), timeStamp, + memInfo.vm_rss_kb()); + streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_ANON), timeStamp, + memInfo.rss_anon_kb()); + streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_RSS_FILE), timeStamp, + memInfo.rss_file_kb()); + streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_RSS_SHMEM), timeStamp, + memInfo.rss_shmem_kb()); + streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_SWAP), timeStamp, + memInfo.vm_swap_kb()); + streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_LOCKED), timeStamp, + memInfo.vm_locked_kb()); + streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_HWM), timeStamp, + memInfo.vm_hwm_kb()); + streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_OOM_SCORE_ADJ), + timeStamp, memInfo.oom_score_adj()); + } +} + +void HtraceMemParser::ParseMemInfoEasy(const MemoryData& tracePacket, uint64_t timeStamp) const +{ + if (tracePacket.meminfo_size()) { + streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_MEMORY, STAT_EVENT_RECEIVED); + } + for (int i = 0; i < tracePacket.meminfo_size(); i++) { + auto memInfo = tracePacket.meminfo(i); + if (config_.sysMemNameMap_.find(memInfo.key()) != config_.sysMemNameMap_.end()) { + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData(sysMemNameDictMap_.at(memInfo.key()), + timeStamp, memInfo.value()); + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_MEMORY, STAT_EVENT_DATA_INVALID); + } + } +} + +void HtraceMemParser::ParseVMemInfoEasy(const MemoryData& tracePacket, uint64_t timeStamp) const +{ + traceDataCache_->UpdateTraceTime(timeStamp); + if (tracePacket.vmeminfo_size()) { + streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_RECEIVED); + } + for (int i = 0; i < tracePacket.vmeminfo_size(); i++) { + auto memInfo = tracePacket.vmeminfo(i); + if (config_.sysVirtualMemNameMap_.find(memInfo.key()) != config_.sysVirtualMemNameMap_.end()) { + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData(sysVMemNameDictMap_.at(memInfo.key()), + timeStamp, memInfo.value()); + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_DATA_INVALID); + } + } +} + +void HtraceMemParser::ParseMemInfo(const MemoryData& tracePacket, uint64_t timeStamp) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_MEMORY, STAT_EVENT_RECEIVED); + for (int i = 0; i < tracePacket.meminfo_size(); i++) { + auto vMemInfo = tracePacket.meminfo(i); + switch (static_cast(vMemInfo.key())) { + case SysMeminfoType::PMEM_UNSPECIFIED: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_UNSPECIFIED), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_MEM_TOTAL: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_MEM_TOTAL), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_MEM_FREE: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_MEM_FREE), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_MEM_AVAILABLE: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_MEM_AVAILABLE), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_BUFFERS: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_BUFFERS), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_CACHED: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_CACHED), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_SWAP_CACHED: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_SWAP_CACHED), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_ACTIVE: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_ACTIVE), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_INACTIVE: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_INACTIVE), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_ACTIVE_ANON: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_ACTIVE_ANON), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_INACTIVE_ANON: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_INACTIVE_ANON), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_ACTIVE_FILE: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_ACTIVE_FILE), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_INACTIVE_FILE: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_INACTIVE_FILE), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_UNEVICTABLE: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_UNEVICTABLE), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_MLOCKED: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_MLOCKED), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_SWAP_TOTAL: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_SWAP_TOTAL), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_SWAP_FREE: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_SWAP_FREE), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_DIRTY: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_DIRTY), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_WRITEBACK: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_WRITEBACK), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_ANON_PAGES: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_ANON_PAGES), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_MAPPED: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_MAPPED), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_SHMEM: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_SHMEM), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_SLAB: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_SLAB), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_SLAB_RECLAIMABLE: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_SLAB_RECLAIMABLE), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_SLAB_UNRECLAIMABLE: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_SLAB_UNRECLAIMABLE), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_KERNEL_STACK: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_KERNEL_STACK), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_PAGE_TABLES: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_PAGE_TABLES), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_COMMIT_LIMIT: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_COMMIT_LIMIT), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_COMMITED_AS: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_COMMITED_AS), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_VMALLOC_TOTAL: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_VMALLOC_TOTAL), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_VMALLOC_USED: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_VMALLOC_USED), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_VMALLOC_CHUNK: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_VMALLOC_CHUNK), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_CMA_TOTAL: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_CMA_TOTAL), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType::PMEM_CMA_FREE: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_CMA_FREE), timeStamp, vMemInfo.value()); + break; + case SysMeminfoType_INT_MIN_SENTINEL_DO_NOT_USE_: + case SysMeminfoType_INT_MAX_SENTINEL_DO_NOT_USE_: + default: + streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_MEMORY, STAT_EVENT_DATA_INVALID); + break; + } + } +} +void HtraceMemParser::ParseVMemInfo(const MemoryData& tracePacket, uint64_t timeStamp) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_RECEIVED); + for (int i = 0; i < tracePacket.vmeminfo_size(); i++) { + auto vMemInfo = tracePacket.vmeminfo(i); + switch (static_cast(vMemInfo.key())) { + case SysVMeminfoType::VMEMINFO_UNSPECIFIED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_UNSPECIFIED), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_FREE_PAGES: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_FREE_PAGES), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ALLOC_BATCH: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ALLOC_BATCH), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_INACTIVE_ANON: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_INACTIVE_ANON), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ACTIVE_ANON: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ACTIVE_ANON), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_INACTIVE_FILE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_INACTIVE_FILE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ACTIVE_FILE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ACTIVE_FILE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_UNEVICTABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_UNEVICTABLE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_MLOCK: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_MLOCK), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ANON_PAGES: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ANON_PAGES), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_MAPPED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_MAPPED), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_FILE_PAGES: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_FILE_PAGES), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_DIRTY: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_DIRTY), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_WRITEBACK: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_WRITEBACK), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_SLAB_RECLAIMABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_SLAB_RECLAIMABLE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_SLAB_UNRECLAIMABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_SLAB_UNRECLAIMABLE), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_PAGE_TABLE_PAGES: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_PAGE_TABLE_PAGES), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_KERNEL_STACK: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_KERNEL_STACK), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_OVERHEAD: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_OVERHEAD), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_UNSTABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_UNSTABLE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_BOUNCE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_BOUNCE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_VMSCAN_WRITE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_VMSCAN_WRITE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_VMSCAN_IMMEDIATE_RECLAIM: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_VMSCAN_IMMEDIATE_RECLAIM), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_WRITEBACK_TEMP: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_WRITEBACK_TEMP), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ISOLATED_ANON: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ISOLATED_ANON), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ISOLATED_FILE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ISOLATED_FILE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_SHMEM: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_SHMEM), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_DIRTIED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_DIRTIED), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_WRITTEN: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_WRITTEN), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_PAGES_SCANNED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_PAGES_SCANNED), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_WORKINGSET_REFAULT: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_WORKINGSET_REFAULT), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_WORKINGSET_ACTIVATE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_WORKINGSET_ACTIVATE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_WORKINGSET_NODERECLAIM: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_WORKINGSET_NODERECLAIM), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ANON_TRANSPARENT_HUGEPAGES: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ANON_TRANSPARENT_HUGEPAGES), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_FREE_CMA: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_FREE_CMA), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_SWAPCACHE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_SWAPCACHE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_DIRTY_THRESHOLD: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_DIRTY_THRESHOLD), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_DIRTY_BACKGROUND_THRESHOLD: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_DIRTY_BACKGROUND_THRESHOLD), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGPGIN: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGPGIN), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGPGOUT: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGPGOUT), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGPGOUTCLEAN: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGPGOUTCLEAN), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PSWPIN: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PSWPIN), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PSWPOUT: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PSWPOUT), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGALLOC_DMA: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGALLOC_DMA), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGALLOC_NORMAL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGALLOC_NORMAL), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGALLOC_MOVABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGALLOC_MOVABLE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGFREE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGFREE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGACTIVATE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGACTIVATE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGDEACTIVATE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGDEACTIVATE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGFAULT: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGFAULT), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGMAJFAULT: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGMAJFAULT), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGREFILL_DMA: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGREFILL_DMA), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGREFILL_NORMAL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGREFILL_NORMAL), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGREFILL_MOVABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGREFILL_MOVABLE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSTEAL_KSWAPD_DMA: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSTEAL_KSWAPD_DMA), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSTEAL_KSWAPD_NORMAL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSTEAL_KSWAPD_NORMAL), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSTEAL_KSWAPD_MOVABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSTEAL_KSWAPD_MOVABLE), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSTEAL_DIRECT_DMA: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSTEAL_DIRECT_DMA), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSTEAL_DIRECT_NORMAL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSTEAL_DIRECT_NORMAL), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSTEAL_DIRECT_MOVABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSTEAL_DIRECT_MOVABLE), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSCAN_KSWAPD_DMA: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSCAN_KSWAPD_DMA), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSCAN_KSWAPD_NORMAL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSCAN_KSWAPD_NORMAL), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSCAN_KSWAPD_MOVABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSCAN_KSWAPD_MOVABLE), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT_DMA: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT_DMA), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT_NORMAL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT_NORMAL), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT_MOVABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT_MOVABLE), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT_THROTTLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT_THROTTLE), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGINODESTEAL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGINODESTEAL), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_SLABS_SCANNED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_SLABS_SCANNED), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_KSWAPD_INODESTEAL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_KSWAPD_INODESTEAL), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_KSWAPD_LOW_WMARK_HIT_QUICKLY: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_KSWAPD_LOW_WMARK_HIT_QUICKLY), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_KSWAPD_HIGH_WMARK_HIT_QUICKLY: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_KSWAPD_HIGH_WMARK_HIT_QUICKLY), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PAGEOUTRUN: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PAGEOUTRUN), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_ALLOCSTALL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_ALLOCSTALL), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGROTATED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGROTATED), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_DROP_PAGECACHE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_DROP_PAGECACHE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_DROP_SLAB: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_DROP_SLAB), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGMIGRATE_SUCCESS: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGMIGRATE_SUCCESS), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGMIGRATE_FAIL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGMIGRATE_FAIL), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_COMPACT_MIGRATE_SCANNED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_COMPACT_MIGRATE_SCANNED), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_COMPACT_FREE_SCANNED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_COMPACT_FREE_SCANNED), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_COMPACT_ISOLATED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_COMPACT_ISOLATED), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_COMPACT_STALL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_COMPACT_STALL), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_COMPACT_FAIL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_COMPACT_FAIL), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_COMPACT_SUCCESS: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_COMPACT_SUCCESS), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_COMPACT_DAEMON_WAKE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_COMPACT_DAEMON_WAKE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_CULLED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_CULLED), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_SCANNED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_SCANNED), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_RESCUED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_RESCUED), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_MLOCKED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_MLOCKED), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_MUNLOCKED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_MUNLOCKED), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_CLEARED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_CLEARED), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_STRANDED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_UNEVICTABLE_PGS_STRANDED), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ZSPAGES: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ZSPAGES), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ION_HEAP: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ION_HEAP), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_GPU_HEAP: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_GPU_HEAP), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_ALLOCSTALL_DMA: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_ALLOCSTALL_DMA), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_ALLOCSTALL_MOVABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_ALLOCSTALL_MOVABLE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_ALLOCSTALL_NORMAL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_ALLOCSTALL_NORMAL), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_COMPACT_DAEMON_FREE_SCANNED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_COMPACT_DAEMON_FREE_SCANNED), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_COMPACT_DAEMON_MIGRATE_SCANNED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_COMPACT_DAEMON_MIGRATE_SCANNED), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_FASTRPC: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_FASTRPC), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_INDIRECTLY_RECLAIMABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_INDIRECTLY_RECLAIMABLE), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ION_HEAP_POOL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ION_HEAP_POOL), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_KERNEL_MISC_RECLAIMABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_KERNEL_MISC_RECLAIMABLE), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_SHADOW_CALL_STACK_BYTES: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_SHADOW_CALL_STACK_BYTES), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_SHMEM_HUGEPAGES: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_SHMEM_HUGEPAGES), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_SHMEM_PMDMAPPED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_SHMEM_PMDMAPPED), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_UNRECLAIMABLE_PAGES: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_UNRECLAIMABLE_PAGES), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ZONE_ACTIVE_ANON: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ZONE_ACTIVE_ANON), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ZONE_ACTIVE_FILE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ZONE_ACTIVE_FILE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ZONE_INACTIVE_ANON: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ZONE_INACTIVE_ANON), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ZONE_INACTIVE_FILE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ZONE_INACTIVE_FILE), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ZONE_UNEVICTABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ZONE_UNEVICTABLE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_NR_ZONE_WRITE_PENDING: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_NR_ZONE_WRITE_PENDING), timeStamp, + vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_OOM_KILL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_OOM_KILL), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGLAZYFREE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGLAZYFREE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGLAZYFREED: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGLAZYFREED), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGREFILL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGREFILL), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSCAN_DIRECT), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSCAN_KSWAPD: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSCAN_KSWAPD), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSKIP_DMA: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSKIP_DMA), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSKIP_MOVABLE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSKIP_MOVABLE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSKIP_NORMAL: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSKIP_NORMAL), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSTEAL_DIRECT: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSTEAL_DIRECT), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_PGSTEAL_KSWAPD: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_PGSTEAL_KSWAPD), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_SWAP_RA: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_SWAP_RA), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_SWAP_RA_HIT: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_SWAP_RA_HIT), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType::VMEMINFO_WORKINGSET_RESTORE: + streamFilters_->sysEventVMemMeasureFilter_->AppendNewMeasureData( + sysVMemNameDictMap_.at(SysVMeminfoType::VMEMINFO_WORKINGSET_RESTORE), timeStamp, vMemInfo.value()); + break; + case SysVMeminfoType_INT_MIN_SENTINEL_DO_NOT_USE_: + case SysVMeminfoType_INT_MAX_SENTINEL_DO_NOT_USE_: + default: + streamFilters_->statFilter_->IncreaseStat(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_DATA_INVALID); + } + } +} +void HtraceMemParser::Finish() +{ + traceDataCache_->MixTraceTime(traceStartTime_, traceEndTime_); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_mem_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_mem_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..a5d762beb043935bc3d4fc3792c2556452721e73 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_mem_parser.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HTRACE_MEM_PARSER_H +#define HTRACE_MEM_PARSER_H + +#include +#include +#include +#include +#include +#include "memory_plugin_result.pb.h" +#include "trace_data/trace_data_cache.h" +#include "trace_streamer_config.h" +#include "trace_streamer_filters.h" +namespace SysTuning { +namespace TraceStreamer { +class HtraceMemParser { +public: + HtraceMemParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~HtraceMemParser(); + void Parse(const MemoryData& tracePacket, uint64_t, BuiltinClocks clock); + void Finish(); +private: + void ParseProcessInfo(const MemoryData& tracePacket, uint64_t timeStamp) const; + void ParseMemInfo(const MemoryData& tracePacket, uint64_t timeStamp) const; + void ParseMemInfoEasy(const MemoryData& tracePacket, uint64_t timeStamp) const; + void ParseVMemInfo(const MemoryData& tracePacket, uint64_t timeStamp) const; + void ParseVMemInfoEasy(const MemoryData& tracePacket, uint64_t timeStamp) const; + const TraceStreamerFilters* streamFilters_; + TraceDataCache* traceDataCache_; + TraceStreamerConfig config_ = {}; + std::map memNameDictMap_ = {}; + std::map sysMemNameDictMap_ = {}; + std::map sysVMemNameDictMap_ = {}; + uint64_t traceStartTime_ = std::numeric_limits::max(); + uint64_t traceEndTime_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_MEM_PARSER_H diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_native_hook_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_native_hook_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ef8098758805b9505c8acd908f73d10b3927b061 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_native_hook_parser.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "clock_filter.h" +#include "htrace_event_parser.h" +#include "native_hook_result.pb.h" +#include "process_filter.h" +#include "stat_filter.h" +#include "htrace_native_hook_parser.h" +namespace SysTuning { +namespace TraceStreamer { +uint64_t HtraceNativeHookParser::eventId_ = 0; +HtraceNativeHookParser::HtraceNativeHookParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : streamFilters_(ctx), traceDataCache_(dataCache), addrToAllocEventRow_(INVALID_UINT64) +{ + if (!traceDataCache_) { + TS_LOGE("traceDataCache_ should not be null"); + return; + } + if (!streamFilters_) { + TS_LOGE("streamFilters_ should not be null"); + return; + } +} + +HtraceNativeHookParser::~HtraceNativeHookParser() +{ + TS_LOGI("native hook data ts MIN:%llu, MAX:%llu", + static_cast(traceStartTime_), static_cast(traceEndTime_)); +} +void HtraceNativeHookParser::Parse(BatchNativeHookData& tracePacket) +{ + if (!tracePacket.events_size()) { + return; + } + if (!traceDataCache_) { + TS_LOGE("traceDataCache_ should not be null"); + return; + } + if (!streamFilters_) { + TS_LOGE("streamFilters_ should not be null"); + return; + } + for (auto i = 0; i < tracePacket.events_size(); i++) { + auto nativeHookData = tracePacket.mutable_events(i); + auto timeStamp = nativeHookData->tv_nsec() + nativeHookData->tv_sec() * SEC_TO_NS; + auto newTimeStamp = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, timeStamp); + if (newTimeStamp != timeStamp) { // record the time only when the time is valid + traceStartTime_ = std::min(traceStartTime_, newTimeStamp); + traceEndTime_ = std::max(traceEndTime_, newTimeStamp); + } + // kAllocEvent = 3 kFreeEvent = 4 EVENT_NOT_SET = 0 + auto eventCase = nativeHookData->event_case(); + if (eventCase == NativeHookData::kAllocEvent) { + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED); + if (newTimeStamp == timeStamp) { + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_DATA_INVALID); + } + auto allocEvent = nativeHookData->alloc_event(); + DataIndex allocIndex = traceDataCache_->dataDict_.GetStringIndex("AllocEvent"); + auto itid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(allocEvent.tid(), allocEvent.pid()); + auto ipid = streamFilters_->processFilter_->GetInternalPid(allocEvent.pid()); + auto row = traceDataCache_->GetHeapData()->AppendNewHeapInfo(eventId_, ipid, itid, allocIndex, newTimeStamp, + 0, 0, allocEvent.addr(), allocEvent.size(), + allocEvent.size(), 0); + addrToAllocEventRow_.Insert(ipid, allocEvent.addr(), static_cast(row)); + traceDataCache_->GetHeapData()->UpdateCurrentSizeDur(row, newTimeStamp); + for (auto depth = 0; depth < allocEvent.frame_info_size(); depth++) { + auto allocEventFrame = allocEvent.frame_info(depth); + DataIndex symbolNameIndex = + traceDataCache_->dataDict_.GetStringIndex(allocEventFrame.symbol_name().c_str()); + DataIndex filePathIndex = + traceDataCache_->dataDict_.GetStringIndex(allocEventFrame.file_path().c_str()); + traceDataCache_->GetHeapFrameData()->AppendNewHeapFrameInfo( + eventId_, depth, allocEventFrame.ip(), allocEventFrame.sp(), symbolNameIndex, filePathIndex, + allocEventFrame.offset(), allocEventFrame.symbol_offset()); + } + eventId_++; + } else if (eventCase == NativeHookData::kFreeEvent) { + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED); + if (newTimeStamp == timeStamp) { + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_DATA_INVALID); + } + auto freeEvent = nativeHookData->free_event(); + DataIndex freeIndex = traceDataCache_->dataDict_.GetStringIndex("FreeEvent"); + auto itid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(freeEvent.tid(), freeEvent.pid()); + auto ipid = streamFilters_->processFilter_->GetInternalPid(freeEvent.pid()); + int64_t freeHeapSize = 0; + auto row = addrToAllocEventRow_.Find(ipid, freeEvent.addr()); + if (row != INVALID_UINT64 && newTimeStamp > traceDataCache_->GetHeapData()->TimeStamData()[row]) { + addrToAllocEventRow_.Erase(ipid, freeEvent.addr()); + traceDataCache_->GetHeapData()->UpdateHeapDuration(row, newTimeStamp); + freeHeapSize = traceDataCache_->GetHeapData()->HeapSizes()[row]; + } else if (row == INVALID_UINT64) { + TS_LOGW("func addr:%lu is empty", freeEvent.addr()); + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_DATA_INVALID); + } + row = traceDataCache_->GetHeapData()->AppendNewHeapInfo(eventId_, ipid, itid, freeIndex, newTimeStamp, 0, 0, + freeEvent.addr(), freeHeapSize, -freeHeapSize, 0); + traceDataCache_->GetHeapData()->UpdateCurrentSizeDur(row, newTimeStamp); + for (auto depth = 0; depth < freeEvent.frame_info_size(); depth++) { + auto freeEventFrame = freeEvent.frame_info(depth); + DataIndex symbolNameIndex = + traceDataCache_->dataDict_.GetStringIndex(freeEventFrame.symbol_name().c_str()); + DataIndex filePathIndex = traceDataCache_->dataDict_.GetStringIndex(freeEventFrame.file_path().c_str()); + traceDataCache_->GetHeapFrameData()->AppendNewHeapFrameInfo( + eventId_, depth, freeEventFrame.ip(), freeEventFrame.sp(), symbolNameIndex, filePathIndex, + freeEventFrame.offset(), freeEventFrame.symbol_offset()); + } + eventId_++; + } else { + TS_LOGE("An unknown type of data was received!"); + } + } +} +void HtraceNativeHookParser::Finish() +{ + traceDataCache_->MixTraceTime(traceStartTime_, traceEndTime_); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_native_hook_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_native_hook_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..6e1cfa949152e6e57fb9bdd3e4e2e5323e0edda7 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_native_hook_parser.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HTRACE_NATIVE_HOOK_PARSER_H +#define HTRACE_NATIVE_HOOK_PARSER_H +#include +#include +#include +#include "double_map.h" +#include "trace_data/trace_data_cache.h" +#include "trace_streamer_config.h" +#include "trace_streamer_filters.h" + + +namespace SysTuning { +namespace TraceStreamer { +class HtraceNativeHookParser { +public: + HtraceNativeHookParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~HtraceNativeHookParser(); + void Parse(BatchNativeHookData& tracePacket); + void Finish(); + +private: + const TraceStreamerFilters* streamFilters_; + TraceDataCache* traceDataCache_; + TraceStreamerConfig config_ = {}; + uint64_t traceStartTime_ = std::numeric_limits::max(); + uint64_t traceEndTime_ = 0; + static uint64_t eventId_; + DoubleMap addrToAllocEventRow_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_NATIVE_HOOK_PARSER_H diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9893c5dac298224915acef962c754409b1f104f4 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_parser.cpp @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "htrace_parser.h" +#include +#include "binder_filter.h" +#include "cpu_filter.h" +#include "ftrace_event.pb.h" +#include "log.h" +#include "memory_plugin_result.pb.h" +#include "services/common_types.pb.h" +#include "stat_filter.h" +#include "trace_plugin_config.pb.h" +#include "trace_plugin_result.pb.h" +namespace SysTuning { +namespace TraceStreamer { +HtraceParser::HtraceParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters) + : ParserBase(filters), + htraceCpuDetailParser_(std::make_unique(dataCache, filters)), + htraceSymbolsDetailParser_(std::make_unique(dataCache, filters)), + htraceMemParser_(std::make_unique(dataCache, filters)), + htraceClockDetailParser_(std::make_unique(dataCache, filters)), + htraceHiLogParser_(std::make_unique(dataCache, filters)), + htraceNativeHookParser_(std::make_unique(dataCache, filters)), + htraceHidumpParser_(std::make_unique(dataCache, filters)), + dataSegArray(new HtraceDataSegment[MAX_SEG_ARRAY_SIZE]) +{ +#ifdef SUPPORTTHREAD + noThread_ = false; +#endif +} + +HtraceParser::~HtraceParser() +{ + TS_LOGI("clockid 2 is for RealTime and 1 is for BootTime"); +} + +void HtraceParser::WaitForParserEnd() +{ + if (parseThreadStarted_ || filterThreadStarted_) { + toExit_ = true; + while (!exited_) { + usleep(sleepDur_ * sleepDur_); + } + } + streamFilters_->cpuFilter_->FinishCpuEvent(); + streamFilters_->binderFilter_->FinishBinderEvent(); + htraceHiLogParser_->Finish(); + htraceMemParser_->Finish(); + htraceNativeHookParser_->Finish(); + htraceHidumpParser_->Finish(); +} + +void HtraceParser::ParseTraceDataItem(const std::string& buffer) +{ + int head = rawDataHead_; + while (!toExit_) { + if (!noThread_ && dataSegArray[head].status.load() != TS_PARSE_STATUS_INIT) { + usleep(sleepDur_); + continue; + } + dataSegArray[head].seg = std::move(buffer); + dataSegArray[head].status = TS_PARSE_STATUS_SEPRATED; + if (!noThread_) { + rawDataHead_ = (rawDataHead_ + 1) % MAX_SEG_ARRAY_SIZE; + } + break; + } + if (!parseThreadStarted_ && !noThread_) { + parseThreadStarted_ = true; + int tmp = maxThread_; + while (tmp--) { + parserThreadCount_++; + std::thread ParseTypeThread(&HtraceParser::ParseThread, this); + ParseTypeThread.detach(); + TS_LOGI("parser Thread:%d/%d start working ...\n", maxThread_ - tmp, maxThread_); + } + } + if (noThread_) { + ParserData(dataSegArray[head]); + } +} +void HtraceParser::FilterData(HtraceDataSegment& seg) +{ + if (seg.dataType == DATA_SOURCE_TYPE_TRACE) { + if (seg.traceData.ftrace_cpu_detail_size()) { + htraceCpuDetailParser_->Parse(seg.traceData, clock_); // has Event + } + if (seg.traceData.symbols_detail_size()) { + htraceSymbolsDetailParser_->Parse(seg.traceData); // has Event + } + if (seg.traceData.clocks_detail_size()) { + htraceClockDetailParser_->Parse(seg.traceData); // has Event + } + } else if (seg.dataType == DATA_SOURCE_TYPE_MEM) { + htraceMemParser_->Parse(seg.memData, seg.timeStamp, seg.clockId); + } else if (seg.dataType == DATA_SOURCE_TYPE_HILOG) { + htraceHiLogParser_->Parse(seg.logData); + } else if (seg.dataType == DATA_SOURCE_TYPE_HEAP) { + htraceNativeHookParser_->Parse(seg.batchNativeHookData); + } else if (seg.dataType == DATA_SOURCE_TYPE_FPS) { + htraceHidumpParser_->Parse(seg.hidumpInfo); + } + if (!noThread_) { + filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE; + } + seg.status = TS_PARSE_STATUS_INIT; +} +void HtraceParser::FilterThread() +{ + while (1) { + HtraceDataSegment& seg = dataSegArray[filterHead_]; + if (seg.status.load() == TS_PARSE_STATUS_INVALID) { + seg.status = TS_PARSE_STATUS_INIT; + filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE; + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID); + TS_LOGI("seprateHead_d:\t%d, parseHead_:\t%d, filterHead_:\t%d\n", rawDataHead_, parseHead_, filterHead_); + continue; + } + if (seg.status.load() != TS_PARSE_STATUS_PARSED) { + if (toExit_ && !parserThreadCount_) { + TS_LOGI("exiting ParseLine Thread"); + exited_ = true; + filterThreadStarted_ = false; + TS_LOGD("seprateHead:\t%d, parseHead_:\t%d, filterHead_:\t%d, status:%d\n", rawDataHead_, parseHead_, + filterHead_, seg.status.load()); + return; + } + TS_LOGD("seprateHead:\t%d, parseHead_:\t%d, filterHead_:\t%d, status:%d\n", rawDataHead_, parseHead_, + filterHead_, seg.status.load()); + usleep(sleepDur_); + continue; + } + FilterData(seg); + } +} + +void HtraceParser::ParserData(HtraceDataSegment& dataSeg) +{ + ProfilerPluginData pluginData; + if (!pluginData.ParseFromArray(dataSeg.seg.data(), static_cast(dataSeg.seg.length()))) { + TS_LOGW("ProfilerPluginData ParseFromArray failed\n"); + dataSeg.status = TS_PARSE_STATUS_INVALID; + return; + } + if (pluginData.name() == "memory-plugin") { + ParseMemory(pluginData, dataSeg); + } else if (pluginData.name() == "hilog-plugin" || pluginData.name() == "/data/local/tmp/libhilogplugin.z.so") { + ParseHilog(pluginData, dataSeg); + } else if (pluginData.name() == "ftrace-plugin" || pluginData.name() == "/data/local/tmp/libftrace_plugin.z.so") { + ParseFtrace(pluginData, dataSeg); + } else if (pluginData.name() == "nativehook" || pluginData.name() == "hookdaemon") { + ParseNativeHook(pluginData, dataSeg); + } else if (pluginData.name() == "hidump-plugin" || pluginData.name() == "/data/local/tmp/libhidumpplugin.z.so") { + ParseFPS(pluginData, dataSeg); + } else { + TS_LOGW("unrecognized pluginData.name():%s", pluginData.name().c_str()); + } + if (noThread_) { // do it only in wasm mode, wasm noThead_ will be true + FilterData(dataSeg); + } +} +void HtraceParser::ParseThread() +{ + while (1) { + if (!filterThreadStarted_ && !noThread_) { + filterThreadStarted_ = true; + std::thread ParserThread(&HtraceParser::FilterThread, this); + ParserThread.detach(); + } + int head = GetNextSegment(); + if (head < 0) { + if (head == ERROR_CODE_EXIT) { + return; + } else if (head == ERROR_CODE_NODATA) { + continue; + } + } + HtraceDataSegment& dataSeg = dataSegArray[head]; + ParserData(dataSeg); + } +} + +void HtraceParser::ParseMemory(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg) +{ + dataSeg.dataType = DATA_SOURCE_TYPE_MEM; + auto timeStamp = pluginData.tv_nsec() + pluginData.tv_sec() * SEC_TO_NS; + BuiltinClocks clockId = TS_CLOCK_REALTIME; + auto clockIdTemp = pluginData.clock_id(); + if (clockIdTemp == ProfilerPluginData_ClockId_CLOCKID_REALTIME) { + clockId = TS_CLOCK_REALTIME; + } + dataSeg.memData.Clear(); + if (!dataSeg.memData.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { + TS_LOGW("tracePacketParseFromArray failed\n"); + dataSeg.status = TS_PARSE_STATUS_INVALID; + return; + } + if (dataSeg.memData.processesinfo_size()) { + dataSeg.dataType = DATA_SOURCE_TYPE_MEM; + dataSeg.timeStamp = timeStamp; + dataSeg.clockId = clockId; + dataSeg.status = TS_PARSE_STATUS_PARSED; + } else if (dataSeg.memData.meminfo_size()) { + dataSeg.dataType = DATA_SOURCE_TYPE_MEM; + dataSeg.timeStamp = timeStamp; + dataSeg.clockId = clockId; + dataSeg.status = TS_PARSE_STATUS_PARSED; + } else if (dataSeg.memData.vmeminfo_size()) { + dataSeg.dataType = DATA_SOURCE_TYPE_MEM; + dataSeg.timeStamp = timeStamp; + dataSeg.clockId = clockId; + dataSeg.status = TS_PARSE_STATUS_PARSED; + } else { + dataSeg.status = TS_PARSE_STATUS_INVALID; + } +} +void HtraceParser::ParseHilog(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg) +{ + dataSeg.dataType = DATA_SOURCE_TYPE_HILOG; + dataSeg.traceData.Clear(); + if (!dataSeg.logData.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { + TS_LOGW("tracePacketParseFromArray failed\n"); + dataSeg.status = TS_PARSE_STATUS_PARSED; + return; + } + if (dataSeg.logData.info_size()) { + dataSeg.status = TS_PARSE_STATUS_PARSED; + return; + } + dataSeg.status = TS_PARSE_STATUS_INVALID; +} +void HtraceParser::ParseFtrace(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg) +{ + dataSeg.dataType = DATA_SOURCE_TYPE_TRACE; + dataSeg.traceData.Clear(); + if (!dataSeg.traceData.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { + TS_LOGW("tracePacketParseFromArray failed\n"); + dataSeg.status = TS_PARSE_STATUS_INVALID; + return; + } + if (dataSeg.traceData.ftrace_cpu_stats_size()) { + auto cpuStats = dataSeg.traceData.ftrace_cpu_stats(0); + auto s = cpuStats.per_cpu_stats(0); + TS_LOGD("s.overrun():%lu", s.overrun()); + TS_LOGD("s.dropped_events():%lu", s.dropped_events()); + auto clock = cpuStats.trace_clock(); + if (clock == "boot") { + clock_ = TS_CLOCK_BOOTTIME; + } + dataSeg.clockId = clock_; + dataSeg.status = TS_PARSE_STATUS_PARSED; + return; + } + if (dataSeg.traceData.clocks_detail_size() || dataSeg.traceData.ftrace_cpu_detail_size() || + dataSeg.traceData.symbols_detail_size()) { + dataSeg.status = TS_PARSE_STATUS_PARSED; + return; + } + dataSeg.status = TS_PARSE_STATUS_INVALID; +} + +void HtraceParser::ParseNativeHook(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg) +{ + dataSeg.dataType = DATA_SOURCE_TYPE_HEAP; + dataSeg.traceData.Clear(); + if (!dataSeg.batchNativeHookData.ParseFromArray(pluginData.data().data(), + static_cast(pluginData.data().size()))) { + TS_LOGW("tracePacketParseFromArray failed\n"); + dataSeg.status = TS_PARSE_STATUS_INVALID; + return; + } + if (dataSeg.batchNativeHookData.events_size()) { + dataSeg.status = TS_PARSE_STATUS_PARSED; + return; + } + dataSeg.status = TS_PARSE_STATUS_INVALID; +} + +void HtraceParser::ParseFPS(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg) +{ + dataSeg.dataType = DATA_SOURCE_TYPE_FPS; + dataSeg.traceData.Clear(); + if (!dataSeg.hidumpInfo.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { + TS_LOGW("tracePacketParseFromArray failed\n"); + dataSeg.status = TS_PARSE_STATUS_INVALID; + return; + } + if (dataSeg.hidumpInfo.fps_event_size()) { + dataSeg.status = TS_PARSE_STATUS_PARSED; + return; + } + dataSeg.status = TS_PARSE_STATUS_INVALID; +} +int HtraceParser::GetNextSegment() +{ + int head; + dataSegMux_.lock(); + head = parseHead_; + HtraceDataSegment& seg = dataSegArray[head]; + if (seg.status.load() != TS_PARSE_STATUS_SEPRATED) { + if (toExit_) { + parserThreadCount_--; + TS_LOGI("exiting parser, parserThread Count:%d\n", parserThreadCount_); + TS_LOGD("seprateHead_x:\t%d, parseHead_:\t%d, filterHead_:\t%d status:%d\n", rawDataHead_, parseHead_, + filterHead_, seg.status.load()); + dataSegMux_.unlock(); + if (!parserThreadCount_ && !filterThreadStarted_) { + exited_ = true; + } + return ERROR_CODE_EXIT; + } + if (seg.status.load() == TS_PARSE_STATUS_PARSING) { + dataSegMux_.unlock(); + usleep(sleepDur_); + return ERROR_CODE_NODATA; + } + dataSegMux_.unlock(); + usleep(sleepDur_); + return ERROR_CODE_NODATA; + } + parseHead_ = (parseHead_ + 1) % MAX_SEG_ARRAY_SIZE; + seg.status = TS_PARSE_STATUS_PARSING; + dataSegMux_.unlock(); + return head; +} +void HtraceParser::ParseTraceDataSegment(std::unique_ptr bufferStr, size_t size) +{ + packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]); + auto packagesBegin = packagesBuffer_.begin(); + auto currentLength = packagesBuffer_.size(); + if (!hasGotHeader) { + std::string start(reinterpret_cast(bufferStr.get()), std::min(size, 20)); + if (start.compare(0, std::string("OHOSPROF").length(), "OHOSPROF") == 0) { + currentLength -= PACKET_HEADER_LENGTH; + packagesBegin += PACKET_HEADER_LENGTH; + } + hasGotHeader = true; + } + while (1) { + if (!hasGotSegLength_) { + if (currentLength < PACKET_SEG_LENGTH) { + break; + } + std::string bufferLine(packagesBegin, packagesBegin + PACKET_SEG_LENGTH); + const uint32_t* len = reinterpret_cast(bufferLine.data()); + nextLength_ = *len; + hasGotSegLength_ = true; + currentLength -= PACKET_SEG_LENGTH; + packagesBegin += PACKET_SEG_LENGTH; + } + if (currentLength < nextLength_) { + break; + } + std::string bufferLine(packagesBegin, packagesBegin + nextLength_); + ParseTraceDataItem(bufferLine); + hasGotSegLength_ = false; + packagesBegin += nextLength_; + currentLength -= nextLength_; + } + packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin); + return; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..3b0e6a6c8b1704e86406a931d75a26a63cdc6da2 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_parser.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HTRACE_PARSER_H +#define HTRACE_PARSER_H +#include +#include +#include +#include +#include +#include +#include "common_types.h" +#include "htrace_clock_detail_parser.h" +#include "htrace_cpu_detail_parser.h" +#include "htrace_hidump_parser.h" +#include "htrace_hilog_parser.h" +#include "htrace_mem_parser.h" +#include "htrace_native_hook_parser.h" +#include "htrace_symbols_detail_parser.h" +#include "log.h" +#include "parser_base.h" +#include "trace_data/trace_data_cache.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +class HtraceParser : public ParserBase { +public: + HtraceParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters); + ~HtraceParser(); + void ParseTraceDataSegment(std::unique_ptr bufferStr, size_t size) override; + void WaitForParserEnd(); +private: + void ParseTraceDataItem(const std::string& buffer) override; + void FilterData(HtraceDataSegment& dataSeg); + void ParserData(HtraceDataSegment& dataSeg); +private: + void ParseMemory(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); + void ParseHilog(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); + void ParseFtrace(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); + void ParseNativeHook(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); + void ParseFPS(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); + void ParseThread(); + int GetNextSegment(); + void FilterThread(); + enum ErrorCode { + ERROR_CODE_EXIT = -2, + ERROR_CODE_NODATA = -1 + }; + bool hasGotSegLength_ = false; + bool hasGotHeader = false; + uint32_t nextLength_ = 0; + const size_t PACKET_SEG_LENGTH = 4; + const size_t PACKET_HEADER_LENGTH = 1024; + std::unique_ptr htraceCpuDetailParser_; + std::unique_ptr htraceSymbolsDetailParser_; + std::unique_ptr htraceMemParser_; + std::unique_ptr htraceClockDetailParser_; + std::unique_ptr htraceHiLogParser_; + std::unique_ptr htraceNativeHookParser_; + std::unique_ptr htraceHidumpParser_; + std::atomic filterThreadStarted_{false}; + const int MAX_SEG_ARRAY_SIZE = 10000; + std::unique_ptr dataSegArray; + int rawDataHead_ = 0; + bool toExit_ = false; + bool exited_ = false; + int filterHead_ = 0; + int parseHead_ = 0; + const int sleepDur_ = 100; + bool parseThreadStarted_ = false; + const int maxThread_ = 4; // 4 is the best on ubuntu 113MB/s, max 138MB/s, 6 is best on mac m1 21MB/s, + int parserThreadCount_ = 0; + std::mutex dataSegMux_; + bool noThread_ = true; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_PARSER_H_ diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_symbols_detail_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_symbols_detail_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63f22e8bcebf6f493e10c3ec81cc85dc6c98ed61 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_symbols_detail_parser.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "htrace_symbols_detail_parser.h" +#include "htrace_event_parser.h" +#include "symbols_filter.h" +namespace SysTuning { +namespace TraceStreamer { +HtraceSymbolsDetailParser::HtraceSymbolsDetailParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : streamFilters_(ctx), traceDataCache_(dataCache) +{ + UNUSED(traceDataCache_); + if (!streamFilters_) { + TS_LOGE("streamFilters_ should not be null"); + return; + } +} + +HtraceSymbolsDetailParser::~HtraceSymbolsDetailParser() = default; +void HtraceSymbolsDetailParser::Parse(const TracePluginResult& tracePacket) +{ + if (!tracePacket.symbols_detail_size()) { + return; + } + if (!streamFilters_) { + TS_LOGE("streamFilters_ should not be null"); + return; + } + for (int i = 0; i < tracePacket.symbols_detail_size(); i++) { + auto symbol = const_cast(tracePacket).mutable_symbols_detail(i); + TS_LOGD("symbol_name:%s, symbol_addr:%lu", symbol->symbol_name().c_str(), symbol->symbol_addr()); + // symbol + streamFilters_->symbolsFilter_->RegisterFunc(symbol->symbol_addr(), + traceDataCache_->GetDataIndex(symbol->symbol_name())); + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_symbols_detail_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_symbols_detail_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..5af70f96844f17c1db064ba7d264ac8c6e67327d --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_symbols_detail_parser.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HTRACE_SYMBOLS_DETAIL_PARSER_H +#define HTRACE_SYMBOLS_DETAIL_PARSER_H + +#include +#include +#include +#include +#include +#include "trace_data/trace_data_cache.h" +#include "trace_plugin_result.pb.h" +#include "trace_streamer_filters.h" +namespace SysTuning { +namespace TraceStreamer { +class HtraceSymbolsDetailParser { +public: + HtraceSymbolsDetailParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~HtraceSymbolsDetailParser(); + void Parse(const TracePluginResult& tracePacket); + +private: + const TraceStreamerFilters* streamFilters_; + TraceDataCache* traceDataCache_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_SYMBOLS_DETAIL_PARSER_H diff --git a/host/trace_streamer/src/parser/parser.pri b/host/trace_streamer/src/parser/parser.pri new file mode 100644 index 0000000000000000000000000000000000000000..47f8a891137b9175e8356249abaa32f6e5222d2e --- /dev/null +++ b/host/trace_streamer/src/parser/parser.pri @@ -0,0 +1,51 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +INCLUDEPATH += $$PWD \ + $$PWD/bytrace_parser \ + $$PWD/htrace_parser/htrace_cpu_parser \ + $$PWD/htrace_parser/htrace_event_parser \ + $$PWD/htrace_parser/htrace_symbol_parser +HEADERS += \ + $$PWD/common_types.h \ + $$PWD/event_parser_base.h \ + $$PWD/thread_state.h \ + $$PWD/print_event_parser.h \ + $$PWD/bytrace_parser/bytrace_parser.h \ + $$PWD/bytrace_parser/bytrace_event_parser.h \ + $$PWD/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.h \ + $$PWD/htrace_parser/htrace_event_parser/htrace_event_parser.h \ + $$PWD/htrace_parser/htrace_parser.h \ + $$PWD/htrace_parser/htrace_mem_parser.h \ + $$PWD/htrace_parser/htrace_hilog_parser.h \ + $$PWD/htrace_parser/htrace_native_hook_parser.h \ + $$PWD/htrace_parser/htrace_hidump_parser.h \ + $$PWD/htrace_parser/htrace_clock_detail_parser.h \ + $$PWD/htrace_parser/htrace_symbols_detail_parser.h + + +SOURCES += \ + $$PWD/parser_base.cpp \ + $$PWD/event_parser_base.cpp \ + $$PWD/thread_state.cpp \ + $$PWD/print_event_parser.cpp \ + $$PWD/bytrace_parser/bytrace_parser.cpp \ + $$PWD/bytrace_parser/bytrace_event_parser.cpp \ + $$PWD/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.cpp \ + $$PWD/htrace_parser/htrace_event_parser/htrace_event_parser.cpp \ + $$PWD/htrace_parser/htrace_parser.cpp \ + $$PWD/htrace_parser/htrace_mem_parser.cpp \ + $$PWD/htrace_parser/htrace_hilog_parser.cpp \ + $$PWD/htrace_parser/htrace_native_hook_parser.cpp \ + $$PWD/htrace_parser/htrace_hidump_parser.cpp \ + $$PWD/htrace_parser/htrace_clock_detail_parser.cpp \ + $$PWD/htrace_parser/htrace_symbols_detail_parser.cpp diff --git a/host/trace_streamer/src/parser/parser_base.cpp b/host/trace_streamer/src/parser/parser_base.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5f06e9c87652b7599d05905cbee822577eb952e6 --- /dev/null +++ b/host/trace_streamer/src/parser/parser_base.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "parser_base.h" +namespace SysTuning { +namespace TraceStreamer { +ParserBase::ParserBase(const TraceStreamerFilters* filter) + : streamFilters_(filter), clock_(TS_CLOCK_UNKNOW) +{ +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/parser_base.h b/host/trace_streamer/src/parser/parser_base.h new file mode 100644 index 0000000000000000000000000000000000000000..ed5e142751b5c497929faf0e79a3b7e88e16a0be --- /dev/null +++ b/host/trace_streamer/src/parser/parser_base.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_PARSER_BASE_H +#define SRC_PARSER_BASE_H +#include +#include +#include "trace_streamer_filters.h" +#include "ts_common.h" +namespace SysTuning { +namespace TraceStreamer { +class ParserBase { +public: + explicit ParserBase(const TraceStreamerFilters* filter); + virtual ~ParserBase() = default; + virtual void ParseTraceDataSegment(std::unique_ptr, size_t size) = 0; +protected: + virtual void ParseTraceDataItem(const std::string& buffer) = 0; + std::deque packagesBuffer_ = {}; + const TraceStreamerFilters *streamFilters_; + BuiltinClocks clock_; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif diff --git a/host/trace_streamer/src/parser/print_event_parser.cpp b/host/trace_streamer/src/parser/print_event_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8773bbb7d5eca086e187ed2726809bab375a7dfe --- /dev/null +++ b/host/trace_streamer/src/parser/print_event_parser.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "print_event_parser.h" +#include "stat_filter.h" +#include "string_to_numerical.h" +namespace SysTuning { +namespace TraceStreamer { +PrintEventParser::PrintEventParser(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : EventParserBase(dataCache, filter), + pointLength_(1), + maxPointLength_(2) +{ +} + +void PrintEventParser::ParsePrintEvent(uint64_t ts, uint32_t pid, std::string_view event) const +{ + TracePoint point; + if (GetTracePoint(event, point) == SUCCESS) { + ParseTracePoint(ts, pid, point); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_RECEIVED); + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_INVALID); + } +} + +void PrintEventParser::ParseTracePoint(uint64_t ts, uint32_t pid, TracePoint point) const +{ + if (point.tgid_) { + streamFilters_->processFilter_->GetOrCreateInternalPid(ts, point.tgid_); + } + switch (point.phase_) { + case 'B': { + if (streamFilters_->sliceFilter_->BeginSlice(ts, pid, point.tgid_, 0, + traceDataCache_->GetDataIndex(point.name_))) { + // add distributed data + traceDataCache_->GetInternalSlicesData()->AppendDistributeInfo( + point.chainId_, point.spanId_, point.parentSpanId_, point.flag_, point.args_); + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_LOST); + } + break; + } + case 'E': { + streamFilters_->sliceFilter_->EndSlice(ts, pid, point.tgid_); + break; + } + case 'S': { + auto cookie = static_cast(point.value_); + streamFilters_->sliceFilter_->StartAsyncSlice(ts, pid, point.tgid_, cookie, + traceDataCache_->GetDataIndex(point.name_)); + break; + } + case 'F': { + auto cookie = static_cast(point.value_); + streamFilters_->sliceFilter_->FinishAsyncSlice(ts, pid, point.tgid_, cookie, + traceDataCache_->GetDataIndex(point.name_)); + break; + } + case 'C': { + DataIndex nameIndex = traceDataCache_->GetDataIndex(point.name_); + uint32_t internalPid = streamFilters_->processFilter_->GetInternalPid(point.tgid_); + if (internalPid != INVALID_ID) { + streamFilters_->processMeasureFilter_->AppendNewMeasureData(internalPid, nameIndex, ts, point.value_); + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_INVALID); + } + break; + } + default: + TS_LOGD("point missing!"); + break; + } +} + +ParseResult PrintEventParser::CheckTracePoint(std::string_view pointStr) const +{ + if (pointStr.size() == 0) { + TS_LOGD("get trace point data size is 0!"); + return ERROR; + } + + std::string clockSyncSts = "trace_event_clock_sync"; + if (pointStr.compare(0, clockSyncSts.length(), clockSyncSts.c_str()) == 0) { + TS_LOGD("skip trace point :%s!", clockSyncSts.c_str()); + return ERROR; + } + + if (pointStr.find_first_of('B') != 0 && pointStr.find_first_of('E') != 0 && pointStr.find_first_of('C') != 0 && + pointStr.find_first_of('S') != 0 && pointStr.find_first_of('F') != 0) { + TS_LOGD("trace point not supported : [%c] !", pointStr[0]); + return ERROR; + } + + if (pointStr.find_first_of('E') != 0 && pointStr.size() == 1) { + TS_LOGD("point string size error!"); + return ERROR; + } + + if (pointStr.size() >= maxPointLength_) { + if ((pointStr[1] != '|') && (pointStr[1] != '\n')) { + TS_LOGD("not support data formart!"); + return ERROR; + } + } + + return SUCCESS; +} + +std::string_view PrintEventParser::GetPointNameForBegin(std::string_view pointStr, size_t tGidlength) const +{ + size_t index = maxPointLength_ + tGidlength + pointLength_; + + size_t length = pointStr.size() - index - ((pointStr.back() == '\n') ? 1 : 0); + std::string_view name = std::string_view(pointStr.data() + index, length); + return name; +} + +ParseResult PrintEventParser::HandlerB(std::string_view pointStr, TracePoint& outPoint, size_t tGidlength) const +{ + outPoint.name_ = GetPointNameForBegin(pointStr, tGidlength); + if (outPoint.name_.empty()) { + TS_LOGD("point name is empty!"); + return ERROR; + } + // Use $# to differentiate distributed data + if (outPoint.name_.find("$#") == std::string::npos) { + return SUCCESS; + } + // Resolve distributed calls + const std::regex distributeMatcher = + std::regex(R"((?:^\[([a-z0-9]+),(\d+),(\d+)\]:?([CS]?)\$#)?(.*)\$#(.*)$)"); + std::smatch matcheLine; + bool matched = std::regex_match(outPoint.name_, matcheLine, distributeMatcher); + if (matched) { + size_t index = 0; + outPoint.chainId_ = matcheLine[++index].str(); + outPoint.spanId_ = matcheLine[++index].str(); + outPoint.parentSpanId_ = matcheLine[++index].str(); + outPoint.flag_ = matcheLine[++index].str(); + outPoint.name_ = matcheLine[++index].str(); + outPoint.args_ = matcheLine[++index].str(); + } + return SUCCESS; +} + +ParseResult PrintEventParser::HandlerE(void) const +{ + return SUCCESS; +} + +size_t PrintEventParser::GetNameLength(std::string_view pointStr, size_t nameIndex) const +{ + size_t namelength = 0; + for (size_t i = nameIndex; i < pointStr.size(); i++) { + if (pointStr[i] == '|') { + namelength = i - nameIndex; + break; + } + } + return namelength; +} + +size_t PrintEventParser::GetValueLength(std::string_view pointStr, size_t valueIndex) const +{ + size_t valuePipe = pointStr.find('|', valueIndex); + size_t valueLen = pointStr.size() - valueIndex; + if (valuePipe != std::string_view::npos) { + valueLen = valuePipe - valueIndex; + } + + if (valueLen == 0) { + return 0; + } + + if (pointStr[valueIndex + valueLen - pointLength_] == '\n') { + valueLen--; + } + + return valueLen; +} + +ParseResult PrintEventParser::HandlerCSF(std::string_view pointStr, TracePoint& outPoint, size_t tGidlength) const +{ + // point name + size_t nameIndex = maxPointLength_ + tGidlength + pointLength_; + size_t namelength = GetNameLength(pointStr, nameIndex); + if (namelength == 0) { + TS_LOGD("point name length is error!"); + return ERROR; + } + outPoint.name_ = std::string_view(pointStr.data() + nameIndex, namelength); + + // point value + size_t valueIndex = nameIndex + namelength + pointLength_; + size_t valueLen = GetValueLength(pointStr, valueIndex); + if (valueLen == 0) { + TS_LOGD("point value length is error!"); + return ERROR; + } + + std::string valueStr(pointStr.data() + valueIndex, valueLen); + if (!base::StrToUInt64(valueStr).has_value()) { + TS_LOGD("point value is error!"); + return ERROR; + } + outPoint.value_ = base::StrToUInt64(valueStr).value(); + + size_t valuePipe = pointStr.find('|', valueIndex); + if (valuePipe != std::string_view::npos) { + size_t groupLen = pointStr.size() - valuePipe - pointLength_; + if (groupLen == 0) { + return ERROR; + } + + if (pointStr[pointStr.size() - pointLength_] == '\n') { + groupLen--; + } + + outPoint.categoryGroup_ = std::string_view(pointStr.data() + valuePipe + 1, groupLen); + } + + return SUCCESS; +} + +ParseResult PrintEventParser::GetTracePoint(std::string_view pointStr, TracePoint& outPoint) const +{ + if (CheckTracePoint(pointStr) != SUCCESS) { + return ERROR; + } + + size_t tGidlength = 0; + + outPoint.phase_ = pointStr.front(); + outPoint.tgid_ = GetThreadGroupId(pointStr, tGidlength); + + ParseResult ret = ERROR; + switch (outPoint.phase_) { + case 'B': { + ret = HandlerB(pointStr, outPoint, tGidlength); + break; + } + case 'E': { + ret = HandlerE(); + break; + } + case 'S': + case 'F': + case 'C': { + ret = HandlerCSF(pointStr, outPoint, tGidlength); + break; + } + default: + return ERROR; + } + return ret; +} + +uint32_t PrintEventParser::GetThreadGroupId(std::string_view pointStr, size_t& length) const +{ + for (size_t i = maxPointLength_; i < pointStr.size(); i++) { + if (pointStr[i] == '|' || pointStr[i] == '\n') { + break; + } + + if (pointStr[i] < '0' || pointStr[i] > '9') { + return ERROR; + } + + length++; + } + + std::string str(pointStr.data() + maxPointLength_, length); + return base::StrToUInt32(str).value_or(0); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/print_event_parser.h b/host/trace_streamer/src/parser/print_event_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..71311215407a7e9388436576e764d820d1102d26 --- /dev/null +++ b/host/trace_streamer/src/parser/print_event_parser.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SRC_PRINT_EVENT_PARSER_H +#define SRC_PRINT_EVENT_PARSER_H +#include +#include +#include "common_types.h" +#include "event_parser_base.h" +#include "filter/measure_filter.h" +#include "filter/process_filter.h" +#include "filter/slice_filter.h" +#include "string_to_numerical.h" +namespace SysTuning { +namespace TraceStreamer { +class PrintEventParser : private EventParserBase { +public: + PrintEventParser(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + void ParsePrintEvent(uint64_t ts, uint32_t pid, std::string_view event) const; +private: + void ParseTracePoint(uint64_t ts, uint32_t pid, TracePoint point) const; + ParseResult GetTracePoint(std::string_view str, TracePoint& out) const; + ParseResult CheckTracePoint(std::string_view pointStr) const; + uint32_t GetThreadGroupId(std::string_view pointStr, size_t& length) const; + std::string_view GetPointNameForBegin(std::string_view pointStr, size_t tGidlength) const; + ParseResult HandlerB(std::string_view pointStr, TracePoint& outPoint, size_t tGidlength) const; + ParseResult HandlerE(void) const; + ParseResult HandlerCSF(std::string_view pointStr, TracePoint& outPoint, size_t tGidlength) const; + size_t GetNameLength(std::string_view pointStr, size_t nameIndex) const; + size_t GetValueLength(std::string_view pointStr, size_t valueIndex) const; +private: + const uint32_t pointLength_; + const uint32_t maxPointLength_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // SRC_PRINT_EVENT_PARSER_H diff --git a/host/trace_streamer/src/parser/thread_state.cpp b/host/trace_streamer/src/parser/thread_state.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a373a7855acd5ae90291c03526b82dbb94b5895a --- /dev/null +++ b/host/trace_streamer/src/parser/thread_state.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "thread_state.h" + +namespace SysTuning { +namespace TraceStreamer { +Direction ThreadState::SetStatByChar(char ch) +{ + if (ch == 'R') { + if (state_ == 0) { + return NEED_CONTINUE; + } + } + + if (statMap_.find(ch) == statMap_.end()) { + return NEED_BREAK; + } + + state_ |= statMap_[ch]; + return NEED_GO; +} + +void ThreadState::ProcessSate(const std::string& stateStr) +{ + for (size_t i = 0; i < stateStr.size(); i++) { + if (stateStr[i] == '+') { + invalid_ = true; + SetStat(TASKNEW); + continue; + } + + Direction ret = SetStatByChar(stateStr[i]); + if (ret == NEED_CONTINUE) { + invalid_ = true; + continue; + } else if (ret == NEED_BREAK) { + break; + } + } +} + +ThreadState::ThreadState(const std::string& stateStr) +{ + ProcessSate(stateStr); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/thread_state.h b/host/trace_streamer/src/parser/thread_state.h new file mode 100644 index 0000000000000000000000000000000000000000..f0b90154a2f60d6204217d24f499a710507bf157 --- /dev/null +++ b/host/trace_streamer/src/parser/thread_state.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BYTRACE_THREAD_STATES_H +#define BYTRACE_THREAD_STATES_H + +#include +#include "common_types.h" +#include "log.h" + +namespace SysTuning { +namespace TraceStreamer { +enum Direction { NEED_GO = 0, NEED_CONTINUE, NEED_BREAK }; + +class ThreadState { +public: + explicit ThreadState(const std::string& stateStr); + ~ThreadState() {} + + uint32_t State() const + { + return state_ & ~VALID; + } + bool IsValid() const + { + return invalid_; + } + +private: + void SetStat(Stat value) + { + state_ |= value; + } + + void ProcessSate(const std::string& stateStr); + Direction SetStatByChar(char ch); +private: + uint32_t state_ = 0; + std::map statMap_ = { + {'R', RUNNABLE}, + {'S', INTERRUPTABLESLEEP}, + {'D', UNINTERRUPTIBLESLEEP}, + {'T', STOPPED}, + {'t', TRACED}, + {'X', EXITDEAD}, + {'Z', EXITZOMBIE}, + {'x', TASKDEAD}, + {'I', TASKDEAD}, + {'K', WAKEKILL}, + {'P', PARKED}, + {'N', NOLOAD}, + {'|', VALID}, + }; + bool invalid_ = false; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // _BYTRACE_THREAD_STATES_H_ diff --git a/host/trace_streamer/src/protos/README_zh.md b/host/trace_streamer/src/protos/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..112aca9fde16f35a2df60912239483812ae69484 --- /dev/null +++ b/host/trace_streamer/src/protos/README_zh.md @@ -0,0 +1,10 @@ +# protos 代码仓 + + + +`services` 目录下存放的是 服务接口定义, + +`types` 目录下存放的是 具体插件业务相关的类型定义,主要为配置类型和结果类型定义; + +例如,`types/plugins/cpu_data/` 目录存放CPU数据插件的配置类型和结果类型; + diff --git a/host/trace_streamer/src/protos/protogen.sh b/host/trace_streamer/src/protos/protogen.sh new file mode 100644 index 0000000000000000000000000000000000000000..c35b0515d89492c2de6a9266ab5c36913943aba7 --- /dev/null +++ b/host/trace_streamer/src/protos/protogen.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +SOURCE="${BASH_SOURCE[0]}" +cd $(dirname ${SOURCE}) +echo "begin to generate proto based files" +SOURCE=$(dirname ${SOURCE}) +proto_dir="." +services_dir="$proto_dir/services" +ftrace_data_dir="$proto_dir/types/plugins/ftrace_data" +memory_data_dir="$proto_dir/types/plugins/memory_data" +hilog_data_dir="$proto_dir/types/plugins/hilog_data" +native_hook_dir="$proto_dir/types/plugins/native_hook" +hidump_data_dir="$proto_dir/types/plugins/hidump_data" +arrayWen=("${services_dir}/common_types.proto" + "$ftrace_data_dir/trace_plugin_result.proto" + "$ftrace_data_dir/ftrace_event.proto" + "$ftrace_data_dir/irq.proto" + "$ftrace_data_dir/vmscan.proto" + "$ftrace_data_dir/workqueue.proto" + "$ftrace_data_dir/task.proto" + "$ftrace_data_dir/power.proto" + "$ftrace_data_dir/sched.proto" + "$ftrace_data_dir/filemap.proto" + "$ftrace_data_dir/i2c.proto" + "$ftrace_data_dir/kmem.proto" + "$ftrace_data_dir/block.proto" + "$ftrace_data_dir/ipi.proto" + "$ftrace_data_dir/ftrace.proto" + "$ftrace_data_dir/ext4.proto" + "$ftrace_data_dir/oom.proto" + "$ftrace_data_dir/compaction.proto" + "$ftrace_data_dir/clk.proto" + "$ftrace_data_dir/cgroup.proto" + "$ftrace_data_dir/binder.proto" + "$ftrace_data_dir/signal.proto" + "$ftrace_data_dir/sunrpc.proto" + "$ftrace_data_dir/net.proto" + "$ftrace_data_dir/cpuhp.proto" + "$ftrace_data_dir/writeback.proto" + "$ftrace_data_dir/v4l2.proto" + "$ftrace_data_dir/pagemap.proto" + "$ftrace_data_dir/dma_fence.proto" + "$ftrace_data_dir/printk.proto" + "$ftrace_data_dir/filelock.proto" + "$ftrace_data_dir/gpio.proto" + "$ftrace_data_dir/timer.proto" + "$ftrace_data_dir/raw_syscalls.proto" + "$ftrace_data_dir/rcu.proto" + "$memory_data_dir/memory_plugin_common.proto" + "$memory_data_dir/memory_plugin_config.proto" + "$memory_data_dir/memory_plugin_result.proto" + "$hilog_data_dir/hilog_plugin_result.proto" + "$native_hook_dir/native_hook_result.proto" + "$native_hook_dir/native_hook_config.proto" + "$hidump_data_dir/hidump_plugin_result.proto" + "$hidump_data_dir/hidump_plugin_config.proto") + +export LD_LIBRARY_PATH=../../out/linux +for ((i = 0; i < ${#arrayWen[@]}; i ++)) +do + newpath=$(dirname ${arrayWen[$i]}) + newpath=${newpath:2} + cppout=../../third_party/protogen/$newpath + mkdir -p $cppout + ../../out/linux/protoc --proto_path=$memory_data_dir:$native_hook_dir:$hidump_data_dir:$hilog_data_dir:$ftrace_data_dir:$services_dir --cpp_out=$cppout ${arrayWen[$i]} +done +echo "generate proto based files over" \ No newline at end of file diff --git a/host/trace_streamer/src/protos/protos.gni b/host/trace_streamer/src/protos/protos.gni new file mode 100644 index 0000000000000000000000000000000000000000..59b67bb4b515a7fbc307e19b3349aad8ee5e25c2 --- /dev/null +++ b/host/trace_streamer/src/protos/protos.gni @@ -0,0 +1,24 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("../../../build/config.gni") + +subsys_name = OHOS_PROFILER_SUBSYS_NAME +subsys_x64_out = "clang_x64/$subsys_name/$subsys_name" +libc_dir_proto = rebase_path("$asdk_libs_dir", "//") +root_output_dir_proto = rebase_path("$root_out_dir", "//") +# print("grpc_cpp_plugin = ", grpc_cpp_plugin) +# print("ipc_cpp_plugin = ", ipc_cpp_plugin) +# print("root_build_dir = ", root_build_dir) +# print("root_out_dir = ", root_out_dir) +# print("root_gen_dir = ", root_gen_dir) diff --git a/host/trace_streamer/src/protos/services/BUILD.gn b/host/trace_streamer/src/protos/services/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..81abebbbd4a31b3ccbbc71f2ddba39dddadf18dd --- /dev/null +++ b/host/trace_streamer/src/protos/services/BUILD.gn @@ -0,0 +1,225 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../protos.gni") + +proto_types_defines = [ + "./common_types.proto", + "./plugin_service_types.proto", + "./profiler_service_types.proto", +] + +plugin_services_defines = [ "./plugin_service.proto" ] + +profiler_services_defines = [ "./profiler_service.proto" ] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) +print("proto_out_dir", proto_out_dir, proto_rel_out_dir) + +grpc_cpp_plugin = "$subsys_x64_out/grpc_cpp_plugin" +ipc_cpp_plugin = "$subsys_x64_out/protoc_gen_ipc" + +####################################################### +proto_types_codegen = [] +foreach(proto, proto_types_defines) { + name = get_path_info(proto, "name") + proto_types_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] +} + +action("service_types_proto_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = proto_types_defines + outputs = proto_types_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ + "${OHOS_PROFILER_3RDPARTY_GRPC_DIR}:grpc_cpp_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + ] +} + +config("service_types_proto_config") { + include_dirs = [ "$proto_out_dir" ] +} + +ohos_source_set("service_types_proto") { + deps = [ ":service_types_proto_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":service_types_proto_config" ] + sources = proto_types_codegen +} + +ohos_source_set("service_types_proto_static") { + deps = [ ":service_types_proto_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite_static", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_static", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":service_types_proto_config" ] + sources = proto_types_codegen +} + +####################################################### +profiler_services_codegen = [] +foreach(proto, profiler_services_defines) { + name = get_path_info(proto, "name") + profiler_services_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + "$proto_out_dir/$name.grpc.pb.h", + "$proto_out_dir/$name.grpc.pb.cc", + ] +} + +action("profiler_services_proto_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = profiler_services_defines + outputs = profiler_services_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--plugin=protoc-gen-grpc=$grpc_cpp_plugin", + "--grpc_out", + "$proto_rel_out_dir", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ + "${OHOS_PROFILER_3RDPARTY_GRPC_DIR}:grpc_cpp_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + ] +} + +config("profiler_services_proto_config") { + include_dirs = [ "$proto_out_dir" ] +} + +ohos_source_set("profiler_services_proto") { + deps = [ + ":profiler_services_proto_gen", + ":service_types_proto", + ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_GRPC_DIR}:grpc", + "${OHOS_PROFILER_3RDPARTY_GRPC_DIR}:grpcxx", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":profiler_services_proto_config" ] + sources = profiler_services_codegen +} + +####################################################### +plugin_services_codegen = [] +foreach(proto, plugin_services_defines) { + name = get_path_info(proto, "name") + plugin_services_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + "$proto_out_dir/$name.ipc.h", + "$proto_out_dir/$name.ipc.cc", + ] +} + +action("plugin_services_proto_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = plugin_services_defines + outputs = plugin_services_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--plugin=protoc-gen-ipc=$ipc_cpp_plugin", + "--ipc_out", + "$proto_rel_out_dir", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${OHOS_PROFILER_DIR}/device/services/ipc:protoc_gen_ipc(${host_toolchain})", + ] +} + +config("plugin_services_proto_config") { + include_dirs = [ "$proto_out_dir" ] +} + +ohos_source_set("plugin_services_proto") { + deps = [ + ":plugin_services_proto_gen", + ":service_types_proto", + ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + "${OHOS_PROFILER_DIR}/device/services/ipc:ipc", + ] + include_dirs = [ + "$proto_out_dir", + "${OHOS_PROFILER_DIR}/device/services/ipc/include", + ] + public_configs = [ ":plugin_services_proto_config" ] + sources = plugin_services_codegen +} + +ohos_source_set("plugin_services_proto_static") { + deps = [ + ":plugin_services_proto_gen", + ":service_types_proto_static", + ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite_static", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_static", + "${OHOS_PROFILER_DIR}/device/services/ipc:ipc", + ] + include_dirs = [ + "$proto_out_dir", + "${OHOS_PROFILER_DIR}/device/services/ipc/include", + ] + public_configs = [ ":plugin_services_proto_config" ] + sources = plugin_services_codegen +} + +####################################################### +ohos_source_set("proto_services_cpp") { + public_deps = [ + ":plugin_services_proto", + ":profiler_services_proto", + ":service_types_proto", + ] +} diff --git a/host/trace_streamer/src/protos/services/common_types.proto b/host/trace_streamer/src/protos/services/common_types.proto new file mode 100644 index 0000000000000000000000000000000000000000..fa67090edba2d200a1f505316e7df62252f3dd0f --- /dev/null +++ b/host/trace_streamer/src/protos/services/common_types.proto @@ -0,0 +1,58 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; + +// Common message define for profiler tools, imported by profiler and plugin proto file. +message ProfilerPluginConfig { + string name = 1; + string plugin_sha256 = 2; + uint32 sample_interval = 3; + bytes config_data = 4; +} + +message ProfilerPluginState { + string name = 1; + enum State { + INITED = 0; + REGISTERED = 1; // registered to plugin service. + LOADED = 2; // have created session. + IN_SESSION = 3; // have started session. + }; + State state = 2; +} + +// for FetchDataResponse +message ProfilerPluginData { + string name = 1; + uint32 status = 2; + bytes data = 3; + enum ClockId { + CLOCKID_REALTIME = 0; + CLOCKID_REALTIME_ALARM = 1; // since Linux 3.0; Linux-specific + CLOCKID_REALTIME_COARSE = 2; // since Linux 2.6.32; Linux-specific + CLOCKID_TAI = 3; // since Linux 3.10; Linux-specific + CLOCKID_MONOTONIC = 4; + CLOCKID_MONOTONIC_COARSE = 5; // since Linux 2.6.32; Linux-specific + CLOCKID_MONOTONIC_RAW = 6; // since Linux 2.6.28; Linux-specific + CLOCKID_BOOTTIME = 7; // since Linux 2.6.39; Linux-specific + CLOCKID_BOOTTIME_ALARM = 8; // since Linux 3.0; Linux-specific + CLOCKID_PROCESS_CPUTIME_ID = 9; // since Linux 2.6.12 + CLOCKID_THREAD_CPUTIME_ID = 10; // since Linux 2.6.12 + }; + ClockId clock_id = 4; + uint64 tv_sec = 5; + uint64 tv_nsec = 6; +} diff --git a/host/trace_streamer/src/protos/services/plugin_service.proto b/host/trace_streamer/src/protos/services/plugin_service.proto new file mode 100644 index 0000000000000000000000000000000000000000..ab8583d216c151f1dbdf4839c1f94a00f65a6bcf --- /dev/null +++ b/host/trace_streamer/src/protos/services/plugin_service.proto @@ -0,0 +1,31 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +import "plugin_service_types.proto"; + +// IPC interface between profiler service and plugin service. +// Use protobuf plug-ins to convert proto define to +// source and header files during the build process. +service IPluginService { + + rpc RegisterPlugin(RegisterPluginRequest) returns (RegisterPluginResponse); + + rpc UnregisterPlugin(UnregisterPluginRequest) returns (UnregisterPluginResponse); + + // service will use this interface to push commands with streamed return channel. + rpc GetCommand(GetCommandRequest) returns (stream GetCommandResponse); + + rpc NotifyResult(NotifyResultRequest) returns (NotifyResultResponse); +}; diff --git a/host/trace_streamer/src/protos/services/plugin_service_types.proto b/host/trace_streamer/src/protos/services/plugin_service_types.proto new file mode 100644 index 0000000000000000000000000000000000000000..3f54f23066364586a6a53543be59c258e8f98806 --- /dev/null +++ b/host/trace_streamer/src/protos/services/plugin_service_types.proto @@ -0,0 +1,103 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +import "common_types.proto"; + +// Message define for IPC interface, imported by plugin service proto file. +// for RegisterPlugin API +message RegisterPluginRequest { + uint32 request_id = 1; + string path = 2; + string sha256 = 3; + + string name = 4; + uint32 buffer_size_hint = 5; +} + +message RegisterPluginResponse { + uint32 status = 1; + uint32 plugin_id = 2; +} + +// for UnregisterPlugin API +message UnregisterPluginRequest { + uint32 request_id = 1; + uint32 plugin_id = 2; +} + +message UnregisterPluginResponse { + uint32 status = 1; +} + +// for GetCommand API +message GetCommandRequest { + uint32 request_id = 1; +} + +message CreateSessionCmd { + repeated uint32 buffer_sizes = 1; + repeated ProfilerPluginConfig plugin_configs = 2; +} + +message DestroySessionCmd { + repeated uint32 plugin_ids = 1; +} + +message StartSessionCmd { + repeated uint32 plugin_ids = 1; + repeated ProfilerPluginConfig plugin_configs = 2; +} + +message StopSessionCmd { + repeated uint32 plugin_ids = 1; +} + +message GetCommandResponse { + uint32 status = 1; + bool has_more = 2; + uint32 command_id = 3; + oneof command { + CreateSessionCmd create_session_cmd = 10; + DestroySessionCmd destroy_session_cmd = 11; + StartSessionCmd start_session_cmd = 12; + StopSessionCmd stop_session_cmd = 13; + } +} + +// for NotifyResult API +message BufferDescriptor { + int32 buffer_id = 1; + uint32 offset = 2; + uint32 length = 3; +} + +message PluginResult { + uint32 plugin_id = 1; + oneof descriptor { + bytes data = 2; + BufferDescriptor buffer = 3; + }; + ProfilerPluginState status = 10; +} + +message NotifyResultRequest { + uint32 request_id = 1; + uint32 command_id = 2; + repeated PluginResult result = 3; +} + +message NotifyResultResponse { + uint32 status = 1; +} diff --git a/host/trace_streamer/src/protos/services/profiler_service.proto b/host/trace_streamer/src/protos/services/profiler_service.proto new file mode 100644 index 0000000000000000000000000000000000000000..35e1e1866dcc847bb4fe1a9b6882b94355fb0471 --- /dev/null +++ b/host/trace_streamer/src/protos/services/profiler_service.proto @@ -0,0 +1,44 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; + +import "profiler_service_types.proto"; + +// RPC interface between profiler service and host service +// Use protobuf plug-ins to convert proto define to +// source and header files during the build process. +service IProfilerService { + // get all plugin infos and capabilities. + rpc GetCapabilities(GetCapabilitiesRequest) returns (GetCapabilitiesResponse); + + // create tracing sesion and pass tracing config to plugins. + rpc CreateSession(CreateSessionRequest) returns (CreateSessionResponse); + + // start tracing session, active server side tracing triggers. + rpc StartSession(StartSessionRequest) returns (StartSessionResponse); + + // get server-side cached tracing data since current session started. + rpc FetchData(FetchDataRequest) returns (stream FetchDataResponse); + + // stop tracing session, deactivate server side tracing triggers. + rpc StopSession(StopSessionRequest) returns (StopSessionResponse); + + // destroy tracing session. + rpc DestroySession(DestroySessionRequest) returns (DestroySessionResponse); + + // keep tracing session alive, call this interface will restart session expire count down task. + rpc KeepSession(KeepSessionRequest) returns (KeepSessionResponse); +} diff --git a/host/trace_streamer/src/protos/services/profiler_service_types.proto b/host/trace_streamer/src/protos/services/profiler_service_types.proto new file mode 100644 index 0000000000000000000000000000000000000000..a557e620a7e79f61ed99c19f93e91293aa6d1e2b --- /dev/null +++ b/host/trace_streamer/src/protos/services/profiler_service_types.proto @@ -0,0 +1,129 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; + +import "common_types.proto"; + +// Message define for profiler service, imported by profiler service proto file. +// for GetCapabilities +message GetCapabilitiesRequest { + uint32 request_id = 1; +} + +message ProfilerPluginCapability { + string path = 1; + string name = 2; +} + +message GetCapabilitiesResponse { + uint32 status = 1; + repeated ProfilerPluginCapability capabilities = 2; +} + + +// for CreateSessionRequest +message ProfilerSessionConfig { + message BufferConfig { + enum Policy { + RECYCLE = 0; + FLATTEN = 1; + }; + uint32 pages = 1; + Policy policy = 2; + } + repeated BufferConfig buffers = 1; + + enum Mode { + OFFLINE = 0; // save all plugin results to result file. + ONLINE = 1; // push all plugin results to host PC with streamed FetchDataResponse. + }; + Mode session_mode = 2; + string result_file = 3; // for OFFLINE mode, result file path + uint32 result_max_size = 4; // for OFFLINE mode, result file max size in KB + uint32 sample_duration = 5; // for OFFLINE mode, sample duration in ms + uint32 keep_alive_time = 6; // if set to non-zero value, session will auto-destroyed after CreateSession in ms +} + +message CreateSessionRequest { + uint32 request_id = 1; + ProfilerSessionConfig session_config = 2; + repeated ProfilerPluginConfig plugin_configs = 3; +} + +message CreateSessionResponse { + uint32 status = 1; + uint32 session_id = 2; + repeated ProfilerPluginState plugin_status = 3; +} + +// for StartSession +message StartSessionRequest { + uint32 request_id = 1; + uint32 session_id = 2; + repeated ProfilerPluginConfig update_configs = 3; +} + +message StartSessionResponse { + uint32 status = 1; + repeated ProfilerPluginState plugin_status = 3; +} + +// for FetchData +message FetchDataRequest { + uint32 request_id = 1; + uint32 session_id = 2; + bytes addtion_data = 3; +} + +message FetchDataResponse { + uint32 status = 1; + uint32 response_id = 2; + bool has_more = 3; + repeated ProfilerPluginData plugin_data = 4; +} + +// for StopSession +message StopSessionRequest { + uint32 request_id = 1; + uint32 session_id = 2; +} + +message StopSessionResponse { + uint32 status = 1; + repeated ProfilerPluginState plugin_status = 3; +} + +// for DestroySession +message DestroySessionRequest { + uint32 request_id = 1; + uint32 session_id = 2; +} + +message DestroySessionResponse { + uint32 status = 1; + repeated ProfilerPluginState plugin_status = 3; +} + +// for KeepSession +message KeepSessionRequest { + uint32 request_id = 1; + uint32 session_id = 2; + uint32 keep_alive_time = 3; +} + +message KeepSessionResponse { + uint32 status = 1; +} diff --git a/host/trace_streamer/src/protos/types/plugins/agent_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/agent_data/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..1d2b050538813a5b49d8f502bdb15762aeb64ba0 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/agent_data/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../protos.gni") + +agent_sources = [ + "./agent_plugin_app_data.proto", + "./agent_plugin_config.proto", + "./agent_plugin_energy_data.proto", + "./agent_plugin_java_heap.proto", + "./agent_plugin_network_data.proto", + "./agent_plugin_result.proto", +] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) + +agent_data_codegen = [] +foreach(proto, agent_sources) { + name = get_path_info(proto, "name") + agent_data_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] +} + +config("agent_include_config") { + include_dirs = [ "$proto_out_dir" ] +} + +####################################################### +action("agent_data_cpp_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = agent_sources + outputs = agent_data_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +ohos_source_set("agent_data_cpp") { + deps = [ ":agent_data_cpp_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":agent_include_config" ] + sources = agent_data_codegen +} diff --git a/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_app_data.proto b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_app_data.proto new file mode 100644 index 0000000000000000000000000000000000000000..5ae99f08e7d6c56e36e6ffb53b898cd8ed41c397 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_app_data.proto @@ -0,0 +1,68 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message AbilityStateInfo { + enum AbilityState { + UNSPECIFIED = 0; + START = 1; + INACTIVE = 2; + ACTIVE = 3; + BACKGROUND = 4; + FOREGROUND = 5; + STOP = 6; + } + int32 life_cycle_id = 1; + string ability_name = 2; + AbilityState state = 3; +} + +message KeyEvent { + int32 key_type = 1; + bool is_down = 2; +} + +message TouchEvent { + int32 touch_type = 1; +} + +message MouseEvent { + int32 action_type = 1; + int32 action_button = 2; +} + +message RotationEvent { + float value = 1; +} + +message AgentAbilityEvent { + // timestamp obtained by CLOCK_REALTIME + uint64 tv_sec = 1; + uint64 tv_nsec = 2; + + oneof event { + AbilityStateInfo ability_state = 3; + KeyEvent key_event = 4; + TouchEvent touch_event = 5; + MouseEvent mouse_event = 6; + RotationEvent rotation_event = 7; + } +} + +message BatchAgentAbilityEvent { + repeated AgentAbilityEvent events = 1; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..470d9461c87fef829dffe3eb1e828a5b7663901e --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_config.proto @@ -0,0 +1,23 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + + +message AgentConfig { + int32 pid = 1; + int32 stack_depth = 2; +} diff --git a/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_energy_data.proto b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_energy_data.proto new file mode 100644 index 0000000000000000000000000000000000000000..575dcfff62d80a94e58a8b6a99a949584ad27149 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_energy_data.proto @@ -0,0 +1,201 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message RunningLockBegin { + enum Type { + UNSPECIFIED = 0; + BACKGROUND = 1; + PROXIMITY_SCREEN_CONTROL = 2; + } + + int32 lock_id = 1; // 锁ID + Type type = 2; // 唤醒锁的类型 + string name = 3; // 唤醒锁名称 +} + +message RunningLockEnd { + int32 lock_id = 1; // 锁ID +} + +message PendingIntent { + string creator_package = 1; // 创建此PendingIntent的应用程序的程序包名称 + int32 creator_uid = 2; // 应用程序UID +} + +enum TimerType { + UNSPECIFIED = 0; + TIMER_TYPE_REALTIME = 1; + TIMER_TYPE_WAKEUP = 2; + TIMER_TYPE_EXACT = 4; + TIMER_TYPE_IDLE = 8; +} + +message OneShotStart { + PendingIntent intent = 1; + int64 oneshot_id = 2; + TimerType type = 3; + int64 triggertime_ns = 4; +} + +message RepeatStart { + PendingIntent intent = 1; + int64 repeat_id = 2; + TimerType type = 3; + int64 triggertime_ns = 4; + int64 interval_ns = 5; +} + +message TimerStop { + int64 stop_id = 1; +} + +message LocationRequest { + enum Priority { + UNSPECIFIED = 0; + PRIORITY_UNSET = 512; + PRIORITY_ACCURACY = 513; + PRIORITY_LOW_POWER = 514; + PRIORITY_FAST_FIRST_FIX = 515; + } + string provider = 1; // 提供位置的程序名称。通过LocationManager设置,则可以是“gps”、“network”、“passive”或空。通过FusedLocationProviderClient设置,则是“fused”。 + int64 interval_ms = 2; // 位置请求所需的间隔时间(ms),间隔时间越短越耗电 + int64 fastest_interval_ms = 3; // 位置请求的最快间隔时间(ms) + Priority priority = 4; // 位置请求精确度,精确度越高越耗电 +} + +message LocationUpdateRequested { + PendingIntent intent = 1; // 要为每个位置更新发送的挂起内容的元数据 + int32 location_id = 2; // 位置ID + LocationRequest request = 3; // 位置更新请求 +} + +message LocationReport { + int32 location_id = 1; // 位置ID + float accuracy_of_metre = 2; // 该位置的估计水平精度,径向,单位为米。 +} + +message LocationUpdateRemoved { + int32 location_id = 1; // 位置ID +} + +message WorkInfo { + enum BatteryLevel { + BATTERY_LEVEL_LOW = 0; + BATTERY_LEVEL_OKAY = 1; + BATTERY_LEVEL_LOW_OR_OKAY = 2; + } + enum ChargeType { + CHARGING_PLUGGED_ANY = 0; + CHARGING_PLUGGED_AC = 1; + CHARGING_PLUGGED_USB = 2; + CHARGING_PLUGGED_WIRELESS = 3; + } + enum NetworkType { + NETWORK_TYPE_ANY = 0; + NETWORK_TYPE_MOBILE = 1; + NETWORK_TYPE_WIFI = 2; + NETWORK_TYPE_BLUETOOTH = 3; + NETWORK_TYPE_WIFI_P2P = 4; + NETWORK_TYPE_ETHERNET = 5; + } + enum StorageType { + STORAGE_LEVEL_LOW = 0; + STORAGE_LEVEL_OKAY = 1; + STORAGE_LEVEL_LOW_OR_OKAY = 2; + } + + string ability_name = 1; // 运行作业的页面名称 + string bundle_name = 2; // 运行作业的程序名称 + int32 repeat_counter = 3; // 重复作业次数 + int64 repeat_cycle_time = 4; // 定期作业重复的间隔时间 + BatteryLevel battery_level = 5; // 作业设备的电池等级 + int32 battery_status = 6; // 作业设备的电池状态 + ChargeType charge_type = 7; // 作业设备的充电类型 + int32 wait_time = 8; // 非定期作业的延迟时间 + NetworkType network_type = 9; // 作业运行的网络类型 + StorageType storage_type = 10; // 作业设备的存储类型 + bool is_request_battery = 11; // 作业是否需要设备的电池电量不低于临界阈值 + bool is_request_charging = 12; // 作业是否需要充电 + bool is_request_deep_idle = 13; // 作业是否需要设备处于空闲维护窗口中 + bool is_request_delay = 14; // 作业是否需要延迟 + bool is_request_network = 15; // 作业是否需要网络 + bool is_request_persisted = 16; // 是否应跨设备重新引导持久化此作业 + bool is_request_repeat = 17; // 是否在给定时间内重复作业 + bool is_request_storage = 18; // 作业是否需要设备的存储空间不低 + bool is_work_info_valid = 19; // 作业是否有效 +} + +message WorkStart { + int64 work_id = 1; + WorkInfo work_info = 2; + bool start_now = 3; + bool is_start = 4; +} + +message WorkCancel { + int64 work_id = 1; + bool is_cancel = 2; +} + +message WorkStop { + int64 work_id = 1; + bool is_stop = 2; +} + +message BackgroundWork { + int64 work_id = 1; + int32 actual_delay_time = 2; + int32 request_id = 3; + string reason = 4; +} + +message OnStartWork { + int64 work_id = 1; + WorkInfo work_info = 2; +} + +message OnStopWork { + int64 work_id = 1; +} + +message AgentEnergyEvent { + // timestamp obtained by CLOCK_REALTIME + uint64 tv_sec = 1; + uint64 tv_nsec = 2; + string callstack = 3; // 生成此事件的调用堆栈 + oneof data { + RunningLockBegin runlock_begin = 4; // 获取唤醒锁(强制设备保持唤醒) + RunningLockEnd runlock_end = 5; // 释放唤醒锁 + OneShotStart oneshot_start = 6; // 闹钟 + RepeatStart repeat_start = 7; // 需要重复的闹钟 + TimerStop timer_stop = 8; + LocationUpdateRequested location_update_requested = 9; // 位置更新请求 + LocationReport location_report = 10; + LocationUpdateRemoved location_update_removed = 11; // 位置更新请求已删除 + WorkStart work_start = 12; + WorkCancel work_cancel = 13; + WorkStop work_stop = 14; + BackgroundWork back_work = 15; + OnStartWork on_start = 16; // 启动承载work的服务 + OnStopWork on_stop = 17; // 停止承载work的服务 + } +} + +message BatchAgentEnergyEvent { + repeated AgentEnergyEvent events = 1; +} diff --git a/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_java_heap.proto b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_java_heap.proto new file mode 100644 index 0000000000000000000000000000000000000000..7b8930931acfcf27b02a64dcb15dd23670c1eb7e --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_java_heap.proto @@ -0,0 +1,62 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +// Java heap memory event from jvmti interface. +message ClassInfo { + int32 class_id = 1; + string class_name = 2; +} + +message AllocationInfo { + int32 object_id = 1; + int32 class_id = 2; + int32 object_size = 3; + int32 array_length = 4; + int32 heap_id = 5; + string thread_name = 6; + + message StackFrameInfo { + int32 frame_id = 1; + string class_name = 2; + string method_name = 3; + string file_name = 4; + int32 line_number = 5; + } + // First element means stack top. + repeated StackFrameInfo frame_info = 7; +} + +message DeallocationInfo { + int32 object_id = 1; +} + +message AgentMemoryEvent { + // timestamp obtained by CLOCK_REALTIME + uint64 tv_sec = 1; + uint64 tv_nsec = 2; + + oneof event { + ClassInfo class_data = 3; + AllocationInfo alloc_data = 4; + DeallocationInfo free_data = 5; + } +} + +message BatchAgentMemoryEvent { + repeated AgentMemoryEvent events = 1; +} diff --git a/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_network_data.proto b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_network_data.proto new file mode 100644 index 0000000000000000000000000000000000000000..918af6320a8c3b796c6343981fd2d5630d357c24 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_network_data.proto @@ -0,0 +1,64 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message HttpRequestHead { + string url = 1; + string method = 2; + string fields = 3; + string trace = 4; +} + +message HttpResponseHead { + string fields = 1; +} + +message HttpBody { + string payload_id = 1; + int32 payload_size = 2; + bytes payload_fields = 3; +} + +message HttpEndStatus { + bool aborted = 1; +} + +// thread +message AgentThread { + int64 id = 1; + string name = 2; +} + +message AgentNetworkEvent { + // timestamp obtained by CLOCK_REALTIME + uint64 tv_sec = 1; + uint64 tv_nsec = 2; + int64 event_id = 3; + + oneof event { + HttpRequestHead request_head = 4; + HttpResponseHead response_head = 5; + HttpBody request_body = 6; + HttpBody response_body = 7; + HttpEndStatus end_status = 8; + AgentThread agent_thread = 9; + } +} + +message BatchAgentNetworkEvent { + repeated AgentNetworkEvent events = 1; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_result.proto new file mode 100644 index 0000000000000000000000000000000000000000..ad9a3704af99363009136628db1a735ccdd40af6 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_result.proto @@ -0,0 +1,31 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +import "agent_plugin_java_heap.proto"; +import "agent_plugin_app_data.proto"; +import "agent_plugin_network_data.proto"; +import "agent_plugin_energy_data.proto"; + +message AgentData { + oneof data { + BatchAgentMemoryEvent javaheap_data = 1; + BatchAgentAbilityEvent app_data = 2; + BatchAgentNetworkEvent network_data = 3; + BatchAgentEnergyEvent energy_data = 4; + } +} diff --git a/host/trace_streamer/src/protos/types/plugins/bytrace_plugin/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/bytrace_plugin/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..c2f3dc33dda605ba631455c1b6d94f94bf6901ce --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/bytrace_plugin/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../protos.gni") + +bytrace_plugin_protos_defines = [ "./bytrace_plugin_config.proto" ] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) +print("proto_out_dir", proto_out_dir, proto_rel_out_dir) + +####################################################### +bytrace_plugin_protos_codegen = [] +foreach(proto, bytrace_plugin_protos_defines) { + name = get_path_info(proto, "name") + bytrace_plugin_protos_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] +} + +action("bytrace_plugin_protos_protoc") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = bytrace_plugin_protos_defines + outputs = bytrace_plugin_protos_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +config("bytrace_plugin_protos_config") { + include_dirs = [ "$proto_out_dir" ] +} + +ohos_source_set("bytrace_plugin_protos_cpp") { + deps = [ ":bytrace_plugin_protos_protoc" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":bytrace_plugin_protos_config" ] + sources = bytrace_plugin_protos_codegen +} diff --git a/host/trace_streamer/src/protos/types/plugins/bytrace_plugin/bytrace_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/bytrace_plugin/bytrace_plugin_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..8c26822268288ae9adca92f98e862583e0f141f5 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/bytrace_plugin/bytrace_plugin_config.proto @@ -0,0 +1,24 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; +option optimize_for = LITE_RUNTIME; + +message BytracePluginConfig { + uint32 buffe_size = 1; // Sets the size of the buffer (KB) for storing and reading traces. + repeated string categories = 2; // Lists available bytrace categories. + uint32 time = 3; // Sets the bytrace running duration in seconds (5s by default) + string clock = 4; // Sets the clock, which can be boot (default), global, mono, uptime, or perf. + string outfile_name = 5; // Sets the name of the target file (stdout by default). + bool is_root = 6; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/cpu_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/cpu_data/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..b881f9da5ea32e1ba4187658a91745c1bee44260 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/cpu_data/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../protos.gni") + +cpu_data_sources = [ + "./cpu_plugin_config.proto", + "./cpu_plugin_result.proto", +] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) + +cpu_data_codegen = [] +foreach(proto, cpu_data_sources) { + name = get_path_info(proto, "name") + cpu_data_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] +} + +config("cpu_include_config") { + include_dirs = [ "$proto_out_dir" ] +} + +####################################################### +action("cpu_data_cpp_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = cpu_data_sources + outputs = cpu_data_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +ohos_source_set("cpu_data_cpp") { + deps = [ ":cpu_data_cpp_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":cpu_include_config" ] + sources = cpu_data_codegen +} diff --git a/host/trace_streamer/src/protos/types/plugins/cpu_data/cpu_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/cpu_data/cpu_plugin_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..f3a730c9846020f333726a3630bf8d16151ebe6c --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/cpu_data/cpu_plugin_config.proto @@ -0,0 +1,23 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + + +// Cpu plug-in configuration, passed to plug-in by plug-in service. +message CpuConfig { + int32 pid = 1; +} diff --git a/host/trace_streamer/src/protos/types/plugins/cpu_data/cpu_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/cpu_data/cpu_plugin_result.proto new file mode 100644 index 0000000000000000000000000000000000000000..7b18965564cf2ffdf738b9f346fe16d1a3080175 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/cpu_data/cpu_plugin_result.proto @@ -0,0 +1,71 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message SampleTimeStamp { + uint64 tv_sec = 1; + uint64 tv_nsec = 2; +} + +message CpuCoreFrequency { + int32 min_frequency_khz = 1; + int32 max_frequency_khz = 2; + int32 cur_frequency_khz = 3; +} + +message CpuCoreUsageInfo { + int32 cpu_core = 1; + int64 prev_system_cpu_time_ms = 2; + int64 prev_system_boot_time_ms = 3; + int64 system_cpu_time_ms = 4; + int64 system_boot_time_ms = 5; + CpuCoreFrequency frequency = 6; + bool is_little_core = 7; +} + +message CpuUsageInfo { + int64 prev_process_cpu_time_ms = 1; + int64 prev_system_cpu_time_ms = 2; + int64 prev_system_boot_time_ms = 3; + int64 process_cpu_time_ms = 4; + int64 system_cpu_time_ms = 5; + int64 system_boot_time_ms = 6; + repeated CpuCoreUsageInfo cores = 7; + SampleTimeStamp timestamp = 8; +} + +enum ThreadState { + THREAD_UNSPECIFIED = 0; + THREAD_RUNNING = 1; + THREAD_SLEEPING = 2; + THREAD_STOPPED = 3; + THREAD_WAITING = 4; +} + +message ThreadInfo { + int32 tid = 1; + string thread_name = 2; + ThreadState thread_state = 3; + int64 prev_thread_cpu_time_ms = 4; + int64 thread_cpu_time_ms = 5; + SampleTimeStamp timestamp = 6; +} + +message CpuData { + CpuUsageInfo cpu_usage_info = 1; + repeated ThreadInfo thread_info = 2; +} diff --git a/host/trace_streamer/src/protos/types/plugins/diskio_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/diskio_data/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..401a8d7fc1a09bd987b8b8993d45f223da437417 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/diskio_data/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../protos.gni") + +diskio_data_sources = [ + "./diskio_plugin_config.proto", + "./diskio_plugin_result.proto", +] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) + +diskio_data_codegen = [] +foreach(proto, diskio_data_sources) { + name = get_path_info(proto, "name") + diskio_data_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] +} + +config("diskio_include_config") { + include_dirs = [ "$proto_out_dir" ] +} + +####################################################### +action("diskio_data_cpp_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = diskio_data_sources + outputs = diskio_data_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +ohos_source_set("diskio_data_cpp") { + deps = [ ":diskio_data_cpp_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":diskio_include_config" ] + sources = diskio_data_codegen +} diff --git a/host/trace_streamer/src/protos/types/plugins/diskio_data/diskio_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/diskio_data/diskio_plugin_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..4e69f0d051c0268bcd0f6d161701bf214e0e5225 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/diskio_data/diskio_plugin_config.proto @@ -0,0 +1,23 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + + +// Diskio plug-in configuration, passed to plug-in by plug-in service. +message DiskioConfig { + int32 unspeci_fied = 1; // Reserved field, not used +} diff --git a/host/trace_streamer/src/protos/types/plugins/diskio_data/diskio_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/diskio_data/diskio_plugin_result.proto new file mode 100644 index 0000000000000000000000000000000000000000..742e9a64ffc2f828331fd557fc26cc058df0f038 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/diskio_data/diskio_plugin_result.proto @@ -0,0 +1,31 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message CollectTimeStamp { + uint64 tv_sec = 1; + uint64 tv_nsec = 2; +} + +message DiskioData { + int64 prev_rd_sectors_kb = 1; + int64 prev_wr_sectors_kb = 2; + CollectTimeStamp prev_timestamp = 3; + int64 rd_sectors_kb = 4; + int64 wr_sectors_kb = 5; + CollectTimeStamp timestamp = 6; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/ftrace_data/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..2dd0861009d0c04b6f591b77cf5b5f732edd468d --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../protos.gni") +import("autogenerated.gni") + +ftrace_data_sources = auto_generated_ftrace_proto_sources + [ + "trace_plugin_config.proto", + "trace_plugin_result.proto", + ] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) + +ftrace_data_codegen = [] +foreach(proto, ftrace_data_sources) { + dir = get_path_info(proto, "dir") + name = get_path_info(proto, "name") + ftrace_data_codegen += [ + "$proto_out_dir/$dir/$name.pb.h", + "$proto_out_dir/$dir/$name.pb.cc", + ] +} + +config("ftrace_data_include_config") { + include_dirs = [ "$proto_out_dir" ] +} + +####################################################### +action("ftrace_data_cpp_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = ftrace_data_sources + outputs = ftrace_data_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +ohos_source_set("ftrace_data_cpp") { + deps = [ ":ftrace_data_cpp_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":ftrace_data_include_config" ] + sources = ftrace_data_codegen +} diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/autogenerated.gni b/host/trace_streamer/src/protos/types/plugins/ftrace_data/autogenerated.gni new file mode 100644 index 0000000000000000000000000000000000000000..fcae596874f54b553a799e96b3f2022460405093 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/autogenerated.gni @@ -0,0 +1,48 @@ +# THIS FILE IS GENERATE BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +auto_generated_ftrace_proto_sources = [ + "binder.proto", + "block.proto", + "cgroup.proto", + "clk.proto", + "compaction.proto", + "cpuhp.proto", + "dma_fence.proto", + "ext4.proto", + "filelock.proto", + "filemap.proto", + "ftrace.proto", + "ftrace_event.proto", + "gpio.proto", + "i2c.proto", + "ipi.proto", + "irq.proto", + "kmem.proto", + "net.proto", + "oom.proto", + "pagemap.proto", + "power.proto", + "printk.proto", + "raw_syscalls.proto", + "rcu.proto", + "sched.proto", + "signal.proto", + "sunrpc.proto", + "task.proto", + "timer.proto", + "v4l2.proto", + "vmscan.proto", + "workqueue.proto", + "writeback.proto", +] diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/binder.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/binder.proto new file mode 100644 index 0000000000000000000000000000000000000000..f1d0acd59d8986e9b5606fa3684bdebc76057726 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/binder.proto @@ -0,0 +1,216 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: binder +// /sys/kernel/debug/tracing/events/binder/binder_alloc_lru_end/format +message BinderAllocLruEndFormat { + int32 proc = 1; + uint64 page_index = 2; +} + +// /sys/kernel/debug/tracing/events/binder/binder_alloc_lru_start/format +message BinderAllocLruStartFormat { + int32 proc = 1; + uint64 page_index = 2; +} + +// /sys/kernel/debug/tracing/events/binder/binder_alloc_page_end/format +message BinderAllocPageEndFormat { + int32 proc = 1; + uint64 page_index = 2; +} + +// /sys/kernel/debug/tracing/events/binder/binder_alloc_page_start/format +message BinderAllocPageStartFormat { + int32 proc = 1; + uint64 page_index = 2; +} + +// /sys/kernel/debug/tracing/events/binder/binder_command/format +message BinderCommandFormat { + uint32 cmd = 1; +} + +// /sys/kernel/debug/tracing/events/binder/binder_free_lru_end/format +message BinderFreeLruEndFormat { + int32 proc = 1; + uint64 page_index = 2; +} + +// /sys/kernel/debug/tracing/events/binder/binder_free_lru_start/format +message BinderFreeLruStartFormat { + int32 proc = 1; + uint64 page_index = 2; +} + +// /sys/kernel/debug/tracing/events/binder/binder_ioctl/format +message BinderIoctlFormat { + uint32 cmd = 1; + uint64 arg = 2; +} + +// /sys/kernel/debug/tracing/events/binder/binder_ioctl_done/format +message BinderIoctlDoneFormat { + int32 ret = 1; +} + +// /sys/kernel/debug/tracing/events/binder/binder_lock/format +message BinderLockFormat { + string tag = 1; +} + +// /sys/kernel/debug/tracing/events/binder/binder_locked/format +message BinderLockedFormat { + string tag = 1; +} + +// /sys/kernel/debug/tracing/events/binder/binder_read_done/format +message BinderReadDoneFormat { + int32 ret = 1; +} + +// /sys/kernel/debug/tracing/events/binder/binder_return/format +message BinderReturnFormat { + uint32 cmd = 1; +} + +// /sys/kernel/debug/tracing/events/binder/binder_transaction/format +message BinderTransactionFormat { + int32 debug_id = 1; + int32 target_node = 2; + int32 to_proc = 3; + int32 to_thread = 4; + int32 reply = 5; + uint32 code = 6; + uint32 flags = 7; +} + +// /sys/kernel/debug/tracing/events/binder/binder_transaction_alloc_buf/format +message BinderTransactionAllocBufFormat { + int32 debug_id = 1; + uint64 data_size = 2; + uint64 offsets_size = 3; + uint64 extra_buffers_size = 4; +} + +// /sys/kernel/debug/tracing/events/binder/binder_transaction_buffer_release/format +message BinderTransactionBufferReleaseFormat { + int32 debug_id = 1; + uint64 data_size = 2; + uint64 offsets_size = 3; + uint64 extra_buffers_size = 4; +} + +// /sys/kernel/debug/tracing/events/binder/binder_transaction_failed_buffer_release/format +message BinderTransactionFailedBufferReleaseFormat { + int32 debug_id = 1; + uint64 data_size = 2; + uint64 offsets_size = 3; + uint64 extra_buffers_size = 4; +} + +// /sys/kernel/debug/tracing/events/binder/binder_transaction_fd/format +message BinderTransactionFdFormat { + int32 debug_id = 1; + int32 src_fd = 2; + int32 dest_fd = 3; +} + +// /sys/kernel/debug/tracing/events/binder/binder_transaction_node_to_ref/format +message BinderTransactionNodeToRefFormat { + int32 debug_id = 1; + int32 node_debug_id = 2; + uint64 node_ptr = 3; + int32 ref_debug_id = 4; + uint32 ref_desc = 5; +} + +// /sys/kernel/debug/tracing/events/binder/binder_transaction_received/format +message BinderTransactionReceivedFormat { + int32 debug_id = 1; +} + +// /sys/kernel/debug/tracing/events/binder/binder_transaction_ref_to_node/format +message BinderTransactionRefToNodeFormat { + int32 debug_id = 1; + int32 ref_debug_id = 2; + uint32 ref_desc = 3; + int32 node_debug_id = 4; + uint64 node_ptr = 5; +} + +// /sys/kernel/debug/tracing/events/binder/binder_transaction_ref_to_ref/format +message BinderTransactionRefToRefFormat { + int32 debug_id = 1; + int32 node_debug_id = 2; + int32 src_ref_debug_id = 3; + uint32 src_ref_desc = 4; + int32 dest_ref_debug_id = 5; + uint32 dest_ref_desc = 6; +} + +// /sys/kernel/debug/tracing/events/binder/binder_unlock/format +message BinderUnlockFormat { + string tag = 1; +} + +// /sys/kernel/debug/tracing/events/binder/binder_unmap_kernel_end/format +message BinderUnmapKernelEndFormat { + int32 proc = 1; + uint64 page_index = 2; +} + +// /sys/kernel/debug/tracing/events/binder/binder_unmap_kernel_start/format +message BinderUnmapKernelStartFormat { + int32 proc = 1; + uint64 page_index = 2; +} + +// /sys/kernel/debug/tracing/events/binder/binder_unmap_user_end/format +message BinderUnmapUserEndFormat { + int32 proc = 1; + uint64 page_index = 2; +} + +// /sys/kernel/debug/tracing/events/binder/binder_unmap_user_start/format +message BinderUnmapUserStartFormat { + int32 proc = 1; + uint64 page_index = 2; +} + +// /sys/kernel/debug/tracing/events/binder/binder_update_page_range/format +message BinderUpdatePageRangeFormat { + int32 proc = 1; + uint32 allocate = 2; + uint64 offset = 3; + uint64 size = 4; +} + +// /sys/kernel/debug/tracing/events/binder/binder_wait_for_work/format +message BinderWaitForWorkFormat { + uint32 proc_work = 1; + uint32 transaction_stack = 2; + uint32 thread_todo = 3; +} + +// /sys/kernel/debug/tracing/events/binder/binder_write_done/format +message BinderWriteDoneFormat { + int32 ret = 1; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/block.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/block.proto new file mode 100644 index 0000000000000000000000000000000000000000..5975c0e3ff1d4a4e6bd2cdd26e9ca4bba2409d1a --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/block.proto @@ -0,0 +1,179 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: block +// /sys/kernel/debug/tracing/events/block/block_bio_backmerge/format +message BlockBioBackmergeFormat { + uint64 dev = 1; + uint64 sector = 2; + uint32 nr_sector = 3; + string rwbs = 4; + string comm = 5; +} + +// /sys/kernel/debug/tracing/events/block/block_bio_bounce/format +message BlockBioBounceFormat { + uint64 dev = 1; + uint64 sector = 2; + uint32 nr_sector = 3; + string rwbs = 4; + string comm = 5; +} + +// /sys/kernel/debug/tracing/events/block/block_bio_complete/format +message BlockBioCompleteFormat { + uint64 dev = 1; + uint64 sector = 2; + uint32 nr_sector = 3; + int32 error = 4; + string rwbs = 5; +} + +// /sys/kernel/debug/tracing/events/block/block_bio_frontmerge/format +message BlockBioFrontmergeFormat { + uint64 dev = 1; + uint64 sector = 2; + uint32 nr_sector = 3; + string rwbs = 4; + string comm = 5; +} + +// /sys/kernel/debug/tracing/events/block/block_bio_queue/format +message BlockBioQueueFormat { + uint64 dev = 1; + uint64 sector = 2; + uint32 nr_sector = 3; + string rwbs = 4; + string comm = 5; +} + +// /sys/kernel/debug/tracing/events/block/block_bio_remap/format +message BlockBioRemapFormat { + uint64 dev = 1; + uint64 sector = 2; + uint32 nr_sector = 3; + uint64 old_dev = 4; + uint64 old_sector = 5; + string rwbs = 6; +} + +// /sys/kernel/debug/tracing/events/block/block_dirty_buffer/format +message BlockDirtyBufferFormat { + uint64 dev = 1; + uint64 sector = 2; + uint64 size = 3; +} + +// /sys/kernel/debug/tracing/events/block/block_getrq/format +message BlockGetrqFormat { + uint64 dev = 1; + uint64 sector = 2; + uint32 nr_sector = 3; + string rwbs = 4; + string comm = 5; +} + +// /sys/kernel/debug/tracing/events/block/block_plug/format +message BlockPlugFormat { + string comm = 1; +} + +// /sys/kernel/debug/tracing/events/block/block_rq_complete/format +message BlockRqCompleteFormat { + uint64 dev = 1; + uint64 sector = 2; + uint32 nr_sector = 3; + int32 error = 4; + string rwbs = 5; + string cmd = 6; +} + +// /sys/kernel/debug/tracing/events/block/block_rq_insert/format +message BlockRqInsertFormat { + uint64 dev = 1; + uint64 sector = 2; + uint32 nr_sector = 3; + uint32 bytes = 4; + string rwbs = 5; + string comm = 6; + string cmd = 7; +} + +// /sys/kernel/debug/tracing/events/block/block_rq_issue/format +message BlockRqIssueFormat { + uint64 dev = 1; + uint64 sector = 2; + uint32 nr_sector = 3; + uint32 bytes = 4; + string rwbs = 5; + string comm = 6; + string cmd = 7; +} + +// /sys/kernel/debug/tracing/events/block/block_rq_remap/format +message BlockRqRemapFormat { + uint64 dev = 1; + uint64 sector = 2; + uint32 nr_sector = 3; + uint64 old_dev = 4; + uint64 old_sector = 5; + uint32 nr_bios = 6; + string rwbs = 7; +} + +// /sys/kernel/debug/tracing/events/block/block_rq_requeue/format +message BlockRqRequeueFormat { + uint64 dev = 1; + uint64 sector = 2; + uint32 nr_sector = 3; + string rwbs = 4; + string cmd = 5; +} + +// /sys/kernel/debug/tracing/events/block/block_sleeprq/format +message BlockSleeprqFormat { + uint64 dev = 1; + uint64 sector = 2; + uint32 nr_sector = 3; + string rwbs = 4; + string comm = 5; +} + +// /sys/kernel/debug/tracing/events/block/block_split/format +message BlockSplitFormat { + uint64 dev = 1; + uint64 sector = 2; + uint64 new_sector = 3; + string rwbs = 4; + string comm = 5; +} + +// /sys/kernel/debug/tracing/events/block/block_touch_buffer/format +message BlockTouchBufferFormat { + uint64 dev = 1; + uint64 sector = 2; + uint64 size = 3; +} + +// /sys/kernel/debug/tracing/events/block/block_unplug/format +message BlockUnplugFormat { + int32 nr_rq = 1; + string comm = 2; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/cgroup.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/cgroup.proto new file mode 100644 index 0000000000000000000000000000000000000000..22544329885160245b94d20d0d8a6e1d51877328 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/cgroup.proto @@ -0,0 +1,93 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: cgroup +// /sys/kernel/debug/tracing/events/cgroup/cgroup_attach_task/format +message CgroupAttachTaskFormat { + int32 dst_root = 1; + int32 dst_id = 2; + int32 dst_level = 3; + int32 pid = 4; + string dst_path = 5; + string comm = 6; +} + +// /sys/kernel/debug/tracing/events/cgroup/cgroup_destroy_root/format +message CgroupDestroyRootFormat { + int32 root = 1; + uint32 ss_mask = 2; + string name = 3; +} + +// /sys/kernel/debug/tracing/events/cgroup/cgroup_mkdir/format +message CgroupMkdirFormat { + int32 root = 1; + int32 id = 2; + int32 level = 3; + string path = 4; +} + +// /sys/kernel/debug/tracing/events/cgroup/cgroup_release/format +message CgroupReleaseFormat { + int32 root = 1; + int32 id = 2; + int32 level = 3; + string path = 4; +} + +// /sys/kernel/debug/tracing/events/cgroup/cgroup_remount/format +message CgroupRemountFormat { + int32 root = 1; + uint32 ss_mask = 2; + string name = 3; +} + +// /sys/kernel/debug/tracing/events/cgroup/cgroup_rename/format +message CgroupRenameFormat { + int32 root = 1; + int32 id = 2; + int32 level = 3; + string path = 4; +} + +// /sys/kernel/debug/tracing/events/cgroup/cgroup_rmdir/format +message CgroupRmdirFormat { + int32 root = 1; + int32 id = 2; + int32 level = 3; + string path = 4; +} + +// /sys/kernel/debug/tracing/events/cgroup/cgroup_setup_root/format +message CgroupSetupRootFormat { + int32 root = 1; + uint32 ss_mask = 2; + string name = 3; +} + +// /sys/kernel/debug/tracing/events/cgroup/cgroup_transfer_tasks/format +message CgroupTransferTasksFormat { + int32 dst_root = 1; + int32 dst_id = 2; + int32 dst_level = 3; + int32 pid = 4; + string dst_path = 5; + string comm = 6; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/clk.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/clk.proto new file mode 100644 index 0000000000000000000000000000000000000000..0f74b25fb2eef0935707786bcf3402d169dd55f8 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/clk.proto @@ -0,0 +1,96 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: clk +// /sys/kernel/debug/tracing/events/clk/clk_disable/format +message ClkDisableFormat { + string name = 1; +} + +// /sys/kernel/debug/tracing/events/clk/clk_disable_complete/format +message ClkDisableCompleteFormat { + string name = 1; +} + +// /sys/kernel/debug/tracing/events/clk/clk_enable/format +message ClkEnableFormat { + string name = 1; +} + +// /sys/kernel/debug/tracing/events/clk/clk_enable_complete/format +message ClkEnableCompleteFormat { + string name = 1; +} + +// /sys/kernel/debug/tracing/events/clk/clk_prepare/format +message ClkPrepareFormat { + string name = 1; +} + +// /sys/kernel/debug/tracing/events/clk/clk_prepare_complete/format +message ClkPrepareCompleteFormat { + string name = 1; +} + +// /sys/kernel/debug/tracing/events/clk/clk_set_parent/format +message ClkSetParentFormat { + string name = 1; + string pname = 2; +} + +// /sys/kernel/debug/tracing/events/clk/clk_set_parent_complete/format +message ClkSetParentCompleteFormat { + string name = 1; + string pname = 2; +} + +// /sys/kernel/debug/tracing/events/clk/clk_set_phase/format +message ClkSetPhaseFormat { + string name = 1; + int32 phase = 2; +} + +// /sys/kernel/debug/tracing/events/clk/clk_set_phase_complete/format +message ClkSetPhaseCompleteFormat { + string name = 1; + int32 phase = 2; +} + +// /sys/kernel/debug/tracing/events/clk/clk_set_rate/format +message ClkSetRateFormat { + string name = 1; + uint64 rate = 2; +} + +// /sys/kernel/debug/tracing/events/clk/clk_set_rate_complete/format +message ClkSetRateCompleteFormat { + string name = 1; + uint64 rate = 2; +} + +// /sys/kernel/debug/tracing/events/clk/clk_unprepare/format +message ClkUnprepareFormat { + string name = 1; +} + +// /sys/kernel/debug/tracing/events/clk/clk_unprepare_complete/format +message ClkUnprepareCompleteFormat { + string name = 1; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/compaction.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/compaction.proto new file mode 100644 index 0000000000000000000000000000000000000000..2df331f2893674fb8d8d65163e25a9efba26e3e2 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/compaction.proto @@ -0,0 +1,114 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: compaction +// /sys/kernel/debug/tracing/events/compaction/mm_compaction_begin/format +message MmCompactionBeginFormat { + uint64 zone_start = 1; + uint64 migrate_pfn = 2; + uint64 free_pfn = 3; + uint64 zone_end = 4; + uint32 sync = 5; +} + +// /sys/kernel/debug/tracing/events/compaction/mm_compaction_defer_compaction/format +message MmCompactionDeferCompactionFormat { + int32 nid = 1; + uint32 idx = 2; + int32 order = 3; + uint32 considered = 4; + uint32 defer_shift = 5; + int32 order_failed = 6; +} + +// /sys/kernel/debug/tracing/events/compaction/mm_compaction_defer_reset/format +message MmCompactionDeferResetFormat { + int32 nid = 1; + uint32 idx = 2; + int32 order = 3; + uint32 considered = 4; + uint32 defer_shift = 5; + int32 order_failed = 6; +} + +// /sys/kernel/debug/tracing/events/compaction/mm_compaction_deferred/format +message MmCompactionDeferredFormat { + int32 nid = 1; + uint32 idx = 2; + int32 order = 3; + uint32 considered = 4; + uint32 defer_shift = 5; + int32 order_failed = 6; +} + +// /sys/kernel/debug/tracing/events/compaction/mm_compaction_end/format +message MmCompactionEndFormat { + uint64 zone_start = 1; + uint64 migrate_pfn = 2; + uint64 free_pfn = 3; + uint64 zone_end = 4; + uint32 sync = 5; + int32 status = 6; +} + +// /sys/kernel/debug/tracing/events/compaction/mm_compaction_finished/format +message MmCompactionFinishedFormat { + int32 nid = 1; + uint32 idx = 2; + int32 order = 3; + int32 ret = 4; +} + +// /sys/kernel/debug/tracing/events/compaction/mm_compaction_isolate_freepages/format +message MmCompactionIsolateFreepagesFormat { + uint64 start_pfn = 1; + uint64 end_pfn = 2; + uint64 nr_scanned = 3; + uint64 nr_taken = 4; +} + +// /sys/kernel/debug/tracing/events/compaction/mm_compaction_isolate_migratepages/format +message MmCompactionIsolateMigratepagesFormat { + uint64 start_pfn = 1; + uint64 end_pfn = 2; + uint64 nr_scanned = 3; + uint64 nr_taken = 4; +} + +// /sys/kernel/debug/tracing/events/compaction/mm_compaction_migratepages/format +message MmCompactionMigratepagesFormat { + uint64 nr_migrated = 1; + uint64 nr_failed = 2; +} + +// /sys/kernel/debug/tracing/events/compaction/mm_compaction_suitable/format +message MmCompactionSuitableFormat { + int32 nid = 1; + uint32 idx = 2; + int32 order = 3; + int32 ret = 4; +} + +// /sys/kernel/debug/tracing/events/compaction/mm_compaction_try_to_compact_pages/format +message MmCompactionTryToCompactPagesFormat { + int32 order = 1; + uint32 gfp_mask = 2; + int32 prio = 3; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/cpuhp.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/cpuhp.proto new file mode 100644 index 0000000000000000000000000000000000000000..db805bc33e41cdc383846b1f81ab9dd358456cc5 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/cpuhp.proto @@ -0,0 +1,44 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: cpuhp +// /sys/kernel/debug/tracing/events/cpuhp/cpuhp_enter/format +message CpuhpEnterFormat { + uint32 cpu = 1; + int32 target = 2; + int32 idx = 3; + uint64 fun = 4; +} + +// /sys/kernel/debug/tracing/events/cpuhp/cpuhp_exit/format +message CpuhpExitFormat { + uint32 cpu = 1; + int32 state = 2; + int32 idx = 3; + int32 ret = 4; +} + +// /sys/kernel/debug/tracing/events/cpuhp/cpuhp_multi_enter/format +message CpuhpMultiEnterFormat { + uint32 cpu = 1; + int32 target = 2; + int32 idx = 3; + uint64 fun = 4; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/dma_fence.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/dma_fence.proto new file mode 100644 index 0000000000000000000000000000000000000000..74b511b8f5be7f6f77db7b9dfd351393dc38c53e --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/dma_fence.proto @@ -0,0 +1,76 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: dma_fence +// /sys/kernel/debug/tracing/events/dma_fence/dma_fence_destroy/format +message DmaFenceDestroyFormat { + string driver = 1; + string timeline = 2; + uint32 context = 3; + uint32 seqno = 4; +} + +// /sys/kernel/debug/tracing/events/dma_fence/dma_fence_emit/format +message DmaFenceEmitFormat { + string driver = 1; + string timeline = 2; + uint32 context = 3; + uint32 seqno = 4; +} + +// /sys/kernel/debug/tracing/events/dma_fence/dma_fence_enable_signal/format +message DmaFenceEnableSignalFormat { + string driver = 1; + string timeline = 2; + uint32 context = 3; + uint32 seqno = 4; +} + +// /sys/kernel/debug/tracing/events/dma_fence/dma_fence_init/format +message DmaFenceInitFormat { + string driver = 1; + string timeline = 2; + uint32 context = 3; + uint32 seqno = 4; +} + +// /sys/kernel/debug/tracing/events/dma_fence/dma_fence_signaled/format +message DmaFenceSignaledFormat { + string driver = 1; + string timeline = 2; + uint32 context = 3; + uint32 seqno = 4; +} + +// /sys/kernel/debug/tracing/events/dma_fence/dma_fence_wait_end/format +message DmaFenceWaitEndFormat { + string driver = 1; + string timeline = 2; + uint32 context = 3; + uint32 seqno = 4; +} + +// /sys/kernel/debug/tracing/events/dma_fence/dma_fence_wait_start/format +message DmaFenceWaitStartFormat { + string driver = 1; + string timeline = 2; + uint32 context = 3; + uint32 seqno = 4; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/ext4.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/ext4.proto new file mode 100644 index 0000000000000000000000000000000000000000..d66f4baaebf2e2bba8ee3428377e76ee502a1e02 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/ext4.proto @@ -0,0 +1,872 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: ext4 +// /sys/kernel/debug/tracing/events/ext4/ext4_alloc_da_blocks/format +message Ext4AllocDaBlocksFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 data_blocks = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_allocate_blocks/format +message Ext4AllocateBlocksFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 block = 3; + uint32 len = 4; + uint32 logical = 5; + uint32 lleft = 6; + uint32 lright = 7; + uint64 goal = 8; + uint64 pleft = 9; + uint64 pright = 10; + uint32 flags = 11; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_allocate_inode/format +message Ext4AllocateInodeFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 dir = 3; + uint32 mode = 4; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_begin_ordered_truncate/format +message Ext4BeginOrderedTruncateFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 new_size = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_collapse_range/format +message Ext4CollapseRangeFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 offset = 3; + uint64 len = 4; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_da_release_space/format +message Ext4DaReleaseSpaceFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 i_blocks = 3; + int32 freed_blocks = 4; + int32 reserved_data_blocks = 5; + uint32 mode = 6; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_da_reserve_space/format +message Ext4DaReserveSpaceFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 i_blocks = 3; + int32 reserved_data_blocks = 4; + uint32 mode = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_da_update_reserve_space/format +message Ext4DaUpdateReserveSpaceFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 i_blocks = 3; + int32 used_blocks = 4; + int32 reserved_data_blocks = 5; + int32 quota_claim = 6; + uint32 mode = 7; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/format +message Ext4DaWriteBeginFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 pos = 3; + uint32 len = 4; + uint32 flags = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/format +message Ext4DaWriteEndFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 pos = 3; + uint32 len = 4; + uint32 copied = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_da_write_pages/format +message Ext4DaWritePagesFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 first_page = 3; + uint64 nr_to_write = 4; + int32 sync_mode = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_da_write_pages_extent/format +message Ext4DaWritePagesExtentFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 lblk = 3; + uint32 len = 4; + uint32 flags = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_direct_IO_enter/format +message Ext4DirectIoEnterFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 pos = 3; + uint64 len = 4; + int32 rw = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_direct_IO_exit/format +message Ext4DirectIoExitFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 pos = 3; + uint64 len = 4; + int32 rw = 5; + int32 ret = 6; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_discard_blocks/format +message Ext4DiscardBlocksFormat { + uint64 dev = 1; + uint64 blk = 2; + uint64 count = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_discard_preallocations/format +message Ext4DiscardPreallocationsFormat { + uint64 dev = 1; + uint64 ino = 2; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_drop_inode/format +message Ext4DropInodeFormat { + uint64 dev = 1; + uint64 ino = 2; + int32 drop = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_es_cache_extent/format +message Ext4EsCacheExtentFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 lblk = 3; + uint32 len = 4; + uint64 pblk = 5; + uint32 status = 6; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_es_find_delayed_extent_range_enter/format +message Ext4EsFindDelayedExtentRangeEnterFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 lblk = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_es_find_delayed_extent_range_exit/format +message Ext4EsFindDelayedExtentRangeExitFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 lblk = 3; + uint32 len = 4; + uint64 pblk = 5; + uint32 status = 6; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_es_insert_extent/format +message Ext4EsInsertExtentFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 lblk = 3; + uint32 len = 4; + uint64 pblk = 5; + uint32 status = 6; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_es_lookup_extent_enter/format +message Ext4EsLookupExtentEnterFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 lblk = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_es_lookup_extent_exit/format +message Ext4EsLookupExtentExitFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 lblk = 3; + uint32 len = 4; + uint64 pblk = 5; + uint32 status = 6; + int32 found = 7; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_es_remove_extent/format +message Ext4EsRemoveExtentFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 lblk = 3; + uint64 len = 4; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_es_shrink/format +message Ext4EsShrinkFormat { + uint64 dev = 1; + int32 nr_shrunk = 2; + uint64 scan_time = 3; + int32 nr_skipped = 4; + int32 retried = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_es_shrink_count/format +message Ext4EsShrinkCountFormat { + uint64 dev = 1; + int32 nr_to_scan = 2; + int32 cache_cnt = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_es_shrink_scan_enter/format +message Ext4EsShrinkScanEnterFormat { + uint64 dev = 1; + int32 nr_to_scan = 2; + int32 cache_cnt = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_es_shrink_scan_exit/format +message Ext4EsShrinkScanExitFormat { + uint64 dev = 1; + int32 nr_shrunk = 2; + int32 cache_cnt = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_evict_inode/format +message Ext4EvictInodeFormat { + uint64 dev = 1; + uint64 ino = 2; + int32 nlink = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ext_convert_to_initialized_enter/format +message Ext4ExtConvertToInitializedEnterFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 m_lblk = 3; + uint32 m_len = 4; + uint32 u_lblk = 5; + uint32 u_len = 6; + uint64 u_pblk = 7; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ext_convert_to_initialized_fastpath/format +message Ext4ExtConvertToInitializedFastpathFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 m_lblk = 3; + uint32 m_len = 4; + uint32 u_lblk = 5; + uint32 u_len = 6; + uint64 u_pblk = 7; + uint32 i_lblk = 8; + uint32 i_len = 9; + uint64 i_pblk = 10; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ext_handle_unwritten_extents/format +message Ext4ExtHandleUnwrittenExtentsFormat { + uint64 dev = 1; + uint64 ino = 2; + int32 flags = 3; + uint32 lblk = 4; + uint64 pblk = 5; + uint32 len = 6; + uint32 allocated = 7; + uint64 newblk = 8; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ext_in_cache/format +message Ext4ExtInCacheFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 lblk = 3; + int32 ret = 4; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ext_load_extent/format +message Ext4ExtLoadExtentFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 pblk = 3; + uint32 lblk = 4; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ext_map_blocks_enter/format +message Ext4ExtMapBlocksEnterFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 lblk = 3; + uint32 len = 4; + uint32 flags = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ext_map_blocks_exit/format +message Ext4ExtMapBlocksExitFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 flags = 3; + uint64 pblk = 4; + uint32 lblk = 5; + uint32 len = 6; + uint32 mflags = 7; + int32 ret = 8; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ext_put_in_cache/format +message Ext4ExtPutInCacheFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 lblk = 3; + uint32 len = 4; + uint64 start = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ext_remove_space/format +message Ext4ExtRemoveSpaceFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 start = 3; + uint32 end = 4; + int32 depth = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ext_remove_space_done/format +message Ext4ExtRemoveSpaceDoneFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 start = 3; + uint32 end = 4; + int32 depth = 5; + uint64 partial = 6; + uint32 eh_entries = 7; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ext_rm_idx/format +message Ext4ExtRmIdxFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 pblk = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ext_rm_leaf/format +message Ext4ExtRmLeafFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 partial = 3; + uint32 start = 4; + uint32 ee_lblk = 5; + uint64 ee_pblk = 6; + int32 ee_len = 7; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ext_show_extent/format +message Ext4ExtShowExtentFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 pblk = 3; + uint32 lblk = 4; + uint32 len = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_fallocate_enter/format +message Ext4FallocateEnterFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 offset = 3; + uint64 len = 4; + int32 mode = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_fallocate_exit/format +message Ext4FallocateExitFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 pos = 3; + uint32 blocks = 4; + int32 ret = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_find_delalloc_range/format +message Ext4FindDelallocRangeFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 from = 3; + uint32 to = 4; + int32 reverse = 5; + int32 found = 6; + uint32 found_blk = 7; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_forget/format +message Ext4ForgetFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 block = 3; + int32 is_metadata = 4; + uint32 mode = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_free_blocks/format +message Ext4FreeBlocksFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 block = 3; + uint64 count = 4; + int32 flags = 5; + uint32 mode = 6; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_free_inode/format +message Ext4FreeInodeFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 uid = 3; + uint32 gid = 4; + uint64 blocks = 5; + uint32 mode = 6; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_get_implied_cluster_alloc_exit/format +message Ext4GetImpliedClusterAllocExitFormat { + uint64 dev = 1; + uint32 flags = 2; + uint32 lblk = 3; + uint64 pblk = 4; + uint32 len = 5; + int32 ret = 6; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_get_reserved_cluster_alloc/format +message Ext4GetReservedClusterAllocFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 lblk = 3; + uint32 len = 4; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ind_map_blocks_enter/format +message Ext4IndMapBlocksEnterFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 lblk = 3; + uint32 len = 4; + uint32 flags = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_ind_map_blocks_exit/format +message Ext4IndMapBlocksExitFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 flags = 3; + uint64 pblk = 4; + uint32 lblk = 5; + uint32 len = 6; + uint32 mflags = 7; + int32 ret = 8; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_insert_range/format +message Ext4InsertRangeFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 offset = 3; + uint64 len = 4; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_invalidatepage/format +message Ext4InvalidatepageFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 index = 3; + uint32 offset = 4; + uint32 length = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_journal_start/format +message Ext4JournalStartFormat { + uint64 dev = 1; + uint64 ip = 2; + int32 blocks = 3; + int32 rsv_blocks = 4; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_journal_start_reserved/format +message Ext4JournalStartReservedFormat { + uint64 dev = 1; + uint64 ip = 2; + int32 blocks = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_journalled_invalidatepage/format +message Ext4JournalledInvalidatepageFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 index = 3; + uint32 offset = 4; + uint32 length = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_journalled_write_end/format +message Ext4JournalledWriteEndFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 pos = 3; + uint32 len = 4; + uint32 copied = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_load_inode/format +message Ext4LoadInodeFormat { + uint64 dev = 1; + uint64 ino = 2; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_load_inode_bitmap/format +message Ext4LoadInodeBitmapFormat { + uint64 dev = 1; + uint32 group = 2; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_mark_inode_dirty/format +message Ext4MarkInodeDirtyFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 ip = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_mb_bitmap_load/format +message Ext4MbBitmapLoadFormat { + uint64 dev = 1; + uint32 group = 2; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_mb_buddy_bitmap_load/format +message Ext4MbBuddyBitmapLoadFormat { + uint64 dev = 1; + uint32 group = 2; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_mb_discard_preallocations/format +message Ext4MbDiscardPreallocationsFormat { + uint64 dev = 1; + int32 needed = 2; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_mb_new_group_pa/format +message Ext4MbNewGroupPaFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 pa_pstart = 3; + uint64 pa_lstart = 4; + uint32 pa_len = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_mb_new_inode_pa/format +message Ext4MbNewInodePaFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 pa_pstart = 3; + uint64 pa_lstart = 4; + uint32 pa_len = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_mb_release_group_pa/format +message Ext4MbReleaseGroupPaFormat { + uint64 dev = 1; + uint64 pa_pstart = 2; + uint32 pa_len = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_mb_release_inode_pa/format +message Ext4MbReleaseInodePaFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 block = 3; + uint32 count = 4; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_mballoc_alloc/format +message Ext4MballocAllocFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 orig_logical = 3; + int32 orig_start = 4; + uint32 orig_group = 5; + int32 orig_len = 6; + uint32 goal_logical = 7; + int32 goal_start = 8; + uint32 goal_group = 9; + int32 goal_len = 10; + uint32 result_logical = 11; + int32 result_start = 12; + uint32 result_group = 13; + int32 result_len = 14; + uint32 found = 15; + uint32 groups = 16; + uint32 buddy = 17; + uint32 flags = 18; + uint32 tail = 19; + uint32 cr = 20; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_mballoc_discard/format +message Ext4MballocDiscardFormat { + uint64 dev = 1; + uint64 ino = 2; + int32 result_start = 3; + uint32 result_group = 4; + int32 result_len = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_mballoc_free/format +message Ext4MballocFreeFormat { + uint64 dev = 1; + uint64 ino = 2; + int32 result_start = 3; + uint32 result_group = 4; + int32 result_len = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_mballoc_prealloc/format +message Ext4MballocPreallocFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 orig_logical = 3; + int32 orig_start = 4; + uint32 orig_group = 5; + int32 orig_len = 6; + uint32 result_logical = 7; + int32 result_start = 8; + uint32 result_group = 9; + int32 result_len = 10; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_other_inode_update_time/format +message Ext4OtherInodeUpdateTimeFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 orig_ino = 3; + uint32 uid = 4; + uint32 gid = 5; + uint32 mode = 6; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_punch_hole/format +message Ext4PunchHoleFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 offset = 3; + uint64 len = 4; + int32 mode = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_read_block_bitmap_load/format +message Ext4ReadBlockBitmapLoadFormat { + uint64 dev = 1; + uint32 group = 2; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_readpage/format +message Ext4ReadpageFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 index = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_releasepage/format +message Ext4ReleasepageFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 index = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_remove_blocks/format +message Ext4RemoveBlocksFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 from = 3; + uint32 to = 4; + uint64 partial = 5; + uint64 ee_pblk = 6; + uint32 ee_lblk = 7; + uint32 ee_len = 8; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_request_blocks/format +message Ext4RequestBlocksFormat { + uint64 dev = 1; + uint64 ino = 2; + uint32 len = 3; + uint32 logical = 4; + uint32 lleft = 5; + uint32 lright = 6; + uint64 goal = 7; + uint64 pleft = 8; + uint64 pright = 9; + uint32 flags = 10; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_request_inode/format +message Ext4RequestInodeFormat { + uint64 dev = 1; + uint64 dir = 2; + uint32 mode = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/format +message Ext4SyncFileEnterFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 parent = 3; + int32 datasync = 4; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/format +message Ext4SyncFileExitFormat { + uint64 dev = 1; + uint64 ino = 2; + int32 ret = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_sync_fs/format +message Ext4SyncFsFormat { + uint64 dev = 1; + int32 wait = 2; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_trim_all_free/format +message Ext4TrimAllFreeFormat { + int32 dev_major = 1; + int32 dev_minor = 2; + uint32 group = 3; + int32 start = 4; + int32 len = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_trim_extent/format +message Ext4TrimExtentFormat { + int32 dev_major = 1; + int32 dev_minor = 2; + uint32 group = 3; + int32 start = 4; + int32 len = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_truncate_enter/format +message Ext4TruncateEnterFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 blocks = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_truncate_exit/format +message Ext4TruncateExitFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 blocks = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_unlink_enter/format +message Ext4UnlinkEnterFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 parent = 3; + uint64 size = 4; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_unlink_exit/format +message Ext4UnlinkExitFormat { + uint64 dev = 1; + uint64 ino = 2; + int32 ret = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_write_begin/format +message Ext4WriteBeginFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 pos = 3; + uint32 len = 4; + uint32 flags = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_write_end/format +message Ext4WriteEndFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 pos = 3; + uint32 len = 4; + uint32 copied = 5; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_writepage/format +message Ext4WritepageFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 index = 3; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_writepages/format +message Ext4WritepagesFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 nr_to_write = 3; + uint64 pages_skipped = 4; + uint64 range_start = 5; + uint64 range_end = 6; + uint64 writeback_index = 7; + int32 sync_mode = 8; + uint32 for_kupdate = 9; + uint32 range_cyclic = 10; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_writepages_result/format +message Ext4WritepagesResultFormat { + uint64 dev = 1; + uint64 ino = 2; + int32 ret = 3; + int32 pages_written = 4; + uint64 pages_skipped = 5; + uint64 writeback_index = 6; + int32 sync_mode = 7; +} + +// /sys/kernel/debug/tracing/events/ext4/ext4_zero_range/format +message Ext4ZeroRangeFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 offset = 3; + uint64 len = 4; + int32 mode = 5; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/filelock.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/filelock.proto new file mode 100644 index 0000000000000000000000000000000000000000..1a52d8c9f3c34b90b57db8f8da444eb2d7c62c91 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/filelock.proto @@ -0,0 +1,97 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: filelock +// /sys/kernel/debug/tracing/events/filelock/break_lease_block/format +message BreakLeaseBlockFormat { + uint64 fl = 1; + uint64 i_ino = 2; + uint64 s_dev = 3; + uint64 fl_next = 4; + uint32 fl_owner = 5; + uint32 fl_flags = 6; + uint32 fl_type = 7; + uint64 fl_break_time = 8; + uint64 fl_downgrade_time = 9; +} + +// /sys/kernel/debug/tracing/events/filelock/break_lease_noblock/format +message BreakLeaseNoblockFormat { + uint64 fl = 1; + uint64 i_ino = 2; + uint64 s_dev = 3; + uint64 fl_next = 4; + uint32 fl_owner = 5; + uint32 fl_flags = 6; + uint32 fl_type = 7; + uint64 fl_break_time = 8; + uint64 fl_downgrade_time = 9; +} + +// /sys/kernel/debug/tracing/events/filelock/break_lease_unblock/format +message BreakLeaseUnblockFormat { + uint64 fl = 1; + uint64 i_ino = 2; + uint64 s_dev = 3; + uint64 fl_next = 4; + uint32 fl_owner = 5; + uint32 fl_flags = 6; + uint32 fl_type = 7; + uint64 fl_break_time = 8; + uint64 fl_downgrade_time = 9; +} + +// /sys/kernel/debug/tracing/events/filelock/generic_add_lease/format +message GenericAddLeaseFormat { + uint64 i_ino = 1; + int32 wcount = 2; + int32 dcount = 3; + int32 icount = 4; + uint64 s_dev = 5; + uint32 fl_owner = 6; + uint32 fl_flags = 7; + uint32 fl_type = 8; +} + +// /sys/kernel/debug/tracing/events/filelock/generic_delete_lease/format +message GenericDeleteLeaseFormat { + uint64 fl = 1; + uint64 i_ino = 2; + uint64 s_dev = 3; + uint64 fl_next = 4; + uint32 fl_owner = 5; + uint32 fl_flags = 6; + uint32 fl_type = 7; + uint64 fl_break_time = 8; + uint64 fl_downgrade_time = 9; +} + +// /sys/kernel/debug/tracing/events/filelock/time_out_leases/format +message TimeOutLeasesFormat { + uint64 fl = 1; + uint64 i_ino = 2; + uint64 s_dev = 3; + uint64 fl_next = 4; + uint32 fl_owner = 5; + uint32 fl_flags = 6; + uint32 fl_type = 7; + uint64 fl_break_time = 8; + uint64 fl_downgrade_time = 9; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/filemap.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/filemap.proto new file mode 100644 index 0000000000000000000000000000000000000000..5410c6f4f35946198bab32688f1f0eae025873ee --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/filemap.proto @@ -0,0 +1,36 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: filemap +// /sys/kernel/debug/tracing/events/filemap/mm_filemap_add_to_page_cache/format +message MmFilemapAddToPageCacheFormat { + uint64 pfn = 1; + uint64 i_ino = 2; + uint64 index = 3; + uint64 s_dev = 4; +} + +// /sys/kernel/debug/tracing/events/filemap/mm_filemap_delete_from_page_cache/format +message MmFilemapDeleteFromPageCacheFormat { + uint64 pfn = 1; + uint64 i_ino = 2; + uint64 index = 3; + uint64 s_dev = 4; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/ftrace.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/ftrace.proto new file mode 100644 index 0000000000000000000000000000000000000000..6c9429dd63b99dba7aea98a040497e7f72bcf6da --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/ftrace.proto @@ -0,0 +1,115 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: ftrace +// /sys/kernel/debug/tracing/events/ftrace/bputs/format +message BputsFormat { + uint64 ip = 1; + string str = 2; +} + +// /sys/kernel/debug/tracing/events/ftrace/branch/format +message BranchFormat { + uint32 line = 1; + string func = 2; + string file = 3; + uint32 correct = 4; + uint32 constant = 5; +} + +// /sys/kernel/debug/tracing/events/ftrace/context_switch/format +message ContextSwitchFormat { + uint32 prev_pid = 1; + uint32 next_pid = 2; + uint32 next_cpu = 3; + uint32 prev_prio = 4; + uint32 prev_state = 5; + uint32 next_prio = 6; + uint32 next_state = 7; +} + +// /sys/kernel/debug/tracing/events/ftrace/funcgraph_entry/format +message FuncgraphEntryFormat { + uint64 func = 1; + int32 depth = 2; +} + +// /sys/kernel/debug/tracing/events/ftrace/funcgraph_exit/format +message FuncgraphExitFormat { + uint64 func = 1; + uint64 calltime = 2; + uint64 rettime = 3; + uint64 overrun = 4; + int32 depth = 5; +} + +// /sys/kernel/debug/tracing/events/ftrace/function/format +message FunctionFormat { + uint64 ip = 1; + uint64 parent_ip = 2; +} + +// /sys/kernel/debug/tracing/events/ftrace/kernel_stack/format +message KernelStackFormat { + int32 size = 1; + uint64 caller = 2; +} + +// /sys/kernel/debug/tracing/events/ftrace/mmiotrace_map/format +message MmiotraceMapFormat { + uint64 phys = 1; + uint64 virt = 2; + uint64 len = 3; + int32 map_id = 4; + uint32 opcode = 5; +} + +// /sys/kernel/debug/tracing/events/ftrace/mmiotrace_rw/format +message MmiotraceRwFormat { + uint64 phys = 1; + uint64 value = 2; + uint64 pc = 3; + int32 map_id = 4; + uint32 opcode = 5; + uint32 width = 6; +} + +// /sys/kernel/debug/tracing/events/ftrace/print/format +message PrintFormat { + uint64 ip = 1; + string buf = 2; +} + +// /sys/kernel/debug/tracing/events/ftrace/user_stack/format +message UserStackFormat { + uint32 tgid = 1; + string caller = 2; +} + +// /sys/kernel/debug/tracing/events/ftrace/wakeup/format +message WakeupFormat { + uint32 prev_pid = 1; + uint32 next_pid = 2; + uint32 next_cpu = 3; + uint32 prev_prio = 4; + uint32 prev_state = 5; + uint32 next_prio = 6; + uint32 next_state = 7; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/ftrace_event.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/ftrace_event.proto new file mode 100644 index 0000000000000000000000000000000000000000..53b3e5848ac02e8b0e54a7620f07c62462829b66 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/ftrace_event.proto @@ -0,0 +1,452 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +import "binder.proto"; +import "block.proto"; +import "cgroup.proto"; +import "clk.proto"; +import "compaction.proto"; +import "cpuhp.proto"; +import "dma_fence.proto"; +import "ext4.proto"; +import "filelock.proto"; +import "filemap.proto"; +import "ftrace.proto"; +import "gpio.proto"; +import "i2c.proto"; +import "ipi.proto"; +import "irq.proto"; +import "kmem.proto"; +import "net.proto"; +import "oom.proto"; +import "pagemap.proto"; +import "power.proto"; +import "printk.proto"; +import "raw_syscalls.proto"; +import "rcu.proto"; +import "sched.proto"; +import "signal.proto"; +import "sunrpc.proto"; +import "task.proto"; +import "timer.proto"; +import "v4l2.proto"; +import "vmscan.proto"; +import "workqueue.proto"; +import "writeback.proto"; + +message FtraceEvent { + uint64 timestamp = 1; + int32 tgid = 2; + string comm = 3; + + message CommonFileds { + uint32 type = 1; + uint32 flags = 2; + uint32 preempt_count = 3; + int32 pid = 4; + }; + CommonFileds common_fields = 50; + + oneof event { + BinderAllocLruEndFormat binder_alloc_lru_end_format = 100; + BinderAllocLruStartFormat binder_alloc_lru_start_format = 101; + BinderAllocPageEndFormat binder_alloc_page_end_format = 102; + BinderAllocPageStartFormat binder_alloc_page_start_format = 103; + BinderCommandFormat binder_command_format = 104; + BinderFreeLruEndFormat binder_free_lru_end_format = 105; + BinderFreeLruStartFormat binder_free_lru_start_format = 106; + BinderIoctlFormat binder_ioctl_format = 107; + BinderIoctlDoneFormat binder_ioctl_done_format = 108; + BinderLockFormat binder_lock_format = 109; + BinderLockedFormat binder_locked_format = 110; + BinderReadDoneFormat binder_read_done_format = 111; + BinderReturnFormat binder_return_format = 112; + BinderTransactionFormat binder_transaction_format = 113; + BinderTransactionAllocBufFormat binder_transaction_alloc_buf_format = 114; + BinderTransactionBufferReleaseFormat binder_transaction_buffer_release_format = 115; + BinderTransactionFailedBufferReleaseFormat binder_transaction_failed_buffer_release_format = 116; + BinderTransactionFdFormat binder_transaction_fd_format = 117; + BinderTransactionNodeToRefFormat binder_transaction_node_to_ref_format = 118; + BinderTransactionReceivedFormat binder_transaction_received_format = 119; + BinderTransactionRefToNodeFormat binder_transaction_ref_to_node_format = 120; + BinderTransactionRefToRefFormat binder_transaction_ref_to_ref_format = 121; + BinderUnlockFormat binder_unlock_format = 122; + BinderUnmapKernelEndFormat binder_unmap_kernel_end_format = 123; + BinderUnmapKernelStartFormat binder_unmap_kernel_start_format = 124; + BinderUnmapUserEndFormat binder_unmap_user_end_format = 125; + BinderUnmapUserStartFormat binder_unmap_user_start_format = 126; + BinderUpdatePageRangeFormat binder_update_page_range_format = 127; + BinderWaitForWorkFormat binder_wait_for_work_format = 128; + BinderWriteDoneFormat binder_write_done_format = 129; + BlockBioBackmergeFormat block_bio_backmerge_format = 200; + BlockBioBounceFormat block_bio_bounce_format = 201; + BlockBioCompleteFormat block_bio_complete_format = 202; + BlockBioFrontmergeFormat block_bio_frontmerge_format = 203; + BlockBioQueueFormat block_bio_queue_format = 204; + BlockBioRemapFormat block_bio_remap_format = 205; + BlockDirtyBufferFormat block_dirty_buffer_format = 206; + BlockGetrqFormat block_getrq_format = 207; + BlockPlugFormat block_plug_format = 208; + BlockRqCompleteFormat block_rq_complete_format = 209; + BlockRqInsertFormat block_rq_insert_format = 210; + BlockRqIssueFormat block_rq_issue_format = 211; + BlockRqRemapFormat block_rq_remap_format = 212; + BlockRqRequeueFormat block_rq_requeue_format = 213; + BlockSleeprqFormat block_sleeprq_format = 214; + BlockSplitFormat block_split_format = 215; + BlockTouchBufferFormat block_touch_buffer_format = 216; + BlockUnplugFormat block_unplug_format = 217; + CgroupAttachTaskFormat cgroup_attach_task_format = 300; + CgroupDestroyRootFormat cgroup_destroy_root_format = 301; + CgroupMkdirFormat cgroup_mkdir_format = 302; + CgroupReleaseFormat cgroup_release_format = 303; + CgroupRemountFormat cgroup_remount_format = 304; + CgroupRenameFormat cgroup_rename_format = 305; + CgroupRmdirFormat cgroup_rmdir_format = 306; + CgroupSetupRootFormat cgroup_setup_root_format = 307; + CgroupTransferTasksFormat cgroup_transfer_tasks_format = 308; + ClkDisableFormat clk_disable_format = 400; + ClkDisableCompleteFormat clk_disable_complete_format = 401; + ClkEnableFormat clk_enable_format = 402; + ClkEnableCompleteFormat clk_enable_complete_format = 403; + ClkPrepareFormat clk_prepare_format = 404; + ClkPrepareCompleteFormat clk_prepare_complete_format = 405; + ClkSetParentFormat clk_set_parent_format = 406; + ClkSetParentCompleteFormat clk_set_parent_complete_format = 407; + ClkSetPhaseFormat clk_set_phase_format = 408; + ClkSetPhaseCompleteFormat clk_set_phase_complete_format = 409; + ClkSetRateFormat clk_set_rate_format = 410; + ClkSetRateCompleteFormat clk_set_rate_complete_format = 411; + ClkUnprepareFormat clk_unprepare_format = 412; + ClkUnprepareCompleteFormat clk_unprepare_complete_format = 413; + MmCompactionBeginFormat mm_compaction_begin_format = 500; + MmCompactionDeferCompactionFormat mm_compaction_defer_compaction_format = 501; + MmCompactionDeferResetFormat mm_compaction_defer_reset_format = 502; + MmCompactionDeferredFormat mm_compaction_deferred_format = 503; + MmCompactionEndFormat mm_compaction_end_format = 504; + MmCompactionFinishedFormat mm_compaction_finished_format = 505; + MmCompactionIsolateFreepagesFormat mm_compaction_isolate_freepages_format = 506; + MmCompactionIsolateMigratepagesFormat mm_compaction_isolate_migratepages_format = 507; + MmCompactionMigratepagesFormat mm_compaction_migratepages_format = 508; + MmCompactionSuitableFormat mm_compaction_suitable_format = 509; + MmCompactionTryToCompactPagesFormat mm_compaction_try_to_compact_pages_format = 510; + CpuhpEnterFormat cpuhp_enter_format = 600; + CpuhpExitFormat cpuhp_exit_format = 601; + CpuhpMultiEnterFormat cpuhp_multi_enter_format = 602; + DmaFenceDestroyFormat dma_fence_destroy_format = 700; + DmaFenceEmitFormat dma_fence_emit_format = 701; + DmaFenceEnableSignalFormat dma_fence_enable_signal_format = 702; + DmaFenceInitFormat dma_fence_init_format = 703; + DmaFenceSignaledFormat dma_fence_signaled_format = 704; + DmaFenceWaitEndFormat dma_fence_wait_end_format = 705; + DmaFenceWaitStartFormat dma_fence_wait_start_format = 706; + Ext4AllocDaBlocksFormat ext4_alloc_da_blocks_format = 800; + Ext4AllocateBlocksFormat ext4_allocate_blocks_format = 801; + Ext4AllocateInodeFormat ext4_allocate_inode_format = 802; + Ext4BeginOrderedTruncateFormat ext4_begin_ordered_truncate_format = 803; + Ext4CollapseRangeFormat ext4_collapse_range_format = 804; + Ext4DaReleaseSpaceFormat ext4_da_release_space_format = 805; + Ext4DaReserveSpaceFormat ext4_da_reserve_space_format = 806; + Ext4DaUpdateReserveSpaceFormat ext4_da_update_reserve_space_format = 807; + Ext4DaWriteBeginFormat ext4_da_write_begin_format = 808; + Ext4DaWriteEndFormat ext4_da_write_end_format = 809; + Ext4DaWritePagesFormat ext4_da_write_pages_format = 810; + Ext4DaWritePagesExtentFormat ext4_da_write_pages_extent_format = 811; + Ext4DirectIoEnterFormat ext4_direct_io_enter_format = 812; + Ext4DirectIoExitFormat ext4_direct_io_exit_format = 813; + Ext4DiscardBlocksFormat ext4_discard_blocks_format = 814; + Ext4DiscardPreallocationsFormat ext4_discard_preallocations_format = 815; + Ext4DropInodeFormat ext4_drop_inode_format = 816; + Ext4EsCacheExtentFormat ext4_es_cache_extent_format = 817; + Ext4EsFindDelayedExtentRangeEnterFormat ext4_es_find_delayed_extent_range_enter_format = 818; + Ext4EsFindDelayedExtentRangeExitFormat ext4_es_find_delayed_extent_range_exit_format = 819; + Ext4EsInsertExtentFormat ext4_es_insert_extent_format = 820; + Ext4EsLookupExtentEnterFormat ext4_es_lookup_extent_enter_format = 821; + Ext4EsLookupExtentExitFormat ext4_es_lookup_extent_exit_format = 822; + Ext4EsRemoveExtentFormat ext4_es_remove_extent_format = 823; + Ext4EsShrinkFormat ext4_es_shrink_format = 824; + Ext4EsShrinkCountFormat ext4_es_shrink_count_format = 825; + Ext4EsShrinkScanEnterFormat ext4_es_shrink_scan_enter_format = 826; + Ext4EsShrinkScanExitFormat ext4_es_shrink_scan_exit_format = 827; + Ext4EvictInodeFormat ext4_evict_inode_format = 828; + Ext4ExtConvertToInitializedEnterFormat ext4_ext_convert_to_initialized_enter_format = 829; + Ext4ExtConvertToInitializedFastpathFormat ext4_ext_convert_to_initialized_fastpath_format = 830; + Ext4ExtHandleUnwrittenExtentsFormat ext4_ext_handle_unwritten_extents_format = 831; + Ext4ExtInCacheFormat ext4_ext_in_cache_format = 832; + Ext4ExtLoadExtentFormat ext4_ext_load_extent_format = 833; + Ext4ExtMapBlocksEnterFormat ext4_ext_map_blocks_enter_format = 834; + Ext4ExtMapBlocksExitFormat ext4_ext_map_blocks_exit_format = 835; + Ext4ExtPutInCacheFormat ext4_ext_put_in_cache_format = 836; + Ext4ExtRemoveSpaceFormat ext4_ext_remove_space_format = 837; + Ext4ExtRemoveSpaceDoneFormat ext4_ext_remove_space_done_format = 838; + Ext4ExtRmIdxFormat ext4_ext_rm_idx_format = 839; + Ext4ExtRmLeafFormat ext4_ext_rm_leaf_format = 840; + Ext4ExtShowExtentFormat ext4_ext_show_extent_format = 841; + Ext4FallocateEnterFormat ext4_fallocate_enter_format = 842; + Ext4FallocateExitFormat ext4_fallocate_exit_format = 843; + Ext4FindDelallocRangeFormat ext4_find_delalloc_range_format = 844; + Ext4ForgetFormat ext4_forget_format = 845; + Ext4FreeBlocksFormat ext4_free_blocks_format = 846; + Ext4FreeInodeFormat ext4_free_inode_format = 847; + Ext4GetImpliedClusterAllocExitFormat ext4_get_implied_cluster_alloc_exit_format = 848; + Ext4GetReservedClusterAllocFormat ext4_get_reserved_cluster_alloc_format = 849; + Ext4IndMapBlocksEnterFormat ext4_ind_map_blocks_enter_format = 850; + Ext4IndMapBlocksExitFormat ext4_ind_map_blocks_exit_format = 851; + Ext4InsertRangeFormat ext4_insert_range_format = 852; + Ext4InvalidatepageFormat ext4_invalidatepage_format = 853; + Ext4JournalStartFormat ext4_journal_start_format = 854; + Ext4JournalStartReservedFormat ext4_journal_start_reserved_format = 855; + Ext4JournalledInvalidatepageFormat ext4_journalled_invalidatepage_format = 856; + Ext4JournalledWriteEndFormat ext4_journalled_write_end_format = 857; + Ext4LoadInodeFormat ext4_load_inode_format = 858; + Ext4LoadInodeBitmapFormat ext4_load_inode_bitmap_format = 859; + Ext4MarkInodeDirtyFormat ext4_mark_inode_dirty_format = 860; + Ext4MbBitmapLoadFormat ext4_mb_bitmap_load_format = 861; + Ext4MbBuddyBitmapLoadFormat ext4_mb_buddy_bitmap_load_format = 862; + Ext4MbDiscardPreallocationsFormat ext4_mb_discard_preallocations_format = 863; + Ext4MbNewGroupPaFormat ext4_mb_new_group_pa_format = 864; + Ext4MbNewInodePaFormat ext4_mb_new_inode_pa_format = 865; + Ext4MbReleaseGroupPaFormat ext4_mb_release_group_pa_format = 866; + Ext4MbReleaseInodePaFormat ext4_mb_release_inode_pa_format = 867; + Ext4MballocAllocFormat ext4_mballoc_alloc_format = 868; + Ext4MballocDiscardFormat ext4_mballoc_discard_format = 869; + Ext4MballocFreeFormat ext4_mballoc_free_format = 870; + Ext4MballocPreallocFormat ext4_mballoc_prealloc_format = 871; + Ext4OtherInodeUpdateTimeFormat ext4_other_inode_update_time_format = 872; + Ext4PunchHoleFormat ext4_punch_hole_format = 873; + Ext4ReadBlockBitmapLoadFormat ext4_read_block_bitmap_load_format = 874; + Ext4ReadpageFormat ext4_readpage_format = 875; + Ext4ReleasepageFormat ext4_releasepage_format = 876; + Ext4RemoveBlocksFormat ext4_remove_blocks_format = 877; + Ext4RequestBlocksFormat ext4_request_blocks_format = 878; + Ext4RequestInodeFormat ext4_request_inode_format = 879; + Ext4SyncFileEnterFormat ext4_sync_file_enter_format = 880; + Ext4SyncFileExitFormat ext4_sync_file_exit_format = 881; + Ext4SyncFsFormat ext4_sync_fs_format = 882; + Ext4TrimAllFreeFormat ext4_trim_all_free_format = 883; + Ext4TrimExtentFormat ext4_trim_extent_format = 884; + Ext4TruncateEnterFormat ext4_truncate_enter_format = 885; + Ext4TruncateExitFormat ext4_truncate_exit_format = 886; + Ext4UnlinkEnterFormat ext4_unlink_enter_format = 887; + Ext4UnlinkExitFormat ext4_unlink_exit_format = 888; + Ext4WriteBeginFormat ext4_write_begin_format = 889; + Ext4WriteEndFormat ext4_write_end_format = 890; + Ext4WritepageFormat ext4_writepage_format = 891; + Ext4WritepagesFormat ext4_writepages_format = 892; + Ext4WritepagesResultFormat ext4_writepages_result_format = 893; + Ext4ZeroRangeFormat ext4_zero_range_format = 894; + BreakLeaseBlockFormat break_lease_block_format = 900; + BreakLeaseNoblockFormat break_lease_noblock_format = 901; + BreakLeaseUnblockFormat break_lease_unblock_format = 902; + GenericAddLeaseFormat generic_add_lease_format = 903; + GenericDeleteLeaseFormat generic_delete_lease_format = 904; + TimeOutLeasesFormat time_out_leases_format = 905; + MmFilemapAddToPageCacheFormat mm_filemap_add_to_page_cache_format = 1000; + MmFilemapDeleteFromPageCacheFormat mm_filemap_delete_from_page_cache_format = 1001; + BputsFormat bputs_format = 1100; + BranchFormat branch_format = 1101; + ContextSwitchFormat context_switch_format = 1102; + FuncgraphEntryFormat funcgraph_entry_format = 1103; + FuncgraphExitFormat funcgraph_exit_format = 1104; + FunctionFormat function_format = 1105; + KernelStackFormat kernel_stack_format = 1106; + MmiotraceMapFormat mmiotrace_map_format = 1107; + MmiotraceRwFormat mmiotrace_rw_format = 1108; + PrintFormat print_format = 1109; + UserStackFormat user_stack_format = 1110; + WakeupFormat wakeup_format = 1111; + GpioDirectionFormat gpio_direction_format = 1200; + GpioValueFormat gpio_value_format = 1201; + I2cReadFormat i2c_read_format = 1300; + I2cReplyFormat i2c_reply_format = 1301; + I2cResultFormat i2c_result_format = 1302; + I2cWriteFormat i2c_write_format = 1303; + IpiEntryFormat ipi_entry_format = 1400; + IpiExitFormat ipi_exit_format = 1401; + IpiRaiseFormat ipi_raise_format = 1402; + IrqHandlerEntryFormat irq_handler_entry_format = 1500; + IrqHandlerExitFormat irq_handler_exit_format = 1501; + SoftirqEntryFormat softirq_entry_format = 1502; + SoftirqExitFormat softirq_exit_format = 1503; + SoftirqRaiseFormat softirq_raise_format = 1504; + KfreeFormat kfree_format = 1600; + KmallocFormat kmalloc_format = 1601; + KmallocNodeFormat kmalloc_node_format = 1602; + KmemCacheAllocFormat kmem_cache_alloc_format = 1603; + KmemCacheAllocNodeFormat kmem_cache_alloc_node_format = 1604; + KmemCacheFreeFormat kmem_cache_free_format = 1605; + MmPageAllocFormat mm_page_alloc_format = 1606; + MmPageAllocExtfragFormat mm_page_alloc_extfrag_format = 1607; + MmPageAllocZoneLockedFormat mm_page_alloc_zone_locked_format = 1608; + MmPageFreeFormat mm_page_free_format = 1609; + MmPageFreeBatchedFormat mm_page_free_batched_format = 1610; + MmPagePcpuDrainFormat mm_page_pcpu_drain_format = 1611; + NapiGroFragsEntryFormat napi_gro_frags_entry_format = 1700; + NapiGroReceiveEntryFormat napi_gro_receive_entry_format = 1701; + NetDevQueueFormat net_dev_queue_format = 1702; + NetDevStartXmitFormat net_dev_start_xmit_format = 1703; + NetDevXmitFormat net_dev_xmit_format = 1704; + NetifReceiveSkbFormat netif_receive_skb_format = 1705; + NetifReceiveSkbEntryFormat netif_receive_skb_entry_format = 1706; + NetifRxFormat netif_rx_format = 1707; + NetifRxEntryFormat netif_rx_entry_format = 1708; + NetifRxNiEntryFormat netif_rx_ni_entry_format = 1709; + OomScoreAdjUpdateFormat oom_score_adj_update_format = 1800; + MmLruActivateFormat mm_lru_activate_format = 1900; + MmLruInsertionFormat mm_lru_insertion_format = 1901; + ClockDisableFormat clock_disable_format = 2000; + ClockEnableFormat clock_enable_format = 2001; + ClockSetRateFormat clock_set_rate_format = 2002; + CpuFrequencyFormat cpu_frequency_format = 2003; + CpuFrequencyLimitsFormat cpu_frequency_limits_format = 2004; + CpuIdleFormat cpu_idle_format = 2005; + DevPmQosAddRequestFormat dev_pm_qos_add_request_format = 2006; + DevPmQosRemoveRequestFormat dev_pm_qos_remove_request_format = 2007; + DevPmQosUpdateRequestFormat dev_pm_qos_update_request_format = 2008; + DevicePmCallbackEndFormat device_pm_callback_end_format = 2009; + DevicePmCallbackStartFormat device_pm_callback_start_format = 2010; + PmQosAddRequestFormat pm_qos_add_request_format = 2011; + PmQosRemoveRequestFormat pm_qos_remove_request_format = 2012; + PmQosUpdateFlagsFormat pm_qos_update_flags_format = 2013; + PmQosUpdateRequestFormat pm_qos_update_request_format = 2014; + PmQosUpdateRequestTimeoutFormat pm_qos_update_request_timeout_format = 2015; + PmQosUpdateTargetFormat pm_qos_update_target_format = 2016; + PowerDomainTargetFormat power_domain_target_format = 2017; + PstateSampleFormat pstate_sample_format = 2018; + SuspendResumeFormat suspend_resume_format = 2019; + WakeupSourceActivateFormat wakeup_source_activate_format = 2020; + WakeupSourceDeactivateFormat wakeup_source_deactivate_format = 2021; + ConsoleFormat console_format = 2100; + SysEnterFormat sys_enter_format = 2200; + SysExitFormat sys_exit_format = 2201; + RcuUtilizationFormat rcu_utilization_format = 2300; + SchedKthreadStopFormat sched_kthread_stop_format = 2400; + SchedKthreadStopRetFormat sched_kthread_stop_ret_format = 2401; + SchedMigrateTaskFormat sched_migrate_task_format = 2402; + SchedMoveNumaFormat sched_move_numa_format = 2403; + SchedPiSetprioFormat sched_pi_setprio_format = 2404; + SchedProcessExecFormat sched_process_exec_format = 2405; + SchedProcessExitFormat sched_process_exit_format = 2406; + SchedProcessForkFormat sched_process_fork_format = 2407; + SchedProcessFreeFormat sched_process_free_format = 2408; + SchedProcessWaitFormat sched_process_wait_format = 2409; + SchedStatBlockedFormat sched_stat_blocked_format = 2410; + SchedStatIowaitFormat sched_stat_iowait_format = 2411; + SchedStatRuntimeFormat sched_stat_runtime_format = 2412; + SchedStatSleepFormat sched_stat_sleep_format = 2413; + SchedStatWaitFormat sched_stat_wait_format = 2414; + SchedStickNumaFormat sched_stick_numa_format = 2415; + SchedSwapNumaFormat sched_swap_numa_format = 2416; + SchedSwitchFormat sched_switch_format = 2417; + SchedWaitTaskFormat sched_wait_task_format = 2418; + SchedWakeIdleWithoutIpiFormat sched_wake_idle_without_ipi_format = 2419; + SchedWakeupFormat sched_wakeup_format = 2420; + SchedWakeupNewFormat sched_wakeup_new_format = 2421; + SchedWakingFormat sched_waking_format = 2422; + SignalDeliverFormat signal_deliver_format = 2500; + SignalGenerateFormat signal_generate_format = 2501; + RpcBindStatusFormat rpc_bind_status_format = 2600; + RpcCallStatusFormat rpc_call_status_format = 2601; + RpcConnectStatusFormat rpc_connect_status_format = 2602; + RpcSocketCloseFormat rpc_socket_close_format = 2603; + RpcSocketConnectFormat rpc_socket_connect_format = 2604; + RpcSocketErrorFormat rpc_socket_error_format = 2605; + RpcSocketResetConnectionFormat rpc_socket_reset_connection_format = 2606; + RpcSocketShutdownFormat rpc_socket_shutdown_format = 2607; + RpcSocketStateChangeFormat rpc_socket_state_change_format = 2608; + RpcTaskBeginFormat rpc_task_begin_format = 2609; + RpcTaskCompleteFormat rpc_task_complete_format = 2610; + RpcTaskRunActionFormat rpc_task_run_action_format = 2611; + RpcTaskSleepFormat rpc_task_sleep_format = 2612; + RpcTaskWakeupFormat rpc_task_wakeup_format = 2613; + SvcHandleXprtFormat svc_handle_xprt_format = 2614; + SvcProcessFormat svc_process_format = 2615; + SvcRecvFormat svc_recv_format = 2616; + SvcSendFormat svc_send_format = 2617; + SvcWakeUpFormat svc_wake_up_format = 2618; + SvcXprtDequeueFormat svc_xprt_dequeue_format = 2619; + SvcXprtDoEnqueueFormat svc_xprt_do_enqueue_format = 2620; + XprtCompleteRqstFormat xprt_complete_rqst_format = 2621; + XprtLookupRqstFormat xprt_lookup_rqst_format = 2622; + XprtTransmitFormat xprt_transmit_format = 2623; + XsTcpDataReadyFormat xs_tcp_data_ready_format = 2624; + XsTcpDataRecvFormat xs_tcp_data_recv_format = 2625; + TaskNewtaskFormat task_newtask_format = 2700; + TaskRenameFormat task_rename_format = 2701; + HrtimerCancelFormat hrtimer_cancel_format = 2800; + HrtimerExpireEntryFormat hrtimer_expire_entry_format = 2801; + HrtimerExpireExitFormat hrtimer_expire_exit_format = 2802; + HrtimerInitFormat hrtimer_init_format = 2803; + HrtimerStartFormat hrtimer_start_format = 2804; + ItimerExpireFormat itimer_expire_format = 2805; + ItimerStateFormat itimer_state_format = 2806; + TimerCancelFormat timer_cancel_format = 2807; + TimerExpireEntryFormat timer_expire_entry_format = 2808; + TimerExpireExitFormat timer_expire_exit_format = 2809; + TimerInitFormat timer_init_format = 2810; + TimerStartFormat timer_start_format = 2811; + V4l2DqbufFormat v4l2_dqbuf_format = 2900; + V4l2QbufFormat v4l2_qbuf_format = 2901; + Vb2V4l2BufDoneFormat vb2_v4l2_buf_done_format = 2902; + Vb2V4l2BufQueueFormat vb2_v4l2_buf_queue_format = 2903; + Vb2V4l2DqbufFormat vb2_v4l2_dqbuf_format = 2904; + Vb2V4l2QbufFormat vb2_v4l2_qbuf_format = 2905; + MmShrinkSlabEndFormat mm_shrink_slab_end_format = 3000; + MmShrinkSlabStartFormat mm_shrink_slab_start_format = 3001; + MmVmscanDirectReclaimBeginFormat mm_vmscan_direct_reclaim_begin_format = 3002; + MmVmscanDirectReclaimEndFormat mm_vmscan_direct_reclaim_end_format = 3003; + MmVmscanKswapdSleepFormat mm_vmscan_kswapd_sleep_format = 3004; + MmVmscanKswapdWakeFormat mm_vmscan_kswapd_wake_format = 3005; + MmVmscanLruIsolateFormat mm_vmscan_lru_isolate_format = 3006; + MmVmscanLruShrinkInactiveFormat mm_vmscan_lru_shrink_inactive_format = 3007; + MmVmscanWakeupKswapdFormat mm_vmscan_wakeup_kswapd_format = 3008; + MmVmscanWritepageFormat mm_vmscan_writepage_format = 3009; + WorkqueueActivateWorkFormat workqueue_activate_work_format = 3100; + WorkqueueExecuteEndFormat workqueue_execute_end_format = 3101; + WorkqueueExecuteStartFormat workqueue_execute_start_format = 3102; + WorkqueueQueueWorkFormat workqueue_queue_work_format = 3103; + BalanceDirtyPagesFormat balance_dirty_pages_format = 3200; + BdiDirtyRatelimitFormat bdi_dirty_ratelimit_format = 3201; + GlobalDirtyStateFormat global_dirty_state_format = 3202; + WbcWritepageFormat wbc_writepage_format = 3203; + WritebackBdiRegisterFormat writeback_bdi_register_format = 3204; + WritebackCongestionWaitFormat writeback_congestion_wait_format = 3205; + WritebackDirtyInodeFormat writeback_dirty_inode_format = 3206; + WritebackDirtyInodeEnqueueFormat writeback_dirty_inode_enqueue_format = 3207; + WritebackDirtyInodeStartFormat writeback_dirty_inode_start_format = 3208; + WritebackDirtyPageFormat writeback_dirty_page_format = 3209; + WritebackExecFormat writeback_exec_format = 3210; + WritebackLazytimeFormat writeback_lazytime_format = 3211; + WritebackLazytimeIputFormat writeback_lazytime_iput_format = 3212; + WritebackMarkInodeDirtyFormat writeback_mark_inode_dirty_format = 3213; + WritebackPagesWrittenFormat writeback_pages_written_format = 3214; + WritebackQueueFormat writeback_queue_format = 3215; + WritebackQueueIoFormat writeback_queue_io_format = 3216; + WritebackSbInodesRequeueFormat writeback_sb_inodes_requeue_format = 3217; + WritebackSingleInodeFormat writeback_single_inode_format = 3218; + WritebackSingleInodeStartFormat writeback_single_inode_start_format = 3219; + WritebackStartFormat writeback_start_format = 3220; + WritebackWaitFormat writeback_wait_format = 3221; + WritebackWaitIffCongestedFormat writeback_wait_iff_congested_format = 3222; + WritebackWakeBackgroundFormat writeback_wake_background_format = 3223; + WritebackWriteInodeFormat writeback_write_inode_format = 3224; + WritebackWriteInodeStartFormat writeback_write_inode_start_format = 3225; + WritebackWrittenFormat writeback_written_format = 3226; + } +} diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/gpio.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/gpio.proto new file mode 100644 index 0000000000000000000000000000000000000000..1410af52c24e250e5aa6434c7993537c2f918a25 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/gpio.proto @@ -0,0 +1,34 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: gpio +// /sys/kernel/debug/tracing/events/gpio/gpio_direction/format +message GpioDirectionFormat { + uint32 gpio = 1; + int32 in = 2; + int32 err = 3; +} + +// /sys/kernel/debug/tracing/events/gpio/gpio_value/format +message GpioValueFormat { + uint32 gpio = 1; + int32 get = 2; + int32 value = 3; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/i2c.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/i2c.proto new file mode 100644 index 0000000000000000000000000000000000000000..4f1de54988f7d1c3b06502630e09b60c4258e0b9 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/i2c.proto @@ -0,0 +1,56 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: i2c +// /sys/kernel/debug/tracing/events/i2c/i2c_read/format +message I2cReadFormat { + int32 adapter_nr = 1; + uint32 msg_nr = 2; + uint32 addr = 3; + uint32 flags = 4; + uint32 len = 5; +} + +// /sys/kernel/debug/tracing/events/i2c/i2c_reply/format +message I2cReplyFormat { + int32 adapter_nr = 1; + uint32 msg_nr = 2; + uint32 addr = 3; + uint32 flags = 4; + uint32 len = 5; + uint32 buf = 6; +} + +// /sys/kernel/debug/tracing/events/i2c/i2c_result/format +message I2cResultFormat { + int32 adapter_nr = 1; + uint32 nr_msgs = 2; + int32 ret = 3; +} + +// /sys/kernel/debug/tracing/events/i2c/i2c_write/format +message I2cWriteFormat { + int32 adapter_nr = 1; + uint32 msg_nr = 2; + uint32 addr = 3; + uint32 flags = 4; + uint32 len = 5; + uint32 buf = 6; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/ipi.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/ipi.proto new file mode 100644 index 0000000000000000000000000000000000000000..0eda02f6e3b3485f07125e6bfb5baa1ceb34b004 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/ipi.proto @@ -0,0 +1,36 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: ipi +// /sys/kernel/debug/tracing/events/ipi/ipi_entry/format +message IpiEntryFormat { + string reason = 1; +} + +// /sys/kernel/debug/tracing/events/ipi/ipi_exit/format +message IpiExitFormat { + string reason = 1; +} + +// /sys/kernel/debug/tracing/events/ipi/ipi_raise/format +message IpiRaiseFormat { + uint64 target_cpus = 1; + string reason = 2; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/irq.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/irq.proto new file mode 100644 index 0000000000000000000000000000000000000000..1e3ce1afebc69cd764ddb991914090168d3b79e1 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/irq.proto @@ -0,0 +1,47 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: irq +// /sys/kernel/debug/tracing/events/irq/irq_handler_entry/format +message IrqHandlerEntryFormat { + int32 irq = 1; + string name = 2; +} + +// /sys/kernel/debug/tracing/events/irq/irq_handler_exit/format +message IrqHandlerExitFormat { + int32 irq = 1; + int32 ret = 2; +} + +// /sys/kernel/debug/tracing/events/irq/softirq_entry/format +message SoftirqEntryFormat { + uint32 vec = 1; +} + +// /sys/kernel/debug/tracing/events/irq/softirq_exit/format +message SoftirqExitFormat { + uint32 vec = 1; +} + +// /sys/kernel/debug/tracing/events/irq/softirq_raise/format +message SoftirqRaiseFormat { + uint32 vec = 1; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/kmem.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/kmem.proto new file mode 100644 index 0000000000000000000000000000000000000000..51b7d49818bf0c51b463d641ccf495dbbb6907a4 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/kmem.proto @@ -0,0 +1,113 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: kmem +// /sys/kernel/debug/tracing/events/kmem/kfree/format +message KfreeFormat { + uint64 call_site = 1; + uint64 ptr = 2; +} + +// /sys/kernel/debug/tracing/events/kmem/kmalloc/format +message KmallocFormat { + uint64 call_site = 1; + uint64 ptr = 2; + uint64 bytes_req = 3; + uint64 bytes_alloc = 4; + uint32 gfp_flags = 5; +} + +// /sys/kernel/debug/tracing/events/kmem/kmalloc_node/format +message KmallocNodeFormat { + uint64 call_site = 1; + uint64 ptr = 2; + uint64 bytes_req = 3; + uint64 bytes_alloc = 4; + uint32 gfp_flags = 5; + int32 node = 6; +} + +// /sys/kernel/debug/tracing/events/kmem/kmem_cache_alloc/format +message KmemCacheAllocFormat { + uint64 call_site = 1; + uint64 ptr = 2; + uint64 bytes_req = 3; + uint64 bytes_alloc = 4; + uint32 gfp_flags = 5; +} + +// /sys/kernel/debug/tracing/events/kmem/kmem_cache_alloc_node/format +message KmemCacheAllocNodeFormat { + uint64 call_site = 1; + uint64 ptr = 2; + uint64 bytes_req = 3; + uint64 bytes_alloc = 4; + uint32 gfp_flags = 5; + int32 node = 6; +} + +// /sys/kernel/debug/tracing/events/kmem/kmem_cache_free/format +message KmemCacheFreeFormat { + uint64 call_site = 1; + uint64 ptr = 2; +} + +// /sys/kernel/debug/tracing/events/kmem/mm_page_alloc/format +message MmPageAllocFormat { + uint64 pfn = 1; + uint32 order = 2; + uint32 gfp_flags = 3; + int32 migratetype = 4; +} + +// /sys/kernel/debug/tracing/events/kmem/mm_page_alloc_extfrag/format +message MmPageAllocExtfragFormat { + uint64 pfn = 1; + int32 alloc_order = 2; + int32 fallback_order = 3; + int32 alloc_migratetype = 4; + int32 fallback_migratetype = 5; + int32 change_ownership = 6; +} + +// /sys/kernel/debug/tracing/events/kmem/mm_page_alloc_zone_locked/format +message MmPageAllocZoneLockedFormat { + uint64 pfn = 1; + uint32 order = 2; + int32 migratetype = 3; +} + +// /sys/kernel/debug/tracing/events/kmem/mm_page_free/format +message MmPageFreeFormat { + uint64 pfn = 1; + uint32 order = 2; +} + +// /sys/kernel/debug/tracing/events/kmem/mm_page_free_batched/format +message MmPageFreeBatchedFormat { + uint64 pfn = 1; +} + +// /sys/kernel/debug/tracing/events/kmem/mm_page_pcpu_drain/format +message MmPagePcpuDrainFormat { + uint64 pfn = 1; + uint32 order = 2; + int32 migratetype = 3; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/net.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/net.proto new file mode 100644 index 0000000000000000000000000000000000000000..c4b3c31fcf7a647765843c4d694dde9ace41f7fb --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/net.proto @@ -0,0 +1,185 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: net +// /sys/kernel/debug/tracing/events/net/napi_gro_frags_entry/format +message NapiGroFragsEntryFormat { + string name = 1; + uint32 napi_id = 2; + uint32 queue_mapping = 3; + uint64 skbaddr = 4; + uint32 vlan_tagged = 5; + uint32 vlan_proto = 6; + uint32 vlan_tci = 7; + uint32 protocol = 8; + uint32 ip_summed = 9; + uint32 hash = 10; + uint32 l4_hash = 11; + uint32 len = 12; + uint32 data_len = 13; + uint32 truesize = 14; + uint32 mac_header_valid = 15; + int32 mac_header = 16; + uint32 nr_frags = 17; + uint32 gso_size = 18; + uint32 gso_type = 19; +} + +// /sys/kernel/debug/tracing/events/net/napi_gro_receive_entry/format +message NapiGroReceiveEntryFormat { + string name = 1; + uint32 napi_id = 2; + uint32 queue_mapping = 3; + uint64 skbaddr = 4; + uint32 vlan_tagged = 5; + uint32 vlan_proto = 6; + uint32 vlan_tci = 7; + uint32 protocol = 8; + uint32 ip_summed = 9; + uint32 hash = 10; + uint32 l4_hash = 11; + uint32 len = 12; + uint32 data_len = 13; + uint32 truesize = 14; + uint32 mac_header_valid = 15; + int32 mac_header = 16; + uint32 nr_frags = 17; + uint32 gso_size = 18; + uint32 gso_type = 19; +} + +// /sys/kernel/debug/tracing/events/net/net_dev_queue/format +message NetDevQueueFormat { + uint64 skbaddr = 1; + uint32 len = 2; + string name = 3; +} + +// /sys/kernel/debug/tracing/events/net/net_dev_start_xmit/format +message NetDevStartXmitFormat { + string name = 1; + uint32 queue_mapping = 2; + uint64 skbaddr = 3; + uint32 vlan_tagged = 4; + uint32 vlan_proto = 5; + uint32 vlan_tci = 6; + uint32 protocol = 7; + uint32 ip_summed = 8; + uint32 len = 9; + uint32 data_len = 10; + int32 network_offset = 11; + uint32 transport_offset_valid = 12; + int32 transport_offset = 13; + uint32 tx_flags = 14; + uint32 gso_size = 15; + uint32 gso_segs = 16; + uint32 gso_type = 17; +} + +// /sys/kernel/debug/tracing/events/net/net_dev_xmit/format +message NetDevXmitFormat { + uint64 skbaddr = 1; + uint32 len = 2; + int32 rc = 3; + string name = 4; +} + +// /sys/kernel/debug/tracing/events/net/netif_receive_skb/format +message NetifReceiveSkbFormat { + uint64 skbaddr = 1; + uint32 len = 2; + string name = 3; +} + +// /sys/kernel/debug/tracing/events/net/netif_receive_skb_entry/format +message NetifReceiveSkbEntryFormat { + string name = 1; + uint32 napi_id = 2; + uint32 queue_mapping = 3; + uint64 skbaddr = 4; + uint32 vlan_tagged = 5; + uint32 vlan_proto = 6; + uint32 vlan_tci = 7; + uint32 protocol = 8; + uint32 ip_summed = 9; + uint32 hash = 10; + uint32 l4_hash = 11; + uint32 len = 12; + uint32 data_len = 13; + uint32 truesize = 14; + uint32 mac_header_valid = 15; + int32 mac_header = 16; + uint32 nr_frags = 17; + uint32 gso_size = 18; + uint32 gso_type = 19; +} + +// /sys/kernel/debug/tracing/events/net/netif_rx/format +message NetifRxFormat { + uint64 skbaddr = 1; + uint32 len = 2; + string name = 3; +} + +// /sys/kernel/debug/tracing/events/net/netif_rx_entry/format +message NetifRxEntryFormat { + string name = 1; + uint32 napi_id = 2; + uint32 queue_mapping = 3; + uint64 skbaddr = 4; + uint32 vlan_tagged = 5; + uint32 vlan_proto = 6; + uint32 vlan_tci = 7; + uint32 protocol = 8; + uint32 ip_summed = 9; + uint32 hash = 10; + uint32 l4_hash = 11; + uint32 len = 12; + uint32 data_len = 13; + uint32 truesize = 14; + uint32 mac_header_valid = 15; + int32 mac_header = 16; + uint32 nr_frags = 17; + uint32 gso_size = 18; + uint32 gso_type = 19; +} + +// /sys/kernel/debug/tracing/events/net/netif_rx_ni_entry/format +message NetifRxNiEntryFormat { + string name = 1; + uint32 napi_id = 2; + uint32 queue_mapping = 3; + uint64 skbaddr = 4; + uint32 vlan_tagged = 5; + uint32 vlan_proto = 6; + uint32 vlan_tci = 7; + uint32 protocol = 8; + uint32 ip_summed = 9; + uint32 hash = 10; + uint32 l4_hash = 11; + uint32 len = 12; + uint32 data_len = 13; + uint32 truesize = 14; + uint32 mac_header_valid = 15; + int32 mac_header = 16; + uint32 nr_frags = 17; + uint32 gso_size = 18; + uint32 gso_type = 19; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/oom.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/oom.proto new file mode 100644 index 0000000000000000000000000000000000000000..d7b6b9c60bb8b17f279c158396f78af802d5bdcc --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/oom.proto @@ -0,0 +1,27 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: oom +// /sys/kernel/debug/tracing/events/oom/oom_score_adj_update/format +message OomScoreAdjUpdateFormat { + int32 pid = 1; + string comm = 2; + int32 oom_score_adj = 3; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/pagemap.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/pagemap.proto new file mode 100644 index 0000000000000000000000000000000000000000..c931e12f275aead37148fc5395a94829b4d2153b --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/pagemap.proto @@ -0,0 +1,34 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: pagemap +// /sys/kernel/debug/tracing/events/pagemap/mm_lru_activate/format +message MmLruActivateFormat { + uint64 page = 1; + uint64 pfn = 2; +} + +// /sys/kernel/debug/tracing/events/pagemap/mm_lru_insertion/format +message MmLruInsertionFormat { + uint64 page = 1; + uint64 pfn = 2; + int32 lru = 3; + uint64 flags = 4; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/power.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/power.proto new file mode 100644 index 0000000000000000000000000000000000000000..3a223d1b3d640688eef81982287ec3fb99ba43dd --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/power.proto @@ -0,0 +1,175 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: power +// /sys/kernel/debug/tracing/events/power/clock_disable/format +message ClockDisableFormat { + string name = 1; + uint64 state = 2; + uint64 cpu_id = 3; +} + +// /sys/kernel/debug/tracing/events/power/clock_enable/format +message ClockEnableFormat { + string name = 1; + uint64 state = 2; + uint64 cpu_id = 3; +} + +// /sys/kernel/debug/tracing/events/power/clock_set_rate/format +message ClockSetRateFormat { + string name = 1; + uint64 state = 2; + uint64 cpu_id = 3; +} + +// /sys/kernel/debug/tracing/events/power/cpu_frequency/format +message CpuFrequencyFormat { + uint32 state = 1; + uint32 cpu_id = 2; +} + +// /sys/kernel/debug/tracing/events/power/cpu_frequency_limits/format +message CpuFrequencyLimitsFormat { + uint32 min_freq = 1; + uint32 max_freq = 2; + uint32 cpu_id = 3; +} + +// /sys/kernel/debug/tracing/events/power/cpu_idle/format +message CpuIdleFormat { + uint32 state = 1; + uint32 cpu_id = 2; +} + +// /sys/kernel/debug/tracing/events/power/dev_pm_qos_add_request/format +message DevPmQosAddRequestFormat { + string name = 1; + uint32 type = 2; + int32 new_value = 3; +} + +// /sys/kernel/debug/tracing/events/power/dev_pm_qos_remove_request/format +message DevPmQosRemoveRequestFormat { + string name = 1; + uint32 type = 2; + int32 new_value = 3; +} + +// /sys/kernel/debug/tracing/events/power/dev_pm_qos_update_request/format +message DevPmQosUpdateRequestFormat { + string name = 1; + uint32 type = 2; + int32 new_value = 3; +} + +// /sys/kernel/debug/tracing/events/power/device_pm_callback_end/format +message DevicePmCallbackEndFormat { + string device = 1; + string driver = 2; + int32 error = 3; +} + +// /sys/kernel/debug/tracing/events/power/device_pm_callback_start/format +message DevicePmCallbackStartFormat { + string device = 1; + string driver = 2; + string parent = 3; + string pm_ops = 4; + int32 event = 5; +} + +// /sys/kernel/debug/tracing/events/power/pm_qos_add_request/format +message PmQosAddRequestFormat { + int32 pm_qos_class = 1; + int32 value = 2; +} + +// /sys/kernel/debug/tracing/events/power/pm_qos_remove_request/format +message PmQosRemoveRequestFormat { + int32 pm_qos_class = 1; + int32 value = 2; +} + +// /sys/kernel/debug/tracing/events/power/pm_qos_update_flags/format +message PmQosUpdateFlagsFormat { + uint32 action = 1; + int32 prev_value = 2; + int32 curr_value = 3; +} + +// /sys/kernel/debug/tracing/events/power/pm_qos_update_request/format +message PmQosUpdateRequestFormat { + int32 pm_qos_class = 1; + int32 value = 2; +} + +// /sys/kernel/debug/tracing/events/power/pm_qos_update_request_timeout/format +message PmQosUpdateRequestTimeoutFormat { + int32 pm_qos_class = 1; + int32 value = 2; + uint64 timeout_us = 3; +} + +// /sys/kernel/debug/tracing/events/power/pm_qos_update_target/format +message PmQosUpdateTargetFormat { + uint32 action = 1; + int32 prev_value = 2; + int32 curr_value = 3; +} + +// /sys/kernel/debug/tracing/events/power/power_domain_target/format +message PowerDomainTargetFormat { + string name = 1; + uint64 state = 2; + uint64 cpu_id = 3; +} + +// /sys/kernel/debug/tracing/events/power/pstate_sample/format +message PstateSampleFormat { + uint32 core_busy = 1; + uint32 scaled_busy = 2; + uint32 from = 3; + uint32 to = 4; + uint64 mperf = 5; + uint64 aperf = 6; + uint64 tsc = 7; + uint32 freq = 8; + uint32 io_boost = 9; +} + +// /sys/kernel/debug/tracing/events/power/suspend_resume/format +message SuspendResumeFormat { + string action = 1; + int32 val = 2; + uint32 start = 3; +} + +// /sys/kernel/debug/tracing/events/power/wakeup_source_activate/format +message WakeupSourceActivateFormat { + string name = 1; + uint64 state = 2; +} + +// /sys/kernel/debug/tracing/events/power/wakeup_source_deactivate/format +message WakeupSourceDeactivateFormat { + string name = 1; + uint64 state = 2; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/printk.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/printk.proto new file mode 100644 index 0000000000000000000000000000000000000000..39be37e143ef980b271bb70391613cdd71966345 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/printk.proto @@ -0,0 +1,25 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: printk +// /sys/kernel/debug/tracing/events/printk/console/format +message ConsoleFormat { + string msg = 1; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/raw_syscalls.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/raw_syscalls.proto new file mode 100644 index 0000000000000000000000000000000000000000..590b964924c3d87e36e3e542eaf1fb891371f209 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/raw_syscalls.proto @@ -0,0 +1,32 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: raw_syscalls +// /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/format +message SysEnterFormat { + uint64 id = 1; + string args = 2; +} + +// /sys/kernel/debug/tracing/events/raw_syscalls/sys_exit/format +message SysExitFormat { + uint64 id = 1; + uint64 ret = 2; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/rcu.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/rcu.proto new file mode 100644 index 0000000000000000000000000000000000000000..5448d1e605bf867d5745d8aff4b391622b909490 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/rcu.proto @@ -0,0 +1,25 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: rcu +// /sys/kernel/debug/tracing/events/rcu/rcu_utilization/format +message RcuUtilizationFormat { + string s = 1; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/sched.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/sched.proto new file mode 100644 index 0000000000000000000000000000000000000000..173a30551837cc428549fff8f9773eeab63c7b07 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/sched.proto @@ -0,0 +1,206 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: sched +// /sys/kernel/debug/tracing/events/sched/sched_kthread_stop/format +message SchedKthreadStopFormat { + string comm = 1; + int32 pid = 2; +} + +// /sys/kernel/debug/tracing/events/sched/sched_kthread_stop_ret/format +message SchedKthreadStopRetFormat { + int32 ret = 1; +} + +// /sys/kernel/debug/tracing/events/sched/sched_migrate_task/format +message SchedMigrateTaskFormat { + string comm = 1; + int32 pid = 2; + int32 prio = 3; + int32 orig_cpu = 4; + int32 dest_cpu = 5; +} + +// /sys/kernel/debug/tracing/events/sched/sched_move_numa/format +message SchedMoveNumaFormat { + int32 pid = 1; + int32 tgid = 2; + int32 ngid = 3; + int32 src_cpu = 4; + int32 src_nid = 5; + int32 dst_cpu = 6; + int32 dst_nid = 7; +} + +// /sys/kernel/debug/tracing/events/sched/sched_pi_setprio/format +message SchedPiSetprioFormat { + string comm = 1; + int32 pid = 2; + int32 oldprio = 3; + int32 newprio = 4; +} + +// /sys/kernel/debug/tracing/events/sched/sched_process_exec/format +message SchedProcessExecFormat { + string filename = 1; + int32 pid = 2; + int32 old_pid = 3; +} + +// /sys/kernel/debug/tracing/events/sched/sched_process_exit/format +message SchedProcessExitFormat { + string comm = 1; + int32 pid = 2; + int32 prio = 3; +} + +// /sys/kernel/debug/tracing/events/sched/sched_process_fork/format +message SchedProcessForkFormat { + string parent_comm = 1; + int32 parent_pid = 2; + string child_comm = 3; + int32 child_pid = 4; +} + +// /sys/kernel/debug/tracing/events/sched/sched_process_free/format +message SchedProcessFreeFormat { + string comm = 1; + int32 pid = 2; + int32 prio = 3; +} + +// /sys/kernel/debug/tracing/events/sched/sched_process_wait/format +message SchedProcessWaitFormat { + string comm = 1; + int32 pid = 2; + int32 prio = 3; +} + +// /sys/kernel/debug/tracing/events/sched/sched_stat_blocked/format +message SchedStatBlockedFormat { + string comm = 1; + int32 pid = 2; + uint64 delay = 3; +} + +// /sys/kernel/debug/tracing/events/sched/sched_stat_iowait/format +message SchedStatIowaitFormat { + string comm = 1; + int32 pid = 2; + uint64 delay = 3; +} + +// /sys/kernel/debug/tracing/events/sched/sched_stat_runtime/format +message SchedStatRuntimeFormat { + string comm = 1; + int32 pid = 2; + uint64 runtime = 3; + uint64 vruntime = 4; +} + +// /sys/kernel/debug/tracing/events/sched/sched_stat_sleep/format +message SchedStatSleepFormat { + string comm = 1; + int32 pid = 2; + uint64 delay = 3; +} + +// /sys/kernel/debug/tracing/events/sched/sched_stat_wait/format +message SchedStatWaitFormat { + string comm = 1; + int32 pid = 2; + uint64 delay = 3; +} + +// /sys/kernel/debug/tracing/events/sched/sched_stick_numa/format +message SchedStickNumaFormat { + int32 pid = 1; + int32 tgid = 2; + int32 ngid = 3; + int32 src_cpu = 4; + int32 src_nid = 5; + int32 dst_cpu = 6; + int32 dst_nid = 7; +} + +// /sys/kernel/debug/tracing/events/sched/sched_swap_numa/format +message SchedSwapNumaFormat { + int32 src_pid = 1; + int32 src_tgid = 2; + int32 src_ngid = 3; + int32 src_cpu = 4; + int32 src_nid = 5; + int32 dst_pid = 6; + int32 dst_tgid = 7; + int32 dst_ngid = 8; + int32 dst_cpu = 9; + int32 dst_nid = 10; +} + +// /sys/kernel/debug/tracing/events/sched/sched_switch/format +message SchedSwitchFormat { + string prev_comm = 1; + int32 prev_pid = 2; + int32 prev_prio = 3; + uint64 prev_state = 4; + string next_comm = 5; + int32 next_pid = 6; + int32 next_prio = 7; +} + +// /sys/kernel/debug/tracing/events/sched/sched_wait_task/format +message SchedWaitTaskFormat { + string comm = 1; + int32 pid = 2; + int32 prio = 3; +} + +// /sys/kernel/debug/tracing/events/sched/sched_wake_idle_without_ipi/format +message SchedWakeIdleWithoutIpiFormat { + int32 cpu = 1; +} + +// /sys/kernel/debug/tracing/events/sched/sched_wakeup/format +message SchedWakeupFormat { + string comm = 1; + int32 pid = 2; + int32 prio = 3; + int32 success = 4; + int32 target_cpu = 5; +} + +// /sys/kernel/debug/tracing/events/sched/sched_wakeup_new/format +message SchedWakeupNewFormat { + string comm = 1; + int32 pid = 2; + int32 prio = 3; + int32 success = 4; + int32 target_cpu = 5; +} + +// /sys/kernel/debug/tracing/events/sched/sched_waking/format +message SchedWakingFormat { + string comm = 1; + int32 pid = 2; + int32 prio = 3; + int32 success = 4; + int32 target_cpu = 5; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/signal.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/signal.proto new file mode 100644 index 0000000000000000000000000000000000000000..01246e67df9f2004cd132d2b688a5de74174bae5 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/signal.proto @@ -0,0 +1,40 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: signal +// /sys/kernel/debug/tracing/events/signal/signal_deliver/format +message SignalDeliverFormat { + int32 sig = 1; + int32 error_code = 2; + int32 code = 3; + uint64 sig_handler = 4; + uint64 sig_flags = 5; +} + +// /sys/kernel/debug/tracing/events/signal/signal_generate/format +message SignalGenerateFormat { + int32 sig = 1; + int32 error_code = 2; + int32 code = 3; + string comm = 4; + int32 pid = 5; + int32 group = 6; + int32 result = 7; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/sunrpc.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/sunrpc.proto new file mode 100644 index 0000000000000000000000000000000000000000..35c4f67cb56077b32598918dd8dbede5dd329c4c --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/sunrpc.proto @@ -0,0 +1,247 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: sunrpc +// /sys/kernel/debug/tracing/events/sunrpc/rpc_bind_status/format +message RpcBindStatusFormat { + uint32 task_id = 1; + uint32 client_id = 2; + int32 status = 3; +} + +// /sys/kernel/debug/tracing/events/sunrpc/rpc_call_status/format +message RpcCallStatusFormat { + uint32 task_id = 1; + uint32 client_id = 2; + int32 status = 3; +} + +// /sys/kernel/debug/tracing/events/sunrpc/rpc_connect_status/format +message RpcConnectStatusFormat { + uint32 task_id = 1; + uint32 client_id = 2; + int32 status = 3; +} + +// /sys/kernel/debug/tracing/events/sunrpc/rpc_socket_close/format +message RpcSocketCloseFormat { + uint32 socket_state = 1; + uint32 sock_state = 2; + uint64 ino = 3; + string dstaddr = 4; + string dstport = 5; +} + +// /sys/kernel/debug/tracing/events/sunrpc/rpc_socket_connect/format +message RpcSocketConnectFormat { + int32 error = 1; + uint32 socket_state = 2; + uint32 sock_state = 3; + uint64 ino = 4; + string dstaddr = 5; + string dstport = 6; +} + +// /sys/kernel/debug/tracing/events/sunrpc/rpc_socket_error/format +message RpcSocketErrorFormat { + int32 error = 1; + uint32 socket_state = 2; + uint32 sock_state = 3; + uint64 ino = 4; + string dstaddr = 5; + string dstport = 6; +} + +// /sys/kernel/debug/tracing/events/sunrpc/rpc_socket_reset_connection/format +message RpcSocketResetConnectionFormat { + int32 error = 1; + uint32 socket_state = 2; + uint32 sock_state = 3; + uint64 ino = 4; + string dstaddr = 5; + string dstport = 6; +} + +// /sys/kernel/debug/tracing/events/sunrpc/rpc_socket_shutdown/format +message RpcSocketShutdownFormat { + uint32 socket_state = 1; + uint32 sock_state = 2; + uint64 ino = 3; + string dstaddr = 4; + string dstport = 5; +} + +// /sys/kernel/debug/tracing/events/sunrpc/rpc_socket_state_change/format +message RpcSocketStateChangeFormat { + uint32 socket_state = 1; + uint32 sock_state = 2; + uint64 ino = 3; + string dstaddr = 4; + string dstport = 5; +} + +// /sys/kernel/debug/tracing/events/sunrpc/rpc_task_begin/format +message RpcTaskBeginFormat { + uint32 task_id = 1; + uint32 client_id = 2; + uint64 action = 3; + uint64 runstate = 4; + int32 status = 5; + uint32 flags = 6; +} + +// /sys/kernel/debug/tracing/events/sunrpc/rpc_task_complete/format +message RpcTaskCompleteFormat { + uint32 task_id = 1; + uint32 client_id = 2; + uint64 action = 3; + uint64 runstate = 4; + int32 status = 5; + uint32 flags = 6; +} + +// /sys/kernel/debug/tracing/events/sunrpc/rpc_task_run_action/format +message RpcTaskRunActionFormat { + uint32 task_id = 1; + uint32 client_id = 2; + uint64 action = 3; + uint64 runstate = 4; + int32 status = 5; + uint32 flags = 6; +} + +// /sys/kernel/debug/tracing/events/sunrpc/rpc_task_sleep/format +message RpcTaskSleepFormat { + uint32 task_id = 1; + uint32 client_id = 2; + uint64 timeout = 3; + uint64 runstate = 4; + int32 status = 5; + uint32 flags = 6; + string q_name = 7; +} + +// /sys/kernel/debug/tracing/events/sunrpc/rpc_task_wakeup/format +message RpcTaskWakeupFormat { + uint32 task_id = 1; + uint32 client_id = 2; + uint64 timeout = 3; + uint64 runstate = 4; + int32 status = 5; + uint32 flags = 6; + string q_name = 7; +} + +// /sys/kernel/debug/tracing/events/sunrpc/svc_handle_xprt/format +message SvcHandleXprtFormat { + uint64 xprt = 1; + int32 len = 2; + uint64 flags = 3; + string addr = 4; +} + +// /sys/kernel/debug/tracing/events/sunrpc/svc_process/format +message SvcProcessFormat { + uint32 xid = 1; + uint32 vers = 2; + uint32 proc = 3; + string service = 4; + string addr = 5; +} + +// /sys/kernel/debug/tracing/events/sunrpc/svc_recv/format +message SvcRecvFormat { + uint32 xid = 1; + int32 len = 2; + uint64 flags = 3; + string addr = 4; +} + +// /sys/kernel/debug/tracing/events/sunrpc/svc_send/format +message SvcSendFormat { + uint32 xid = 1; + int32 status = 2; + uint64 flags = 3; + string addr = 4; +} + +// /sys/kernel/debug/tracing/events/sunrpc/svc_wake_up/format +message SvcWakeUpFormat { + int32 pid = 1; +} + +// /sys/kernel/debug/tracing/events/sunrpc/svc_xprt_dequeue/format +message SvcXprtDequeueFormat { + uint64 xprt = 1; + uint64 flags = 2; + uint64 wakeup = 3; + string addr = 4; +} + +// /sys/kernel/debug/tracing/events/sunrpc/svc_xprt_do_enqueue/format +message SvcXprtDoEnqueueFormat { + uint64 xprt = 1; + int32 pid = 2; + uint64 flags = 3; + string addr = 4; +} + +// /sys/kernel/debug/tracing/events/sunrpc/xprt_complete_rqst/format +message XprtCompleteRqstFormat { + uint32 xid = 1; + int32 status = 2; + string addr = 3; + string port = 4; +} + +// /sys/kernel/debug/tracing/events/sunrpc/xprt_lookup_rqst/format +message XprtLookupRqstFormat { + uint32 xid = 1; + int32 status = 2; + string addr = 3; + string port = 4; +} + +// /sys/kernel/debug/tracing/events/sunrpc/xprt_transmit/format +message XprtTransmitFormat { + uint32 xid = 1; + int32 status = 2; + string addr = 3; + string port = 4; +} + +// /sys/kernel/debug/tracing/events/sunrpc/xs_tcp_data_ready/format +message XsTcpDataReadyFormat { + int32 err = 1; + uint32 total = 2; + string addr = 3; + string port = 4; +} + +// /sys/kernel/debug/tracing/events/sunrpc/xs_tcp_data_recv/format +message XsTcpDataRecvFormat { + string addr = 1; + string port = 2; + uint32 xid = 3; + uint64 flags = 4; + uint64 copied = 5; + uint32 reclen = 6; + uint64 offset = 7; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/task.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/task.proto new file mode 100644 index 0000000000000000000000000000000000000000..82177f60b5bd3e1d62077d63627490c360280624 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/task.proto @@ -0,0 +1,36 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: task +// /sys/kernel/debug/tracing/events/task/task_newtask/format +message TaskNewtaskFormat { + int32 pid = 1; + string comm = 2; + uint64 clone_flags = 3; + int32 oom_score_adj = 4; +} + +// /sys/kernel/debug/tracing/events/task/task_rename/format +message TaskRenameFormat { + int32 pid = 1; + string oldcomm = 2; + string newcomm = 3; + int32 oom_score_adj = 4; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/timer.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/timer.proto new file mode 100644 index 0000000000000000000000000000000000000000..d85b207f4e7532ea457dbc8b054fd594115c513c --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/timer.proto @@ -0,0 +1,101 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: timer +// /sys/kernel/debug/tracing/events/timer/hrtimer_cancel/format +message HrtimerCancelFormat { + uint64 hrtimer = 1; +} + +// /sys/kernel/debug/tracing/events/timer/hrtimer_expire_entry/format +message HrtimerExpireEntryFormat { + uint64 hrtimer = 1; + int64 now = 2; + uint64 function = 3; +} + +// /sys/kernel/debug/tracing/events/timer/hrtimer_expire_exit/format +message HrtimerExpireExitFormat { + uint64 hrtimer = 1; +} + +// /sys/kernel/debug/tracing/events/timer/hrtimer_init/format +message HrtimerInitFormat { + uint64 hrtimer = 1; + int32 clockid = 2; + uint32 mode = 3; +} + +// /sys/kernel/debug/tracing/events/timer/hrtimer_start/format +message HrtimerStartFormat { + uint64 hrtimer = 1; + uint64 function = 2; + int64 expires = 3; + int64 softexpires = 4; + uint32 mode = 5; +} + +// /sys/kernel/debug/tracing/events/timer/itimer_expire/format +message ItimerExpireFormat { + int32 which = 1; + int32 pid = 2; + uint64 now = 3; +} + +// /sys/kernel/debug/tracing/events/timer/itimer_state/format +message ItimerStateFormat { + int32 which = 1; + uint64 expires = 2; + uint64 value_sec = 3; + uint64 value_usec = 4; + uint64 interval_sec = 5; + uint64 interval_usec = 6; +} + +// /sys/kernel/debug/tracing/events/timer/timer_cancel/format +message TimerCancelFormat { + uint64 timer = 1; +} + +// /sys/kernel/debug/tracing/events/timer/timer_expire_entry/format +message TimerExpireEntryFormat { + uint64 timer = 1; + uint64 now = 2; + uint64 function = 3; +} + +// /sys/kernel/debug/tracing/events/timer/timer_expire_exit/format +message TimerExpireExitFormat { + uint64 timer = 1; +} + +// /sys/kernel/debug/tracing/events/timer/timer_init/format +message TimerInitFormat { + uint64 timer = 1; +} + +// /sys/kernel/debug/tracing/events/timer/timer_start/format +message TimerStartFormat { + uint64 timer = 1; + uint64 function = 2; + uint64 expires = 3; + uint64 now = 4; + uint32 flags = 5; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/trace_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/trace_plugin_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..e56265861500c204d39f398e9e674eaaafcb2f25 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/trace_plugin_config.proto @@ -0,0 +1,28 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; +option optimize_for = LITE_RUNTIME; + +message TracePluginConfig { + repeated string ftrace_events = 1; + repeated string bytrace_categories = 2; + repeated string bytrace_apps = 3; + uint32 buffer_size_kb = 4; // for ftrace procfs + uint32 flush_interval_ms = 5; + uint32 flush_threshold_kb = 6; + bool parse_ksyms = 7; // enable /proc/kallsyms parser + string clock = 8; + uint32 trace_period_ms = 10; + string raw_data_prefix = 13; +} diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/trace_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/trace_plugin_result.proto new file mode 100644 index 0000000000000000000000000000000000000000..96476feea7211c28e737ede7ec903f924075ac86 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/trace_plugin_result.proto @@ -0,0 +1,80 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +import "ftrace_event.proto"; + +option optimize_for = LITE_RUNTIME; + +message TracePluginResult { + repeated FtraceCpuStatsMsg ftrace_cpu_stats = 1; + repeated FtraceCpuDetailMsg ftrace_cpu_detail = 2; + repeated SymbolsDetailMsg symbols_detail = 5; + repeated ClockDetailMsg clocks_detail = 6; +} + +message ClockDetailMsg { + // man clock_gettime + enum ClockId { + UNKNOW = 0; + BOOTTIME = 1; + REALTIME = 2; + REALTIME_COARSE = 3; + MONOTONIC = 4; + MONOTONIC_COARSE = 5; + MONOTONIC_RAW = 6; + } + ClockId id = 1; + message TimeSpec { + uint32 tv_sec = 1; + uint32 tv_nsec = 2; + }; + TimeSpec time = 2; + TimeSpec resolution = 3; +}; + +message SymbolsDetailMsg { + uint64 symbol_addr = 1; // symbol address + string symbol_name = 2; // symbol name +} + +message FtraceCpuStatsMsg { + enum Status { + TRACE_START = 0; + TRACE_END = 1; + } + + Status status = 1; + repeated PerCpuStatsMsg per_cpu_stats = 2; + string trace_clock = 3; +} + +// cat /sys/kernel/debug/tracing/per_cpu/cpu0/stats +message PerCpuStatsMsg { + uint64 cpu = 1; + uint64 entries = 2; + uint64 overrun = 3; + uint64 commit_overrun = 4; + uint64 bytes = 5; + double oldest_event_ts = 6; + double now_ts = 7; + uint64 dropped_events = 8; + uint64 read_events = 9; +} + +message FtraceCpuDetailMsg { + uint32 cpu = 1; + repeated FtraceEvent event = 2; + uint64 overwrite = 3; +} diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/v4l2.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/v4l2.proto new file mode 100644 index 0000000000000000000000000000000000000000..7ca31b507160e8a66bd9ddeb1b485d957dcb6c50 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/v4l2.proto @@ -0,0 +1,140 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: v4l2 +// /sys/kernel/debug/tracing/events/v4l2/v4l2_dqbuf/format +message V4l2DqbufFormat { + int32 minor = 1; + uint32 index = 2; + uint32 type = 3; + uint32 bytesused = 4; + uint32 flags = 5; + uint32 field = 6; + int64 timestamp = 7; + uint32 timecode_type = 8; + uint32 timecode_flags = 9; + uint32 timecode_frames = 10; + uint32 timecode_seconds = 11; + uint32 timecode_minutes = 12; + uint32 timecode_hours = 13; + uint32 timecode_userbits0 = 14; + uint32 timecode_userbits1 = 15; + uint32 timecode_userbits2 = 16; + uint32 timecode_userbits3 = 17; + uint32 sequence = 18; +} + +// /sys/kernel/debug/tracing/events/v4l2/v4l2_qbuf/format +message V4l2QbufFormat { + int32 minor = 1; + uint32 index = 2; + uint32 type = 3; + uint32 bytesused = 4; + uint32 flags = 5; + uint32 field = 6; + int64 timestamp = 7; + uint32 timecode_type = 8; + uint32 timecode_flags = 9; + uint32 timecode_frames = 10; + uint32 timecode_seconds = 11; + uint32 timecode_minutes = 12; + uint32 timecode_hours = 13; + uint32 timecode_userbits0 = 14; + uint32 timecode_userbits1 = 15; + uint32 timecode_userbits2 = 16; + uint32 timecode_userbits3 = 17; + uint32 sequence = 18; +} + +// /sys/kernel/debug/tracing/events/v4l2/vb2_v4l2_buf_done/format +message Vb2V4l2BufDoneFormat { + int32 minor = 1; + uint32 flags = 2; + uint32 field = 3; + uint64 timestamp = 4; + uint32 timecode_type = 5; + uint32 timecode_flags = 6; + uint32 timecode_frames = 7; + uint32 timecode_seconds = 8; + uint32 timecode_minutes = 9; + uint32 timecode_hours = 10; + uint32 timecode_userbits0 = 11; + uint32 timecode_userbits1 = 12; + uint32 timecode_userbits2 = 13; + uint32 timecode_userbits3 = 14; + uint32 sequence = 15; +} + +// /sys/kernel/debug/tracing/events/v4l2/vb2_v4l2_buf_queue/format +message Vb2V4l2BufQueueFormat { + int32 minor = 1; + uint32 flags = 2; + uint32 field = 3; + uint64 timestamp = 4; + uint32 timecode_type = 5; + uint32 timecode_flags = 6; + uint32 timecode_frames = 7; + uint32 timecode_seconds = 8; + uint32 timecode_minutes = 9; + uint32 timecode_hours = 10; + uint32 timecode_userbits0 = 11; + uint32 timecode_userbits1 = 12; + uint32 timecode_userbits2 = 13; + uint32 timecode_userbits3 = 14; + uint32 sequence = 15; +} + +// /sys/kernel/debug/tracing/events/v4l2/vb2_v4l2_dqbuf/format +message Vb2V4l2DqbufFormat { + int32 minor = 1; + uint32 flags = 2; + uint32 field = 3; + uint64 timestamp = 4; + uint32 timecode_type = 5; + uint32 timecode_flags = 6; + uint32 timecode_frames = 7; + uint32 timecode_seconds = 8; + uint32 timecode_minutes = 9; + uint32 timecode_hours = 10; + uint32 timecode_userbits0 = 11; + uint32 timecode_userbits1 = 12; + uint32 timecode_userbits2 = 13; + uint32 timecode_userbits3 = 14; + uint32 sequence = 15; +} + +// /sys/kernel/debug/tracing/events/v4l2/vb2_v4l2_qbuf/format +message Vb2V4l2QbufFormat { + int32 minor = 1; + uint32 flags = 2; + uint32 field = 3; + uint64 timestamp = 4; + uint32 timecode_type = 5; + uint32 timecode_flags = 6; + uint32 timecode_frames = 7; + uint32 timecode_seconds = 8; + uint32 timecode_minutes = 9; + uint32 timecode_hours = 10; + uint32 timecode_userbits0 = 11; + uint32 timecode_userbits1 = 12; + uint32 timecode_userbits2 = 13; + uint32 timecode_userbits3 = 14; + uint32 sequence = 15; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/vmscan.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/vmscan.proto new file mode 100644 index 0000000000000000000000000000000000000000..c9f1867f74c298e46b96323be93926d24cf1c0d7 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/vmscan.proto @@ -0,0 +1,111 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: vmscan +// /sys/kernel/debug/tracing/events/vmscan/mm_shrink_slab_end/format +message MmShrinkSlabEndFormat { + uint64 shr = 1; + int32 nid = 2; + uint64 shrink = 3; + uint64 unused_scan = 4; + uint64 new_scan = 5; + int32 retval = 6; + uint64 total_scan = 7; +} + +// /sys/kernel/debug/tracing/events/vmscan/mm_shrink_slab_start/format +message MmShrinkSlabStartFormat { + uint64 shr = 1; + uint64 shrink = 2; + int32 nid = 3; + uint64 nr_objects_to_shrink = 4; + uint32 gfp_flags = 5; + uint64 cache_items = 6; + uint64 delta = 7; + uint64 total_scan = 8; + int32 priority = 9; +} + +// /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/format +message MmVmscanDirectReclaimBeginFormat { + int32 order = 1; + int32 may_writepage = 2; + uint32 gfp_flags = 3; + int32 classzone_idx = 4; +} + +// /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_end/format +message MmVmscanDirectReclaimEndFormat { + uint64 nr_reclaimed = 1; +} + +// /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep/format +message MmVmscanKswapdSleepFormat { + int32 nid = 1; +} + +// /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake/format +message MmVmscanKswapdWakeFormat { + int32 nid = 1; + int32 zid = 2; + int32 order = 3; +} + +// /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_lru_isolate/format +message MmVmscanLruIsolateFormat { + int32 classzone_idx = 1; + int32 order = 2; + uint64 nr_requested = 3; + uint64 nr_scanned = 4; + uint64 nr_skipped = 5; + uint64 nr_taken = 6; + uint32 isolate_mode = 7; + int32 lru = 8; +} + +// /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_lru_shrink_inactive/format +message MmVmscanLruShrinkInactiveFormat { + int32 nid = 1; + uint64 nr_scanned = 2; + uint64 nr_reclaimed = 3; + uint64 nr_dirty = 4; + uint64 nr_writeback = 5; + uint64 nr_congested = 6; + uint64 nr_immediate = 7; + uint64 nr_activate = 8; + uint64 nr_ref_keep = 9; + uint64 nr_unmap_fail = 10; + int32 priority = 11; + int32 reclaim_flags = 12; +} + +// /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_wakeup_kswapd/format +message MmVmscanWakeupKswapdFormat { + int32 nid = 1; + int32 zid = 2; + int32 order = 3; + uint32 gfp_flags = 4; +} + +// /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_writepage/format +message MmVmscanWritepageFormat { + uint64 pfn = 1; + int32 reclaim_flags = 2; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/workqueue.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/workqueue.proto new file mode 100644 index 0000000000000000000000000000000000000000..040e5abf1bfc038ee0be5ea33de0c25e4bcfd68c --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/workqueue.proto @@ -0,0 +1,45 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: workqueue +// /sys/kernel/debug/tracing/events/workqueue/workqueue_activate_work/format +message WorkqueueActivateWorkFormat { + uint64 work = 1; +} + +// /sys/kernel/debug/tracing/events/workqueue/workqueue_execute_end/format +message WorkqueueExecuteEndFormat { + uint64 work = 1; +} + +// /sys/kernel/debug/tracing/events/workqueue/workqueue_execute_start/format +message WorkqueueExecuteStartFormat { + uint64 work = 1; + uint64 function = 2; +} + +// /sys/kernel/debug/tracing/events/workqueue/workqueue_queue_work/format +message WorkqueueQueueWorkFormat { + uint64 work = 1; + uint64 function = 2; + uint64 workqueue = 3; + uint32 req_cpu = 4; + uint32 cpu = 5; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/writeback.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/writeback.proto new file mode 100644 index 0000000000000000000000000000000000000000..fdf2bdb1002df4a7593eff0e1725366237357420 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/writeback.proto @@ -0,0 +1,288 @@ +// THIS FILE IS GENERATED BY ftrace_proto_generator.py, PLEASE DON'T EDIT IT! +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +option optimize_for = LITE_RUNTIME; + +// category: writeback +// /sys/kernel/debug/tracing/events/writeback/balance_dirty_pages/format +message BalanceDirtyPagesFormat { + string bdi = 1; + uint64 limit = 2; + uint64 setpoint = 3; + uint64 dirty = 4; + uint64 bdi_setpoint = 5; + uint64 bdi_dirty = 6; + uint64 dirty_ratelimit = 7; + uint64 task_ratelimit = 8; + uint32 dirtied = 9; + uint32 dirtied_pause = 10; + uint64 paused = 11; + uint64 pause = 12; + uint64 period = 13; + uint64 think = 14; + uint32 cgroup_ino = 15; +} + +// /sys/kernel/debug/tracing/events/writeback/bdi_dirty_ratelimit/format +message BdiDirtyRatelimitFormat { + string bdi = 1; + uint64 write_bw = 2; + uint64 avg_write_bw = 3; + uint64 dirty_rate = 4; + uint64 dirty_ratelimit = 5; + uint64 task_ratelimit = 6; + uint64 balanced_dirty_ratelimit = 7; + uint32 cgroup_ino = 8; +} + +// /sys/kernel/debug/tracing/events/writeback/global_dirty_state/format +message GlobalDirtyStateFormat { + uint64 nr_dirty = 1; + uint64 nr_writeback = 2; + uint64 nr_unstable = 3; + uint64 background_thresh = 4; + uint64 dirty_thresh = 5; + uint64 dirty_limit = 6; + uint64 nr_dirtied = 7; + uint64 nr_written = 8; +} + +// /sys/kernel/debug/tracing/events/writeback/wbc_writepage/format +message WbcWritepageFormat { + string name = 1; + uint64 nr_to_write = 2; + uint64 pages_skipped = 3; + int32 sync_mode = 4; + int32 for_kupdate = 5; + int32 for_background = 6; + int32 for_reclaim = 7; + int32 range_cyclic = 8; + uint64 range_start = 9; + uint64 range_end = 10; + uint32 cgroup_ino = 11; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_bdi_register/format +message WritebackBdiRegisterFormat { + string name = 1; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_congestion_wait/format +message WritebackCongestionWaitFormat { + uint32 usec_timeout = 1; + uint32 usec_delayed = 2; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_dirty_inode/format +message WritebackDirtyInodeFormat { + string name = 1; + uint64 ino = 2; + uint64 state = 3; + uint64 flags = 4; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_dirty_inode_enqueue/format +message WritebackDirtyInodeEnqueueFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 state = 3; + uint32 mode = 4; + uint64 dirtied_when = 5; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_dirty_inode_start/format +message WritebackDirtyInodeStartFormat { + string name = 1; + uint64 ino = 2; + uint64 state = 3; + uint64 flags = 4; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_dirty_page/format +message WritebackDirtyPageFormat { + string name = 1; + uint64 ino = 2; + uint64 index = 3; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_exec/format +message WritebackExecFormat { + string name = 1; + uint64 nr_pages = 2; + uint64 sb_dev = 3; + int32 sync_mode = 4; + int32 for_kupdate = 5; + int32 range_cyclic = 6; + int32 for_background = 7; + int32 reason = 8; + uint32 cgroup_ino = 9; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_lazytime/format +message WritebackLazytimeFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 state = 3; + uint32 mode = 4; + uint64 dirtied_when = 5; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_lazytime_iput/format +message WritebackLazytimeIputFormat { + uint64 dev = 1; + uint64 ino = 2; + uint64 state = 3; + uint32 mode = 4; + uint64 dirtied_when = 5; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_mark_inode_dirty/format +message WritebackMarkInodeDirtyFormat { + string name = 1; + uint64 ino = 2; + uint64 state = 3; + uint64 flags = 4; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_pages_written/format +message WritebackPagesWrittenFormat { + uint64 pages = 1; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_queue/format +message WritebackQueueFormat { + string name = 1; + uint64 nr_pages = 2; + uint64 sb_dev = 3; + int32 sync_mode = 4; + int32 for_kupdate = 5; + int32 range_cyclic = 6; + int32 for_background = 7; + int32 reason = 8; + uint32 cgroup_ino = 9; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_queue_io/format +message WritebackQueueIoFormat { + string name = 1; + uint64 older = 2; + uint64 age = 3; + int32 moved = 4; + int32 reason = 5; + uint32 cgroup_ino = 6; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_sb_inodes_requeue/format +message WritebackSbInodesRequeueFormat { + string name = 1; + uint64 ino = 2; + uint64 state = 3; + uint64 dirtied_when = 4; + uint32 cgroup_ino = 5; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_single_inode/format +message WritebackSingleInodeFormat { + string name = 1; + uint64 ino = 2; + uint64 state = 3; + uint64 dirtied_when = 4; + uint64 writeback_index = 5; + uint64 nr_to_write = 6; + uint64 wrote = 7; + uint32 cgroup_ino = 8; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_single_inode_start/format +message WritebackSingleInodeStartFormat { + string name = 1; + uint64 ino = 2; + uint64 state = 3; + uint64 dirtied_when = 4; + uint64 writeback_index = 5; + uint64 nr_to_write = 6; + uint64 wrote = 7; + uint32 cgroup_ino = 8; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_start/format +message WritebackStartFormat { + string name = 1; + uint64 nr_pages = 2; + uint64 sb_dev = 3; + int32 sync_mode = 4; + int32 for_kupdate = 5; + int32 range_cyclic = 6; + int32 for_background = 7; + int32 reason = 8; + uint32 cgroup_ino = 9; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_wait/format +message WritebackWaitFormat { + string name = 1; + uint64 nr_pages = 2; + uint64 sb_dev = 3; + int32 sync_mode = 4; + int32 for_kupdate = 5; + int32 range_cyclic = 6; + int32 for_background = 7; + int32 reason = 8; + uint32 cgroup_ino = 9; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_wait_iff_congested/format +message WritebackWaitIffCongestedFormat { + uint32 usec_timeout = 1; + uint32 usec_delayed = 2; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_wake_background/format +message WritebackWakeBackgroundFormat { + string name = 1; + uint32 cgroup_ino = 2; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_write_inode/format +message WritebackWriteInodeFormat { + string name = 1; + uint64 ino = 2; + int32 sync_mode = 3; + uint32 cgroup_ino = 4; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_write_inode_start/format +message WritebackWriteInodeStartFormat { + string name = 1; + uint64 ino = 2; + int32 sync_mode = 3; + uint32 cgroup_ino = 4; +} + +// /sys/kernel/debug/tracing/events/writeback/writeback_written/format +message WritebackWrittenFormat { + string name = 1; + uint64 nr_pages = 2; + uint64 sb_dev = 3; + int32 sync_mode = 4; + int32 for_kupdate = 5; + int32 range_cyclic = 6; + int32 for_background = 7; + int32 reason = 8; + uint32 cgroup_ino = 9; +} + diff --git a/host/trace_streamer/src/protos/types/plugins/hidump_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/hidump_data/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..966f0221992e6c15113cfb529b7e33e98f27eaa8 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/hidump_data/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../protos.gni") + +hidump_data_sources = [ + "./hidump_plugin_config.proto", + "./hidump_plugin_result.proto", +] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) + +hidump_data_codegen = [] +foreach(proto, hidump_data_sources) { + name = get_path_info(proto, "name") + hidump_data_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] +} + +config("hidump_include_config") { + include_dirs = [ "$proto_out_dir" ] +} + +####################################################### +action("hidump_data_cpp_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = hidump_data_sources + outputs = hidump_data_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +ohos_source_set("hidump_data_cpp") { + deps = [ ":hidump_data_cpp_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":hidump_include_config" ] + sources = hidump_data_codegen +} diff --git a/host/trace_streamer/src/protos/types/plugins/hidump_data/hidump_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/hidump_data/hidump_plugin_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..46e33f6a89516b63123fb03cea6252c6900a5543 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/hidump_data/hidump_plugin_config.proto @@ -0,0 +1,20 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +syntax = "proto3"; +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + + +message HidumpConfig { + bool report_fps = 1; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/hidump_data/hidump_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/hidump_data/hidump_plugin_result.proto new file mode 100644 index 0000000000000000000000000000000000000000..5cf6e5534268dd72699a0384e3779615ff0ee77e --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/hidump_data/hidump_plugin_result.proto @@ -0,0 +1,39 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +syntax = "proto3"; +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + + +message FpsData { + enum ClockId { + UNKNOW = 0; + BOOTTIME = 1; + REALTIME = 2; + REALTIME_COARSE = 3; + MONOTONIC = 4; + MONOTONIC_COARSE = 5; + MONOTONIC_RAW = 6; + } + ClockId id = 1; + message TimeSpec { + uint32 tv_sec = 1; + uint32 tv_nsec = 2; + }; + TimeSpec time = 2; + uint32 fps = 3; +} + +message HidumpInfo { + repeated FpsData fps_event = 1; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/hilog_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/hilog_data/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..e040bbf78a80b7dbdd2535c18753d0db2fc83fbf --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/hilog_data/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../protos.gni") + +hilog_data_sources = [ + "./hilog_plugin_config.proto", + "./hilog_plugin_result.proto", +] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) + +hilog_data_codegen = [] +foreach(proto, hilog_data_sources) { + name = get_path_info(proto, "name") + hilog_data_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] +} + +config("hilog_include_config") { + include_dirs = [ "$proto_out_dir" ] +} + +####################################################### +action("hilog_data_cpp_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = hilog_data_sources + outputs = hilog_data_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +ohos_source_set("hilog_data_cpp") { + deps = [ ":hilog_data_cpp_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":hilog_include_config" ] + sources = hilog_data_codegen +} diff --git a/host/trace_streamer/src/protos/types/plugins/hilog_data/hilog_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/hilog_data/hilog_plugin_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..1b1872474f4bdc4d2f18284015dc6aabbb359b75 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/hilog_data/hilog_plugin_config.proto @@ -0,0 +1,38 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +syntax = "proto3"; +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +enum Type { + TYPE_UNSPECIFIED = 0; + HI3516 = 1; + P40 = 2; +} + +enum Level { + LEVEL_UNSPECIFIED = 0; + ERROR = 1; + INFO = 2; + DEBUG = 3; + WARN = 4; +} + +message HilogConfig { + Type device_type = 1; + Level log_level = 2; + + int32 pid = 3; + bool need_record = 4; + bool need_clear = 5; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/hilog_data/hilog_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/hilog_data/hilog_plugin_result.proto new file mode 100644 index 0000000000000000000000000000000000000000..64e678def7dcc24176e55185be17027c34c0d15c --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/hilog_data/hilog_plugin_result.proto @@ -0,0 +1,36 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +syntax = "proto3"; +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message HilogDetails { + // log time + uint64 tv_sec = 1; + uint64 tv_nsec = 2; + uint32 pid = 3; + uint32 tid = 4; + uint32 level = 5; + string tag = 6; +} + +message HilogLine { + HilogDetails detail = 1; + string context = 2; + uint64 id = 3; +} + +message HilogInfo { + repeated HilogLine info = 1; + uint32 clock = 2; // 空值 +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..fb8d3da2111f79cb69b85e58898e5c2892a77512 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../protos.gni") + +hiperf_call_plugin_protos_defines = [ "./hiperf_call_plugin_config.proto" ] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) +print("proto_out_dir", proto_out_dir, proto_rel_out_dir) + +####################################################### +hiperf_call_plugin_protos_codegen = [] +foreach(proto, hiperf_call_plugin_protos_defines) { + name = get_path_info(proto, "name") + hiperf_call_plugin_protos_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] +} + +action("hiperf_call_plugin_protos_protoc") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = hiperf_call_plugin_protos_defines + outputs = hiperf_call_plugin_protos_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +config("hiperf_call_plugin_protos_config") { + include_dirs = [ "$proto_out_dir" ] +} + +ohos_source_set("hiperf_call_plugin_protos_cpp") { + deps = [ ":hiperf_call_plugin_protos_protoc" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":hiperf_call_plugin_protos_config" ] + sources = hiperf_call_plugin_protos_codegen +} diff --git a/host/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/hiperf_call_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/hiperf_call_plugin_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..e11b279f296a3ebf0b5bc52ce51b0fd88311ccc7 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/hiperf_call_plugin_config.proto @@ -0,0 +1,26 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; +option optimize_for = LITE_RUNTIME; + +message HiperfCallPluginConfig { + int32 pid = 1; // pid of app. + string app_name = 2; // app name. + string outfile = 4; // the name of the output target file. + + uint32 frequency = 3; // Set the counts of dumpping records per second, default 1000. + bool is_trace = 5; // Set if using --trace-offcpu, default true. + bool is_root = 6; // Set if using root privilege, default true. + bool is_emulator = 7; // Set if the device is emulator, default false. +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/memory_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/memory_data/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..a1b679a22fe78d4fa73cc084a28e7b9f14711222 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/memory_data/BUILD.gn @@ -0,0 +1,66 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../protos.gni") + +memory_data_sources = [ + "./memory_plugin_common.proto", + "./memory_plugin_config.proto", + "./memory_plugin_result.proto", +] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) + +memory_data_codegen = [] +foreach(proto, memory_data_sources) { + name = get_path_info(proto, "name") + memory_data_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] +} + +config("memory_include_config") { + include_dirs = [ "$proto_out_dir" ] +} + +####################################################### +action("memory_data_cpp_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = memory_data_sources + outputs = memory_data_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +ohos_source_set("memory_data_cpp") { + deps = [ ":memory_data_cpp_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":memory_include_config" ] + sources = memory_data_codegen +} diff --git a/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_common.proto b/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_common.proto new file mode 100644 index 0000000000000000000000000000000000000000..1dac1d9a9c82ae6870413051f5c4d02b7fa7b43d --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_common.proto @@ -0,0 +1,187 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +// Common define for memory plug-in, imported by memory data and config proto file. +enum SysMeminfoType { + PMEM_UNSPECIFIED = 0; + PMEM_MEM_TOTAL = 1; + PMEM_MEM_FREE = 2; + PMEM_MEM_AVAILABLE = 3; + PMEM_BUFFERS = 4; + PMEM_CACHED = 5; + PMEM_SWAP_CACHED = 6; + PMEM_ACTIVE = 7; + PMEM_INACTIVE = 8; + PMEM_ACTIVE_ANON = 9; + PMEM_INACTIVE_ANON = 10; + PMEM_ACTIVE_FILE = 11; + PMEM_INACTIVE_FILE = 12; + PMEM_UNEVICTABLE = 13; + PMEM_MLOCKED = 14; + PMEM_SWAP_TOTAL = 15; + PMEM_SWAP_FREE = 16; + PMEM_DIRTY = 17; + PMEM_WRITEBACK = 18; + PMEM_ANON_PAGES = 19; + PMEM_MAPPED = 20; + PMEM_SHMEM = 21; + PMEM_SLAB = 22; + PMEM_SLAB_RECLAIMABLE = 23; + PMEM_SLAB_UNRECLAIMABLE = 24; + PMEM_KERNEL_STACK = 25; + PMEM_PAGE_TABLES = 26; + PMEM_COMMIT_LIMIT = 27; + PMEM_COMMITED_AS = 28; + PMEM_VMALLOC_TOTAL = 29; + PMEM_VMALLOC_USED = 30; + PMEM_VMALLOC_CHUNK = 31; + PMEM_CMA_TOTAL = 32; + PMEM_CMA_FREE = 33; +} + +enum SysVMeminfoType { + VMEMINFO_UNSPECIFIED = 0; + VMEMINFO_NR_FREE_PAGES = 1; + VMEMINFO_NR_ALLOC_BATCH = 2; + VMEMINFO_NR_INACTIVE_ANON = 3; + VMEMINFO_NR_ACTIVE_ANON = 4; + VMEMINFO_NR_INACTIVE_FILE = 5; + VMEMINFO_NR_ACTIVE_FILE = 6; + VMEMINFO_NR_UNEVICTABLE = 7; + VMEMINFO_NR_MLOCK = 8; + VMEMINFO_NR_ANON_PAGES = 9; + VMEMINFO_NR_MAPPED = 10; + VMEMINFO_NR_FILE_PAGES = 11; + VMEMINFO_NR_DIRTY = 12; + VMEMINFO_NR_WRITEBACK = 13; + VMEMINFO_NR_SLAB_RECLAIMABLE = 14; + VMEMINFO_NR_SLAB_UNRECLAIMABLE = 15; + VMEMINFO_NR_PAGE_TABLE_PAGES = 16; + VMEMINFO_NR_KERNEL_STACK = 17; + VMEMINFO_NR_OVERHEAD = 18; + VMEMINFO_NR_UNSTABLE = 19; + VMEMINFO_NR_BOUNCE = 20; + VMEMINFO_NR_VMSCAN_WRITE = 21; + VMEMINFO_NR_VMSCAN_IMMEDIATE_RECLAIM = 22; + VMEMINFO_NR_WRITEBACK_TEMP = 23; + VMEMINFO_NR_ISOLATED_ANON = 24; + VMEMINFO_NR_ISOLATED_FILE = 25; + VMEMINFO_NR_SHMEM = 26; + VMEMINFO_NR_DIRTIED = 27; + VMEMINFO_NR_WRITTEN = 28; + VMEMINFO_NR_PAGES_SCANNED = 29; + VMEMINFO_WORKINGSET_REFAULT = 30; + VMEMINFO_WORKINGSET_ACTIVATE = 31; + VMEMINFO_WORKINGSET_NODERECLAIM = 32; + VMEMINFO_NR_ANON_TRANSPARENT_HUGEPAGES = 33; + VMEMINFO_NR_FREE_CMA = 34; + VMEMINFO_NR_SWAPCACHE = 35; + VMEMINFO_NR_DIRTY_THRESHOLD = 36; + VMEMINFO_NR_DIRTY_BACKGROUND_THRESHOLD = 37; + VMEMINFO_PGPGIN = 38; + VMEMINFO_PGPGOUT = 39; + VMEMINFO_PGPGOUTCLEAN = 40; + VMEMINFO_PSWPIN = 41; + VMEMINFO_PSWPOUT = 42; + VMEMINFO_PGALLOC_DMA = 43; + VMEMINFO_PGALLOC_NORMAL = 44; + VMEMINFO_PGALLOC_MOVABLE = 45; + VMEMINFO_PGFREE = 46; + VMEMINFO_PGACTIVATE = 47; + VMEMINFO_PGDEACTIVATE = 48; + VMEMINFO_PGFAULT = 49; + VMEMINFO_PGMAJFAULT = 50; + VMEMINFO_PGREFILL_DMA = 51; + VMEMINFO_PGREFILL_NORMAL = 52; + VMEMINFO_PGREFILL_MOVABLE = 53; + VMEMINFO_PGSTEAL_KSWAPD_DMA = 54; + VMEMINFO_PGSTEAL_KSWAPD_NORMAL = 55; + VMEMINFO_PGSTEAL_KSWAPD_MOVABLE = 56; + VMEMINFO_PGSTEAL_DIRECT_DMA = 57; + VMEMINFO_PGSTEAL_DIRECT_NORMAL = 58; + VMEMINFO_PGSTEAL_DIRECT_MOVABLE = 59; + VMEMINFO_PGSCAN_KSWAPD_DMA = 60; + VMEMINFO_PGSCAN_KSWAPD_NORMAL = 61; + VMEMINFO_PGSCAN_KSWAPD_MOVABLE = 62; + VMEMINFO_PGSCAN_DIRECT_DMA = 63; + VMEMINFO_PGSCAN_DIRECT_NORMAL = 64; + VMEMINFO_PGSCAN_DIRECT_MOVABLE = 65; + VMEMINFO_PGSCAN_DIRECT_THROTTLE = 66; + VMEMINFO_PGINODESTEAL = 67; + VMEMINFO_SLABS_SCANNED = 68; + VMEMINFO_KSWAPD_INODESTEAL = 69; + VMEMINFO_KSWAPD_LOW_WMARK_HIT_QUICKLY = 70; + VMEMINFO_KSWAPD_HIGH_WMARK_HIT_QUICKLY = 71; + VMEMINFO_PAGEOUTRUN = 72; + VMEMINFO_ALLOCSTALL = 73; + VMEMINFO_PGROTATED = 74; + VMEMINFO_DROP_PAGECACHE = 75; + VMEMINFO_DROP_SLAB = 76; + VMEMINFO_PGMIGRATE_SUCCESS = 77; + VMEMINFO_PGMIGRATE_FAIL = 78; + VMEMINFO_COMPACT_MIGRATE_SCANNED = 79; + VMEMINFO_COMPACT_FREE_SCANNED = 80; + VMEMINFO_COMPACT_ISOLATED = 81; + VMEMINFO_COMPACT_STALL = 82; + VMEMINFO_COMPACT_FAIL = 83; + VMEMINFO_COMPACT_SUCCESS = 84; + VMEMINFO_COMPACT_DAEMON_WAKE = 85; + VMEMINFO_UNEVICTABLE_PGS_CULLED = 86; + VMEMINFO_UNEVICTABLE_PGS_SCANNED = 87; + VMEMINFO_UNEVICTABLE_PGS_RESCUED = 88; + VMEMINFO_UNEVICTABLE_PGS_MLOCKED = 89; + VMEMINFO_UNEVICTABLE_PGS_MUNLOCKED = 90; + VMEMINFO_UNEVICTABLE_PGS_CLEARED = 91; + VMEMINFO_UNEVICTABLE_PGS_STRANDED = 92; + VMEMINFO_NR_ZSPAGES = 93; + VMEMINFO_NR_ION_HEAP = 94; + VMEMINFO_NR_GPU_HEAP = 95; + VMEMINFO_ALLOCSTALL_DMA = 96; + VMEMINFO_ALLOCSTALL_MOVABLE = 97; + VMEMINFO_ALLOCSTALL_NORMAL = 98; + VMEMINFO_COMPACT_DAEMON_FREE_SCANNED = 99; + VMEMINFO_COMPACT_DAEMON_MIGRATE_SCANNED = 100; + VMEMINFO_NR_FASTRPC = 101; + VMEMINFO_NR_INDIRECTLY_RECLAIMABLE = 102; + VMEMINFO_NR_ION_HEAP_POOL = 103; + VMEMINFO_NR_KERNEL_MISC_RECLAIMABLE = 104; + VMEMINFO_NR_SHADOW_CALL_STACK_BYTES = 105; + VMEMINFO_NR_SHMEM_HUGEPAGES = 106; + VMEMINFO_NR_SHMEM_PMDMAPPED = 107; + VMEMINFO_NR_UNRECLAIMABLE_PAGES = 108; + VMEMINFO_NR_ZONE_ACTIVE_ANON = 109; + VMEMINFO_NR_ZONE_ACTIVE_FILE = 110; + VMEMINFO_NR_ZONE_INACTIVE_ANON = 111; + VMEMINFO_NR_ZONE_INACTIVE_FILE = 112; + VMEMINFO_NR_ZONE_UNEVICTABLE = 113; + VMEMINFO_NR_ZONE_WRITE_PENDING = 114; + VMEMINFO_OOM_KILL = 115; + VMEMINFO_PGLAZYFREE = 116; + VMEMINFO_PGLAZYFREED = 117; + VMEMINFO_PGREFILL = 118; + VMEMINFO_PGSCAN_DIRECT = 119; + VMEMINFO_PGSCAN_KSWAPD = 120; + VMEMINFO_PGSKIP_DMA = 121; + VMEMINFO_PGSKIP_MOVABLE = 122; + VMEMINFO_PGSKIP_NORMAL = 123; + VMEMINFO_PGSTEAL_DIRECT = 124; + VMEMINFO_PGSTEAL_KSWAPD = 125; + VMEMINFO_SWAP_RA = 126; + VMEMINFO_SWAP_RA_HIT = 127; + VMEMINFO_WORKINGSET_RESTORE = 128; +} diff --git a/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..72f824df4f75a37224bcf24fb4d50181c1093f4f --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_config.proto @@ -0,0 +1,42 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +import "memory_plugin_common.proto"; + +// Memory plug-in configuration, passed to plug-in by plug-in service. +message MemoryConfig { + // set true to report process list + bool report_process_tree = 1; + // set true to report memory counter from /proc/meminfo + bool report_sysmem_mem_info = 2; + // set required counter list of system meminfo, eg:MemTotal, MemFree, etc. + repeated SysMeminfoType sys_meminfo_counters = 3; + // set true to report memory counter from /proc/vmstat + bool report_sysmem_vmem_info = 4; + // set required counter list of virtual system meminfo, eg:nr_free_pages, nr_anon_pages, etc. + repeated SysVMeminfoType sys_vmeminfo_counters = 5; + // set true to report process meminfo from /proc/${pid}/stat + bool report_process_mem_info = 6; + // set true to report application memory usage summary, eg:java heap memory, native heap, stack memory, etc. + bool report_app_mem_info = 7; + // set true to report application memory by dumpsys service, otherwise, + // application memory will count up by /proc/${pid}/smaps information + bool report_app_mem_by_dumpsys = 8; + // set required pid list + repeated int32 pid = 9; +} diff --git a/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_result.proto new file mode 100644 index 0000000000000000000000000000000000000000..c0e622762d0125ea8e3f99d239153dfb5fe07eb6 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_result.proto @@ -0,0 +1,73 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +import "memory_plugin_common.proto"; + +// Data format of memory collect plug-in. +// Various memory data count, including system level and application level. +// Obtained from the proc file system or system service. +message SysMeminfo { + SysMeminfoType key = 1; + uint64 value = 2; +}; +message SysVMeminfo { + SysVMeminfoType key = 1; + uint64 value = 2; +}; + +message SmapsInfo { + string mapinfo = 1; + int32 size = 2; + int32 rss = 3; + int32 pss = 4; + int32 anonymous = 5; +}; + +message AppSummary { + uint64 java_heap = 1; + uint64 native_heap = 2; + uint64 code = 3; + uint64 stack = 4; + uint64 graphics = 5; + uint64 private_other = 6; + uint64 system = 7; +}; + +message ProcessMemoryInfo { + int32 pid = 1; + string name = 2; + // data from /proc/$pid/stat + uint64 vm_size_kb = 3; + uint64 vm_rss_kb = 4; + uint64 rss_anon_kb = 5; + uint64 rss_file_kb = 6; + uint64 rss_shmem_kb = 7; + uint64 vm_swap_kb = 8; + uint64 vm_locked_kb = 9; + uint64 vm_hwm_kb = 10; + int64 oom_score_adj = 11; + // data from /proc/$pid/smaps + repeated SmapsInfo smapinfo = 12; + AppSummary memsummary = 13; +} + +message MemoryData { + repeated ProcessMemoryInfo processesinfo = 1; + repeated SysMeminfo meminfo = 2; + repeated SysVMeminfo vmeminfo = 3; +} diff --git a/host/trace_streamer/src/protos/types/plugins/native_hook/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/native_hook/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..0ca0fc90eda2b4309c1550194cd538ce42ae2a91 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/native_hook/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../protos.gni") + +native_hook_sources = [ + "./native_hook_config.proto", + "./native_hook_result.proto", +] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) + +native_hook_codegen = [] +foreach(proto, native_hook_sources) { + name = get_path_info(proto, "name") + native_hook_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] +} + +config("native_hook_include_config") { + include_dirs = [ "$proto_out_dir" ] +} + +####################################################### +action("native_hook_cpp_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = native_hook_sources + outputs = native_hook_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +ohos_source_set("native_hook_cpp") { + deps = [ ":native_hook_cpp_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":native_hook_include_config" ] + sources = native_hook_codegen +} diff --git a/host/trace_streamer/src/protos/types/plugins/native_hook/native_hook_config.proto b/host/trace_streamer/src/protos/types/plugins/native_hook/native_hook_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..53c39b1697cc21142c5bb6750693f48c60c754b1 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/native_hook/native_hook_config.proto @@ -0,0 +1,27 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + + +message NativeHookConfig { + int32 pid = 1; + bool save_file = 2; + string file_name = 3; + int32 filter_size = 4; + int32 smb_pages = 5; + int32 max_stack_depth = 6; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/native_hook/native_hook_result.proto b/host/trace_streamer/src/protos/types/plugins/native_hook/native_hook_result.proto new file mode 100644 index 0000000000000000000000000000000000000000..3a93eff3c7b733c04b2adf42a5fc16ff2bc986e8 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/native_hook/native_hook_result.proto @@ -0,0 +1,54 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message Frame { + uint64 ip = 1; + uint64 sp = 2; + string symbol_name = 3; + string file_path = 4; + uint64 offset = 5; + uint64 symbol_offset = 6; +} + +message AllocEvent { + int32 pid = 1; + int32 tid = 2; + uint64 addr = 3; + uint32 size = 4; + repeated Frame frame_info = 5; +} + +message FreeEvent { + int32 pid = 1; + int32 tid = 2; + uint64 addr = 3; + repeated Frame frame_info = 4; +} + +message NativeHookData { + uint64 tv_sec = 1; + uint64 tv_nsec = 2; + oneof event { + AllocEvent alloc_event = 3; + FreeEvent free_event = 4; + } +} + +message BatchNativeHookData { + repeated NativeHookData events = 1; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/network_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/network_data/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..206dc986cf8b93b346425223fb5d9001972aa8c6 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/network_data/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../protos.gni") + +network_data_sources = [ + "./network_plugin_config.proto", + "./network_plugin_result.proto", +] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) + +network_data_codegen = [] +foreach(proto, network_data_sources) { + name = get_path_info(proto, "name") + network_data_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] +} + +config("network_include_config") { + include_dirs = [ "$proto_out_dir" ] +} + +####################################################### +action("network_data_cpp_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = network_data_sources + outputs = network_data_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +ohos_source_set("network_data_cpp") { + deps = [ ":network_data_cpp_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":network_include_config" ] + sources = network_data_codegen +} diff --git a/host/trace_streamer/src/protos/types/plugins/network_data/network_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/network_data/network_plugin_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..b993e8c595554e5e9408c2aa43b8e4489c2fbc1e --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/network_data/network_plugin_config.proto @@ -0,0 +1,21 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message NetworkConfig { + repeated int32 pid = 1; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/network_data/network_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/network_data/network_plugin_result.proto new file mode 100644 index 0000000000000000000000000000000000000000..8df215fb18ff4edf0229e1302ae254008e12980e --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/network_data/network_plugin_result.proto @@ -0,0 +1,37 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message NetworkDetails { + uint64 tx_bytes = 1; + uint64 rx_bytes = 2; + string type = 3; // e.g. "wlan0", "rmnet0", etc. +} + +message NetworkData { + int32 pid = 1; + // timestamp obtained by CLOCK_REALTIME + uint64 tv_sec = 2; + uint64 tv_nsec = 3; + uint64 tx_bytes = 4; + uint64 rx_bytes = 5; + repeated NetworkDetails details = 6; +} + +message NetworkDatas { + repeated NetworkData networkinfo = 1; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/process_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/process_data/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..893064d2965c70c4186ac7659e80ec62f3512cec --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/process_data/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../protos.gni") + +process_data_sources = [ + "./process_plugin_config.proto", + "./process_plugin_result.proto", +] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) + +process_data_codegen = [] +foreach(proto, process_data_sources) { + name = get_path_info(proto, "name") + process_data_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] +} + +config("process_include_config") { + include_dirs = [ "$proto_out_dir" ] +} + +####################################################### +action("process_data_cpp_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = process_data_sources + outputs = process_data_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +ohos_source_set("process_data_cpp") { + deps = [ ":process_data_cpp_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":process_include_config" ] + sources = process_data_codegen +} diff --git a/host/trace_streamer/src/protos/types/plugins/process_data/process_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/process_data/process_plugin_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..ecb8389276bd5e728f4bd14edf8a66710d7d6b13 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/process_data/process_plugin_config.proto @@ -0,0 +1,22 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message ProcessConfig { + // set true to report process list + bool report_process_tree = 1; +} diff --git a/host/trace_streamer/src/protos/types/plugins/process_data/process_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/process_data/process_plugin_result.proto new file mode 100644 index 0000000000000000000000000000000000000000..53f586b5feccf678ffb98979fe2cbc098293e7c3 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/process_data/process_plugin_result.proto @@ -0,0 +1,26 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message ProcessInfo { + int32 pid = 1; + string name = 2; +} + +message ProcessData { + repeated ProcessInfo processesinfo = 1; +} diff --git a/host/trace_streamer/src/protos/types/plugins/sample_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/sample_data/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..954a9b354d6645e9353266d7f755cef15a3135b5 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/sample_data/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../protos.gni") + +sample_data_sources = [ + "./sample_plugin_config.proto", + "./sample_plugin_result.proto", +] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) + +sample_data_codegen = [] +foreach(proto, sample_data_sources) { + name = get_path_info(proto, "name") + sample_data_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] +} + +config("sample_include_config") { + include_dirs = [ "$proto_out_dir" ] +} + +####################################################### +action("sample_data_cpp_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = sample_data_sources + outputs = sample_data_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +ohos_source_set("sample_data_cpp") { + deps = [ ":sample_data_cpp_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":sample_include_config" ] + sources = sample_data_codegen +} diff --git a/host/trace_streamer/src/protos/types/plugins/sample_data/sample_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/sample_data/sample_plugin_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..262398e4f7ef762650353047c804927db761f6c8 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/sample_data/sample_plugin_config.proto @@ -0,0 +1,19 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +syntax = "proto3"; +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message SampleConfig { + int32 pid = 1; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/sample_data/sample_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/sample_data/sample_plugin_result.proto new file mode 100644 index 0000000000000000000000000000000000000000..0a8d74393c6387eb5d0bfd4ce8a5a2bdc0d289c0 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/sample_data/sample_plugin_result.proto @@ -0,0 +1,19 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +syntax = "proto3"; +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message SampleData { + uint64 time_ms = 1; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/stream_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/stream_data/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..8aa3506a107570857269cbe3ce241383d1b94554 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/stream_data/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("../../../protos.gni") + +stream_data_sources = [ + "./stream_plugin_config.proto", + "./stream_plugin_result.proto", +] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) + +stream_data_codegen = [] +foreach(proto, stream_data_sources) { + name = get_path_info(proto, "name") + stream_data_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] +} + +config("stream_include_config") { + include_dirs = [ "$proto_out_dir" ] +} + +####################################################### +action("stream_data_cpp_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = stream_data_sources + outputs = stream_data_codegen + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +ohos_source_set("stream_data_cpp") { + deps = [ ":stream_data_cpp_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":stream_include_config" ] + sources = stream_data_codegen +} diff --git a/host/trace_streamer/src/protos/types/plugins/stream_data/stream_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/stream_data/stream_plugin_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..9d124a74c2b03a0bd03313bdd35bc66c73c1730d --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/stream_data/stream_plugin_config.proto @@ -0,0 +1,19 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +syntax = "proto3"; +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message StreamConfig { + int32 pid = 1; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/stream_data/stream_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/stream_data/stream_plugin_result.proto new file mode 100644 index 0000000000000000000000000000000000000000..ece7d24105cc0f46574aefe0d7b4c2a456e746a1 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/stream_data/stream_plugin_result.proto @@ -0,0 +1,19 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +syntax = "proto3"; +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message StreamData { + uint64 time_ms = 1; +} \ No newline at end of file diff --git a/host/trace_streamer/src/rpc/http_server.cpp b/host/trace_streamer/src/rpc/http_server.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ada95d93e64b71f52b4319a518126a644e8590b0 --- /dev/null +++ b/host/trace_streamer/src/rpc/http_server.cpp @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "http_server.h" +#include +#include +#include +#include +#ifdef _WIN32 +#include +#else +#include +#include +#endif +#include "log.h" +namespace SysTuning { +namespace TraceStreamer { +void HttpServer::RegisterRpcFunction(RpcServer* rpc) +{ + rpcFunctions_.clear(); + + using std::placeholders::_1; + using std::placeholders::_2; + using std::placeholders::_3; + + auto parsedata = std::bind(&RpcServer::ParseData, rpc, _1, _2, _3); + rpcFunctions_["/parsedata"] = parsedata; + + auto parsedataover = std::bind(&RpcServer::ParseDataOver, rpc, _1, _2, _3); + rpcFunctions_["/parsedataover"] = parsedataover; + + auto sqlquery = std::bind(&RpcServer::SqlQuery, rpc, _1, _2, _3); + rpcFunctions_["/sqlquery"] = sqlquery; + + auto sqloperate = std::bind(&RpcServer::SqlOperate, rpc, _1, _2, _3); + rpcFunctions_["/sqloperate"] = sqloperate; + + auto reset = std::bind(&RpcServer::Reset, rpc, _1, _2, _3); + rpcFunctions_["/reset"] = reset; +} + +#ifdef _WIN32 +void HttpServer::Run(int port) +{ + WSADATA ws{}; + if (WSAStartup(MAKEWORD(WS_VERSION_FIRST, WS_VERSION_SEC), &ws) != 0) { + return; + } + if (!CreateSocket(port)) { + return; + } + WSAEVENT events[COUNT_SOCKET]; + for (int i = 0; i < COUNT_SOCKET; i++) { + if ((events[i] = WSACreateEvent()) == WSA_INVALID_EVENT) { + TS_LOGE("WSACreateEvent error %d", WSAGetLastError()); + return; + } + WSAEventSelect(sockets_[i].GetFd(), events[i], FD_ACCEPT | FD_CLOSE); + } + + while (!isExit_) { + ClearDeadClientThread(); + + int index = WSAWaitForMultipleEvents(COUNT_SOCKET, events, false, pollTimeOut_, false); + if (index == WSA_WAIT_FAILED) { + TS_LOGE("WSAWaitForMultipleEvents error %d", WSAGetLastError()); + break; + } else if (index == WSA_WAIT_TIMEOUT) { + continue; + } + + index = index - WSA_WAIT_EVENT_0; + WSANETWORKEVENTS event; + WSAEnumNetworkEvents(sockets_[index].GetFd(), events[index], &event); + if (event.lNetworkEvents & FD_ACCEPT) { + if (event.iErrorCode[FD_ACCEPT_BIT] != 0) { + continue; + } + + std::unique_ptr client = std::make_unique(); + if (sockets_[index].Accept(client->sock_)) { + client->thread_ = std::thread(&HttpServer::ProcessClient, this, std::ref(client->sock_)); + clientThreads_.push_back(std::move(client)); + } else { + TS_LOGE("http socket accept error"); + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } + } + + for (auto& it : clientThreads_) { + if (it->thread_.joinable()) { + it->sock_.Close(); + it->thread_.join(); + } + } + clientThreads_.clear(); + + WSACleanup(); +} +#else +void HttpServer::Run(int port) +{ + signal(SIGPIPE, SIG_IGN); + + if (!CreateSocket(port)) { + return; + } + TS_LOGI("http server running"); + + struct pollfd fds[COUNT_SOCKET] = {{sockets_[0].GetFd(), POLLIN, 0}, {sockets_[1].GetFd(), POLLIN, 0}}; + while (!isExit_) { + ClearDeadClientThread(); + + if (poll(fds, sizeof(fds)/sizeof(pollfd), pollTimeOut_) <= 0) { + continue; // try again + } + + for (int i = 0; i < COUNT_SOCKET; i++) { + if (fds[i].revents != POLLIN) { + continue; + } + std::unique_ptr client = std::make_unique(); + if (sockets_[i].Accept(client->sock_)) { + client->thread_ = std::thread(&HttpServer::ProcessClient, this, std::ref(client->sock_)); + clientThreads_.push_back(std::move(client)); + } else { + TS_LOGE("http socket accept error"); + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } + } + + for (auto& it : clientThreads_) { + if (it->thread_.joinable()) { + it->sock_.Close(); + it->thread_.join(); + } + } + clientThreads_.clear(); + TS_LOGI("http server exit"); +} +#endif + +void HttpServer::Exit() +{ + isExit_ = true; + for (int i = 0; i < COUNT_SOCKET; i++) { + sockets_[i].Close(); + } +} + +bool HttpServer::CreateSocket(int port) +{ + if (!sockets_[0].CreateSocket(AF_INET) || !sockets_[1].CreateSocket(AF_INET6)) { + TS_LOGE("Create http socket error"); + return false; + } + for (int i = 0; i < COUNT_SOCKET; i++) { + if (!sockets_[i].Bind(port)) { + TS_LOGE("bind http socket error"); + return false; + } + if (!sockets_[i].Listen(SOMAXCONN)) { + TS_LOGE("listen http socket error"); + return false; + } + } + + return true; +} + +void HttpServer::ClearDeadClientThread() +{ + for (auto it = clientThreads_.begin(); it != clientThreads_.end();) { + if (it->get()->sock_.GetFd() != -1) { + it++; + continue; + } + if (it->get()->thread_.joinable()) { + it->get()->thread_.join(); + } + it = clientThreads_.erase(it); + } +} + +#ifdef _WIN32 +void HttpServer::ProcessClient(HttpSocket& client) +{ + std::vector recvBuf(MAXLEN_REQUEST); + size_t recvLen = recvBuf.size(); + size_t recvPos = 0; + RequestST reqST; + WSAEVENT recvEvent = WSACreateEvent(); + if (recvEvent == WSA_INVALID_EVENT) { + TS_LOGE("WSACreateEvent error %d", WSAGetLastError()); + return; + } + WSAEventSelect(client.GetFd(), recvEvent, FD_READ | FD_CLOSE); + while (!isExit_) { + int index = WSAWaitForMultipleEvents(1, &recvEvent, false, pollTimeOut_, false); + if (index == WSA_WAIT_FAILED) { + TS_LOGE("WSAWaitForMultipleEvents error %d", WSAGetLastError()); + break; + } else if (index == WSA_WAIT_TIMEOUT) { + if (reqST.stat != RequstParseStat::INIT) { + ProcessRequest(client, reqST); + reqST.stat = RequstParseStat::INIT; + recvPos = 0; + recvLen = recvBuf.size(); + } + continue; + } + + WSANETWORKEVENTS event; + WSAEnumNetworkEvents(client.GetFd(), recvEvent, &event); + if (event.lNetworkEvents & FD_READ) { + if (event.iErrorCode[FD_READ_BIT] != 0) { + continue; + } + if (!client.Recv(recvBuf.data() + recvPos, recvLen)) { + break; + } + recvPos += recvLen; + ParseRequest(recvBuf.data(), recvPos, reqST); + recvLen = recvBuf.size() - recvPos; + if (reqST.stat == RequstParseStat::RECVING) { + continue; + } + ProcessRequest(client, reqST); + reqST.stat = RequstParseStat::INIT; + } else if (event.lNetworkEvents & FD_CLOSE) { + TS_LOGI("client close socket(%d)", client.GetFd()); + break; + } + } + TS_LOGI("recive client thread exit. socket(%d)", client.GetFd()); + + client.Close(); +} +#else +void HttpServer::ProcessClient(HttpSocket& client) +{ + std::vector recvBuf(MAXLEN_REQUEST); + size_t recvLen = recvBuf.size(); + size_t recvPos = 0; + RequestST reqST; + + struct pollfd fd = {client.GetFd(), POLLIN, 0}; + while (!isExit_) { + int pollRet = poll(&fd, sizeof(fd)/sizeof(pollfd), pollTimeOut_); + if (pollRet < 0) { + TS_LOGE("poll client socket(%d) error: %d:%s", client.GetFd(), errno, strerror(errno)); + break; + } + if (pollRet == 0) { + if (reqST.stat != RequstParseStat::INIT) { + ProcessRequest(client, reqST); + reqST.stat = RequstParseStat::INIT; + recvPos = 0; + recvLen = recvBuf.size(); + } + continue; + } + if (!client.Recv(recvBuf.data() + recvPos, recvLen)) { + break; + } + recvPos += recvLen; + ParseRequest(recvBuf.data(), recvPos, reqST); + recvLen = recvBuf.size() - recvPos; + if (reqST.stat == RequstParseStat::RECVING) { + continue; + } + ProcessRequest(client, reqST); + reqST.stat = RequstParseStat::INIT; + } + TS_LOGI("recive client thread exit. socket(%d)", client.GetFd()); + + client.Close(); +} +#endif + +void HttpServer::ProcessRequest(HttpSocket& client, RequestST& request) +{ + if (request.stat == RequstParseStat::RECVING) { + TS_LOGE("http request data missing, client %d\n", client.GetFd()); + HttpResponse(client, "408 Request Time-out"); + return; + } else if (request.stat != RequstParseStat::OK) { + TS_LOGE("bad http request, client %d\n", client.GetFd()); + HttpResponse(client, "400 Bad Request"); + return; + } + if (request.method == "OPTIONS") { + HttpResponse(client, "204 No Content\r\n" + "Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n" + "Access-Control-Allow-Headers: *\r\n" + "Access-Control-Max-Age: 86400\r\n"); + return; + } else if (request.method != "POST" && request.method != "GET") { + TS_LOGE("method(%s) not allowed, client %d", request.method.c_str(), client.GetFd()); + HttpResponse(client, "405 Method Not Allowed\r\n"); + return; + } + auto it = rpcFunctions_.find(request.uri); + if (it == rpcFunctions_.end()) { + TS_LOGE("http uri(%s) not found, client %d", request.uri.c_str(), client.GetFd()); + HttpResponse(client, "404 Not Found\r\n"); + return; + } + HttpResponse(client, "200 OK\r\n", true); + auto resultCallback = [&](const std::string result) { + std::stringstream chunkLenbuff; + chunkLenbuff << std::hex << result.size() << "\r\n"; + if (!client.Send(chunkLenbuff.str().data(), chunkLenbuff.str().size())) { + TS_LOGE("send client socket(%d) error", client.GetFd()); + return; + } + if (!client.Send(result.data(), result.size())) { + TS_LOGE("send client socket(%d) error", client.GetFd()); + return; + } + if (!client.Send("\r\n", strlen("\r\n"))) { + TS_LOGE("send client socket(%d) error", client.GetFd()); + return; + } + }; + it->second(request.body, request.bodyLen, resultCallback); + if (!client.Send("0\r\n\r\n", strlen("0\r\n\r\n"))) { // chunk tail + TS_LOGE("send client socket(%d) error", client.GetFd()); + } +} + +void HttpServer::ParseRequest(const uint8_t* requst, size_t& len, RequestST& httpReq) +{ + std::string_view reqStr(reinterpret_cast(requst), len); + size_t bodyPos = reqStr.find("\r\n\r\n"); + if (bodyPos == 0) { + len = 0; + httpReq.stat = RequstParseStat::BAD; + return; + } else if (bodyPos == std::string_view::npos) { + httpReq.stat = RequstParseStat::RECVING; + return; + } + std::string_view header = reqStr.substr(0, bodyPos); + bodyPos += strlen("\r\n\r\n"); + httpReq.bodyLen = reqStr.size() - bodyPos; + + std::vector headerlines = StringSplit(header, "\r\n"); + // at least 1 line in headerlines, such as "GET /parsedata HTTP/1.1" + std::vector requestItems = StringSplit(headerlines[0], " "); + const size_t indexHttpMethod = 0; + const size_t indexHttpUri = 1; + const size_t indexHttpVersion = 2; + const size_t countRequestItems = 3; + if (requestItems.size() != countRequestItems || + requestItems[indexHttpVersion] != "HTTP/1.1") { + len = 0; + httpReq.stat = RequstParseStat::BAD; + return; + } + httpReq.method = requestItems[indexHttpMethod]; + httpReq.uri = requestItems[indexHttpUri]; + + for (size_t i = 1; i < headerlines.size(); i++) { + size_t tagPos = headerlines[i].find(": "); + if (tagPos == std::string_view::npos) { + len = 0; + httpReq.stat = RequstParseStat::BAD; + return; + } + std::string_view tag = headerlines[i].substr(0, tagPos); + if (strncasecmp(tag.data(), "content-length", tag.size()) == 0) { + std::string value(headerlines[i].data() + tagPos + strlen(": "), + headerlines[i].size() - tagPos - strlen(": ")); + size_t conterntLen = atoi(value.c_str()); + if (conterntLen > httpReq.bodyLen) { + httpReq.stat = RequstParseStat::RECVING; + return; + } else if (conterntLen < httpReq.bodyLen) { + httpReq.bodyLen = conterntLen; + } + } + } + + if (httpReq.bodyLen > 0) { + httpReq.body = (requst + bodyPos); + } + httpReq.stat = RequstParseStat::OK; + len -= (bodyPos + httpReq.bodyLen); + return; +} + +void HttpServer::HttpResponse(HttpSocket& client, const std::string& status, bool hasBody) +{ + std::string res; + const size_t maxLenResponse = 1024; + res.reserve(maxLenResponse); + res += "HTTP/1.1 "; + res += status; + res += "\r\n"; + + res += "Connection: Keep-Alive\r\n"; + + if (hasBody) { + res += "Content-Type: application/json\r\n"; + res += "Transfer-Encoding: chunked\r\n"; + } + res += "\r\n"; + + if (!client.Send(res.data(), res.size())) { + TS_LOGE("send client socket(%d) error", client.GetFd()); + } +} + +std::vector HttpServer::StringSplit(std::string_view source, std::string_view split) +{ + std::vector result; + if (!split.empty()) { + size_t pos = 0; + while ((pos = source.find(split)) != std::string_view::npos) { + // split + std::string_view token = source.substr(0, pos); + if (!token.empty()) { + result.push_back(token); + } + source = source.substr(pos + split.size(), source.size() - token.size() - split.size()); + } + } + // add last token + if (!source.empty()) { + result.push_back(source); + } + return result; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/rpc/http_server.h b/host/trace_streamer/src/rpc/http_server.h new file mode 100644 index 0000000000000000000000000000000000000000..e8d4305905ef14bad19fb3fb4e59f8b229d13bc3 --- /dev/null +++ b/host/trace_streamer/src/rpc/http_server.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RPC_HTTPD_H +#define RPC_HTTPD_H + +#include +#include +#include +#include +#include +#include "http_socket.h" +#include "rpc_server.h" +namespace SysTuning { +namespace TraceStreamer { +class HttpServer { +public: + void RegisterRpcFunction(RpcServer* rpc); + void Run(int port = 9001); + void Exit(); + + static constexpr size_t MAXLEN_REQUEST = 2 * 1024 + 1024 * 1024; // header 2K + body 1M + +private: + struct ClientThread { + HttpSocket sock_; + std::thread thread_; + }; + + enum RequstParseStat { + INIT = 0, + OK, + BAD, + RECVING + }; + + struct RequestST { + int stat = RequstParseStat::INIT; + std::string method; + std::string uri; + const uint8_t* body; + size_t bodyLen; + }; + + bool CreateSocket(int port); + void ProcessClient(HttpSocket& client); + void ProcessRequest(HttpSocket& client, RequestST& request); + void HttpResponse(HttpSocket& client, const std::string& status, bool hasBody = false); + void ParseRequest(const uint8_t* requst, size_t& len, RequestST& httpReq); + void ClearDeadClientThread(); + std::vector StringSplit(std::string_view source, std::string_view split); + + static const int COUNT_SOCKET = 2; + HttpSocket sockets_[COUNT_SOCKET]; // ipv4 and ipv6 + std::atomic_bool isExit_ = {false}; + std::vector> clientThreads_; + using RpcFunction = std::function; + std::map rpcFunctions_; + const int pollTimeOut_ = 1000; +#ifdef _WIN32 + const uint32_t WS_VERSION_FIRST = 2; + const uint32_t WS_VERSION_SEC = 2; +#endif +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // RPC_HTTPD_H diff --git a/host/trace_streamer/src/rpc/http_socket.cpp b/host/trace_streamer/src/rpc/http_socket.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dee3474f34eeabf061b06134071ae432f610a723 --- /dev/null +++ b/host/trace_streamer/src/rpc/http_socket.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "http_socket.h" +#include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#endif +#include "log.h" +namespace SysTuning { +namespace TraceStreamer { +HttpSocket::~HttpSocket() +{ + Close(); +} +bool HttpSocket::CreateSocket(int domain) +{ + SOCKET sockId = socket(domain, SOCK_STREAM, 0); + if (sockId == INVALID_SOCKET) { + TS_LOGE("CreateSocket socket error, domain %d: %d:%s", domain, errno, strerror(errno)); + return false; + } + sockId_ = sockId; + if (domain == AF_INET || domain == AF_INET6) { + int enable = 1; + if (setsockopt(sockId, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&enable), + sizeof(enable)) == SOCKET_ERROR) { + Close(); + return false; + } + if (domain == AF_INET6) { + if (setsockopt(sockId, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast(&enable), + sizeof(enable)) == SOCKET_ERROR) { + Close(); + return false; + } + } + } + domain_ = domain; + TS_LOGI("CreateSocket socket ok, socket %d domain %d", sockId_, domain); + return true; +} + +bool HttpSocket::Bind(int port) +{ + if (sockId_ == INVALID_SOCKET) { + TS_LOGE("the socket not created"); + return false; + } + + if (domain_ == AF_INET) { + struct sockaddr_in addr; + std::fill(reinterpret_cast(&addr), reinterpret_cast(&addr) + sizeof(addr), 0); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htons(INADDR_ANY); + addr.sin_port = htons(static_cast(port)); + if (bind(sockId_, reinterpret_cast(&addr), sizeof(addr)) == -1) { + TS_LOGE("bind ipv4 socket error, port %d: %d:%s", port, errno, strerror(errno)); + return false; + } + } else if (domain_ == AF_INET6) { + struct sockaddr_in6 addr; + std::fill(reinterpret_cast(&addr), reinterpret_cast(&addr) + sizeof(addr), 0); + addr.sin6_family = AF_INET6; + addr.sin6_addr = in6addr_any; + addr.sin6_port = htons(static_cast(port)); + if (bind(sockId_, reinterpret_cast(&addr), sizeof(addr)) == -1) { + TS_LOGE("bind ipv6 socket error, port %d: %d:%s", port, errno, strerror(errno)); + return false; + } + } else { + return false; + } + TS_LOGI("bind socket ok, port %d", port); + return true; +} + +bool HttpSocket::Listen(int maxConn) +{ + if (listen(sockId_, maxConn) == SOCKET_ERROR) { + TS_LOGE("listen socket error: %d:%s", errno, strerror(errno)); + return false; + } + TS_LOGI("listen socket ok, maxConn %d", maxConn); + return true; +} + +bool HttpSocket::Accept(HttpSocket& client) +{ + int clientId = accept(sockId_, nullptr, nullptr); + if (clientId == INVALID_SOCKET) { + TS_LOGE("accept socket error: %d:%s", errno, strerror(errno)); + return false; + } + + client.domain_ = domain_; + client.sockId_ = clientId; + TS_LOGI("accept client socket id %d domain %d", clientId, domain_); + return true; +} + +bool HttpSocket::Recv(void* data, size_t& len) +{ +#ifdef _WIN32 + ssize_t recvLen = recv(sockId_, static_cast(data), len, 0); +#else + ssize_t recvLen = recv(sockId_, data, len, 0); +#endif + if (recvLen == SOCKET_ERROR) { + if (errno == EAGAIN) { + recvLen = 0; + } else { + TS_LOGE("recv from socket(%d) error: %d:%s", sockId_, errno, strerror(errno)); + return false; + } + } else if (recvLen == 0) { + TS_LOGI("client socket(%d) closed", sockId_); + return false; + } + len = recvLen; + TS_LOGD("Recv from socket(%d) len %zu", sockId_, len); + return true; +} + +bool HttpSocket::Send(const void* data, size_t len) +{ +#ifdef _WIN32 + ssize_t sendLen = send(sockId_, static_cast(data), len, 0); +#else + ssize_t sendLen = send(sockId_, data, len, 0); +#endif + if (sendLen == SOCKET_ERROR) { + TS_LOGE("send to socket(%d) error: %d:%s", sockId_, errno, strerror(errno)); + return false; + } + TS_LOGD("send to socket(%d) len %zu", sockId_, len); + return true; +} + +void HttpSocket::Close() +{ + if (sockId_ == INVALID_SOCKET) { + return; + } + TS_LOGI("close socket(%d)", sockId_); +#ifdef _WIN32 + if (closesocket(sockId_) == SOCKET_ERROR) { +#else + if (close(sockId_) == SOCKET_ERROR) { +#endif + TS_LOGE("close socket(%d) error: %d:%s", sockId_, errno, strerror(errno)); + } + sockId_ = INVALID_SOCKET; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/rpc/http_socket.h b/host/trace_streamer/src/rpc/http_socket.h new file mode 100644 index 0000000000000000000000000000000000000000..f03ccb5e3959a951d4d455908fe2a5b9f8cee5fc --- /dev/null +++ b/host/trace_streamer/src/rpc/http_socket.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RPC_HTTPSOCKET_H +#define RPC_HTTPSOCKET_H + +#include +namespace SysTuning { +namespace TraceStreamer { +class HttpSocket { +public: + HttpSocket() {} + HttpSocket(int sockId, int domain) : sockId_(sockId), domain_(domain) {} + ~HttpSocket(); + + bool CreateSocket(int domain); + bool Bind(int port); + bool Listen(int maxConn); + bool Accept(HttpSocket& client); + bool Recv(void* data, size_t& len); + bool Send(const void* data, size_t len); + void Close(); + int GetFd() + { + return sockId_; + } + +private: + int sockId_ = -1; + int domain_ = 0; +#ifndef _WIN32 + using SOCKET = int; + const int SOCKET_ERROR = -1; + const SOCKET INVALID_SOCKET = -1; +#endif +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // RPC_HTTPSOCKET_H diff --git a/host/trace_streamer/src/rpc/rpc.pri b/host/trace_streamer/src/rpc/rpc.pri new file mode 100644 index 0000000000000000000000000000000000000000..0bee6706469c8d52d6c002d7615ccdd493cff44f --- /dev/null +++ b/host/trace_streamer/src/rpc/rpc.pri @@ -0,0 +1,17 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +INCLUDEPATH +=$$PWD \ + $$PWD/../cfg +SOURCES += $$PWD/rpc_server.cpp \ + $$PWD/http_socket.cpp \ + $$PWD/http_server.cpp diff --git a/host/trace_streamer/src/rpc/rpc_server.cpp b/host/trace_streamer/src/rpc/rpc_server.cpp new file mode 100644 index 0000000000000000000000000000000000000000..64a9d96cedc0bcf1cc1d50056f8627be9e90fc49 --- /dev/null +++ b/host/trace_streamer/src/rpc/rpc_server.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "rpc_server.h" + +#include +#include +#include + +#include "log.h" + +namespace SysTuning { +namespace TraceStreamer { +bool RpcServer::ParseData(const uint8_t* data, size_t len, ResultCallBack resultCallBack) +{ + TS_LOGI("RPC ParseData, has parsed len %zu + %zu", lenParseData_, len); + do { + constexpr size_t blockSize = 1024 * 1024; + size_t parseSize = std::min(len, blockSize); + std::unique_ptr buf = std::make_unique(parseSize); + std::copy(data, data + parseSize, buf.get()); + + if (!ts_->ParseTraceDataSegment(std::move(buf), parseSize)) { + if (resultCallBack) { + resultCallBack("formaterror\r\n"); + } + return false; + } + data += parseSize; + len -= parseSize; + lenParseData_ += parseSize; + } while (len > 0); + if (resultCallBack) { + resultCallBack("ok\r\n"); + } + return true; +} + +bool RpcServer::ParseDataOver(const uint8_t* data, size_t len, ResultCallBack resultCallBack) +{ + TS_LOGI("RPC ParseDataOver, has parsed len %zu", lenParseData_); + + ts_->WaitForParserEnd(); + ts_->Clear(); + if (resultCallBack) { + resultCallBack("ok\r\n"); + } + lenParseData_ = 0; + return true; +} + +bool RpcServer::SqlOperate(const uint8_t* data, size_t len, ResultCallBack resultCallBack) +{ + std::string sql(reinterpret_cast(data), len); + TS_LOGI("RPC SqlOperate(%s, %zu)", sql.c_str(), len); + + int ret = ts_->OperateDatabase(sql); + if (resultCallBack) { + std::string response = "ok\r\n"; + if (ret != 0) { + response = "dberror\r\n"; + } + resultCallBack(response); + } + return (ret == 0); +} + +bool RpcServer::SqlQuery(const uint8_t* data, size_t len, ResultCallBack resultCallBack) +{ + std::string sql(reinterpret_cast(data), len); + TS_LOGI("RPC SqlQuery %zu:%s", len, sql.c_str()); + + int ret = ts_->SearchDatabase(sql, resultCallBack); + if (resultCallBack && ret != 0) { + resultCallBack("dberror\r\n"); + } + return (ret == 0); +} + +bool RpcServer::Reset(const uint8_t* data, size_t len, ResultCallBack resultCallBack) +{ + TS_LOGI("RPC reset trace_streamer"); + + ts_->WaitForParserEnd(); + ts_ = std::make_unique(); + if (resultCallBack) { + resultCallBack("ok\r\n"); + } + return true; +} + +int RpcServer::WasmSqlQuery(const uint8_t* data, size_t len, uint8_t* out, int outLen) +{ + std::string sql(reinterpret_cast(data), len); + TS_LOGI("WASM RPC SqlQuery out(%p:%d) sql(%zu:%s)", reinterpret_cast(out), outLen, + len, sql.c_str()); + + int ret = ts_->SearchDatabase(sql, out, outLen); + return ret; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/rpc/rpc_server.h b/host/trace_streamer/src/rpc/rpc_server.h new file mode 100644 index 0000000000000000000000000000000000000000..0c1137d18ceae59c4d5dad4a3bc0e09b0fb235f5 --- /dev/null +++ b/host/trace_streamer/src/rpc/rpc_server.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RPC_RPC_H +#define RPC_RPC_H + +#include +#include +#include "trace_streamer_selector.h" +namespace SysTuning { +namespace TraceStreamer { +class RpcServer { +public: + using ResultCallBack = std::function; + bool ParseData(const uint8_t* data, size_t len, ResultCallBack resultCallBack); + bool ParseDataOver(const uint8_t* data, size_t len, ResultCallBack resultCallBack); + bool SqlOperate(const uint8_t* data, size_t len, ResultCallBack resultCallBack); + bool SqlQuery(const uint8_t* data, size_t len, ResultCallBack resultCallBack); + bool Reset(const uint8_t* data, size_t len, ResultCallBack resultCallBack); + + // only for wasm, no callback + int WasmSqlQuery(const uint8_t* data, size_t len, uint8_t* out, int outLen); + +private: + std::unique_ptr ts_ = std::make_unique(); + size_t lenParseData_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // RPC_RPC_H diff --git a/host/trace_streamer/src/rpc/wasm_func.cpp b/host/trace_streamer/src/rpc/wasm_func.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8a0645630a5c33cd205ed9f51a8a26cff1f1db0d --- /dev/null +++ b/host/trace_streamer/src/rpc/wasm_func.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wasm_func.h" +#include +#include +#include "rpc_server.h" +namespace SysTuning { +namespace TraceStreamer { +RpcServer g_wasmTraceStreamer; +extern "C" { +// return 0 while ok, -1 while failed +EMSCRIPTEN_KEEPALIVE int TraceStreamerParseData(const uint8_t* data, int dataLen) +{ + if (g_wasmTraceStreamer.ParseData(data, dataLen, nullptr)) { + return 0; + } + return -1; +} +EMSCRIPTEN_KEEPALIVE int TraceStreamerParseDataOver() +{ + if (g_wasmTraceStreamer.ParseDataOver(nullptr, 0, nullptr)) { + return 0; + } + return -1; +} +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlOperate(const uint8_t* sql, int sqlLen) +{ + if (g_wasmTraceStreamer.SqlOperate(sql, sqlLen, nullptr)) { + return 0; + } + return -1; +} +EMSCRIPTEN_KEEPALIVE int TraceStreamerReset() +{ + g_wasmTraceStreamer.Reset(nullptr, 0, nullptr); + return 0; +} +// return the length of result, -1 while failed +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlQuery(const uint8_t* sql, int sqlLen, uint8_t* out, int outLen) +{ + return g_wasmTraceStreamer.WasmSqlQuery(sql, sqlLen, out, outLen); +} +} // extern "C" +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/rpc/wasm_func.h b/host/trace_streamer/src/rpc/wasm_func.h new file mode 100644 index 0000000000000000000000000000000000000000..2182d4743c8d755d3014ab89e01a5618de5e329c --- /dev/null +++ b/host/trace_streamer/src/rpc/wasm_func.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RPC_WASM_FUNC_H +#define RPC_WASM_FUNC_H + +#endif // RPC_WASM_FUNC_H diff --git a/host/trace_streamer/src/table/args_table.cpp b/host/trace_streamer/src/table/args_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c56414892c5f9fbe923ad7eab72a9aa07080c2f0 --- /dev/null +++ b/host/trace_streamer/src/table/args_table.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "args_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, KEY, DATATYPE, VALUE, ARGSETID }; +} +ArgsTable::ArgsTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("key", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("datatype", "UNSIGNED SHORT")); + tableColumn_.push_back(TableBase::ColumnInfo("value", "BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("argset", "UNSIGNED INT")); + tablePriKey_.push_back("id"); +} + +ArgsTable::~ArgsTable() {} + +void ArgsTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +ArgsTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstArgSetData().Size())), + argSet_(dataCache->GetConstArgSetData()) +{ +} + +ArgsTable::Cursor::~Cursor() {} + +int ArgsTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(argSet_.IdsData()[CurrentRow()])); + break; + case KEY: + sqlite3_result_int64(context_, static_cast(argSet_.NamesData()[CurrentRow()])); + break; + case DATATYPE: + sqlite3_result_int64(context_, static_cast(argSet_.DataTypes()[CurrentRow()])); + break; + case VALUE: + sqlite3_result_int64(context_, static_cast(argSet_.ValuesData()[CurrentRow()])); + break; + case ARGSETID: + sqlite3_result_int64(context_, static_cast(argSet_.ArgsData()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/args_table.h b/host/trace_streamer/src/table/args_table.h new file mode 100644 index 0000000000000000000000000000000000000000..fdcea564db0b2a3c5ce55ef93d5f17eeec90edf9 --- /dev/null +++ b/host/trace_streamer/src/table/args_table.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ARGS_TABLE_H +#define ARGS_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class ArgsTable : public TableBase { +public: + enum Column { ID = 0, TYPE = 1, NAME = 2, ARG_ID = 3 }; + explicit ArgsTable(const TraceDataCache* storage); + ~ArgsTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + + private: + const ArgSet& argSet_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // ARGS_TABLE_H diff --git a/host/trace_streamer/src/table/callstack_table.cpp b/host/trace_streamer/src/table/callstack_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0c54940041fb068f871cc362eb8748343b8848b0 --- /dev/null +++ b/host/trace_streamer/src/table/callstack_table.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "callstack_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { + ID = 0, + TS, + DUR, + CALL_ID, + CAT, + NAME, + DEPTH, + COOKIE_ID, + PARENT_ID, + ARGSET, + CHAIN_ID, + SPAN_ID, + PARENT_SPAN_ID, + FLAG, + ARGS +}; +} +CallStackTable::CallStackTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("callid", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("cat", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("depth", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("cookie", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("parent_id", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("argsetid", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("chainId", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("spanId", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("parentSpanId", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("flag", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("args", "STRING")); + tablePriKey_.push_back("callid"); + tablePriKey_.push_back("ts"); + tablePriKey_.push_back("depth"); +} + +CallStackTable::~CallStackTable() {} + +void CallStackTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +CallStackTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstInternalSlicesData().Size())), + slicesObj_(dataCache->GetConstInternalSlicesData()) +{ +} + +CallStackTable::Cursor::~Cursor() {} + +int CallStackTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, CurrentRow()); + break; + case TS: + sqlite3_result_int64(context_, static_cast(slicesObj_.TimeStamData()[CurrentRow()])); + break; + case DUR: + sqlite3_result_int64(context_, static_cast(slicesObj_.DursData()[CurrentRow()])); + break; + case CALL_ID: + sqlite3_result_int64(context_, static_cast(slicesObj_.CallIds()[CurrentRow()])); + break; + case CAT: { + if (slicesObj_.CatsData()[CurrentRow()] != INVALID_UINT64) { + auto catsDataIndex = static_cast(slicesObj_.CatsData()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(catsDataIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case NAME: { + if (slicesObj_.NamesData()[CurrentRow()] != INVALID_UINT64) { + auto nameDataIndex = static_cast(slicesObj_.NamesData()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(nameDataIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case DEPTH: + sqlite3_result_int64(context_, static_cast(slicesObj_.Depths()[CurrentRow()])); + break; + case COOKIE_ID: + if (slicesObj_.Cookies()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(slicesObj_.Cookies()[CurrentRow()])); + } + break; + case PARENT_ID: { + if (slicesObj_.ParentIdData()[CurrentRow()].has_value()) { + sqlite3_result_int64(context_, static_cast(slicesObj_.ParentIdData()[CurrentRow()].value())); + } + break; + } + case ARGSET: + if (slicesObj_.ArgSetIdsData()[CurrentRow()] != INVALID_UINT32) { + sqlite3_result_int64(context_, static_cast(slicesObj_.ArgSetIdsData()[CurrentRow()])); + } + break; + case CHAIN_ID: + sqlite3_result_text(context_, slicesObj_.ChainIds()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr); + break; + case SPAN_ID: + sqlite3_result_text(context_, slicesObj_.SpanIds()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr); + break; + case PARENT_SPAN_ID: + sqlite3_result_text(context_, slicesObj_.ParentSpanIds()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr); + break; + case FLAG: + sqlite3_result_text(context_, slicesObj_.Flags()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr); + break; + case ARGS: + sqlite3_result_text(context_, slicesObj_.ArgsData()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/callstack_table.h b/host/trace_streamer/src/table/callstack_table.h new file mode 100644 index 0000000000000000000000000000000000000000..e902e7a730967ef943536b932c8404f04fe57ab2 --- /dev/null +++ b/host/trace_streamer/src/table/callstack_table.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CALL_STACK_TABLE_H +#define CALL_STACK_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class CallStackTable : public TableBase { +public: + explicit CallStackTable(const TraceDataCache* dataCache); + ~CallStackTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + + private: + const CallStack& slicesObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // CALL_STACK_TABLE_H diff --git a/host/trace_streamer/src/table/clk_event_filter_table.cpp b/host/trace_streamer/src/table/clk_event_filter_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..40906948a4da2df4b544b7f3e6094295918f26cb --- /dev/null +++ b/host/trace_streamer/src/table/clk_event_filter_table.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "clk_event_filter_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPE, NAME, CPU }; +} +ClkEventFilterTable::ClkEventFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INT")); + tablePriKey_.push_back("id"); +} + +ClkEventFilterTable::~ClkEventFilterTable() {} + +void ClkEventFilterTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +ClkEventFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstClkEventFilterData().Size())) +{ +} + +ClkEventFilterTable::Cursor::~Cursor() {} + +int ClkEventFilterTable::Cursor::Column(int col) const +{ + switch (col) { + case ID: + sqlite3_result_int64(context_, + static_cast(dataCache_->GetConstClkEventFilterData().IdsData()[CurrentRow()])); + break; + case TYPE: { + size_t typeId = static_cast(dataCache_->GetConstClkEventFilterData().RatesData()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(typeId).c_str(), STR_DEFAULT_LEN, nullptr); + break; + } + case NAME: { + size_t strId = + static_cast(dataCache_->GetConstClkEventFilterData().NamesData()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(strId).c_str(), STR_DEFAULT_LEN, nullptr); + break; + } + case CPU: + sqlite3_result_int64(context_, + static_cast(dataCache_->GetConstClkEventFilterData().CpusData()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", col); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/clk_event_filter_table.h b/host/trace_streamer/src/table/clk_event_filter_table.h new file mode 100644 index 0000000000000000000000000000000000000000..37a69ff487be275ecb7aee62b04a40a0922c13b2 --- /dev/null +++ b/host/trace_streamer/src/table/clk_event_filter_table.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_CLK_EVENT_FILTER_TABLE_H +#define SRC_CLK_EVENT_FILTER_TABLE_H + + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class ClkEventFilterTable : public TableBase { +public: + explicit ClkEventFilterTable(const TraceDataCache*); + ~ClkEventFilterTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int col) const override; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // SRC_CLK_EVENT_FILTER_TABLE_H diff --git a/host/trace_streamer/src/table/clock_event_filter_table.cpp b/host/trace_streamer/src/table/clock_event_filter_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a123ed86c6e07cd64daf3c415e5b90df2ca3223a --- /dev/null +++ b/host/trace_streamer/src/table/clock_event_filter_table.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "clock_event_filter_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPE, NAME, CPU }; +} +ClockEventFilterTable::ClockEventFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INT")); + tablePriKey_.push_back("id"); +} + +ClockEventFilterTable::~ClockEventFilterTable() {} + +void ClockEventFilterTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +ClockEventFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstClockEventFilterData().Size())) +{ +} + +ClockEventFilterTable::Cursor::~Cursor() {} + +int ClockEventFilterTable::Cursor::Column(int col) const +{ + switch (col) { + case ID: + sqlite3_result_int64(context_, static_cast( + dataCache_->GetConstClockEventFilterData().IdsData()[CurrentRow()])); + break; + case TYPE: { + size_t typeId = static_cast(dataCache_->GetConstClockEventFilterData().TypesData()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(typeId).c_str(), STR_DEFAULT_LEN, nullptr); + break; + } + case NAME: { + size_t strId = static_cast(dataCache_->GetConstClockEventFilterData().NamesData()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(strId).c_str(), STR_DEFAULT_LEN, nullptr); + break; + } + case CPU: + sqlite3_result_int64(context_, static_cast( + dataCache_->GetConstClockEventFilterData().CpusData()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", col); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/clock_event_filter_table.h b/host/trace_streamer/src/table/clock_event_filter_table.h new file mode 100644 index 0000000000000000000000000000000000000000..d7e3cb0e617f514ce14a3765b838520fa2863cf8 --- /dev/null +++ b/host/trace_streamer/src/table/clock_event_filter_table.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_CLOCK_EVENT_FILTER_TABLE_H +#define SRC_CLOCK_EVENT_FILTER_TABLE_H + + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class ClockEventFilterTable : public TableBase { +public: + explicit ClockEventFilterTable(const TraceDataCache* dataCache); + ~ClockEventFilterTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int col) const override; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // SRC_CLOCK_EVENT_FILTER_TABLE_H diff --git a/host/trace_streamer/src/table/cpu_measure_filter_table.cpp b/host/trace_streamer/src/table/cpu_measure_filter_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ba89f946a98168b9251e5888917abb68cfb68480 --- /dev/null +++ b/host/trace_streamer/src/table/cpu_measure_filter_table.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cpu_measure_filter_table.h" +#include "log.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPE, NAME, CPU }; +} +CpuMeasureFilterTable::CpuMeasureFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu", "UNSIGNED INT")); + tablePriKey_.push_back("id"); +} + +CpuMeasureFilterTable::~CpuMeasureFilterTable() {} + +void CpuMeasureFilterTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +CpuMeasureFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstCpuMeasureData().Size())), + cpuMeasureObj_(dataCache->GetConstCpuMeasureData()) +{ +} + +CpuMeasureFilterTable::Cursor::~Cursor() {} + +int CpuMeasureFilterTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(cpuMeasureObj_.IdsData()[CurrentRow()])); + break; + case TYPE: + sqlite3_result_text(context_, "cpu_measure_filter", STR_DEFAULT_LEN, nullptr); + break; + case NAME: { + const std::string& str = + dataCache_->GetDataFromDict(static_cast(cpuMeasureObj_.NameData()[CurrentRow()])); + sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr); + break; + } + case CPU: + sqlite3_result_int64(context_, static_cast(cpuMeasureObj_.CpuData()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/cpu_measure_filter_table.h b/host/trace_streamer/src/table/cpu_measure_filter_table.h new file mode 100644 index 0000000000000000000000000000000000000000..7463d156585d923170bae1dedec205c0f7a95c0a --- /dev/null +++ b/host/trace_streamer/src/table/cpu_measure_filter_table.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CPU_MEASURE_FILTER_TABLE_H +#define CPU_MEASURE_FILTER_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class CpuMeasureFilterTable : public TableBase { +public: + explicit CpuMeasureFilterTable(const TraceDataCache* dataCache); + ~CpuMeasureFilterTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + + private: + const CpuMeasureFilter& cpuMeasureObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // CPU_MEASURE_FILTER_TABLE_H diff --git a/host/trace_streamer/src/table/data_dict_table.cpp b/host/trace_streamer/src/table/data_dict_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9624bf49432198bec13beca64c84a23aeb9ea3fa --- /dev/null +++ b/host/trace_streamer/src/table/data_dict_table.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_dict_table.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, STR }; +} +DataDictTable::DataDictTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("data", "STRING")); + tablePriKey_.push_back("id"); +} + +DataDictTable::~DataDictTable() {} + +void DataDictTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +DataDictTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->DataDictSize())) +{ +} + +DataDictTable::Cursor::~Cursor() {} + +int DataDictTable::Cursor::Column(int col) const +{ + DataIndex index = static_cast(CurrentRow()); + switch (col) { + case ID: + sqlite3_result_int64(context_, static_cast(CurrentRow())); + break; + case STR: + sqlite3_result_text(context_, dataCache_->GetDataFromDict(index).c_str(), STR_DEFAULT_LEN, nullptr); + break; + default: + TS_LOGF("Unknown column %d", col); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/data_dict_table.h b/host/trace_streamer/src/table/data_dict_table.h new file mode 100644 index 0000000000000000000000000000000000000000..9f431e8526e9c2327ebd013718680073326edfeb --- /dev/null +++ b/host/trace_streamer/src/table/data_dict_table.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DATA_DICT_TABLE_H +#define DATA_DICT_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class DataDictTable : public TableBase { +public: + explicit DataDictTable(const TraceDataCache* dataCache); + ~DataDictTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int col) const override; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // DATA_DICT_TABLE_H diff --git a/host/trace_streamer/src/table/data_type_table.cpp b/host/trace_streamer/src/table/data_type_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..479135abe998ffe02671f3cbcc3157fa7276a16d --- /dev/null +++ b/host/trace_streamer/src/table/data_type_table.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_type_table.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPEID, DESC }; +} +DataTypeTable::DataTypeTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("typeId", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("desc", "STRING")); + tablePriKey_.push_back("id"); +} + +DataTypeTable::~DataTypeTable() {} + +void DataTypeTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +DataTypeTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstDataTypeData().Size())), + dataTypeObj_(dataCache->GetConstDataTypeData()) +{ +} + +DataTypeTable::Cursor::~Cursor() {} + +int DataTypeTable::Cursor::Column(int col) const +{ + switch (col) { + case ID: + sqlite3_result_int64(context_, static_cast(CurrentRow())); + break; + case TYPEID: + sqlite3_result_int64(context_, static_cast(dataTypeObj_.DataTypes()[CurrentRow()])); + break; + case DESC: + sqlite3_result_text(context_, dataCache_->GetDataFromDict(dataTypeObj_.DataDesc()[CurrentRow()]).c_str(), + STR_DEFAULT_LEN, nullptr); + break; + default: + TS_LOGF("Unknown column %d", col); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/data_type_table.h b/host/trace_streamer/src/table/data_type_table.h new file mode 100644 index 0000000000000000000000000000000000000000..af518f538f34159b7abe0f53d5397ae61e1068a7 --- /dev/null +++ b/host/trace_streamer/src/table/data_type_table.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DATA_TYPE_TABLE_H +#define DATA_TYPE_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class DataTypeTable : public TableBase { +public: + explicit DataTypeTable(const TraceDataCache*); + ~DataTypeTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int col) const override; + private: + const DataType& dataTypeObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // DATA_TYPE_TABLE_H diff --git a/host/trace_streamer/src/table/filter_table.cpp b/host/trace_streamer/src/table/filter_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..471cca7f75017687b11d728f1ea35ab900e7972f --- /dev/null +++ b/host/trace_streamer/src/table/filter_table.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "filter_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPE, NAME, SOURCE_ARG_SET_ID }; +} +FilterTable::FilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("source_arg_set_id", "UNSIGNED BIG INT")); + tablePriKey_.push_back("id"); +} + +FilterTable::~FilterTable() {} + +void FilterTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +FilterTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstFilterData().Size())), + filterObj_(dataCache->GetConstFilterData()) +{ +} + +FilterTable::Cursor::~Cursor() {} + +int FilterTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(filterObj_.IdsData()[CurrentRow()])); + break; + case TYPE: + sqlite3_result_text(context_, filterObj_.TypeData()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr); + break; + case NAME: + sqlite3_result_text(context_, filterObj_.NameData()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr); + break; + case SOURCE_ARG_SET_ID: + sqlite3_result_int64(context_, static_cast(filterObj_.SourceArgSetIdData()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/filter_table.h b/host/trace_streamer/src/table/filter_table.h new file mode 100644 index 0000000000000000000000000000000000000000..5b5a359b5d9ebe7950b8af912733a4b8b61af23d --- /dev/null +++ b/host/trace_streamer/src/table/filter_table.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FILTER_TABLE_H +#define FILTER_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class FilterTable : public TableBase { +public: + enum Column { ID = 0, TYPE = 1, NAME = 2, ARG_ID = 3 }; + explicit FilterTable(const TraceDataCache* storage); + ~FilterTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + + private: + const Filter& filterObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // FILTER_TABLE_H diff --git a/host/trace_streamer/src/table/heap_frame_table.cpp b/host/trace_streamer/src/table/heap_frame_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90afefaa54b7b2f0c72e7deeca9d158e1cae0674 --- /dev/null +++ b/host/trace_streamer/src/table/heap_frame_table.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "heap_frame_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { EVENT_ID = 0, DEPTH, IP, SP, SYMBOL_NAME, FILE_PATH, OFFSET, SYMBOL_OFFSET }; +} +HeapFrameTable::HeapFrameTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("eventId", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("depth", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("ip", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("sp", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("symbol_name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("file_path", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("offset", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("symbol_offset", "UNSIGNED BIG INT")); + tablePriKey_.push_back("eventId"); +} + +HeapFrameTable::~HeapFrameTable() {} + +void HeapFrameTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +HeapFrameTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstHeapFrameData().Size())), + heapFrameInfoObj_(dataCache->GetConstHeapFrameData()) +{ +} + +HeapFrameTable::Cursor::~Cursor() {} + +int HeapFrameTable::Cursor::Column(int column) const +{ + switch (column) { + case EVENT_ID: + sqlite3_result_int64(context_, static_cast(heapFrameInfoObj_.EventIds()[CurrentRow()])); + break; + case DEPTH: + sqlite3_result_int64(context_, static_cast(heapFrameInfoObj_.Depths()[CurrentRow()])); + break; + case IP: + sqlite3_result_int64(context_, static_cast(heapFrameInfoObj_.Ips()[CurrentRow()])); + break; + case SP: { + sqlite3_result_int64(context_, static_cast(heapFrameInfoObj_.Sps()[CurrentRow()])); + break; + } + case SYMBOL_NAME: + if (heapFrameInfoObj_.SymbolNames()[CurrentRow()] != INVALID_UINT64) { + auto symbolNameDataIndex = static_cast(heapFrameInfoObj_.SymbolNames()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(symbolNameDataIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + case FILE_PATH: { + if (heapFrameInfoObj_.FilePaths()[CurrentRow()] != INVALID_UINT64) { + auto filePathDataIndex = static_cast(heapFrameInfoObj_.FilePaths()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(filePathDataIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case OFFSET: { + sqlite3_result_int64(context_, static_cast(heapFrameInfoObj_.Offsets()[CurrentRow()])); + break; + } + case SYMBOL_OFFSET: { + sqlite3_result_int64(context_, static_cast(heapFrameInfoObj_.SymbolOffsets()[CurrentRow()])); + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/heap_frame_table.h b/host/trace_streamer/src/table/heap_frame_table.h new file mode 100644 index 0000000000000000000000000000000000000000..572b66739f1ca91044b49f3dce7f08d76f08bce3 --- /dev/null +++ b/host/trace_streamer/src/table/heap_frame_table.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HEAP_FRAME_TABLE_H +#define HEAP_FRAME_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class HeapFrameTable : public TableBase { +public: + explicit HeapFrameTable(const TraceDataCache* dataCache); + ~HeapFrameTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + + private: + const HeapFrameInfo& heapFrameInfoObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // HEAP_FRAME_TABLE_H diff --git a/host/trace_streamer/src/table/heap_table.cpp b/host/trace_streamer/src/table/heap_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aee2925fe45440b9dd2e54db9ce7a2da784d34d4 --- /dev/null +++ b/host/trace_streamer/src/table/heap_table.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "heap_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { + EVENT_ID = 0, + IPID, + ITID, + EVENT_TYPE, + START_TS, + END_TS, + DURATION, + ADDR, + HEAP_SIZE, + ALL_HEAP_SIZE, + CURRENT_SIZE_DUR +}; +} +HeapTable::HeapTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("eventId", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("ipid", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("event_type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("addr", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("heap_size", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("all_heap_size", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("current_size_dur", "UNSIGNED INT")); + tablePriKey_.push_back("eventId"); +} + +HeapTable::~HeapTable() {} + +void HeapTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +HeapTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstHeapData().Size())), + heapInfoObj_(dataCache->GetConstHeapData()) +{ +} + +HeapTable::Cursor::~Cursor() {} + +int HeapTable::Cursor::Column(int column) const +{ + switch (column) { + case EVENT_ID: + sqlite3_result_int64(context_, static_cast(heapInfoObj_.EventIds()[CurrentRow()])); + break; + case IPID: + sqlite3_result_int64(context_, static_cast(heapInfoObj_.Ipids()[CurrentRow()])); + break; + case ITID: + sqlite3_result_int64(context_, static_cast(heapInfoObj_.Itids()[CurrentRow()])); + break; + case EVENT_TYPE: { + if (heapInfoObj_.EventTypes()[CurrentRow()] != INVALID_UINT64) { + auto eventTypeDataIndex = static_cast(heapInfoObj_.EventTypes()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(eventTypeDataIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case START_TS: + sqlite3_result_int64(context_, static_cast(heapInfoObj_.TimeStamData()[CurrentRow()])); + break; + case END_TS: + if (static_cast(heapInfoObj_.EndTimeStamps()[CurrentRow()]) != 0) { + sqlite3_result_int64(context_, static_cast(heapInfoObj_.EndTimeStamps()[CurrentRow()])); + } + break; + case DURATION: + if (static_cast(heapInfoObj_.Durations()[CurrentRow()]) != 0) { + sqlite3_result_int64(context_, static_cast(heapInfoObj_.Durations()[CurrentRow()])); + } + break; + case ADDR: { + sqlite3_result_int64(context_, static_cast(heapInfoObj_.Addrs()[CurrentRow()])); + break; + } + case HEAP_SIZE: { + sqlite3_result_int64(context_, static_cast(heapInfoObj_.HeapSizes()[CurrentRow()])); + break; + } + case ALL_HEAP_SIZE: { + sqlite3_result_int64(context_, static_cast(heapInfoObj_.AllHeapSizes()[CurrentRow()])); + break; + } + case CURRENT_SIZE_DUR: { + sqlite3_result_int64(context_, static_cast(heapInfoObj_.CurrentSizeDurs()[CurrentRow()])); + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/heap_table.h b/host/trace_streamer/src/table/heap_table.h new file mode 100644 index 0000000000000000000000000000000000000000..704f16d2f7781d337d0a8d0c997cc7f2c976d677 --- /dev/null +++ b/host/trace_streamer/src/table/heap_table.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HEAP_TABLE_H +#define HEAP_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class HeapTable : public TableBase { +public: + explicit HeapTable(const TraceDataCache* dataCache); + ~HeapTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + + private: + const HeapInfo& heapInfoObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // HEAP_TABLE_H diff --git a/host/trace_streamer/src/table/hidump_table.cpp b/host/trace_streamer/src/table/hidump_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0b3cb174bc7b4e7becd51e9d8aa5d95d5020659d --- /dev/null +++ b/host/trace_streamer/src/table/hidump_table.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hidump_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { TS = 0, FPS }; +} +HidumpTable::HidumpTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("fps", "UNSIGNED INT")); + tablePriKey_.push_back("ts"); +} + +HidumpTable::~HidumpTable() {} + +void HidumpTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +HidumpTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstHidumpData().Size())), + hidumpObj_(dataCache->GetConstHidumpData()) +{ +} + +HidumpTable::Cursor::~Cursor() {} + +int HidumpTable::Cursor::Column(int column) const +{ + switch (column) { + case TS: + sqlite3_result_int64(context_, static_cast(hidumpObj_.TimeStamData()[CurrentRow()])); + break; + case FPS: { + sqlite3_result_int64(context_, static_cast(hidumpObj_.Fpss()[CurrentRow()])); + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/hidump_table.h b/host/trace_streamer/src/table/hidump_table.h new file mode 100644 index 0000000000000000000000000000000000000000..8c1bb1e8a50624765f43f94980d8c1ade9bfa620 --- /dev/null +++ b/host/trace_streamer/src/table/hidump_table.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HIDUMP_TABLE_H +#define HIDUMP_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class HidumpTable : public TableBase { +public: + explicit HidumpTable(const TraceDataCache* dataCache); + ~HidumpTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + + private: + const Hidump& hidumpObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // HIDUMP_TABLE_H diff --git a/host/trace_streamer/src/table/instants_table.cpp b/host/trace_streamer/src/table/instants_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9d4ec7099671caf0f906e4c9e512b44500232ef1 --- /dev/null +++ b/host/trace_streamer/src/table/instants_table.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "instants_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { TS = 0, NAME, REF, REF_TYPE }; +} +InstantsTable::InstantsTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("ref", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("ref_type", "STRING")); + tablePriKey_.push_back("ts"); + tablePriKey_.push_back("ref"); +} + +InstantsTable::~InstantsTable() {} + +void InstantsTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +InstantsTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstInstantsData().Size())), + InstantsObj_(dataCache->GetConstInstantsData()) +{ +} + +InstantsTable::Cursor::~Cursor() {} + +int InstantsTable::Cursor::Column(int column) const +{ + size_t stringIdentity = static_cast(InstantsObj_.NameIndexsData()[CurrentRow()]); + switch (column) { + case TS: + sqlite3_result_int64(context_, static_cast(InstantsObj_.TimeStamData()[CurrentRow()])); + break; + case NAME: { + sqlite3_result_text(context_, dataCache_->GetDataFromDict(stringIdentity).c_str(), + STR_DEFAULT_LEN, nullptr); + break; + } + case REF: + sqlite3_result_int64(context_, static_cast(InstantsObj_.InternalTidsData()[CurrentRow()])); + break; + case REF_TYPE: { + sqlite3_result_text(context_, "itid", STR_DEFAULT_LEN, nullptr); + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/instants_table.h b/host/trace_streamer/src/table/instants_table.h new file mode 100644 index 0000000000000000000000000000000000000000..06b7c0aedeb7329600b06e47dc2d5b04a9d19e30 --- /dev/null +++ b/host/trace_streamer/src/table/instants_table.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INSTANTS_TABLE_H +#define INSTANTS_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class InstantsTable : public TableBase { +public: + explicit InstantsTable(const TraceDataCache* dataCache); + ~InstantsTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + + private: + const Instants& InstantsObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // INSTANTS_TABLE_H diff --git a/host/trace_streamer/src/table/irq_table.cpp b/host/trace_streamer/src/table/irq_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a6e6a76b132b3e917471b9cd7a33641142f20ec0 --- /dev/null +++ b/host/trace_streamer/src/table/irq_table.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "irq_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { + ID = 0, + TS, + DUR, + CALL_ID, + CAT, + NAME, + DEPTH, + COOKIE_ID, + PARENT_ID, + ARGSET, + CHAIN_ID, + SPAN_ID, + PARENT_SPAN_ID, + FLAG, + ARGS +}; +} +IrqTable::IrqTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("callid", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("cat", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("depth", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("cookie", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("parent_id", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("argsetid", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("chainId", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("spanId", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("parentSpanId", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("flag", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("args", "STRING")); + tablePriKey_.push_back("callid"); + tablePriKey_.push_back("ts"); + tablePriKey_.push_back("depth"); +} + +IrqTable::~IrqTable() {} + +void IrqTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +IrqTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstIrqData().Size())), + slicesObj_(dataCache->GetConstIrqData()) +{ +} + +IrqTable::Cursor::~Cursor() {} + +int IrqTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, CurrentRow()); + break; + case TS: + sqlite3_result_int64(context_, static_cast(slicesObj_.TimeStamData()[CurrentRow()])); + break; + case DUR: + sqlite3_result_int64(context_, static_cast(slicesObj_.DursData()[CurrentRow()])); + break; + case CALL_ID: + sqlite3_result_int64(context_, static_cast(slicesObj_.CallIds()[CurrentRow()])); + break; + case CAT: { + if (slicesObj_.CatsData()[CurrentRow()] != INVALID_UINT64) { + auto catsDataIndex = static_cast(slicesObj_.CatsData()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(catsDataIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case NAME: { + if (slicesObj_.NamesData()[CurrentRow()] != INVALID_UINT64) { + auto nameDataIndex = static_cast(slicesObj_.NamesData()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(nameDataIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case DEPTH: + sqlite3_result_int64(context_, static_cast(slicesObj_.Depths()[CurrentRow()])); + break; + case COOKIE_ID: + if (slicesObj_.Cookies()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(slicesObj_.Cookies()[CurrentRow()])); + } + break; + case PARENT_ID: { + if (slicesObj_.ParentIdData()[CurrentRow()].has_value()) { + sqlite3_result_int64(context_, static_cast(slicesObj_.ParentIdData()[CurrentRow()].value())); + } + break; + } + case ARGSET: + if (slicesObj_.ArgSetIdsData()[CurrentRow()] != INVALID_UINT32) { + sqlite3_result_int64(context_, static_cast(slicesObj_.ArgSetIdsData()[CurrentRow()])); + } + break; + case CHAIN_ID: + sqlite3_result_text(context_, slicesObj_.ChainIds()[CurrentRow()].c_str(), + STR_DEFAULT_LEN, nullptr); + break; + case SPAN_ID: + sqlite3_result_text(context_, slicesObj_.SpanIds()[CurrentRow()].c_str(), + STR_DEFAULT_LEN, nullptr); + break; + case PARENT_SPAN_ID: + sqlite3_result_text(context_, + slicesObj_.ParentSpanIds()[CurrentRow()].c_str(), + STR_DEFAULT_LEN, nullptr); + break; + case FLAG: + sqlite3_result_text(context_, slicesObj_.Flags()[CurrentRow()].c_str(), + STR_DEFAULT_LEN, nullptr); + break; + case ARGS: + sqlite3_result_text(context_, slicesObj_.ArgsData()[CurrentRow()].c_str(), + STR_DEFAULT_LEN, nullptr); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/irq_table.h b/host/trace_streamer/src/table/irq_table.h new file mode 100644 index 0000000000000000000000000000000000000000..46b22c7f63c2b6762348830dc53bac25dbdc6525 --- /dev/null +++ b/host/trace_streamer/src/table/irq_table.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IRQ_TABLE_H +#define IRQ_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class IrqTable : public TableBase { +public: + explicit IrqTable(const TraceDataCache* dataCache); + ~IrqTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + + private: + const CallStack& slicesObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // IRQ_TABLE_H diff --git a/host/trace_streamer/src/table/log_table.cpp b/host/trace_streamer/src/table/log_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53b542c49a8fcaf7a41242d198c4783780e78d56 --- /dev/null +++ b/host/trace_streamer/src/table/log_table.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "log_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { SEQ = 0, TS, PID, TID, LEVEL, TAG, CONTEXT, ORIGINTS }; +} +LogTable::LogTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("seq", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("pid", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("tid", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("level", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("tag", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("context", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("origints", "UNSIGNED BIG INT")); + tablePriKey_.push_back("ts"); +} + +LogTable::~LogTable() {} + +void LogTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +LogTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstHilogData().Size())), + logInfoObj_(dataCache->GetConstHilogData()) +{ +} + +LogTable::Cursor::~Cursor() {} + +int LogTable::Cursor::Column(int column) const +{ + switch (column) { + case SEQ: + sqlite3_result_int64(context_, static_cast(logInfoObj_.HilogLineSeqs()[CurrentRow()])); + break; + case TS: + sqlite3_result_int64(context_, static_cast(logInfoObj_.TimeStamData()[CurrentRow()])); + break; + case PID: { + sqlite3_result_int64(context_, static_cast(logInfoObj_.Pids()[CurrentRow()])); + break; + } + case TID: + sqlite3_result_int64(context_, static_cast(logInfoObj_.Tids()[CurrentRow()])); + break; + case LEVEL: { + if (logInfoObj_.Levels()[CurrentRow()] != INVALID_UINT64) { + auto levelDataIndex = static_cast(logInfoObj_.Levels()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(levelDataIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case TAG: { + if (logInfoObj_.Tags()[CurrentRow()] != INVALID_UINT64) { + auto tagDataIndex = static_cast(logInfoObj_.Tags()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(tagDataIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case CONTEXT: { + if (logInfoObj_.Contexts()[CurrentRow()] != INVALID_UINT64) { + auto contextDataIndex = static_cast(logInfoObj_.Contexts()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(contextDataIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case ORIGINTS: { + sqlite3_result_int64(context_, static_cast(logInfoObj_.OriginTimeStamData()[CurrentRow()])); + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/log_table.h b/host/trace_streamer/src/table/log_table.h new file mode 100644 index 0000000000000000000000000000000000000000..22c5042b6c35816e8b52265aa8d767427f7d017b --- /dev/null +++ b/host/trace_streamer/src/table/log_table.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LOG_TABLE_H +#define LOG_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class LogTable : public TableBase { +public: + explicit LogTable(const TraceDataCache* dataCache); + ~LogTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + + private: + const LogInfo& logInfoObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // LOG_TABLE_H diff --git a/host/trace_streamer/src/table/measure_filter_table.cpp b/host/trace_streamer/src/table/measure_filter_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..18131ee0f9516e26cfcb99f8e5c64daa2daeaf79 --- /dev/null +++ b/host/trace_streamer/src/table/measure_filter_table.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "measure_filter_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPE, NAME, INTERNAL_TID }; +} +MeasureFilterTable::MeasureFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "UNSIGNED INT")); + tablePriKey_.push_back("id"); +} + +MeasureFilterTable::~MeasureFilterTable() {} + +void MeasureFilterTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +MeasureFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstThreadMeasureFilterData().Size())) +{ +} + +MeasureFilterTable::Cursor::~Cursor() {} + +int MeasureFilterTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64( + context_, + static_cast(dataCache_->GetConstThreadMeasureFilterData().FilterIdData()[CurrentRow()])); + break; + case TYPE: + sqlite3_result_text(context_, "thread_measure_filter", STR_DEFAULT_LEN, nullptr); + break; + case NAME: { + const std::string& str = dataCache_->GetDataFromDict( + dataCache_->GetConstThreadMeasureFilterData().NameIndexData()[CurrentRow()]); + sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr); + break; + } + case INTERNAL_TID: + sqlite3_result_int64(context_, + static_cast(dataCache_->GetConstThreadMeasureFilterData().InternalTidData()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/measure_filter_table.h b/host/trace_streamer/src/table/measure_filter_table.h new file mode 100644 index 0000000000000000000000000000000000000000..54e8ceed1211b0a2701c56b8ed321afcefca8abb --- /dev/null +++ b/host/trace_streamer/src/table/measure_filter_table.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_MEASURE_FILTER_H +#define THREAD_MEASURE_FILTER_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class MeasureFilterTable : public TableBase { +public: + explicit MeasureFilterTable(const TraceDataCache* dataCache); + ~MeasureFilterTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // THREAD_MEASURE_FILTER_H diff --git a/host/trace_streamer/src/table/measure_table.cpp b/host/trace_streamer/src/table/measure_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2636dc70b6f2f4902626fbdd2a12574405bf3c0b --- /dev/null +++ b/host/trace_streamer/src/table/measure_table.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "measure_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { TYPE = 0, TS, VALUE, FILTER_ID }; +} +MeasureTable::MeasureTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("value", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("filter_id", "UNSIGNED INT")); + tablePriKey_.push_back("ts"); + tablePriKey_.push_back("filter_id"); +} + +MeasureTable::~MeasureTable() {} + +void MeasureTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +MeasureTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstMeasureData().Size())), + measureObj(dataCache->GetConstMeasureData()) +{ +} + +MeasureTable::Cursor::~Cursor() {} + +int MeasureTable::Cursor::Column(int column) const +{ + switch (column) { + case TYPE: + sqlite3_result_text(context_, "measure", STR_DEFAULT_LEN, nullptr); + break; + case TS: + sqlite3_result_int64(context_, static_cast(measureObj.TimeStamData()[CurrentRow()])); + break; + case VALUE: + sqlite3_result_int64(context_, static_cast(measureObj.ValuesData()[CurrentRow()])); + break; + case FILTER_ID: + sqlite3_result_int64(context_, static_cast(measureObj.FilterIdData()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/measure_table.h b/host/trace_streamer/src/table/measure_table.h new file mode 100644 index 0000000000000000000000000000000000000000..418730d13737321e81e5b7e804c101dd26192170 --- /dev/null +++ b/host/trace_streamer/src/table/measure_table.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MEASURE_TABLE_H +#define MEASURE_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class MeasureTable : public TableBase { +public: + explicit MeasureTable(const TraceDataCache* dataCache); + ~MeasureTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + + private: + const Measure& measureObj; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // MEASURE_TABLE_H diff --git a/host/trace_streamer/src/table/meta_table.cpp b/host/trace_streamer/src/table/meta_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4d9304cfdf802bb03a3897b228f4e69db39686b4 --- /dev/null +++ b/host/trace_streamer/src/table/meta_table.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "meta_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { NAMEINDEX = 0, VALUE }; +} +MetaTable::MetaTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("value", "STRING")); + tablePriKey_.push_back("name"); +} + +MetaTable::~MetaTable() {} + +void MetaTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +MetaTable::Cursor::Cursor(const TraceDataCache* dataCache) : TableBase::Cursor(dataCache, 0, METADATA_ITEM_MAX) {} + +MetaTable::Cursor::~Cursor() {} + +int MetaTable::Cursor::Column(int column) const +{ + switch (column) { + case NAMEINDEX: + sqlite3_result_text(context_, dataCache_->GetConstMetaData().Name(CurrentRow()).c_str(), STR_DEFAULT_LEN, + nullptr); + break; + case VALUE: + sqlite3_result_text(context_, dataCache_->GetConstMetaData().Value(CurrentRow()).c_str(), STR_DEFAULT_LEN, + nullptr); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/meta_table.h b/host/trace_streamer/src/table/meta_table.h new file mode 100644 index 0000000000000000000000000000000000000000..e75e71b7143c8e90aba91c574dea77aff38974e7 --- /dev/null +++ b/host/trace_streamer/src/table/meta_table.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef META_TABLE_H +#define META_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class MetaTable : public TableBase { +public: + explicit MetaTable(const TraceDataCache* dataCache); + ~MetaTable() override; + void CreateCursor() override; +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // META_TABLE_H diff --git a/host/trace_streamer/src/table/process_filter_table.cpp b/host/trace_streamer/src/table/process_filter_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63bba49acda433425cb067c514fd388aae51577d --- /dev/null +++ b/host/trace_streamer/src/table/process_filter_table.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "process_filter_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPE, NAME, INTERNAL_PID }; +} +ProcessFilterTable::ProcessFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("ipid", "UNSIGNED INT")); + tablePriKey_.push_back("id"); +} + +ProcessFilterTable::~ProcessFilterTable() {} + +void ProcessFilterTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +ProcessFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstProcessFilterData().Size())), + processFilterObj_(dataCache->GetConstProcessFilterData()) +{ +} + +ProcessFilterTable::Cursor::~Cursor() {} + +int ProcessFilterTable::Cursor::Column(int col) const +{ + switch (col) { + case ID: + sqlite3_result_int64(context_, static_cast(processFilterObj_.IdsData()[CurrentRow()])); + break; + case TYPE: + sqlite3_result_text(context_, "process_filter", STR_DEFAULT_LEN, nullptr); + break; + case NAME: { + DataIndex stringIdentity = static_cast(processFilterObj_.NamesData()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(stringIdentity).c_str(), STR_DEFAULT_LEN, + nullptr); + break; + } + case INTERNAL_PID: + sqlite3_result_int64(context_, static_cast(processFilterObj_.UpidsData()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", col); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/process_filter_table.h b/host/trace_streamer/src/table/process_filter_table.h new file mode 100644 index 0000000000000000000000000000000000000000..2e8c2399570e47a770045e6ad9bb928a5be7778d --- /dev/null +++ b/host/trace_streamer/src/table/process_filter_table.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PROCESS_FILTER_TABLE_H +#define PROCESS_FILTER_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class ProcessFilterTable : public TableBase { +public: + explicit ProcessFilterTable(const TraceDataCache* dataCache); + ~ProcessFilterTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int col) const override; + + private: + const ProcessMeasureFilter& processFilterObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // PROCESS_FILTER_TABLE_H diff --git a/host/trace_streamer/src/table/process_measure_filter_table.cpp b/host/trace_streamer/src/table/process_measure_filter_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..afd6e807355eb491de54db17bd86f3ccb17ae677 --- /dev/null +++ b/host/trace_streamer/src/table/process_measure_filter_table.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "process_measure_filter_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPE, NAME, INTERNAL_PID }; +} +ProcessMeasureFilterTable::ProcessMeasureFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INT")); + tablePriKey_.push_back("id"); +} + +ProcessMeasureFilterTable::~ProcessMeasureFilterTable() {} + +void ProcessMeasureFilterTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +ProcessMeasureFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstProcessMeasureFilterData().Size())) +{ +} + +ProcessMeasureFilterTable::Cursor::~Cursor() {} + +int ProcessMeasureFilterTable::Cursor::Column(int col) const +{ + switch (col) { + case ID: + sqlite3_result_int64(context_, static_cast( + dataCache_->GetConstProcessMeasureFilterData().IdsData()[CurrentRow()])); + break; + case TYPE: + sqlite3_result_text(context_, "process_measure_filter", STR_DEFAULT_LEN, nullptr); + break; + case NAME: { + size_t strId = + static_cast(dataCache_->GetConstProcessMeasureFilterData().NamesData()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(strId).c_str(), STR_DEFAULT_LEN, nullptr); + break; + } + case INTERNAL_PID: + sqlite3_result_int64( + context_, + static_cast(dataCache_->GetConstProcessMeasureFilterData().UpidsData()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", col); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/process_measure_filter_table.h b/host/trace_streamer/src/table/process_measure_filter_table.h new file mode 100644 index 0000000000000000000000000000000000000000..5b1ff4ae484e801de8e1871a0781166a4129ee02 --- /dev/null +++ b/host/trace_streamer/src/table/process_measure_filter_table.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_PROCESS_MEASURE_FILTER_TABLE_H +#define SRC_PROCESS_MEASURE_FILTER_TABLE_H + + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class ProcessMeasureFilterTable : public TableBase { +public: + explicit ProcessMeasureFilterTable(const TraceDataCache* dataCache); + ~ProcessMeasureFilterTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int col) const override; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // SRC_PROCESS_MEASURE_FILTER_TABLE_H diff --git a/host/trace_streamer/src/table/process_table.cpp b/host/trace_streamer/src/table/process_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..02b05e70fc8c364e00838ec6adced5609bc83dbf --- /dev/null +++ b/host/trace_streamer/src/table/process_table.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "process_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPE, PID, NAME, START_TS, END_TS, PARENT_ID, UID, APP_ID }; +} +ProcessTable::ProcessTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("pid", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "UNSIGNED INT")); + tablePriKey_.push_back("id"); +} + +ProcessTable::~ProcessTable() {} + +void ProcessTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +ProcessTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->ProcessSize())) +{ +} + +ProcessTable::Cursor::~Cursor() {} + +int ProcessTable::Cursor::Column(int column) const +{ + const auto& process = dataCache_->GetConstProcessData(CurrentRow()); + switch (column) { + case ID: + sqlite3_result_int64(context_, CurrentRow()); + break; + case TYPE: + sqlite3_result_text(context_, "process", STR_DEFAULT_LEN, nullptr); + break; + case PID: + sqlite3_result_int64(context_, process.pid_); + break; + case NAME: + if (process.cmdLine_.size()) { + sqlite3_result_text(context_, process.cmdLine_.c_str(), static_cast(process.cmdLine_.length()), + nullptr); + } + break; + case START_TS: + if (process.startT_) { + sqlite3_result_int64(context_, static_cast(process.startT_)); + } + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/process_table.h b/host/trace_streamer/src/table/process_table.h new file mode 100644 index 0000000000000000000000000000000000000000..a614ba8121b5c8c302e0071e44341d9febdeaca4 --- /dev/null +++ b/host/trace_streamer/src/table/process_table.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PROCESS_TABLE_H +#define PROCESS_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class ProcessTable : public TableBase { +public: + explicit ProcessTable(const TraceDataCache* dataCache); + ~ProcessTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // PROCESS_TABLE_H diff --git a/host/trace_streamer/src/table/range_table.cpp b/host/trace_streamer/src/table/range_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ae9f3c287183514927de83bdf773c9e33e94f45 --- /dev/null +++ b/host/trace_streamer/src/table/range_table.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "range_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { START_TS = 0, END_TS }; +} +RangeTable::RangeTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "INT")); + tablePriKey_.push_back("start_ts"); +} + +RangeTable::~RangeTable() {} + +void RangeTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +RangeTable::Cursor::Cursor(const TraceDataCache* dataCache) : TableBase::Cursor(dataCache, 0, 1) {} + +RangeTable::Cursor::~Cursor() {} + +int RangeTable::Cursor::Column(int column) const +{ + switch (column) { + case START_TS: + sqlite3_result_int64(context_, static_cast(dataCache_->TraceStartTime())); + break; + case END_TS: + sqlite3_result_int64(context_, static_cast(dataCache_->TraceEndTime())); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/range_table.h b/host/trace_streamer/src/table/range_table.h new file mode 100644 index 0000000000000000000000000000000000000000..ea0d8f6ea67d8e80a17c66b743c45ef1b56a9945 --- /dev/null +++ b/host/trace_streamer/src/table/range_table.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RANGE_TABLE_H +#define RANGE_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class RangeTable : public TableBase { +public: + explicit RangeTable(const TraceDataCache* dataCache); + ~RangeTable() override; + void CreateCursor() override; +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // RANGE_TABLE_H diff --git a/host/trace_streamer/src/table/raw_table.cpp b/host/trace_streamer/src/table/raw_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6a1086c63e1167820f54e8d8d12bd3ea78f84f63 --- /dev/null +++ b/host/trace_streamer/src/table/raw_table.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "raw_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPE, TS, NAME, CPU, INTERNAL_TID }; +} +RawTable::RawTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "UNSIGNED INT")); + tablePriKey_.push_back("id"); +} + +RawTable::~RawTable() {} + +void RawTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +RawTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstRawTableData().Size())), + rawObj_(dataCache->GetConstRawTableData()) +{ +} + +RawTable::Cursor::~Cursor() {} + +int RawTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(CurrentRow())); + break; + case TYPE: + sqlite3_result_text(context_, "raw", STR_DEFAULT_LEN, nullptr); + break; + case TS: + sqlite3_result_int64(context_, static_cast(rawObj_.TimeStamData()[CurrentRow()])); + break; + case NAME: { + if (rawObj_.NameData()[CurrentRow()] == CPU_IDLE) { + sqlite3_result_text(context_, "cpu_idle", STR_DEFAULT_LEN, nullptr); + } else if (rawObj_.NameData()[CurrentRow()] == SCHED_WAKEUP) { + sqlite3_result_text(context_, "sched_wakeup", STR_DEFAULT_LEN, nullptr); + } else { + sqlite3_result_text(context_, "sched_waking", STR_DEFAULT_LEN, nullptr); + } + break; + } + case CPU: + sqlite3_result_int64(context_, static_cast(rawObj_.CpuData()[CurrentRow()])); + break; + case INTERNAL_TID: + sqlite3_result_int64(context_, static_cast(rawObj_.InternalTidData()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/raw_table.h b/host/trace_streamer/src/table/raw_table.h new file mode 100644 index 0000000000000000000000000000000000000000..2cc92b0e28d1d2acf4b62cc23a1cad6996dd75f9 --- /dev/null +++ b/host/trace_streamer/src/table/raw_table.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RAW_TABLE_H +#define RAW_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class RawTable : public TableBase { +public: + enum EventName : uint32_t { CPU_IDLE = 1, SCHED_WAKEUP = 2, SCHED_WAKING = 3 }; + explicit RawTable(const TraceDataCache* dataCache); + ~RawTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + + private: + const Raw& rawObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // RAW_TABLE_H diff --git a/host/trace_streamer/src/table/sched_slice_table.cpp b/host/trace_streamer/src/table/sched_slice_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e87e3036d1be77ea10bfd87499fdafcdc6251a8b --- /dev/null +++ b/host/trace_streamer/src/table/sched_slice_table.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sched_slice_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPE, TS, DUR, CPU, INTERNAL_TID, END_STATE, PRIORITY }; +} +SchedSliceTable::SchedSliceTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("end_state", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("priority", "INT")); + tablePriKey_.push_back("id"); +} + +SchedSliceTable::~SchedSliceTable() {} + +void SchedSliceTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +SchedSliceTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstSchedSliceData().Size())), + schedSliceObj_(dataCache->GetConstSchedSliceData()) +{ +} + +SchedSliceTable::Cursor::~Cursor() {} + +int SchedSliceTable::Cursor::Column(int col) const +{ + switch (col) { + case ID: + sqlite3_result_int64(context_, static_cast(CurrentRow())); + break; + case TYPE: + sqlite3_result_text(context_, "sched_slice", STR_DEFAULT_LEN, nullptr); + break; + case TS: + sqlite3_result_int64(context_, static_cast(schedSliceObj_.TimeStamData()[CurrentRow()])); + break; + case DUR: + sqlite3_result_int64(context_, static_cast(schedSliceObj_.DursData()[CurrentRow()])); + break; + case CPU: + sqlite3_result_int64(context_, static_cast(schedSliceObj_.CpusData()[CurrentRow()])); + break; + case INTERNAL_TID: + sqlite3_result_int64(context_, static_cast(schedSliceObj_.InternalTidsData()[CurrentRow()])); + break; + case END_STATE: { + const std::string& str = dataCache_->GetConstSchedStateData(schedSliceObj_.EndStatesData()[CurrentRow()]); + sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr); + break; + } + case PRIORITY: + sqlite3_result_int64(context_, static_cast(schedSliceObj_.PriorityData()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", col); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/sched_slice_table.h b/host/trace_streamer/src/table/sched_slice_table.h new file mode 100644 index 0000000000000000000000000000000000000000..2d4fb34093ae7b54a09cc341f4eb0d5f5ec70aeb --- /dev/null +++ b/host/trace_streamer/src/table/sched_slice_table.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SCHED_SLICE_TABLE_H +#define SCHED_SLICE_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class SchedSliceTable : public TableBase { +public: + explicit SchedSliceTable(const TraceDataCache* dataCache); + ~SchedSliceTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int col) const override; + + private: + const SchedSlice& schedSliceObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // SCHED_SLICE_TABLE_H diff --git a/host/trace_streamer/src/table/stat_table.cpp b/host/trace_streamer/src/table/stat_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7294826aac2e0b8090f05ac2e6aa143489ac1ce4 --- /dev/null +++ b/host/trace_streamer/src/table/stat_table.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stat_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { EVENT_NAME = 0, STAT_EVENT_TYPE = 1, COUNT = 2, SEVERITY = 3, SOURCE = 4 }; +} +StatTable::StatTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("event_name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("stat_type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("count", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("serverity", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("source", "STRING")); + tablePriKey_.push_back("event_name"); + tablePriKey_.push_back("stat_type"); +} + +StatTable::~StatTable() {} + +void StatTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +StatTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, STAT_EVENT_MAX * TRACE_EVENT_MAX) +{ +} + +StatTable::Cursor::~Cursor() {} + +int StatTable::Cursor::Column(int column) const +{ + const StatAndInfo stat = dataCache_->GetConstStatAndInfo(); + SupportedTraceEventType eventType = static_cast(CurrentRow() / STAT_EVENT_MAX); + StatType statType = static_cast(CurrentRow() % STAT_EVENT_MAX); + switch (column) { + case EVENT_NAME: + sqlite3_result_text(context_, dataCache_->GetConstStatAndInfo().GetEvent(eventType).c_str(), + STR_DEFAULT_LEN, nullptr); + break; + case STAT_EVENT_TYPE: + sqlite3_result_text(context_, dataCache_->GetConstStatAndInfo().GetStat(statType).c_str(), + STR_DEFAULT_LEN, nullptr); + break; + case COUNT: + sqlite3_result_int64(context_, static_cast(dataCache_->GetConstStatAndInfo().GetValue(eventType, + statType))); + break; + case SEVERITY: + sqlite3_result_text(context_, dataCache_->GetConstStatAndInfo().GetSeverityDesc(eventType, + statType).c_str(), STR_DEFAULT_LEN, nullptr); + break; + case SOURCE: + sqlite3_result_text(context_, "trace", STR_DEFAULT_LEN, nullptr); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/stat_table.h b/host/trace_streamer/src/table/stat_table.h new file mode 100644 index 0000000000000000000000000000000000000000..1e1fd995b8302924d15c9aa682b525882c0ede30 --- /dev/null +++ b/host/trace_streamer/src/table/stat_table.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STAT_TABLE_H +#define STAT_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class StatTable : public TableBase { +public: + explicit StatTable(const TraceDataCache* dataCache); + ~StatTable() override; + void CreateCursor() override; +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // STAT_TABLE_H diff --git a/host/trace_streamer/src/table/symbols_table.cpp b/host/trace_streamer/src/table/symbols_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4ec5421d287a6edcb4cabfcc363708eda39c7b94 --- /dev/null +++ b/host/trace_streamer/src/table/symbols_table.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "symbols_table.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, STR, ADDR }; +} +SymbolsTable::SymbolsTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("funcname", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("addr", "UNSIGNED BIG INT")); + tablePriKey_.push_back("id"); +} + +SymbolsTable::~SymbolsTable() {} + +void SymbolsTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +SymbolsTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstSymbolsData().Size())) +{ +} + +SymbolsTable::Cursor::~Cursor() {} + +int SymbolsTable::Cursor::Column(int col) const +{ + DataIndex index = static_cast(CurrentRow()); + switch (col) { + case ID: + sqlite3_result_int64(context_, static_cast(CurrentRow())); + break; + case STR: + sqlite3_result_text(context_, + dataCache_->GetDataFromDict(dataCache_->GetConstSymbolsData().GetConstFuncNames()[index]).c_str(), + STR_DEFAULT_LEN, nullptr); + break; + case ADDR: + sqlite3_result_int64(context_, + static_cast(dataCache_->GetConstSymbolsData().GetConstAddrs()[index])); + break; + default: + TS_LOGF("Unknown column %d", col); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/symbols_table.h b/host/trace_streamer/src/table/symbols_table.h new file mode 100644 index 0000000000000000000000000000000000000000..1f9fdeb6cc23c53a7bde70c32ff6cf0f46a0c9bc --- /dev/null +++ b/host/trace_streamer/src/table/symbols_table.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SYMBOLS_DICT_TABLE_H +#define SYMBOLS_DICT_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class SymbolsTable : public TableBase { +public: + explicit SymbolsTable(const TraceDataCache* dataCache); + ~SymbolsTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int col) const override; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // SYMBOLS_DICT_TABLE_H diff --git a/host/trace_streamer/src/table/system_call_table.cpp b/host/trace_streamer/src/table/system_call_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a499eb549c23c923c9e4b9911cced90e7a5c20d5 --- /dev/null +++ b/host/trace_streamer/src/table/system_call_table.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "system_call_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { SYSCALL_NUM = 0, TYPE, IPID, TS, RET }; +} +SystemCallTable::SystemCallTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("syscall_num", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("ipid", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("ret", "INT")); + tablePriKey_.push_back("syscall_num"); +} + +SystemCallTable::~SystemCallTable() {} + +void SystemCallTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +SystemCallTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstSysCallData().Size())), + sysCallObj_(dataCache->GetConstSysCallData()) +{ +} + +SystemCallTable::Cursor::~Cursor() {} + +int SystemCallTable::Cursor::Column(int column) const +{ + switch (column) { + case SYSCALL_NUM: + sqlite3_result_int64(context_, dataCache_->GetConstSysCallData().SysCallsData()[CurrentRow()]); + break; + case TYPE: + sqlite3_result_text(context_, dataCache_->GetDataFromDict(sysCallObj_.TypesData()[CurrentRow()]).c_str(), + STR_DEFAULT_LEN, nullptr); + break; + case IPID: + sqlite3_result_int64(context_, dataCache_->GetConstSysCallData().IpidsData()[CurrentRow()]); + break; + case TS: + sqlite3_result_int64(context_, dataCache_->GetConstSysCallData().TimeStamData()[CurrentRow()]); + break; + case RET: + sqlite3_result_int64(context_, dataCache_->GetConstSysCallData().RetsData()[CurrentRow()]); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/system_call_table.h b/host/trace_streamer/src/table/system_call_table.h new file mode 100644 index 0000000000000000000000000000000000000000..fab317e1100a62dbe99719d959f6af098c4517fa --- /dev/null +++ b/host/trace_streamer/src/table/system_call_table.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SYSCALL_TABLE_H +#define SYSCALL_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class SystemCallTable : public TableBase { +public: + explicit SystemCallTable(const TraceDataCache*); + ~SystemCallTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + private: + const SysCall& sysCallObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // PROCESS_TABLE_H diff --git a/host/trace_streamer/src/table/system_event_filter_table.cpp b/host/trace_streamer/src/table/system_event_filter_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ce23b8ca90016ea8fb1ebad23ba31242da88e5d --- /dev/null +++ b/host/trace_streamer/src/table/system_event_filter_table.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "system_event_filter_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPE, NAME }; +} +SystemEventFilterTable::SystemEventFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tablePriKey_.push_back("id"); +} + +SystemEventFilterTable::~SystemEventFilterTable() {} + +void SystemEventFilterTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +SystemEventFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstSysMeasureFilterData().Size())), + sysEventObj_(dataCache->GetConstSysMeasureFilterData()) +{ +} + +SystemEventFilterTable::Cursor::~Cursor() {} + +int SystemEventFilterTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, sysEventObj_.IdsData()[CurrentRow()]); + break; + case TYPE: + sqlite3_result_text(context_, dataCache_->GetDataFromDict(sysEventObj_.TypesData()[CurrentRow()]).c_str(), + STR_DEFAULT_LEN, nullptr); + break; + case NAME: + sqlite3_result_text(context_, dataCache_->GetDataFromDict(sysEventObj_.NamesData()[CurrentRow()]).c_str(), + STR_DEFAULT_LEN, nullptr); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/system_event_filter_table.h b/host/trace_streamer/src/table/system_event_filter_table.h new file mode 100644 index 0000000000000000000000000000000000000000..80aeb454612c561c6d3fd973c010d1ee7e1e0d03 --- /dev/null +++ b/host/trace_streamer/src/table/system_event_filter_table.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SYSTEM_EVENT_FILTER_TABLE_H +#define SYSTEM_EVENT_FILTER_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class SystemEventFilterTable : public TableBase { +public: + explicit SystemEventFilterTable(const TraceDataCache*); + ~SystemEventFilterTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + private: + const SysMeasureFilter& sysEventObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // SYSTEM_EVENT_FILTER_TABLE_H diff --git a/host/trace_streamer/src/table/table.pri b/host/trace_streamer/src/table/table.pri new file mode 100644 index 0000000000000000000000000000000000000000..a5da2ea2038a16001f1d637561d9524c51e3a57f --- /dev/null +++ b/host/trace_streamer/src/table/table.pri @@ -0,0 +1,78 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +INCLUDEPATH += $$PWD +HEADERS += \ + $$PWD/range_table.h \ + $$PWD/cpu_measure_filter_table.h \ + $$PWD/data_dict_table.h \ + $$PWD/filter_table.h \ + $$PWD/instants_table.h \ + $$PWD/callstack_table.h \ + $$PWD/thread_table.h \ + $$PWD/measure_filter_table.h \ + $$PWD/measure_table.h \ + $$PWD/process_filter_table.h \ + $$PWD/process_measure_filter_table.h \ + $$PWD/process_table.h \ + $$PWD/raw_table.h \ + $$PWD/sched_slice_table.h \ + $$PWD/table_base.h \ + $$PWD/thread_filter_table.h \ + $$PWD/thread_state_table.h \ + $$PWD/clock_event_filter_table.h \ + $$PWD/clk_event_filter_table.h \ + $$PWD/stat_table.h \ + $$PWD/meta_table.h \ + $$PWD/symbols_table.h \ + $$PWD/system_call_table.h \ + $$PWD/log_table.h \ + $$PWD/heap_table.h \ + $$PWD/heap_frame_table.h \ + $$PWD/hidump_table.h \ + $$PWD/args_table.h \ + $$PWD/data_type_table.h \ + $$PWD/system_event_filter_table.h + +SOURCES += \ + $$PWD/range_table.cpp \ + $$PWD/cpu_measure_filter_table.cpp \ + $$PWD/data_dict_table.cpp \ + $$PWD/filter_table.cpp \ + $$PWD/instants_table.cpp \ + $$PWD/callstack_table.cpp \ + $$PWD/irq_table.cpp \ + $$PWD/thread_table.cpp \ + $$PWD/measure_filter_table.cpp \ + $$PWD/measure_table.cpp \ + $$PWD/process_filter_table.cpp \ + $$PWD/process_measure_filter_table.cpp \ + $$PWD/process_table.cpp \ + $$PWD/raw_table.cpp \ + $$PWD/sched_slice_table.cpp \ + $$PWD/table_base.cpp \ + $$PWD/thread_filter_table.cpp \ + $$PWD/thread_state_table.cpp \ + $$PWD/clock_event_filter_table.cpp \ + $$PWD/clk_event_filter_table.cpp \ + $$PWD/stat_table.cpp \ + $$PWD/meta_table.cpp \ + $$PWD/symbols_table.cpp \ + $$PWD/system_call_table.cpp \ + $$PWD/log_table.cpp \ + $$PWD/heap_table.cpp \ + $$PWD/heap_frame_table.cpp \ + $$PWD/hidump_table.cpp \ + $$PWD/args_table.cpp \ + $$PWD/data_type_table.cpp \ + $$PWD/system_event_filter_table.cpp diff --git a/host/trace_streamer/src/table/table_base.cpp b/host/trace_streamer/src/table/table_base.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fef5f10814c08e6343dbde58718ea78d1bb6eef7 --- /dev/null +++ b/host/trace_streamer/src/table/table_base.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "table_base.h" +#include +#include +#include "log.h" + +#define UNUSED(expr) \ + do { \ + static_cast(expr); \ + } while (0) + +namespace SysTuning { +namespace TraceStreamer { +namespace { +struct TableContext { + TabTemplate tmplate; + const TraceDataCache* dataCache; + sqlite3_module module; +}; +} // namespace + +TableBase::~TableBase() +{ + dataCache_ = nullptr; + cursor_ = nullptr; +} + +void TableBase::TableRegister(sqlite3& db, + const TraceDataCache* cache, + const std::string& tableName, + TabTemplate tmplate) +{ + std::unique_ptr context(std::make_unique()); + context->dataCache = cache; + context->tmplate = tmplate; + sqlite3_module& module = context->module; + + auto createFn = [](sqlite3* xdb, void* arg, int argc, const char* const* argv, sqlite3_vtab** tab, char** other) { + UNUSED(argc); + UNUSED(argv); + UNUSED(other); + auto xdesc = static_cast(arg); + auto table = xdesc->tmplate(xdesc->dataCache); + std::string createStmt = table->CreateTableSql(); + int res = sqlite3_declare_vtab(xdb, createStmt.c_str()); + if (res != SQLITE_OK) { + return res; + } + *tab = table.release(); + return SQLITE_OK; + }; + + auto destroyFn = [](sqlite3_vtab* t) { + delete static_cast(t); + return SQLITE_OK; + }; + + module.xCreate = createFn; + module.xConnect = createFn; + module.xBestIndex = [](sqlite3_vtab*, sqlite3_index_info*) { return SQLITE_OK; }; + module.xDisconnect = destroyFn; + module.xDestroy = destroyFn; + module.xOpen = [](sqlite3_vtab* t, sqlite3_vtab_cursor** c) { + return (static_cast(t))->Open(c); + }; + module.xClose = [](sqlite3_vtab_cursor* c) { + UNUSED(c); + return SQLITE_OK; + }; + module.xFilter = [](sqlite3_vtab_cursor* c, int arg1, const char* arg2, int, sqlite3_value** sqlite) { + UNUSED(c); + UNUSED(arg1); + UNUSED(arg2); + UNUSED(sqlite); + return SQLITE_OK; + }; + module.xNext = [](sqlite3_vtab_cursor* c) { return static_cast(c)->Next(); }; + module.xEof = [](sqlite3_vtab_cursor* c) { return static_cast(c)->Eof(); }; + module.xColumn = [](sqlite3_vtab_cursor* c, sqlite3_context* a, int b) { + static_cast(c)->context_ = a; + return static_cast(c)->Column(b); + }; + + sqlite3_create_module_v2(&db, tableName.c_str(), &module, context.release(), + [](void* arg) { delete static_cast(arg); }); +} + +std::string TableBase::CreateTableSql() const +{ + std::string stmt = "CREATE TABLE x("; + for (const auto& col : tableColumn_) { + stmt += " " + col.name_ + " " + col.type_; + stmt += ","; + } + stmt += " PRIMARY KEY("; + for (size_t i = 0; i < tablePriKey_.size(); i++) { + if (i != 0) + stmt += ", "; + stmt += tablePriKey_.at(i); + } + stmt += ")) WITHOUT ROWID;"; + return stmt; +} + +int TableBase::Open(sqlite3_vtab_cursor** ppCursor) +{ + CreateCursor(); + *ppCursor = static_cast(cursor_.get()); + return SQLITE_OK; +} + +TableBase::Cursor::Cursor(const TraceDataCache* dataCache, uint32_t row, uint32_t totalRows) + : context_(nullptr), dataCache_(dataCache), currentRow_(row), rowsTotalNum_(totalRows) +{ +} + +TableBase::Cursor::~Cursor() +{ + context_ = nullptr; + dataCache_ = nullptr; +} + +int TableBase::Cursor::Next() +{ + currentRow_++; + return SQLITE_OK; +} + +int TableBase::Cursor::Eof() +{ + return currentRow_ >= rowsTotalNum_; +} + +uint32_t TableBase::Cursor::CurrentRow() const +{ + return currentRow_; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/table_base.h b/host/trace_streamer/src/table/table_base.h new file mode 100644 index 0000000000000000000000000000000000000000..22e51ca24e030e0df3da0c0b8f9679cb158d2a08 --- /dev/null +++ b/host/trace_streamer/src/table/table_base.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TABLE_H +#define TABLE_H + +#include +#include +#include +#include +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class TableBase; +using TabTemplate = std::unique_ptr (*)(const TraceDataCache* dataCache); +class TableBase : public sqlite3_vtab { +public: + virtual ~TableBase(); + TableBase(const TableBase&) = delete; + TableBase& operator=(const TableBase&) = delete; + + template + static void TableDeclare(sqlite3& db, TraceDataCache* dataCache, const std::string& name) + { + TableRegister(db, dataCache, name, [](const TraceDataCache* cache) { + return std::unique_ptr(std::make_unique(cache)); + }); + dataCache->AppendNewTable(name); + } + + std::string CreateTableSql() const; + + class Cursor : public sqlite3_vtab_cursor { + public: + Cursor(const TraceDataCache*, uint32_t, uint32_t); + virtual ~Cursor(); + virtual int Next(); + virtual int Eof(); + virtual int Column(int) const = 0; + public: + sqlite3_context* context_; + protected: + uint32_t CurrentRow() const; + protected: + const TraceDataCache* dataCache_; + private: + uint32_t currentRow_; + uint32_t rowsTotalNum_; + }; + + struct ColumnInfo { + ColumnInfo(const std::string& name, const std::string& type) : name_(name), type_(type) {} + std::string name_; + std::string type_; + }; + +protected: + explicit TableBase(const TraceDataCache* dataCache) : dataCache_(dataCache), cursor_(nullptr) {} + virtual void CreateCursor() = 0; +protected: + std::vector tableColumn_ = {}; + std::vector tablePriKey_ = {}; + const TraceDataCache* dataCache_; + std::unique_ptr cursor_; +private: + static void TableRegister(sqlite3& db, const TraceDataCache* cache, const std::string& name, TabTemplate tmplate); + int Open(sqlite3_vtab_cursor** ppCursor); +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TABLE_H diff --git a/host/trace_streamer/src/table/thread_filter_table.cpp b/host/trace_streamer/src/table/thread_filter_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f26908a74a66e944b1042b65f5270fa3632afb01 --- /dev/null +++ b/host/trace_streamer/src/table/thread_filter_table.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "thread_filter_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPE, NAME, INTERNAL_TID }; +} +ThreadFilterTable::ThreadFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "UNSIGNED INT")); + tablePriKey_.push_back("id"); +} + +ThreadFilterTable::~ThreadFilterTable() {} + +void ThreadFilterTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +ThreadFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstThreadFilterData().Size())) +{ +} + +ThreadFilterTable::Cursor::~Cursor() {} + +int ThreadFilterTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, + static_cast(dataCache_->GetConstThreadFilterData().FilterIdData()[CurrentRow()])); + break; + case TYPE: + sqlite3_result_text(context_, "thread_filter", STR_DEFAULT_LEN, nullptr); + break; + case NAME: { + std::string str = + dataCache_->GetDataFromDict(dataCache_->GetConstThreadFilterData().NameIndexData()[CurrentRow()]); + sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr); + break; + } + case INTERNAL_TID: + sqlite3_result_int64(context_, + static_cast(dataCache_->GetConstThreadFilterData().InternalTidData()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/thread_filter_table.h b/host/trace_streamer/src/table/thread_filter_table.h new file mode 100644 index 0000000000000000000000000000000000000000..c868dddf45d35a2f16b63e98909f7fd6f64ced8f --- /dev/null +++ b/host/trace_streamer/src/table/thread_filter_table.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_FILTER_TABLE_H +#define THREAD_FILTER_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class ThreadFilterTable : public TableBase { +public: + explicit ThreadFilterTable(const TraceDataCache* dataCache); + ~ThreadFilterTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // THREAD_FILTER_TABLE_H diff --git a/host/trace_streamer/src/table/thread_state_table.cpp b/host/trace_streamer/src/table/thread_state_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..37dc915651ef98d947ed3f25ab3525e69894df5e --- /dev/null +++ b/host/trace_streamer/src/table/thread_state_table.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "thread_state_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPE, TS, DUR, CPU, INTERNAL_TID, STATE }; +} +ThreadStateTable::ThreadStateTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("state", "STRING")); + tablePriKey_.push_back("id"); +} + +ThreadStateTable::~ThreadStateTable() {} + +void ThreadStateTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +ThreadStateTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstThreadStateData().Size())), + threadStateObj_(dataCache->GetConstThreadStateData()) +{ +} + +ThreadStateTable::Cursor::~Cursor() {} + +int ThreadStateTable::Cursor::Column(int col) const +{ + switch (col) { + case ID: + sqlite3_result_int64(context_, static_cast(CurrentRow())); + break; + case TYPE: + sqlite3_result_text(context_, "thread_state", STR_DEFAULT_LEN, nullptr); + break; + case TS: + sqlite3_result_int64(context_, static_cast(threadStateObj_.TimeStamData()[CurrentRow()])); + break; + case DUR: + if (static_cast(threadStateObj_.DursData()[CurrentRow()]) >= 0) { + sqlite3_result_int64(context_, static_cast(threadStateObj_.DursData()[CurrentRow()])); + } + break; + case CPU: + if (static_cast(threadStateObj_.CpusData()[CurrentRow()]) >= 0) { + sqlite3_result_int64(context_, static_cast(threadStateObj_.CpusData()[CurrentRow()])); + } + break; + case INTERNAL_TID: + sqlite3_result_int64(context_, + static_cast(threadStateObj_.InternalTidsData()[CurrentRow()])); + break; + case STATE: { + const std::string& str = dataCache_->GetConstSchedStateData(threadStateObj_.StatesData()[CurrentRow()]); + sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr); + break; + } + default: + TS_LOGF("Unregistered column : %d", col); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/thread_state_table.h b/host/trace_streamer/src/table/thread_state_table.h new file mode 100644 index 0000000000000000000000000000000000000000..374a4a8ddf8228c927e4e88d55d081da94b701da --- /dev/null +++ b/host/trace_streamer/src/table/thread_state_table.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_STATE_TABLE_H +#define THREAD_STATE_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class ThreadStateTable : public TableBase { +public: + explicit ThreadStateTable(const TraceDataCache* dataCache); + ~ThreadStateTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int col) const override; + + private: + const ThreadState& threadStateObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // THREAD_STATE_TABLE_H diff --git a/host/trace_streamer/src/table/thread_table.cpp b/host/trace_streamer/src/table/thread_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af67cb7cedccbda6e7f3f67101a300e9eda0ea47 --- /dev/null +++ b/host/trace_streamer/src/table/thread_table.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "thread_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TYPE, TID, NAME, START_TS, END_TS, INTERNAL_PID, IS_MAIN_THREAD }; +} +ThreadTable::ThreadTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("tid", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("ipid", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("is_main_thread", "UNSIGNED INT")); + tablePriKey_.push_back("id"); +} + +ThreadTable::~ThreadTable() {} + +void ThreadTable::CreateCursor() +{ + cursor_ = std::make_unique(dataCache_); +} + +ThreadTable::Cursor::Cursor(const TraceDataCache* dataCache) + : TableBase::Cursor(dataCache, 0, static_cast(dataCache->ThreadSize())) +{ +} + +ThreadTable::Cursor::~Cursor() {} + +int ThreadTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: { + sqlite3_result_int64(context_, CurrentRow()); + break; + } + case TYPE: { + sqlite3_result_text(context_, "thread", strlen("thread"), nullptr); + break; + } + case TID: { + const auto& process = dataCache_->GetConstThreadData(CurrentRow()); + sqlite3_result_int64(context_, static_cast(process.tid_)); + break; + } + case NAME: { + const auto& thread = dataCache_->GetConstThreadData(CurrentRow()); + const auto& name = dataCache_->GetDataFromDict(thread.nameIndex_); + sqlite3_result_text(context_, name.c_str(), static_cast(name.length()), nullptr); + break; + } + case START_TS: { + const auto& thread = dataCache_->GetConstThreadData(CurrentRow()); + if (thread.startT_) { + sqlite3_result_int64(context_, static_cast(thread.startT_)); + } + break; + } + case END_TS: { + const auto& thread = dataCache_->GetConstThreadData(CurrentRow()); + if (thread.endT_) { + sqlite3_result_int64(context_, static_cast(thread.endT_)); + } + break; + } + case INTERNAL_PID: { + const auto& thread = dataCache_->GetConstThreadData(CurrentRow()); + if (thread.internalPid_) { + sqlite3_result_int(context_, static_cast(thread.internalPid_)); + } + break; + } + case IS_MAIN_THREAD: { + const auto& thread = dataCache_->GetConstThreadData(CurrentRow()); + // When it is not clear which process the thread belongs to, is_main_thread should be set to null + if (!thread.internalPid_) { + break; + } + const auto& process = dataCache_->GetConstProcessData(thread.internalPid_); + sqlite3_result_int(context_, thread.tid_ == process.pid_); + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/thread_table.h b/host/trace_streamer/src/table/thread_table.h new file mode 100644 index 0000000000000000000000000000000000000000..960f90812b67e2eef63f73f39021c6cdde590557 --- /dev/null +++ b/host/trace_streamer/src/table/thread_table.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_THREAD_TABLE_H +#define SRC_THREAD_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class ThreadTable : public TableBase { +public: + explicit ThreadTable(const TraceDataCache* dataCache); + ~ThreadTable() override; + void CreateCursor() override; + +private: + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache); + ~Cursor() override; + int Column(int column) const override; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // SRC_THREAD_TABLE_H diff --git a/host/trace_streamer/src/trace_data/trace_data.pri b/host/trace_streamer/src/trace_data/trace_data.pri new file mode 100644 index 0000000000000000000000000000000000000000..ec15f896fd4d6ec5b34313c593bdb30842f1aa3f --- /dev/null +++ b/host/trace_streamer/src/trace_data/trace_data.pri @@ -0,0 +1,28 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +INCLUDEPATH +=$$PWD +HEADERS += \ + $$PWD/trace_data_cache.h \ + $$PWD/trace_data_cache_base.h \ + $$PWD/trace_data_cache_reader.h \ + $$PWD/trace_data_cache_writer.h \ + $$PWD/trace_data_db.h \ + $$PWD/trace_stdtype.h + +SOURCES += \ + $$PWD/trace_data_cache.cpp \ + $$PWD/trace_data_cache_base.cpp \ + $$PWD/trace_data_cache_reader.cpp \ + $$PWD/trace_data_cache_writer.cpp \ + $$PWD/trace_data_db.cpp \ + $$PWD/trace_stdtype.cpp diff --git a/host/trace_streamer/src/trace_data/trace_data_cache.cpp b/host/trace_streamer/src/trace_data/trace_data_cache.cpp new file mode 100644 index 0000000000000000000000000000000000000000..900d411edb5bbaaa6670fb231c1cf62ea2190655 --- /dev/null +++ b/host/trace_streamer/src/trace_data/trace_data_cache.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "trace_data_cache.h" +#include +#include "args_table.h" +#include "callstack_table.h" +#include "clk_event_filter_table.h" +#include "clock_event_filter_table.h" +#include "cpu_measure_filter_table.h" +#include "data_dict_table.h" +#include "data_type_table.h" +#include "filter_table.h" +#include "heap_frame_table.h" +#include "heap_table.h" +#include "hidump_table.h" +#include "instants_table.h" +#include "irq_table.h" +#include "log_table.h" +#include "measure_filter_table.h" +#include "measure_table.h" +#include "meta_table.h" +#include "process_filter_table.h" +#include "process_measure_filter_table.h" +#include "process_table.h" +#include "range_table.h" +#include "raw_table.h" +#include "sched_slice_table.h" +#include "stat_table.h" +#include "symbols_table.h" +#include "system_call_table.h" +#include "system_event_filter_table.h" +#include "table_base.h" +#include "thread_filter_table.h" +#include "thread_state_table.h" +#include "thread_table.h" + + +namespace SysTuning { +namespace TraceStreamer { +TraceDataCache::TraceDataCache() +{ + InitDB(); +} + +TraceDataCache::~TraceDataCache() {} + +void TraceDataCache::InitDB() +{ + if (dbInited) { + return; + } + TableBase::TableDeclare(*db_, this, "_process"); + TableBase::TableDeclare(*db_, this, "_sched_slice"); + TableBase::TableDeclare(*db_, this, "_callstack"); + TableBase::TableDeclare(*db_, this, "_irq"); + TableBase::TableDeclare(*db_, this, "_data_dict"); + TableBase::TableDeclare(*db_, this, "_thread_state"); + TableBase::TableDeclare(*db_, this, "_instant"); + TableBase::TableDeclare(*db_, this, "_measure"); + TableBase::TableDeclare(*db_, this, "_trace_range"); + TableBase::TableDeclare(*db_, this, "_thread"); + TableBase::TableDeclare(*db_, this, "_raw"); + TableBase::TableDeclare(*db_, this, "_cpu_measure_filter"); + TableBase::TableDeclare(*db_, this, "_measure_filter"); + TableBase::TableDeclare(*db_, this, "_process_measure_filter"); + TableBase::TableDeclare(*db_, this, "_stat"); + TableBase::TableDeclare(*db_, this, "_clock_event_filter"); + TableBase::TableDeclare(*db_, this, "_clk_event_filter"); + TableBase::TableDeclare(*db_, this, "_symbols"); + TableBase::TableDeclare(*db_, this, "_syscall"); + TableBase::TableDeclare(*db_, this, "_args"); + TableBase::TableDeclare(*db_, this, "_data_type"); + TableBase::TableDeclare(*db_, this, "_meta"); + TableBase::TableDeclare(*db_, this, "_log"); + TableBase::TableDeclare(*db_, this, "_heap"); + TableBase::TableDeclare(*db_, this, "_heap_frame"); + TableBase::TableDeclare(*db_, this, "_hidump"); + TableBase::TableDeclare(*db_, this, "_sys_event_filter"); + dbInited = true; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/trace_data/trace_data_cache.h b/host/trace_streamer/src/trace_data/trace_data_cache.h new file mode 100644 index 0000000000000000000000000000000000000000..e1f995d67dabbae517d85f10e57d3d7108c8b0a0 --- /dev/null +++ b/host/trace_streamer/src/trace_data/trace_data_cache.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TRACE_DATA_CACHE_H +#define TRACE_DATA_CACHE_H + +#include "trace_data_cache_reader.h" +#include "trace_data_cache_writer.h" +#include "trace_data_db.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace TraceStdtype; +class TraceDataCache : public TraceDataCacheReader, public TraceDataCacheWriter, public TraceDataDB { +public: + TraceDataCache(); + TraceDataCache(const TraceDataCache* dataCache) = delete; + TraceDataCache* operator=(const TraceDataCache* dataCache) = delete; + ~TraceDataCache() override; + +private: + void InitDB() override; + bool dbInited = false; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TRACE_DATA_CACHE_H diff --git a/host/trace_streamer/src/trace_data/trace_data_cache_base.cpp b/host/trace_streamer/src/trace_data/trace_data_cache_base.cpp new file mode 100644 index 0000000000000000000000000000000000000000..62314ea418beccfff9b9ae5ea7e1a50698ddcf47 --- /dev/null +++ b/host/trace_streamer/src/trace_data/trace_data_cache_base.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "trace_data_cache_base.h" +#include + +namespace SysTuning { +namespace TraceStreamer { +TraceDataCacheBase::TraceDataCacheBase() +{ + internalProcessesData_.emplace_back(0); + internalThreadsData_.emplace_back(0); + + GetDataIndex(""); +} +DataIndex TraceDataCacheBase::GetDataIndex(std::string_view str) +{ + return dataDict_.GetStringIndex(str); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/trace_data/trace_data_cache_base.h b/host/trace_streamer/src/trace_data/trace_data_cache_base.h new file mode 100644 index 0000000000000000000000000000000000000000..cc1181ab5c67edefad6946fcbbd4bc837ade9dde --- /dev/null +++ b/host/trace_streamer/src/trace_data/trace_data_cache_base.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TRACE_DATA_CACHE_BASE_H +#define TRACE_DATA_CACHE_BASE_H + + +#include +#include +#include +#include +#include +#include +#include "trace_stdtype.h" +namespace SysTuning { +namespace TraceStreamer { +using namespace TraceStdtype; +class TraceDataCacheBase { +public: + TraceDataCacheBase(); + TraceDataCacheBase(const TraceDataCacheBase&) = delete; + TraceDataCacheBase& operator=(const TraceDataCacheBase&) = delete; + virtual ~TraceDataCacheBase() = default; + +public: + size_t ThreadSize() const + { + return internalThreadsData_.size(); + } + size_t ProcessSize() const + { + return internalProcessesData_.size(); + } + + size_t DataDictSize() const + { + return dataDict_.Size(); + } + void UpdateTraceRange() + { + metaData_.SetTraceDuration((traceEndTime_ - traceStartTime_) / SEC_TO_NS); + } + DataIndex GetDataIndex(std::string_view str); + std::map statusString_ = {{TASK_RUNNABLE, "R"}, + {TASK_INTERRUPTIBLE, "S"}, + {TASK_UNINTERRUPTIBLE, "D"}, + {TASK_RUNNING, "Running"}, + {TASK_INTERRUPTED, "I"}, + {TASK_TRACED, "T"}, + {TASK_EXIT_DEAD, "X"}, + {TASK_ZOMBIE, "Z"}, + {TASK_KILLED, "I"}, + {TASK_WAKEKILL, "R"}, + {TASK_INVALID, "U"}, + {TASK_CLONE, "I"}, + {TASK_DK, "DK"}, + {TASK_TRACED_KILL, "TK"}, + {TASK_FOREGROUND, "R+"}, + {TASK_MAX, "S"}}; + uint64_t traceStartTime_ = std::numeric_limits::max(); + uint64_t traceEndTime_ = 0; + + Raw rawData_; + ThreadState threadStateData_; + Instants instantsData_; + + Filter filterData_; + ProcessMeasureFilter processMeasureFilterData_; + ClockEventData clockEventFilterData_; + ClkEventData clkEventFilterData_; + ProcessMeasureFilter processFilterData_; + ThreadMeasureFilter threadMeasureFilterData_; + ThreadMeasureFilter threadFilterData_; + DataDict dataDict_; + + SchedSlice schedSliceData_; + CallStack callstackData_; + CallStack irqData_; + LogInfo hilogData_; + HeapInfo heapData_; + HeapFrameInfo heapFrameData_; + Hidump hidumpData_; + + std::deque internalProcessesData_ = {}; + std::deque internalThreadsData_ = {}; + + Measure measureData_; + CpuMeasureFilter cpuMeasureData_; + + StatAndInfo stat_; + MetaData metaData_; + SymbolsData symbolsData_; + SysCall sysCallData_; + ArgSet argSet_; + DataType dataType_; + SysMeasureFilter sysEvent_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TRACE_DATA_CACHE_BASE_H diff --git a/host/trace_streamer/src/trace_data/trace_data_cache_reader.cpp b/host/trace_streamer/src/trace_data/trace_data_cache_reader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..095e64804cc52fdb7dd3b55c4da7a5209b47cdbb --- /dev/null +++ b/host/trace_streamer/src/trace_data/trace_data_cache_reader.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "trace_data_cache_reader.h" +#include "log.h" +namespace SysTuning { +namespace TraceStreamer { +using namespace TraceStdtype; +TraceDataCacheReader::~TraceDataCacheReader() {} +const std::string& TraceDataCacheReader::GetDataFromDict(DataIndex id) const +{ + return dataDict_.GetDataFromDict(id); +} +const Process& TraceDataCacheReader::GetConstProcessData(InternalPid internalPid) const +{ + TS_ASSERT(internalPid < internalProcessesData_.size()); + return internalProcessesData_[internalPid]; +} +const Thread& TraceDataCacheReader::GetConstThreadData(InternalTid internalTid) const +{ + TS_ASSERT(internalTid < internalThreadsData_.size()); + return internalThreadsData_[internalTid]; +} +const CallStack& TraceDataCacheReader::GetConstInternalSlicesData() const +{ + return callstackData_; +} +const CallStack& TraceDataCacheReader::GetConstIrqData() const +{ + return irqData_; +} +const Filter& TraceDataCacheReader::GetConstFilterData() const +{ + return filterData_; +} +const Raw& TraceDataCacheReader::GetConstRawTableData() const +{ + return rawData_; +} +const Measure& TraceDataCacheReader::GetConstMeasureData() const +{ + return measureData_; +} + +const ThreadMeasureFilter& TraceDataCacheReader::GetConstThreadMeasureFilterData() const +{ + return threadMeasureFilterData_; +} +const ThreadState& TraceDataCacheReader::GetConstThreadStateData() const +{ + return threadStateData_; +} +const SchedSlice& TraceDataCacheReader::GetConstSchedSliceData() const +{ + return schedSliceData_; +} +const CpuMeasureFilter& TraceDataCacheReader::GetConstCpuMeasureData() const +{ + return cpuMeasureData_; +} +const ThreadMeasureFilter& TraceDataCacheReader::GetConstThreadFilterData() const +{ + return threadFilterData_; +} +const Instants& TraceDataCacheReader::GetConstInstantsData() const +{ + return instantsData_; +} +const ProcessMeasureFilter& TraceDataCacheReader::GetConstProcessFilterData() const +{ + return processFilterData_; +} +const ProcessMeasureFilter& TraceDataCacheReader::GetConstProcessMeasureFilterData() const +{ + return processMeasureFilterData_; +} + +const ClockEventData& TraceDataCacheReader::GetConstClockEventFilterData() const +{ + return clockEventFilterData_; +} +const ClkEventData& TraceDataCacheReader::GetConstClkEventFilterData() const +{ + return clkEventFilterData_; +} +const std::string& TraceDataCacheReader::GetConstSchedStateData(uint64_t rowId) const +{ + TS_ASSERT(statusString_.find(rowId) != statusString_.end()); + return statusString_.at(rowId); +} +uint64_t TraceDataCacheReader::TraceStartTime() const +{ + return traceStartTime_; +} +uint64_t TraceDataCacheReader::TraceEndTime() const +{ + return traceEndTime_; +} + +const StatAndInfo& TraceDataCacheReader::GetConstStatAndInfo() const +{ + return stat_; +} +const MetaData& TraceDataCacheReader::GetConstMetaData() const +{ + return metaData_; +} + +const SymbolsData& TraceDataCacheReader::GetConstSymbolsData() const +{ + return symbolsData_; +} + +const LogInfo& TraceDataCacheReader::GetConstHilogData() const +{ + return hilogData_; +} + +const HeapInfo& TraceDataCacheReader::GetConstHeapData() const +{ + return heapData_; +} + +const HeapFrameInfo& TraceDataCacheReader::GetConstHeapFrameData() const +{ + return heapFrameData_; +} + +const Hidump& TraceDataCacheReader::GetConstHidumpData() const +{ + return hidumpData_; +} + +const SysCall& TraceDataCacheReader::GetConstSysCallData() const +{ + return sysCallData_; +} +const ArgSet& TraceDataCacheReader::GetConstArgSetData() const +{ + return argSet_; +} + +const DataType& TraceDataCacheReader::GetConstDataTypeData() const +{ + return dataType_; +} + +const SysMeasureFilter& TraceDataCacheReader::GetConstSysMeasureFilterData() const +{ + return sysEvent_; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/trace_data/trace_data_cache_reader.h b/host/trace_streamer/src/trace_data/trace_data_cache_reader.h new file mode 100644 index 0000000000000000000000000000000000000000..ffe1f81c3db9966eb006280593da5e7441653d1a --- /dev/null +++ b/host/trace_streamer/src/trace_data/trace_data_cache_reader.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TRACE_DATA_CACHE_READER_H +#define TRACE_DATA_CACHE_READER_H + +#include "log.h" +#include "trace_data_cache_base.h" +#include "trace_stdtype.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace TraceStdtype; +class TraceDataCacheReader : virtual public TraceDataCacheBase { +public: + TraceDataCacheReader() = default; + TraceDataCacheReader(const TraceDataCacheReader&) = delete; + TraceDataCacheReader& operator=(const TraceDataCacheReader&) = delete; + ~TraceDataCacheReader() override; + +public: + const std::string& GetDataFromDict(DataIndex id) const; + const Process& GetConstProcessData(InternalPid internalPid) const; + const Thread& GetConstThreadData(InternalTid internalTid) const; + const CallStack& GetConstInternalSlicesData() const; + const CallStack& GetConstIrqData() const; + const Filter& GetConstFilterData() const; + const Raw& GetConstRawTableData() const; + const Measure& GetConstMeasureData() const; + const ThreadMeasureFilter& GetConstThreadMeasureFilterData() const; + const ThreadState& GetConstThreadStateData() const; + const SchedSlice& GetConstSchedSliceData() const; + const CpuMeasureFilter& GetConstCpuMeasureData() const; + const ThreadMeasureFilter& GetConstThreadFilterData() const; + const Instants& GetConstInstantsData() const; + const ProcessMeasureFilter& GetConstProcessFilterData() const; + const ProcessMeasureFilter& GetConstProcessMeasureFilterData() const; + const ClockEventData& GetConstClockEventFilterData() const; + const ClkEventData& GetConstClkEventFilterData() const; + const std::string& GetConstSchedStateData(uint64_t rowId) const; + uint64_t TraceStartTime() const; + uint64_t TraceEndTime() const; + const StatAndInfo& GetConstStatAndInfo() const; + const MetaData& GetConstMetaData() const; + const SymbolsData& GetConstSymbolsData() const; + const SysCall& GetConstSysCallData() const; + const LogInfo& GetConstHilogData() const; + const HeapInfo& GetConstHeapData() const; + const HeapFrameInfo& GetConstHeapFrameData() const; + const Hidump& GetConstHidumpData() const; + const ArgSet& GetConstArgSetData() const; + const DataType& GetConstDataTypeData() const; + const SysMeasureFilter& GetConstSysMeasureFilterData() const; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif diff --git a/host/trace_streamer/src/trace_data/trace_data_cache_writer.cpp b/host/trace_streamer/src/trace_data/trace_data_cache_writer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4fc2925a0a9547988f23ebdad82d862dafb7f64e --- /dev/null +++ b/host/trace_streamer/src/trace_data/trace_data_cache_writer.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "trace_data_cache_writer.h" +#include "log.h" +namespace SysTuning { +namespace TraceStreamer { +using namespace TraceStdtype; +TraceDataCacheWriter::~TraceDataCacheWriter() {} +InternalPid TraceDataCacheWriter::GetProcessInternalPid(uint32_t pid) +{ + internalProcessesData_.emplace_back(pid); + return static_cast(internalProcessesData_.size() - 1); +} +Process* TraceDataCacheWriter::GetProcessData(InternalPid internalPid) +{ + TS_ASSERT(internalPid < internalProcessesData_.size()); + return &internalProcessesData_[internalPid]; +} + +InternalTid TraceDataCacheWriter::NewInternalThread(uint32_t tid) +{ + internalThreadsData_.emplace_back(tid); + return static_cast(internalThreadsData_.size() - 1); +} +Thread* TraceDataCacheWriter::GetThreadData(InternalTid internalTid) +{ + if (internalTid >= internalThreadsData_.size()) { + return nullptr; + } + return &internalThreadsData_[internalTid]; +} + +void TraceDataCacheWriter::UpdateTraceTime(uint64_t timestamp) +{ + traceStartTime_ = std::min(traceStartTime_, timestamp); + traceEndTime_ = std::max(traceEndTime_, timestamp); +} + +void TraceDataCacheWriter::MixTraceTime(uint64_t timestampMin, uint64_t timestampMax) +{ + if (timestampMin == std::numeric_limits::max() || timestampMax == 0) { + return; + } + if (traceStartTime_ != std::numeric_limits::max()) { + traceStartTime_ = std::max(traceStartTime_, timestampMin); + } else { + traceStartTime_ = timestampMin; + } + if (traceEndTime_) { + traceEndTime_ = std::min(traceEndTime_, timestampMax); + } else { + traceEndTime_ = timestampMax; + } +} +CallStack* TraceDataCacheWriter::GetInternalSlicesData() +{ + return &callstackData_; +} +CallStack* TraceDataCacheWriter::GetIrqData() +{ + return &irqData_; +} + +Filter* TraceDataCacheWriter::GetFilterData() +{ + return &filterData_; +} + +Raw* TraceDataCacheWriter::GetRawData() +{ + return &rawData_; +} + +Measure* TraceDataCacheWriter::GetMeasureData() +{ + return &measureData_; +} + +ThreadState* TraceDataCacheWriter::GetThreadStateData() +{ + return &threadStateData_; +} + +SchedSlice* TraceDataCacheWriter::GetSchedSliceData() +{ + return &schedSliceData_; +} + +CpuMeasureFilter* TraceDataCacheWriter::GetCpuMeasuresData() +{ + return &cpuMeasureData_; +} + +ThreadMeasureFilter* TraceDataCacheWriter::GetThreadMeasureFilterData() +{ + return &threadMeasureFilterData_; +} + +ThreadMeasureFilter* TraceDataCacheWriter::GetThreadFilterData() +{ + return &threadFilterData_; +} + +Instants* TraceDataCacheWriter::GetInstantsData() +{ + return &instantsData_; +} + +ProcessMeasureFilter* TraceDataCacheWriter::GetProcessFilterData() +{ + return &processFilterData_; +} + +ProcessMeasureFilter* TraceDataCacheWriter::GetProcessMeasureFilterData() +{ + return &processMeasureFilterData_; +} + +ClockEventData* TraceDataCacheWriter::GetClockEventFilterData() +{ + return &clockEventFilterData_; +} + +ClkEventData* TraceDataCacheWriter::GetClkEventFilterData() +{ + return &clkEventFilterData_; +} +StatAndInfo* TraceDataCacheWriter::GetStatAndInfo() +{ + return &stat_; +} + +MetaData* TraceDataCacheWriter::GetMetaData() +{ + return &metaData_; +} + +SymbolsData* TraceDataCacheWriter::GetSymbolsData() +{ + return &symbolsData_; +} +SysCall* TraceDataCacheWriter::GetSysCallData() +{ + return &sysCallData_; +} +LogInfo* TraceDataCacheWriter::GetHilogData() +{ + return &hilogData_; +} + +HeapInfo* TraceDataCacheWriter::GetHeapData() +{ + return &heapData_; +} + +HeapFrameInfo* TraceDataCacheWriter::GetHeapFrameData() +{ + return &heapFrameData_; +} + +Hidump* TraceDataCacheWriter::GetHidumpData() +{ + return &hidumpData_; +} + +ArgSet* TraceDataCacheWriter::GetArgSetData() +{ + return &argSet_; +} + +DataType* TraceDataCacheWriter::GetDataTypeData() +{ + return &dataType_; +} + +SysMeasureFilter* TraceDataCacheWriter::GetSysMeasureFilterData() +{ + return &sysEvent_; +} +void TraceDataCacheWriter::Clear() +{ + rawData_.Clear(); + threadStateData_.Clear(); + instantsData_.Clear(); + + filterData_.Clear(); + processMeasureFilterData_.Clear(); + clockEventFilterData_.Clear(); + clkEventFilterData_.Clear(); + processFilterData_.Clear(); + threadMeasureFilterData_.Clear(); + threadFilterData_.Clear(); + dataDict_.Clear(); + + schedSliceData_.Clear(); + callstackData_.Clear(); + irqData_.Clear(); + hilogData_.Clear(); + heapData_.Clear(); + heapFrameData_.Clear(); + hidumpData_.Clear(); + + internalProcessesData_.clear(); + internalThreadsData_.clear(); + + measureData_.Clear(); + cpuMeasureData_.Clear(); + + metaData_.Clear(); + symbolsData_.Clear(); + sysCallData_.Clear(); + argSet_.Clear(); + dataType_.Clear(); + sysEvent_.Clear(); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/trace_data/trace_data_cache_writer.h b/host/trace_streamer/src/trace_data/trace_data_cache_writer.h new file mode 100644 index 0000000000000000000000000000000000000000..5d421046a5d64750b113961bde3f4ce325b78618 --- /dev/null +++ b/host/trace_streamer/src/trace_data/trace_data_cache_writer.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TRACE_DATA_CACHE_WRITER_H +#define TRACE_DATA_CACHE_WRITER_H + +#include "trace_data_cache_reader.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace TraceStdtype; +class TraceDataCacheWriter : virtual public TraceDataCacheBase { +public: + TraceDataCacheWriter() = default; + TraceDataCacheWriter(const TraceDataCacheWriter&) = delete; + TraceDataCacheWriter& operator=(const TraceDataCacheWriter&) = delete; + ~TraceDataCacheWriter() override; + void Clear(); + +public: + InternalPid GetProcessInternalPid(uint32_t pid); + Process* GetProcessData(InternalPid internalPid); + InternalTid NewInternalThread(uint32_t tid); + Thread* GetThreadData(InternalTid internalTid); + void UpdateTraceTime(uint64_t timestamp); + void MixTraceTime(uint64_t timestampMin, uint64_t timestampMax); + CallStack* GetInternalSlicesData(); + CallStack* GetIrqData(); + Filter* GetFilterData(); + Raw* GetRawData(); + Measure* GetMeasureData(); + ThreadState* GetThreadStateData(); + SchedSlice* GetSchedSliceData(); + CpuMeasureFilter* GetCpuMeasuresData(); + ThreadMeasureFilter* GetThreadMeasureFilterData(); + ThreadMeasureFilter* GetThreadFilterData(); + Instants* GetInstantsData(); + ProcessMeasureFilter* GetProcessFilterData(); + ProcessMeasureFilter* GetProcessMeasureFilterData(); + ClockEventData* GetClockEventFilterData(); + ClkEventData* GetClkEventFilterData(); + StatAndInfo* GetStatAndInfo(); + MetaData* GetMetaData(); + SymbolsData* GetSymbolsData(); + SysCall* GetSysCallData(); + LogInfo* GetHilogData(); + HeapInfo* GetHeapData(); + HeapFrameInfo* GetHeapFrameData(); + Hidump* GetHidumpData(); + ArgSet* GetArgSetData(); + DataType* GetDataTypeData(); + SysMeasureFilter* GetSysMeasureFilterData(); +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif diff --git a/host/trace_streamer/src/trace_data/trace_data_db.cpp b/host/trace_streamer/src/trace_data/trace_data_db.cpp new file mode 100644 index 0000000000000000000000000000000000000000..07fd63aeb0b7551859560b6af1e0d70292681060 --- /dev/null +++ b/host/trace_streamer/src/trace_data/trace_data_db.cpp @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "trace_data_db.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "codec_cov.h" +#include "ext/sqlite_ext_funcs.h" +#include "file.h" +#include "log.h" + +namespace SysTuning { +namespace TraceStreamer { +int PrintQueryResult(void* para, int column, char** columnValue, char** columnName) +{ + int i; + printf("Query results include %d column\n", column); + for (i = 0; i < column; i++) { + printf("name : %s \t value : %s\n", columnName[i], columnValue[i]); + } + printf("------------------\n"); + return 0; +} +TraceDataDB::TraceDataDB() : db_(nullptr) +{ + if (sqlite3_threadsafe() > 0) { + int retCode = sqlite3_config(SQLITE_CONFIG_SERIALIZED); + if (retCode == SQLITE_OK) { + TS_LOGI("Can now use sqlite on multiple threads, using the same connection"); + } else { + TS_LOGE("setting sqlite thread safe mode to serialized failed!!! return code: %d", retCode); + } + } else { + TS_LOGE("Your SQLite database is not compiled to be threadsafe."); + } + if (sqlite3_open(":memory:", &db_)) { + TS_LOGF("open :memory db failed"); + } + CreateExtendFunction(db_); +} + +TraceDataDB::~TraceDataDB() +{ + sqlite3_close(db_); +} + +void TraceDataDB::AppendNewTable(std::string tableName) +{ + internalTables_.push_back(tableName); +} +void TraceDataDB::EnableMetaTable(bool enabled) +{ + exportMetaTable_ = enabled; +} +int TraceDataDB::ExportDatabase(const std::string& outputName) +{ + { + int fd(base::OpenFile(outputName, O_CREAT | O_RDWR, 0600)); + if (!fd) { + fprintf(stdout, "Failed to create file: %s", outputName.c_str()); + return 1; + } + ftruncate(fd, 0); + close(fd); + } + + std::string attachSql("ATTACH DATABASE '" + outputName + "' AS systuning_export"); +#ifdef _WIN32 + if (!base::GetCoding(reinterpret_cast(attachSql.c_str()), attachSql.length())) { + attachSql = base::GbkToUtf8(attachSql.c_str()); + } +#endif + ExecuteSql(attachSql); + + for (auto itor = internalTables_.begin(); itor != internalTables_.end(); itor++) { + if (*itor == "meta") { + if (!exportMetaTable_) { + continue; + } + if ((*itor) != "_data_dict") { + std::string exportSql("CREATE TABLE systuning_export." + (*itor).substr(1, -1) + + " AS SELECT * FROM " + *itor); + ExecuteSql(exportSql); + } + } else { + std::string exportSql("CREATE TABLE systuning_export." + (*itor).substr(1, -1) + + " AS SELECT * FROM " + *itor); + ExecuteSql(exportSql); + } + } + std::string createArgsView = + "create view systuning_export.args_view AS select A.argset, V2.data as keyName, A.id, D.desc, (case when " + "A.datatype==1 then V.data else A.value end) as strValue from args as A left join data_type as D on (D.typeId " + "= A.datatype) left join data_dict as V on V.id = A.value left join data_dict as V2 on V2.id = A.key"; + ExecuteSql(createArgsView); + std::string updateProcessName = + "update process set name = (select name from thread t where t.ipid = process.id and t.name is not null and " + "is_main_thread = 1)"; + ExecuteSql(updateProcessName); + std::string detachSql("DETACH DATABASE systuning_export"); + ExecuteSql(detachSql); + return 0; +} +void TraceDataDB::Prepare() +{ + if (pared_) { + return; + } + pared_ = true; + for (auto itor = internalTables_.begin(); itor != internalTables_.end(); itor++) { + std::string exportSql("CREATE TABLE " + (*itor).substr(1, -1) + " AS SELECT * FROM " + *itor); + ExecuteSql(exportSql); + } + std::string createArgsView = + "create view args_view AS select A.argset, V2.data as keyName, A.id, D.desc, (case when " + "A.datatype==1 then V.data else A.value end) as strValue from args as A left join data_type as D on " + "(D.typeId " + "= A.datatype) left join data_dict as V on V.id = A.value left join data_dict as V2 on V2.id = A.key"; + ExecuteSql(createArgsView); + std::string updateProcessNewName = + "update process set name = (select name from thread t where t.ipid = process.id and t.name is not " + "null and " + "is_main_thread = 1)"; + ExecuteSql(updateProcessNewName); +} +void TraceDataDB::ExecuteSql(const std::string_view& sql) +{ + sqlite3_stmt* stmt = nullptr; + int ret = sqlite3_prepare_v2(db_, sql.data(), static_cast(sql.size()), &stmt, nullptr); + + while (!ret) { + int err = sqlite3_step(stmt); + if (err == SQLITE_ROW) { + continue; + } + if (err == SQLITE_DONE) { + break; + } + ret = err; + } + + sqlite3_finalize(stmt); +} +int TraceDataDB::SearchData() +{ + Prepare(); + int result; + char* errmsg = nullptr; + std::string line; + for (;;) { + std::cout << "> "; + getline(std::cin, line); + if (line.empty()) { + std::cout << "If you want to quit either type -q or press CTRL-Z" << std::endl; + continue; + } + if (!line.compare("-q") || !line.compare("-quit")) { + break; + } else if (!line.compare("-e")) { + TS_LOGI("the db file will be at current folder, the name is default.db"); + return ExportDatabase("default.db"); + } else if (!line.compare("-help") || !line.compare("-h")) { + std::cout << "use info" << std::endl; + continue; + } + result = sqlite3_exec(db_, line.c_str(), PrintQueryResult, NULL, &errmsg); + } + return 0; +} +int TraceDataDB::OperateDatabase(const std::string& sql) +{ + Prepare(); + char* errmsg = nullptr; + int ret = sqlite3_exec(db_, sql.c_str(), NULL, NULL, &errmsg); + if (ret != SQLITE_OK && errmsg) { + TS_LOGE("sqlite3_exec(%s) failed: %d:%s", sql.c_str(), ret, errmsg); + sqlite3_free(errmsg); + } + return ret; +} +int TraceDataDB::SearchDatabase(const std::string& sql, ResultCallBack resultCallBack) +{ + Prepare(); + sqlite3_stmt* stmt = nullptr; + int ret = sqlite3_prepare_v2(db_, sql.c_str(), static_cast(sql.size()), &stmt, nullptr); + if (ret != SQLITE_OK) { + TS_LOGE("sqlite3_prepare_v2(%s) failed: %d:", sql.c_str(), ret); + return ret; + } + if (!resultCallBack) { + return ret; + } + + const size_t maxLenResponse = 4 * 1024; + std::string res; + res.reserve(maxLenResponse); + res = "ok\r\n"; + int colCount = sqlite3_column_count(stmt); + if (colCount == 0) { + resultCallBack(res); + return ret; + } + res += "{\"columns\":["; + for (int i = 0; i < colCount; i++) { + res += "\""; + res += sqlite3_column_name(stmt, i); + res += "\","; + } + res.pop_back(); // remove the last "," + res += "],\"values\":["; + bool hasRow = false; + constexpr int defaultLenRowString = 1024; + std::string row; + row.reserve(defaultLenRowString); + while (sqlite3_step(stmt) == SQLITE_ROW) { + hasRow = true; + GetRowString(stmt, colCount, row); + if (res.size() + row.size() + strlen(",]}\r\n") >= maxLenResponse) { + resultCallBack(res); + res.clear(); + } + res += row + ","; + } + if (hasRow) { + res.pop_back(); // remove the last ',' + } + res += "]}\r\n"; + resultCallBack(res); + + sqlite3_finalize(stmt); + return ret; +} +int TraceDataDB::SearchDatabase(const std::string& sql, uint8_t* out, int outLen) +{ + Prepare(); + sqlite3_stmt* stmt = nullptr; + int ret = sqlite3_prepare_v2(db_, sql.c_str(), static_cast(sql.size()), &stmt, nullptr); + if (ret != SQLITE_OK) { + TS_LOGE("sqlite3_prepare_v2(%s) failed: %d:", sql.c_str(), ret); + return -1; + } + char* res = reinterpret_cast(out); + int retSnprintf = std::snprintf(res, outLen, "%s", "ok\r\n"); + if (retSnprintf < 0) { + return -1; + } + int pos = retSnprintf; + int colCount = sqlite3_column_count(stmt); + if (colCount == 0) { + return pos; + } + retSnprintf = std::snprintf(res + pos, outLen - pos, "%s", "{\"columns\":["); + if (retSnprintf < 0) { + return -1; + } + pos += retSnprintf; + for (int i = 0; i < colCount; i++) { + retSnprintf = std::snprintf(res + pos, outLen - pos, "%s%s%s", "\"", sqlite3_column_name(stmt, i), "\","); + if (retSnprintf < 0) { + return -1; + } + pos += retSnprintf; + } + pos--; // rmove the last ',' + retSnprintf = std::snprintf(res + pos, outLen - pos, "%s", "],\"values\":["); + if (retSnprintf < 0) { + return -1; + } + pos += retSnprintf; + bool hasRow = false; + constexpr int defaultLenRowString = 1024; + std::string row; + row.reserve(defaultLenRowString); + while (sqlite3_step(stmt) == SQLITE_ROW) { + hasRow = true; + GetRowString(stmt, colCount, row); + if (pos + row.size() + strlen(",]}\r\n") >= size_t(outLen)) { + retSnprintf = std::snprintf(res + pos, outLen - pos, "%s", "]}\r\n"); + if (retSnprintf < 0) { + return -1; + } + pos += retSnprintf; + sqlite3_finalize(stmt); + return pos; + } + retSnprintf = std::snprintf(res + pos, outLen - pos, "%s%s", row.c_str(), ","); + if (retSnprintf < 0) { + return -1; + } + pos += retSnprintf; + } + if (hasRow) { + pos--; // remove the last ',' + } + retSnprintf = std::snprintf(res + pos, outLen - pos, "%s", "]}\r\n"); + if (retSnprintf < 0) { + return -1; + } + pos += retSnprintf; + sqlite3_finalize(stmt); + return pos; +} +void TraceDataDB::GetRowString(sqlite3_stmt* stmt, int colCount, std::string& rowStr) +{ + rowStr.clear(); + rowStr = "["; + for (int i = 0; i < colCount; i++) { + const char* p = reinterpret_cast(sqlite3_column_text(stmt, i)); + if (p == nullptr) { + rowStr += "null,"; + continue; + } + int type = sqlite3_column_type(stmt, i); + switch (type) { + case SQLITE_TEXT: + rowStr += "\""; + rowStr += p; + rowStr += "\""; + break; + default: + rowStr += p; + break; + } + rowStr += ","; + } + rowStr.pop_back(); // remove the last ',' + rowStr += "]"; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/trace_data/trace_data_db.h b/host/trace_streamer/src/trace_data/trace_data_db.h new file mode 100644 index 0000000000000000000000000000000000000000..d9ff9b68cb2827bd2ea8a04c3aaea4e787169a5c --- /dev/null +++ b/host/trace_streamer/src/trace_data/trace_data_db.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TRACE_DATA_DB_H +#define TRACE_DATA_DB_H + +#include +#include +#include + +extern "C" { +#include "sqlite3.h" +} + +namespace SysTuning { +namespace TraceStreamer { +class TraceDataDB { +public: + TraceDataDB(); + TraceDataDB(const TraceDataDB&) = delete; + TraceDataDB& operator=(const TraceDataDB&) = delete; + virtual ~TraceDataDB(); + virtual void InitDB() = 0; + void Prepare(); +public: + int ExportDatabase(const std::string& outputName); + int SearchData(); + int OperateDatabase(const std::string& sql); + using ResultCallBack = std::function; + int SearchDatabase(const std::string& sql, ResultCallBack resultCallBack); + int SearchDatabase(const std::string& sql, uint8_t* out, int outLen); + void AppendNewTable(std::string tableName); + void EnableMetaTable(bool enabled); + +public: + sqlite3* db_; + +private: + void ExecuteSql(const std::string_view& sql); + void GetRowString(sqlite3_stmt* stmt, int colCount, std::string& rowStr); + std::list internalTables_ = {}; + bool exportMetaTable_ = false; + bool pared_ = false; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif diff --git a/host/trace_streamer/src/trace_data/trace_stdtype.cpp b/host/trace_streamer/src/trace_data/trace_stdtype.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c791a84d9b452a28c1f3970003e02484e79d9bb9 --- /dev/null +++ b/host/trace_streamer/src/trace_data/trace_stdtype.cpp @@ -0,0 +1,695 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "trace_stdtype.h" +#include +namespace SysTuning { +namespace TraceStdtype { +size_t ThreadState::AppendThreadState(uint64_t ts, uint64_t dur, uint64_t cpu, uint64_t internalTid, uint64_t state) +{ + internalTids_.emplace_back(internalTid); + states_.emplace_back(state); + timeStamps_.emplace_back(ts); + durs_.emplace_back(dur); + cpus_.emplace_back(cpu); + return Size() - 1; +} + +void ThreadState::SetDuration(size_t index, uint64_t duration) +{ + durs_[index] = duration; +} + +uint64_t ThreadState::UpdateDuration(size_t index, uint64_t timestamp) +{ + if (durs_[index] == INVALID_UINT64) { + durs_[index] = timestamp - timeStamps_[index]; + } + return internalTids_[index]; +} + +void ThreadState::UpdateState(size_t index, uint64_t state) +{ + states_[index] = state; +} +void ThreadState::UpdateDuration(size_t index, uint64_t timestamp, uint64_t state) +{ + durs_[index] = timestamp - timeStamps_[index]; + states_[index] = state; +} + +uint64_t ThreadState::UpdateDuration(size_t index, uint64_t timestamp, uint64_t cpu, uint64_t state) +{ + cpus_[index] = cpu; + durs_[index] = timestamp - timeStamps_[index]; + states_[index] = state; + return internalTids_[index]; +} + +size_t SchedSlice::AppendSchedSlice(uint64_t ts, + uint64_t dur, + uint64_t cpu, + uint64_t internalTid, + uint64_t endState, + uint64_t priority) +{ + timeStamps_.emplace_back(ts); + durs_.emplace_back(dur); + cpus_.emplace_back(cpu); + internalTids_.emplace_back(internalTid); + endStates_.emplace_back(endState); + priority_.emplace_back(priority); + return Size() - 1; +} + +void SchedSlice::SetDuration(size_t index, uint64_t duration) +{ + durs_[index] = duration; +} + +void SchedSlice::Update(uint64_t index, uint64_t ts, uint64_t state, uint64_t pior) +{ + durs_[index] = ts - timeStamps_[index]; + endStates_[index] = state; + priority_[index] = pior; +} + +size_t CallStack::AppendInternalAsyncSlice(uint64_t startT, + uint64_t durationNs, + InternalTid internalTid, + DataIndex cat, + DataIndex name, + uint8_t depth, + uint64_t cookid, + const std::optional& parentId) +{ + AppendCommonInfo(startT, durationNs, internalTid); + AppendCallStack(cat, name, depth, parentId); + AppendDistributeInfo(); + cookies_.emplace_back(cookid); + ids_.emplace_back(ids_.size()); + return Size() - 1; +} +size_t CallStack::AppendInternalSlice(uint64_t startT, + uint64_t durationNs, + InternalTid internalTid, + DataIndex cat, + DataIndex name, + uint8_t depth, + const std::optional& parentId) +{ + AppendCommonInfo(startT, durationNs, internalTid); + AppendCallStack(cat, name, depth, parentId); + ids_.emplace_back(ids_.size()); + cookies_.emplace_back(INVALID_UINT64); + return Size() - 1; +} + +void CallStack::AppendCommonInfo(uint64_t startT, uint64_t durationNs, InternalTid internalTid) +{ + timeStamps_.emplace_back(startT); + durs_.emplace_back(durationNs); + callIds_.emplace_back(internalTid); +} +void CallStack::AppendCallStack(DataIndex cat, DataIndex name, uint8_t depth, std::optional parentId) +{ + parentIds_.emplace_back(parentId); + cats_.emplace_back(cat); + names_.emplace_back(name); + depths_.emplace_back(depth); +} +void CallStack::AppendDistributeInfo(const std::string& chainId, + const std::string& spanId, + const std::string& parentSpanId, + const std::string& flag, + const std::string& args) +{ + chainIds_.emplace_back(chainId); + spanIds_.emplace_back(spanId); + parentSpanIds_.emplace_back(parentSpanId); + flags_.emplace_back(flag); + args_.emplace_back(args); + argSet_.emplace_back(INVALID_UINT32); +} +void CallStack::AppendDistributeInfo() +{ + chainIds_.emplace_back(""); + spanIds_.emplace_back(""); + parentSpanIds_.emplace_back(""); + flags_.emplace_back(""); + args_.emplace_back(""); + argSet_.emplace_back(INVALID_UINT32); +} +void CallStack::AppendArgSet(uint32_t argSetId) +{ + chainIds_.emplace_back(""); + spanIds_.emplace_back(""); + parentSpanIds_.emplace_back(""); + flags_.emplace_back(""); + args_.emplace_back(""); + argSet_.emplace_back(argSetId); +} +void CallStack::SetDuration(size_t index, uint64_t timestamp) +{ + durs_[index] = timestamp - timeStamps_[index]; +} + +void CallStack::SetDurationAndArg(size_t index, uint64_t timestamp, uint32_t argSetId) +{ + SetTimeStamp(index, timestamp); + argSet_[index] = argSetId; +} +void CallStack::SetTimeStamp(size_t index, uint64_t timestamp) +{ + timeStamps_[index] = timestamp; +} + +const std::deque>& CallStack::ParentIdData() const +{ + return parentIds_; +} +const std::deque& CallStack::CatsData() const +{ + return cats_; +} +const std::deque& CallStack::NamesData() const +{ + return names_; +} +const std::deque& CallStack::Depths() const +{ + return depths_; +} +const std::deque& CallStack::Cookies() const +{ + return cookies_; +} +const std::deque& CallStack::CallIds() const +{ + return callIds_; +} +const std::deque& CallStack::ChainIds() const +{ + return chainIds_; +} +const std::deque& CallStack::SpanIds() const +{ + return spanIds_; +} +const std::deque& CallStack::ParentSpanIds() const +{ + return parentSpanIds_; +} +const std::deque& CallStack::Flags() const +{ + return flags_; +} +const std::deque& CallStack::ArgsData() const +{ + return args_; +} +const std::deque& CallStack::ArgSetIdsData() const +{ + return argSet_; +} + +size_t ArgSet::AppendNewArg(DataIndex nameId, BaseDataType dataType, int64_t value, size_t argSet) +{ + dataTypes_.emplace_back(dataType); + argset_.emplace_back(argSet); + ids_.emplace_back(Size()); + values_.emplace_back(value); + names_.emplace_back(nameId); + return Size() - 1; +} +const std::deque& ArgSet::DataTypes() const +{ + return dataTypes_; +} +const std::deque& ArgSet::ValuesData() const +{ + return values_; +} +const std::deque& ArgSet::ArgsData() const +{ + return argset_; +} +const std::deque& ArgSet::NamesData() const +{ + return names_; +} + +size_t SysMeasureFilter::AppendNewFilter(uint64_t filterId, DataIndex type, DataIndex nameId) +{ + ids_.emplace_back(filterId); + names_.emplace_back(nameId); + types_.emplace_back(type); + return ids_.size() - 1; +} +const std::deque& SysMeasureFilter::NamesData() const +{ + return names_; +} + +const std::deque& SysMeasureFilter::TypesData() const +{ + return types_; +} +size_t DataType::AppendNewDataType(BaseDataType dataType, DataIndex dataDescIndex) +{ + ids_.emplace_back(Size()); + dataTypes_.emplace_back(dataType); + descs_.emplace_back(dataDescIndex); + return Size() - 1; +} + +const std::deque& DataType::DataTypes() const +{ + return dataTypes_; +} +const std::deque& DataType::DataDesc() const +{ + return descs_; +} +size_t Filter::AppendNewFilterData(std::string type, std::string name, uint64_t sourceArgSetId) +{ + nameDeque_.emplace_back(name); + sourceArgSetId_.emplace_back(sourceArgSetId); + ids_.emplace_back(Size()); + typeDeque_.emplace_back(type); + return Size() - 1; +} + +size_t Measure::AppendMeasureData(uint32_t type, uint64_t timestamp, int64_t value, uint32_t filterId) +{ + valuesDeque_.emplace_back(value); + filterIdDeque_.emplace_back(filterId); + typeDeque_.emplace_back(type); + timeStamps_.emplace_back(timestamp); + return Size() - 1; +} + +size_t Raw::AppendRawData(uint32_t id, uint64_t timestamp, uint32_t name, uint32_t cpu, uint32_t internalTid) +{ + ids_.emplace_back(id); + timeStamps_.emplace_back(timestamp); + nameDeque_.emplace_back(name); + cpuDeque_.emplace_back(cpu); + itidDeque_.emplace_back(internalTid); + return Size() - 1; +} + +size_t ThreadMeasureFilter::AppendNewFilter(uint64_t filterId, uint32_t nameIndex, uint64_t internalTid) +{ + filterId_.emplace_back(filterId); + nameIndex_.emplace_back(nameIndex); + internalTids_.emplace_back(internalTid); + return Size() - 1; +} + +size_t Instants::AppendInstantEventData(uint64_t timestamp, DataIndex nameIndex, int64_t internalTid) +{ + internalTids_.emplace_back(internalTid); + timeStamps_.emplace_back(timestamp); + NameIndexs_.emplace_back(nameIndex); + return Size() - 1; +} +size_t LogInfo::AppendNewLogInfo(uint64_t seq, + uint64_t timestamp, + uint32_t pid, + uint32_t tid, + DataIndex level, + DataIndex tag, + DataIndex context, + uint64_t originTs) +{ + hilogLineSeqs_.emplace_back(seq); + timeStamps_.emplace_back(timestamp); + pids_.emplace_back(pid); + tids_.emplace_back(tid); + levels_.emplace_back(level); + tags_.emplace_back(tag); + contexts_.emplace_back(context); + originTs_.emplace_back(originTs); + return Size() - 1; +} +const std::deque& LogInfo::HilogLineSeqs() const +{ + return hilogLineSeqs_; +} +const std::deque& LogInfo::Pids() const +{ + return pids_; +} +const std::deque& LogInfo::Tids() const +{ + return tids_; +} +const std::deque& LogInfo::Levels() const +{ + return levels_; +} +const std::deque& LogInfo::Tags() const +{ + return tags_; +} +const std::deque& LogInfo::Contexts() const +{ + return contexts_; +} +const std::deque& LogInfo::OriginTimeStamData() const +{ + return originTs_; +} + +size_t HeapInfo::AppendNewHeapInfo(uint64_t eventId, + uint32_t ipid, + uint32_t itid, + DataIndex eventType, + uint64_t timestamp, + uint64_t endTimestamp, + uint64_t duration, + uint64_t addr, + int64_t heapSize, + int64_t allHeapSize, + uint64_t currentSizeDur) +{ + eventIds_.emplace_back(eventId); + ipids_.emplace_back(ipid); + itids_.emplace_back(itid); + eventTypes_.emplace_back(eventType); + timeStamps_.emplace_back(timestamp); + endTimestamps_.emplace_back(endTimestamp); + durations_.emplace_back(duration); + addrs_.emplace_back(addr); + heapSizes_.emplace_back(heapSize); + countHeapSizes_ += allHeapSize; + allHeapSizes_.emplace_back(countHeapSizes_); + currentSizeDurs_.emplace_back(currentSizeDur); + return Size() - 1; +} +void HeapInfo::UpdateHeapDuration(size_t row, uint64_t endTimestamp) +{ + endTimestamps_[row] = endTimestamp; + durations_[row] = endTimestamp - timeStamps_[row]; +} +void HeapInfo::UpdateCurrentSizeDur(size_t row, uint64_t nextStartTime) +{ + if (row == 0) { + return; + } + if (nextStartTime > timeStamps_[--row]) { + currentSizeDurs_[row] = nextStartTime - timeStamps_[row]; + } +} +const std::deque& HeapInfo::EventIds() const +{ + return eventIds_; +} +const std::deque& HeapInfo::Ipids() const +{ + return ipids_; +} +const std::deque& HeapInfo::Itids() const +{ + return itids_; +} +const std::deque& HeapInfo::EventTypes() const +{ + return eventTypes_; +} +const std::deque& HeapInfo::EndTimeStamps() const +{ + return endTimestamps_; +} +const std::deque& HeapInfo::Durations() const +{ + return durations_; +} +const std::deque& HeapInfo::Addrs() const +{ + return addrs_; +} +const std::deque& HeapInfo::HeapSizes() const +{ + return heapSizes_; +} +const std::deque& HeapInfo::AllHeapSizes() const +{ + return allHeapSizes_; +} +const std::deque& HeapInfo::CurrentSizeDurs() const +{ + return currentSizeDurs_; +} + +size_t HeapFrameInfo::AppendNewHeapFrameInfo(uint64_t eventId, + uint64_t depth, + DataIndex ip, + DataIndex sp, + DataIndex symbolName, + DataIndex filePath, + DataIndex offset, + uint64_t symbolOffset) +{ + eventIds_.emplace_back(eventId); + depths_.emplace_back(depth); + ips_.emplace_back(ip); + sps_.emplace_back(sp); + symbolNames_.emplace_back(symbolName); + filePaths_.emplace_back(filePath); + offsets_.emplace_back(offset); + symbolOffsets_.emplace_back(symbolOffset); + return Size() - 1; +} +const std::deque& HeapFrameInfo::EventIds() const +{ + return eventIds_; +} +const std::deque& HeapFrameInfo::Depths() const +{ + return depths_; +} +const std::deque& HeapFrameInfo::Ips() const +{ + return ips_; +} +const std::deque& HeapFrameInfo::Sps() const +{ + return sps_; +} +const std::deque& HeapFrameInfo::SymbolNames() const +{ + return symbolNames_; +} +const std::deque& HeapFrameInfo::FilePaths() const +{ + return filePaths_; +} +const std::deque& HeapFrameInfo::Offsets() const +{ + return offsets_; +} +const std::deque& HeapFrameInfo::SymbolOffsets() const +{ + return symbolOffsets_; +} + +size_t Hidump::AppendNewHidumpInfo(uint64_t timestamp, uint32_t fps) +{ + timeStamps_.emplace_back(timestamp); + fpss_.emplace_back(fps); + return Size() - 1; +} +const std::deque& Hidump::Fpss() const +{ + return fpss_; +} +size_t ProcessMeasureFilter::AppendNewFilter(uint64_t id, DataIndex name, uint32_t internalPid) +{ + internalPids_.emplace_back(internalPid); + ids_.emplace_back(id); + names_.emplace_back(name); + return Size() - 1; +} +size_t ClockEventData::AppendNewFilter(uint64_t id, DataIndex type, DataIndex name, uint64_t cpu) +{ + cpus_.emplace_back(cpu); + ids_.emplace_back(id); + types_.emplace_back(type); + names_.emplace_back(name); + return Size() - 1; +} +size_t ClkEventData::AppendNewFilter(uint64_t id, uint64_t rate, DataIndex name, uint64_t cpu) +{ + ids_.emplace_back(id); + rates_.emplace_back(rate); + names_.emplace_back(name); + cpus_.emplace_back(cpu); + return Size() - 1; +} +size_t SysCall::AppendSysCallData(int64_t sysCallNum, DataIndex type, uint64_t ipid, uint64_t timestamp, int64_t ret) +{ + sysCallNums_.emplace_back(sysCallNum); + types_.emplace_back(type); + ipids_.emplace_back(ipid); + timeStamps_.emplace_back(timestamp); + rets_.emplace_back(ret); + return Size() - 1; +} +StatAndInfo::StatAndInfo() +{ + // sched_switch_received | sched_switch_not_match | sched_switch_not_not_supported etc. + for (int i = TRACE_EVENT_START; i < TRACE_EVENT_MAX; i++) { + event_[i] = config_.eventNameMap_.at(static_cast(i)); + } + for (int j = STAT_EVENT_START; j < STAT_EVENT_MAX; j++) { + stat_[j] = config_.eventErrorDescMap_.at(static_cast(j)); + } + + for (int i = TRACE_EVENT_START; i < TRACE_EVENT_MAX; i++) { + for (int j = STAT_EVENT_START; j < STAT_EVENT_MAX; j++) { + statSeverity_[i][j] = config_.eventParserStatSeverityDescMap_.at(static_cast(i)) + .at(static_cast(j)); + } + } + + for (int i = TRACE_EVENT_START; i < TRACE_EVENT_MAX; i++) { + for (int j = STAT_EVENT_START; j < STAT_EVENT_MAX; j++) { + statSeverityDesc_[i][j] = config_.serverityLevelDescMap_.at(statSeverity_[i][j]); + } + } + + for (int i = TRACE_EVENT_START; i < TRACE_EVENT_MAX; i++) { + for (int j = STAT_EVENT_START; j < STAT_EVENT_MAX; j++) { + statCount_[i][j] = 0; + } + } +} +void StatAndInfo::IncreaseStat(SupportedTraceEventType eventType, StatType type) +{ + statCount_[eventType][type]++; +} +const uint32_t& StatAndInfo::GetValue(SupportedTraceEventType eventType, StatType type) const +{ + return statCount_[eventType][type]; +} +const std::string& StatAndInfo::GetEvent(SupportedTraceEventType eventType) const +{ + return event_[eventType]; +} +const std::string& StatAndInfo::GetStat(StatType type) const +{ + return stat_[type]; +} +const std::string& StatAndInfo::GetSeverityDesc(SupportedTraceEventType eventType, StatType type) const +{ + return statSeverityDesc_[eventType][type]; +} +const StatSeverityLevel& StatAndInfo::GetSeverity(SupportedTraceEventType eventType, StatType type) const +{ + return statSeverity_[eventType][type]; +} +uint64_t SymbolsData::Size() const +{ + return addrs_.size(); +} +void SymbolsData::InsertSymbol(const DataIndex& name, const uint64_t& addr) +{ + addrs_.emplace_back(addr); + funcName_.emplace_back(name); +} +const std::deque& SymbolsData::GetConstFuncNames() const +{ + return funcName_; +} +const std::deque& SymbolsData::GetConstAddrs() const +{ + return addrs_; +} +MetaData::MetaData() +{ + columnNames_.resize(METADATA_ITEM_MAX); + values_.resize(METADATA_ITEM_MAX); + columnNames_[METADATA_ITEM_DATASIZE] = METADATA_ITEM_DATASIZE_COLNAME; + columnNames_[METADATA_ITEM_PARSETOOL_NAME] = METADATA_ITEM_PARSETOOL_NAME_COLNAME; + columnNames_[METADATA_ITEM_PARSERTOOL_VERSION] = METADATA_ITEM_PARSERTOOL_VERSION_COLNAME; + columnNames_[METADATA_ITEM_PARSERTOOL_PUBLISH_DATETIME] = METADATA_ITEM_PARSERTOOL_PUBLISH_DATETIME_COLNAME; + columnNames_[METADATA_ITEM_SOURCE_FILENAME] = METADATA_ITEM_SOURCE_FILENAME_COLNAME; + columnNames_[METADATA_ITEM_OUTPUT_FILENAME] = METADATA_ITEM_OUTPUT_FILENAME_COLNAME; + columnNames_[METADATA_ITEM_PARSERTIME] = METADATA_ITEM_PARSERTIME_COLNAME; + columnNames_[METADATA_ITEM_TRACE_DURATION] = METADATA_ITEM_TRACE_DURATION_COLNAME; + columnNames_[METADATA_ITEM_SOURCE_DATETYPE] = METADATA_ITEM_SOURCE_DATETYPE_COLNAME; + values_[METADATA_ITEM_PARSETOOL_NAME] = "trace_streamer"; +} +void MetaData::SetTraceType(const std::string& traceType) +{ + values_[METADATA_ITEM_SOURCE_DATETYPE] = traceType; +} +void MetaData::SetSourceFileName(const std::string& fileName) +{ + MetaData::values_[METADATA_ITEM_SOURCE_FILENAME] = fileName; +} +void MetaData::SetOutputFileName(const std::string& fileName) +{ + MetaData::values_[METADATA_ITEM_OUTPUT_FILENAME] = fileName; +} +void MetaData::SetParserToolVersion(const std::string& version) +{ + values_[METADATA_ITEM_PARSERTOOL_VERSION] = version; +} +void MetaData::SetParserToolPublishDateTime(const std::string& datetime) +{ + values_[METADATA_ITEM_PARSERTOOL_PUBLISH_DATETIME] = datetime; +} +void MetaData::SetTraceDataSize(uint64_t dataSize) +{ + std::stringstream ss; + ss << dataSize; + values_[METADATA_ITEM_DATASIZE] = ss.str(); + // Function 'time' may return error. It is not allowed to do anything that might fail inside the constructor. + time_t rawtime; + struct tm* timeinfo = nullptr; + void(time(&rawtime)); + timeinfo = localtime(&rawtime); + values_[METADATA_ITEM_PARSERTIME] = asctime(timeinfo); +} +void MetaData::SetTraceDuration(uint64_t dur) +{ + values_[METADATA_ITEM_TRACE_DURATION] = std::to_string(dur) + " s"; +} +const std::string& MetaData::Value(uint64_t row) const +{ + return values_[row]; +} +const std::string& MetaData::Name(uint64_t row) const +{ + return columnNames_[row]; +} +DataIndex DataDict::GetStringIndex(std::string_view str) +{ + auto hashValue = hashFun(str); + auto itor = dataDictInnerMap_.find(hashValue); + if (itor != dataDictInnerMap_.end()) { + TS_ASSERT(std::string_view(dataDict_[itor->second]) == str); + return itor->second; + } + dataDict_.emplace_back(std::string(str)); + DataIndex stringIdentity = dataDict_.size() - 1; + dataDictInnerMap_.emplace(hashValue, stringIdentity); + return stringIdentity; +} +} // namespace TraceStdtype +} // namespace SysTuning diff --git a/host/trace_streamer/src/trace_data/trace_stdtype.h b/host/trace_streamer/src/trace_data/trace_stdtype.h new file mode 100644 index 0000000000000000000000000000000000000000..2ecd2360d011d16ffef948924ae66467304942d2 --- /dev/null +++ b/host/trace_streamer/src/trace_data/trace_stdtype.h @@ -0,0 +1,824 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TRACE_STDTYPE_H +#define TRACE_STDTYPE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cfg/trace_streamer_config.h" +#include "log.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStdtype { +using namespace SysTuning::TraceCfg; +using namespace SysTuning::TraceStreamer; +class CacheBase { +public: + size_t Size() const + { + return std::max(timeStamps_.size(), ids_.size()); + } + const std::deque& IdsData() const + { + return ids_; + } + const std::deque& TimeStamData() const + { + return timeStamps_; + } + const std::deque& InternalTidsData() const + { + return internalTids_; + } + void Clear() + { + internalTids_.clear(); + timeStamps_.clear(); + ids_.clear(); + } +public: + std::deque internalTids_ = {}; + std::deque timeStamps_ = {}; + std::deque ids_ = {}; +}; + +class CpuCacheBase { +public: + const std::deque& DursData() const + { + return durs_; + } + + const std::deque& CpusData() const + { + return cpus_; + } + void Clear() + { + durs_.clear(); + cpus_.clear(); + } +public: + std::deque durs_; + std::deque cpus_; +}; +class Thread { +public: + explicit Thread(uint32_t t) : tid_(t) {} + InternalPid internalPid_ = 0; + uint32_t tid_ = 0; + DataIndex nameIndex_ = 0; + InternalTime startT_ = 0; + InternalTime endT_ = 0; +}; + +class Process { +public: + explicit Process(uint32_t p) : pid_(p) {} + std::string cmdLine_ = ""; + InternalTime startT_ = 0; + uint32_t pid_ = 0; +}; + +class ThreadState : public CacheBase, public CpuCacheBase { +public: + size_t AppendThreadState(uint64_t ts, uint64_t dur, uint64_t cpu, uint64_t internalTid, uint64_t state); + void SetDuration(size_t index, uint64_t duration); + uint64_t UpdateDuration(size_t index, uint64_t timestamp); + void UpdateState(size_t index, uint64_t state); + void UpdateDuration(size_t index, uint64_t timestamp, uint64_t state); + uint64_t UpdateDuration(size_t index, uint64_t timestamp, uint64_t cpu, uint64_t state); + const std::deque& StatesData() const + { + return states_; + } + void Clear() + { + CacheBase::Clear(); + CpuCacheBase::Clear(); + states_.clear(); + } + +private: + std::deque states_ = {}; +}; + +class SchedSlice : public CacheBase, public CpuCacheBase { +public: + size_t AppendSchedSlice(uint64_t ts, + uint64_t dur, + uint64_t cpu, + uint64_t internalTid, + uint64_t endState, + uint64_t priority); + void SetDuration(size_t index, uint64_t duration); + void Update(uint64_t index, uint64_t ts, uint64_t state, uint64_t pior); + + const std::deque& EndStatesData() const + { + return endStates_; + } + + const std::deque& PriorityData() const + { + return priority_; + } + void Clear() + { + CacheBase::Clear(); + CpuCacheBase::Clear(); + endStates_.clear(); + priority_.clear(); + } + +private: + std::deque endStates_ = {}; + std::deque priority_ = {}; +}; + +class CallStack : public CacheBase, public CpuCacheBase { +public: + size_t AppendInternalAsyncSlice(uint64_t startT, + uint64_t durationNs, + InternalTid internalTid, + DataIndex cat, + DataIndex name, + uint8_t depth, + uint64_t cookid, + const std::optional& parentId); + size_t AppendInternalSlice(uint64_t startT, + uint64_t durationNs, + InternalTid internalTid, + DataIndex cat, + DataIndex name, + uint8_t depth, + const std::optional& parentId); + void AppendDistributeInfo(const std::string& chainId, + const std::string& spanId, + const std::string& parentSpanId, + const std::string& flag, + const std::string& args); + void AppendArgSet(uint32_t argSetId); + void AppendDistributeInfo(); + void SetDuration(size_t index, uint64_t timestamp); + void SetDurationAndArg(size_t index, uint64_t timestamp, uint32_t argSetId); + void SetTimeStamp(size_t index, uint64_t timestamp); + void Clear() + { + CacheBase::Clear(); + CpuCacheBase::Clear(); + cats_.clear(); + cookies_.clear(); + callIds_.clear(); + names_.clear(); + depths_.clear(); + chainIds_.clear(); + spanIds_.clear(); + parentSpanIds_.clear(); + flags_.clear(); + args_.clear(); + argSet_.clear(); + } + + const std::deque>& ParentIdData() const; + const std::deque& CatsData() const; + const std::deque& NamesData() const; + const std::deque& Depths() const; + const std::deque& Cookies() const; + const std::deque& CallIds() const; + const std::deque& ChainIds() const; + const std::deque& SpanIds() const; + const std::deque& ParentSpanIds() const; + const std::deque& Flags() const; + const std::deque& ArgsData() const; + const std::deque& ArgSetIdsData() const; + +private: + void AppendCommonInfo(uint64_t startT, uint64_t durationNs, InternalTid internalTid); + void AppendCallStack(DataIndex cat, DataIndex name, uint8_t depth, std::optional parentId); + +private: + std::deque> parentIds_; + std::deque cats_ = {}; + std::deque cookies_ = {}; + std::deque callIds_ = {}; + std::deque names_ = {}; + std::deque depths_ = {}; + + std::deque chainIds_ = {}; + std::deque spanIds_ = {}; + std::deque parentSpanIds_ = {}; + std::deque flags_ = {}; + std::deque args_ = {}; + std::deque argSet_ = {}; +}; + +class Filter : public CacheBase { +public: + size_t AppendNewFilterData(std::string type, std::string name, uint64_t sourceArgSetId); + const std::deque& NameData() const + { + return nameDeque_; + } + const std::deque& TypeData() const + { + return typeDeque_; + } + const std::deque& SourceArgSetIdData() const + { + return sourceArgSetId_; + } + void Clear() + { + CacheBase::Clear(); + nameDeque_.clear(); + typeDeque_.clear(); + sourceArgSetId_.clear(); + } + +private: + std::deque nameDeque_ = {}; + std::deque typeDeque_ = {}; + std::deque sourceArgSetId_ = {}; +}; + +class Measure : public CacheBase { +public: + size_t AppendMeasureData(uint32_t type, uint64_t timestamp, int64_t value, uint32_t filterId); + const std::deque& TypeData() const + { + return typeDeque_; + } + const std::deque& ValuesData() const + { + return valuesDeque_; + } + const std::deque& FilterIdData() const + { + return filterIdDeque_; + } + void Clear() + { + CacheBase::Clear(); + typeDeque_.clear(); + valuesDeque_.clear(); + filterIdDeque_.clear(); + } + +private: + std::deque typeDeque_ = {}; + std::deque valuesDeque_ = {}; + std::deque filterIdDeque_ = {}; +}; + +class Raw : public CacheBase { +public: + size_t AppendRawData(uint32_t id, uint64_t timestamp, uint32_t name, uint32_t cpu, uint32_t internalTid); + const std::deque& NameData() const + { + return nameDeque_; + } + const std::deque& CpuData() const + { + return cpuDeque_; + } + const std::deque& InternalTidData() const + { + return itidDeque_; + } + void Clear() + { + CacheBase::Clear(); + nameDeque_.clear(); + cpuDeque_.clear(); + itidDeque_.clear(); + } + +private: + std::deque nameDeque_ = {}; + std::deque cpuDeque_ = {}; + std::deque itidDeque_ = {}; +}; + +class ThreadMeasureFilter { +public: + size_t AppendNewFilter(uint64_t filterId, uint32_t nameIndex, uint64_t internalTid); + size_t Size() const + { + return filterId_.size(); + } + const std::deque& FilterIdData() const + { + return filterId_; + } + const std::deque& InternalTidData() const + { + return internalTids_; + } + const std::deque& NameIndexData() const + { + return nameIndex_; + } + void Clear() + { + filterId_.clear(); + internalTids_.clear(); + nameIndex_.clear(); + } + +private: + std::deque filterId_ = {}; + std::deque internalTids_ = {}; + std::deque nameIndex_ = {}; +}; + +class CpuMeasureFilter : public CacheBase { +public: + inline size_t AppendNewFilter(uint64_t filterId, DataIndex name, uint64_t cpu) + { + ids_.emplace_back(filterId); + cpu_.emplace_back(cpu); + name_.emplace_back(name); + return Size() - 1; + } + + const std::deque& CpuData() const + { + return cpu_; + } + + const std::deque& TypeData() const + { + return type_; + } + + const std::deque& NameData() const + { + return name_; + } + void Clear() + { + CacheBase::Clear(); + cpu_.clear(); + type_.clear(); + name_.clear(); + } + +private: + std::deque cpu_ = {}; + std::deque type_ = {}; + std::deque name_ = {}; +}; + +class Instants : public CacheBase { +public: + size_t AppendInstantEventData(uint64_t timestamp, DataIndex nameIndex, int64_t internalTid); + + const std::deque& NameIndexsData() const + { + return NameIndexs_; + } + void Clear() + { + CacheBase::Clear(); + NameIndexs_.clear(); + } + +private: + std::deque NameIndexs_; +}; + +class ProcessMeasureFilter : public CacheBase { +public: + size_t AppendNewFilter(uint64_t id, DataIndex name, uint32_t internalPid); + + const std::deque& UpidsData() const + { + return internalPids_; + } + + const std::deque& NamesData() const + { + return names_; + } + void Clear() + { + CacheBase::Clear(); + internalPids_.clear(); + names_.clear(); + } + +private: + std::deque internalPids_ = {}; + std::deque names_ = {}; +}; +class ClockEventData : public CacheBase { +public: + size_t AppendNewFilter(uint64_t id, DataIndex type, DataIndex name, uint64_t cpu); + + const std::deque& CpusData() const + { + return cpus_; + } + + const std::deque& NamesData() const + { + return names_; + } + const std::deque& TypesData() const + { + return types_; + } + void Clear() + { + CacheBase::Clear(); + cpus_.clear(); + names_.clear(); + types_.clear(); + } + +private: + std::deque cpus_ = {}; // in clock_set_rate event, it save cpu + std::deque names_ = {}; + std::deque types_ = {}; +}; +class ClkEventData : public CacheBase { +public: + size_t AppendNewFilter(uint64_t id, uint64_t rate, DataIndex name, uint64_t cpu); + + const std::deque& NamesData() const + { + return names_; + } + const std::deque& RatesData() const + { + return rates_; + } + const std::deque& CpusData() const + { + return cpus_; + } + void Clear() + { + CacheBase::Clear(); + names_.clear(); + rates_.clear(); + cpus_.clear(); + } + +private: + std::deque names_; + std::deque rates_; + std::deque cpus_; +}; +class SysCall : public CacheBase { +public: + size_t AppendSysCallData(int64_t sysCallNum, DataIndex type, uint64_t ipid, uint64_t timestamp, int64_t ret); + const std::deque& SysCallsData() const + { + return sysCallNums_; + } + const std::deque& TypesData() const + { + return types_; + } + const std::deque& IpidsData() const + { + return ipids_; + } + const std::deque& RetsData() const + { + return rets_; + } + void Clear() + { + CacheBase::Clear(); + sysCallNums_.clear(); + types_.clear(); + ipids_.clear(); + rets_.clear(); + } + +private: + std::deque sysCallNums_ = {}; + std::deque types_ = {}; + std::deque ipids_ = {}; + std::deque rets_ = {}; +}; +class ArgSet : public CacheBase { +public: + size_t AppendNewArg(DataIndex nameId, BaseDataType dataType, int64_t value, size_t argSet); + const std::deque& DataTypes() const; + const std::deque& ValuesData() const; + const std::deque& ArgsData() const; + const std::deque& NamesData() const; + + void Clear() + { + CacheBase::Clear(); + names_.clear(); + dataTypes_.clear(); + values_.clear(); + argset_.clear(); + } +private: + std::deque names_ = {}; + std::deque dataTypes_ = {}; + std::deque values_ = {}; + std::deque argset_ = {}; +}; +class SysMeasureFilter : public CacheBase { +public: + size_t AppendNewFilter(uint64_t filterId, DataIndex type, DataIndex nameId); + const std::deque& NamesData() const; + const std::deque& TypesData() const; + void Clear() + { + CacheBase::Clear(); + types_.clear(); + names_.clear(); + } + +private: + std::deque types_ = {}; + std::deque names_ = {}; +}; +class DataType : public CacheBase { +public: + size_t AppendNewDataType(BaseDataType dataType, DataIndex dataDescIndex); + const std::deque& DataTypes() const; + const std::deque& DataDesc() const; + void Clear() + { + CacheBase::Clear(); + dataTypes_.clear(); + descs_.clear(); + } + +private: + std::deque dataTypes_ = {}; + std::deque descs_ = {}; +}; +class LogInfo : public CacheBase { +public: + size_t AppendNewLogInfo(uint64_t seq, + uint64_t timestamp, + uint32_t pid, + uint32_t tid, + DataIndex level, + DataIndex tag, + DataIndex context, + uint64_t originTs); + const std::deque& HilogLineSeqs() const; + const std::deque& Pids() const; + const std::deque& Tids() const; + const std::deque& Levels() const; + const std::deque& Tags() const; + const std::deque& Contexts() const; + const std::deque& OriginTimeStamData() const; + void Clear() + { + CacheBase::Clear(); + hilogLineSeqs_.clear(); + pids_.clear(); + levels_.clear(); + tags_.clear(); + contexts_.clear(); + originTs_.clear(); + } + +private: + std::deque hilogLineSeqs_ = {}; + std::deque pids_ = {}; + std::deque tids_ = {}; + std::deque levels_ = {}; + std::deque tags_ = {}; + std::deque contexts_ = {}; + std::deque originTs_ = {}; +}; + +class HeapInfo : public CacheBase { +public: + size_t AppendNewHeapInfo(uint64_t eventId, + uint32_t ipid, + uint32_t itid, + DataIndex eventType, + uint64_t timestamp, + uint64_t endTimestamp, + uint64_t duration, + uint64_t addr, + int64_t heapSize, + int64_t allHeapSize, + uint64_t currentSizeDur); + void UpdateHeapDuration(size_t row, uint64_t endTimestamp); + void UpdateCurrentSizeDur(size_t row, uint64_t nextStartTime); + const std::deque& EventIds() const; + const std::deque& Ipids() const; + const std::deque& Itids() const; + const std::deque& EventTypes() const; + const std::deque& EndTimeStamps() const; + const std::deque& Durations() const; + const std::deque& Addrs() const; + const std::deque& HeapSizes() const; + const std::deque& AllHeapSizes() const; + const std::deque& CurrentSizeDurs() const; + void Clear() + { + CacheBase::Clear(); + eventIds_.clear(); + ipids_.clear(); + itids_.clear(); + eventTypes_.clear(); + endTimestamps_.clear(); + durations_.clear(); + addrs_.clear(); + heapSizes_.clear(); + allHeapSizes_.clear(); + currentSizeDurs_.clear(); + } + +private: + std::deque eventIds_ = {}; + std::deque ipids_ = {}; + std::deque itids_ = {}; + std::deque eventTypes_ = {}; + std::deque endTimestamps_ = {}; + std::deque durations_ = {}; + std::deque addrs_ = {}; + std::deque heapSizes_ = {}; + std::deque allHeapSizes_ = {}; + std::deque currentSizeDurs_ = {}; + int64_t countHeapSizes_ = 0; +}; + +class HeapFrameInfo { +public: + size_t AppendNewHeapFrameInfo(uint64_t eventId, + uint64_t depth, + DataIndex ip, + DataIndex sp, + DataIndex symbolName, + DataIndex filePath, + DataIndex offset, + uint64_t symbolOffset); + const std::deque& EventIds() const; + const std::deque& Depths() const; + const std::deque& Ips() const; + const std::deque& Sps() const; + const std::deque& SymbolNames() const; + const std::deque& FilePaths() const; + const std::deque& Offsets() const; + const std::deque& SymbolOffsets() const; + size_t Size() const + { + return eventIds_.size(); + } + void Clear() + { + eventIds_.clear(); + depths_.clear(); + ips_.clear(); + sps_.clear(); + symbolNames_.clear(); + filePaths_.clear(); + offsets_.clear(); + symbolOffsets_.clear(); + } + +private: + std::deque eventIds_ = {}; + std::deque depths_ = {}; + std::deque ips_ = {}; + std::deque sps_ = {}; + std::deque symbolNames_ = {}; + std::deque filePaths_ = {}; + std::deque offsets_ = {}; + std::deque symbolOffsets_ = {}; +}; + +class Hidump : public CacheBase { +public: + size_t AppendNewHidumpInfo(uint64_t timestamp, uint32_t fps); + const std::deque& Fpss() const; +private: + std::deque fpss_ = {}; +}; + +class StatAndInfo { +public: + StatAndInfo(); + ~StatAndInfo() = default; + void IncreaseStat(SupportedTraceEventType eventType, StatType type); + const uint32_t& GetValue(SupportedTraceEventType eventType, StatType type) const; + const std::string& GetEvent(SupportedTraceEventType eventType) const; + const std::string& GetStat(StatType type) const; + const std::string& GetSeverityDesc(SupportedTraceEventType eventType, StatType type) const; + const StatSeverityLevel& GetSeverity(SupportedTraceEventType eventType, StatType type) const; + +private: + uint32_t statCount_[TRACE_EVENT_MAX][STAT_EVENT_MAX]; + std::string event_[TRACE_EVENT_MAX]; + std::string stat_[STAT_EVENT_MAX]; + std::string statSeverityDesc_[TRACE_EVENT_MAX][STAT_EVENT_MAX]; + StatSeverityLevel statSeverity_[TRACE_EVENT_MAX][STAT_EVENT_MAX]; + TraceStreamerConfig config_; +}; +class SymbolsData { +public: + SymbolsData() = default; + ~SymbolsData() = default; + uint64_t Size() const; + void InsertSymbol(const DataIndex& name, const uint64_t& addr); + const std::deque& GetConstFuncNames() const; + const std::deque& GetConstAddrs() const; + void Clear() + { + addrs_.clear(); + funcName_.clear(); + } +private: + std::deque addrs_ = {}; + std::deque funcName_ = {}; +}; +class MetaData { +public: + MetaData(); + ~MetaData() = default; + void SetTraceType(const std::string& traceType); + void SetSourceFileName(const std::string& fileName); + void SetOutputFileName(const std::string& fileName); + void SetParserToolVersion(const std::string& version); + void SetParserToolPublishDateTime(const std::string& datetime); + void SetTraceDataSize(uint64_t dataSize); + void SetTraceDuration(uint64_t dur); + const std::string& Value(uint64_t row) const; + const std::string& Name(uint64_t row) const; + void Clear() + { + columnNames_.clear(); + values_.clear(); + } +private: + const std::string METADATA_ITEM_DATASIZE_COLNAME = "datasize"; + const std::string METADATA_ITEM_PARSETOOL_NAME_COLNAME = "parse_tool"; + const std::string METADATA_ITEM_PARSERTOOL_VERSION_COLNAME = "tool_version"; + const std::string METADATA_ITEM_PARSERTOOL_PUBLISH_DATETIME_COLNAME = "tool_publish_time"; + const std::string METADATA_ITEM_SOURCE_FILENAME_COLNAME = "source_name"; + const std::string METADATA_ITEM_OUTPUT_FILENAME_COLNAME = "output_name"; + const std::string METADATA_ITEM_PARSERTIME_COLNAME = "runtime"; + const std::string METADATA_ITEM_TRACE_DURATION_COLNAME = "trace_duration"; + const std::string METADATA_ITEM_SOURCE_DATETYPE_COLNAME = "source_type"; + + std::deque columnNames_ = {}; + std::deque values_ = {}; +}; +class DataDict { +public: + size_t Size() const + { + return dataDict_.size(); + } + DataIndex GetStringIndex(std::string_view str); + const std::string& GetDataFromDict(DataIndex id) const + { + TS_ASSERT(id < dataDict_.size()); + return dataDict_[id]; + } + void Clear() + { + dataDict_.clear(); + } +public: + std::deque dataDict_; + std::unordered_map dataDictInnerMap_; + +private: + std::hash hashFun; +}; +} // namespace TraceStdtype +} // namespace SysTuning + +#endif // TRACE_STDTYPE_H diff --git a/host/trace_streamer/src/trace_streamer.pro b/host/trace_streamer/src/trace_streamer.pro new file mode 100644 index 0000000000000000000000000000000000000000..45afeed64405658f50f15f42f494329b9811994a --- /dev/null +++ b/host/trace_streamer/src/trace_streamer.pro @@ -0,0 +1,79 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +QT -= gui core +TEMPLATE = app +#TEMPLATE = lib +CONFIG += c++17 console +#CONFIG += c++17 lib +#CONFIG += c++17 +CONFIG += WITHRPC +TARGET = trace_streamer +DEFINES += SUPPORTTHREAD + +#CONFIG += release + +DEFINES += HAVE_PTHREAD +DEFINES += _LIBCPP_DISABLE_AVAILABILITY + +DEFINES += HAVE_PTHREAD +ROOTSRCDIR = $$PWD/../ + +#QMAKE_CXXFLAGS =-ftrapv -fPIE -fstack-protector-strong -fstack-protector-all -D_FORTIFY_SOURCE=2 -O2 +#QMAKE_CFLAGS=-ftrapv -fPIE -fstack-protector-strong -fstack-protector-all -D_FORTIFY_SOURCE=2 -O2 +!unix{ +#QMAKE_LFLAGS=-fpie -Wl,-rpath=\$ORIGIN/. +} else { +#QMAKE_LFLAGS=-fpie +#QMAKE_LFLAGS=-fpie -Wl,-z,noexecstack -Wl,-z,now -Wl,-rpath=\$ORIGIN/. -Wl,-z,relro +} +include($$PWD/multi_platform/global.pri) +INCLUDEPATH += $$PWD/include \ + $$PWD/../third_party/protobuf/src \ + $$PWD/../third_party/sqlite/include \ + $$PWD/../third_party/protogen/gen \ + $$PWD/../third_party/protogen/gen/types/plugins/memory_data \ + $$PWD/../third_party/protogen/gen/types/plugins/ftrace_data \ + $$PWD/../third_party/protogen/gen/types/plugins/hilog_data \ + $$PWD/../third_party/protogen/gen/types/plugins/native_hook \ + $$PWD/../third_party/protogen/gen/types/plugins/hidump_data + + +include($$PWD/trace_streamer/trace_streamer.pri) +include($$PWD/base/base.pri) +WITHRPC{ +DEFINES += WIN32_LEAN_AND_MEAN +include($$PWD/rpc/rpc.pri) +INCLUDEPATH += $$PWD/rpc +!unix{ +LIBS += -lws2_32 +} +} +include($$PWD/filter/filter.pri) +include($$PWD/parser/parser.pri) +include($$PWD/multi_platform/protogen.pri) +include($$PWD/table/table.pri) +include($$PWD/trace_data/trace_data.pri) +include($$PWD/cfg/cfg.pri) +include($$PWD/ext/sqlite_ext.pri) + +unix{ +LIBS += -L$$DESTDIR/ -lstdc++ \ + -L$${ROOTSRCDIR}/lib/$${DESTFOLDER} -lprotobuf -lsqlite -ldl +} else { +LIBS += -L$$DESTDIR/ -lstdc++ \ + -L$${ROOTSRCDIR}/lib/$${DESTFOLDER} -lprotobuf -lsqlite +} +INCLUDEPATH +=$$PWD/include + +SOURCES += \ + main.cpp diff --git a/host/trace_streamer/src/trace_streamer/trace_streamer.pri b/host/trace_streamer/src/trace_streamer/trace_streamer.pri new file mode 100644 index 0000000000000000000000000000000000000000..9b33d314fe33af24bfe6409b2d61751a3c83e308 --- /dev/null +++ b/host/trace_streamer/src/trace_streamer/trace_streamer.pri @@ -0,0 +1,21 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +INCLUDEPATH += $$PWD +HEADERS += \ + $$PWD/trace_streamer_selector.h \ + $$PWD/trace_streamer_filters.h + +SOURCES += \ + $$PWD/trace_streamer_selector.cpp \ + $$PWD/trace_streamer_filters.cpp diff --git a/host/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp b/host/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a39ee3fee1557fd0e16e77a2a2d4c842a8691a6f --- /dev/null +++ b/host/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "trace_streamer_filters.h" +#include "args_filter.h" +#include "binder_filter.h" +#include "clock_filter.h" +#include "cpu_filter.h" +#include "filter_filter.h" +#include "irq_filter.h" +#include "measure_filter.h" +#include "process_filter.h" +#include "slice_filter.h" +#include "stat_filter.h" +#include "symbols_filter.h" +#include "system_event_measure_filter.h" + +namespace SysTuning { +namespace TraceStreamer { +TraceStreamerFilters::TraceStreamerFilters() = default; +TraceStreamerFilters::~TraceStreamerFilters() = default; +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/trace_streamer/trace_streamer_filters.h b/host/trace_streamer/src/trace_streamer/trace_streamer_filters.h new file mode 100644 index 0000000000000000000000000000000000000000..22e405a22a51878e0c04380e5970470087e932d7 --- /dev/null +++ b/host/trace_streamer/src/trace_streamer/trace_streamer_filters.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TRACE_STREAMERTOKEN_H +#define TRACE_STREAMERTOKEN_H + +#include +namespace SysTuning { +namespace TraceStreamer { +class SliceFilter; +class ProcessFilter; +class CpuFilter; +class MeasureFilter; +class FilterFilter; +class ClockFilter; +class SymbolsFilter; +class StatFilter; +class BinderFilter; +class ArgsFilter; +class IrqFilter; +class SystemEventMeasureFilter; +class TraceStreamerFilters { +public: + TraceStreamerFilters(); + ~TraceStreamerFilters(); + + std::unique_ptr clockFilter_; + std::unique_ptr filterFilter_; + std::unique_ptr sliceFilter_; + std::unique_ptr processFilter_; + std::unique_ptr cpuFilter_; + std::unique_ptr cpuMeasureFilter_; + std::unique_ptr threadMeasureFilter_; + std::unique_ptr threadFilter_; + std::unique_ptr processMeasureFilter_; + std::unique_ptr processFilterFilter_; + std::unique_ptr symbolsFilter_; + std::unique_ptr statFilter_; + std::unique_ptr clockRateFilter_; + std::unique_ptr clockEnableFilter_; + std::unique_ptr clockDisableFilter_; + std::unique_ptr clkRateFilter_; + std::unique_ptr clkEnableFilter_; + std::unique_ptr clkDisableFilter_; + std::unique_ptr binderFilter_; + std::unique_ptr argsFilter_; + std::unique_ptr irqFilter_; + std::unique_ptr sysEventMemMeasureFilter_; + std::unique_ptr sysEventVMemMeasureFilter_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TRACE_STREAMERTOKEN_H diff --git a/host/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp b/host/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c3978598609b8678ff4ec764db07ef6e4eff9612 --- /dev/null +++ b/host/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "trace_streamer_selector.h" +#include +#include +#include +#include +#include "args_filter.h" +#include "binder_filter.h" +#include "clock_filter.h" +#include "cpu_filter.h" +#include "file.h" +#include "filter_filter.h" +#include "irq_filter.h" +#include "measure_filter.h" +#include "parser/bytrace_parser/bytrace_parser.h" +#include "parser/htrace_parser/htrace_parser.h" +#include "process_filter.h" +#include "slice_filter.h" +#include "stat_filter.h" +#include "symbols_filter.h" +#include "system_event_measure_filter.h" + +using namespace SysTuning::base; +namespace SysTuning { +namespace TraceStreamer { +namespace { +TraceFileType GuessFileType(const uint8_t* data, size_t size) +{ + if (size == 0) { + return TRACE_FILETYPE_UN_KNOW; + } + std::string start(reinterpret_cast(data), std::min(size, 20)); + if (start.find("# tracer") != std::string::npos) { + return TRACE_FILETYPE_BY_TRACE; + } + if (start.find("# TRACE") != std::string::npos) { + return TRACE_FILETYPE_BY_TRACE; + } + if ((start.compare(0, std::string("").length(), "") == 0) || + (start.compare(0, std::string("").length(), "") == 0)) { + return TRACE_FILETYPE_BY_TRACE; + } + if (start.compare(0, std::string("\x0a").length(), "\x0a") == 0) { + return TRACE_FILETYPE_UN_KNOW; + } + if (start.compare(0, std::string("OHOSPROF").length(), "OHOSPROF") == 0) { + return TRACE_FILETYPE_H_TRACE; + } + const std::regex bytraceMatcher = std::regex(R"(-(\d+)\s+\(?\s*(\d+|-+)?\)?\s?\[(\d+)\]\s*)" + R"([a-zA-Z0-9.]{0,5}\s+(\d+\.\d+):\s+(\S+):)"); + std::smatch matcheLine; + std::string bytraceMode(reinterpret_cast(data), size); + if (std::regex_search(bytraceMode, matcheLine, bytraceMatcher)) { + return TRACE_FILETYPE_BY_TRACE; + } + return TRACE_FILETYPE_UN_KNOW; +} +} // namespace + +TraceStreamerSelector::TraceStreamerSelector() + : fileType_(TRACE_FILETYPE_UN_KNOW), bytraceParser_(nullptr), htraceParser_(nullptr) +{ + InitFilter(); +} +TraceStreamerSelector::~TraceStreamerSelector() {} + +void TraceStreamerSelector::InitFilter() +{ + streamFilters_ = std::make_unique(); + traceDataCache_ = std::make_unique(); + streamFilters_->cpuFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + streamFilters_->sliceFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + + streamFilters_->processFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + streamFilters_->clockFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + streamFilters_->filterFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + + streamFilters_->threadMeasureFilter_ = + std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_THREADMEASURE_FILTER); + streamFilters_->threadFilter_ = + std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_THREAD_FILTER); + streamFilters_->cpuMeasureFilter_ = + std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_CPU_MEASURE_FILTER); + streamFilters_->processMeasureFilter_ = + std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_PROCESS_MEASURE_FILTER); + streamFilters_->processFilterFilter_ = + std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_PROCESS_FILTER_FILTER); + streamFilters_->symbolsFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + streamFilters_->statFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + streamFilters_->binderFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + streamFilters_->argsFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + streamFilters_->irqFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + streamFilters_->clockRateFilter_ = + std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_CLOCK_RATE_FILTER); + streamFilters_->clockEnableFilter_ = + std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_CLOCK_ENABLE_FILTER); + streamFilters_->clockDisableFilter_ = + std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_CLOCK_DISABLE_FILTER); + streamFilters_->clkRateFilter_ = + std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_CLK_RATE_FILTER); + streamFilters_->clkEnableFilter_ = + std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_CLK_ENABLE_FILTER); + streamFilters_->clkDisableFilter_ = + std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_CLK_DISABLE_FILTER); + streamFilters_->sysEventMemMeasureFilter_ = + std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_SYS_MEMORY_FILTER); + streamFilters_->sysEventVMemMeasureFilter_ = std::make_unique( + traceDataCache_.get(), streamFilters_.get(), E_SYS_VIRTUAL_MEMORY_FILTER); +} + +void TraceStreamerSelector::WaitForParserEnd() +{ + if (fileType_ == TRACE_FILETYPE_H_TRACE) { + htraceParser_->WaitForParserEnd(); + } + if (fileType_ == TRACE_FILETYPE_BY_TRACE) { + bytraceParser_->WaitForParserEnd(); + } +} + +MetaData* TraceStreamerSelector::GetMetaData() +{ + return traceDataCache_->GetMetaData(); +} +bool TraceStreamerSelector::ParseTraceDataSegment(std::unique_ptr data, size_t size) +{ + if (size == 0) { + return true; + } + if (fileType_ == TRACE_FILETYPE_UN_KNOW) { + fileType_ = GuessFileType(data.get(), size); + if (fileType_ == TRACE_FILETYPE_H_TRACE) { + htraceParser_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + } else if (fileType_ == TRACE_FILETYPE_BY_TRACE) { + bytraceParser_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + } + if (fileType_ == TRACE_FILETYPE_UN_KNOW) { + SetAnalysisResult(TRACE_PARSER_FILE_TYPE_ERROR); + TS_LOGI( + "File type is not supported!,\nthe head content is:%s\n ---waring!!!---\n" + "File type is not supported!,\n", + data.get()); + return false; + } + } + if (fileType_ == TRACE_FILETYPE_H_TRACE) { + htraceParser_->ParseTraceDataSegment(std::move(data), size); + } + if (fileType_ == TRACE_FILETYPE_BY_TRACE) { + bytraceParser_->ParseTraceDataSegment(std::move(data), size); + } + SetAnalysisResult(TRACE_PARSER_NORMAL); + return true; +} +void TraceStreamerSelector::EnableMetaTable(bool enabled) +{ + traceDataCache_->EnableMetaTable(enabled); +} + +void TraceStreamerSelector::SetCleanMode(bool cleanMode) +{ + g_cleanMode = true; +} +int TraceStreamerSelector::ExportDatabase(const std::string& outputName) const +{ + traceDataCache_->UpdateTraceRange(); + return traceDataCache_->ExportDatabase(outputName); +} +void TraceStreamerSelector::Clear() +{ + traceDataCache_->Prepare(); + traceDataCache_->Clear(); +} +int TraceStreamerSelector::SearchData() +{ + return traceDataCache_->SearchData(); +} +int TraceStreamerSelector::OperateDatabase(const std::string& sql) +{ + return traceDataCache_->OperateDatabase(sql); +} +int TraceStreamerSelector::SearchDatabase(const std::string& sql, + TraceDataDB::ResultCallBack resultCallBack) +{ + return traceDataCache_->SearchDatabase(sql, resultCallBack); +} +int TraceStreamerSelector::SearchDatabase(const std::string& sql, uint8_t* out, int outLen) +{ + return traceDataCache_->SearchDatabase(sql, out, outLen); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/trace_streamer/trace_streamer_selector.h b/host/trace_streamer/src/trace_streamer/trace_streamer_selector.h new file mode 100644 index 0000000000000000000000000000000000000000..69eb9732bff175030ede70a1c7f9054c32adb2cd --- /dev/null +++ b/host/trace_streamer/src/trace_streamer/trace_streamer_selector.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TRACE_STREAMER_SELECTOR_H +#define TRACE_STREAMER_SELECTOR_H +#include +#include +#include "trace_data/trace_data_cache.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +class BytraceParser; +class HtraceParser; +enum TraceFileType { TRACE_FILETYPE_BY_TRACE, TRACE_FILETYPE_H_TRACE, TRACE_FILETYPE_UN_KNOW }; +class TraceStreamerSelector { +public: + TraceStreamerSelector(); + ~TraceStreamerSelector(); + bool ParseTraceDataSegment(std::unique_ptr data, size_t size); + void EnableMetaTable(bool enabled); + void SetCleanMode(bool cleanMode); + int ExportDatabase(const std::string& outputName) const; + int SearchData(); + int OperateDatabase(const std::string& sql); + int SearchDatabase(const std::string& sql, TraceDataDB::ResultCallBack resultCallBack); + int SearchDatabase(const std::string& sql, uint8_t* out, int outLen); + void WaitForParserEnd(); + void Clear(); + MetaData* GetMetaData(); + void SetDataType(TraceFileType type) + { + fileType_ = type; + } + TraceFileType DataType() + { + return fileType_; + } + +private: + void InitFilter(); + TraceFileType fileType_; + std::unique_ptr streamFilters_ = {}; + std::unique_ptr traceDataCache_ = {}; + + std::unique_ptr bytraceParser_; + std::unique_ptr htraceParser_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TRACE_STREAMER_SELECTOR_H diff --git a/host/trace_streamer/src/ts.gni b/host/trace_streamer/src/ts.gni new file mode 100644 index 0000000000000000000000000000000000000000..3dd4e2a5a520f3bd4b19ede491b673e48dc1a660 --- /dev/null +++ b/host/trace_streamer/src/ts.gni @@ -0,0 +1,56 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +OHOS_PROTO_DIR = "" + +if (target_os == "linux" || target_os == "windows" || target_os == "wasm" || + target_os == "test") { + # OHOS_FTRACE_PROTO_DIR="//third_party/protogen" + OHOS_FTRACE_PROTO_DIR = "//src/multi_platform" + + # OHOS_MEMORY_PROTO_DIR="//third_party/protogen" + OHOS_MEMORY_PROTO_DIR = "//src/multi_platform" + + # OHOS_HILOG_PROTO_DIR="//third_party/protogen" + OHOS_HILOG_PROTO_DIR = "//src/multi_platform" + + # OHOS_NATIVE_HOOK_PROTO_DIR="//third_party/protogen" + OHOS_NATIVE_HOOK_PROTO_DIR = "//src/multi_platform" + + # OHOS_HIDUMP_PROTO_DIR="//third_party/protogen" + OHOS_HIDUMP_PROTO_DIR = "//src/multi_platform" + + # OHOS_SERVICE_PROTO_DIR = "//third_party/protogen" + OHOS_SERVICE_PROTO_DIR = "//src/multi_platform" + OHOS_PROTO_GEN = "//third_party/protogen" + if (target_os == "test") { + enable_ts_utest = true + } else { + enable_ts_utest = false + } +} else { + enable_ts_utest = true + use_wasm = false + OHOS_FTRACE_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/ftrace_data" + OHOS_MEMORY_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/memory_data" + OHOS_HILOG_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/hilog_data" + OHOS_NATIVE_HOOK_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/native_hook" + OHOS_HIDUMP_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/hidump_data" + OHOS_SERVICE_PROTO_DIR = "//developtools/profiler/protos/services" + OHOS_PROTO_GEN = + "//developtools/profiler/trace_analyzer/third_party/protogen/" +} diff --git a/host/trace_streamer/test/BUILD.gn b/host/trace_streamer/test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..1d20471e7ef42f9630aabc2fd2f23bd5b4b9214b --- /dev/null +++ b/host/trace_streamer/test/BUILD.gn @@ -0,0 +1,130 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//build/test.gni") + +#import("../../device/base/config.gni") +import("test_ts.gni") + +#module_output_path = "${OHOS_PROFILER_TEST_MODULE_OUTPUT_PATH}/trace_analyzer" +config("module_private_config") { + visibility = [ ":*" ] + cflags_cc = [ "-std=c++17" ] + + # if (current_toolchain != host_toolchain) { + # defines = [ "HAVE_HILOG" ] + # } +} + +ohos_unittest("hiprofiler_ts_ut") { + # module_out_path = module_output_path + sources = [ + "unittest/binder_filter_test.cpp", + "unittest/bytrace_parser_test.cpp", + "unittest/clock_filter_test.cpp", + "unittest/cpu_filter_test.cpp", + "unittest/event_parser_test.cpp", + "unittest/filter_filter_test.cpp", + "unittest/hilog_parser_test.cpp", + "unittest/htrace_binder_event_test.cpp", + "unittest/htrace_event_parser_test.cpp", + "unittest/htrace_irq_event_test.cpp", + "unittest/htrace_mem_parser_test.cpp", + "unittest/htrace_sys_mem_parser_test.cpp", + "unittest/htrace_sys_vmem_parser_test.cpp", + "unittest/irq_filter_test.cpp", + "unittest/measure_filter_test.cpp", + "unittest/parser_test.cpp", + "unittest/process_filter_test.cpp", + "unittest/slice_filter_test.cpp", + ] + deps = [ + # "${OHOS_FTRACE_PROTO_DIR}:ftrace_data_cpp", + # "${OHOS_MEMORY_PROTO_DIR}:memory_data_cpp", + # "${OHOS_HILOG_PROTO_DIR}:hilog_data_cpp", + # "${OHOS_NATIVE_HOOK_PROTO_DIR}:native_hook_cpp", + # "${OHOS_HIDUMP_PROTO_DIR}:hidump_data_cpp", + # "${OHOS_SERVICE_PROTO_DIR}:proto_services_cpp", + "../src:trace_streamer_source", + "//prebuilts/protos:ts_proto_data_cpp", + "//third_party/googletest:gtest_main", + "//third_party/protobuf:protobuf", + "//third_party/protobuf:protobuf_lite", + "//third_party/sqlite:sqlite", + + # "//utils/native/base:utilsecurec", + ] + include_dirs = [ + "../src", + "../src/trace_data", + "../src/table", + "../src/filter", + "../src/base", + "../src/include", + "../src/trace_streamer", + "../src/parser/bytrace_parser", + "../src/parser", + "../src/cfg", + "../src/parser/htrace_parser", + "../src/parser/htrace_parser/htrace_event_parser", + "../src/parser/htrace_parser/htrace_cpu_parser", + "..", + "//third_party/googletest/googletest/include/gtest", + "//utils/native/base/include", + "//third_party/protobuf/src", + "${OHOS_PROTO_GEN}", + "${OHOS_FTRACE_PROTO_DIR}", + "${OHOS_MEMORY_PROTO_DIR}", + "${OHOS_HILOG_PROTO_DIR}", + "${OHOS_NATIVE_HOOK_PROTO_DIR}", + "${OHOS_HIDUMP_PROTO_DIR}", + "${OHOS_SERVICE_PROTO_DIR}", + ] + cflags = [ + "-Wno-inconsistent-missing-override", + "-Dprivate=public", #allow test code access private members + "-fprofile-arcs", + "-ftest-coverage", + "-Wno-unused-command-line-argument", + "-Wno-format", + "-Wno-unused-const-variable", + "-Wno-unused-variable", + "-Wno-used-but-marked-unused", + ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + + # external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + # public_configs = [ "${OHOS_PROFILER_DIR}/device/base:hiprofiler_test_config" ] + configs = [ ":module_private_config" ] + + # subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" +} + +# this is the dest for ohos.build +group("unittest") { + testonly = true + deps = [ ":hiprofiler_ts_ut" ] +} +#group("fuzztest") { +# testonly = true +# deps = [ +# "test_fuzzer/bytrace_fuzzer:fuzztest", +# "test_fuzzer/htrace_fuzzer:fuzztest", +# "test_fuzzer/selector_fuzzer:fuzztest", +# ] +#} diff --git a/host/trace_streamer/test/test_ts.gni b/host/trace_streamer/test/test_ts.gni new file mode 100644 index 0000000000000000000000000000000000000000..6b7c44b89c21b411b5fa6b6d166006766bafc5c4 --- /dev/null +++ b/host/trace_streamer/test/test_ts.gni @@ -0,0 +1,48 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +OHOS_PROTO_DIR = "" + +if (target_os == "linux" || target_os == "windows" || target_os == "test") { + OHOS_FTRACE_PROTO_DIR = "//src/multi_platform" + OHOS_MEMORY_PROTO_DIR = "//src/multi_platform" + OHOS_SERVICE_PROTO_DIR = "//src/multi_platform" + OHOS_PROTO_GEN = "//third_party/protogen" + if (target_os == "test") { + OHOS_MEMORY_PROTO_DIR = "//third_party/protogen/types/plugins/memory_data" + enable_ts_utest = true + OHOS_HILOG_PROTO_DIR = "//src/multi_platform" + + # OHOS_NATIVE_HOOK_PROTO_DIR="//third_party/protogen" + OHOS_NATIVE_HOOK_PROTO_DIR = "//src/multi_platform" + + # OHOS_HIDUMP_PROTO_DIR="//third_party/protogen" + OHOS_HIDUMP_PROTO_DIR = "//src/multi_platform" + } +} else { + use_wasm = false + OHOS_FTRACE_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/ftrace_data" + OHOS_MEMORY_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/memory_data" + OHOS_HILOG_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/hilog_data" + OHOS_NATIVE_HOOK_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/native_hook" + OHOS_HIDUMP_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/hidump_data" + OHOS_SERVICE_PROTO_DIR = "//developtools/profiler/protos/services" + OHOS_PROTO_GEN = + "//developtools/profiler/trace_analyzer/third_party/protogen/" + enable_ts_utest = true +} diff --git a/host/trace_streamer/test/unittest/README.md b/host/trace_streamer/test/unittest/README.md new file mode 100644 index 0000000000000000000000000000000000000000..4bb1a397f53544e67aecb79a14bb54aadf99df8b --- /dev/null +++ b/host/trace_streamer/test/unittest/README.md @@ -0,0 +1,53 @@ +# 准备测试的硬件环境 + 1. 测试依赖hi3516DV300设备。 + 2. 烧录OHOS_STD代码。 + 3. 通过直连方式,使用USB线将设备连接到存储测试代码的主机。 + +# 准备测试的软件环境 + 1. 设置UT环境变量 + 在代码根目录执行:export BUILD_UT=true + 2. 连接设备 + 在代码根目录执行: root + remount + 3. 准备UT依赖的动态库 + 通过push 把测试依赖的libsqlite.z.so等动态库推到hi3516DV300设备的system/lib文件夹下。 + 4. 准备UT依赖的资源文件 + 将OHOS_STD/test/resource目录push到hi3516DV300设备的/data目录 + 在代码根目录执行: push ./test/resource/ /data/ + 5. 环境清理 + (a) 执行之前先清理OHOS_STD/out/xxx-arm-release/obj/developtools 临时文件。 + rm -rf ~/OHOS_STD/out/xxx-arm-release/obj/developtools + (b) 清理hi3516DV300设备上生成的中间文件/home/XXX/OHOS_STD/out。 + rm -rf /home/ohos/OHOS_STD/out* + (c) 清理UT环境残留的覆盖率报告。 + rm -rf ~/OHOS_STD/developtools/profiler/build/html + +# 测试步骤 + 1. 启动UT执行环境, 启动后根据提示信息输入hi3516DV300对应的设备编号。 + 在代码根目录执行:./test/developertest/start.sh + 2. 编译并执行hiprofiler_ts_ut。 + 在start.sh启动的交互式窗口执行:run -t ut -ss developtools -ts hiprofiler_ts_ut + +# 生成测试报告 + 1. pull设备上生成的gcda + 进入设备环境后: 执行cd /home/XXX/OHOS_STD + tar -cvf out.tar out + exit + 退出shell后:pull /home/XXX/OHOS_STD/out.tar ~/OHOS_STD/ + tar -xvf out.tar + pull /home/ohos/OHOS_STD/out/* /home/ohos/OHOS_STD/out/ + cd /home/ohos/OHOS_STD/developtools/profiler/build + 2. 生成UT覆盖率报告 + 在代码根目录执行:./developtools/profiler/build/lcov.sh + pull /data/test/hiprofiler_ts_ut.xml ~/OHOS_STD/developtools/profiler/build/html/ + 报告位置:~/OHOS_STD/developtools/profiler/build/html/index.html + +# 可能遇到的问题 + 1. gcno文件不存在问题 + gcno文件是在编译阶段生成,编译时如果out目录存在.o临时文件,则不会编译源码,需要删除out/ obj/developtools/目录的编译中间文件后重新编译 + 2. 运行时报缺少依赖库libsqlite.z.so + 需要把libsqlite.z.so push到设备的system/lib目录,在developtools/profiler/device/ohos_test.xml文件增加push命令 + 3. UT所有步骤执行完之后,html中没有生成覆盖率信息 + 权限问题,从设备中pull出来gcov文件后,需要关注文件权限 + 4. UT输出覆盖率世间点不是当前最新时间 + 清理掉原来的html文件,重新执行lcov.sh,生成新的html覆盖率报告 \ No newline at end of file diff --git a/host/trace_streamer/test/unittest/binder_filter_test.cpp b/host/trace_streamer/test/unittest/binder_filter_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e028b407e5dd1e275c9439a1b0da0a7a908eabc --- /dev/null +++ b/host/trace_streamer/test/unittest/binder_filter_test.cpp @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "args_filter.h" +#include "binder_filter.h" +#include "process_filter.h" +#include "slice_filter.h" +#include "stat_filter.h" +#include "trace_plugin_result.pb.h" +#include "ts_common.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class BinderFilterTest : public ::testing::Test { +public: + void SetUp() + { + streamFilters_.processFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + streamFilters_.argsFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + streamFilters_.binderFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + streamFilters_.statFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + streamFilters_.sliceFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + } + + void TearDown() {} + +public: + TraceStreamerFilters streamFilters_; + TraceDataCache traceDataCache_; +}; + +/** + * @tc.name: BinderSenderfilterNeedReply + * @tc.desc: Binder event needs reply to + * @tc.type: FUNC + */ +HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReply, TestSize.Level1) +{ + TS_LOGI("test9-1"); + uint64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = false; + int32_t flags = 0x02; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_); 0x01 + int32_t code = 0; // not important + streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, destTgid1, + destTid1, isReply, flags, code); // start binder + streamFilters_.binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 7); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().TimeStamData()[0] == ts1); +} + +/** + * @tc.name: BinderSenderfilterNeedReplyAndReceive + * @tc.desc: Complete event, Binder event needs reply to + * @tc.type: FUNC + */ +HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReplyAndReceive, TestSize.Level1) +{ + TS_LOGI("test9-2"); + int64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = false; + int32_t flags = 0x02; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_) + int32_t code = 0; // not importent + streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, + destTgid1, destTid1, isReply, flags, code); // start binder + streamFilters_.binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 7); + ts1 = 200; + uint32_t pid1 = 1; + streamFilters_.binderFilter_->ReceiveTraction(ts1, pid1, transactionId1); // receive binder + streamFilters_.binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 2); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[1] == 1); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 11); + auto len = traceDataCache_.GetConstArgSetData().Size(); + for (uint64_t i = 0; i < len; i++) { + if (traceDataCache_.GetConstArgSetData().names_[i] == streamFilters_.binderFilter_->isReplayId_) { + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().values_[i] == static_cast(isReply)); + } else if (traceDataCache_.GetConstArgSetData().names_[i] == streamFilters_.binderFilter_->destNodeId_) { + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().values_[i] == static_cast(destNode1)); + } else if (traceDataCache_.GetConstArgSetData().names_[i] == streamFilters_.binderFilter_->destThreadId_) { + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().values_[i] == static_cast(pid1)); + } else if (traceDataCache_.GetConstArgSetData().names_[i] == streamFilters_.binderFilter_->callingTid_) { + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().values_[i] == static_cast(tid1)); + } else if (traceDataCache_.GetConstArgSetData().names_[i] == streamFilters_.binderFilter_->transId_) { + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().values_[i] == static_cast(transactionId1)); + } + } +} + +/** + * @tc.name: BinderSenderfilterNeedReplyAndReceiveWithAlloc + * @tc.desc: The binder test that needs to be replied and there is an allock event + * @tc.type: FUNC + */ +HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReplyAndReceiveWithAlloc, TestSize.Level1) +{ + TS_LOGI("test9-3"); + int64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = false; + int32_t flags = 0x02; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_) + int32_t code = 0; // not importent + streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, destTgid1, + destTid1, isReply, flags, + code); // start binder + streamFilters_.binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 7); + + ts1 = 150; + uint64_t dataSize = 100; + uint64_t offsetSize = 200; + streamFilters_.binderFilter_->TransactionAllocBuf(ts1, tid1, dataSize, offsetSize); + streamFilters_.binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 9); + + ts1 = 200; + uint32_t pid1 = 1; + streamFilters_.binderFilter_->ReceiveTraction(ts1, pid1, transactionId1); // receive binder + streamFilters_.binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 2); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[1] == 1); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 13); +} + +/** + * @tc.name: BinderSenderfilterNeedReplyAndReceiveNotmatch + * @tc.desc: The binder test that needs to be replied but not match + * @tc.type: FUNC + */ +HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReplyAndReceiveNotmatch, TestSize.Level1) +{ + TS_LOGI("test9-4"); + int64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = false; + int32_t flags = 0x02; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_) + int32_t code = 0; // not importent + streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, + destTgid1, destTid1, isReply, flags, + code); // start binder + streamFilters_.binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + ts1 = 200; + uint32_t pid1 = 1; + uint64_t transactionId2 = 2; + streamFilters_.binderFilter_->ReceiveTraction(ts1, pid1, transactionId2); // receive binder + streamFilters_.binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); +} + +/** + * @tc.name: BinderSenderfilterNoNeedReply + * @tc.desc: The binder test that donot needs to be replied + * @tc.type: FUNC + */ +HWTEST_F(BinderFilterTest, BinderSenderfilterNoNeedReply, TestSize.Level1) +{ + TS_LOGI("test9-5"); + int64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = false; + int32_t flags = 0x01; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_) + int32_t code = 0; // not importent + streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, destTgid1, + destTid1, isReply, flags, code); // start binder + streamFilters_.binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); +} + +/** + * @tc.name: BinderSenderNoneedReplyAndReceivefilter + * @tc.desc: Complete event, The binder test that donot needs to be replied + * @tc.type: FUNC + */ +HWTEST_F(BinderFilterTest, BinderSenderNoneedReplyAndReceivefilter, TestSize.Level1) +{ + TS_LOGI("test9-6"); + int64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = false; + int32_t flags = 0x01; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_) + int32_t code = 0; // not importent + streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, destTgid1, + destTid1, isReply, flags, + code); // start binder + streamFilters_.binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + + ts1 = 200; + uint32_t pid1 = 1; + streamFilters_.binderFilter_->ReceiveTraction(ts1, pid1, transactionId1); // receive binder + streamFilters_.binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 2); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[1] == 1); +} + +/** + * @tc.name: BinderSenderNoneedReplyAndReceivefilterNotmatch + * @tc.desc: Not Match, The binder test that donot needs to be replied + * @tc.type: FUNC + */ +HWTEST_F(BinderFilterTest, BinderSenderNoneedReplyAndReceivefilterNotmatch, TestSize.Level1) +{ + TS_LOGI("test9-7"); + int64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = false; + int32_t flags = 0x01; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_) + int32_t code = 0; // not importent + streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, destTgid1, + destTid1, isReply, flags, + code); // start binder + streamFilters_.binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + + ts1 = 200; + uint32_t pid1 = 1; + uint64_t transactionId2 = 2; + streamFilters_.binderFilter_->ReceiveTraction(ts1, pid1, transactionId2); // receive binder + streamFilters_.binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); +} + +/** + * @tc.name: BinderSenderfilterWrongReply + * @tc.desc: The binder test with wrong replie + * @tc.type: FUNC + */ +HWTEST_F(BinderFilterTest, BinderSenderfilterWrongReply, TestSize.Level1) +{ + TS_LOGI("test9-8"); + int64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = true; + int32_t flags = 0x01; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_) + int32_t code = 0; // not important + streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, + destTgid1, destTid1, isReply, flags, + code); // start binder + streamFilters_.binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 0); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 0); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/bytrace_parser_test.cpp b/host/trace_streamer/test/unittest/bytrace_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b613d1819b72fac5574d83d647d5e8a772f0601a --- /dev/null +++ b/host/trace_streamer/test/unittest/bytrace_parser_test.cpp @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "parser/bytrace_parser/bytrace_parser.h" +#include "parser/common_types.h" +#include "securec.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; + +namespace SysTuning { +namespace TraceStreamer { +class BytraceParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; + const std::string dbPath_ = "/data/resource/out.db"; +}; + +/** + * @tc.name: ParseNoData + * @tc.desc: Test ParseTraceDataSegment interface Parse empty memory + * @tc.type: FUNC + */ +HWTEST_F(BytraceParserTest, ParseNoData, TestSize.Level1) +{ + TS_LOGI("test1-1"); + auto buf = std::make_unique(1); + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + printf("xxx\n"); + bytraceParser.ParseTraceDataSegment(std::move(buf), 1); + printf("xxx2\n"); + bytraceParser.WaitForParserEnd(); + printf("xxx3\n"); + EXPECT_TRUE(bytraceParser.TraceCommentLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceValidLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceInvalidLines() == 0); +} + +/** + * @tc.name: ParseNoDataWhithLineFlag + * @tc.desc: Test ParseTraceDataSegment interface Parse "\n" + * @tc.type: FUNC + */ +HWTEST_F(BytraceParserTest, ParseNoDataWhithLineFlag, TestSize.Level1) +{ + TS_LOGI("test1-2"); + constexpr uint32_t bufSize = 1024; + auto buf = std::make_unique(bufSize); + if (memcpy_s(buf.get(), bufSize, " \n", strlen(" \n"))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), bufSize); + bytraceParser.WaitForParserEnd(); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + EXPECT_TRUE(bytraceParser.TraceCommentLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceValidLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceInvalidLines() == 1); +} + +/** + * @tc.name: ParseInvalidData + * @tc.desc: Test ParseTraceDataSegment interface Parse invalid string + * @tc.type: FUNC + */ +HWTEST_F(BytraceParserTest, ParseInvalidData, TestSize.Level1) +{ + TS_LOGI("test1-3"); + constexpr uint32_t bufSize = 1024; + auto buf = std::make_unique(bufSize); + if (memcpy_s(buf.get(), bufSize, "0123456789\n", strlen("0123456789\n"))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), bufSize); + bytraceParser.WaitForParserEnd(); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + EXPECT_TRUE(bytraceParser.TraceCommentLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceValidLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceInvalidLines() == 1); +} + +/** + * @tc.name: ParseComment + * @tc.desc: Test ParseTraceDataSegment interface Parse Multiline data + * @tc.type: FUNC + */ +HWTEST_F(BytraceParserTest, ParseComment, TestSize.Level1) +{ + TS_LOGI("test1-4"); + constexpr uint32_t bufSize = 1024; + auto buf = std::make_unique(bufSize); + if (memcpy_s(buf.get(), bufSize, "TRACE: \n# tracer: nop \n# \n", strlen("TRACE: \n# tracer: nop \n# \n"))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), bufSize); + bytraceParser.WaitForParserEnd(); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + EXPECT_TRUE(bytraceParser.TraceCommentLines() == 2); + EXPECT_TRUE(bytraceParser.ParsedTraceValidLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceInvalidLines() == 1); +} + +/** + * @tc.name: ParseInvalidLines + * @tc.desc: Test ParseTraceDataSegment interface Parse Multiline Invalid data + * @tc.type: FUNC + */ +HWTEST_F(BytraceParserTest, ParseInvalidLines, TestSize.Level1) +{ + TS_LOGI("test1-5"); + constexpr uint32_t bufSize = 1024; + auto buf = std::make_unique(bufSize); + if (memcpy_s(buf.get(), bufSize, "\nafafda\n", strlen("\nafafda\n"))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), bufSize); + bytraceParser.WaitForParserEnd(); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + EXPECT_TRUE(bytraceParser.TraceCommentLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceValidLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceInvalidLines() == 2); +} + +/** + * @tc.name: ParseNormal + * @tc.desc: Test ParseTraceDataItem interface Parse normal data + * @tc.type: FUNC + */ +HWTEST_F(BytraceParserTest, ParseNormal, TestSize.Level1) +{ + TS_LOGI("test1-6"); + std::string str( + "ACCS0-2716 ( 2519) [000] ...1 168758.662861: binder_transaction: \ + transaction=25137708 dest_node=4336 dest_proc=924 dest_thread=0 reply=0 flags=0x10 code=0x3\n"); + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataItem(str); + bytraceParser.WaitForParserEnd(); + + EXPECT_TRUE(bytraceParser.TraceCommentLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceValidLines() == 1); + EXPECT_TRUE(bytraceParser.ParsedTraceInvalidLines() == 0); +} + +/** + * @tc.name: LineParser_abnormal_pid_err + * @tc.desc: Test ParseTraceDataItem interface Parse data with error pid + * @tc.type: FUNC + */ +HWTEST_F(BytraceParserTest, LineParser_abnormal_pid_err, TestSize.Level1) +{ + TS_LOGI("test1-7"); + std::string str( + "ACCS0-27X6 ( 2519) [000] ...1 168758.662861: binder_transaction: \ + transaction=25137708 dest_node=4336 dest_proc=924 dest_thread=0 reply=0 flags=0x10 code=0x3\n"); + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataItem(str); + bytraceParser.WaitForParserEnd(); + + EXPECT_TRUE(bytraceParser.TraceCommentLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceValidLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceInvalidLines() == 1); +} + +/** + * @tc.name: LineParserWithInvalidCpu + * @tc.desc: Test ParseTraceDataItem interface Parse data with invalid cpu + * @tc.type: FUNC + */ +HWTEST_F(BytraceParserTest, LineParserWithInvalidCpu, TestSize.Level1) +{ + TS_LOGI("test1-8"); + std::string str( + "ACCS0-2716 ( 2519) [00X] ...1 168758.662861: binder_transaction: \ + transaction=25137708 dest_node=4336 dest_proc=924 dest_thread=0 reply=0 flags=0x10 code=0x3\n"); + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataItem(str); + bytraceParser.WaitForParserEnd(); + + EXPECT_TRUE(bytraceParser.TraceCommentLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceValidLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceInvalidLines() == 1); +} + +/** + * @tc.name: LineParserWithInvalidTs + * @tc.desc: Test ParseTraceDataItem interface Parse data with invalid ts + * @tc.type: FUNC + */ +HWTEST_F(BytraceParserTest, LineParserWithInvalidTs, TestSize.Level1) +{ + TS_LOGI("test1-9"); + std::string str( + "ACCS0-2716 ( 2519) [000] ...1 168758.662X61: binder_transaction: \ + transaction=25137708 dest_node=4336 dest_proc=924 dest_thread=0 reply=0 flags=0x10 code=0x3\n"); + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataItem(str); + bytraceParser.WaitForParserEnd(); + + EXPECT_TRUE(bytraceParser.TraceCommentLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceValidLines() == 0); + EXPECT_TRUE(bytraceParser.ParsedTraceInvalidLines() == 1); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/clock_filter_test.cpp b/host/trace_streamer/test/unittest/clock_filter_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..833a3301a2ef1f6b3709d769953510e7fe8cdd35 --- /dev/null +++ b/host/trace_streamer/test/unittest/clock_filter_test.cpp @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "clock_filter.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class ClockFilterTest : public ::testing::Test { +public: + void SetUp() + { + streamFilters_.clockFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + } + + void TearDown() {} + +public: + SysTuning::TraceStreamer::TraceStreamerFilters streamFilters_; + SysTuning::TraceStreamer::TraceDataCache traceDataCache_; +}; + +/** + * @tc.name: ConvertBoottimeToMonitonicTime + * @tc.desc: convert Boottime to MonitonicTime + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertBoottimeToMonitonicTime, TestSize.Level1) +{ + TS_LOGI("test2-1"); + uint64_t tsBoottime = 100; + uint64_t tsMonotonicTime = 200; + std::vector snapShot0; + snapShot0.push_back({TS_CLOCK_BOOTTIME, tsBoottime}); + snapShot0.push_back({TS_MONOTONIC, tsMonotonicTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + + uint64_t time1 = 150; + uint64_t expectTime1 = 250; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_BOOTTIME, time1, TS_MONOTONIC), expectTime1); +} + +/** + * @tc.name: ConvertBoottimeToMonitonicTime + * @tc.desc: convert twice Boottime to MonitonicTime + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertBoottimeToMonitonicTimeTwice, TestSize.Level1) +{ + TS_LOGI("test2-2"); + uint64_t tsBoottime = 100; + uint64_t tsMonotonicTime = 200; + std::vector snapShot0; + snapShot0.push_back({TS_CLOCK_BOOTTIME, tsBoottime}); + snapShot0.push_back({TS_MONOTONIC, tsMonotonicTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + + uint64_t time1 = 150; + uint64_t expectTime1 = 250; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_BOOTTIME, time1, TS_MONOTONIC), expectTime1); + uint64_t time2 = 200; + uint64_t expectTime2 = 300; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_BOOTTIME, time2, TS_MONOTONIC), expectTime2); +} + +/** + * @tc.name: ConvertBoottimeToMonitonicTime + * @tc.desc: convert Boottime to MonitonicTime twice + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertTimestampInvalid, TestSize.Level1) +{ + TS_LOGI("test2-4"); + uint64_t tsBoottime = 100; + uint64_t tsMonotonicTime = 200; + std::vector snapShot0; + snapShot0.push_back({TS_CLOCK_BOOTTIME, tsBoottime}); + snapShot0.push_back({TS_MONOTONIC, tsMonotonicTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + + std::vector snapShot1; + uint64_t tsBoottime2 = 200; + uint64_t tsMonotonicTime2 = 350; + snapShot1.push_back({TS_CLOCK_BOOTTIME, tsBoottime2}); + snapShot1.push_back({TS_MONOTONIC, tsMonotonicTime2}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot1); + uint64_t time2 = 200; + uint64_t expectTime2 = 200; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_BOOTTIME, time2, TS_CLOCK_REALTIME), expectTime2); +} + +/** + * @tc.name: ConvertTimestampBoottimeToRealtime + * @tc.desc: convert Boottime to Realtime + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertTimestampBoottimeToRealtime, TestSize.Level1) +{ + TS_LOGI("test2-5"); + uint64_t tsBoottime = 100; + uint64_t tsRealTime = 300; + std::vector snapShot0; + snapShot0.push_back({TS_CLOCK_BOOTTIME, tsBoottime}); + snapShot0.push_back({TS_CLOCK_REALTIME, tsRealTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + + std::vector snapShot1; + uint64_t tsBoottime2 = 200; + uint64_t tsRealTime2 = 400; + snapShot1.push_back({TS_CLOCK_BOOTTIME, tsBoottime2}); + snapShot1.push_back({TS_CLOCK_REALTIME, tsRealTime2}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot1); + uint64_t time3 = 101; + uint64_t expectTime3 = 301; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_BOOTTIME, time3, TS_CLOCK_REALTIME), expectTime3); +} + +/** + * @tc.name: ConvertBoottimeToRealtimeTwiceWithTwoSnapShot + * @tc.desc: convert Boottime to Realtime twice with two snapShot + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertBoottimeToRealtimeTwiceWithTwoSnapShot, TestSize.Level1) +{ + TS_LOGI("test2-6"); + uint64_t tsBoottime = 100; + uint64_t tsRealTime = 300; + std::vector snapShot0; + snapShot0.push_back({TS_CLOCK_BOOTTIME, tsBoottime}); + snapShot0.push_back({TS_CLOCK_REALTIME, tsRealTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + + std::vector snapShot1; + uint64_t tsBoottime2 = 200; + uint64_t tsRealTime2 = 400; + snapShot1.push_back({TS_CLOCK_BOOTTIME, tsBoottime2}); + snapShot1.push_back({TS_CLOCK_REALTIME, tsRealTime2}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot1); + uint64_t time3 = 101; + uint64_t expectTime3 = 301; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_BOOTTIME, time3, TS_CLOCK_REALTIME), expectTime3); + time3 = 201; + expectTime3 = 401; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_BOOTTIME, time3, TS_CLOCK_REALTIME), expectTime3); +} + +/** + * @tc.name: ConvertBoottimeToRealtimeWithSingleSnapShot + * @tc.desc: convert Boottime to Realtime twice with single snapShot + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertBoottimeToRealtimeWithSingleSnapShot, TestSize.Level1) +{ + TS_LOGI("test2-7"); + uint64_t tsBoottime = 100; + uint64_t tsRealTime = 300; + std::vector snapShot0; + snapShot0.push_back({TS_CLOCK_BOOTTIME, tsBoottime}); + snapShot0.push_back({TS_CLOCK_REALTIME, tsRealTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + + uint64_t time3 = 101; + uint64_t expectTime3 = 301; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_BOOTTIME, time3, TS_CLOCK_REALTIME), expectTime3); + time3 = 201; + expectTime3 = 401; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_BOOTTIME, time3, TS_CLOCK_REALTIME), expectTime3); +} + +/** + * @tc.name: ConvertRealtimeToBoottime + * @tc.desc: convert Realtime to Boottime with single snapShot + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertRealtimeToBoottime, TestSize.Level1) +{ + TS_LOGI("test2-8"); + uint64_t tsBoottime = 100; + uint64_t tsRealTime = 300; + std::vector snapShot0; + snapShot0.push_back({TS_CLOCK_BOOTTIME, tsBoottime}); + snapShot0.push_back({TS_CLOCK_REALTIME, tsRealTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + uint64_t time7 = 301; + uint64_t expectTime7 = 101; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_REALTIME, time7, TS_CLOCK_BOOTTIME), expectTime7); +} + +/** + * @tc.name: ConvertRealtimeToBoottimeTwice + * @tc.desc: convert Realtime to Boottime twice with single snapShot + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertRealtimeToBoottimeTwice, TestSize.Level1) +{ + TS_LOGI("test2-8"); + uint64_t tsBoottime = 100; + uint64_t tsRealTime = 300; + std::vector snapShot0; + snapShot0.push_back({TS_CLOCK_BOOTTIME, tsBoottime}); + snapShot0.push_back({TS_CLOCK_REALTIME, tsRealTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + uint64_t time7 = 301; + uint64_t expectTime7 = 101; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_REALTIME, time7, TS_CLOCK_BOOTTIME), expectTime7); + time7 = 501; + expectTime7 = 301; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_REALTIME, time7, TS_CLOCK_BOOTTIME), expectTime7); +} + +/** + * @tc.name: ConvertRealtimeToBoottimeTwiceWithTwoSnapshot + * @tc.desc: convert Realtime to Boottime twice with two snapShot + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertRealtimeToBoottimeTwiceWithTwoSnapshot, TestSize.Level1) +{ + TS_LOGI("test2-9"); + uint64_t tsBoottime = 100; + uint64_t tsRealTime = 300; + std::vector snapShot0; + snapShot0.push_back({TS_CLOCK_BOOTTIME, tsBoottime}); + snapShot0.push_back({TS_CLOCK_REALTIME, tsRealTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + + std::vector snapShot1; + uint64_t tsBoottime2 = 200; + uint64_t tsRealTime2 = 400; + snapShot1.push_back({TS_CLOCK_BOOTTIME, tsBoottime2}); + snapShot1.push_back({TS_CLOCK_REALTIME, tsRealTime2}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot1); + uint64_t time7 = 401; + uint64_t expectTime7 = 201; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_REALTIME, time7, TS_CLOCK_BOOTTIME), expectTime7); + time7 = 301; + expectTime7 = 101; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_REALTIME, time7, TS_CLOCK_BOOTTIME), expectTime7); +} + +/** + * @tc.name: ConvertTimestamp + * @tc.desc: muti type timestamp convert + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertTimestamp, TestSize.Level1) +{ + TS_LOGI("test2-10"); + uint64_t tsBoottime = 100; + uint64_t tsMonotonicTime = 200; + uint64_t tsRealTime = 300; + uint64_t tsRealTimeCoarseTime = 400; + std::vector snapShot0; + snapShot0.push_back({TS_CLOCK_BOOTTIME, tsBoottime}); + snapShot0.push_back({TS_MONOTONIC, tsMonotonicTime}); + snapShot0.push_back({TS_CLOCK_REALTIME, tsRealTime}); + snapShot0.push_back({TS_CLOCK_REALTIME_COARSE, tsRealTimeCoarseTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + + std::vector snapShot1; + uint64_t tsBoottime2 = 200; + uint64_t tsMonotonicTime2 = 350; + uint64_t tsRealTime2 = 400; + uint64_t tsRealTimeCoarseTime2 = 800; + snapShot1.push_back({TS_CLOCK_BOOTTIME, tsBoottime2}); + snapShot1.push_back({TS_MONOTONIC, tsMonotonicTime2}); + snapShot1.push_back({TS_CLOCK_REALTIME, tsRealTime2}); + snapShot1.push_back({TS_CLOCK_REALTIME_COARSE, tsRealTimeCoarseTime2}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot1); + uint64_t time1 = 150; + uint64_t expectTime1 = 250; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_BOOTTIME, time1, TS_MONOTONIC), expectTime1); + uint64_t time2 = 200; + uint64_t expectTime2 = 350; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_BOOTTIME, time2, TS_MONOTONIC), expectTime2); + uint64_t time3 = 101; + uint64_t expectTime3 = 301; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_BOOTTIME, time3, TS_CLOCK_REALTIME), expectTime3); + uint64_t time4 = 102; + uint64_t expectTime4 = 402; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_BOOTTIME, time4, TS_CLOCK_REALTIME_COARSE), expectTime4); + uint64_t time5 = 102; + uint64_t expectTime5 = 202; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_MONOTONIC, time5, TS_CLOCK_REALTIME), expectTime5); + uint64_t time6 = 351; + uint64_t expectTime6 = 251; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_REALTIME, time6, TS_MONOTONIC), expectTime6); + uint64_t time7 = 401; + uint64_t expectTime7 = 351; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_CLOCK_REALTIME, time7, TS_MONOTONIC), expectTime7); + uint64_t time8 = 150; + uint64_t expectTime8 = 50; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_MONOTONIC, time8, TS_CLOCK_BOOTTIME), expectTime8); + uint64_t time9 = 250; + uint64_t expectTime9 = 150; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_MONOTONIC, time9, TS_CLOCK_BOOTTIME), expectTime9); + uint64_t time10 = 351; + uint64_t expectTime10 = 201; + EXPECT_EQ(streamFilters_.clockFilter_->Convert(TS_MONOTONIC, time10, TS_CLOCK_BOOTTIME), expectTime10); +} + +/** + * @tc.name: ConvertToPrimary + * @tc.desc: set realtime as primary time type, and convert boottime to Primary time type + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertToPrimary, TestSize.Level1) +{ + TS_LOGI("test2-11"); + std::vector snapShot0; + uint64_t tsBoottime = 100; + uint64_t tsRealTime = 300; + snapShot0.push_back({TS_CLOCK_BOOTTIME, tsBoottime}); + snapShot0.push_back({TS_CLOCK_REALTIME, tsRealTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + + std::vector snapShot1; + uint64_t tsBoottime2 = 200; + uint64_t tsRealTime2 = 400; + snapShot1.push_back({TS_CLOCK_BOOTTIME, tsBoottime2}); + snapShot1.push_back({TS_CLOCK_REALTIME, tsRealTime2}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot1); + + streamFilters_.clockFilter_->SetPrimaryClock(TS_CLOCK_REALTIME); + uint64_t time1 = 150; + uint64_t expectTime1 = 350; + EXPECT_EQ(streamFilters_.clockFilter_->ToPrimaryTraceTime(TS_CLOCK_BOOTTIME, time1), expectTime1); +} + +/** + * @tc.name: ConvertToPrimaryTwice + * @tc.desc: set realtime as primary time type, and convert boottime to Primary time type twice + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertToPrimaryTwice, TestSize.Level1) +{ + TS_LOGI("test2-11"); + std::vector snapShot0; + uint64_t tsBoottime = 100; + uint64_t tsRealTime = 300; + snapShot0.push_back({TS_CLOCK_BOOTTIME, tsBoottime}); + snapShot0.push_back({TS_CLOCK_REALTIME, tsRealTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + + std::vector snapShot1; + uint64_t tsBoottime2 = 200; + uint64_t tsRealTime2 = 400; + snapShot1.push_back({TS_CLOCK_BOOTTIME, tsBoottime2}); + snapShot1.push_back({TS_CLOCK_REALTIME, tsRealTime2}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot1); + + streamFilters_.clockFilter_->SetPrimaryClock(TS_CLOCK_BOOTTIME); + uint64_t time1 = 350; + uint64_t expectTime1 = 150; + EXPECT_EQ(streamFilters_.clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, time1), expectTime1); +} + +/** + * @tc.name: ConvertToPrimaryTimestampLessThanSnapShop + * @tc.desc: convert realtime to primary time type, and timestamp less than snapshop + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertToPrimaryTimestampLessThanSnapShop, TestSize.Level1) +{ + TS_LOGI("test2-13"); + std::vector snapShot0; + uint64_t tsBoottime = 100; + uint64_t tsRealTime = 300; + snapShot0.push_back({TS_CLOCK_BOOTTIME, tsBoottime}); + snapShot0.push_back({TS_CLOCK_REALTIME, tsRealTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + + streamFilters_.clockFilter_->SetPrimaryClock(TS_CLOCK_BOOTTIME); + uint64_t time1 = 250; + uint64_t expectTime1 = 50; + EXPECT_EQ(streamFilters_.clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, time1), expectTime1); +} + +/** + * @tc.name: ConvertMonotonicTimeToPrimaryTwice + * @tc.desc: convert TS_MONOTONIC to primary time type with single snapshop + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertMonotonicTimeToPrimaryTwice, TestSize.Level1) +{ + TS_LOGI("test2-14"); + std::vector snapShot0; + uint64_t tsMonotonicTime = 200; + uint64_t tsRealTimeCoarseTime = 400; + snapShot0.push_back({TS_MONOTONIC, tsMonotonicTime}); + snapShot0.push_back({TS_CLOCK_REALTIME_COARSE, tsRealTimeCoarseTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + + streamFilters_.clockFilter_->SetPrimaryClock(TS_CLOCK_REALTIME_COARSE); + uint64_t time1 = 250; + uint64_t expectTime1 = 450; + EXPECT_EQ(streamFilters_.clockFilter_->ToPrimaryTraceTime(TS_MONOTONIC, time1), expectTime1); + time1 = 550; + expectTime1 = 750; + EXPECT_EQ(streamFilters_.clockFilter_->ToPrimaryTraceTime(TS_MONOTONIC, time1), expectTime1); +} + +/** + * @tc.name: ConvertToPrimaryTwiceWithTwoSnapshop + * @tc.desc: convert TS_MONOTONIC & TS_CLOCK_BOOTTIME to primary time type with two snapshop + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, ConvertToPrimaryTwiceWithTwoSnapshop, TestSize.Level1) +{ + TS_LOGI("test2-15"); + std::vector snapShot0; + uint64_t tsMonotonicTime = 200; + uint64_t tsRealTimeCoarseTime = 400; + snapShot0.push_back({TS_MONOTONIC, tsMonotonicTime}); + snapShot0.push_back({TS_CLOCK_REALTIME_COARSE, tsRealTimeCoarseTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + + std::vector snapShot1; + uint64_t tsBootTime2 = 350; + uint64_t tsRealTimeCoarseTime2 = 800; + snapShot1.push_back({TS_CLOCK_BOOTTIME, tsBootTime2}); + snapShot1.push_back({TS_CLOCK_REALTIME_COARSE, tsRealTimeCoarseTime2}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot1); + + streamFilters_.clockFilter_->SetPrimaryClock(TS_CLOCK_REALTIME_COARSE); + + uint64_t time1 = 250; + uint64_t expectTime1 = 450; + EXPECT_EQ(streamFilters_.clockFilter_->ToPrimaryTraceTime(TS_MONOTONIC, time1), expectTime1); + + uint64_t time2 = 450; + uint64_t expectTime2 = 900; + EXPECT_EQ(streamFilters_.clockFilter_->ToPrimaryTraceTime(TS_CLOCK_BOOTTIME, time2), expectTime2); +} + +/** + * @tc.name: MutiTimeTypeConvertWithMutiSnapshop + * @tc.desc: convert muti time type to primary time type with muti snapshop + * @tc.type: FUNC + */ +HWTEST_F(ClockFilterTest, MutiTimeTypeConvertWithMutiSnapshop, TestSize.Level1) +{ + TS_LOGI("test2-13"); + std::vector snapShot0; + uint64_t tsBoottime = 100; + uint64_t tsMonotonicTime = 200; + uint64_t tsRealTime = 300; + uint64_t tsRealTimeCoarseTime = 400; + snapShot0.push_back({TS_CLOCK_BOOTTIME, tsBoottime}); + snapShot0.push_back({TS_MONOTONIC, tsMonotonicTime}); + snapShot0.push_back({TS_CLOCK_REALTIME, tsRealTime}); + snapShot0.push_back({TS_CLOCK_REALTIME_COARSE, tsRealTimeCoarseTime}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot0); + + std::vector snapShot1; + uint64_t tsBoottime2 = 200; + uint64_t tsMonotonicTime2 = 350; + uint64_t tsRealTime2 = 400; + uint64_t tsRealTimeCoarseTime2 = 800; + snapShot1.push_back({TS_CLOCK_BOOTTIME, tsBoottime2}); + snapShot1.push_back({TS_MONOTONIC, tsMonotonicTime2}); + snapShot1.push_back({TS_CLOCK_REALTIME, tsRealTime2}); + snapShot1.push_back({TS_CLOCK_REALTIME_COARSE, tsRealTimeCoarseTime2}); + streamFilters_.clockFilter_->AddClockSnapshot(snapShot1); + + streamFilters_.clockFilter_->SetPrimaryClock(TS_CLOCK_REALTIME); + uint64_t time1 = 150; + uint64_t expectTime1 = 350; + EXPECT_EQ(streamFilters_.clockFilter_->ToPrimaryTraceTime(TS_CLOCK_BOOTTIME, time1), expectTime1); + uint64_t time2 = 101; + uint64_t expectTime2 = 301; + EXPECT_EQ(streamFilters_.clockFilter_->ToPrimaryTraceTime(TS_CLOCK_BOOTTIME, time2), expectTime2); + uint64_t time3 = 101; + uint64_t expectTime3 = 101; + EXPECT_EQ(streamFilters_.clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, time3), expectTime3); + uint64_t time4 = 351; + uint64_t expectTime4 = 351; + EXPECT_EQ(streamFilters_.clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, time4), expectTime4); + uint64_t time5 = 350; + uint64_t expectTime5 = 250; + EXPECT_EQ(streamFilters_.clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME_COARSE, time5), expectTime5); + uint64_t time6 = 420; + uint64_t expectTime6 = 320; + EXPECT_EQ(streamFilters_.clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME_COARSE, time6), expectTime6); + uint64_t time7 = 801; + uint64_t expectTime7 = 401; + EXPECT_EQ(streamFilters_.clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME_COARSE, time7), expectTime7); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/cpu_filter_test.cpp b/host/trace_streamer/test/unittest/cpu_filter_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3239bf9937c20f573bdaf49c95b9a96b5d9832fe --- /dev/null +++ b/host/trace_streamer/test/unittest/cpu_filter_test.cpp @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "cpu_filter.h" +#include "ts_common.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class CpuFilterTest : public ::testing::Test { +public: + void SetUp() + { + streamFilters_.cpuFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + } + + void TearDown() {} + +public: + TraceStreamerFilters streamFilters_; + TraceDataCache traceDataCache_; +}; + +/** + * @tc.name: CpufilterInsertWakeupTest + * @tc.desc: Test CpuFilter insert WakeupEvent + * @tc.type: FUNC + */ +HWTEST_F(CpuFilterTest, CpufilterInsertWakeupTest, TestSize.Level1) +{ + TS_LOGI("test3-1"); + /* InsertWakeupEvent ts, internalTid */ + uint64_t ts1 = 168758662877000; + uint64_t itid = 1; + streamFilters_.cpuFilter_->InsertWakeupEvent(ts1, itid); // 1st waking + streamFilters_.cpuFilter_->FinishCpuEvent(); + + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itid) == INVALID_UINT64); + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itid) == TASK_INVALID); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 0); // 0 thread state only +} + +/** + * @tc.name: CpufilterInsertSwitchTest + * @tc.desc: Test CpuFilter insert SwitchEvent + * @tc.type: FUNC + */ +HWTEST_F(CpuFilterTest, CpufilterInsertSwitchTest, TestSize.Level1) +{ + TS_LOGI("test3-2"); + uint64_t ts1 = 168758662919000; + uint64_t itidPre = 2; + uint64_t prePior = 120; + uint64_t cpu = 0; + uint64_t itidNext = 3; + uint64_t nextPior = 124; + + streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_INTERRUPTIBLE, itidNext, + nextPior); // 1st switch + streamFilters_.cpuFilter_->FinishCpuEvent(); + printf("state of pre itid: %llu\n", streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre)); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre) == TASK_INTERRUPTIBLE); + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_RUNNING); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itidNext) == 0); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 2); // 2 thread state +} + +/** + * @tc.name: CpufilterInsertSwitchFromZeroThread + * @tc.desc: Test CpuFilter insert SwitchEvent switch from zero thread + * @tc.type: FUNC + */ +HWTEST_F(CpuFilterTest, CpufilterInsertSwitchFromZeroThread, TestSize.Level1) +{ + TS_LOGI("test3-2-2"); + uint64_t ts1 = 168758662919000; + uint64_t itidPre = 0; + uint64_t prePior = 120; + uint64_t cpu = 0; + uint64_t itidNext = 3; + uint64_t nextPior = 124; + + streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_INTERRUPTIBLE, itidNext, + nextPior); // 1st switch + streamFilters_.cpuFilter_->FinishCpuEvent(); + printf("state of pre itid: %llu\n", streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre)); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre) == TASK_INVALID); + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_RUNNING); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itidNext) == 0); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 1); // 1 thread state +} + +/** + * @tc.name: CpufilterInsertSwitchToZeroThread + * @tc.desc: Test CpuFilter insert SwitchEvent switch to zero thread + * @tc.type: FUNC + */ +HWTEST_F(CpuFilterTest, CpufilterInsertSwitchToZeroThread, TestSize.Level1) +{ + TS_LOGI("test3-2-3"); + uint64_t ts1 = 168758662919000; + uint64_t itidPre = 2; + uint64_t prePior = 120; + uint64_t cpu = 0; + uint64_t itidNext = 0; + uint64_t nextPior = 124; + + streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_INTERRUPTIBLE, itidNext, + nextPior); // 1st switch + streamFilters_.cpuFilter_->FinishCpuEvent(); + printf("state of pre itid: %llu\n", streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre)); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre) == TASK_INTERRUPTIBLE); + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_INVALID); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itidNext) == INVALID_UINT64); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 1); // 1 thread state +} + +/** + * @tc.name: CpufilterInsertSwitchDoubleThread + * @tc.desc: Test CpuFilter insert SwitchEvent, A switch to B and B switch to A + * @tc.type: FUNC + */ +HWTEST_F(CpuFilterTest, CpufilterInsertSwitchDoubleThread, TestSize.Level1) +{ + TS_LOGI("test3-3"); + uint64_t ts1 = 168758662919000; + uint64_t itidPre = 2; + uint64_t prePior = 120; + uint64_t cpu = 0; + uint64_t itidNext = 3; + uint64_t nextPior = 124; + + streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_INTERRUPTIBLE, itidNext, + nextPior); // 1st switch + streamFilters_.cpuFilter_->FinishCpuEvent(); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre) == TASK_INTERRUPTIBLE); + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_RUNNING); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itidNext) == 0); + + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 2); // 2 thread state + + ts1 = 168758663017000; + itidPre = 3; + prePior = 120; + cpu = 0; + itidNext = 4; + nextPior = 120; + streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_RUNNABLE, itidNext, + nextPior); // 2nd switch + streamFilters_.cpuFilter_->FinishCpuEvent(); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_RUNNING); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itidNext) == 2); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itidPre) == 3); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 4); // 4 thread state +} + +/** + * @tc.name: CpufilterInsertSwitchThreeThread + * @tc.desc: Test CpuFilter insert SwitchEvent, A switch to B and B switch to C + * @tc.type: FUNC + */ +HWTEST_F(CpuFilterTest, CpufilterInsertSwitchThreeThread, TestSize.Level1) +{ + TS_LOGI("test3-3-2"); + uint64_t ts1 = 168758662919000; + uint64_t itidPre = 2; + uint64_t prePior = 120; + uint64_t cpu = 0; + uint64_t itidNext = 3; + uint64_t nextPior = 124; + + streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_INTERRUPTIBLE, itidNext, + nextPior); // 1st switch + streamFilters_.cpuFilter_->FinishCpuEvent(); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre) == TASK_INTERRUPTIBLE); + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_RUNNING); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itidNext) == 0); + + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 2); // 2 thread state + + ts1 = 168758663017000; + itidPre = 3; + prePior = 120; + cpu = 0; + itidNext = 2; + nextPior = 120; + streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_RUNNABLE, itidNext, + nextPior); // 2nd switch + streamFilters_.cpuFilter_->FinishCpuEvent(); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_RUNNING); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itidNext) == 2); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itidPre) == 3); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 4); // 4 thread state +} + +/** + * @tc.name: CpufilterInsertSwitchTestZero + * @tc.desc: Test CpuFilter insert SwitchEvent, A switch to B and B switch to zero thread + * @tc.type: FUNC + */ +HWTEST_F(CpuFilterTest, CpufilterInsertSwitchTestZero, TestSize.Level1) +{ + TS_LOGI("test3-3-3"); + uint64_t ts1 = 168758662919000; + uint64_t itidPre = 2; + uint64_t prePior = 120; + uint64_t cpu = 0; + uint64_t itidNext = 3; + uint64_t nextPior = 124; + + streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_INTERRUPTIBLE, itidNext, + nextPior); // 1st switch + streamFilters_.cpuFilter_->FinishCpuEvent(); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre) == TASK_INTERRUPTIBLE); + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_RUNNING); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itidNext) == 0); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 2); // 2 thread state + + ts1 = 168758663017000; + itidPre = 0; + prePior = 120; + cpu = 0; + itidNext = 4; + nextPior = 120; + streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_RUNNABLE, itidNext, + nextPior); // 2nd switch + streamFilters_.cpuFilter_->FinishCpuEvent(); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_RUNNING); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itidNext) == 2); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 3); // 4 thread state +} + +/** + * @tc.name: CpufiltertWakeingTest + * @tc.desc: Test CpuFilter insert Waking Event + * @tc.type: FUNC + */ +HWTEST_F(CpuFilterTest, CpufiltertWakeupTest, TestSize.Level1) +{ + TS_LOGI("test3-5"); + uint64_t ts1 = 168758662919000; + uint64_t itid = 2; + + streamFilters_.cpuFilter_->InsertWakeupEvent(ts1, itid); + streamFilters_.cpuFilter_->FinishCpuEvent(); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itid) == TASK_INVALID); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itid) == INVALID_UINT64); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 0); // 0 thread state +} + +/** + * @tc.name: CpufiltertWakingTwice + * @tc.desc: Test CpuFilter insert Waking Event, one thread waking twice + * @tc.type: FUNC + */ +HWTEST_F(CpuFilterTest, CpufiltertWakingTwice, TestSize.Level1) +{ + TS_LOGI("test3-6"); + uint64_t ts1 = 168758662919000; + uint64_t itid = 2; + + streamFilters_.cpuFilter_->InsertWakeupEvent(ts1, itid); + streamFilters_.cpuFilter_->FinishCpuEvent(); + ts1 = 168758662929000; + itid = 4; + streamFilters_.cpuFilter_->InsertWakeupEvent(ts1, itid); + streamFilters_.cpuFilter_->FinishCpuEvent(); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itid) == TASK_INVALID); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itid) == INVALID_UINT64); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 0); // 0 thread state +} + +/** + * @tc.name: CpufilterInsertSwitchTestFull + * @tc.desc: Parsing multiple switch and wakeup alternates + * @tc.type: FUNC + */ +HWTEST_F(CpuFilterTest, CpufilterInsertSwitchTestFull, TestSize.Level1) +{ + TS_LOGI("test3-7"); + /* InsertWakeupEvent ts, internalTid */ + /* InsertSwitchEvent ts, cpu, prevPid, prevPior, prevState, nextPid, nextPior */ + streamFilters_.cpuFilter_->InsertWakeupEvent(168758662877000, 1); // 1st waking + streamFilters_.cpuFilter_->FinishCpuEvent(); + + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(1) == INVALID_UINT64); + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(1) == TASK_INVALID); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 0); // 0 thread state only + + streamFilters_.cpuFilter_->InsertSwitchEvent(168758662919000, 0, 1, 120, TASK_INTERRUPTIBLE, 2, 124); // 1st switch + streamFilters_.cpuFilter_->FinishCpuEvent(); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(1) == TASK_INTERRUPTIBLE); + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(2) == TASK_RUNNING); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(2) == 0); + // 2 thread state, the waking event add a runnable state + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 3); + streamFilters_.cpuFilter_->InsertSwitchEvent(168758663017000, 0, 0, 120, TASK_RUNNABLE, 4, 120); // 2nd switch + streamFilters_.cpuFilter_->FinishCpuEvent(); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(4) == TASK_RUNNING); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(4) == 3); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 4); // 4 thread state + + streamFilters_.cpuFilter_->InsertWakeupEvent(168758663078000, 0); // 2nd waking + + streamFilters_.cpuFilter_->InsertWakeupEvent(168758663092000, 0); // 3rd waking + streamFilters_.cpuFilter_->FinishCpuEvent(); + + streamFilters_.cpuFilter_->InsertSwitchEvent(168758663107000, 0, 2, 124, TASK_RUNNABLE, 5, 98); // 3rd switch + streamFilters_.cpuFilter_->FinishCpuEvent(); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(5) == TASK_RUNNING); + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(2) == TASK_RUNNABLE); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(5) == 4); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(2) == 5); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 6); // 6 thread state + + streamFilters_.cpuFilter_->InsertSwitchEvent(168758663126000, 0, 5, 98, TASK_INTERRUPTIBLE, 2, 124); // 4th switch + streamFilters_.cpuFilter_->FinishCpuEvent(); + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(2) == TASK_RUNNING); + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(5) == TASK_INTERRUPTIBLE); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(2) == 6); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(5) == 7); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 8); // 8 thread state + + streamFilters_.cpuFilter_->InsertSwitchEvent(168758663136000, 3, 5, 120, TASK_RUNNABLE, 6, 120); // 5th switch + streamFilters_.cpuFilter_->FinishCpuEvent(); + + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(6) == TASK_RUNNING); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(6) == 8); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 10); // 10 thread state + + // after 3rd switch + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->DursData()[0] == 168758663107000 - 168758662919000); + // after 4th switch + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->DursData()[4] == 168758663126000 - 168758663107000); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->DursData()[5] == 168758663126000 - 168758663107000); + // after 5th switch + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->DursData()[7] == 168758663136000 - 168758663126000); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/event_parser_test.cpp b/host/trace_streamer/test/unittest/event_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..56a87765d3f760129c8b4fb464f2aef9368a6eef --- /dev/null +++ b/host/trace_streamer/test/unittest/event_parser_test.cpp @@ -0,0 +1,1214 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "cpu_filter.h" +#include "parser/bytrace_parser/bytrace_event_parser.h" +#include "parser/bytrace_parser/bytrace_parser.h" +#include "parser/common_types.h" +#include "securec.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +const uint32_t G_BUF_SIZE = 1024; +// TestSuite: +class EventParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() + { + if (access(dbPath_.c_str(), F_OK) == 0) { + remove(dbPath_.c_str()); + } + } + +public: + TraceStreamerSelector stream_ = {}; + const std::string dbPath_ = "/data/resource/out.db"; +}; + +/** + * @tc.name: ParseLine + * @tc.desc: Parse a complete sched_switch event in bytrace format + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseLine, TestSize.Level1) +{ + TS_LOGI("test4-1"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.pid = 1; + bytraceLine.cpu = 0; + bytraceLine.task = "ACCS0-2716"; + bytraceLine.pidStr = "12"; + bytraceLine.tGidStr = "12"; + bytraceLine.eventName = "sched_switch"; + ArgsMap args; + args.insert(std::make_pair("prev_comm", "ACCS0")); + args.insert(std::make_pair("prev_pid", "2716")); + args.insert(std::make_pair("prev_prio", "120")); + args.insert(std::make_pair("prev_state", "R")); + args.insert(std::make_pair("next_comm", "kworker/0:0")); + args.insert(std::make_pair("next_pid", "8326")); + args.insert(std::make_pair("next_prio", "120")); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.ParseDataItem(bytraceLine, args, 2519); + EXPECT_EQ(result, true); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto readStatIndex = stream_.traceDataCache_->GetConstSchedSliceData().EndStatesData()[0]; + EXPECT_EQ(TASK_RUNNABLE, readStatIndex); + auto realTimeStamp = stream_.traceDataCache_->GetConstSchedSliceData().TimeStamData()[0]; + EXPECT_TRUE(bytraceLine.ts == realTimeStamp); + auto realCpu = stream_.traceDataCache_->GetConstSchedSliceData().CpusData()[0]; + EXPECT_TRUE(bytraceLine.cpu == realCpu); +} + +/** + * @tc.name: ParseLineNotEnoughArgs + * @tc.desc: Parse a sched_switch event which has not enough args in bytrace format + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseLineNotEnoughArgs, TestSize.Level1) +{ + TS_LOGI("test4-1"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.pid = 1; + bytraceLine.cpu = 0; + bytraceLine.task = "ACCS0-2716"; + bytraceLine.pidStr = "12"; + bytraceLine.tGidStr = "12"; + bytraceLine.eventName = "sched_switch"; + ArgsMap args; + args.insert(std::make_pair("prev_prio", "120")); + args.insert(std::make_pair("prev_state", "R")); + args.insert(std::make_pair("next_comm", "kworker/0:0")); + args.insert(std::make_pair("next_pid", "8326")); + args.insert(std::make_pair("next_prio", "120")); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.ParseDataItem(bytraceLine, args, 2519); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: ParseLineUnCognizableEventname + * @tc.desc: Parse a UnCognizable Eventname event in bytrace format + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseLineUnCognizableEventname, TestSize.Level1) +{ + TS_LOGI("test4-2"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.pid = 1; + bytraceLine.cpu = 0; + bytraceLine.task = "ACCS0-2716"; + bytraceLine.pidStr = "12"; + bytraceLine.tGidStr = "12"; + bytraceLine.eventName = "ThisEventNameDoNotExist"; // UnRecognizable event name + ArgsMap args; + args.insert(std::make_pair("prev_comm", "ACCS0")); + args.insert(std::make_pair("prev_pid", "2716")); + args.insert(std::make_pair("prev_prio", "120")); + args.insert(std::make_pair("prev_state", "R")); + args.insert(std::make_pair("next_comm", "kworker/0:0")); + args.insert(std::make_pair("next_pid", "8326")); + args.insert(std::make_pair("next_prio", "120")); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.ParseDataItem(bytraceLine, args, 2519); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: ParseSchedSwitchNoArgs + * @tc.desc: Parse a SchedSwitch event which has no args in bytrace format + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseSchedSwitchNoArgs, TestSize.Level1) +{ + TS_LOGI("test4-4"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.pid = 1; + bytraceLine.cpu = 0; + bytraceLine.task = "ACCS0-2716"; + bytraceLine.pidStr = "12"; + bytraceLine.tGidStr = "12"; + bytraceLine.eventName = "sched_switch"; + ArgsMap args; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.ParseDataItem(bytraceLine, args, 2519); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: ParseSchedWakeupNoArgs + * @tc.desc: Parse a SchedWakeup event which has no args in bytrace format + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseSchedWakeupNoArgs, TestSize.Level1) +{ + TS_LOGI("test4-4"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.pid = 1; + bytraceLine.cpu = 0; + bytraceLine.task = "ACCS0-2716"; + bytraceLine.pidStr = "12"; + bytraceLine.tGidStr = "12"; + bytraceLine.eventName = "sched_wakeup"; + ArgsMap args; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.ParseDataItem(bytraceLine, args, 2519); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: ParseTracingMarkWriteC + * @tc.desc: Parse a TracingMarkWrite C event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseTracingMarkWriteC, TestSize.Level1) +{ + TS_LOGI("test4-7"); + + const uint8_t str[] = + "ACCS0-2716 ( 2519) [000] ...1 174330.284808: tracing_mark_write: C|2519|Heap size (KB)|2906\n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParseTracingMarkWriteBE + * @tc.desc: Parse a TracingMarkWrite BE event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseTracingMarkWriteBE, TestSize.Level1) +{ + TS_LOGI("test4-8"); + const uint8_t str[] = + "system-1298 ( 1298) [001] ...1 174330.287420: tracing_mark_write: B|1298|Choreographer#doFrame\n \ + system - 1298(1298)[001]... 1 174330.287622 : tracing_mark_write : E | 1298\n"; // E | 1298 wrong format + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + EXPECT_EQ(bytraceParser.ParsedTraceInvalidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParseTracingMarkWriteSF + * @tc.desc: Parse a TracingMarkWrite SF event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseTracingMarkWriteSF, TestSize.Level1) +{ + TS_LOGI("test4-9"); + + const uint8_t str[] = + "system-1298 ( 1298) [001] ...1 174330.287478: tracing_mark_write: S|1298|animator:\ + translateX|18888109\n system-1298(1298)[001]... 1 174330.287514 : tracing_mark_write : \ + F | 1298 | animator : translateX | 18888109\n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + EXPECT_EQ(bytraceParser.ParsedTraceInvalidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParseTracingMarkWriteErrorPoint + * @tc.desc: Parse a TracingMarkWrite event with error point info + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseTracingMarkWriteErrorPoint, TestSize.Level1) +{ + TS_LOGI("test4-10"); + const uint8_t str[] = + "system-1298 ( 1298) [001] ...1 174330.287478: tracing_mark_write: G|1298|animator: \ + translateX|18888109\n system-1298(1298)[001]... 1 174330.287514 : tracing_mark_write : \ + F | 1298 | animator : translateX | 18888109\n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + EXPECT_EQ(bytraceParser.ParsedTraceInvalidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParseCpuIdle + * @tc.desc: Parse a CpuIdle event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseCpuIdle, TestSize.Level1) +{ + TS_LOGI("test4-14"); + const uint8_t str[] = "-0 (-----) [003] d..2 174330.280761: cpu_idle: state=2 cpu_id=3\n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParseIrqHandlerEntry + * @tc.desc: Parse a IrqHandlerEntry event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseIrqHandlerEntry, TestSize.Level1) +{ + TS_LOGI("test4-15"); + const uint8_t str[] = + "ACCS0-2716 ( 2519) [000] d.h1 174330.280362: irq_handler_entry: irq=19 name=408000.qcom,cpu-bwmon\n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParseIrqHandlerExit + * @tc.desc: Parse a IrqHandlerExit event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseIrqHandlerExit, TestSize.Level1) +{ + TS_LOGI("test4-16"); + const uint8_t str[] = + "ACCS0-2716 ( 2519) [000] d.h1 174330.280382: irq_handler_exit: irq=19 ret=handled\n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParseSchedWaking + * @tc.desc: Parse a SchedWaking event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseSchedWaking, TestSize.Level1) +{ + TS_LOGI("test4-17"); + const uint8_t str[] = + "ACCS0-2716 ( 2519) [000] d..5 174330.280567: sched_waking: \ + comm=Binder:924_6 pid=1332 prio=120 target_cpu=000\n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParseSchedWakeup + * @tc.desc: Parse a SchedWakeup event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseSchedWakeup, TestSize.Level1) +{ + TS_LOGI("test4-18"); + const uint8_t str[] = + "ACCS0-2716 ( 2519) [000] d..6 174330.280575: sched_wakeup: \ + comm=Binder:924_6 pid=1332 prio=120 target_cpu=000\n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParseTraceEventClockSync + * @tc.desc: Parse a TraceEventClockSync event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseTraceEventClockSync, TestSize.Level1) +{ + TS_LOGI("test4-19"); + const uint8_t str[] = + "sampletrace-12728 (12728) [003] ...1 174330.280300: tracing_mark_write: \ + trace_event_clock_sync:parent_ts=23139.998047\n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParseSchedSwitch + * @tc.desc: Parse a SchedSwitch event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseSchedSwitch, TestSize.Level1) +{ + TS_LOGI("test4-27"); + const uint8_t str[] = + "ACCS0-2716 ( 2519) [000] d..3 174330.289220: sched_switch: prev_comm=ACCS0 prev_pid=2716 prev_prio=120 \ + prev_state=R+ ==> next_comm=Binder:924_6 next_pid=1332 next_prio=120\n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParseTaskRename + * @tc.desc: Parse a TaskRename event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseTaskRename, TestSize.Level1) +{ + TS_LOGI("test4-28"); + const uint8_t str[] = + "<...>-2093 (-----) [001] ...2 174332.792290: task_rename: pid=12729 oldcomm=perfd \ + newcomm=POSIX timer 249 oom_score_adj=-1000\n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParseTaskNewtask + * @tc.desc: Parse a TaskNewtask event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseTaskNewtask, TestSize.Level1) +{ + TS_LOGI("test4-29"); + const uint8_t str[] = + "<...>-2 (-----) [003] ...1 174332.825588: task_newtask: pid=12730 \ + comm=kthreadd clone_flags=800711 oom_score_adj=0\n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParseWorkqueueExecuteStart + * @tc.desc: Parse a WorkqueueExecuteStart event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseWorkqueueExecuteStart, TestSize.Level1) +{ + TS_LOGI("test4-30"); + const uint8_t str[] = + "<...>-12180 (-----) [001] ...1 174332.827595: workqueue_execute_start: \ + work struct 0000000000000000: function pm_runtime_work\n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParseWorkqueueExecuteEnd + * @tc.desc: Parse a WorkqueueExecuteEnd event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseWorkqueueExecuteEnd, TestSize.Level1) +{ + TS_LOGI("test4-31"); + const uint8_t str[] = + "<...>-12180 (-----) [001] ...1 174332.828056: workqueue_execute_end: work struct 0000000000000000\n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); +} + +/** + * @tc.name: ParsDistribute + * @tc.desc: Parse a Distribute event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParsDistribute, TestSize.Level1) +{ + TS_LOGI("test4-31-1"); + const uint8_t str[] = + "system-1298 ( 1298) [001] ...1 174330.287420: tracing_mark_write: B|1298|[8b00e96b2,2,1]:C$#decodeFrame$#" + "{\"Process\":\"DecodeVideoFrame\",\"frameTimestamp\":37313484466} \ + system - 1298(1298)[001]... 1 174330.287622 : tracing_mark_write : E | 1298 \n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ChainIds()[0] == "8b00e96b2"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().SpanIds()[0] == "2"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ParentSpanIds()[0] == "1"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Flags()[0] == "C"); +} + +/** + * @tc.name: ParsPairsOfDistributeEvent + * @tc.desc: Parse a pair of Distribute event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParsPairsOfDistributeEvent, TestSize.Level1) +{ + TS_LOGI("test4-31-2"); + const uint8_t str[] = + "system-1298 ( 1298) [001] ...1 174330.287420: tracing_mark_write: B|1298|[8b00e96b2,2,1]:C$#decodeFrame$#" + "{\"Process\":\"DecodeVideoFrame\",\"frameTimestamp\":37313484466} \ + system - 1298(1298)[001]... 1 174330.287622 : tracing_mark_write : E | 1298 \n" + "startVC-7601 ( 7601) [002] ...1 174330.387420: tracing_mark_write: B|7601|[8b00e96b2,2,1]:S$#startVCFrame$#" + "{\"Process\":\"DecodeVideoFrame\",\"frameTimestamp\":37313484466} \ + startVC-7601 (7601)[002]... 1 174330.487622 : tracing_mark_write : E | 7601 \n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(2)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 2); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ChainIds()[0] == "8b00e96b2"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().SpanIds()[0] == "2"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ParentSpanIds()[0] == "1"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Flags()[0] == "C"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ChainIds()[1] == "8b00e96b2"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().SpanIds()[1] == "2"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ParentSpanIds()[1] == "1"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Flags()[1] == "S"); +} + +/** + * @tc.name: ParsDistributeWithNoFlag + * @tc.desc: Parse a Distribute event with no flag + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParsDistributeWithNoFlag, TestSize.Level1) +{ + TS_LOGI("test4-31-3"); + const uint8_t str[] = + "system-1298 ( 1298) [001] ...1 174330.287420: tracing_mark_write: B|1298|[8b00e96b2,2,1]$#decodeFrame$#" + "{\"Process\":\"DecodeVideoFrame\",\"frameTimestamp\":37313484466} \ + system - 1298(1298)[001]... 1 174330.287622 : tracing_mark_write : E | 1298 \n"; + auto buf = std::make_unique(G_BUF_SIZE); + if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { + EXPECT_TRUE(false); + return; + } + BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + bytraceParser.ParseTraceDataSegment(std::move(buf), G_BUF_SIZE); + bytraceParser.WaitForParserEnd(); + + EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); + stream_.traceDataCache_->ExportDatabase(dbPath_); + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ChainIds()[0] == "8b00e96b2"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().SpanIds()[0] == "2"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ParentSpanIds()[0] == "1"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Flags()[0] == ""); +} + +/** + * @tc.name: ParseSchedSwitchByInitParam + * @tc.desc: Parse a SchedSwitch event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseSchedSwitchByInitParam, TestSize.Level1) +{ + TS_LOGI("test4-32"); + BytraceLine bytraceLine; + static std::unordered_map args{{"prev_comm", "ACCS0"}, {"next_comm", "HeapTaskDaemon"}, + {"prev_prio", "120"}, {"next_prio", "124"}, + {"prev_pid", "2716"}, {"next_pid", "2532"}, + {"prev_state", "S"}}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.SchedSwitchEvent(args, bytraceLine); + + EXPECT_EQ(result, true); +} + +/** + * @tc.name: ParseSchedSwitchByAbnormalInitParam + * @tc.desc: Parse a SchedSwitch event with some Null parameter + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseSchedSwitchByAbnormalInitParam, TestSize.Level1) +{ + TS_LOGI("test4-33"); + BytraceLine bytraceLine; + static std::unordered_map args{{"prev_comm", "ACCS0"}, {"next_comm", "HeapTaskDaemon"}, + {"prev_prio", ""}, {"next_prio", ""}, + {"prev_pid", ""}, {"next_pid", ""}, + {"prev_state", "S"}}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.SchedSwitchEvent(args, bytraceLine); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: ParseTaskRenameEventByInitParam + * @tc.desc: Parse a TaskRename event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseTaskRenameByInitParam, TestSize.Level1) +{ + TS_LOGI("test4-34"); + BytraceLine bytraceLine; + static std::unordered_map args{{"newcomm", "POSIX"}, {"pid", "8542"}}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.TaskRenameEvent(args, bytraceLine); + + EXPECT_EQ(result, true); +} + +/** + * @tc.name: ParseTaskNewtaskByInitParam + * @tc.desc: Parse a TaskNew event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseTaskNewtaskByInitParam, TestSize.Level1) +{ + TS_LOGI("test4-35"); + BytraceLine bytraceLine; + bytraceLine.tGidStr = "12"; + static std::unordered_map args{{"comm", "POSIX"}, {"pid", "8542"}, {"clone_flags", "1"}}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.TaskNewtaskEvent(args, bytraceLine); + + EXPECT_EQ(result, true); +} + +/** + * @tc.name: ParseTracingMarkWriteByInitParam + * @tc.desc: Parse a TracingMarkWriteEvent event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseTracingMarkWriteByInitParam, TestSize.Level1) +{ + TS_LOGI("test4-36"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.pid = 1; + bytraceLine.argsStr = "vec=9 [action=RCU]"; + static std::unordered_map args{}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.TracingMarkWriteEvent(args, bytraceLine); + + EXPECT_EQ(result, true); +} + +/** + * @tc.name: ParseSchedWakeupByInitParam + * @tc.desc: Parse a SchedWakeup event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseSchedWakeupByInitParam, TestSize.Level1) +{ + TS_LOGI("test4-37"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.pid = 1; + static std::unordered_map args{{"pid", "1200"}, {"target_cpu", "1"}}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.SchedWakeupEvent(args, bytraceLine); + + EXPECT_EQ(result, true); +} + +/** + * @tc.name: ParseSchedWakeupByAbromalInitParam + * @tc.desc: Parse a SchedWakeup event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseSchedWakeupByAbromalInitParam, TestSize.Level1) +{ + TS_LOGI("test4-38"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.pid = 1; + static std::unordered_map args{{"pid", ""}, {"target_cpu", "1"}}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.SchedWakeupEvent(args, bytraceLine); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: ParseSchedWakingByInitParam + * @tc.desc: Parse a SchedWaking event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseSchedWakingByInitParam, TestSize.Level1) +{ + TS_LOGI("test4-39"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.pid = 1; + static std::unordered_map args{{"pid", "1200"}, {"target_cpu", "1"}}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.SchedWakingEvent(args, bytraceLine); + + EXPECT_EQ(result, true); +} + +/** + * @tc.name: ParseSchedWakingByAbnormalInitParam + * @tc.desc: Parse a SchedWaking event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseSchedWakingByAbnormalInitParam, TestSize.Level1) +{ + TS_LOGI("test4-40"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.pid = 1; + static std::unordered_map args{{"pid", ""}, {"target_cpu", "1"}}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.SchedWakingEvent(args, bytraceLine); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: ParseCpuIdleByInitParam + * @tc.desc: Parse a CpuIdle event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseCpuIdleByInitParam, TestSize.Level1) +{ + TS_LOGI("test4-41"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.eventName = "POSIX"; + static std::unordered_map args{{"cpu_id", "3"}, {"state", "4294967295"}}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.CpuIdleEvent(args, bytraceLine); + + EXPECT_EQ(result, true); +} + +/** + * @tc.name: ParseCpuIdleByAbnormalInitParam + * @tc.desc: Parse a CpuIdle event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseCpuIdleByAbnormalInitParam, TestSize.Level1) +{ + TS_LOGI("test4-42"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.eventName = "POSIX"; + static std::unordered_map args{{"cpu_id", ""}, {"state", "4294967295"}}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.CpuIdleEvent(args, bytraceLine); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: ParseCpuFrequencyNormal + * @tc.desc: Parse a CpuFrequency event normally + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseCpuFrequencyNormal, TestSize.Level1) +{ + TS_LOGI("test4-44"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.eventName = "POSIX"; + static std::unordered_map args{{"cpu_id", "3"}, {"state", "4294967295"}}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.CpuFrequencyEvent(args, bytraceLine); + + EXPECT_EQ(result, true); +} + +/** + * @tc.name: ParseCpuFrequencyByAbnormalInitEmptyCpuId + * @tc.desc: Parse a CpuFrequency event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseCpuFrequencyByAbnormalInitEmptyCpuId, TestSize.Level1) +{ + TS_LOGI("test4-45"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.eventName = "POSIX"; + static std::unordered_map args{{"cpu_id", ""}, {"state", "4294967295"}}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.CpuFrequencyEvent(args, bytraceLine); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: ParseCpuFrequencyByAbnormalInitEmptyStateValue + * @tc.desc: Parse a CpuFrequency event, empty state value + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseCpuFrequencyByAbnormalInitEmptyStateValue, TestSize.Level1) +{ + TS_LOGI("test4-46"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.eventName = "POSIX"; + static std::unordered_map args{{"cpu_id", "3"}, {"state", ""}}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.CpuFrequencyEvent(args, bytraceLine); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: ParseWorkqueueExecuteStartByInitParam + * @tc.desc: Parse a WorkqueueExecuteStart event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseWorkqueueExecuteStartByInitParam, TestSize.Level1) +{ + TS_LOGI("test4-47"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.pid = 1355; + bytraceLine.argsStr = "vec=9 [action=RCU]"; + static std::unordered_map args{}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.WorkqueueExecuteStartEvent(args, bytraceLine); + + EXPECT_EQ(result, true); +} + +/** + * @tc.name: ParseWorkqueueExecuteEndByInitParam + * @tc.desc: Parse a WorkqueueExecuteEnd event + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, ParseWorkqueueExecuteEndByInitParam, TestSize.Level1) +{ + TS_LOGI("test4-48"); + BytraceLine bytraceLine; + bytraceLine.ts = 1616439852302; + bytraceLine.pid = 1355; + static std::unordered_map args{}; + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.WorkqueueExecuteEndEvent(args, bytraceLine); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: CheckTracePoint + * @tc.desc: Judge whether the "tracepoint information conforming to the specification" in a text format conforms to the + * tracepoint specification + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, CheckTracePoint, TestSize.Level1) +{ + TS_LOGI("test4-49"); + std::string str("B|924|FullSuspendCheck"); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.CheckTracePoint(str); + + EXPECT_TRUE(result == SUCCESS); +} + +/** + * @tc.name: CheckTracePointEmptyString + * @tc.desc: Judge whether the Empty string conforms to the tracepoint specification + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, CheckTracePointEmptyString, TestSize.Level1) +{ + TS_LOGI("test4-50"); + std::string str(""); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.CheckTracePoint(str); + + EXPECT_TRUE(result == ERROR); +} + +/** + * @tc.name: CheckTracePointNoSplit + * @tc.desc: Judge whether the string No Split conforms to the tracepoint specification + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, CheckTracePointNoSplit, TestSize.Level1) +{ + TS_LOGI("test4-51"); + std::string str("trace_event_clock_sync"); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.CheckTracePoint(str); + + EXPECT_TRUE(result == ERROR); +} + +/** + * @tc.name: CheckTracePointMultiType + * @tc.desc: Judge whether the string has multipul Case type conforms to the tracepoint specification + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, CheckTracePointMultiType, TestSize.Level1) +{ + TS_LOGI("test4-52"); + std::string str("BECSF|924|FullSuspendCheck"); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.CheckTracePoint(str); + + EXPECT_TRUE(result == ERROR); +} + +/** + * @tc.name: CheckTracePointCheckSingleCharacter + * @tc.desc: Check whether a single character conforms to tracepoint format + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, CheckTracePointCheckSingleCharacter, TestSize.Level1) +{ + TS_LOGI("test4-53"); + std::string str("X"); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.CheckTracePoint(str); + + EXPECT_TRUE(result == ERROR); +} + +/** + * @tc.name: CheckTracePointCheckErrorSplit + * @tc.desc: Check error split + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, CheckTracePointCheckErrorSplit, TestSize.Level1) +{ + TS_LOGI("test4-54"); + std::string str("B&924|FullSuspendCheck"); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.CheckTracePoint(str); + + EXPECT_TRUE(result == ERROR); +} + +/** + * @tc.name: GetTracePoint + * @tc.desc: Test GetTracePoint interface + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, GetTracePoint, TestSize.Level1) +{ + TS_LOGI("test4-55"); + TracePoint point; + std::string str("B|924|SuspendThreadByThreadId suspended Binder:924_8 id=39"); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.GetTracePoint(str, point); + + EXPECT_TRUE(result == SUCCESS); +} + +/** + * @tc.name: GetTracePointParseEmptyString + * @tc.desc: Test GetTracePoint interface parse empty string + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, GetTracePointParseEmptyString, TestSize.Level1) +{ + TS_LOGI("test4-56"); + TracePoint point; + std::string str(""); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.GetTracePoint(str, point); + + EXPECT_TRUE(result == ERROR); +} + +/** + * @tc.name: GetTracePointParseErrorSubEventType + * @tc.desc: Test GetTracePoint interface parse error Sub event type + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, GetTracePointParseErrorSubEventType, TestSize.Level1) +{ + TS_LOGI("test4-57"); + TracePoint point; + std::string str("X|924|SuspendThreadByThreadId suspended Binder:924_8 id=39"); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.GetTracePoint(str, point); + + EXPECT_TRUE(result == ERROR); +} + +/** + * @tc.name: GetThreadGroupId + * @tc.desc: Test GetThreadGroupId interface + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, GetThreadGroupId, TestSize.Level1) +{ + TS_LOGI("test4-58"); + size_t length{0}; + std::string str("E|924"); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.GetThreadGroupId(str, length); + + EXPECT_TRUE(result == 924); +} + +/** + * @tc.name: GetThreadGroupIdParseErrorPid + * @tc.desc: Test GetThreadGroupId interface parse error pid + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, GetThreadGroupIdParseErrorPid, TestSize.Level1) +{ + TS_LOGI("test4-59"); + size_t length{0}; + std::string str("E|abc"); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.GetThreadGroupId(str, length); + + EXPECT_TRUE(result == ERROR); +} + +/** + * @tc.name: HandlerB + * @tc.desc: Test HandlerB interface + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, HandlerB, TestSize.Level1) +{ + TS_LOGI("test4-60"); + size_t length{3}; + TracePoint outPoint; + std::string str("B|924|HID::ISensors::batch::client"); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.HandlerB(str, outPoint, length); + + EXPECT_TRUE(result == SUCCESS); +} + +/** + * @tc.name: HandlerB + * @tc.desc: Test HandlerBAbnormal interface using Abnormal format + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, HandlerBAbnormal, TestSize.Level1) +{ + TS_LOGI("test4-61"); + size_t length{3}; + TracePoint outPoint; + std::string str("B|924|"); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.HandlerB(str, outPoint, length); + + EXPECT_TRUE(result == ERROR); +} + +/** + * @tc.name: HandlerCsf + * @tc.desc: Test HandlerCSF interface + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, HandlerCsf, TestSize.Level1) +{ + TS_LOGI("test4-62"); + size_t length{4}; + TracePoint outPoint; + std::string str("C|2519|Heap size (KB)|2363"); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.HandlerCSF(str, outPoint, length); + + EXPECT_TRUE(result == SUCCESS); +} + +/** + * @tc.name: HandlerCsfParseEmptyString + * @tc.desc: Parse empty string using HandlerCSF interface + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, HandlerCsfParseEmptyString, TestSize.Level1) +{ + TS_LOGI("test4-63"); + size_t length{4}; + TracePoint outPoint; + std::string str(""); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.HandlerCSF(str, outPoint, length); + + EXPECT_TRUE(result == ERROR); +} + +/** + * @tc.name: HandlerCsfParseErrorFormate + * @tc.desc: Parse "C|2519|Heap size (KB)|" using HandlerCSF interface + * @tc.type: FUNC + */ +HWTEST_F(EventParserTest, HandlerCsfParseErrorFormate, TestSize.Level1) +{ + TS_LOGI("test4-64"); + size_t length{4}; + TracePoint outPoint; + std::string str("C|2519|Heap size (KB)|"); + BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + int result = eventParser.printEventParser_.HandlerCSF(str, outPoint, length); + + EXPECT_TRUE(result == ERROR); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/filter_filter_test.cpp b/host/trace_streamer/test/unittest/filter_filter_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..732dbb00c1596c478c50eb61310c583d807d5503 --- /dev/null +++ b/host/trace_streamer/test/unittest/filter_filter_test.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "filter_filter.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class FilterFilterTest : public ::testing::Test { +public: + void SetUp() + { + streamFilters_.filterFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + } + + void TearDown() {} + +public: + TraceStreamerFilters streamFilters_; + TraceDataCache traceDataCache_; +}; + +/** + * @tc.name: AddCpuCounterFilter + * @tc.desc: Add cpu_counter_filter through AddFilter interface + * @tc.type: FUNC + */ +HWTEST_F(FilterFilterTest, AddCpuCounterFilter, TestSize.Level1) +{ + TS_LOGI("test5-1"); + uint32_t filterId = streamFilters_.filterFilter_->AddFilter("cpu_counter_filter", "cpu1", 1); + EXPECT_EQ(filterId, static_cast(0)); + + filterId = streamFilters_.filterFilter_->AddFilter("cpu_counter_filter", "cpu2", 2); + EXPECT_EQ(filterId, static_cast(1)); + + Filter* filterTable = traceDataCache_.GetFilterData(); + EXPECT_EQ(filterTable->Size(), static_cast(2)); +} + +/** + * @tc.name: AddCpuCounterFilter + * @tc.desc: Add thread_counter_filter & thread_filter through AddFilter interface + * @tc.type: FUNC + */ +HWTEST_F(FilterFilterTest, AddThreadFilter, TestSize.Level1) +{ + TS_LOGI("test5-2"); + uint32_t threadFilterId = streamFilters_.filterFilter_->AddFilter("thread_counter_filter", "threadCount1", 1); + EXPECT_EQ(threadFilterId, static_cast(0)); + + threadFilterId = streamFilters_.filterFilter_->AddFilter("thread_counter_filter", "threadCount2", 2); + EXPECT_EQ(threadFilterId, static_cast(1)); + + Filter* filterTable = traceDataCache_.GetFilterData(); + EXPECT_EQ(filterTable->Size(), static_cast(2)); + + threadFilterId = streamFilters_.filterFilter_->AddFilter("thread_filter", "thread1", 1); + EXPECT_EQ(threadFilterId, static_cast(2)); + + threadFilterId = streamFilters_.filterFilter_->AddFilter("thread_filter", "thread2", 2); + EXPECT_EQ(threadFilterId, static_cast(3)); + + EXPECT_EQ(filterTable->Size(), static_cast(4)); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/hilog_parser_test.cpp b/host/trace_streamer/test/unittest/hilog_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..69f71d6495d54aa32e0ec76bdc87c80b1cc8aecb --- /dev/null +++ b/host/trace_streamer/test/unittest/hilog_parser_test.cpp @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "htrace_hilog_parser.h" +#include "parser/bytrace_parser/bytrace_parser.h" +#include "parser/common_types.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; + +namespace SysTuning { +namespace TraceStreamer { +class HilogParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; +}; + +/** + * @tc.name: HilogParseWithoutHilogLine + * @tc.desc: Parse a HilogInfo that does not contain any hiloglines + * @tc.type: FUNC + */ +HWTEST_F(HilogParserTest, ParseHilogInfoWithoutHilogLine, TestSize.Level1) +{ + HilogInfo* hilogInfo = new HilogInfo(); + HtraceHiLogParser htraceHiLogParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceHiLogParser.Parse(*hilogInfo); + auto size = stream_.traceDataCache_->GetConstHilogData().Size(); + EXPECT_FALSE(size); +} + +/** + * @tc.name: ParseHilogInfoWithOneHilogLine + * @tc.desc: Parse a HilogInfo with only one Hilogline + * @tc.type: FUNC + */ +HWTEST_F(HilogParserTest, ParseHilogInfoWithOneHilogLine, TestSize.Level1) +{ + const uint64_t TV_SEC = 1632675525; + const uint64_t TV_NSEC = 996560700; + const std::string LOG_TAG = "HwMSDPMovementService"; + const std::string LOG_CONTEXT = "handleGetSupportedModule"; + const uint32_t LOG_LEVEL_D = 68; + const uint32_t PID = 2716; + const uint32_t TID = 1532; + const uint64_t LOG_ID = 1; + + HilogDetails* hilogDetails = new HilogDetails(); + hilogDetails->set_tv_sec(TV_SEC); + hilogDetails->set_tv_nsec(TV_NSEC); + hilogDetails->set_pid(PID); + hilogDetails->set_tid(TID); + hilogDetails->set_level(LOG_LEVEL_D); + hilogDetails->set_tag(LOG_TAG); + + HilogInfo* hilogInfo = new HilogInfo(); + auto hilogLine = hilogInfo->add_info(); + hilogLine->set_allocated_detail(hilogDetails); + hilogLine->set_context(LOG_CONTEXT); + hilogLine->set_id(LOG_ID); + + HtraceHiLogParser htraceHiLogParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceHiLogParser.Parse(*hilogInfo); + + auto seq = stream_.traceDataCache_->GetConstHilogData().HilogLineSeqs()[0]; + EXPECT_EQ(seq, LOG_ID); + + auto timestamp = stream_.traceDataCache_->GetConstHilogData().TimeStamData()[0]; + EXPECT_EQ(timestamp, (TV_NSEC + TV_SEC * SEC_TO_NS)); + + auto pid = stream_.traceDataCache_->GetConstHilogData().Pids()[0]; + EXPECT_EQ(pid, PID); + + auto tid = stream_.traceDataCache_->GetConstHilogData().Tids()[0]; + EXPECT_EQ(tid, TID); + + auto level = stream_.traceDataCache_->GetConstHilogData().Levels()[0]; + auto iter = htraceHiLogParser.logLevelString_.find(LOG_LEVEL_D); + if (iter == htraceHiLogParser.logLevelString_.end()) { + EXPECT_FALSE(0); + } + DataIndex levelDIndex = stream_.traceDataCache_->dataDict_.GetStringIndex(iter->second.c_str()); + EXPECT_EQ(level, levelDIndex); + + auto readTagIndex = stream_.traceDataCache_->GetConstHilogData().Tags()[0]; + DataIndex writeTagIndex = stream_.traceDataCache_->dataDict_.GetStringIndex(LOG_TAG); + EXPECT_EQ(readTagIndex, writeTagIndex); + + auto readContextIndex = stream_.traceDataCache_->GetConstHilogData().Contexts()[0]; + DataIndex writeContextIndex = stream_.traceDataCache_->dataDict_.GetStringIndex(LOG_CONTEXT); + EXPECT_EQ(readContextIndex, writeContextIndex); + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_HILOG, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseHilogInfoWithMultipleHilogLine + * @tc.desc: Parse a HilogInfo with multiple Hiloglines + * @tc.type: FUNC + */ +HWTEST_F(HilogParserTest, ParseHilogInfoWithMultipleHilogLine, TestSize.Level1) +{ + const uint64_t TV_SEC_01 = 1632675525; + const uint64_t TV_NSEC_01 = 996560700; + const uint32_t PID_01 = 2716; + const uint32_t TID_01 = 1532; + const uint32_t LOG_LEVEL_D = 68; + const std::string LOG_TAG_01 = "HwMSDPMovementService"; + const std::string LOG_CONTEXT_01 = "handleGetSupportedModule"; + const uint64_t LOG_ID_01 = 1; + + HilogDetails* hilogDetailsFirst = new HilogDetails(); + hilogDetailsFirst->set_tv_sec(TV_SEC_01); + hilogDetailsFirst->set_tv_nsec(TV_NSEC_01); + hilogDetailsFirst->set_pid(PID_01); + hilogDetailsFirst->set_tid(TID_01); + hilogDetailsFirst->set_level(LOG_LEVEL_D); + hilogDetailsFirst->set_tag(LOG_TAG_01); + + const uint64_t TV_SEC_02 = 1632688888; + const uint64_t TV_NSEC_02 = 996588888; + const uint32_t PID_02 = 2532; + const uint32_t TID_02 = 1716; + const uint32_t LOG_LEVEL_E = 69; + const std::string LOG_TAG_02 = "ProfilerService"; + const std::string LOG_CONTEXT_02 = "POST_RECV_MESSAGE method: /IProfilerService/CreateSession"; + const uint64_t LOG_ID_02 = 2; + + HilogDetails* hilogDetailsSecond = new HilogDetails(); + hilogDetailsSecond->set_tv_sec(TV_SEC_02); + hilogDetailsSecond->set_tv_nsec(TV_NSEC_02); + hilogDetailsSecond->set_pid(PID_02); + hilogDetailsSecond->set_tid(TID_02); + hilogDetailsSecond->set_level(LOG_LEVEL_E); + hilogDetailsSecond->set_tag(LOG_TAG_02); + + HilogInfo* hilogInfo = new HilogInfo(); + auto hilogLineFirst = hilogInfo->add_info(); + hilogLineFirst->set_allocated_detail(hilogDetailsFirst); + hilogLineFirst->set_context(LOG_CONTEXT_01); + hilogLineFirst->set_id(LOG_ID_01); + + auto hilogLineSecond = hilogInfo->add_info(); + hilogLineSecond->set_allocated_detail(hilogDetailsSecond); + hilogLineSecond->set_context(LOG_CONTEXT_02); + hilogLineSecond->set_id(LOG_ID_02); + + HtraceHiLogParser htraceHiLogParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceHiLogParser.Parse(*hilogInfo); + + auto seqFirst = stream_.traceDataCache_->GetConstHilogData().HilogLineSeqs()[0]; + auto seqSecond = stream_.traceDataCache_->GetConstHilogData().HilogLineSeqs()[1]; + EXPECT_EQ(seqFirst, LOG_ID_01); + EXPECT_EQ(seqSecond, LOG_ID_02); + + auto timestampFirst = stream_.traceDataCache_->GetConstHilogData().TimeStamData()[0]; + auto timestampSecond = stream_.traceDataCache_->GetConstHilogData().TimeStamData()[1]; + EXPECT_EQ(timestampFirst, (TV_NSEC_01 + TV_SEC_01 * SEC_TO_NS)); + EXPECT_EQ(timestampSecond, (TV_NSEC_02 + TV_SEC_02 * SEC_TO_NS)); + + auto pidFirst = stream_.traceDataCache_->GetConstHilogData().Pids()[0]; + auto pidSecond = stream_.traceDataCache_->GetConstHilogData().Pids()[1]; + EXPECT_EQ(pidFirst, PID_01); + EXPECT_EQ(pidSecond, PID_02); + + auto tidFirst = stream_.traceDataCache_->GetConstHilogData().Tids()[0]; + auto tidSecond = stream_.traceDataCache_->GetConstHilogData().Tids()[1]; + EXPECT_EQ(tidFirst, TID_01); + EXPECT_EQ(tidSecond, TID_02); + + auto levelFirst = stream_.traceDataCache_->GetConstHilogData().Levels()[0]; + auto iterFirst = htraceHiLogParser.logLevelString_.find(LOG_LEVEL_D); + if (iterFirst == htraceHiLogParser.logLevelString_.end()) { + EXPECT_FALSE(0); + } + DataIndex levelDIndex = stream_.traceDataCache_->dataDict_.GetStringIndex(iterFirst->second.c_str()); + EXPECT_EQ(levelFirst, levelDIndex); + + auto levelSecond = stream_.traceDataCache_->GetConstHilogData().Levels()[1]; + auto iterSecond = htraceHiLogParser.logLevelString_.find(LOG_LEVEL_E); + if (iterSecond == htraceHiLogParser.logLevelString_.end()) { + EXPECT_FALSE(0); + } + DataIndex levelEIndex = stream_.traceDataCache_->dataDict_.GetStringIndex(iterSecond->second.c_str()); + EXPECT_EQ(levelSecond, levelEIndex); + + auto readTagIndexFirst = stream_.traceDataCache_->GetConstHilogData().Tags()[0]; + auto readTagIndexSecond = stream_.traceDataCache_->GetConstHilogData().Tags()[1]; + DataIndex writeTagIndexFirst = stream_.traceDataCache_->dataDict_.GetStringIndex(LOG_TAG_01); + DataIndex writeTagIndexSecond = stream_.traceDataCache_->dataDict_.GetStringIndex(LOG_TAG_02); + EXPECT_EQ(readTagIndexFirst, writeTagIndexFirst); + EXPECT_EQ(readTagIndexSecond, writeTagIndexSecond); + + auto readContextIndexFirst = stream_.traceDataCache_->GetConstHilogData().Contexts()[0]; + auto readContextIndexSecond = stream_.traceDataCache_->GetConstHilogData().Contexts()[1]; + DataIndex writeContextIndexFirst = stream_.traceDataCache_->dataDict_.GetStringIndex(LOG_CONTEXT_01); + DataIndex writeContextIndexSecond = stream_.traceDataCache_->dataDict_.GetStringIndex(LOG_CONTEXT_02); + EXPECT_EQ(readContextIndexFirst, writeContextIndexFirst); + EXPECT_EQ(readContextIndexSecond, writeContextIndexSecond); + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_HILOG, STAT_EVENT_RECEIVED); + EXPECT_TRUE(2 == eventCount); +} + +/** + * @tc.name: ParseHilogInfoWithErrLevelHilogLine + * @tc.desc: Parse a HilogInfo with error level Hiloglines + * @tc.type: FUNC + */ +HWTEST_F(HilogParserTest, ParseHilogInfoWithErrLevelHilogLine, TestSize.Level1) +{ + const uint64_t TV_SEC = 1632675525; + const uint64_t TV_NSEC = 996560700; + const std::string LOG_TAG = "HwMSDPMovementService"; + const std::string LOG_CONTEXT = "handleGetSupportedModule"; + const uint32_t LOG_LEVEL_ILLEGAL = 0; + const uint32_t PID = 2716; + const uint32_t TID = 1532; + const uint64_t LOG_ID = 1; + + HilogDetails* hilogDetails = new HilogDetails(); + hilogDetails->set_tv_sec(TV_SEC); + hilogDetails->set_tv_nsec(TV_NSEC); + hilogDetails->set_pid(PID); + hilogDetails->set_tid(TID); + hilogDetails->set_level(LOG_LEVEL_ILLEGAL); + hilogDetails->set_tag(LOG_TAG); + + HilogInfo* hilogInfo = new HilogInfo(); + auto hilogLine = hilogInfo->add_info(); + hilogLine->set_allocated_detail(hilogDetails); + hilogLine->set_context(LOG_CONTEXT); + hilogLine->set_id(LOG_ID); + + HtraceHiLogParser htraceHiLogParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceHiLogParser.Parse(*hilogInfo); + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_HILOG, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_HILOG, STAT_EVENT_DATA_INVALID); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseHilogInfoLostHilogLine + * @tc.desc: Parse a HilogInfo that lost a Hiloglines + * @tc.type: FUNC + */ +HWTEST_F(HilogParserTest, ParseHilogInfoLostHilogLine, TestSize.Level1) +{ + const uint64_t TV_SEC = 1632675525; + const uint64_t TV_NSEC = 996560700; + const std::string LOG_TAG = "HwMSDPMovementService"; + const std::string LOG_CONTEXT = "handleGetSupportedModule"; + const uint32_t LOG_LEVEL_D = 68; + const uint32_t PID = 2716; + const uint32_t TID = 1532; + const uint64_t LOG_ID = 2; + + HilogDetails* hilogDetails = new HilogDetails(); + hilogDetails->set_tv_sec(TV_SEC); + hilogDetails->set_tv_nsec(TV_NSEC); + hilogDetails->set_pid(PID); + hilogDetails->set_tid(TID); + hilogDetails->set_level(LOG_LEVEL_D); + hilogDetails->set_tag(LOG_TAG); + + HilogInfo* hilogInfo = new HilogInfo(); + auto hilogLine = hilogInfo->add_info(); + hilogLine->set_allocated_detail(hilogDetails); + hilogLine->set_context(LOG_CONTEXT); + hilogLine->set_id(LOG_ID); + + HtraceHiLogParser htraceHiLogParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceHiLogParser.Parse(*hilogInfo); + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_HILOG, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_HILOG, STAT_EVENT_DATA_LOST); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseHilogInfoHasDuplicateHilogLine + * @tc.desc: Parse a HilogInfo has duplicate HilogLine + * @tc.type: FUNC + */ +HWTEST_F(HilogParserTest, ParseHilogInfoHasDuplicateHilogLine, TestSize.Level1) +{ + const uint64_t TV_SEC = 1632675525; + const uint64_t TV_NSEC = 996560700; + const std::string LOG_TAG = "HwMSDPMovementService"; + const std::string LOG_CONTEXT = "handleGetSupportedModule"; + const uint32_t LOG_LEVEL_D = 68; + const uint32_t PID = 2716; + const uint32_t TID = 1532; + const uint64_t LOG_ID = 1; + + HilogDetails* hilogDetails = new HilogDetails(); + hilogDetails->set_tv_sec(TV_SEC); + hilogDetails->set_tv_nsec(TV_NSEC); + hilogDetails->set_pid(PID); + hilogDetails->set_tid(TID); + hilogDetails->set_level(LOG_LEVEL_D); + hilogDetails->set_tag(LOG_TAG); + + HilogInfo* hilogInfo = new HilogInfo(); + auto hilogLineFirst = hilogInfo->add_info(); + hilogLineFirst->set_allocated_detail(hilogDetails); + hilogLineFirst->set_context(LOG_CONTEXT); + hilogLineFirst->set_id(LOG_ID); + auto hilogLineSecond = hilogInfo->add_info(); + hilogLineSecond->set_allocated_detail(hilogDetails); + hilogLineSecond->set_context(LOG_CONTEXT); + hilogLineSecond->set_id(LOG_ID); + + HtraceHiLogParser htraceHiLogParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceHiLogParser.Parse(*hilogInfo); + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_HILOG, STAT_EVENT_RECEIVED); + EXPECT_TRUE(2 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_HILOG, STAT_EVENT_NOTMATCH); + EXPECT_TRUE(1 == eventCount); +} +} // namespace TraceStreamer +} // namespace SysTuning \ No newline at end of file diff --git a/host/trace_streamer/test/unittest/htrace_binder_event_test.cpp b/host/trace_streamer/test/unittest/htrace_binder_event_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32c7c9e982e042c896c0cdb6883ea543e6852c63 --- /dev/null +++ b/host/trace_streamer/test/unittest/htrace_binder_event_test.cpp @@ -0,0 +1,513 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "binder_filter.h" +#include "htrace_cpu_detail_parser.h" +#include "htrace_event_parser.h" +#include "trace_plugin_result.pb.h" +#include "trace_streamer_selector.h" +#include "ts_common.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class HtraceBinderEventTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; +}; + +/** + * @tc.name: BinderSenderfilterNeedReply + * @tc.desc: Binary formate binder event test, The binder event needs reply + * @tc.type: FUNC + */ +HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReply, TestSize.Level1) +{ + std::string appName = "app1"; + int64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = false; + uint32_t flags = 0x02; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_); 0x01 + uint32_t code = 0; // not important + BinderTransactionFormat* binderEvent = new BinderTransactionFormat(); + binderEvent->set_to_proc(destTgid1); + binderEvent->set_target_node(destNode1); + binderEvent->set_to_thread(destTid1); + binderEvent->set_debug_id(transactionId1); + binderEvent->set_reply(static_cast(isReply)); + binderEvent->set_code(code); + binderEvent->set_flags(flags); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_binder_transaction_format(binderEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(stream_.traceDataCache_->GetConstArgSetData().Size() == 7); +} + +/** + * @tc.name: BinderSenderfilterNeedReplyAndReceive + * @tc.desc: Binary formate binder event test, The binder event needs reply and received reply + * @tc.type: FUNC + */ +HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceive, TestSize.Level1) +{ + TS_LOGI("test9-2"); + std::string appName = "app1"; + int64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = false; + uint32_t flags = 0x02; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_); 0x01 + uint32_t code = 0; // not important + BinderTransactionFormat* binderEvent = new BinderTransactionFormat(); + binderEvent->set_to_proc(destTgid1); + binderEvent->set_target_node(destNode1); + binderEvent->set_to_thread(destTid1); + binderEvent->set_debug_id(transactionId1); + binderEvent->set_reply(static_cast(isReply)); + binderEvent->set_code(code); + binderEvent->set_flags(flags); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_binder_transaction_format(binderEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstArgSetData().Size() == 7); + + ts1 = 200; + uint32_t pid1 = 1; + FtraceCpuDetailMsg ftraceCpuDetail2; + ftraceCpuDetail2.set_cpu(0); + ftraceCpuDetail2.set_overwrite(0); + auto ftraceEvent2 = ftraceCpuDetail2.add_event(); + + ftraceEvent2->set_timestamp(ts1); + ftraceEvent2->set_tgid(pid1); + std::string appName2 = "app2"; + ftraceEvent2->set_comm(appName2); + BinderTransactionReceivedFormat* binderReceivedEvent = new BinderTransactionReceivedFormat(); + binderReceivedEvent->set_debug_id(transactionId1); + ftraceEvent2->set_allocated_binder_transaction_received_format(binderReceivedEvent); + eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 2); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[1] == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstArgSetData().Size() == 11); +} + +/** + * @tc.name: BinderSenderfilterNeedReplyAndReceiveWithAlloc + * @tc.desc: Binary formate BinderTransactionAllocBuf event test, The binder event needs reply and received reply + * @tc.type: FUNC + */ +HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceiveWithAlloc, TestSize.Level1) +{ + int64_t ts1 = 100; + std::string appName = "app1"; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = false; + uint32_t flags = 0x02; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_) + uint32_t code = 0; // not important + BinderTransactionFormat* binderEvent = new BinderTransactionFormat(); + binderEvent->set_to_proc(destTgid1); + binderEvent->set_target_node(destNode1); + binderEvent->set_to_thread(destTid1); + binderEvent->set_debug_id(transactionId1); + binderEvent->set_reply(static_cast(isReply)); + binderEvent->set_code(code); + binderEvent->set_flags(flags); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_binder_transaction_format(binderEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstArgSetData().Size() == 7); + + ts1 = 150; + uint64_t dataSize = 100; + uint64_t offsetSize = 200; + BinderTransactionAllocBufFormat* binderAllocEvent = new BinderTransactionAllocBufFormat(); + binderAllocEvent->set_data_size(dataSize); + binderAllocEvent->set_offsets_size(offsetSize); + + FtraceCpuDetailMsg ftraceCpuDetail2; + ftraceCpuDetail2.set_cpu(0); + ftraceCpuDetail2.set_overwrite(0); + auto ftraceEvent2 = ftraceCpuDetail2.add_event(); + + ftraceEvent2->set_timestamp(ts1); + ftraceEvent2->set_tgid(tid1); + ftraceEvent2->set_comm(appName); + ftraceEvent2->set_allocated_binder_transaction_alloc_buf_format(binderAllocEvent); + eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstArgSetData().Size() == 9); + + ts1 = 200; + uint32_t pid1 = 1; + FtraceCpuDetailMsg ftraceCpuDetail3; + ftraceCpuDetail3.set_cpu(0); + ftraceCpuDetail3.set_overwrite(0); + auto ftraceEvent3 = ftraceCpuDetail3.add_event(); + + ftraceEvent3->set_timestamp(ts1); + ftraceEvent3->set_tgid(pid1); + std::string appName2 = "app2"; + ftraceEvent3->set_comm(appName2); + BinderTransactionReceivedFormat* binderReceivedEvent = new BinderTransactionReceivedFormat(); + binderReceivedEvent->set_debug_id(transactionId1); + ftraceEvent3->set_allocated_binder_transaction_received_format(binderReceivedEvent); + eventParser.ParseDataItem(&ftraceCpuDetail3, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 2); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[1] == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstArgSetData().Size() == 13); +} + +/** + * @tc.name: BinderSenderfilterNeedReplyAndReceiveNotmatch + * @tc.desc: Binary formate BinderTransaction event test, The binder event needs reply but received not match + * @tc.type: FUNC + */ +HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceiveNotmatch, TestSize.Level1) +{ + TS_LOGI("test9-4"); + std::string appName = "app1"; + int64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = false; + uint32_t flags = 0x02; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_) + uint32_t code = 0; // not important + BinderTransactionFormat* binderEvent = new BinderTransactionFormat(); + binderEvent->set_to_proc(destTgid1); + binderEvent->set_target_node(destNode1); + binderEvent->set_to_thread(destTid1); + binderEvent->set_debug_id(transactionId1); + binderEvent->set_reply(static_cast(isReply)); + binderEvent->set_code(code); + binderEvent->set_flags(flags); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_binder_transaction_format(binderEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + + ts1 = 200; + uint32_t pid1 = 1; + uint64_t transactionId2 = 2; + FtraceCpuDetailMsg ftraceCpuDetail2; + ftraceCpuDetail2.set_cpu(0); + ftraceCpuDetail2.set_overwrite(0); + auto ftraceEvent2 = ftraceCpuDetail2.add_event(); + + ftraceEvent2->set_timestamp(ts1); + ftraceEvent2->set_tgid(pid1); + std::string appName2 = "app2"; + ftraceEvent2->set_comm(appName2); + BinderTransactionReceivedFormat* binderReceivedEvent = new BinderTransactionReceivedFormat(); + binderReceivedEvent->set_debug_id(transactionId2); + ftraceEvent2->set_allocated_binder_transaction_received_format(binderReceivedEvent); + eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); +} + +/** + * @tc.name: BinderSenderfilterNoNeedReply + * @tc.desc: Binary formate binder event test, The binder event needs no reply + * @tc.type: FUNC + */ +HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNoNeedReply, TestSize.Level1) +{ + TS_LOGI("test9-5"); + std::string appName = "app1"; + int64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = false; + uint32_t flags = 0x01; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_) + uint32_t code = 0; // not important + BinderTransactionFormat* binderEvent = new BinderTransactionFormat(); + binderEvent->set_to_proc(destTgid1); + binderEvent->set_target_node(destNode1); + binderEvent->set_to_thread(destTid1); + binderEvent->set_debug_id(transactionId1); + binderEvent->set_reply(static_cast(isReply)); + binderEvent->set_code(code); + binderEvent->set_flags(flags); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_binder_transaction_format(binderEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); +} + +/** + * @tc.name: BinderSenderNoneedReplyAndReceivefilter + * @tc.desc: Binary formate binder event test, other party received and no need reply。 + * @tc.type: FUNC + */ +HWTEST_F(HtraceBinderEventTest, BinderSenderNoneedReplyAndReceivefilter, TestSize.Level1) +{ + TS_LOGI("test9-6"); + std::string appName = "app1"; + int64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = false; + uint32_t flags = 0x01; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_) + uint32_t code = 0; // not important + BinderTransactionFormat* binderEvent = new BinderTransactionFormat(); + binderEvent->set_to_proc(destTgid1); + binderEvent->set_target_node(destNode1); + binderEvent->set_to_thread(destTid1); + binderEvent->set_debug_id(transactionId1); + binderEvent->set_reply(static_cast(isReply)); + binderEvent->set_code(code); + binderEvent->set_flags(flags); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_binder_transaction_format(binderEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + + ts1 = 200; + uint32_t pid1 = 1; + FtraceCpuDetailMsg ftraceCpuDetail2; + ftraceCpuDetail2.set_cpu(0); + ftraceCpuDetail2.set_overwrite(0); + auto ftraceEvent2 = ftraceCpuDetail2.add_event(); + + ftraceEvent2->set_timestamp(ts1); + ftraceEvent2->set_tgid(pid1); + std::string appName2 = "app2"; + ftraceEvent2->set_comm(appName2); + BinderTransactionReceivedFormat* binderReceivedEvent = new BinderTransactionReceivedFormat(); + binderReceivedEvent->set_debug_id(transactionId1); + ftraceEvent2->set_allocated_binder_transaction_received_format(binderReceivedEvent); + eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 2); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[1] == 1); +} + +/** + * @tc.name: BinderSenderNoneedReplyAndReceivefilterNotmatch + * @tc.desc: Binary formate binder event test, other party received but not match + * @tc.type: FUNC + */ +HWTEST_F(HtraceBinderEventTest, BinderSenderNoneedReplyAndReceivefilterNotmatch, TestSize.Level1) +{ + TS_LOGI("test9-7"); + std::string appName = "app1"; + int64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = false; + uint32_t flags = 0x01; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_) + uint32_t code = 0; // not importent + BinderTransactionFormat* binderEvent = new BinderTransactionFormat(); + binderEvent->set_to_proc(destTgid1); + binderEvent->set_target_node(destNode1); + binderEvent->set_to_thread(destTid1); + binderEvent->set_debug_id(transactionId1); + binderEvent->set_reply(static_cast(isReply)); + binderEvent->set_code(code); + binderEvent->set_flags(flags); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_binder_transaction_format(binderEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + + ts1 = 200; + uint32_t pid1 = 1; + uint64_t transactionId2 = 2; + FtraceCpuDetailMsg ftraceCpuDetail2; + ftraceCpuDetail2.set_cpu(0); + ftraceCpuDetail2.set_overwrite(0); + auto ftraceEvent2 = ftraceCpuDetail2.add_event(); + + ftraceEvent2->set_timestamp(ts1); + ftraceEvent2->set_tgid(pid1); + std::string appName2 = "app2"; + ftraceEvent2->set_comm(appName2); + BinderTransactionReceivedFormat* binderReceivedEvent = new BinderTransactionReceivedFormat(); + binderReceivedEvent->set_debug_id(transactionId2); + ftraceEvent2->set_allocated_binder_transaction_received_format(binderReceivedEvent); + eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); +} + +/** + * @tc.name: BinderSenderfilterWrongReply + * @tc.desc: Binary formate binder event test, other party replyed wrong Info + * @tc.type: FUNC + */ +HWTEST_F(HtraceBinderEventTest, BinderSenderfilterWrongReply, TestSize.Level1) +{ + TS_LOGI("test9-8"); + std::string appName = "app1"; + int64_t ts1 = 100; + uint32_t tid1 = 1; + uint64_t transactionId1 = 1; + int32_t destNode1 = 1; + int32_t destTgid1 = 2; + int32_t destTid1 = 3; + bool isReply = true; + uint32_t flags = 0x01; // if need reply bool needReply = !isReply && !(flags & noReturnMsgFlag_) + uint32_t code = 0; // not important + BinderTransactionFormat* binderEvent = new BinderTransactionFormat(); + binderEvent->set_to_proc(destTgid1); + binderEvent->set_target_node(destNode1); + binderEvent->set_to_thread(destTid1); + binderEvent->set_debug_id(transactionId1); + binderEvent->set_reply(static_cast(isReply)); + binderEvent->set_code(code); + binderEvent->set_flags(flags); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_binder_transaction_format(binderEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 0); + EXPECT_TRUE(stream_.traceDataCache_->GetConstArgSetData().Size() == 0); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/htrace_event_parser_test.cpp b/host/trace_streamer/test/unittest/htrace_event_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..220fe6fa26970e3e68fb0e0ab1d62b5a05af5815 --- /dev/null +++ b/host/trace_streamer/test/unittest/htrace_event_parser_test.cpp @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "cpu_filter.h" +#include "htrace_cpu_detail_parser.h" +#include "parser/common_types.h" +#include "trace_streamer_filters.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +const uint64_t TIMESTAMP = 1616439852302; +const std::string THREAD_NAME_01 = "ACCS0"; +const std::string THREAD_NAME_02 = "HeapTaskDaemon"; +const uint32_t PRIORITY_01 = 120; +const uint32_t PRIORITY_02 = 124; +const uint32_t PID_01 = 2716; +const uint32_t PID_02 = 2532; +class HtraceEventParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; +}; + +/** + * @tc.name: ParseSchedSwitchEvent + * @tc.desc: Parse a schedswitch event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseSchedSwitchEvent, TestSize.Level1) +{ + SchedSwitchFormat* event = new SchedSwitchFormat(); + event->set_prev_prio(PRIORITY_01); + event->set_next_prio(PRIORITY_02); + event->set_prev_pid(PID_01); + event->set_next_pid(PID_02); + event->set_prev_comm(THREAD_NAME_01); + event->set_next_comm(THREAD_NAME_02); + event->set_prev_state(1); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(1); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->unsafe_arena_set_allocated_sched_switch_format(event); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + EXPECT_TRUE(1); + auto realTimeStamp = stream_.traceDataCache_->GetConstSchedSliceData().TimeStamData()[0]; + EXPECT_TRUE(TIMESTAMP == realTimeStamp); + auto realCpu = stream_.traceDataCache_->GetConstSchedSliceData().CpusData()[0]; + EXPECT_TRUE(0 == realCpu); +} + +/** + * @tc.name: ParseFtraceCpuDetailMsgHasNoEvent + * @tc.desc: FtraceCpuDetailMsg has no ftrace event + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseFtraceCpuDetailMsgHasNoEvent, TestSize.Level1) +{ + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_OTHER, STAT_EVENT_DATA_LOST); + EXPECT_TRUE(0 == eventCount); +} + +/** + * @tc.name: ParseFtraceCpuDetailMsgOverwriteTrue + * @tc.desc: FtraceCpuDetailMsg overwrit is true + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseFtraceCpuDetailMsgOverwriteTrue, TestSize.Level1) +{ + SchedSwitchFormat* event = new SchedSwitchFormat(); + event->set_prev_prio(PRIORITY_01); + event->set_next_prio(PRIORITY_02); + event->set_prev_pid(PID_01); + event->set_next_pid(PID_02); + event->set_prev_comm(THREAD_NAME_01); + event->set_next_comm(THREAD_NAME_02); + event->set_prev_state(1); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(1); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(1); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_sched_switch_format(event); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_OTHER, STAT_EVENT_DATA_LOST); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseTaskRenameEvent + * @tc.desc: Parse a task_rename event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseTaskRenameEvent, TestSize.Level1) +{ + TaskRenameFormat* taskRenameEvent = new TaskRenameFormat(); + taskRenameEvent->set_pid(PID_01); + taskRenameEvent->set_oldcomm(THREAD_NAME_01); + taskRenameEvent->set_newcomm(THREAD_NAME_02); + taskRenameEvent->set_oom_score_adj(1); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(1); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_task_rename_format(taskRenameEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_TASK_RENAME, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseTaskNewtaskEvent + * @tc.desc: Parse a task_newtask event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseTaskNewtaskEvent, TestSize.Level1) +{ + TaskNewtaskFormat* newTaskEvent = new TaskNewtaskFormat(); + newTaskEvent->set_pid(PID_01); + newTaskEvent->set_comm(THREAD_NAME_01); + newTaskEvent->set_clone_flags(0); + newTaskEvent->set_oom_score_adj(1); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(1); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_task_newtask_format(newTaskEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_TASK_NEWTASK, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseSchedWakeupEvent + * @tc.desc: Parse a sched_wakeup event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseSchedWakeupEvent, TestSize.Level1) +{ + SchedWakeupFormat* wakeupEvent = new SchedWakeupFormat(); + wakeupEvent->set_comm(THREAD_NAME_01); + wakeupEvent->set_pid(PRIORITY_02); + wakeupEvent->set_prio(PID_01); + wakeupEvent->set_target_cpu(1); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(1); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_sched_wakeup_format(wakeupEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_SCHED_WAKEUP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseSchedWakingEvent + * @tc.desc: Parse a sched_waking event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseSchedWakingEvent, TestSize.Level1) +{ + SchedWakingFormat* wakingEvent = new SchedWakingFormat(); + wakingEvent->set_comm(THREAD_NAME_01); + wakingEvent->set_pid(PRIORITY_02); + wakingEvent->set_prio(PID_01); + wakingEvent->set_target_cpu(1); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(1); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_sched_waking_format(wakingEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_SCHED_WAKING, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseCpuIdleEvent + * @tc.desc: Parse a cpuIdle event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseCpuIdleEvent, TestSize.Level1) +{ + CpuIdleFormat* cpuIdleEvent = new CpuIdleFormat(); + cpuIdleEvent->set_cpu_id(0); + cpuIdleEvent->set_state(1); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(1); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_cpu_idle_format(cpuIdleEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CPU_IDLE, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseCpuFrequencyEvent + * @tc.desc: Parse a CpuFrequency event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseCpuFrequencyEvent, TestSize.Level1) +{ + CpuFrequencyFormat* cpuFrequencyEvent = new CpuFrequencyFormat(); + cpuFrequencyEvent->set_cpu_id(0); + cpuFrequencyEvent->set_state(1); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(2); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_cpu_frequency_format(cpuFrequencyEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CPU_FREQUENCY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseWorkqueueExecuteStartEvent + * @tc.desc: Parse a WorkqueueExecuteStart event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseWorkqueueExecuteStartEvent, TestSize.Level1) +{ + WorkqueueExecuteStartFormat* workqueueExecuteStartEvent = new WorkqueueExecuteStartFormat(); + workqueueExecuteStartEvent->set_work(0); + workqueueExecuteStartEvent->set_function(1); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(1); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_workqueue_execute_start_format(workqueueExecuteStartEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_WORKQUEUE_EXECUTE_START, + STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseWorkqueueExecuteEndEvent + * @tc.desc: Parse a WorkqueueExecuteEnd event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseWorkqueueExecuteEndEvent, TestSize.Level1) +{ + WorkqueueExecuteEndFormat* workqueueExecuteEndEvent = new WorkqueueExecuteEndFormat(); + workqueueExecuteEndEvent->set_work(0); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(1); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_workqueue_execute_end_format(workqueueExecuteEndEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_WORKQUEUE_EXECUTE_END, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseClockDisableEvent + * @tc.desc: Parse a clock_Disable event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseClockDisableEvent, TestSize.Level1) +{ + ClockDisableFormat* clockDisableEvent = new ClockDisableFormat(); + clockDisableEvent->set_name(THREAD_NAME_02); + clockDisableEvent->set_cpu_id(0); + clockDisableEvent->set_state(1); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(2); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_clock_disable_format(clockDisableEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CLOCK_DISABLE, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseClockEnableEvent + * @tc.desc: Parse a clock_Enable event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseClockEnableEvent, TestSize.Level1) +{ + ClockEnableFormat* clockEnableEvent = new ClockEnableFormat(); + clockEnableEvent->set_name(THREAD_NAME_02); + clockEnableEvent->set_cpu_id(0); + clockEnableEvent->set_state(1); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(2); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_clock_enable_format(clockEnableEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CLOCK_ENABLE, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseClockSetRateEvent + * @tc.desc: Parse a clock_set_rate event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseClockSetRateEvent, TestSize.Level1) +{ + ClockSetRateFormat* clockSetRateEvent = new ClockSetRateFormat(); + clockSetRateEvent->set_name(THREAD_NAME_02); + clockSetRateEvent->set_cpu_id(0); + clockSetRateEvent->set_state(1); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(2); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_clock_set_rate_format(clockSetRateEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CLOCK_SET_RATE, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseClkDisableEvent + * @tc.desc: Parse a clk_Disable event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseClkDisableEvent, TestSize.Level1) +{ + ClkDisableFormat* clkDisableEvent = new ClkDisableFormat(); + clkDisableEvent->set_name(THREAD_NAME_02); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(2); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_clk_disable_format(clkDisableEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CLK_DISABLE, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseClkEnableEvent + * @tc.desc: Parse a clk_Enable event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseClkEnableEvent, TestSize.Level1) +{ + ClkEnableFormat* clkEnableEvent = new ClkEnableFormat(); + clkEnableEvent->set_name(THREAD_NAME_02); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(2); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_clk_enable_format(clkEnableEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CLK_ENABLE, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseClkSetRateEvent + * @tc.desc: Parse a clk_set_rate event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseClkSetRateEvent, TestSize.Level1) +{ + ClkSetRateFormat* clkSetRateEvent = new ClkSetRateFormat(); + clkSetRateEvent->set_name(THREAD_NAME_02); + clkSetRateEvent->set_rate(1); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(2); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_clk_set_rate_format(clkSetRateEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CLK_SET_RATE, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseSysEnterEvent + * @tc.desc: Parse a sysEnter event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseSysEnterEvent, TestSize.Level1) +{ + SysEnterFormat* sysEnterEvent = new SysEnterFormat(); + sysEnterEvent->set_id(1); + sysEnterEvent->set_args(THREAD_NAME_02); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(2); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_sys_enter_format(sysEnterEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_SYS_ENTRY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} +/** + * @tc.name: ParseSystemExitEvent + * @tc.desc: Parse a system_exit event in htrace format + * @tc.type: FUNC + */ +HWTEST_F(HtraceEventParserTest, ParseSystemExitEvent, TestSize.Level1) +{ + SysExitFormat* sysExitEvent = new SysExitFormat(); + sysExitEvent->set_id(1); + sysExitEvent->set_ret(1); + + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(0); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(TIMESTAMP); + ftraceEvent->set_tgid(2); + ftraceEvent->set_comm(THREAD_NAME_02); + ftraceEvent->set_allocated_sys_exit_format(sysExitEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_SYS_EXIT, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/htrace_irq_event_test.cpp b/host/trace_streamer/test/unittest/htrace_irq_event_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..79c265ace264f43c8fd5a5953cc22ba5815a3174 --- /dev/null +++ b/host/trace_streamer/test/unittest/htrace_irq_event_test.cpp @@ -0,0 +1,483 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "htrace_cpu_detail_parser.h" +#include "htrace_event_parser.h" +#include "irq_filter.h" +#include "trace_streamer_selector.h" +#include "ts_common.h" +#include "types/plugins/ftrace_data/trace_plugin_result.pb.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class HtraceIrqEventTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; +}; + +/** + * @tc.name: IrqHandlerEntryTest + * @tc.desc: Binary formate IrqHandlerEntry Normal TEST + * @tc.type: FUNC + */ +HWTEST_F(HtraceIrqEventTest, IrqHandlerEntryTest, TestSize.Level1) +{ + TS_LOGI("test10-1"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + std::string appName = "app1"; + uint32_t tid1 = 1; + int32_t irq = 12; + IrqHandlerEntryFormat* irqHandlerEvent = new IrqHandlerEntryFormat(); + irqHandlerEvent->set_irq(irq); + irqHandlerEvent->set_name("user_irq"); + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(cpu1); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_irq_handler_entry_format(irqHandlerEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); +} + +/** + * @tc.name: IrqHandlerEntryTestNotMatch + * @tc.desc: Binary formate IrqHandlerEntry, only start, no end + * @tc.type: FUNC + */ +HWTEST_F(HtraceIrqEventTest, IrqHandlerEntryTestNotMatch, TestSize.Level1) +{ + TS_LOGI("test10-2"); + int64_t ts1 = 120; + uint32_t cpu1 = 1; + std::string appName = "app1"; + uint32_t tid1 = 1; + int32_t irq = 12; + IrqHandlerEntryFormat* irqHandlerEvent = new IrqHandlerEntryFormat(); + irqHandlerEvent->set_irq(irq); + irqHandlerEvent->set_name("user_irq"); + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(cpu1); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_irq_handler_entry_format(irqHandlerEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + ts1 = 110; + IrqHandlerEntryFormat* irqHandlerEvent2 = new IrqHandlerEntryFormat(); + irqHandlerEvent2->set_irq(irq); + irqHandlerEvent2->set_name("user_irq"); + FtraceCpuDetailMsg ftraceCpuDetail2; + ftraceCpuDetail2.set_cpu(cpu1); + ftraceCpuDetail2.set_overwrite(0); + auto ftraceEvent2 = ftraceCpuDetail2.add_event(); + + ftraceEvent2->set_timestamp(ts1); + ftraceEvent2->set_tgid(tid1); + ftraceEvent2->set_comm(appName); + ftraceEvent2->set_allocated_irq_handler_entry_format(irqHandlerEvent2); + eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 2); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_IRQ_HANDLER_ENTRY, STAT_EVENT_DATA_LOST); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: IrqHandlerExitTestEmpty + * @tc.desc: Binary formate IrqHandlerExit, Interrupt only ends, not starts + * @tc.type: FUNC + */ +HWTEST_F(HtraceIrqEventTest, IrqHandlerExitTestEmpty, TestSize.Level1) +{ + TS_LOGI("test10-3"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + uint32_t ret = 1; + std::string appName = "app1"; + uint32_t tid1 = 1; + int32_t irq = 12; // 1 for handled, else for unhandled + + IrqHandlerExitFormat* irqHandlerExitEvent = new IrqHandlerExitFormat(); + irqHandlerExitEvent->set_irq(irq); + irqHandlerExitEvent->set_ret(ret); + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(cpu1); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_irq_handler_exit_format(irqHandlerExitEvent); + + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 0); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_IRQ_HANDLER_EXIT, STAT_EVENT_NOTMATCH); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: IrqHandlerEnterAndExitTest + * @tc.desc: Binary formate IrqHandlerEnter, Interrupt normal start and end + * @tc.type: FUNC + */ +HWTEST_F(HtraceIrqEventTest, IrqHandlerEnterAndExitTest, TestSize.Level1) +{ + TS_LOGI("test10-4"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + std::string appName = "app1"; + uint32_t tid1 = 1; + int32_t irq = 12; + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + IrqHandlerEntryFormat* irqHandlerEvent = new IrqHandlerEntryFormat(); + irqHandlerEvent->set_irq(irq); + irqHandlerEvent->set_name("user_irq"); + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(cpu1); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_irq_handler_entry_format(irqHandlerEvent); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + uint32_t ret = 1; // 1 for handled, else for unhandled + + IrqHandlerExitFormat* irqHandlerExitEvent = new IrqHandlerExitFormat(); + irqHandlerExitEvent->set_irq(irq); + irqHandlerExitEvent->set_ret(ret); + FtraceCpuDetailMsg ftraceCpuDetail2; + ftraceCpuDetail2.set_cpu(cpu1); + ftraceCpuDetail2.set_overwrite(0); + auto ftraceEvent2 = ftraceCpuDetail2.add_event(); + + ftraceEvent2->set_timestamp(ts1); + ftraceEvent2->set_tgid(tid1); + ftraceEvent2->set_comm(appName); + ftraceEvent2->set_allocated_irq_handler_exit_format(irqHandlerExitEvent); + + eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); + + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); +} + +/** + * @tc.name: IrqHandlerEnterAndExitTestTwice + * @tc.desc: Binary formate IrqHandlerEnter and Exit, Interrupt normal start and end Twice + * @tc.type: FUNC + */ +HWTEST_F(HtraceIrqEventTest, IrqHandlerEnterAndExitTestTwice, TestSize.Level1) +{ + TS_LOGI("test10-4-2"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + std::string appName = "app1"; + uint32_t tid1 = 1; + int32_t irq = 12; + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + IrqHandlerEntryFormat* irqHandlerEvent = new IrqHandlerEntryFormat(); + irqHandlerEvent->set_irq(irq); + irqHandlerEvent->set_name("user_irq"); + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(cpu1); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_irq_handler_entry_format(irqHandlerEvent); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + uint32_t ret = 1; // 1 for handled, else for unhandled + cpu1 = 2; + ts1 = 150; + + IrqHandlerExitFormat* irqHandlerExitEvent = new IrqHandlerExitFormat(); + irqHandlerExitEvent->set_irq(irq); + irqHandlerExitEvent->set_ret(ret); + FtraceCpuDetailMsg ftraceCpuDetail2; + ftraceCpuDetail2.set_cpu(cpu1); + ftraceCpuDetail2.set_overwrite(0); + auto ftraceEvent2 = ftraceCpuDetail2.add_event(); + + ftraceEvent2->set_timestamp(ts1); + ftraceEvent2->set_tgid(tid1); + ftraceEvent2->set_comm(appName); + ftraceEvent2->set_allocated_irq_handler_exit_format(irqHandlerExitEvent); + + eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_IRQ_HANDLER_EXIT, + STAT_EVENT_NOTMATCH) == 1); + cpu1 = 1; + ts1 = 200; + + IrqHandlerExitFormat* irqHandlerExitEvent2 = new IrqHandlerExitFormat(); + irqHandlerExitEvent2->set_irq(irq); + irqHandlerExitEvent2->set_ret(ret); + FtraceCpuDetailMsg ftraceCpuDetail3; + ftraceCpuDetail3.set_cpu(cpu1); + ftraceCpuDetail3.set_overwrite(0); + auto ftraceEvent3 = ftraceCpuDetail3.add_event(); + + ftraceEvent3->set_timestamp(ts1); + ftraceEvent3->set_tgid(tid1); + ftraceEvent3->set_comm(appName); + ftraceEvent3->set_allocated_irq_handler_exit_format(irqHandlerExitEvent2); + + eventParser.ParseDataItem(&ftraceCpuDetail3, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); +} + +/** + * @tc.name: SoftIrqEntryTest + * @tc.desc: Binary format Soft interrupt normal test + * @tc.type: FUNC + */ +HWTEST_F(HtraceIrqEventTest, SoftIrqEntryTest, TestSize.Level1) +{ + TS_LOGI("test10-6"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + uint32_t vec = 1; + std::string appName = "app1"; + uint32_t tid1 = 1; + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + SoftirqEntryFormat* softirqEntryEvent = new SoftirqEntryFormat(); + softirqEntryEvent->set_vec(vec); + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(cpu1); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_softirq_entry_format(softirqEntryEvent); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); +} + +/** + * @tc.name: SoftIrqEntryNotMatch + * @tc.desc: The binary format soft interrupts do not match. The two interrupts have only the beginning and no end + * @tc.type: FUNC + */ +HWTEST_F(HtraceIrqEventTest, SoftIrqEntryNotMatch, TestSize.Level1) +{ + TS_LOGI("test10-7"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + uint32_t vec = 1; + std::string appName = "app1"; + uint32_t tid1 = 1; + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + SoftirqEntryFormat* softirqEntryEvent = new SoftirqEntryFormat(); + softirqEntryEvent->set_vec(vec); + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(cpu1); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_softirq_entry_format(softirqEntryEvent); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + ts1 = 150; + + SoftirqEntryFormat* softirqEntryEvent2 = new SoftirqEntryFormat(); + softirqEntryEvent2->set_vec(vec); + FtraceCpuDetailMsg ftraceCpuDetail2; + ftraceCpuDetail2.set_cpu(cpu1); + ftraceCpuDetail2.set_overwrite(0); + auto ftraceEvent2 = ftraceCpuDetail2.add_event(); + + ftraceEvent2->set_timestamp(ts1); + ftraceEvent2->set_tgid(tid1); + ftraceEvent2->set_comm(appName); + ftraceEvent2->set_allocated_softirq_entry_format(softirqEntryEvent2); + eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 2); + EXPECT_TRUE( + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_ENTRY, STAT_EVENT_DATA_LOST) == 1); +} + +/** + * @tc.name: SoftIrqExitEmptyTest + * @tc.desc: The binary format soft interrupt only ends without starting + * @tc.type: FUNC + */ +HWTEST_F(HtraceIrqEventTest, SoftIrqExitEmptyTest, TestSize.Level1) +{ + TS_LOGI("test10-8"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + uint32_t vec = 1; + std::string appName = "app1"; + uint32_t tid1 = 1; + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + SoftirqExitFormat* softirqExitEvent = new SoftirqExitFormat(); + softirqExitEvent->set_vec(vec); + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(cpu1); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_softirq_exit_format(softirqExitEvent); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 0); + EXPECT_TRUE( + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 1); +} + +/** + * @tc.name: SoftIrqTest + * @tc.desc: The binary format soft interrupt normal test + * @tc.type: FUNC + */ +HWTEST_F(HtraceIrqEventTest, SoftIrqTest, TestSize.Level1) +{ + TS_LOGI("test10-9"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + uint32_t vec = 1; + std::string appName = "app1"; + uint32_t tid1 = 1; + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + SoftirqEntryFormat* softirqEntryEvent = new SoftirqEntryFormat(); + softirqEntryEvent->set_vec(vec); + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(cpu1); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_softirq_entry_format(softirqEntryEvent); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + ts1 = 150; + SoftirqExitFormat* softirqExitEvent = new SoftirqExitFormat(); + softirqExitEvent->set_vec(vec); + FtraceCpuDetailMsg ftraceCpuDetail2; + ftraceCpuDetail2.set_cpu(cpu1); + ftraceCpuDetail2.set_overwrite(0); + auto ftraceEvent2 = ftraceCpuDetail2.add_event(); + + ftraceEvent2->set_timestamp(ts1); + ftraceEvent2->set_tgid(tid1); + ftraceEvent2->set_comm(appName); + ftraceEvent2->set_allocated_softirq_exit_format(softirqExitEvent); + eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); +} + +/** + * @tc.name: SoftIrqTestNotMatch + * @tc.desc: The binary soft interrupt test not match + * @tc.type: FUNC + */ +HWTEST_F(HtraceIrqEventTest, SoftIrqTestNotMatch, TestSize.Level1) +{ + TS_LOGI("test10-10"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + uint32_t vec = 1; + std::string appName = "app1"; + uint32_t tid1 = 1; + HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + SoftirqEntryFormat* softirqEntryEvent = new SoftirqEntryFormat(); + softirqEntryEvent->set_vec(vec); + FtraceCpuDetailMsg ftraceCpuDetail; + ftraceCpuDetail.set_cpu(cpu1); + ftraceCpuDetail.set_overwrite(0); + auto ftraceEvent = ftraceCpuDetail.add_event(); + + ftraceEvent->set_timestamp(ts1); + ftraceEvent->set_tgid(tid1); + ftraceEvent->set_comm(appName); + ftraceEvent->set_allocated_softirq_entry_format(softirqEntryEvent); + eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + ts1 = 150; + cpu1 = 2; + + SoftirqExitFormat* softirqExitEvent = new SoftirqExitFormat(); + softirqExitEvent->set_vec(vec); + FtraceCpuDetailMsg ftraceCpuDetail2; + ftraceCpuDetail2.set_cpu(cpu1); + ftraceCpuDetail2.set_overwrite(0); + auto ftraceEvent2 = ftraceCpuDetail2.add_event(); + + ftraceEvent2->set_timestamp(ts1); + ftraceEvent2->set_tgid(tid1); + ftraceEvent2->set_comm(appName); + ftraceEvent2->set_allocated_softirq_exit_format(softirqExitEvent); + eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, + STAT_EVENT_DATA_LOST) == 1); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/htrace_mem_parser_test.cpp b/host/trace_streamer/test/unittest/htrace_mem_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..822a0f2f2cf1ceb663419f8bc1e9591658666984 --- /dev/null +++ b/host/trace_streamer/test/unittest/htrace_mem_parser_test.cpp @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + + +#include "htrace_mem_parser.h" +#include "parser/common_types.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; + +namespace SysTuning { +namespace TraceStreamer { +class HtraceMemParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() + { + if (access(dbPath_.c_str(), F_OK) == 0) { + remove(dbPath_.c_str()); + } + } + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; + const std::string dbPath_ = "/data/resource/out.db"; +}; + +/** + * @tc.name: ParseMemParse + * @tc.desc: Parse MemoryData object and export database + * @tc.type: FUNC + */ +HWTEST_F(HtraceMemParserTest, ParseMemParse, TestSize.Level1) +{ + TS_LOGI("test7-1"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + ProcessMemoryInfo* memoryInfo = tracePacket.add_processesinfo(); + EXPECT_TRUE(memoryInfo != nullptr); + int size = tracePacket.processesinfo_size(); + EXPECT_TRUE(size == 1); + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + + memParser->Parse(tracePacket, timeStamp, clock); + memParser->Finish(); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + tracePacket.clear_processesinfo(); + delete memParser; + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseMemParseTestMeasureDataSize + * @tc.desc: Parse MemoryData object and count StatInfo + * @tc.type: FUNC + */ +HWTEST_F(HtraceMemParserTest, ParseMemParseTestMeasureDataSize, TestSize.Level1) +{ + TS_LOGI("test7-1"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + ProcessMemoryInfo* memoryInfo = tracePacket.add_processesinfo(); + EXPECT_TRUE(memoryInfo != nullptr); + int size = tracePacket.processesinfo_size(); + EXPECT_TRUE(size == 1); + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + uint32_t pid = 12; + int64_t memKb = 1024; + int64_t memRssKb = 512; + int64_t memAnonKb = 128; + int64_t memFileKb = 2048; + memoryInfo->set_pid(pid); + memoryInfo->set_name("Process1"); + memoryInfo->set_vm_size_kb(memKb); + memoryInfo->set_vm_rss_kb(memRssKb); + memoryInfo->set_rss_anon_kb(memAnonKb); + memoryInfo->set_rss_file_kb(memFileKb); + + memParser->Parse(tracePacket, timeStamp, clock); + memParser->Finish(); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + tracePacket.clear_processesinfo(); + delete memParser; + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessData(1).pid_ == pid); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == MEM_MAX * 1); + + for (auto i = 0; i < MEM_MAX; i++) { + if (stream_.traceDataCache_->GetConstMeasureData().filterIdDeque_[i] == + memParser->memNameDictMap_.at(MEM_VM_SIZE)) { + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().valuesDeque_[i] == memKb); + } else if (stream_.traceDataCache_->GetConstMeasureData().filterIdDeque_[i] == + memParser->memNameDictMap_.at(MEM_VM_RSS)) { + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().valuesDeque_[i] == memRssKb); + } else if (stream_.traceDataCache_->GetConstMeasureData().filterIdDeque_[i] == + memParser->memNameDictMap_.at(MEM_VM_ANON)) { + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().valuesDeque_[i] == memAnonKb); + } else if (stream_.traceDataCache_->GetConstMeasureData().filterIdDeque_[i] == + memParser->memNameDictMap_.at(MEM_RSS_FILE)) { + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().valuesDeque_[i] == memFileKb); + } + } +} + +/** + * @tc.name: ParseMemParseTestMutiMeasureData + * @tc.desc: Parse muti MemoryData object and count StatInfo + * @tc.type: FUNC + */ +HWTEST_F(HtraceMemParserTest, ParseMemParseTestMutiMeasureData, TestSize.Level1) +{ + TS_LOGI("test7-1"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + ProcessMemoryInfo* memoryInfo = tracePacket.add_processesinfo(); + EXPECT_TRUE(memoryInfo != nullptr); + int size = tracePacket.processesinfo_size(); + EXPECT_TRUE(size == 1); + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + uint32_t pid = 12; + memoryInfo->set_pid(12); + memoryInfo->set_name("Process1"); + memoryInfo->set_vm_size_kb(1024); + memoryInfo->set_vm_rss_kb(512); + memoryInfo->set_rss_anon_kb(128); + memoryInfo->set_rss_file_kb(128); + + ProcessMemoryInfo* memoryInfo2 = tracePacket.add_processesinfo(); + EXPECT_TRUE(memoryInfo2 != nullptr); + size = tracePacket.processesinfo_size(); + EXPECT_TRUE(size == 2); + timeStamp = 1616439852402; + uint32_t pid2 = 13; + memoryInfo2->set_pid(pid2); + memoryInfo2->set_name("Process2"); + memoryInfo2->set_vm_size_kb(1024); + memoryInfo2->set_vm_rss_kb(512); + memoryInfo2->set_rss_anon_kb(128); + memoryInfo2->set_rss_file_kb(128); + + memParser->Parse(tracePacket, timeStamp, clock); + memParser->Finish(); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + tracePacket.clear_processesinfo(); + delete memParser; + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessData(1).pid_ == pid); + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessData(2).pid_ == pid2); +} + +/** + * @tc.name: ParseMultiEmptyProcessMemoryInfo + * @tc.desc: Parse muti Empty ProcessMemoryInfo object and count StatInfo + * @tc.type: FUNC + */ +HWTEST_F(HtraceMemParserTest, ParseMultiEmptyProcessMemoryInfo, TestSize.Level1) +{ + TS_LOGI("test7-1"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + ProcessMemoryInfo* memoryInfo = tracePacket.add_processesinfo(); + EXPECT_TRUE(memoryInfo != nullptr); + int size = tracePacket.processesinfo_size(); + EXPECT_TRUE(size == 1); + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + + ProcessMemoryInfo* memoryInfo2 = tracePacket.add_processesinfo(); + EXPECT_TRUE(memoryInfo2 != nullptr); + size = tracePacket.processesinfo_size(); + EXPECT_TRUE(size == 2); + + memParser->Parse(tracePacket, timeStamp, clock); + memParser->Finish(); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + tracePacket.clear_processesinfo(); + delete memParser; + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == MEM_MAX * 2); +} + +/** + * @tc.name: ParseEmptyMemoryData + * @tc.desc: Parse Empty MemoryData + * @tc.type: FUNC + */ +HWTEST_F(HtraceMemParserTest, ParseEmptyMemoryData, TestSize.Level1) +{ + TS_LOGI("test7-1"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + int size = tracePacket.processesinfo_size(); + EXPECT_TRUE(size == 0); + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + + memParser->Parse(tracePacket, timeStamp, clock); + memParser->Finish(); + delete memParser; + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(0 == eventCount); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/htrace_sys_mem_parser_test.cpp b/host/trace_streamer/test/unittest/htrace_sys_mem_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..560f22dbe331ca87bcca470a431dd6a7910b8647 --- /dev/null +++ b/host/trace_streamer/test/unittest/htrace_sys_mem_parser_test.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "htrace_mem_parser.h" +#include "parser/common_types.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; + +namespace SysTuning { +namespace TraceStreamer { +class HtraceSysMemParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() + { + if (access(dbPath_.c_str(), F_OK) == 0) { + remove(dbPath_.c_str()); + } + } + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; + const std::string dbPath_ = "/data/resource/out.db"; +}; + +/** + * @tc.name: ParseSysMemParseInputEmpty + * @tc.desc: Kernel memory parsing test, input empty + * @tc.type: FUNC + */ +HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseInputEmpty, TestSize.Level1) +{ + TS_LOGI("test12-1"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + SysMeminfo* mem = tracePacket.add_meminfo(); + EXPECT_TRUE(mem != nullptr); + int size = tracePacket.meminfo_size(); + EXPECT_TRUE(size == 1); + mem->set_key(SysMeminfoType::PMEM_MEM_TOTAL); + uint64_t value = random(); + mem->set_value(value); + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + + memParser->Parse(tracePacket, timeStamp, clock); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + tracePacket.clear_meminfo(); + delete memParser; + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); +} + +/** + * @tc.name: ParseSysMemParseNormal + * @tc.desc: Kernel memory parsing test normal + * @tc.type: FUNC + */ +HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseNormal, TestSize.Level1) +{ + TS_LOGI("test12-2"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + SysMeminfo* mem = tracePacket.add_meminfo(); + EXPECT_TRUE(mem != nullptr); + int size = tracePacket.meminfo_size(); + EXPECT_TRUE(size == 1); + mem->set_key(SysMeminfoType::PMEM_MEM_TOTAL); + uint64_t value = random(); + mem->set_value(value); + + mem = tracePacket.add_meminfo(); + EXPECT_TRUE(mem != nullptr); + size = tracePacket.meminfo_size(); + EXPECT_TRUE(size == 2); + mem->set_key(SysMeminfoType::PMEM_MEM_FREE); + uint64_t value2 = random(); + mem->set_value(value2); + + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + + memParser->Parse(tracePacket, timeStamp, clock); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + tracePacket.clear_meminfo(); + delete memParser; + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 2); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[1] == static_cast(value2)); +} + +/** + * @tc.name: ParseSysMemParseAbnomal + * @tc.desc: Kernel memory parsing test abnomal + * @tc.type: FUNC + */ +HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseAbnomal, TestSize.Level1) +{ + TS_LOGI("test12-3"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + SysMeminfo* mem = tracePacket.add_meminfo(); + EXPECT_TRUE(mem != nullptr); + int size = tracePacket.meminfo_size(); + EXPECT_TRUE(size == 1); + mem->set_key(SysMeminfoType::PMEM_MEM_TOTAL); + uint64_t value = random(); + mem->set_value(value); + + mem = tracePacket.add_meminfo(); + EXPECT_TRUE(mem != nullptr); + size = tracePacket.meminfo_size(); + EXPECT_TRUE(size == 2); + mem->set_key(static_cast(199999)); // invalid data + uint64_t value2 = random(); + mem->set_value(value2); + + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + + memParser->Parse(tracePacket, timeStamp, clock); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + tracePacket.clear_meminfo(); + delete memParser; + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_MEMORY, STAT_EVENT_DATA_INVALID); + EXPECT_TRUE(1 == eventCount); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); +} + +/** + * @tc.name: ParseSysMemParseMutiNomal + * @tc.desc: Kernel memory parsing test with muti nomal + * @tc.type: FUNC + */ +HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseMutiNomal, TestSize.Level1) +{ + TS_LOGI("test12-4"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + SysMeminfo* mem = tracePacket.add_meminfo(); + EXPECT_TRUE(mem != nullptr); + int size = tracePacket.meminfo_size(); + EXPECT_TRUE(size == 1); + mem->set_key(SysMeminfoType::PMEM_CMA_FREE); + uint64_t value = random(); + mem->set_value(value); + + mem = tracePacket.add_meminfo(); + EXPECT_TRUE(mem != nullptr); + size = tracePacket.meminfo_size(); + EXPECT_TRUE(size == 2); + mem->set_key(SysMeminfoType::SysMeminfoType_INT_MIN_SENTINEL_DO_NOT_USE_); + uint64_t value2 = random(); + mem->set_value(value2); + + mem = tracePacket.add_meminfo(); + EXPECT_TRUE(mem != nullptr); + size = tracePacket.meminfo_size(); + EXPECT_TRUE(size == 3); + mem->set_key(SysMeminfoType::SysMeminfoType_INT_MAX_SENTINEL_DO_NOT_USE_); + uint64_t value3 = random(); + mem->set_value(value3); + + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + + memParser->Parse(tracePacket, timeStamp, clock); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + tracePacket.clear_meminfo(); + delete memParser; + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_MEMORY, STAT_EVENT_DATA_INVALID); + EXPECT_TRUE(2 == eventCount); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); +} + +/** + * @tc.name: ParseSysMemParseWithRandomValue + * @tc.desc: Kernel memory parsing test, input a random reasonable value + * @tc.type: FUNC + */ +HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseWithRandomValue, TestSize.Level1) +{ + TS_LOGI("test12-5"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + + std::map sysMemValueMap_ = {}; + for (auto i = 0; i < SysMeminfoType::PMEM_CMA_FREE + 1; i++) { + uint64_t value = random(); + sysMemValueMap_.insert(std::make_pair(static_cast(i), value)); + SysMeminfo* mem = tracePacket.add_meminfo(); + EXPECT_TRUE(mem != nullptr); + mem->set_key(static_cast(i)); + mem->set_value(value); + int size = tracePacket.meminfo_size(); + EXPECT_TRUE(size == i + 1); + } + + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + + memParser->Parse(tracePacket, timeStamp, clock); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + tracePacket.clear_meminfo(); + delete memParser; + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + + for (auto i = 0; i < SysMeminfoType::PMEM_CMA_FREE + 1; i++) { + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[i] == + sysMemValueMap_.at(static_cast(i))); + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/htrace_sys_vmem_parser_test.cpp b/host/trace_streamer/test/unittest/htrace_sys_vmem_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..da4d4064035473b28618a5976efe65ca17cc045f --- /dev/null +++ b/host/trace_streamer/test/unittest/htrace_sys_vmem_parser_test.cpp @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "htrace_mem_parser.h" +#include "parser/common_types.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; + +namespace SysTuning { +namespace TraceStreamer { +class HtraceSysVMemParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() + { + if (access(dbPath_.c_str(), F_OK) == 0) { + remove(dbPath_.c_str()); + } + } + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; + const std::string dbPath_ = "/data/resource/out.db"; +}; + +/** + * @tc.name: ParseSysMemParseWithRandomValue + * @tc.desc: Virtual memory parsing test, input a random reasonable value + * @tc.type: FUNC + */ +HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemParse, TestSize.Level1) +{ + TS_LOGI("test13-1"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + SysVMeminfo* vmem = tracePacket.add_vmeminfo(); + EXPECT_TRUE(vmem != nullptr); + int size = tracePacket.vmeminfo_size(); + EXPECT_TRUE(size == 1); + vmem->set_key(SysVMeminfoType::VMEMINFO_UNSPECIFIED); + uint64_t value = random(); + vmem->set_value(value); + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + + memParser->Parse(tracePacket, timeStamp, clock); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + tracePacket.clear_meminfo(); + delete memParser; + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); +} + +/** + * @tc.name: ParseSysVMemNomal + * @tc.desc: Virtual memory parsing test nomal + * @tc.type: FUNC + */ +HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemNomal, TestSize.Level1) +{ + TS_LOGI("test13-2"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + SysVMeminfo* vmem = tracePacket.add_vmeminfo(); + EXPECT_TRUE(vmem != nullptr); + int size = tracePacket.vmeminfo_size(); + EXPECT_TRUE(size == 1); + vmem->set_key(SysVMeminfoType::VMEMINFO_NR_FREE_PAGES); + uint64_t value = random(); + vmem->set_value(value); + + vmem = tracePacket.add_vmeminfo(); + EXPECT_TRUE(vmem != nullptr); + size = tracePacket.vmeminfo_size(); + EXPECT_TRUE(size == 2); + vmem->set_key(SysVMeminfoType::VMEMINFO_NR_ALLOC_BATCH); + uint64_t value2 = random(); + vmem->set_value(value2); + + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + + memParser->Parse(tracePacket, timeStamp, clock); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + tracePacket.clear_meminfo(); + delete memParser; + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 2); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[1] == static_cast(value2)); +} + +/** + * @tc.name: ParseSysVMemAbnomal + * @tc.desc: Virtual memory parsing test abnomal + * @tc.type: FUNC + */ +HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemAbnomal, TestSize.Level1) +{ + TS_LOGI("test13-3"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + SysVMeminfo* vmem = tracePacket.add_vmeminfo(); + EXPECT_TRUE(vmem != nullptr); + int size = tracePacket.vmeminfo_size(); + EXPECT_TRUE(size == 1); + vmem->set_key(SysVMeminfoType::VMEMINFO_NR_FREE_PAGES); + uint64_t value = random(); + vmem->set_value(value); + + vmem = tracePacket.add_vmeminfo(); + EXPECT_TRUE(vmem != nullptr); + size = tracePacket.vmeminfo_size(); + EXPECT_TRUE(size == 2); + uint64_t value2 = random(); + vmem->set_value(value2); + + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + + memParser->Parse(tracePacket, timeStamp, clock); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + tracePacket.clear_meminfo(); + delete memParser; + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_DATA_INVALID); + EXPECT_TRUE(0 == eventCount); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 2); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); +} + +/** + * @tc.name: ParseSysVMemWithMutiNomal + * @tc.desc: Virtual memory parsing test with muti nomal + * @tc.type: FUNC + */ +HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemWithMutiNomal, TestSize.Level1) +{ + TS_LOGI("test13-4"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + SysVMeminfo* vmem = tracePacket.add_vmeminfo(); + EXPECT_TRUE(vmem != nullptr); + int size = tracePacket.vmeminfo_size(); + EXPECT_TRUE(size == 1); + vmem->set_key(SysVMeminfoType::VMEMINFO_WORKINGSET_RESTORE); + uint64_t value = random(); + vmem->set_value(value); + + vmem = tracePacket.add_vmeminfo(); + EXPECT_TRUE(vmem != nullptr); + size = tracePacket.vmeminfo_size(); + EXPECT_TRUE(size == 2); + vmem->set_key(SysVMeminfoType::SysVMeminfoType_INT_MIN_SENTINEL_DO_NOT_USE_); + uint64_t value2 = random(); + vmem->set_value(value2); + + vmem = tracePacket.add_vmeminfo(); + EXPECT_TRUE(vmem != nullptr); + size = tracePacket.vmeminfo_size(); + EXPECT_TRUE(size == 3); + vmem->set_key(SysVMeminfoType::SysVMeminfoType_INT_MAX_SENTINEL_DO_NOT_USE_); + uint64_t value3 = random(); + vmem->set_value(value3); + + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + + memParser->Parse(tracePacket, timeStamp, clock); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + tracePacket.clear_vmeminfo(); + delete memParser; + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_DATA_INVALID); + EXPECT_TRUE(2 == eventCount); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); +} + +/** + * @tc.name: ParseSysVMemWithRandomValue + * @tc.desc: Virtual memory parsing test, input a random reasonable value + * @tc.type: FUNC + */ +HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemWithRandomValue, TestSize.Level1) +{ + TS_LOGI("test13-5"); + HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + + std::map sysVMemValueMap_ = {}; + for (auto i = 0; i < SysVMeminfoType::VMEMINFO_WORKINGSET_RESTORE + 1; i++) { + uint64_t value = random(); + sysVMemValueMap_.insert(std::make_pair(static_cast(i), value)); + SysVMeminfo* vmem = tracePacket.add_vmeminfo(); + EXPECT_TRUE(vmem != nullptr); + vmem->set_key(static_cast(i)); + vmem->set_value(value); + int size = tracePacket.vmeminfo_size(); + EXPECT_TRUE(size == i + 1); + } + + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_REALTIME; + + memParser->Parse(tracePacket, timeStamp, clock); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + tracePacket.clear_vmeminfo(); + delete memParser; + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + + for (auto i = 0; i < SysVMeminfoType::VMEMINFO_WORKINGSET_RESTORE + 1; i++) { + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[i] == + sysVMemValueMap_.at(static_cast(i))); + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/irq_filter_test.cpp b/host/trace_streamer/test/unittest/irq_filter_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..33ebaa9e4f9b24f46908f84eb761b0a35f9f3565 --- /dev/null +++ b/host/trace_streamer/test/unittest/irq_filter_test.cpp @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "args_filter.h" +#include "irq_filter.h" +#include "slice_filter.h" +#include "stat_filter.h" +#include "ts_common.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class IrqFilterTest : public ::testing::Test { +public: + void SetUp() + { + streamFilters_.argsFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + streamFilters_.irqFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + streamFilters_.sliceFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + streamFilters_.statFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + streamFilters_.statFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + } + + void TearDown() {} + +public: + TraceStreamerFilters streamFilters_; + TraceDataCache traceDataCache_; +}; + +/** + * @tc.name: IrqHandlerEntryTest + * @tc.desc: IrqHandlerEntry Normal TEST + * @tc.type: FUNC + */ +HWTEST_F(IrqFilterTest, IrqHandlerEntryTest, TestSize.Level1) +{ + TS_LOGI("test10-1"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + DataIndex nameId1 = 1; + streamFilters_.irqFilter_->IrqHandlerEntry(ts1, cpu1, nameId1); // IrqHandlerEntry + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); +} + +/** + * @tc.name: IrqHandlerEntryTestNotMatch + * @tc.desc: Test two interrupts, only start, no end + * @tc.type: FUNC + */ +HWTEST_F(IrqFilterTest, IrqHandlerEntryTestNotMatch, TestSize.Level1) +{ + TS_LOGI("test10-2"); + int64_t ts1 = 120; + uint32_t cpu1 = 1; + DataIndex nameId1 = 1; + streamFilters_.irqFilter_->IrqHandlerEntry(ts1, cpu1, nameId1); // IrqHandlerEntry + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + ts1 = 110; + uint32_t irqRet = 1; + streamFilters_.irqFilter_->IrqHandlerEntry(ts1, cpu1, irqRet); // IrqHandlerEntry + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 2); + // TRACE_EVENT_IRQ_HANDLER_ENTRY STAT_EVENT_DATA_LOST + auto eventCount = + traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_IRQ_HANDLER_ENTRY, STAT_EVENT_DATA_LOST); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: IrqHandlerExitTestEmpty + * @tc.desc:Interrupt only ends, not starts + * @tc.type: FUNC + */ +HWTEST_F(IrqFilterTest, IrqHandlerExitTestEmpty, TestSize.Level1) +{ + TS_LOGI("test10-3"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + uint32_t ret = 1; // 1 for handled, else for unhandled + streamFilters_.irqFilter_->IrqHandlerExit(ts1, cpu1, ret); // IrqHandlerExit + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 0); + // TRACE_EVENT_IRQ_HANDLER_EXIT STAT_EVENT_NOTMATCH + auto eventCount = + traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_IRQ_HANDLER_EXIT, STAT_EVENT_NOTMATCH); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: IrqHandlerEnterAndExitTest + * @tc.desc: Interrupt normal start and end + * @tc.type: FUNC + */ +HWTEST_F(IrqFilterTest, IrqHandlerEnterAndExitTest, TestSize.Level1) +{ + TS_LOGI("test10-4"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + DataIndex nameId1 = 1; + streamFilters_.irqFilter_->IrqHandlerEntry(ts1, cpu1, nameId1); // IrqHandlerEntry + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + uint32_t irqRet = 1; // 1 for handled, else for unhandled + streamFilters_.irqFilter_->IrqHandlerExit(ts1, cpu1, irqRet); // IrqHandlerExit + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().values_[0] == + static_cast(streamFilters_.irqFilter_->irqHandled_)); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().names_[0] == streamFilters_.irqFilter_->irqRet_); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().argset_[0] == 0); +} + +/** + * @tc.name: IrqHandlerDoubleEnterAndExitTest + * @tc.desc: Interrupt normal test, 2 interrupts and exits + * @tc.type: FUNC + */ +HWTEST_F(IrqFilterTest, IrqHandlerDoubleEnterAndExitTest, TestSize.Level1) +{ + TS_LOGI("test10-4-2"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + DataIndex nameId1 = 1; + streamFilters_.irqFilter_->IrqHandlerEntry(ts1, cpu1, nameId1); // IrqHandlerEntry + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + uint32_t ret = 1; // 1 for handled, else for unhandled + cpu1 = 2; + ts1 = 150; + streamFilters_.irqFilter_->IrqHandlerExit(ts1, cpu1, ret); // IrqHandlerExit + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_IRQ_HANDLER_EXIT, + STAT_EVENT_NOTMATCH) == 1); + cpu1 = 1; + ts1 = 200; + streamFilters_.irqFilter_->IrqHandlerExit(ts1, cpu1, ret); // IrqHandlerExit + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); +} + +/** + * @tc.name: IrqHandlerTripleEnterAndExitTest + * @tc.desc: Interrupt normal test, 3 interrupts and exits + * @tc.type: FUNC + */ +HWTEST_F(IrqFilterTest, IrqHandlerTripleEnterAndExitTest, TestSize.Level1) +{ + TS_LOGI("test10-5"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + DataIndex nameId1 = 1; + streamFilters_.irqFilter_->IrqHandlerEntry(ts1, cpu1, nameId1); // IrqHandlerEntry + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + uint32_t ret = 1; // 1 for handled, else for unhandled + ts1 = 150; + streamFilters_.irqFilter_->IrqHandlerExit(ts1, cpu1, ret); // IrqHandlerExit + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + // check args + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + + ts1 = 200; + cpu1 = 1; + nameId1 = 1; + streamFilters_.irqFilter_->IrqHandlerEntry(ts1, cpu1, nameId1); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 2); + ret = 1; // 1 for handled, else for unhandled + ts1 = 250; + streamFilters_.irqFilter_->IrqHandlerExit(ts1, cpu1, ret); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 2); + // check args + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[1] == 1); +} + +/** + * @tc.name: SoftIrqEntryTest + * @tc.desc: Soft interrupt normal test + * @tc.type: FUNC + */ +HWTEST_F(IrqFilterTest, SoftIrqEntryTest, TestSize.Level1) +{ + TS_LOGI("test10-6"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + uint32_t vec = 1; + streamFilters_.irqFilter_->SoftIrqEntry(ts1, cpu1, vec); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); +} + +/** + * @tc.name: SoftIrqEntryNotMatch + * @tc.desc: The soft interrupts do not match. The two interrupts have only the beginning and no end + * @tc.type: FUNC + */ +HWTEST_F(IrqFilterTest, SoftIrqEntryNotMatch, TestSize.Level1) +{ + TS_LOGI("test10-7"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + uint32_t vec = 1; + streamFilters_.irqFilter_->SoftIrqEntry(ts1, cpu1, vec); // SoftIrqEntry + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + ts1 = 150; + streamFilters_.irqFilter_->SoftIrqEntry(ts1, cpu1, vec); // SoftIrqEntry + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 2); + EXPECT_TRUE( + traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_ENTRY, STAT_EVENT_DATA_LOST) == 1); +} + +/** + * @tc.name: SoftIrqExitEmptyTest + * @tc.desc: The soft interrupt only ends without starting + * @tc.type: FUNC + */ +HWTEST_F(IrqFilterTest, SoftIrqExitEmptyTest, TestSize.Level1) +{ + TS_LOGI("test10-8"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + uint32_t vec = 1; + streamFilters_.irqFilter_->SoftIrqExit(ts1, cpu1, vec); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 0); + EXPECT_TRUE( + traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 1); +} + +/** + * @tc.name: SoftIrqTest + * @tc.desc: The soft interrupt normal test + * @tc.type: FUNC + */ +HWTEST_F(IrqFilterTest, SoftIrqTest, TestSize.Level1) +{ + TS_LOGI("test10-9"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + uint32_t vec = 1; + streamFilters_.irqFilter_->SoftIrqEntry(ts1, cpu1, vec); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + ts1 = 150; + uint32_t irqRet = 1; + streamFilters_.irqFilter_->SoftIrqExit(ts1, cpu1, irqRet); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 1); + printf("%lld\n", traceDataCache_.GetConstArgSetData().values_[0]); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().values_[0] == + static_cast(streamFilters_.irqFilter_->irqActionNameIds_[irqRet])); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().names_[0] == streamFilters_.irqFilter_->irqRet_); + EXPECT_TRUE(traceDataCache_.GetConstArgSetData().argset_[0] == 0); +} + +/** + * @tc.name: SoftIrqTestWithIrqEntryAndExit + * @tc.desc: The soft interrupt normal test + * @tc.type: FUNC + */ +HWTEST_F(IrqFilterTest, SoftIrqTestWithIrqEntryAndExit, TestSize.Level1) +{ + TS_LOGI("test10-10"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + uint32_t vec = 1; + streamFilters_.irqFilter_->SoftIrqEntry(ts1, cpu1, vec); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + ts1 = 150; + cpu1 = 2; + streamFilters_.irqFilter_->SoftIrqExit(ts1, cpu1, vec); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE( + traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 1); +} + +/** + * @tc.name: SoftIrqTestOneEntryTwoNotMatchExit + * @tc.desc: The soft interrupt test with onece entry and twice Not Match exit + * @tc.type: FUNC + */ +HWTEST_F(IrqFilterTest, SoftIrqTestOneEntryTwoNotMatchExit, TestSize.Level1) +{ + TS_LOGI("test10-11"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + uint32_t vec = 1; + streamFilters_.irqFilter_->SoftIrqEntry(ts1, cpu1, vec); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + ts1 = 150; + cpu1 = 2; + streamFilters_.irqFilter_->SoftIrqExit(ts1, cpu1, vec); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE( + traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 1); + ts1 = 200; + cpu1 = 3; + streamFilters_.irqFilter_->SoftIrqExit(ts1, cpu1, vec); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE( + traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 2); +} + +/** + * @tc.name: SoftIrqTestWithSingleNotMatchExit + * @tc.desc: The soft interrupt test with single not Match Exit + * @tc.type: FUNC + */ +HWTEST_F(IrqFilterTest, SoftIrqTestWithSingleNotMatchExit, TestSize.Level1) +{ + TS_LOGI("test10-12"); + int64_t ts1 = 100; + uint32_t cpu1 = 1; + uint32_t vec = 1; + streamFilters_.irqFilter_->SoftIrqEntry(ts1, cpu1, vec); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + ts1 = 150; + cpu1 = 2; + streamFilters_.irqFilter_->SoftIrqExit(ts1, cpu1, vec); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE( + traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 1); + ts1 = 200; + cpu1 = 1; + streamFilters_.irqFilter_->SoftIrqExit(ts1, cpu1, vec); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE( + traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 1); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/measure_filter_test.cpp b/host/trace_streamer/test/unittest/measure_filter_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e20f9aeac0a862a6a9b81fb10064b606a80cf5e --- /dev/null +++ b/host/trace_streamer/test/unittest/measure_filter_test.cpp @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "filter_filter.h" +#include "measure_filter.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +constexpr int CPU_ID_0 = 0; +constexpr int CPU_ID_1 = 1; +constexpr std::string_view CPU_TYPE_0 = "cpu_idle"; +constexpr std::string_view CPU_TYPE_1 = "cpu_frequency"; +constexpr int INTERNAL_THREAD_ID_0 = 1; +constexpr int INTERNAL_THREAD_ID_1 = 2; +constexpr int INTERNAL_PROCESS_ID_0 = 1; +constexpr int INTERNAL_PROCESS_ID_1 = 2; +constexpr std::string_view TASK_NAME_0 = "softbus_server"; +constexpr std::string_view TASK_NAME_1 = "hiprofilerd"; + +class MeasureFilterTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; +}; + +/** + * @tc.name: ThreadMeasureFilter + * @tc.desc: Test whether the GetOrCreateFilterId interface generated filterid and threadmeasure Info is correct + * @tc.type: FUNC + */ +HWTEST_F(MeasureFilterTest, ThreadMeasureFilter, TestSize.Level1) +{ + TS_LOGI("test8-1"); + auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); + uint32_t filterId = + stream_.streamFilters_->threadMeasureFilter_->GetOrCreateFilterId(INTERNAL_THREAD_ID_0, nameIndex0); + EXPECT_TRUE(filterId == 0); + + auto nameIndex1 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_1); + filterId = stream_.streamFilters_->threadMeasureFilter_->GetOrCreateFilterId(INTERNAL_THREAD_ID_1, nameIndex1); + EXPECT_TRUE(filterId == 1); + + Filter* filterTable = stream_.traceDataCache_->GetFilterData(); + EXPECT_TRUE(filterTable->Size() == 2); + + ThreadMeasureFilter* threadMeasureTable = stream_.traceDataCache_->GetThreadMeasureFilterData(); + EXPECT_TRUE(threadMeasureTable->Size() == 2); + EXPECT_TRUE(threadMeasureTable->FilterIdData()[0] == 0); + EXPECT_TRUE(threadMeasureTable->FilterIdData()[1] == 1); + EXPECT_TRUE(threadMeasureTable->InternalTidData()[0] == INTERNAL_THREAD_ID_0); + EXPECT_TRUE(threadMeasureTable->InternalTidData()[1] == INTERNAL_THREAD_ID_1); +} + +/** + * @tc.name: ThreadFilter + * @tc.desc: Test whether the GetOrCreateFilterId interface generated filterid and thread Info is correct + * @tc.type: FUNC + */ +HWTEST_F(MeasureFilterTest, ThreadFilter, TestSize.Level1) +{ + TS_LOGI("test8-2"); + auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); + uint32_t filterId = stream_.streamFilters_->threadFilter_->GetOrCreateFilterId(INTERNAL_THREAD_ID_0, nameIndex0); + EXPECT_TRUE(filterId == 0); + + auto nameIndex1 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_1); + filterId = stream_.streamFilters_->threadFilter_->GetOrCreateFilterId(INTERNAL_THREAD_ID_1, nameIndex1); + EXPECT_TRUE(filterId == 1); + + Filter* filterTable = stream_.traceDataCache_->GetFilterData(); + EXPECT_TRUE(filterTable->Size() == 2); + + ThreadMeasureFilter* threadTable = stream_.traceDataCache_->GetThreadFilterData(); + EXPECT_TRUE(threadTable->Size() == 2); + EXPECT_TRUE(threadTable->FilterIdData()[0] == 0); + EXPECT_TRUE(threadTable->FilterIdData()[1] == 1); + EXPECT_TRUE(threadTable->InternalTidData()[0] == INTERNAL_THREAD_ID_0); + EXPECT_TRUE(threadTable->InternalTidData()[1] == INTERNAL_THREAD_ID_1); +} + +/** + * @tc.name: CpuFilter + * @tc.desc: Test GetOrCreateFilterId interface of class CpuFilter + * @tc.type: FUNC + */ +HWTEST_F(MeasureFilterTest, CpuFilter, TestSize.Level1) +{ + TS_LOGI("test8-3"); + auto nameIndex_0 = stream_.traceDataCache_->GetDataIndex(CPU_TYPE_0); + uint32_t filterId = stream_.streamFilters_->cpuMeasureFilter_->GetOrCreateFilterId(CPU_ID_0, nameIndex_0); + EXPECT_TRUE(filterId == 0); + + auto nameIndex_1 = stream_.traceDataCache_->GetDataIndex(CPU_TYPE_1); + filterId = stream_.streamFilters_->cpuMeasureFilter_->GetOrCreateFilterId(CPU_ID_1, nameIndex_1); + EXPECT_TRUE(filterId == 1); + + Filter* filterTable = stream_.traceDataCache_->GetFilterData(); + EXPECT_TRUE(filterTable->Size() == 2); + + CpuMeasureFilter* cpuMeasureTable = stream_.traceDataCache_->GetCpuMeasuresData(); + EXPECT_TRUE(cpuMeasureTable->Size() == 2); + EXPECT_TRUE(cpuMeasureTable->IdsData()[0] == 0); + EXPECT_TRUE(cpuMeasureTable->IdsData()[1] == 1); + EXPECT_TRUE(cpuMeasureTable->CpuData()[0] == CPU_ID_0); + EXPECT_TRUE(cpuMeasureTable->CpuData()[1] == CPU_ID_1); +} + +/** + * @tc.name: ProcessFilter + * @tc.desc: Test GetOrCreateFilterId interface of class ProcessFilter + * @tc.type: FUNC + */ +HWTEST_F(MeasureFilterTest, ProcessFilter, TestSize.Level1) +{ + TS_LOGI("test8-4"); + auto nameIndex_0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); + uint32_t filterId = + stream_.streamFilters_->processFilterFilter_->GetOrCreateFilterId(INTERNAL_PROCESS_ID_0, nameIndex_0); + EXPECT_TRUE(filterId == 0); + + auto nameIndex_1 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_1); + filterId = stream_.streamFilters_->processFilterFilter_->GetOrCreateFilterId(INTERNAL_PROCESS_ID_1, nameIndex_1); + EXPECT_TRUE(filterId == 1); + + Filter* filterTable = stream_.traceDataCache_->GetFilterData(); + EXPECT_TRUE(filterTable->Size() == 2); + + ProcessMeasureFilter* processFilterTable = stream_.traceDataCache_->GetProcessFilterData(); + EXPECT_TRUE(processFilterTable->Size() == 2); +} + +/** + * @tc.name: ClockRateFilter + * @tc.desc: Test GetOrCreateFilterId interface of class ClockRateFilter + * @tc.type: FUNC + */ +HWTEST_F(MeasureFilterTest, ClockRateFilter, TestSize.Level1) +{ + TS_LOGI("test8-5"); + auto nameIndex_0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); + uint32_t filterId = stream_.streamFilters_->clockRateFilter_->GetOrCreateFilterId(CPU_ID_0, nameIndex_0); + EXPECT_TRUE(filterId == 0); + + auto nameIndex_1 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_1); + filterId = stream_.streamFilters_->clockRateFilter_->GetOrCreateFilterId(CPU_ID_1, nameIndex_1); + EXPECT_TRUE(filterId == 1); + + Filter* filterTable = stream_.traceDataCache_->GetFilterData(); + EXPECT_TRUE(filterTable->Size() == 2); + + ClockEventData* clockEventTable = stream_.traceDataCache_->GetClockEventFilterData(); + EXPECT_TRUE(clockEventTable->Size() == 2); + EXPECT_TRUE(clockEventTable->CpusData()[0] == CPU_ID_0); + EXPECT_TRUE(clockEventTable->CpusData()[1] == CPU_ID_1); + EXPECT_TRUE(clockEventTable->NamesData()[0] == nameIndex_0); + EXPECT_TRUE(clockEventTable->NamesData()[1] == nameIndex_1); +} + +/** + * @tc.name: ClockEnableFilter + * @tc.desc: Test GetOrCreateFilterId interface of class ClockEnableFilter + * @tc.type: FUNC + */ +HWTEST_F(MeasureFilterTest, ClockEnableFilter, TestSize.Level1) +{ + TS_LOGI("test8-6"); + auto nameIndex_0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); + uint32_t filterId = stream_.streamFilters_->clockEnableFilter_->GetOrCreateFilterId(CPU_ID_0, nameIndex_0); + EXPECT_TRUE(filterId == 0); + + auto nameIndex_1 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_1); + filterId = stream_.streamFilters_->clockEnableFilter_->GetOrCreateFilterId(CPU_ID_1, nameIndex_1); + EXPECT_TRUE(filterId == 1); + + Filter* filterTable = stream_.traceDataCache_->GetFilterData(); + EXPECT_TRUE(filterTable->Size() == 2); + + ClockEventData* clockEventTable = stream_.traceDataCache_->GetClockEventFilterData(); + EXPECT_TRUE(clockEventTable->Size() == 2); + EXPECT_TRUE(clockEventTable->CpusData()[0] == CPU_ID_0); + EXPECT_TRUE(clockEventTable->CpusData()[1] == CPU_ID_1); + EXPECT_TRUE(clockEventTable->NamesData()[0] == nameIndex_0); + EXPECT_TRUE(clockEventTable->NamesData()[1] == nameIndex_1); +} + +/** + * @tc.name: ClockDisableFilter + * @tc.desc: Test GetOrCreateFilterId interface of class ClockDisableFilter + * @tc.type: FUNC + */ +HWTEST_F(MeasureFilterTest, ClockDisableFilter, TestSize.Level1) +{ + TS_LOGI("test8-7"); + auto nameIndex_0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); + uint32_t filterId = stream_.streamFilters_->clockDisableFilter_->GetOrCreateFilterId(CPU_ID_0, nameIndex_0); + EXPECT_TRUE(filterId == 0); + + auto nameIndex_1 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_1); + filterId = stream_.streamFilters_->clockDisableFilter_->GetOrCreateFilterId(CPU_ID_1, nameIndex_1); + EXPECT_TRUE(filterId == 1); + + Filter* filterTable = stream_.traceDataCache_->GetFilterData(); + EXPECT_TRUE(filterTable->Size() == 2); + + ClockEventData* clockEventTable = stream_.traceDataCache_->GetClockEventFilterData(); + EXPECT_TRUE(clockEventTable->Size() == 2); + EXPECT_TRUE(clockEventTable->CpusData()[0] == CPU_ID_0); + EXPECT_TRUE(clockEventTable->CpusData()[1] == CPU_ID_1); + EXPECT_TRUE(clockEventTable->NamesData()[0] == nameIndex_0); + EXPECT_TRUE(clockEventTable->NamesData()[1] == nameIndex_1); +} + +/** + * @tc.name: MeasureFilterTest + * @tc.desc: Test GetOrCreateFilterId interface of class MeasureFilterTest + * @tc.type: FUNC + */ +HWTEST_F(MeasureFilterTest, MeasureFilterTest, TestSize.Level1) +{ + TS_LOGI("test8-8"); + uint64_t itid = 1; + const std::string_view MEASURE_ITEM_NAME = "mem_rss"; + auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME); + auto threadMeasureFilter = stream_.streamFilters_->processMeasureFilter_.get(); + threadMeasureFilter->AppendNewMeasureData(itid, nameIndex0, 168758682476000, 1200); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); +} + +/** + * @tc.name: MeasureFilterAddMultiMemToSingleThread + * @tc.desc: Test GetOrCreateFilterId interface of class MeasureFilterTest, Adding multiple memory information tests to + * the same thread + * @tc.type: FUNC + */ +HWTEST_F(MeasureFilterTest, MeasureFilterAddMultiMemToSingleThread, TestSize.Level1) +{ + TS_LOGI("test8-9"); + uint64_t itid = 1; + auto threadMeasureFilter = stream_.streamFilters_->processMeasureFilter_.get(); + const std::string_view MEASURE_ITEM_NAME = "mem_rss"; + auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME); + threadMeasureFilter->AppendNewMeasureData(itid, nameIndex0, 168758682476000, 1200); + const std::string_view MEASURE_ITEM_NAME2 = "mem_vm"; + auto nameIndex1 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME2); + threadMeasureFilter->AppendNewMeasureData(itid, nameIndex1, 168758682477000, 9200); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 2); +} + +/** + * @tc.name: MeasureFilterAddMultiMemToMultiThread + * @tc.desc: Test GetOrCreateFilterId interface of class MeasureFilterTest, Adding multiple memory information to multi + * thread + * @tc.type: FUNC + */ +HWTEST_F(MeasureFilterTest, MeasureFilterAddMultiMemToMultiThread, TestSize.Level1) +{ + TS_LOGI("test8-10"); + uint64_t itid = 1; + uint64_t itid2 = 2; + auto threadMeasureFilter = stream_.streamFilters_->processMeasureFilter_.get(); + const std::string_view MEASURE_ITEM_NAME = "mem_rss"; + auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME); + threadMeasureFilter->AppendNewMeasureData(itid, nameIndex0, 168758682476000, 1200); + const std::string_view MEASURE_ITEM_NAME2 = "mem_vm"; + auto nameIndex1 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME2); + threadMeasureFilter->AppendNewMeasureData(itid2, nameIndex1, 168758682477000, 9200); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 2); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == 1200); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[1] == 9200); +} + +/** + * @tc.name: MeasureFilterAddPerfclLfMux + * @tc.desc: Add perfcl_ lf_mux status test + * @tc.type: FUNC + */ +HWTEST_F(MeasureFilterTest, MeasureFilterAddPerfclLfMux, TestSize.Level1) +{ + TS_LOGI("test8-11"); + uint64_t cpuId = 1; + int64_t state = 0; + auto threadMeasureFilter = stream_.streamFilters_->clockDisableFilter_.get(); + const std::string_view MEASURE_ITEM_NAME = "perfcl_lf_mux"; + auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME); + threadMeasureFilter->AppendNewMeasureData(cpuId, nameIndex0, 168758682476000, state); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == state); +} + +/** + * @tc.name: MeasureFilterAddPerfclLfMux + * @tc.desc: Add perfcl_pll status test + * @tc.type: FUNC + */ +HWTEST_F(MeasureFilterTest, MeasureFilterAddPerfclPll, TestSize.Level1) +{ + TS_LOGI("test8-12"); + uint64_t cpuId = 1; + int64_t state = 1747200000; + auto threadMeasureFilter = stream_.streamFilters_->clockRateFilter_.get(); + const std::string_view MEASURE_ITEM_NAME = "perfcl_pll"; + auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME); + threadMeasureFilter->AppendNewMeasureData(cpuId, nameIndex0, 168758682476000, state); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == state); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/parser_test.cpp b/host/trace_streamer/test/unittest/parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f6511fb83eb82c6528ca4c3e238377ab0be458a5 --- /dev/null +++ b/host/trace_streamer/test/unittest/parser_test.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "file.h" +#include "trace_streamer_selector.h" +constexpr size_t G_FILE_PERMISSION = 664; + +using namespace testing::ext; +using namespace SysTuning; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class ParserTest : public testing::Test { +protected: + static void SetUpTestCase() {} + static void TearDownTestCase() {} +}; + +/** + * @tc.name: BytraceParserTest + * @tc.desc: Test bytrace parsing TXT file to export database + * @tc.type: FUNC + */ +HWTEST_F(ParserTest, BytraceParserTest, TestSize.Level1) +{ + TS_LOGI("test9-1"); + const std::string tracePath = "/data/resource/ut_bytrace_input_full.txt"; + const std::string utGoldDb = "/data/resource/ut_bytrace_input_full_gold.db"; + const std::string dbPath = "/data/resource/out_db1.db"; + constexpr size_t readSize = 1024 * 1024; + constexpr uint32_t lineLength = 256; + + if (access(tracePath.c_str(), F_OK) == 0) { + std::unique_ptr ta = + std::make_unique(); + ta->EnableMetaTable(false); + ta->SetCleanMode(false); + int fd(base::OpenFile(tracePath, O_RDONLY, G_FILE_PERMISSION)); + while (true) { + std::unique_ptr buf = std::make_unique(std::move(readSize)); + auto rsize = base::Read(fd, buf.get(), readSize); + if (rsize == 0) { + break; + } + if (rsize < 0) { + TS_LOGD("Reading trace file failed (errno: %d, %s)", errno, strerror(errno)); + break; + } + if (!ta->ParseTraceDataSegment(std::move(buf), rsize)) { + break; + }; + } + ta->WaitForParserEnd(); + close(fd); + ta->ExportDatabase(dbPath); + ta->Clear(); + EXPECT_TRUE(access(dbPath.c_str(), F_OK) == 0); + } else { + EXPECT_TRUE(false); + } + + if (access(utGoldDb.c_str(), F_OK) == 0) { + FILE* file1 = nullptr; + FILE* file2 = nullptr; + char line1[lineLength]; + char line2[lineLength]; + const std::string command1 = "md5sum /data/resource/ut_bytrace_input_full_gold.db"; + const std::string md5DbPath = "md5sum "+ dbPath; + file1 = popen(command1.c_str(), "r"); + file2 = popen(md5DbPath.c_str(), "r"); + if (file1 && file2) { + if (fgets(line1, lineLength, file1) != nullptr && fgets(line2, lineLength, file2) != nullptr) { + std::string str1(line1); + std::string str2(line2); + str1 = str1.substr(0, str1.find_first_of(' ')); + str2 = str2.substr(0, str2.find_first_of(' ')); + EXPECT_TRUE(str1.compare(str2) == 0); + } + } + } else { + EXPECT_TRUE(false); + } + + if (access(dbPath.c_str(), F_OK) == 0) { + remove(dbPath.c_str()); + } +} + +/** + * @tc.name: HtraceParserTest + * @tc.desc: Test htrace parsing binary file export database + * @tc.type: FUNC + */ +HWTEST_F(ParserTest, HtraceParserTest, TestSize.Level1) +{ + TS_LOGI("test9-2"); + const std::string tracePath = "/data/resource/htrace.bin"; + const std::string utGoldDb = "/data/resource/htrace_gold.db"; + const std::string dbPath = "/data/resource/out_db2.db"; + constexpr size_t readSize = 1024; + constexpr uint32_t lineLength = 256; + + if (access(tracePath.c_str(), F_OK) == 0) { + std::unique_ptr ta = + std::make_unique(); + ta->EnableMetaTable(false); + ta->SetCleanMode(false); + int fd(base::OpenFile(tracePath, O_RDONLY, G_FILE_PERMISSION)); + while (true) { + std::unique_ptr buf = std::make_unique(std::move(readSize)); + auto rsize = base::Read(fd, buf.get(), readSize); + + if (rsize == 0) { + break; + } + if (rsize < 0) { + TS_LOGD("Reading trace file over (errno: %d, %s)", errno, strerror(errno)); + break; + } + if (!ta->ParseTraceDataSegment(std::move(buf), rsize)) { + break; + }; + } + ta->WaitForParserEnd(); + close(fd); + ta->ExportDatabase(dbPath); + ta->Clear(); + EXPECT_TRUE(access(dbPath.c_str(), F_OK) == 0); + } else { + EXPECT_TRUE(false); + } + + if (access(utGoldDb.c_str(), F_OK) == 0) { + FILE* file1 = nullptr; + FILE* file2 = nullptr; + char line1[lineLength]; + char line2[lineLength]; + const std::string command1 = "md5sum /data/resource/htrace_gold.db"; + const std::string md5DbPath = "md5sum "+ dbPath; + file1 = popen(command1.c_str(), "r"); + file2 = popen(md5DbPath.c_str(), "r"); + if (file1 && file2) { + if (fgets(line1, lineLength, file1) != nullptr && fgets(line2, lineLength, file2) != nullptr) { + std::string str1(line1); + std::string str2(line2); + str1 = str1.substr(0, str1.find_first_of(' ')); + str2 = str2.substr(0, str2.find_first_of(' ')); + EXPECT_TRUE(str1.compare(str2) == 0); + } + } + } else { + EXPECT_TRUE(false); + } + + if (access(dbPath.c_str(), F_OK) == 0) { + remove(dbPath.c_str()); + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/process_filter_test.cpp b/host/trace_streamer/test/unittest/process_filter_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db31d5eb6d3808d8cb6fc04ba17995904452ca3d --- /dev/null +++ b/host/trace_streamer/test/unittest/process_filter_test.cpp @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "process_filter.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class ProcessFilterTest : public ::testing::Test { +public: + void SetUp() + { + streamFilters_.processFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + } + + void TearDown() {} + +public: + TraceStreamerFilters streamFilters_; + TraceDataCache traceDataCache_; +}; + +/** + * @tc.name: UpdateOrCreateThread + * @tc.desc: Test UpdateOrCreateThread interface + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateThread, TestSize.Level1) +{ + TS_LOGI("test10-1"); + uint64_t ts = 168758662877000; + uint32_t tid = 2716; + uint32_t iTid0 = streamFilters_.processFilter_->UpdateOrCreateThread(ts, tid); + EXPECT_TRUE(iTid0 == 1); + + uint32_t tid2 = 2519; + uint32_t iTid1 = streamFilters_.processFilter_->UpdateOrCreateThread(0, 2519); + EXPECT_TRUE(iTid1 == 2); + + Thread* thread = traceDataCache_.GetThreadData(iTid0); + EXPECT_TRUE(thread->tid_ == tid); + + thread = traceDataCache_.GetThreadData(iTid1); + EXPECT_TRUE(thread->tid_ == tid2); + EXPECT_TRUE(thread->internalPid_ == 0); +} + +/** + * @tc.name: UpdateOrCreateProcessWithName + * @tc.desc: Test UpdateOrCreateProcessWithName interface + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithName, TestSize.Level1) +{ + TS_LOGI("test10-2"); + uint32_t pid = 8629; + std::string_view processName = "RenderThread"; + uint32_t iPid0 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid, processName); + EXPECT_TRUE(iPid0 == 1); + + uint32_t pid2 = 8709; + uint32_t iPid1 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid2, processName); + EXPECT_TRUE(iPid1 == 2); + + Process* process = traceDataCache_.GetProcessData(iPid0); + EXPECT_TRUE(process->pid_ == pid); + + process = traceDataCache_.GetProcessData(iPid1); + EXPECT_TRUE(process->pid_ == pid2); +} + +/** + * @tc.name: UpdateOrCreateProcessWithNameSingleIpid + * @tc.desc: Test whether the internal PID of the generated single process is as expected. + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithNameSingleIpid, TestSize.Level1) +{ + TS_LOGI("test10-3"); + uint32_t pid = 8629; + std::string_view processName = "RenderThread"; + uint32_t iPid0 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid, processName); + EXPECT_TRUE(iPid0 == 1); +} + +/** + * @tc.name: UpdateOrCreateProcessWithNameMultiIpid + * @tc.desc: Test genarated multi ipid with UpdateOrCreateProcessWithName interface + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithNameMultiIpid, TestSize.Level1) +{ + TS_LOGI("test10-4"); + uint32_t pid = 8629; + std::string_view processName = "RenderThread"; + uint32_t iPid0 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid, processName); + EXPECT_TRUE(iPid0 == 1); + + uint32_t pid2 = 8709; + uint32_t iPid1 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid2, processName); + EXPECT_TRUE(iPid1 == 2); +} + +/** + * @tc.name: UpdateOrCreateProcessWithNameSinglePid + * @tc.desc: Test genarated single pid with UpdateOrCreateProcessWithName interface + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithNameSinglePid, TestSize.Level1) +{ + TS_LOGI("test10-5"); + uint32_t pid = 8629; + std::string_view processName = "RenderThread"; + uint32_t iPid0 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid, processName); + EXPECT_TRUE(iPid0 == 1); + + Process* process = traceDataCache_.GetProcessData(iPid0); + EXPECT_TRUE(process->pid_ == pid); +} + +/** + * @tc.name: UpdateOrCreateProcessWithNameMultiPid + * @tc.desc: est genarated multi pid with UpdateOrCreateProcessWithName interface + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithNameMultiPid, TestSize.Level1) +{ + TS_LOGI("test10-6"); + uint32_t pid = 8629; + std::string_view processName = "RenderThread"; + uint32_t iPid0 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid, processName); + EXPECT_TRUE(iPid0 == 1); + + uint32_t pid2 = 8709; + uint32_t iPid1 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid2, processName); + EXPECT_TRUE(iPid1 == 2); + + uint32_t pid3 = 87091; + uint32_t iPid2 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(87091, processName); + EXPECT_TRUE(iPid2 == 3); + + Process* process = traceDataCache_.GetProcessData(iPid0); + EXPECT_TRUE(process->pid_ == pid); + + process = traceDataCache_.GetProcessData(iPid1); + EXPECT_TRUE(process->pid_ == pid2); + + process = traceDataCache_.GetProcessData(iPid2); + EXPECT_TRUE(process->pid_ == pid3); +} + +/** + * @tc.name: UpdateOrCreateThreadWithName + * @tc.desc: Test UpdateOrCreateThreadWithName interface + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithName, TestSize.Level1) +{ + TS_LOGI("test10-7"); + uint64_t ts = 168758662957020; + uint32_t tid = 123; + std::string_view threadName = "RenderThread"; + uint32_t iTid0 = streamFilters_.processFilter_->UpdateOrCreateThreadWithName(ts, tid, threadName); + EXPECT_TRUE(iTid0 == 1); + uint64_t ts2 = 168758663957020; + uint32_t tid2 = 2519; + std::string_view threadName2 = "RenderThread2"; + uint32_t iTid1 = streamFilters_.processFilter_->UpdateOrCreateThreadWithName(ts2, tid2, threadName2); + EXPECT_TRUE(iTid1 == 2); + + Thread* thread = traceDataCache_.GetThreadData(iTid0); + EXPECT_TRUE(thread->tid_ == tid); + EXPECT_TRUE(thread->nameIndex_ == traceDataCache_.GetDataIndex(threadName)); + + thread = traceDataCache_.GetThreadData(iTid1); + EXPECT_TRUE(thread->tid_ == tid2); + EXPECT_TRUE(thread->internalPid_ == 0); + EXPECT_TRUE(thread->nameIndex_ == traceDataCache_.GetDataIndex(threadName2)); +} + +/** + * @tc.name: UpdateOrCreateThreadWithNameSingleItid + * @tc.desc: Test genarated single itid with UpdateOrCreateThreadWithName + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithNameSingleItid, TestSize.Level1) +{ + TS_LOGI("test10-8"); + uint64_t ts = 168758662957020; + uint32_t tid = 123; + std::string_view threadName = "RenderThread"; + uint32_t iTid0 = streamFilters_.processFilter_->UpdateOrCreateThreadWithName(ts, tid, threadName); + EXPECT_TRUE(iTid0 == 1); +} + +/** + * @tc.name: UpdateOrCreateThreadWithNameGenarateTidAndItid + * @tc.desc: Test genarated single itid and tid with UpdateOrCreateThreadWithName + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithNameGenarateTidAndItid, TestSize.Level1) +{ + TS_LOGI("test10-9"); + uint64_t ts = 168758662957020; + uint32_t tid = 123; + std::string_view threadName = "RenderThread2"; + uint32_t iTid0 = streamFilters_.processFilter_->UpdateOrCreateThreadWithName(ts, tid, threadName); + EXPECT_TRUE(iTid0 == 1); + Thread* thread = traceDataCache_.GetThreadData(iTid0); + EXPECT_TRUE(thread->tid_ == tid); + EXPECT_TRUE(thread->nameIndex_ == traceDataCache_.GetDataIndex(threadName)); +} + +/** + * @tc.name: UpdateOrCreateThreadWithNameMultiItid + * @tc.desc: Test genarate double itid with UpdateOrCreateThreadWithName interface + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithNameDoubleItid, TestSize.Level1) +{ + TS_LOGI("test10-10"); + uint64_t ts = 168758662957020; + uint32_t tid = 123; + std::string_view threadName = "RenderThread"; + uint32_t iTid0 = streamFilters_.processFilter_->UpdateOrCreateThreadWithName(ts, tid, threadName); + EXPECT_TRUE(iTid0 == 1); + uint64_t ts2 = 168758663957020; + uint32_t tid2 = 2519; + std::string_view threadName2 = "RenderThread2"; + uint32_t iTid1 = streamFilters_.processFilter_->UpdateOrCreateThreadWithName(ts2, tid2, threadName2); + EXPECT_TRUE(iTid1 == 2); + auto thread = traceDataCache_.GetThreadData(iTid1); + EXPECT_TRUE(thread->tid_ == tid2); + EXPECT_TRUE(thread->internalPid_ == 0); + EXPECT_TRUE(thread->nameIndex_ == traceDataCache_.GetDataIndex(threadName2)); +} + +/** + * @tc.name: UpdateOrCreateThreadWithNameTripleItid + * @tc.desc: Test genarate triple itid with UpdateOrCreateThreadWithName interface + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithNameTripleItid, TestSize.Level1) +{ + TS_LOGI("test10-11"); + uint64_t ts = 168758662957020; + uint32_t tid = 123; + std::string_view threadName = "RenderThread"; + uint32_t iTid0 = streamFilters_.processFilter_->UpdateOrCreateThreadWithName(ts, tid, threadName); + EXPECT_TRUE(iTid0 == 1); + uint64_t ts2 = 168758663957020; + uint32_t tid2 = 2519; + std::string_view threadName2 = "RenderThread2"; + uint32_t iTid1 = streamFilters_.processFilter_->UpdateOrCreateThreadWithName(ts2, tid2, threadName2); + EXPECT_TRUE(iTid1 == 2); + uint64_t ts3 = 168758663957020; + uint32_t tid3 = 25191; + std::string_view threadName3 = "RenderThread3"; + uint32_t iTid2 = streamFilters_.processFilter_->UpdateOrCreateThreadWithName(ts3, tid3, threadName3); + EXPECT_TRUE(iTid2 == 3); + auto thread = traceDataCache_.GetThreadData(iTid2); + EXPECT_TRUE(thread->tid_ == tid3); + EXPECT_TRUE(thread->internalPid_ == 0); + EXPECT_TRUE(thread->nameIndex_ == traceDataCache_.GetDataIndex(threadName3)); +} + +/** + * @tc.name: UpdateOrCreateThreadWithPidAndName + * @tc.desc: Test UpdateOrCreateThreadWithPidAndName interface + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithPidAndName, TestSize.Level1) +{ + TS_LOGI("test10-12"); + uint32_t tid = 869; + uint32_t pid = 123; + std::string_view threadName = "RenderThread"; + streamFilters_.processFilter_->UpdateOrCreateThreadWithPidAndName(tid, pid, threadName); + auto itid = streamFilters_.processFilter_->GetInternalTid(tid); + EXPECT_TRUE(itid != INVALID_ID); + + Thread* thread = traceDataCache_.GetThreadData(itid); + EXPECT_TRUE(thread->nameIndex_ == traceDataCache_.GetDataIndex(threadName)); +} + +/** + * @tc.name: UpdateOrCreateThreadWithPidAndNameAbnomal + * @tc.desc: Test UpdateOrCreateThreadWithPidAndName interface + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithPidAndNameAbnomal, TestSize.Level1) +{ + TS_LOGI("test10-13"); + uint32_t tid = 869; + uint32_t pid = 123; + std::string_view threadName = "RenderThread"; + streamFilters_.processFilter_->UpdateOrCreateThreadWithPidAndName(tid, pid, threadName); + uint32_t tid2 = 969; + auto itid = streamFilters_.processFilter_->GetInternalTid(tid2); + EXPECT_TRUE(itid == INVALID_ID); +} + +/** + * @tc.name: UpdateOrCreateThreadWithPidAndNameSingleItid + * @tc.desc: Test UpdateOrCreateThreadWithPidAndName interface + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithPidAndNameSingleItid, TestSize.Level1) +{ + TS_LOGI("test10-14"); + uint32_t tid = 869; + uint32_t pid = 123; + std::string_view threadName = "RenderThread"; + streamFilters_.processFilter_->UpdateOrCreateThreadWithPidAndName(tid, pid, threadName); + auto itid = streamFilters_.processFilter_->GetInternalPid(pid); + EXPECT_TRUE(itid != INVALID_ID); +} + +/** + * @tc.name: UpdateOrCreateThreadWithPidAndNameAbnomalPid + * @tc.desc: Test UpdateOrCreateThreadWithPidAndName interface + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithPidAndNameAbnomalPid, TestSize.Level1) +{ + TS_LOGI("test10-15"); + uint32_t tid = 869; + uint32_t pid = 123; + std::string_view threadName = "RenderThread"; + streamFilters_.processFilter_->UpdateOrCreateThreadWithPidAndName(tid, pid, threadName); + uint32_t pid2 = 124; + auto itid = streamFilters_.processFilter_->GetInternalPid(pid2); + EXPECT_TRUE(itid == INVALID_ID); +} + +/** + * @tc.name: UpdateThreadWithName + * @tc.desc: Test update thread name + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateThreadWithName, TestSize.Level1) +{ + TS_LOGI("test10-16"); + uint32_t tid = 869; + uint64_t timestamp = 168758662957020; + std::string_view threadName = "RenderThread"; + streamFilters_.processFilter_->UpdateOrCreateThread(timestamp, tid); + streamFilters_.processFilter_->UpdateOrCreateThreadWithName(timestamp, tid, threadName); + auto itid = streamFilters_.processFilter_->GetInternalTid(tid); + EXPECT_TRUE(itid != INVALID_ID); + Thread* thread = traceDataCache_.GetThreadData(itid); + EXPECT_TRUE(thread->nameIndex_ == traceDataCache_.GetDataIndex(threadName)); +} + +/** + * @tc.name: UpdateProcessWithName + * @tc.desc: Test update process name + * @tc.type: FUNC + */ +HWTEST_F(ProcessFilterTest, UpdateProcessWithName, TestSize.Level1) +{ + TS_LOGI("test10-17"); + uint32_t pid = 869; + uint64_t timestamp = 168758662957020; + std::string_view processName = "RenderProcess"; + auto ipid = streamFilters_.processFilter_->GetOrCreateInternalPid(timestamp, pid); + EXPECT_TRUE(ipid != INVALID_ID); + streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid, processName); + Process* process = traceDataCache_.GetProcessData(ipid); + EXPECT_TRUE(process->cmdLine_ == processName); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/slice_filter_test.cpp b/host/trace_streamer/test/unittest/slice_filter_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6846cba534403a421d6b0d6e40c8119f8c671add --- /dev/null +++ b/host/trace_streamer/test/unittest/slice_filter_test.cpp @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "filter_filter.h" +#include "measure_filter.h" +#include "process_filter.h" +#include "slice_filter.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class SliceFilterTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + TraceStreamerSelector stream_; +}; + +/** + * @tc.name: SliceTestOnceCall + * @tc.desc: Parse once method call stack + * @tc.type: FUNC + */ +HWTEST_F(SliceFilterTest, SliceTestOnceCall, TestSize.Level1) +{ + TS_LOGI("test1"); + uint64_t ts = 168758662957000; + uint64_t ts2 = 168758663011000; + + uint32_t pid1 = 2532; + uint32_t threadGroupId1 = 2519; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); + DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex("call_function_one"); + stream_.streamFilters_->sliceFilter_->BeginSlice(ts, pid1, threadGroupId1, cat, splitStrIndex); + stream_.streamFilters_->sliceFilter_->EndSlice(ts2, pid1, threadGroupId1); + auto slices = stream_.traceDataCache_->GetInternalSlicesData(); + EXPECT_TRUE(slices->Size() == 1); + EXPECT_TRUE(slices->DursData()[0] == ts2 - ts); +} + +/** + * @tc.name: SliceTestNestedTwoMethod + * @tc.desc: Parse Nested call stack of two methods + * @tc.type: FUNC + */ +HWTEST_F(SliceFilterTest, SliceTestNestedTwoMethod, TestSize.Level1) +{ + TS_LOGI("test2"); + uint64_t ts1 = 168758670506000; + uint32_t pid1 = 1298; + uint32_t threadGroupId1 = 1298; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); + DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex("call_function_one"); + stream_.streamFilters_->sliceFilter_->BeginSlice(ts1, pid1, threadGroupId1, cat, splitStrIndex); + splitStrIndex = stream_.traceDataCache_->GetDataIndex("call_function_two"); + uint64_t ts2 = 168758670523000; + stream_.streamFilters_->sliceFilter_->BeginSlice(ts2, pid1, threadGroupId1, cat, splitStrIndex); + uint64_t ts3 = 168758670720000; + stream_.streamFilters_->sliceFilter_->EndSlice(ts3, pid1, threadGroupId1); + uint64_t ts4 = 168758670732000; + stream_.streamFilters_->sliceFilter_->EndSlice(ts4, pid1, threadGroupId1); + auto slices = stream_.traceDataCache_->GetInternalSlicesData(); + EXPECT_TRUE(slices->Size() == 2); + EXPECT_TRUE(slices->DursData()[0] == ts4 - ts1); + EXPECT_TRUE(slices->DursData()[1] == ts3 - ts2); + EXPECT_TRUE(slices->Depths()[1] == 1); +} + +/** + * @tc.name: SliceTestNestedTwoMethodStackAndOneMethodStack + * @tc.desc: Parse Nested call stack of two methods and one method call stack + * @tc.type: FUNC + */ +HWTEST_F(SliceFilterTest, SliceTestNestedTwoMethodStackAndOneMethodStack, TestSize.Level1) +{ + TS_LOGI("test3"); + uint64_t ts1 = 168758663018000; + uint32_t pid1 = 2532; + uint32_t threadGroupId1 = 2519; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); + DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_one"); + stream_.streamFilters_->sliceFilter_->BeginSlice(ts1, pid1, threadGroupId1, cat, splitStrIndex); // slice 0 + splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_two_call_function_one"); + uint64_t ts2 = 168758663028000; + uint32_t pid2 = 2533; + uint32_t threadGroupId2 = 2529; + stream_.streamFilters_->sliceFilter_->BeginSlice(ts2, pid2, threadGroupId2, cat, splitStrIndex); + splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_two"); + uint64_t ts3 = 168758679303000; + stream_.streamFilters_->sliceFilter_->BeginSlice(ts3, pid1, threadGroupId1, cat, splitStrIndex); // slice 2 + // end thread_one_call_function_two + uint64_t ts4 = 168758682466000; + stream_.streamFilters_->sliceFilter_->EndSlice(ts4, pid1, threadGroupId1); + // end thread_one_call_function_one + uint64_t ts5 = 168758682476000; + stream_.streamFilters_->sliceFilter_->EndSlice(ts5, pid1, threadGroupId1); + // end thread_two_call_function_one slice 1 + uint64_t ts6 = 168758689323000; + stream_.streamFilters_->sliceFilter_->EndSlice(ts6, pid2, threadGroupId2); + auto slices = stream_.traceDataCache_->GetInternalSlicesData(); + EXPECT_TRUE(slices->Size() == 3); + EXPECT_TRUE(slices->DursData()[0] == ts5 - ts1); // slice 0 + EXPECT_TRUE(slices->Depths()[0] == 0); + EXPECT_TRUE(slices->DursData()[1] == ts6 - ts2); // slice 1 + EXPECT_TRUE(slices->Depths()[1] == 0); + EXPECT_TRUE(slices->DursData()[2] == ts4 - ts3); // slice 2 + EXPECT_TRUE(slices->Depths()[2] == 1); +} + +/** + * @tc.name: SliceTestWithoutBeginSlice + * @tc.desc: Test EndSlice without BeginSlice + * @tc.type: FUNC + */ +HWTEST_F(SliceFilterTest, SliceTestWithoutBeginSlice, TestSize.Level1) +{ + TS_LOGI("test3"); + uint64_t ts1 = 168758663018000; + uint32_t pid1 = 2532; + uint32_t threadGroupId1 = 2519; + stream_.streamFilters_->sliceFilter_->EndSlice(ts1, pid1, threadGroupId1); + auto slices = stream_.traceDataCache_->GetInternalSlicesData(); + EXPECT_TRUE(slices->Size() == 0); +} + +/** + * @tc.name: SliceTestWithMultiNestedCall + * @tc.desc: Parse multi nested call stack + * @tc.type: FUNC + */ +HWTEST_F(SliceFilterTest, SliceTestWithMultiNestedCall, TestSize.Level1) +{ + TS_LOGI("test3"); + uint64_t ts1 = 168758663018000; + uint32_t pid1 = 2532; + uint32_t threadGroupId1 = 2519; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); + DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_one"); + stream_.streamFilters_->sliceFilter_->BeginSlice(ts1, pid1, threadGroupId1, cat, splitStrIndex); // slice 0 + splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_two_call_function_one"); + uint64_t ts2 = 168758663028000; + uint32_t pid2 = 2533; + uint32_t threadGroupId2 = 2529; + stream_.streamFilters_->sliceFilter_->BeginSlice(ts2, pid2, threadGroupId2, cat, splitStrIndex); + splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_two"); + uint64_t ts3 = 168758679303000; + stream_.streamFilters_->sliceFilter_->BeginSlice(ts3, pid1, threadGroupId1, cat, splitStrIndex); // slice 2 + splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_two_call_function_two"); + uint64_t ts4 = 168758679312000; + stream_.streamFilters_->sliceFilter_->BeginSlice(ts4, pid2, threadGroupId2, cat, splitStrIndex); + splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_three"); + uint64_t ts5 = 168758679313000; + stream_.streamFilters_->sliceFilter_->BeginSlice(ts5, pid1, threadGroupId1, cat, splitStrIndex); // slice 4 + splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_two_call_function_three"); + uint64_t ts6 = 168758679323000; + stream_.streamFilters_->sliceFilter_->BeginSlice(ts6, pid2, threadGroupId2, cat, splitStrIndex); + // end thread_one_call_function_three + uint64_t ts7 = 168758682456000; + stream_.streamFilters_->sliceFilter_->EndSlice(ts7, pid1, threadGroupId1); + // end thread_one_call_function_two + uint64_t ts8 = 168758682466000; + stream_.streamFilters_->sliceFilter_->EndSlice(ts8, pid1, threadGroupId1); + // end thread_one_call_function_one + uint64_t ts9 = 168758682476000; + stream_.streamFilters_->sliceFilter_->EndSlice(ts9, pid1, threadGroupId1); + // end thread_two_call_function_three slice 5 + uint64_t ts10 = 168758679343000; + stream_.streamFilters_->sliceFilter_->EndSlice(ts10, pid2, threadGroupId2); + // end thread_two_call_function_two slice 3 + uint64_t ts11 = 168758679344000; + stream_.streamFilters_->sliceFilter_->EndSlice(ts11, pid2, threadGroupId2); + // end thread_two_call_function_one slice 1 + uint64_t ts12 = 168758689323000; + stream_.streamFilters_->sliceFilter_->EndSlice(ts12, pid2, threadGroupId2); + auto slices = stream_.traceDataCache_->GetInternalSlicesData(); + EXPECT_TRUE(slices->Size() == 6); + EXPECT_TRUE(slices->DursData()[0] == ts9 - ts1); // slice 0 + EXPECT_TRUE(slices->Depths()[0] == 0); + EXPECT_TRUE(slices->DursData()[1] == ts12 - ts2); // slice 1 + EXPECT_TRUE(slices->Depths()[1] == 0); + EXPECT_TRUE(slices->DursData()[2] == ts8 - ts3); // slice 2 + EXPECT_TRUE(slices->Depths()[2] == 1); + EXPECT_TRUE(slices->DursData()[3] == ts11 - ts4); // slice 3 + EXPECT_TRUE(slices->Depths()[3] == 1); + EXPECT_TRUE(slices->DursData()[4] == ts7 - ts5); // slice 4 + EXPECT_TRUE(slices->DursData()[5] == ts10 - ts6); // slice 5 +} + +/** + * @tc.name: AsyncTest + * @tc.desc: Test once asynchronous method call stack + * @tc.type: FUNC + */ +HWTEST_F(SliceFilterTest, AsyncTest, TestSize.Level1) +{ + TS_LOGI("test3"); + uint64_t ts1 = 168758663018000; + uint32_t pid1 = 2532; + uint32_t threadGroupId1 = 2519; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); + DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex("async_call_function_one"); + stream_.streamFilters_->sliceFilter_->StartAsyncSlice(ts1, pid1, threadGroupId1, cat, splitStrIndex); // slice 0 + splitStrIndex = stream_.traceDataCache_->GetDataIndex("async_call_function_one"); + // end thread_one_call_function_three + uint64_t ts2 = 168758682456000; + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts2, pid1, threadGroupId1, cat, splitStrIndex); + auto slices = stream_.traceDataCache_->GetInternalSlicesData(); + EXPECT_TRUE(slices->Size() == 1); + EXPECT_TRUE(slices->DursData()[0] == ts2 - ts1); // slice 0 +} + +/** + * @tc.name: FinishAsyncSliceWithoutStart + * @tc.desc: Finish async slice without start + * @tc.type: FUNC + */ +HWTEST_F(SliceFilterTest, FinishAsyncSliceWithoutStart, TestSize.Level1) +{ + TS_LOGI("test3"); + uint64_t ts = 100; + uint32_t pid = 2532; + uint32_t threadGroupId = 2519; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); + DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex("async_call_function_one"); + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts, pid, threadGroupId, cat, splitStrIndex); + auto slices = stream_.traceDataCache_->GetInternalSlicesData(); + EXPECT_TRUE(slices->Size() == 0); +} + +/** + * @tc.name: AsyncTestTwiceCallStack + * @tc.desc: Test Twice asynchronous call stack + * @tc.type: FUNC + */ +HWTEST_F(SliceFilterTest, AsyncTestTwiceCallStack, TestSize.Level1) +{ + TS_LOGI("test3"); + uint64_t ts1 = 168758663018000; + uint32_t pid1 = 2532; + uint32_t threadGroupId1 = 2519; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); + DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_one"); + stream_.streamFilters_->sliceFilter_->StartAsyncSlice(ts1, pid1, threadGroupId1, cat, splitStrIndex); // slice 0 + DataIndex splitStrIndex2 = stream_.traceDataCache_->GetDataIndex("thread_two_call_function_one"); + uint64_t ts2 = 168758663028000; + uint32_t pid2 = 2533; + uint32_t threadGroupId2 = 2529; + stream_.streamFilters_->sliceFilter_->StartAsyncSlice(ts2, pid2, threadGroupId2, cat, splitStrIndex2); + // end thread_one_call_function_three + uint64_t ts3 = 168758682456000; + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts3, pid1, threadGroupId1, cat, splitStrIndex); + // end thread_two_call_function_three slice 5 + uint64_t ts4 = 168758679343000; + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts4, pid2, threadGroupId2, cat, splitStrIndex2); + auto slices = stream_.traceDataCache_->GetInternalSlicesData(); + EXPECT_TRUE(slices->Size() == 2); + EXPECT_TRUE(slices->DursData()[0] == ts3 - ts1); // slice 0 + EXPECT_TRUE(slices->Depths()[0] == 0); + EXPECT_TRUE(slices->DursData()[1] == ts4 - ts2); // slice 1 +} + +/** + * @tc.name: BeginAsyncSliceThreeTimes + * @tc.desc: Test asynchronous call three times + * @tc.type: FUNC + */ +HWTEST_F(SliceFilterTest, BeginAsyncSliceThreeTimes, TestSize.Level1) +{ + TS_LOGI("test3"); + uint64_t ts1 = 168758663018000; + uint32_t pid1 = 2532; + uint32_t threadGroupId1 = 2519; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); + DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_one"); + stream_.streamFilters_->sliceFilter_->StartAsyncSlice(ts1, pid1, threadGroupId1, cat, splitStrIndex); // slice 0 + DataIndex splitStrIndex2 = stream_.traceDataCache_->GetDataIndex("thread_two_call_function_one"); + uint64_t ts2 = 168758663028000; + uint32_t pid2 = 2533; + uint32_t threadGroupId2 = 2529; + stream_.streamFilters_->sliceFilter_->StartAsyncSlice(ts2, pid2, threadGroupId2, cat, splitStrIndex2); + DataIndex splitStrIndex3 = stream_.traceDataCache_->GetDataIndex("thread_three_call_function_two"); + DataIndex cat2 = stream_.traceDataCache_->GetDataIndex("Catalog2"); + uint64_t ts3 = 168758679303000; + stream_.streamFilters_->sliceFilter_->StartAsyncSlice(ts3, pid1, threadGroupId1, cat2, splitStrIndex3); // slice 2 + // end thread_one_call_function_three + uint64_t ts4 = 168758682456000; + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts4, pid1, threadGroupId1, cat, splitStrIndex); + // end thread_one_call_function_two + uint64_t ts5 = 168758682466000; + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts5, pid1, threadGroupId1, cat2, splitStrIndex3); + // end thread_two_call_function_three slice 5 + uint64_t ts6 = 168758679343000; + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts6, pid2, threadGroupId2, cat, splitStrIndex2); + auto slices = stream_.traceDataCache_->GetInternalSlicesData(); + EXPECT_TRUE(slices->Size() == 3); + EXPECT_TRUE(slices->DursData()[0] == ts4 - ts1); // slice 0 + EXPECT_TRUE(slices->Depths()[0] == 0); + EXPECT_TRUE(slices->DursData()[1] == ts6 - ts2); // slice 1 + EXPECT_TRUE(slices->Depths()[1] == 0); + EXPECT_TRUE(slices->DursData()[2] == ts5 - ts3); // slice 2 +} + +/** + * @tc.name: BeginAsyncSliceThreeTimes + * @tc.desc: Test asynchronous call muti times + * @tc.type: FUNC + */ +HWTEST_F(SliceFilterTest, BeginSliceMultiTimes, TestSize.Level1) +{ + TS_LOGI("test3"); + uint64_t ts1 = 168758663018000; + uint32_t pid1 = 2532; + uint32_t threadGroupId1 = 2519; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); + DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_one"); + stream_.streamFilters_->sliceFilter_->StartAsyncSlice(ts1, pid1, threadGroupId1, cat, splitStrIndex); // slice 0 + + DataIndex splitStrIndex2 = stream_.traceDataCache_->GetDataIndex("thread_two_call_function_one"); + uint64_t ts2 = 168758663028000; + uint32_t pid2 = 2533; + uint32_t threadGroupId2 = 2529; + stream_.streamFilters_->sliceFilter_->StartAsyncSlice(ts2, pid2, threadGroupId2, cat, splitStrIndex2); // slice 1 + + DataIndex splitStrIndex3 = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_two"); + DataIndex cat2 = stream_.traceDataCache_->GetDataIndex("Catalog2"); + uint64_t ts3 = 168758679303000; + stream_.streamFilters_->sliceFilter_->StartAsyncSlice(ts3, pid1, threadGroupId1, cat2, splitStrIndex3); // slice 2 + + DataIndex splitStrIndex4 = stream_.traceDataCache_->GetDataIndex("thread_two_call_function_two"); + uint64_t ts4 = 168758679312000; + stream_.streamFilters_->sliceFilter_->StartAsyncSlice(ts4, pid2, threadGroupId2, cat2, splitStrIndex4); // slice 3 + + DataIndex splitStrIndex5 = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_three"); + uint64_t ts5 = 168758679313000; + DataIndex cat3 = stream_.traceDataCache_->GetDataIndex("Catalog3"); + stream_.streamFilters_->sliceFilter_->StartAsyncSlice(ts5, pid1, threadGroupId1, cat3, splitStrIndex5); // slice 4 + + DataIndex splitStrIndex6 = stream_.traceDataCache_->GetDataIndex("thread_two_call_function_three"); + uint64_t ts6 = 168758679323000; + stream_.streamFilters_->sliceFilter_->StartAsyncSlice(ts6, pid2, threadGroupId2, cat2, splitStrIndex6); // slice 5 + + // end thread_one_call_function_three + uint64_t ts7 = 168758682456000; + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts7, pid1, threadGroupId1, cat, + splitStrIndex); // end slice 0 + + // end thread_one_call_function_two + uint64_t ts8 = 168758682466000; + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts8, pid1, threadGroupId2, cat, + splitStrIndex2); // end slice 1 + + // end thread_one_call_function_one + uint64_t ts9 = 168758682476000; + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts9, pid1, threadGroupId1, cat2, + splitStrIndex3); // end slice 2 + + // end thread_two_call_function_three slice 5 + uint64_t ts10 = 168758679343000; + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts10, pid2, threadGroupId2, cat2, + splitStrIndex4); // end slice 3 + + // end thread_two_call_function_two slice 3 + uint64_t ts11 = 168758679344000; + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts11, pid2, threadGroupId1, cat3, + splitStrIndex5); // end slice 4 + + // end thread_two_call_function_one slice 1 + uint64_t ts12 = 168758689323000; + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts12, pid2, threadGroupId2, cat2, + splitStrIndex6); // end slice 5 + + auto slices = stream_.traceDataCache_->GetInternalSlicesData(); + EXPECT_TRUE(slices->Size() == 6); + EXPECT_TRUE(slices->DursData()[0] == ts7 - ts1); // slice 0 + EXPECT_TRUE(slices->Depths()[0] == 0); + + EXPECT_TRUE(slices->DursData()[1] == ts8 - ts2); // slice 1 + EXPECT_TRUE(slices->Depths()[1] == 0); + + EXPECT_TRUE(slices->DursData()[2] == ts9 - ts3); // slice 2 + EXPECT_TRUE(slices->Depths()[2] == 1); + + EXPECT_TRUE(slices->DursData()[3] == ts10 - ts4); // slice 3 + EXPECT_TRUE(slices->Depths()[3] == 1); + + EXPECT_TRUE(slices->DursData()[4] == ts11 - ts5); // slice 4 + + EXPECT_TRUE(slices->DursData()[5] == ts12 - ts6); // slice 5 +} +} // namespace TraceStreamer +} // namespace SysTuning