From 54095114aaa0c5a06e4f6f8a2c19d86500810d64 Mon Sep 17 00:00:00 2001 From: jichuan Date: Tue, 25 Jul 2023 16:27:48 +0800 Subject: [PATCH 01/14] =?UTF-8?q?Fix:=E5=9C=A8=E7=BA=BF=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E7=BC=BA=E5=A4=B1=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: jichuan --- .../traceStreamer/db_native_hook_statistic.png | Bin 0 -> 6588 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ide/src/figures/traceStreamer/db_native_hook_statistic.png diff --git a/ide/src/figures/traceStreamer/db_native_hook_statistic.png b/ide/src/figures/traceStreamer/db_native_hook_statistic.png new file mode 100644 index 0000000000000000000000000000000000000000..b20e4439633a00e2a75367ae384ae7773b602f4e GIT binary patch literal 6588 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 DBTA8P literal 0 HcmV?d00001 -- Gitee From 988ca314f66393acb093451f89d7376a107fc231 Mon Sep 17 00:00:00 2001 From: jichuan Date: Thu, 27 Jul 2023 14:48:17 +0800 Subject: [PATCH 02/14] Parse TaskPool Data And fix Code Style Signed-off-by: jichuan --- trace_streamer/BUILD.gn | 8 +- trace_streamer/build.sh | 16 +- trace_streamer/build/config.gni | 21 ++ trace_streamer/build/ohos.gni | 32 +-- trace_streamer/build/protoc.sh | 10 +- trace_streamer/build/protoc_w.sh | 3 +- trace_streamer/build/ts.gni | 81 +++--- trace_streamer/build_operator.sh | 4 +- trace_streamer/gn/BUILD.gn | 6 +- trace_streamer/gn/CONFIG.gn | 1 + trace_streamer/gn/toolchain/BUILD.gn | 6 +- .../prebuilts/patch_hiperf/BUILD.gn | 18 +- .../patch_libunwind/libunwindbuild.gn | 20 +- .../prebuilts/patch_sqlite/sqlite3build.gn | 4 +- trace_streamer/sdk/demo_sdk/BUILD.gn | 9 + trace_streamer/sdk/dubai_sdk/BUILD.gn | 9 + trace_streamer/src/BUILD.gn | 261 +++++++++--------- trace_streamer/src/base/BUILD.gn | 20 +- trace_streamer/src/base/clock_filter.cpp | 13 +- trace_streamer/src/base/htrace_file_header.h | 3 +- .../src/base/htrace_plugin_time_parser.h | 4 +- trace_streamer/src/base/index_map.cpp | 4 +- trace_streamer/src/base/index_map.h | 5 +- trace_streamer/src/base/string_help.cpp | 3 +- trace_streamer/src/filter/BUILD.gn | 17 +- .../src/filter/app_start_filter.cpp | 34 +-- trace_streamer/src/filter/frame_filter.cpp | 11 +- trace_streamer/src/filter/frame_filter.h | 1 + .../src/filter/native_hook_filter.cpp | 10 +- .../filter/offline_symbolization_filter.cpp | 4 +- .../src/filter/task_pool_filter.cpp | 140 ++++++++++ trace_streamer/src/filter/task_pool_filter.h | 47 ++++ trace_streamer/src/include/BUILD.gn | 4 +- trace_streamer/src/main.cpp | 4 +- trace_streamer/src/parser/BUILD.gn | 25 +- .../bytrace_parser/bytrace_event_parser.cpp | 2 +- .../src/parser/ebpf_parser/BUILD.gn | 6 +- .../ebpf_parser/bio_latency_data_parser.cpp | 2 +- .../parser/ebpf_parser/ebpf_data_reader.cpp | 13 +- .../ebpf_parser/file_system_data_parser.cpp | 2 +- .../ebpf_parser/paged_memory_data_parser.cpp | 4 +- .../src/parser/hiperf_parser/BUILD.gn | 15 +- .../parser/hiperf_parser/perf_data_parser.cpp | 6 +- .../parser/htrace_pbreader_parser/BUILD.gn | 55 ++-- .../htrace_clock_detail_parser.cpp | 14 +- .../htrace_cpu_data_parser.cpp | 1 + .../htrace_cpu_data_parser.h | 1 + .../htrace_event_parser.cpp | 7 +- .../htrace_network_parser.cpp | 2 +- .../htrace_pbreader_parser/htrace_parser.cpp | 16 +- .../htrace_pbreader_parser/htrace_parser.h | 7 + .../src/parser/print_event_parser.cpp | 10 +- .../src/parser/print_event_parser.h | 1 + trace_streamer/src/proto_reader/BUILD.gn | 6 +- .../src/proto_reader/include/data_area.h | 4 +- .../src/proto_reader/proto_reader.cpp | 6 +- .../src/proto_reader/protoc_plugin/BUILD.gn | 7 +- .../protoc_plugin/proto_reader_plugin.cpp | 1 + trace_streamer/src/protos/protos.gni | 2 +- trace_streamer/src/protos/services/BUILD.gn | 14 +- .../protos/types/plugins/agent_data/BUILD.gn | 14 +- .../types/plugins/bytrace_plugin/BUILD.gn | 18 +- .../protos/types/plugins/cpu_data/BUILD.gn | 22 +- .../protos/types/plugins/diskio_data/BUILD.gn | 22 +- .../plugins/ftrace_data/default/BUILD.gn | 18 +- .../protos/types/plugins/hidump_data/BUILD.gn | 22 +- .../protos/types/plugins/hiebpf_data/BUILD.gn | 8 +- .../protos/types/plugins/hilog_data/BUILD.gn | 22 +- .../types/plugins/hiperf_call_plugin/BUILD.gn | 10 +- .../protos/types/plugins/hiperf_data/BUILD.gn | 18 +- .../types/plugins/hisysevent_data/BUILD.gn | 22 +- .../protos/types/plugins/js_memory/BUILD.gn | 22 +- .../protos/types/plugins/memory_data/BUILD.gn | 22 +- .../protos/types/plugins/native_hook/BUILD.gn | 22 +- .../types/plugins/network_data/BUILD.gn | 22 +- .../types/plugins/process_data/BUILD.gn | 22 +- .../protos/types/plugins/sample_data/BUILD.gn | 8 +- .../protos/types/plugins/stream_data/BUILD.gn | 8 +- .../protos/types/plugins/test_data/BUILD.gn | 12 +- trace_streamer/src/rpc/rpc_server.cpp | 1 + trace_streamer/src/table/BUILD.gn | 8 +- trace_streamer/src/table/base/BUILD.gn | 4 +- trace_streamer/src/table/ebpf/BUILD.gn | 4 +- trace_streamer/src/table/ftrace/BUILD.gn | 6 +- .../src/table/ftrace/process_table.cpp | 2 + .../src/table/ftrace/task_pool_table.cpp | 139 ++++++++++ .../src/table/ftrace/task_pool_table.h | 53 ++++ trace_streamer/src/table/hi_sysevent/BUILD.gn | 4 +- trace_streamer/src/table/hiperf/BUILD.gn | 4 +- trace_streamer/src/table/js_memory/BUILD.gn | 4 +- trace_streamer/src/table/monitor/BUILD.gn | 4 +- trace_streamer/src/table/native_hook/BUILD.gn | 4 +- trace_streamer/src/trace_data/BUILD.gn | 4 +- .../src/trace_data/trace_data_cache.cpp | 9 + .../src/trace_data/trace_data_cache_base.h | 1 + .../trace_data/trace_data_cache_reader.cpp | 4 + .../src/trace_data/trace_data_cache_reader.h | 1 + .../trace_data/trace_data_cache_writer.cpp | 6 +- .../src/trace_data/trace_data_cache_writer.h | 1 + .../src/trace_data/trace_stdtype.cpp | 139 +++++++++- trace_streamer/src/trace_data/trace_stdtype.h | 69 ++++- .../trace_streamer/trace_streamer_filters.cpp | 1 + .../trace_streamer/trace_streamer_filters.h | 6 + .../trace_streamer_selector.cpp | 6 + trace_streamer/test/BUILD.gn | 25 +- .../test/test_fuzzer/bytrace_fuzzer/BUILD.gn | 2 +- .../test/test_fuzzer/htrace_fuzzer/BUILD.gn | 2 +- .../test/test_fuzzer/selector_fuzzer/BUILD.gn | 2 +- trace_streamer/test/test_ts.gni | 1 + 109 files changed, 1284 insertions(+), 628 deletions(-) create mode 100644 trace_streamer/src/filter/task_pool_filter.cpp create mode 100644 trace_streamer/src/filter/task_pool_filter.h create mode 100644 trace_streamer/src/table/ftrace/task_pool_table.cpp create mode 100644 trace_streamer/src/table/ftrace/task_pool_table.h diff --git a/trace_streamer/BUILD.gn b/trace_streamer/BUILD.gn index a694033df..1bcdb155d 100644 --- a/trace_streamer/BUILD.gn +++ b/trace_streamer/BUILD.gn @@ -11,7 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. import("build/ts.gni") -group("trace_streamer_port") { +group("trace_streamer") { if (is_test) { deps = [ "test:unittest" ] testonly = true @@ -21,9 +21,7 @@ group("trace_streamer_port") { } else if (is_protoc) { deps = [ "${THIRD_PARTY}/protobuf:protoc" ] } else if (is_spb) { - deps = [ - "src/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", - ] + deps = [ "src/proto_reader/protoc_plugin:protoreader_plugin" ] } else if (is_sdkdemo) { deps = [ "sdk/demo_sdk:trace_streamer_sdk_builtin" ] } else if (is_dubai_sdk) { @@ -33,6 +31,6 @@ group("trace_streamer_port") { } else if (use_wasm) { deps = [ "src:trace_streamer_builtin" ] } else { - deps = [ "src:trace_streamer_main" ] + deps = [ "src:trace_streamer" ] } } diff --git a/trace_streamer/build.sh b/trace_streamer/build.sh index 1a2737acc..e1cb2f2ab 100755 --- a/trace_streamer/build.sh +++ b/trace_streamer/build.sh @@ -39,19 +39,15 @@ usage="Usage: $basename $0 wasm/test/fuzz/protoc debug/release/clean" ./dl_tools.sh $gn_path if { [ "$1" == "dubaisdk" ] || [ "$1" == "sdkdemo" ] || [ "$1" == "wasm" ] || [ "$1" == "test" ] || [ "$1" == "fuzz" ]; } && [ "$#" -ne 0 ];then - TARGET_DIR=$1 - if [[ $PARAMS == *"debug"* ]]; then - TARGET_DIR=$1"_debug" - fi - if [ ! -f "out/$TARGET_DIR/clang_x64/developtools/smartperf_host/protoc" ] && [ "$1" != "protoc" ];then + if [ ! -f "out/$1/clang_x64/developtools/profiler/protoc" ] && [ "$1" != "protoc" ];then ./build.sh protoc - mkdir -p out/$TARGET_DIR/clang_x64/developtools/smartperf_host - cp out/$target_os/clang_x64/developtools/smartperf_host/protoc out/$TARGET_DIR/clang_x64/developtools/smartperf_host/protoc + mkdir -p out/$1/clang_x64/developtools/profiler + cp out/$target_os/clang_x64/developtools/profiler/protoc out/$1/clang_x64/developtools/profiler/protoc fi - if [ ! -f "out/$TARGET_DIR/clang_x64/developtools/smartperf_host/protoreader_plugin" ] && [ "$1" != "spb" ] && [ -f "out/$TARGET_DIR/clang_x64/developtools/smartperf_host/protoc" ];then + if [ ! -f "out/$1/clang_x64/developtools/profiler/protoreader_plugin" ] && [ "$1" != "spb" ] && [ -f "out/$1/clang_x64/developtools/profiler/protoc" ];then ./build.sh spb - mkdir -p out/$TARGET_DIR/clang_x64/developtools/smartperf_host - cp out/$target_os/clang_x64/developtools/smartperf_host/protoreader_plugin out/$TARGET_DIR/clang_x64/developtools/smartperf_host/protoreader_plugin + mkdir -p out/$1/clang_x64/developtools/profiler + cp out/$target_os/clang_x64/developtools/profiler/protoreader_plugin out/$1/clang_x64/developtools/profiler/protoreader_plugin fi fi if [ $target_os == "windows" ];then diff --git a/trace_streamer/build/config.gni b/trace_streamer/build/config.gni index f287cf244..3e7f08f25 100644 --- a/trace_streamer/build/config.gni +++ b/trace_streamer/build/config.gni @@ -11,3 +11,24 @@ # See the License for the specific language governing permissions and # limitations under the License. import("ts.gni") +asdk_libs_dir = "." +host_toolchain = "" +OHOS_TRACE_STREAMER_PROTOS_DIR = get_path_info("../src", "abspath") +OHOS_PROFILER_3RDPARTY_DIR = get_path_info("../third_party/", "abspath") +OHOS_PROFILER_3RDPARTY_GRPC_DIR = "${OHOS_PROFILER_3RDPARTY_DIR}/grpc" +OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR = "${OHOS_PROFILER_3RDPARTY_DIR}/protobuf" +OHOS_PROFILER_3RDPARTY_GOOGLETEST_DIR = + "${OHOS_PROFILER_3RDPARTY_DIR}/googletest" + +OHOS_PROFILER_SUBSYS_NAME = "developtools" +OHOS_PROFILER_PART_NAME = "profiler" +OHOS_PROFILER_TEST_MODULE_OUTPUT_PATH = "profiler" + +build_l2 = false +if (getenv("BUILD_L2") == "true") { + build_l2 = true +} + +declare_args() { + profiler_SmartPerf = true +} diff --git a/trace_streamer/build/ohos.gni b/trace_streamer/build/ohos.gni index cb277267c..9934bde4d 100644 --- a/trace_streamer/build/ohos.gni +++ b/trace_streamer/build/ohos.gni @@ -76,14 +76,14 @@ template("ohos_shared_library") { } } template("ohos_static_library") { - if (defined(invoker.subsystem_name)) { - subsystem_name = invoker.subsystem_name - print("subsystem_name", subsystem_name) - } - if (defined(invoker.part_name)) { - part_name = invoker.part_name - print("part_name", part_name) - } + if (defined(invoker.subsystem_name)) { + subsystem_name = invoker.subsystem_name + print("subsystem_name", subsystem_name) + } + if (defined(invoker.part_name)) { + part_name = invoker.part_name + print("part_name", part_name) + } static_library(target_name) { sources = invoker.sources if (defined(invoker.configs)) { @@ -108,14 +108,14 @@ template("ohos_static_library") { } } template("ohos_executable") { - if (defined(invoker.subsystem_name)) { - subsystem_name = invoker.subsystem_name - print("subsystem_name", subsystem_name) - } - if (defined(invoker.part_name)) { - part_name = invoker.part_name - print("part_name", part_name) - } + if (defined(invoker.subsystem_name)) { + subsystem_name = invoker.subsystem_name + print("subsystem_name", subsystem_name) + } + if (defined(invoker.part_name)) { + part_name = invoker.part_name + print("part_name", part_name) + } executable(target_name) { if (defined(invoker.include_dirs)) { include_dirs = invoker.include_dirs diff --git a/trace_streamer/build/protoc.sh b/trace_streamer/build/protoc.sh index 7537db2c8..2dfdf6344 100755 --- a/trace_streamer/build/protoc.sh +++ b/trace_streamer/build/protoc.sh @@ -14,12 +14,10 @@ set -e THIS_DIR=$(dirname ${BASH_SOURCE[0]}) -PROJECT_TOP=$(realpath $THIS_DIR/../../../..) -TAIL_DIR="thirdparty/protobuf" -SUBSYS_DIR="developtools/smartperf_host" +PROJECT_TOP=$(realpath $THIS_DIR/../../..) +TAIL_DIR="developtools/profiler" if [[ $2 == *"developtools"* ]]; then TAIL_DIR="." - SUBSYS_DIR="." PROJECT_TOP=$(realpath $THIS_DIR/..) fi OHOS_X64_OUT=$PROJECT_TOP/$2/ @@ -27,8 +25,8 @@ LIBCXX_X64_OUT=$PROJECT_TOP/$1/ndk/libcxx/linux_x86_64 SUBSYS_X64_OUT=$PROJECT_TOP/$2/$TAIL_DIR PROTOC=$PROJECT_TOP/$2/$TAIL_DIR/protoc -OPT_PLUGIN_PROTOREADER_PATH=$PROJECT_TOP/$2/$SUBSYS_DIR/protoreader_plugin -OPT_PLUGIN_PROTOREADER="--plugin=protoc-gen-plugin=$PROJECT_TOP/$2/$SUBSYS_DIR/protoreader_plugin --plugin_out=wrapper_namespace=ProtoReader" +OPT_PLUGIN_PROTOREADER_PATH=$PROJECT_TOP/$2/$TAIL_DIR/protoreader_plugin +OPT_PLUGIN_PROTOREADER="--plugin=protoc-gen-plugin=$PROJECT_TOP/$2/$TAIL_DIR/protoreader_plugin --plugin_out=wrapper_namespace=ProtoReader" OPT_OUT=--opt_out OPT_PROTOREADER_OUT=--cpp_out PYTHON_SHELL=$THIS_DIR/make_standard_proto.py # shell path diff --git a/trace_streamer/build/protoc_w.sh b/trace_streamer/build/protoc_w.sh index ebc7a8ade..0e3217522 100644 --- a/trace_streamer/build/protoc_w.sh +++ b/trace_streamer/build/protoc_w.sh @@ -1,4 +1,5 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. +#!/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 diff --git a/trace_streamer/build/ts.gni b/trace_streamer/build/ts.gni index 8c30a9263..e7b7efb15 100755 --- a/trace_streamer/build/ts.gni +++ b/trace_streamer/build/ts.gni @@ -10,23 +10,48 @@ # WITHOUT 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("config.gni") +if (target_os == "linux" || target_os == "macx" || target_os == "windows") { + clang_x64_folder = "." + THIRD_PARTY = "//third_party" + SRC = "//src" + PREBUILTS = "//prebuilts" -declare_args() { - profiler_SmartPerf = true - is_independent_compile = false + # kernel_version = "5.10.79_aarch64" + kernel_version = "." + if (target == "test") { + enable_ts_utest = true + } else { + enable_ts_utest = false } - -if (is_independent_compile) { - asdk_libs_dir="." - host_toolchain = "" + device_kernel_version = "default" + is_ohos = false PERF_DIR = "//third_party" - clang_x64_folder = "." - enable_ts_utest = (target == "test") + + OHOS_TRACE_STREAMER_PROTOS_DIR = get_path_info("../src", "abspath") + OHOS_TRACE_STREAMER_DIR = get_path_info("../", "abspath") + OHOS_TRACE_STREAMER_DIR_PROTOC = get_path_info("./protoc.sh", "abspath") + + if (target_os == "windows") { + OHOS_TRACE_STREAMER_DIR_PROTOC = get_path_info("./protoc_w.sh", "abspath") + } else { + script_executable = "/usr/bin/env" + } + OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR = + get_path_info("../third_party/protobuf", "abspath") } else { - PERF_DIR = "//developtools" - with_ebpf_help_table = false + script_executable = "/usr/bin/env" clang_x64_folder = "clang_x64" + with_ebpf_help_table = false + OHOS_TRACE_STREAMER_DIR = get_path_info("..", "abspath") + OHOS_TRACE_STREAMER_DIR_PROTOC = get_path_info("/protoc.sh", "abspath") + THIRD_PARTY = get_path_info("../../../../../../third_party/", "abspath") + PERF_DIR = get_path_info("../../../../../", "abspath") + SRC = "${OHOS_TRACE_STREAMER_DIR}/src" + PREBUILTS = "${OHOS_TRACE_STREAMER_DIR}/prebuilts" + target = "trace_steamer" is_macx = false + with_perf = true is_test = false is_protoc = false is_spb = false @@ -34,34 +59,12 @@ if (is_independent_compile) { is_dubai_sdk = false is_sdkdemo_test = false use_wasm = false - enable_ts_utest = false + enable_ts_utest = true + kernel_version = "." is_fuzz = false + target = "trace_streamer" + is_ohos = true } - -script_executable = "/usr/bin/env" -device_kernel_version = "default" -OHOS_TRACE_STREAMER_PROTOS_DIR = get_path_info("../src", "abspath") - -OHOS_TRACE_STREAMER_DIR = get_path_info("../", "abspath") -SRC = "${OHOS_TRACE_STREAMER_DIR}/src" -PREBUILTS = "//prebuilts" -THIRD_PARTY = "//third_party" -kernel_version = "." - -OHOS_TRACE_STREAMER_DIR_PROTOC= get_path_info("./protoc.sh", "abspath") - -if (target_os == "windows") { - OHOS_TRACE_STREAMER_DIR_PROTOC= get_path_info("./protoc_w.sh", "abspath") -} - -OHOS_PROFILER_3RDPARTY_GRPC_DIR = "${THIRD_PARTY}/grpc" -OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR = "${THIRD_PARTY}/protobuf" -OHOS_PROFILER_3RDPARTY_GOOGLETEST_DIR = "${THIRD_PARTY}/googletest" -OHOS_PROFILER_SUBSYS_NAME = "developtools" -OHOS_PROFILER_PART_NAME = "smartperf_host" -OHOS_PROFILER_TEST_MODULE_OUTPUT_PATH = "smartperf_host" - -build_l2 = false -if (getenv("BUILD_L2") == "true") { - build_l2 = true +if (is_ohos) { + import("../../../../build/config.gni") } diff --git a/trace_streamer/build_operator.sh b/trace_streamer/build_operator.sh index 8b1068fbd..ac4a134e4 100755 --- a/trace_streamer/build_operator.sh +++ b/trace_streamer/build_operator.sh @@ -15,7 +15,7 @@ set -e ext="/clang_x64" target_dir="linux" subsys_name="developtools" -part_name="smartperf_host" +part_name="profiler" is_debug="$1" target="$2" target_os="$3" @@ -78,7 +78,7 @@ if [ "$is_clean" == "true" ];then prebuilts/$gn_path/$gn gen out/"$target_dir""$ext"/$subsys_name/$part_name --clean prebuilts/$gn_path/$ninja -C out/"$target_dir""$ext"/$subsys_name/$part_name -t clean else - prebuilts/$gn_path/$gn gen out/"$target_dir""$ext"/$subsys_name/$part_name --args='is_debug='"$is_debug"' target="'"$target"'" target_os="'"$target_os"'" is_independent_compile=true' + prebuilts/$gn_path/$gn gen out/"$target_dir""$ext"/$subsys_name/$part_name --args='is_debug='"$is_debug"' target="'"$target"'" target_os="'"$target_os"'"' echo "begin to build ..." mkdir -p out/windows touch out/windows/trace_streamer.exe diff --git a/trace_streamer/gn/BUILD.gn b/trace_streamer/gn/BUILD.gn index be63ea1d6..65adceadc 100755 --- a/trace_streamer/gn/BUILD.gn +++ b/trace_streamer/gn/BUILD.gn @@ -91,6 +91,7 @@ config("default") { "-DCC_IS_CLANG", ] libs += [ "z" ] + # with_libunwind = true } if (!use_wasm && !is_win && !is_macx && !is_test) { @@ -137,6 +138,9 @@ config("default") { "-D __KERNEL__", ] } + if (with_perf) { + cflags += [ "-D WITH_PERF" ] + } if (with_ebpf_help_table) { cflags += [ "-D WITH_EBPF_HELP" ] } @@ -187,7 +191,7 @@ config("executable") { print("use_wasm", use_wasm) ldflags = [] - if (is_linux || ((is_macx && !use_wasm))) { + if (is_linux || (is_macx && !use_wasm)) { ldflags += [] } if (!is_macx && !use_wasm && !is_win) { diff --git a/trace_streamer/gn/CONFIG.gn b/trace_streamer/gn/CONFIG.gn index 29d63b33e..8b4791d99 100755 --- a/trace_streamer/gn/CONFIG.gn +++ b/trace_streamer/gn/CONFIG.gn @@ -14,6 +14,7 @@ is_win = false is_linux = false is_macx = false is_protoc = false +with_perf = true with_ebpf_help_table = false is_mingw = false with_libunwind = false diff --git a/trace_streamer/gn/toolchain/BUILD.gn b/trace_streamer/gn/toolchain/BUILD.gn index 37f5bc3d0..3b3150946 100755 --- a/trace_streamer/gn/toolchain/BUILD.gn +++ b/trace_streamer/gn/toolchain/BUILD.gn @@ -14,12 +14,12 @@ import("//gn/wasm.gni") declare_args() { if (target_os == "linux" || target_os == "macx") { - cc = "clang" - cxx = "clang++" + cc = "/usr/bin/clang" + cxx = "/usr/bin/clang++" pic = "-fPIC" rebuild_string = "" extra_asmflags = "" - asm = "clang" + asm = "/usr/bin/clang" } else if (target_os == "windows") { cc = "gcc.exe" cxx = "g++.exe" diff --git a/trace_streamer/prebuilts/patch_hiperf/BUILD.gn b/trace_streamer/prebuilts/patch_hiperf/BUILD.gn index f724fe22e..252d1d034 100644 --- a/trace_streamer/prebuilts/patch_hiperf/BUILD.gn +++ b/trace_streamer/prebuilts/patch_hiperf/BUILD.gn @@ -14,10 +14,10 @@ import("//build/ohos.gni") import("../../build/ts.gni") ohos_source_set("elf") { - subsystem_name = "trace_streamer" - part_name = "elf" - configs -= [ "//gn:trace_cfg" ] - configs += [ "//gn:hiperf_trace_cfg" ] + subsystem_name = "developtools" + part_name = "smartperf_host" + configs -= [ "../../gn:trace_cfg" ] + configs += [ "../../gn:hiperf_trace_cfg" ] sources = [ "include/elf_parser.h", "src/elf_file.cpp", @@ -36,10 +36,10 @@ ohos_source_set("elf") { ] } ohos_source_set("hiperf_src") { - configs -= [ "//gn:trace_cfg" ] - configs += [ "//gn:hiperf_trace_cfg" ] - subsystem_name = "trace_streamer" - part_name = "hiperf_src" + configs -= [ "../../gn:trace_cfg" ] + configs += [ "../../gn:hiperf_trace_cfg" ] + subsystem_name = "developtools" + part_name = "smartperf_host" cflags = [ "-D ALWAYSTRUE" ] sources = [ "./src/callstack.cpp", @@ -82,7 +82,7 @@ ohos_source_set("hiperf_src") { ] } -group("hiperf_platform_common") { +group("hiperf") { deps = [ ":elf", ":hiperf_src", diff --git a/trace_streamer/prebuilts/patch_libunwind/libunwindbuild.gn b/trace_streamer/prebuilts/patch_libunwind/libunwindbuild.gn index 32b347a5d..426bb8b4d 100644 --- a/trace_streamer/prebuilts/patch_libunwind/libunwindbuild.gn +++ b/trace_streamer/prebuilts/patch_libunwind/libunwindbuild.gn @@ -359,8 +359,8 @@ config("unwind_config_x64") { } if (target_cpu == "arm") { ohos_source_set("unwind_source_arm") { - subsystem_name = "trace_streamer" - part_name = "unwind_source_arm" + subsystem_name = "developtools" + part_name = "smartperf_host" configs += [ ":unwind_config_remote" ] public_configs = [ ":unwind_config_public", @@ -384,8 +384,8 @@ if (target_cpu == "arm") { } if (target_cpu == "arm64") { ohos_source_set("unwind_source_arm64") { - subsystem_name = "trace_streamer" - part_name = "unwind_source_arm64" + subsystem_name = "developtools" + part_name = "smartperf_host" configs += [ ":unwind_config_remote" ] public_configs = [ ":unwind_config_public", @@ -402,8 +402,8 @@ if (target_cpu == "arm64") { } if (target_cpu == "x86") { ohos_source_set("unwind_source_x64") { - subsystem_name = "trace_streamer" - part_name = "unwind_source_x64" + subsystem_name = "developtools" + part_name = "smartperf_host" configs += [ ":unwind_config_remote" ] public_configs = [ ":unwind_config_public", @@ -422,8 +422,8 @@ if (target_cpu == "x86") { } } ohos_source_set("unwind_source") { - subsystem_name = "trace_streamer" - part_name = "unwind_source" + subsystem_name = "developtools" + part_name = "smartperf_host" configs += [ ":unwind_config_public" ] sources = common_source if (target_cpu == "arm") { @@ -465,7 +465,7 @@ if (defined(ohos_lite)) { # ] public_configs = [ ":unwind_config_public" ] - # part_name = "faultloggerd" - # subsystem_name = "hiviewdfx" + # part_name = "smartperf_host" + # subsystem_name = "developtools" } } diff --git a/trace_streamer/prebuilts/patch_sqlite/sqlite3build.gn b/trace_streamer/prebuilts/patch_sqlite/sqlite3build.gn index cc5b9467b..5644a48ba 100755 --- a/trace_streamer/prebuilts/patch_sqlite/sqlite3build.gn +++ b/trace_streamer/prebuilts/patch_sqlite/sqlite3build.gn @@ -43,8 +43,8 @@ config("sqlite_config") { ] } ohos_source_set("sqlite") { - subsystem_name = "trace_streamer" - part_name = "sqlite" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "src/sqlite3.c" ] public_configs = [ ":sqlite_config" ] } diff --git a/trace_streamer/sdk/demo_sdk/BUILD.gn b/trace_streamer/sdk/demo_sdk/BUILD.gn index 97ea1db69..498c279f9 100755 --- a/trace_streamer/sdk/demo_sdk/BUILD.gn +++ b/trace_streamer/sdk/demo_sdk/BUILD.gn @@ -52,6 +52,9 @@ ohos_source_set("lib") { "${THIRD_PARTY}/protobuf/src", ] public_deps = [ "protos/types/plugins/mock_data:mock_data_cpp" ] + if (with_perf) { + include_dirs += [] + } } ohos_source_set("trace_streamer_sdk") { subsystem_name = "trace_streamer" @@ -113,12 +116,18 @@ ohos_source_set("trace_streamer_sdk") { "${THIRD_PARTY}/libunwind/src", ] } + if (with_perf) { + sources += [] + include_dirs += [] + } deps = [ "${SRC}/base:base", "${THIRD_PARTY}/sqlite:sqlite", "plugin:sdk_plugin", ] public_deps = [ "protos/types/plugins/mock_data:mock_data_cpp" ] + if (with_perf) { + } if (use_wasm || enable_ts_utest) { sources += [ diff --git a/trace_streamer/sdk/dubai_sdk/BUILD.gn b/trace_streamer/sdk/dubai_sdk/BUILD.gn index beff5bb07..3f1f91248 100755 --- a/trace_streamer/sdk/dubai_sdk/BUILD.gn +++ b/trace_streamer/sdk/dubai_sdk/BUILD.gn @@ -52,6 +52,9 @@ ohos_source_set("lib") { "${THIRD_PARTY}/sqlite/include", "${THIRD_PARTY}/protobuf/src", ] + if (with_perf) { + include_dirs += [] + } public_deps = [ "protos/types/plugins/mock_data:mock_data_cpp" ] } source_set("trace_streamer_sdk") { @@ -112,11 +115,17 @@ source_set("trace_streamer_sdk") { "${THIRD_PARTY}/libunwind/src", ] } + if (with_perf) { + sources += [] + include_dirs += [] + } deps = [ "${SRC}/base:base", "${THIRD_PARTY}/sqlite:sqlite", "plugin:sdk_plugin", ] + if (with_perf) { + } if (use_wasm || enable_ts_utest) { sources += [ diff --git a/trace_streamer/src/BUILD.gn b/trace_streamer/src/BUILD.gn index 01dff9249..a59336582 100644 --- a/trace_streamer/src/BUILD.gn +++ b/trace_streamer/src/BUILD.gn @@ -11,83 +11,74 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//build/ohos.gni") +import("../build/ohos.gni") import("../build/ts.gni") if (use_wasm) { import("//gn/wasm.gni") } - -ohos_source_set("ts_sqlite") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - sources = [ "//third_party/sqlite/src/sqlite3.c" ] - include_dirs = [ "//third_party/sqlite/include" ] - cflags = [ - "-Wno-shorten-64-to-32", - "-Wno-double-promotion", - "-Wno-disabled-macro-expansion", - "-Wno-float-equal", - "-Wno-cast-qual", - "-Wno-conversion", - "-Wno-cast-align", - "-Wno-unused-macros", - "-Wno-comma", - "-Wno-unreachable-code-break", - "-Wno-unreachable-code", - "-Wno-unreachable-code-return", - "-DSQLITE_THREADSAFE=1", - "-DQLITE_DEFAULT_MEMSTATUS=0", - "-DSQLITE_LIKE_DOESNT_MATCH_BLOBS", - "-DSQLITE_OMIT_DEPRECATED", - "-DSQLITE_OMIT_SHARED_CACHE", - "-DHAVE_USLEEP", - "-DHAVE_UTIME", - "-DSQLITE_BYTEORDER=1234", - "-DSQLITE_DEFAULT_AUTOVACUUM=0", - "-DSQLITE_DEFAULT_MMAP_SIZE=0", - "-DSQLITE_CORE", - "-DSQLITE_TEMP_STORE=3", - "-DSQLITE_OMIT_LOAD_EXTENSION", - ] +if (use_wasm) { + ohos_source_set("trace_streamer_builtin") { + subsystem_name = "developtools" + part_name = "smartperf_host" + sources = [] + include_dirs = [] + deps = [] + public_deps = [] + } } +ohos_source_set("lib") { + subsystem_name = "developtools" + part_name = "smartperf_host" + sources = [ "main.cpp" ] + deps = [ + ":trace_streamer_source", + "proto_reader:proto_reader", + ] + include_dirs = [ + "base", + "..", + "trace_streamer", + "filter", + "table", + "trace_data", + "include", + "rpc", + "./", + "parser", + "cfg", + "proto_reader/include", + "${THIRD_PARTY}/sqlite/include", + "${THIRD_PARTY}/json-master/single_include/nlohmann", + "${THIRD_PARTY}/protobuf/src", + "${THIRD_PARTY}/hiperf/include", + ] -trace_streamer_include = [ - "base", - "..", - "trace_streamer", - "filter", - "table", - "trace_data", - "include", - "rpc", - "./", - "parser", - "cfg", - "proto_reader/include", - "parser/ebpf_parser", - "parser/htrace_pbreader_parser", - "parser/htrace_pbreader_parser/htrace_event_parser", - "parser/htrace_pbreader_parser/htrace_cpu_parser", - "parser/hiperf_parser", - "//developtools/hiperf/include", - "${THIRD_PARTY}/sqlite/include", - "${THIRD_PARTY}/json-master/single_include/nlohmann", - "${THIRD_PARTY}/json/single_include/nlohmann", - "${THIRD_PARTY}/protobuf/src", - "${THIRD_PARTY}/hiperf/include", - "${THIRD_PARTY}/hiperf/include/nonlinux", - "${THIRD_PARTY}/hiperf/include/nonlinux/linux", - "${THIRD_PARTY}/perf_include/musl", - "${THIRD_PARTY}/musl", - "${THIRD_PARTY}/libunwind/include", - "${THIRD_PARTY}/libunwind/src", - "${THIRD_PARTY}/perf_include/libbpf", - "${THIRD_PARTY}/googletest/googletest/include", -] + include_dirs += [ + "parser/htrace_pbreader_parser", + "parser/htrace_pbreader_parser/htrace_event_parser", + "parser/htrace_pbreader_parser/htrace_cpu_parser", + ] + if (with_perf) { + include_dirs += [ + "parser/hiperf_parser", + "${THIRD_PARTY}/hiperf/include", + "${THIRD_PARTY}/hiperf/include/nonlinux", + "${THIRD_PARTY}/hiperf/include/nonlinux/linux", + "${THIRD_PARTY}/perf_include/musl", + ] + } + public_deps = [] + if (!use_wasm && !is_test && !is_fuzz) { + public_deps += [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "proto_reader/protoc_plugin:protoreader_plugin", + ] + } +} ohos_source_set("trace_streamer_source") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "cfg/trace_streamer_config.cpp", "cfg/trace_streamer_config.h", @@ -100,31 +91,87 @@ ohos_source_set("trace_streamer_source") { "trace_streamer/trace_streamer_selector.h", "version.cpp", ] - if (!is_test && !is_fuzz) { - sources += [ "main.cpp" ] - } - if (use_wasm) { - sources += [ - "rpc/wasm_func.cpp", - "rpc/wasm_func.h", - ] - } - - include_dirs = trace_streamer_include + include_dirs = [ + "base", + "..", + "trace_streamer", + "filter", + "table", + "trace_data", + "include", + "rpc", + "./", + "parser", + "cfg", + "proto_reader/include", + "parser/ebpf_parser", + "${THIRD_PARTY}/sqlite/include", + "${THIRD_PARTY}/protobuf/src", + ] if (use_wasm) { include_dirs += [ "../prebuilts/emsdk/emsdk/emscripten/cache/sysroot/include" ] } + if (is_macx && !is_test) { + cflags = [ "-D_XOPEN_SOURCE=600" ] + } if (is_test) { include_dirs += [ "../prebuilts/emsdk/emsdk/emscripten/system/include" ] } - cflags = [ "-D target_cpu_${target_cpu}" ] - if (!use_wasm && !is_win && !is_macx && !is_test) { - cflags += [ "-D HAVE_LIBUNWIND" ] + include_dirs += [ + "parser/htrace_pbreader_parser", + "parser/htrace_pbreader_parser/htrace_event_parser", + "parser/htrace_pbreader_parser/htrace_cpu_parser", + ] + + include_dirs += [ + "${THIRD_PARTY}/libunwind/include", + "${THIRD_PARTY}/libunwind/src", + "${THIRD_PARTY}/json-master/single_include/nlohmann", + "${THIRD_PARTY}/hiperf/include", + "${THIRD_PARTY}/hiperf/include/nonlinux/linux", + "${THIRD_PARTY}/hiperf/include/nonlinux", + ] + + if (with_perf) { + include_dirs += [ + "parser/hiperf_parser", + "${THIRD_PARTY}/perf_include/libbpf", + "${THIRD_PARTY}/perf_include/musl", + ] + } + public_deps = [ + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/services:all_type_cpp_standard", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:cpu_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/ftrace_data/${device_kernel_version}:ftrace_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:hilog_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:hisysevent_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_encoder", + ] + + deps = [ + "${THIRD_PARTY}/sqlite:sqlite", + "base:base", + "filter:filter", + "parser:parser", + "table:table", + "trace_data:trace_data", + ] + if (with_perf) { + deps += [ "parser/hiperf_parser:hiperf_parser" ] + } else { + deps += [ "${THIRD_PARTY}/hiperf:elf" ] + } + + if (use_wasm) { + sources += [ + "rpc/wasm_func.cpp", + "rpc/wasm_func.h", + ] } if (enable_ts_utest && !use_wasm) { - cflags += [ + cflags = [ "-fprofile-arcs", "-ftest-coverage", ] @@ -137,56 +184,16 @@ ohos_source_set("trace_streamer_source") { cflags += [ "-D IS_UT" ] } } - - public_deps = [ - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/services:ts_all_type_cpp_standard", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:cpu_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/ftrace_data/${device_kernel_version}:ftrace_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:hilog_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:hisysevent_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_reader", - ] - if (!use_wasm && !is_test && !is_fuzz) { - public_deps += [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", - ] - } - - deps = [ - ":ts_sqlite", - "base:base", - "filter:filter", - "parser:parser", - "parser/hiperf_parser:hiperf_parser", - "proto_reader:proto_reader", - "table:table", - "trace_data:trace_data", - ] } - if (use_wasm) { - ohos_source_set("trace_streamer_builtin") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - sources = [] - include_dirs = [] - deps = [] - public_deps = [] - } wasm_lib("trace_streamer_builtin_wasm") { name = "trace_streamer_builtin" - deps = [ ":trace_streamer_source" ] + deps = [ ":lib" ] } } else { if (!is_test && !is_fuzz) { - ohos_executable("trace_streamer_main") { - output_name = "trace_streamer" - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - sources = [] - include_dirs = trace_streamer_include - deps = [ ":trace_streamer_source" ] + executable("trace_streamer") { + deps = [ ":lib" ] } } } diff --git a/trace_streamer/src/base/BUILD.gn b/trace_streamer/src/base/BUILD.gn index 643a88e32..f4486b375 100644 --- a/trace_streamer/src/base/BUILD.gn +++ b/trace_streamer/src/base/BUILD.gn @@ -14,8 +14,8 @@ import("//build/ohos.gni") import("../../build/ts.gni") ohos_source_set("base") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" deps = [ ":base_parser", ":base_table", @@ -44,13 +44,13 @@ ohos_source_set("base") { } } ohos_source_set("string_help") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "string_help.cpp" ] } ohos_source_set("ibase") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "codec_cov.h", "file.h", @@ -65,8 +65,8 @@ ohos_source_set("ibase") { sources += [ "/usr/x86_64-w64-mingw32/include/windows.h" ] } ohos_source_set("base_parser") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "htrace_plugin_time_parser.cpp", "htrace_plugin_time_parser.h", @@ -76,8 +76,8 @@ ohos_source_set("base_parser") { deps = [] } ohos_source_set("base_table") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "filter_constraints.cpp", "index_map.cpp", diff --git a/trace_streamer/src/base/clock_filter.cpp b/trace_streamer/src/base/clock_filter.cpp index 9fce0b531..eb4d2ffb5 100644 --- a/trace_streamer/src/base/clock_filter.cpp +++ b/trace_streamer/src/base/clock_filter.cpp @@ -16,7 +16,6 @@ #include "clock_filter.h" #include #include -#include #include "log.h" #include "string_help.h" #include "ts_common.h" @@ -106,32 +105,32 @@ int32_t ClockFilter::InitSnapShotTimeRange(const uint8_t* data, int32_t len) std::vector snapShot; - TS_LOGI("SDK clockid: TS_CLOCK_BOOTTIME, ts:%" PRIu64 " ", profilerSDKTraceFileHeader_->data.boottime); + TS_LOGI("SDK clockid: TS_CLOCK_BOOTTIME, ts:%lu", profilerSDKTraceFileHeader_->data.boottime); if (profilerSDKTraceFileHeader_->data.boottime) { snapShot.push_back(SnapShot{TS_CLOCK_BOOTTIME, profilerSDKTraceFileHeader_->data.boottime}); } - TS_LOGI("SDK clockid: TS_CLOCK_REALTIME, ts:%" PRIu64 "", profilerSDKTraceFileHeader_->data.realtime); + TS_LOGI("SDK clockid: TS_CLOCK_REALTIME, ts:%lu", profilerSDKTraceFileHeader_->data.realtime); if (profilerSDKTraceFileHeader_->data.realtime) { snapShot.push_back(SnapShot{TS_CLOCK_REALTIME, profilerSDKTraceFileHeader_->data.realtime}); } - TS_LOGI("SDK clockid: TS_CLOCK_REALTIME_COARSE, ts:%" PRIu64 "", profilerSDKTraceFileHeader_->data.realtimeCoarse); + TS_LOGI("SDK clockid: TS_CLOCK_REALTIME_COARSE, ts:%lu", profilerSDKTraceFileHeader_->data.realtimeCoarse); if (profilerSDKTraceFileHeader_->data.realtimeCoarse) { snapShot.push_back(SnapShot{TS_CLOCK_REALTIME_COARSE, profilerSDKTraceFileHeader_->data.realtimeCoarse}); } - TS_LOGI("SDK clockid: TS_MONOTONIC, ts:%" PRIu64 "", profilerSDKTraceFileHeader_->data.monotonic); + TS_LOGI("SDK clockid: TS_MONOTONIC, ts:%lu", profilerSDKTraceFileHeader_->data.monotonic); if (profilerSDKTraceFileHeader_->data.monotonic) { snapShot.push_back(SnapShot{TS_MONOTONIC, profilerSDKTraceFileHeader_->data.monotonic}); } - TS_LOGI("SDK clockid: TS_MONOTONIC_COARSE, ts:%" PRIu64 "", profilerSDKTraceFileHeader_->data.monotonicCoarse); + TS_LOGI("SDK clockid: TS_MONOTONIC_COARSE, ts:%lu", profilerSDKTraceFileHeader_->data.monotonicCoarse); if (profilerSDKTraceFileHeader_->data.monotonicCoarse) { snapShot.push_back(SnapShot{TS_MONOTONIC_COARSE, profilerSDKTraceFileHeader_->data.monotonicCoarse}); } - TS_LOGI("SDK clockid: TS_MONOTONIC_RAW, ts:%" PRIu64 "", profilerSDKTraceFileHeader_->data.monotonicRaw); + TS_LOGI("SDK clockid: TS_MONOTONIC_RAW, ts:%lu", profilerSDKTraceFileHeader_->data.monotonicRaw); if (profilerSDKTraceFileHeader_->data.monotonicRaw) { snapShot.push_back(SnapShot{TS_MONOTONIC_RAW, profilerSDKTraceFileHeader_->data.monotonicRaw}); } diff --git a/trace_streamer/src/base/htrace_file_header.h b/trace_streamer/src/base/htrace_file_header.h index 9854f2128..607940a39 100644 --- a/trace_streamer/src/base/htrace_file_header.h +++ b/trace_streamer/src/base/htrace_file_header.h @@ -23,8 +23,7 @@ struct ProfilerTraceFileHeader { static constexpr uint64_t HEADER_MAGIC = 0x464F5250534F484FuLL; static constexpr uint32_t V_MAJOR = 0x0001; static constexpr uint32_t V_MAJOR_BITS = 16; - static constexpr uint32_t V_MINOR = 0x0000; - static constexpr uint32_t TRACE_VERSION = (V_MAJOR << V_MAJOR_BITS) | V_MINOR; + static constexpr uint32_t TRACE_VERSION = V_MAJOR << V_MAJOR_BITS; static constexpr uint8_t PLUGIN_MODULE_NAME_MAX = 127; static constexpr uint8_t PLUGIN_MODULE_VERSION_MAX = 7; enum DataType { diff --git a/trace_streamer/src/base/htrace_plugin_time_parser.h b/trace_streamer/src/base/htrace_plugin_time_parser.h index a1959b058..924bd0f28 100644 --- a/trace_streamer/src/base/htrace_plugin_time_parser.h +++ b/trace_streamer/src/base/htrace_plugin_time_parser.h @@ -26,11 +26,11 @@ public: void UpdatePluginTimeRange(ClockId clockId, uint64_t asyncTimestamp, uint64_t syncTimestamp); uint64_t GetPluginStartTime(); uint64_t GetPluginEndTime(); - uint64_t MinTs() + uint64_t MinTs() const { return minTs_; } - uint64_t MaxTs() + uint64_t MaxTs() const { return maxTs_; } diff --git a/trace_streamer/src/base/index_map.cpp b/trace_streamer/src/base/index_map.cpp index eabc4ed29..ac3196882 100644 --- a/trace_streamer/src/base/index_map.cpp +++ b/trace_streamer/src/base/index_map.cpp @@ -21,7 +21,7 @@ namespace SysTuning { namespace TraceStreamer { -IndexMap::IndexMap(TableRowId start, TableRowId end) : end_(end), current_(start), start_(start) {} +IndexMap::IndexMap(TableRowId start, TableRowId end) : end_(end), current_(start), start_(start), type_(COMPACT) {} void IndexMap::CovertToIndexMap() { @@ -146,14 +146,12 @@ void IndexMap::FilterTS(unsigned char op, sqlite3_value* argv, const std::deque< break; case SQLITE_INDEX_CONSTRAINT_GT: v++; - [[fallthrough]]; case SQLITE_INDEX_CONSTRAINT_GE: { IntersectGreaterEqual(times, v, getValue); break; } case SQLITE_INDEX_CONSTRAINT_LE: v++; - [[fallthrough]]; case SQLITE_INDEX_CONSTRAINT_LT: IntersectLessEqual(times, v, getValue); break; diff --git a/trace_streamer/src/base/index_map.h b/trace_streamer/src/base/index_map.h index dfe32dcdd..28169a851 100644 --- a/trace_streamer/src/base/index_map.h +++ b/trace_streamer/src/base/index_map.h @@ -331,7 +331,7 @@ public: } } else { auto size = rows.size(); - for (size_t i = 0; i < size; i++) { + for (auto i = 0; i < size; i++) { if (rows[i] != invalidValue) { rowIndex_.push_back(i); } @@ -354,8 +354,11 @@ private: INDEX_TYPE_OUTER_INDEX, }; FindIndexType indexType_ = INDEX_TYPE_ID; + uint32_t indexSize_ = 0; + uint32_t index_ = 0; enum IndexType { COMPACT, SPARSE }; + uint8_t type_ = COMPACT; bool empty_ = true; bool desc_ = false; bool converted_ = false; diff --git a/trace_streamer/src/base/string_help.cpp b/trace_streamer/src/base/string_help.cpp index bff7b7c81..a3721f0db 100644 --- a/trace_streamer/src/base/string_help.cpp +++ b/trace_streamer/src/base/string_help.cpp @@ -132,11 +132,10 @@ std::vector SplitStringToVec(const std::string& str, const std::str { std::vector result; size_t curPos = 0; - size_t patPos = 0; size_t strSize = str.size(); size_t patSize = pat.size(); while (curPos < strSize) { - patPos = str.find(pat, curPos); + auto patPos = str.find(pat, curPos); if (patPos == std::string::npos) { break; } diff --git a/trace_streamer/src/filter/BUILD.gn b/trace_streamer/src/filter/BUILD.gn index 520f5c8bc..323250f2b 100644 --- a/trace_streamer/src/filter/BUILD.gn +++ b/trace_streamer/src/filter/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../build/ts.gni") ohos_source_set("filter") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "app_start_filter.cpp", "app_start_filter.h", @@ -52,8 +52,8 @@ ohos_source_set("filter") { "symbols_filter.h", "system_event_measure_filter.cpp", "system_event_measure_filter.h", - "perf_data_filter.cpp", - "perf_data_filter.h", + "task_pool_filter.cpp", + "task_pool_filter.h", ] if (enable_ts_utest && !use_wasm) { @@ -70,7 +70,7 @@ ohos_source_set("filter") { cflags += [ "-D IS_UT" ] } } - public_deps = [ "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_data_reader" ] + public_deps = [ "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_data_encoder" ] deps = [] include_dirs = [ "${SRC}/base", @@ -86,4 +86,11 @@ ohos_source_set("filter") { "../proto_reader/include", ".", ] + + if (with_perf) { + sources += [ + "perf_data_filter.cpp", + "perf_data_filter.h", + ] + } } diff --git a/trace_streamer/src/filter/app_start_filter.cpp b/trace_streamer/src/filter/app_start_filter.cpp index 54fa7f2b6..b8940d746 100644 --- a/trace_streamer/src/filter/app_start_filter.cpp +++ b/trace_streamer/src/filter/app_start_filter.cpp @@ -52,6 +52,7 @@ bool APPStartupFilter::CaclRsDataByPid() { auto frameSliceData = traceDataCache_->GetFrameSliceData(); auto sliceData = traceDataCache_->GetConstInternalSlicesData(); + auto itor = mAPPStartupData_.begin(); for (const auto& item : mAPPStartupData_) { if (item.second.empty()) { continue; @@ -67,8 +68,8 @@ bool APPStartupFilter::CaclRsDataByPid() auto endTime = startTime + frameSliceData->Durs()[m]; mAPPStartupData_[dataIndex].emplace( FIRST_FRAME_APP_PHASE, - std::make_unique(callId, itorSecond->second->ipid_, itorSecond->second->tid_, - startTime, endTime)); + std::move(std::make_unique(callId, itorSecond->second->ipid_, + itorSecond->second->tid_, startTime, endTime))); auto dstId = frameSliceData->Dsts()[m]; if (dstId == INVALID_UINT64) { continue; @@ -78,8 +79,8 @@ bool APPStartupFilter::CaclRsDataByPid() endTime = startTime + frameSliceData->Durs()[dstId]; mAPPStartupData_[dataIndex].emplace( FIRST_FRAME_RENDER_PHASE, - std::make_unique(callId, itorSecond->second->ipid_, itorSecond->second->tid_, - startTime, endTime)); + std::move(std::make_unique(callId, itorSecond->second->ipid_, + itorSecond->second->tid_, startTime, endTime))); break; } } @@ -146,8 +147,8 @@ DataIndex APPStartupFilter::GetThreadNameAndUpdateAPPStartupData(uint32_t row, auto callId = sliceData.CallIds()[row]; auto startTime = sliceData.TimeStampData()[row]; mAPPStartupData_[dataIndex].insert( - std::make_pair(startIndex, std::make_unique(callId, INVALID_UINT32, INVALID_UINT32, startTime, - INVALID_UINT64))); + std::make_pair(startIndex, std::move(std::make_unique(callId, INVALID_UINT32, INVALID_UINT32, + startTime, INVALID_UINT64)))); return dataIndex; } @@ -174,8 +175,8 @@ void APPStartupFilter::ParserAppStartup() } callId = sliceData.CallIds()[i]; mAPPStartupData_[traceDataCache_->GetDataIndex(mainThreadName.c_str())].insert(std::make_pair( - PROCESS_CREATING, - std::make_unique(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64))); + PROCESS_CREATING, std::move(std::make_unique(callId, INVALID_UINT32, INVALID_UINT32, + startTime, INVALID_UINT64)))); } else if (StartWith(nameString, APP_LAUNCH)) { GetThreadNameAndUpdateAPPStartupData(i, nameString, APPLICATION_LAUNCHING); } else if (StartWith(nameString, LAUNCH)) { @@ -192,9 +193,9 @@ void APPStartupFilter::ParserAppStartup() auto nameindex = threadData[callId].nameIndex_; auto ipid = threadData[callId].internalPid_; auto tid = threadData[callId].tid_; - mAPPStartupData_[nameindex].insert( - std::make_pair(UI_ABILITY_ONFOREGROUND, - std::make_unique(callId, ipid, tid, startTime, INVALID_UINT64))); + mAPPStartupData_[nameindex].insert(std::make_pair( + UI_ABILITY_ONFOREGROUND, + std::move(std::make_unique(callId, ipid, tid, startTime, INVALID_UINT64)))); } } UpdatePidByNameIndex(); @@ -215,14 +216,15 @@ void APPStartupFilter::CalcDepthByTimeStamp(std::mapsecond.insert(std::make_pair(endTime, it->second.size())); } else { depth = itor->second; + for (auto itorSecond = itor; itorSecond != it->second.end(); ++itorSecond) { + if (itorSecond->first < startTime && depth > itorSecond->second) { + depth = itorSecond->second; + itor = itorSecond; + } + } it->second.erase(itor); it->second.insert(std::make_pair(endTime, depth)); } - for (const auto& item : it->second) { - if (item.first < startTime && depth > item.second) { - depth = item.second; - } - } } else { it->second.insert(std::make_pair(endTime, 0)); } diff --git a/trace_streamer/src/filter/frame_filter.cpp b/trace_streamer/src/filter/frame_filter.cpp index 93b1fb5c6..4a0f6f7ba 100644 --- a/trace_streamer/src/filter/frame_filter.cpp +++ b/trace_streamer/src/filter/frame_filter.cpp @@ -14,7 +14,6 @@ */ #include "frame_filter.h" #include -#include #include "log.h" #define ISINVALIDU32(value) (value == INVALID_UINT32) namespace SysTuning { @@ -56,7 +55,7 @@ bool FrameFilter::MarkRSOnvsyncEvent(uint64_t ts, uint32_t itid) { auto frame = vsyncRenderSlice_.find(itid); if (frame == vsyncRenderSlice_.end()) { - TS_LOGW("BeginOnvsyncEvent find for itid:%u failed, ts:%" PRIu64 "", itid, ts); + TS_LOGW("BeginOnvsyncEvent find for itid:%u failed, ts:%llu", itid, ts); return false; } if (!frame->second.size()) { @@ -174,11 +173,11 @@ bool FrameFilter::EndVsyncEvent(uint64_t ts, uint32_t itid) { auto frame = vsyncRenderSlice_.find(itid); if (frame == vsyncRenderSlice_.end()) { - TS_LOGW("EndVsyncEvent find for itid:%u ts:%" PRIu64" failed", itid, ts); + TS_LOGW("EndVsyncEvent find for itid:%u ts:%llu failed", itid, ts); return false; } if (!frame->second.size()) { - TS_LOGW("EndVsyncEvent find for itid:%u ts:%" PRIu64" failed", itid, ts); + TS_LOGW("EndVsyncEvent find for itid:%u ts:%llu failed", itid, ts); return false; } auto lastFrameSlice = frame->second.back(); @@ -227,11 +226,11 @@ bool FrameFilter::EndFrameQueue(uint64_t ts, uint32_t itid) { auto frame = vsyncRenderSlice_.find(itid); if (frame == vsyncRenderSlice_.end()) { - TS_LOGW("EndFrameQueue find for itid:%u ts:%" PRIu64" failed", itid, ts); + TS_LOGW("EndFrameQueue find for itid:%u ts:%llu failed", itid, ts); return false; } if (!frame->second.size()) { - TS_LOGW("EndFrameQueue find for itid:%u ts:%" PRIu64" failed", itid, ts); + TS_LOGW("EndFrameQueue find for itid:%u ts:%llu failed", itid, ts); return false; } auto firstFrameSlicePos = frame->second.begin(); diff --git a/trace_streamer/src/filter/frame_filter.h b/trace_streamer/src/filter/frame_filter.h index 73152c9b8..71c5b2d47 100644 --- a/trace_streamer/src/filter/frame_filter.h +++ b/trace_streamer/src/filter/frame_filter.h @@ -77,6 +77,7 @@ private: std::unordered_map>> vsyncRenderSlice_ = {}; std::unordered_map>> dstRenderSlice_ = {}; + bool checkFrameAlwasy_ = false; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/filter/native_hook_filter.cpp b/trace_streamer/src/filter/native_hook_filter.cpp index 91e6eab67..1b6504689 100644 --- a/trace_streamer/src/filter/native_hook_filter.cpp +++ b/trace_streamer/src/filter/native_hook_filter.cpp @@ -15,7 +15,6 @@ #include "native_hook_filter.h" #include "native_hook_config.pbreader.h" -#include namespace SysTuning { namespace TraceStreamer { NativeHookFilter::NativeHookFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) @@ -113,12 +112,13 @@ std::unique_ptr NativeHookFilter::ParseFrame(const ProtoRea } auto frameInfo = std::make_unique(reader.ip(), reader.sp(), symbolIndex, filePathIndex, reader.offset(), reader.symbol_offset()); - return frameInfo; + return std::move(frameInfo); } void NativeHookFilter::CompressStackAndFrames(ProtoReader::RepeatedDataAreaIterator frames) { std::vector framesHash; + uint64_t frameHash = INVALID_UINT64; std::string framesHashStr = ""; for (auto itor = frames; itor; itor++) { std::string_view frameStr(reinterpret_cast(itor->Data()), itor->Size()); @@ -501,7 +501,7 @@ inline void NativeHookFilter::FillOfflineSymbolizationFrames( stackIdToCallChainIdMap_.insert(std::make_pair(itor->first, ++callChainId_)); auto framesInfo = OfflineSymbolization(itor->second); uint64_t depth = 0; - uint64_t filePathIndex = INVALID_UINT64; + uint64_t filePathIndex; for (auto itor = framesInfo->rbegin(); itor != framesInfo->rend(); itor++) { // Note that the filePathId here is provided for the end side. Not a true TS internal index dictionary. auto frameInfo = itor->get(); @@ -671,7 +671,7 @@ void NativeHookFilter::MaybeUpdateCurrentSizeDur(uint64_t row, uint64_t timeStam void NativeHookFilter::UpdateSymbolIdsForSymbolizationFailed() { auto size = traceDataCache_->GetNativeHookFrameData()->Size(); - for (size_t i = 0; i < size; ++i) { + for (auto i = 0; i < size; ++i) { if (traceDataCache_->GetNativeHookFrameData()->SymbolNames()[i] == INVALID_UINT64) { auto filePathIndex = traceDataCache_->GetNativeHookFrameData()->FilePaths()[i]; auto filePathStr = traceDataCache_->dataDict_.GetDataFromDict(filePathIndex); @@ -873,7 +873,7 @@ bool NativeHookFilter::GetIpsWitchNeedResymbolization(DataIndex filePathId, std: bool value = false; for (auto itor = ipToFrameInfo_.begin(); itor != ipToFrameInfo_.end(); itor++) { if (!itor->second) { - TS_LOGI("ip :%llu can not symbolization! FrameInfo is nullptr", itor->first); + TS_LOGI("ip :%lu can not symbolization! FrameInfo is nullptr", itor->first); continue; } if (itor->second->filePathId_ == filePathId) { diff --git a/trace_streamer/src/filter/offline_symbolization_filter.cpp b/trace_streamer/src/filter/offline_symbolization_filter.cpp index 3c0c538b4..34c488058 100644 --- a/trace_streamer/src/filter/offline_symbolization_filter.cpp +++ b/trace_streamer/src/filter/offline_symbolization_filter.cpp @@ -18,8 +18,8 @@ namespace SysTuning { namespace TraceStreamer { OfflineSymbolizationFilter::OfflineSymbolizationFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) : FilterBase(dataCache, filter), - filePathIdAndStValueToSymAddr_(nullptr), - symbolTablePtrAndStValueToSymAddr_(nullptr) + symbolTablePtrAndStValueToSymAddr_(nullptr), + filePathIdAndStValueToSymAddr_(nullptr) { } std::shared_ptr>> OfflineSymbolizationFilter::OfflineSymbolization( diff --git a/trace_streamer/src/filter/task_pool_filter.cpp b/trace_streamer/src/filter/task_pool_filter.cpp new file mode 100644 index 000000000..b9ef89fc8 --- /dev/null +++ b/trace_streamer/src/filter/task_pool_filter.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 "task_pool_filter.h" +#include "parting_string.h" +#include "string_to_numerical.h" + +namespace SysTuning { +namespace TraceStreamer { +const uint32_t EXECUTE_DATA_FLAG = 2; + +TaskPoolFilter::TaskPoolFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : FilterBase(dataCache, filter) +{ +} +TaskPoolFilter::~TaskPoolFilter() = default; + +uint32_t TaskPoolFilter::CheckTheSameTask(int32_t executeId) +{ + if (executeMap_.count(executeId)) { + return executeMap_[executeId]; + } + return INVALID_INT32; +} + +void TaskPoolFilter::TaskPoolFieldSegmentation(const std::string& taskPoolStr, + std::unordered_map& args) +{ + for (base::PartingString ss(taskPoolStr, ','); ss.Next();) { + std::string key; + std::string value; + for (base::PartingString inner(ss.GetCur(), ':'); inner.Next();) { + if (key.empty()) { + key = inner.GetCur(); + } else { + value = inner.GetCur(); + } + } + args.emplace(std::move(key), std::move(value)); + } +} + +void TaskPoolFilter::TaskPoolEvent(const std::string& taskPoolStr, int32_t index) +{ + std::string targetStr = "H:Task "; + if (!taskPoolStr.compare(0, targetStr.length(), targetStr)) { + std::unordered_map args; + std::string allocationStr = "H:Task Allocation: "; + if (StartWith(taskPoolStr, allocationStr)) { + allocationStr = taskPoolStr.substr(allocationStr.length(), taskPoolStr.length()); + TaskPoolFieldSegmentation(allocationStr, args); + UpdateAssignData(args, index); + return; + } + std::string executeStr = "H:Task Perform: "; + if (StartWith(taskPoolStr, executeStr)) { + executeStr = taskPoolStr.substr(executeStr.length(), taskPoolStr.length()); + TaskPoolFieldSegmentation(executeStr, args); + UpdateExecuteData(args, index); + return; + } + std::string returnStr = "H:Task PerformTask End: "; + if (StartWith(taskPoolStr, returnStr)) { + returnStr = taskPoolStr.substr(returnStr.length(), taskPoolStr.length()); + TaskPoolFieldSegmentation(returnStr, args); + UpdateReturnData(args, index); + return; + } + } +} + +void TaskPoolFilter::UpdateAssignData(const std::unordered_map& args, int32_t index) +{ + auto assignTaskId = base::StrToInt(args.at("taskId ")); + auto executeId = base::StrToInt(args.at(" executeId ")); + auto priority = base::StrToInt(args.at(" priority ")); + auto executeState = base::StrToInt(args.at(" executeState ")); + + int32_t returnValue = CheckTheSameTask(executeId.value()); + if (returnValue == INVALID_INT32) { + int32_t taskIndex = traceDataCache_->GetTaskPoolData()->AppendAllocationTaskData( + index, assignTaskId.value(), executeId.value(), priority.value(), executeState.value()); + executeMap_.emplace(executeId.value(), taskIndex); + } else { + traceDataCache_->GetTaskPoolData()->UpdateAllocationTaskData(returnValue, index, assignTaskId.value(), + priority.value(), executeState.value()); + } +} + +void TaskPoolFilter::UpdateExecuteData(const std::unordered_map& args, int32_t index) +{ + auto executeTaskId = base::StrToInt(args.at("taskId ")); + auto executeId = base::StrToInt(args.at(" executeId ")); + + int32_t returnValue = CheckTheSameTask(executeId.value()); + if (returnValue == INVALID_INT32) { + int32_t taskIndex = + traceDataCache_->GetTaskPoolData()->AppendExecuteTaskData(index, executeTaskId.value(), executeId.value()); + executeMap_.emplace(executeId.value(), taskIndex); + } else { + traceDataCache_->GetTaskPoolData()->UpdateExecuteTaskData(returnValue, index, executeTaskId.value()); + } +} + +void TaskPoolFilter::UpdateReturnData(const std::unordered_map& args, int32_t index) +{ + int32_t returnState; + auto returnTaskId = base::StrToInt(args.at("taskId ")); + auto executeId = base::StrToInt(args.at(" executeId ")); + auto returnStr = std::string_view(args.at(" performResult ")); + if (!returnStr.compare(" Successful")) { + returnState = 1; + } else { + returnState = 0; + } + + int32_t returnValue = CheckTheSameTask(executeId.value()); + if (returnValue == INVALID_INT32) { + int32_t taskIndex = traceDataCache_->GetTaskPoolData()->AppendReturnTaskData(index, returnTaskId.value(), + executeId.value(), returnState); + executeMap_.emplace(executeId.value(), taskIndex); + } else { + traceDataCache_->GetTaskPoolData()->UpdateReturnTaskData(returnValue, index, returnTaskId.value(), returnState); + } +} + +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/src/filter/task_pool_filter.h b/trace_streamer/src/filter/task_pool_filter.h new file mode 100644 index 000000000..1ed65caf8 --- /dev/null +++ b/trace_streamer/src/filter/task_pool_filter.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 TAKS_POOL_FILTER_H +#define TAKS_POOL_FILTER_H + +#include +#include +#include + +#include "filter_base.h" +#include "string_help.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +class TaskPoolFilter : private FilterBase { +public: + TaskPoolFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + TaskPoolFilter(const TaskPoolFilter&) = delete; + ~TaskPoolFilter() override; + uint32_t CheckTheSameTask(int32_t executeId); + void TaskPoolEvent(const std::string& taskPoolStr, int32_t index); + void TaskPoolFieldSegmentation(const std::string& taskPoolStr, std::unordered_map& args); + void UpdateAssignData(const std::unordered_map& args, int32_t index); + void UpdateExecuteData(const std::unordered_map& args, int32_t index); + void UpdateReturnData(const std::unordered_map& args, int32_t index); + +private: + std::unordered_map executeMap_ = {}; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // TAKS_POOL_FILTER_H diff --git a/trace_streamer/src/include/BUILD.gn b/trace_streamer/src/include/BUILD.gn index 406b80d34..700014459 100755 --- a/trace_streamer/src/include/BUILD.gn +++ b/trace_streamer/src/include/BUILD.gn @@ -12,8 +12,8 @@ # limitations under the License. import("//build/ohos.gni") ohos_source_set("ibase") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "codec_cov.h", "file.h", diff --git a/trace_streamer/src/main.cpp b/trace_streamer/src/main.cpp index eff838d35..74d020163 100644 --- a/trace_streamer/src/main.cpp +++ b/trace_streamer/src/main.cpp @@ -96,8 +96,6 @@ void LoadQueryFile(const std::string& sqlOperator, std::vector& sql auto fd = fopen(sqlOperator.c_str(), "r"); if (!fd) { TS_LOGE("open file failed!"); - fclose(fd); - fd = nullptr; return; } char buffer[G_CHUNK_SIZE]; @@ -128,7 +126,7 @@ void ReadSqlFileAndPrintResult(TraceStreamerSelector& ts, const std::string& sql { std::vector sqlStrings; LoadQueryFile(sqlOperator, sqlStrings); - for (auto& str : sqlStrings) { + for (const auto& str : sqlStrings) { ts.SearchDatabase(str, true); } } diff --git a/trace_streamer/src/parser/BUILD.gn b/trace_streamer/src/parser/BUILD.gn index dda3066ae..2a5e21d6a 100644 --- a/trace_streamer/src/parser/BUILD.gn +++ b/trace_streamer/src/parser/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../build/ts.gni") ohos_source_set("parser") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "bytrace_parser/bytrace_event_parser.cpp", "bytrace_parser/bytrace_event_parser.h", @@ -31,16 +31,16 @@ ohos_source_set("parser") { "thread_state_flag.h", ] deps = [ - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:cpu_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/diskio_data:diskio_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hidump_data:hidump_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:hilog_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:hisysevent_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/js_memory:js_memory_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/network_data:network_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/process_data:process_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:cpu_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/diskio_data:diskio_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hidump_data:hidump_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:hilog_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:hisysevent_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/js_memory:js_memory_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/network_data:network_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/process_data:process_data_encoder", "ebpf_parser:ebpf_parser", ] deps += [ "htrace_pbreader_parser:htrace_pbreader_parser" ] @@ -57,7 +57,6 @@ ohos_source_set("parser") { "${SRC}", ".", "${THIRD_PARTY}/json-master/single_include/nlohmann", - "${THIRD_PARTY}/json/single_include/nlohmann", ] include_dirs += [ "htrace_pbreader_parser" ] diff --git a/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp b/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp index 810599a19..7fbc40684 100644 --- a/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp +++ b/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp @@ -642,7 +642,7 @@ bool BytraceEventParser::BinderTransactionAllocBufEvent(const ArgsMap& args, con } void BytraceEventParser::ParseDataItem(const BytraceLine& line) { - eventList_.push_back(std::make_unique(line.ts, std::move(line))); + eventList_.push_back(std::move(std::make_unique(line.ts, std::move(line)))); return; } void BytraceEventParser::GetDataSegArgs(BytraceLine& bufLine, ArgsMap& args, uint32_t& tgid) const diff --git a/trace_streamer/src/parser/ebpf_parser/BUILD.gn b/trace_streamer/src/parser/ebpf_parser/BUILD.gn index 4a1a98947..df0b8c003 100644 --- a/trace_streamer/src/parser/ebpf_parser/BUILD.gn +++ b/trace_streamer/src/parser/ebpf_parser/BUILD.gn @@ -14,8 +14,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("ebpf_parser_src") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "bio_latency_data_parser.cpp", "bio_latency_data_parser.h", @@ -44,7 +44,7 @@ ohos_source_set("ebpf_parser_src") { "${THIRD_PARTY}/protobuf/src", "${THIRD_PARTY}/sqlite/include", ] - public_deps = [ "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_reader" ] + public_deps = [ "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_encoder" ] if (is_win || is_macx) { include_dirs += [ "${THIRD_PARTY}/perf_include/linux", diff --git a/trace_streamer/src/parser/ebpf_parser/bio_latency_data_parser.cpp b/trace_streamer/src/parser/ebpf_parser/bio_latency_data_parser.cpp index a12fb408f..7f3e9c478 100644 --- a/trace_streamer/src/parser/ebpf_parser/bio_latency_data_parser.cpp +++ b/trace_streamer/src/parser/ebpf_parser/bio_latency_data_parser.cpp @@ -68,7 +68,7 @@ void BioLatencyDataParser::ParseBioLatencyEvent() auto newEndTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, endTs); timeParser_->UpdatePluginTimeRange(clockId_, endTs, newEndTs); if (newStartTs > newEndTs) { - TS_LOGE("File system event origin startTs = %llu, endTs = %llu, newStartTs = %llu, newEndTs = %llu", startTs, + TS_LOGE("File system event origin startTs = %lu, endTs = %lu, newStartTs = %lu, newEndTs = %lu", startTs, endTs, newStartTs, newEndTs); streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_PAGED_MEMORY, STAT_EVENT_DATA_INVALID); return; diff --git a/trace_streamer/src/parser/ebpf_parser/ebpf_data_reader.cpp b/trace_streamer/src/parser/ebpf_parser/ebpf_data_reader.cpp index fe1b8a869..cc191bdfb 100644 --- a/trace_streamer/src/parser/ebpf_parser/ebpf_data_reader.cpp +++ b/trace_streamer/src/parser/ebpf_parser/ebpf_data_reader.cpp @@ -16,7 +16,6 @@ #include "ebpf_data_reader.h" #include "file_system_data_parser.h" #include "string_help.h" -#include namespace SysTuning { namespace TraceStreamer { @@ -24,7 +23,7 @@ using namespace SysTuning::base; using namespace SysTuning::EbpfStdtype; EbpfDataReader::EbpfDataReader(TraceDataCache* dataCache, const TraceStreamerFilters* filter) : EventParserBase(dataCache, filter), - ebpfDataHeader_(nullptr), + ebpfDataHeader_(reinterpret_cast(startAddr_)), pidAndStartAddrToMapsAddr_(nullptr), elfAddrAndStValueToSymAddr_(nullptr), tracerEventToStrIndex_(INVALID_UINT64), @@ -48,20 +47,20 @@ bool EbpfDataReader::InitEbpfData(const std::deque& dequeBuffer, uint64 bool EbpfDataReader::InitEbpfHeader() { if (bufferSize_ < EbpfDataHeader::EBPF_DATA_HEADER_SIZE) { - TS_LOGE("buffer size less than ebpf data header!!!, bufferSize_ = %llu ", bufferSize_); + TS_LOGE("buffer size less than ebpf data header!!!, bufferSize_ = %lu ", bufferSize_); return false; } ebpfDataHeader_ = reinterpret_cast(startAddr_); if (ebpfDataHeader_->header.magic != EbpfDataHeader::HEADER_MAGIC) { - TS_LOGE("Get EBPF file header failed! magic = %llx", ebpfDataHeader_->header.magic); + TS_LOGE("Get EBPF file header failed! magic = %lx", ebpfDataHeader_->header.magic); return false; } if (ebpfDataHeader_->header.headSize != EbpfDataHeader::EBPF_DATA_HEADER_SIZE) { TS_LOGE("Get ebpf file header failed! headSize = %u", ebpfDataHeader_->header.headSize); return false; } - TS_LOGI("EBPF data header : magic = %" PRIu64", headSize = %u, clock = %u, cmdline = %s", + TS_LOGI("EBPF data header : magic = %llx, headSize = %llu, clock = %llu, cmdline = %s", ebpfDataHeader_->header.magic, ebpfDataHeader_->header.headSize, ebpfDataHeader_->header.clock, ebpfDataHeader_->cmdline); startAddr_ += EbpfDataHeader::EBPF_DATA_HEADER_SIZE; @@ -77,7 +76,7 @@ bool EbpfDataReader::ReadEbpfData() unresolvedLen_ -= EBPF_TITLE_SIZE; if (dataTitle->length > unresolvedLen_) { TS_LOGE("Get EBPF data Title failed!"); - TS_LOGE("type = %x, length = %x", dataTitle->type, dataTitle->length); + TS_LOGE("type = %lx, length = %lx", dataTitle->type, dataTitle->length); return false; } if (dataTitle->length == 0) { @@ -187,7 +186,7 @@ void EbpfDataReader::ReadKernelSymAddrMap(const KernelSymbolInfoHeader* elfAddr, maxKernelAddr_ = elfAddr->vaddrEnd; minKernelAddr_ = elfAddr->vaddrStart; for (auto i = 0; i < sysItemSize; i++) { - (void)memset_s(strSymbolName_, MAX_SYMBOL_LENGTH, 0, MAX_SYMBOL_LENGTH); + (void*)memset_s(strSymbolName_, MAX_SYMBOL_LENGTH, 0, MAX_SYMBOL_LENGTH); auto item = start + i; if (strncpy_s(strSymbolName_, MAX_SYMBOL_LENGTH, strTab + item->nameOffset, MAX_SYMBOL_LENGTH) < 0) { TS_LOGE("get kernel symbol name error"); diff --git a/trace_streamer/src/parser/ebpf_parser/file_system_data_parser.cpp b/trace_streamer/src/parser/ebpf_parser/file_system_data_parser.cpp index 0bb185e64..7293d55af 100644 --- a/trace_streamer/src/parser/ebpf_parser/file_system_data_parser.cpp +++ b/trace_streamer/src/parser/ebpf_parser/file_system_data_parser.cpp @@ -77,7 +77,7 @@ void FileSystemDataParser::ParseFileSystemEvent() auto newEndTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, fsFixedHeadrAddr->endTime); timeParser_->UpdatePluginTimeRange(clockId_, fsFixedHeadrAddr->endTime, newEndTs); if (newStartTs > newEndTs) { - TS_LOGE("File system event origin startTs = %llu, endTs = %llu, newStartTs = %llu, newEndTs = %llu", + TS_LOGE("File system event origin startTs = %lu, endTs = %lu, newStartTs = %lu, newEndTs = %lu", fsFixedHeadrAddr->startTime, fsFixedHeadrAddr->endTime, newStartTs, newEndTs); streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_FILE_SYSTEM, STAT_EVENT_DATA_INVALID); return; diff --git a/trace_streamer/src/parser/ebpf_parser/paged_memory_data_parser.cpp b/trace_streamer/src/parser/ebpf_parser/paged_memory_data_parser.cpp index 70a5a3478..b159da1d4 100644 --- a/trace_streamer/src/parser/ebpf_parser/paged_memory_data_parser.cpp +++ b/trace_streamer/src/parser/ebpf_parser/paged_memory_data_parser.cpp @@ -54,7 +54,7 @@ void PagedMemoryDataParser::ParsePagedMemoryEvent() currentCallId_ = callChainId_++; } } else { - currentCallId_ = INVALID_UINT32; + currentCallId_ = INVALID_UINT64; } auto type = pagedMemoryFixedHeadrAddr->type; @@ -71,7 +71,7 @@ void PagedMemoryDataParser::ParsePagedMemoryEvent() auto newEndTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, endTs); timeParser_->UpdatePluginTimeRange(clockId_, endTs, newEndTs); if (newStartTs > newEndTs) { - TS_LOGE("paged memory startTs = %llu, endTs = %llu, newStartTs = %llu, newEndTs = %llu", startTs, endTs, + TS_LOGE("paged memory startTs = %lu, endTs = %lu, newStartTs = %lu, newEndTs = %lu", startTs, endTs, newStartTs, newEndTs); streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_PAGED_MEMORY, STAT_EVENT_DATA_INVALID); return; diff --git a/trace_streamer/src/parser/hiperf_parser/BUILD.gn b/trace_streamer/src/parser/hiperf_parser/BUILD.gn index 445869e40..9a9e90161 100644 --- a/trace_streamer/src/parser/hiperf_parser/BUILD.gn +++ b/trace_streamer/src/parser/hiperf_parser/BUILD.gn @@ -14,8 +14,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("hiperf_parser_src") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "perf_data_parser.cpp" ] include_dirs = [ "${THIRD_PARTY}/hiperf/include/nonlinux/linux", @@ -34,18 +34,11 @@ ohos_source_set("hiperf_parser_src") { "${THIRD_PARTY}/protobuf/src", "${THIRD_PARTY}/perf_include", "${THIRD_PARTY}/perf_include/libbpf", - "//developtools/hiperf/include", - "//commonlibrary/c_utils/base/include", - "${THIRD_PARTY}/googletest/googletest/include", ] include_dirs += [ "${THIRD_PARTY}/libunwind/include" ] - cflags = [ "-D target_cpu_${target_cpu}" ] - if (!use_wasm && !is_win && !is_macx && !is_test) { - cflags += [ "-D HAVE_LIBUNWIND" ] - } if (enable_ts_utest && !use_wasm) { - cflags += [ + cflags = [ "-fprofile-arcs", "-ftest-coverage", ] @@ -63,7 +56,7 @@ ohos_source_set("hiperf_parser_src") { group("hiperf_parser") { deps = [ ":hiperf_parser_src", - "${PERF_DIR}/hiperf:hiperf_platform_common", + "${PERF_DIR}/hiperf:hiperf", "${THIRD_PARTY}/protobuf:protobuf", "${THIRD_PARTY}/protobuf:protobuf_lite", ] diff --git a/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp b/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp index 0d75bee49..c268c099b 100644 --- a/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp +++ b/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp @@ -73,8 +73,8 @@ bool PerfDataParser::LoadPerfData() fprintf(stdout, "Failed to create file: %s", tmpPerfData_.c_str()); return false; } - (void)ftruncate(fd, 0); - if (bufferSize_ != (size_t)write(fd, buffer_.get(), bufferSize_)) { + auto ret = ftruncate(fd, 0); + if (bufferSize_ != write(fd, buffer_.get(), bufferSize_)) { close(fd); return false; } @@ -263,7 +263,7 @@ uint32_t PerfDataParser::UpdatePerfCallChainData(const std::unique_ptrsecond; callStackTemp.emplace_back( - std::make_unique(depth, frame->vaddrInFile_, fileId, symbolId)); + std::move(std::make_unique(depth, frame->vaddrInFile_, fileId, symbolId))); depth++; } // Determine whether to write callstack data to cache diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/BUILD.gn b/trace_streamer/src/parser/htrace_pbreader_parser/BUILD.gn index d865bc06e..4cf1aa16c 100755 --- a/trace_streamer/src/parser/htrace_pbreader_parser/BUILD.gn +++ b/trace_streamer/src/parser/htrace_pbreader_parser/BUILD.gn @@ -13,8 +13,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("htrace_pbreader_parser_src") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "../parser_base.cpp", "htrace_clock_detail_parser.cpp", @@ -62,7 +62,6 @@ ohos_source_set("htrace_pbreader_parser_src") { "${THIRD_PARTY}/protobuf/src", "${THIRD_PARTY}/sqlite/include", "${THIRD_PARTY}/json-master/single_include/nlohmann", - "${THIRD_PARTY}/json/single_include/nlohmann", "../../filter", "../../base", "../ebpf_parser", @@ -73,24 +72,20 @@ ohos_source_set("htrace_pbreader_parser_src") { "${THIRD_PARTY}/hiperf/include", "${THIRD_PARTY}/hiperf/include/nonlinux/linux", "${THIRD_PARTY}/hiperf/include/nonlinux", - "//developtools/hiperf/include", - "${THIRD_PARTY}/musl", - "${THIRD_PARTY}/googletest/googletest/include", - "${THIRD_PARTY}/perf_include/musl", - "${THIRD_PARTY}/perf_include/libbpf", - "${THIRD_PARTY}/perf_include/include", - "${THIRD_PARTY}/perf_include", - "${THIRD_PARTY}/perf_include/linux", - "../hiperf_parser", - "../hiperf_parser/include", ] - - cflags = [ "-D target_cpu_${target_cpu}" ] - if (!use_wasm && !is_win && !is_macx && !is_test) { - cflags += [ "-D HAVE_LIBUNWIND" ] + if (with_perf) { + include_dirs += [ + "${THIRD_PARTY}/perf_include/musl", + "${THIRD_PARTY}/perf_include/libbpf", + "${THIRD_PARTY}/perf_include/include", + "${THIRD_PARTY}/perf_include", + "${THIRD_PARTY}/perf_include/linux", + "../hiperf_parser", + "../hiperf_parser/include", + ] } if (enable_ts_utest && !use_wasm) { - cflags += [ + cflags = [ "-fprofile-arcs", "-ftest-coverage", ] @@ -102,18 +97,18 @@ ohos_source_set("htrace_pbreader_parser_src") { } public_deps = [] deps = [ - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/services:ts_all_type_cpp_standard", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:cpu_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/diskio_data:diskio_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/ftrace_data/${device_kernel_version}:ftrace_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hidump_data:hidump_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:hilog_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:hisysevent_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/js_memory:js_memory_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/network_data:network_data_reader", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/process_data:process_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/services:all_type_cpp_standard", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:cpu_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/diskio_data:diskio_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/ftrace_data/${device_kernel_version}:ftrace_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hidump_data:hidump_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:hilog_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:hisysevent_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/js_memory:js_memory_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/network_data:network_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/process_data:process_data_encoder", ] } group("htrace_pbreader_parser") { diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_clock_detail_parser.cpp b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_clock_detail_parser.cpp index af1d16a92..102e7e8e7 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_clock_detail_parser.cpp +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_clock_detail_parser.cpp @@ -19,8 +19,6 @@ #include "process_filter.h" #include "stat_filter.h" #include "symbols_filter.h" -#include - namespace SysTuning { namespace TraceStreamer { HtraceClockDetailParser::HtraceClockDetailParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters) @@ -74,32 +72,32 @@ void HtraceClockDetailParser::Parse(const ProfilerTraceFileHeader* profilerTrace std::vector snapShot; TS_LOGI("got clock snapshot"); - TS_LOGI("clockid: TS_CLOCK_BOOTTIME, ts:%" PRIu64"", profilerTraceFileHeader->data.boottime); + TS_LOGI("clockid: TS_CLOCK_BOOTTIME, ts:%llu", profilerTraceFileHeader->data.boottime); if (profilerTraceFileHeader->data.boottime) { snapShot.push_back(SnapShot{TS_CLOCK_BOOTTIME, profilerTraceFileHeader->data.boottime}); } - TS_LOGI("clockid: TS_CLOCK_REALTIME, ts:%" PRIu64"", profilerTraceFileHeader->data.realtime); + TS_LOGI("clockid: TS_CLOCK_REALTIME, ts:%llu", profilerTraceFileHeader->data.realtime); if (profilerTraceFileHeader->data.realtime) { snapShot.push_back(SnapShot{TS_CLOCK_REALTIME, profilerTraceFileHeader->data.realtime}); } - TS_LOGI("clockid: TS_CLOCK_REALTIME_COARSE, ts:%" PRIu64"", profilerTraceFileHeader->data.realtimeCoarse); + TS_LOGI("clockid: TS_CLOCK_REALTIME_COARSE, ts:%llu", profilerTraceFileHeader->data.realtimeCoarse); if (profilerTraceFileHeader->data.realtimeCoarse) { snapShot.push_back(SnapShot{TS_CLOCK_REALTIME_COARSE, profilerTraceFileHeader->data.realtimeCoarse}); } - TS_LOGI("clockid: TS_MONOTONIC, ts:%" PRIu64"", profilerTraceFileHeader->data.monotonic); + TS_LOGI("clockid: TS_MONOTONIC, ts:%llu", profilerTraceFileHeader->data.monotonic); if (profilerTraceFileHeader->data.monotonic) { snapShot.push_back(SnapShot{TS_MONOTONIC, profilerTraceFileHeader->data.monotonic}); } - TS_LOGI("clockid: TS_MONOTONIC_COARSE, ts:%" PRIu64"", profilerTraceFileHeader->data.monotonicCoarse); + TS_LOGI("clockid: TS_MONOTONIC_COARSE, ts:%llu", profilerTraceFileHeader->data.monotonicCoarse); if (profilerTraceFileHeader->data.monotonicCoarse) { snapShot.push_back(SnapShot{TS_MONOTONIC_COARSE, profilerTraceFileHeader->data.monotonicCoarse}); } - TS_LOGI("clockid: TS_MONOTONIC_RAW, ts:%" PRIu64"", profilerTraceFileHeader->data.monotonicRaw); + TS_LOGI("clockid: TS_MONOTONIC_RAW, ts:%llu", profilerTraceFileHeader->data.monotonicRaw); if (profilerTraceFileHeader->data.monotonicRaw) { snapShot.push_back(SnapShot{TS_MONOTONIC_RAW, profilerTraceFileHeader->data.monotonicRaw}); } diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.cpp b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.cpp index 8869ef6b7..491537236 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.cpp +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.cpp @@ -36,6 +36,7 @@ void HtraceCpuDataParser::Parse(ProtoReader::BytesView tracePacket, uint64_t ts) return; } if (cpuData.has_cpu_usage_info()) { + auto cpuInfo = cpuData.cpu_usage_info(); auto userLoad = cpuData.user_load(); auto sysLoad = cpuData.sys_load(); auto process_num = cpuData.process_num(); diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.h b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.h index 5954b8ebc..abb3282cc 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.h +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.h @@ -71,6 +71,7 @@ public: private: std::string threadStateDesc_[ProtoReader::THREAD_WAITING + 1] = {"undefined", "Running", "Sleep", "Sloped", "Watting"}; + uint64_t lastLineSeq_ = 0; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_event_parser/htrace_event_parser.cpp b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_event_parser/htrace_event_parser.cpp index b228be926..0b3afb071 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_event_parser/htrace_event_parser.cpp +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_event_parser/htrace_event_parser.cpp @@ -164,7 +164,7 @@ void HtraceEventParser::ParseDataItem(HtraceDataSegment& tracePacket, BuiltinClo lastOverwrite_ = msg.overwrite(); } if (lastOverwrite_ != msg.overwrite()) { - TS_LOGW("lost events:%llu", msg.overwrite() - lastOverwrite_); + TS_LOGW("lost events:%lu", msg.overwrite() - lastOverwrite_); lastOverwrite_ = msg.overwrite(); } streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_LOST); @@ -176,7 +176,8 @@ void HtraceEventParser::ParseDataItem(HtraceDataSegment& tracePacket, BuiltinClo ProtoReader::BytesView event(i->ToBytes()); uint64_t timeStamp = 0; if (event.size_ > MIN_DATA_AREA && event.data_[0] == tsTag) { - (void)ProtoReader::VarIntDecode(event.data_ + DATA_AREA_START, event.data_ + DATA_AREA_END, &timeStamp); + const uint8_t* nextData = + ProtoReader::VarIntDecode(event.data_ + DATA_AREA_START, event.data_ + DATA_AREA_END, &timeStamp); } eventTimeStamp_ = timeStamp; ftraceOriginStartTime_ = std::min(ftraceOriginStartTime_, eventTimeStamp_); @@ -187,7 +188,7 @@ void HtraceEventParser::ParseDataItem(HtraceDataSegment& tracePacket, BuiltinClo traceDataCache_->UpdateTraceTime(eventTimeStamp_); ProtoReader::BytesView commonField; eventList_.push_back( - std::make_unique(eventTimeStamp_, eventCpu_, tracePacket.seg, i->ToBytes())); + std::move(std::make_unique(eventTimeStamp_, eventCpu_, tracePacket.seg, i->ToBytes()))); FilterAllEventsReader(); } } diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_network_parser.cpp b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_network_parser.cpp index 79f804934..49597383f 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_network_parser.cpp +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_network_parser.cpp @@ -44,7 +44,7 @@ void HtraceNetworkParser::Parse(ProtoReader::BytesView tracePacket, uint64_t ts) ts = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, ts); streamFilters_->statFilter_->IncreaseStat(TRACE_NETWORK, STAT_EVENT_RECEIVED); - networkData_.push_back(TsNetworkData{ts, tv_sec, tv_nsec, rx_bytes, rx_packets, tx_bytes, tx_packets}); + networkData_.push_back(std::move(TsNetworkData{ts, tv_sec, tv_nsec, rx_bytes, rx_packets, tx_bytes, tx_packets})); } void HtraceNetworkParser::Finish() { diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.cpp b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.cpp index f55fc980e..5e079c368 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.cpp +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.cpp @@ -46,7 +46,9 @@ HtraceParser::HtraceParser(TraceDataCache* dataCache, const TraceStreamerFilters processParser_(std::make_unique(dataCache, filters)), hisyseventParser_(std::make_unique(dataCache, filters)), jsMemoryParser_(std::make_unique(dataCache, filters)), +#if WITH_PERF perfDataParser_(std::make_unique(dataCache, filters)), +#endif #ifdef SUPPORTTHREAD supportThread_(true), dataSegArray_(std::make_unique(MAX_SEG_ARRAY_SIZE)) @@ -143,9 +145,11 @@ bool HtraceParser::ReparseSymbolFilesAndResymbolization(std::string& symbolsPath std::vector& symbolsPaths) { auto parsePerfStatus = false; +#if WITH_PERF std::vector dir; dir.emplace_back(symbolsPath); parsePerfStatus = perfDataParser_->PerfReloadSymbolFiles(dir); +#endif auto parseFileSOStatus = ParserFileSO(symbolsPath, symbolsPaths); if (!parseFileSOStatus) { elfSymbolTables_.reset(); @@ -180,7 +184,9 @@ void HtraceParser::WaitForParserEnd() jsMemoryParser_->Finish(); // keep final upate perf and ebpf data time range ebpfDataParser_->Finish(); +#if WITH_PERF perfDataParser_->Finish(); +#endif htraceNativeHookParser_->Finish(); htraceMemParser_->Finish(); traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_TRACE, @@ -385,7 +391,7 @@ void HtraceParser::ParserData(HtraceDataSegment& dataSeg) return; } if (!supportThread_) { // do it only in wasm mode, wasm noThead_ will be true - if (dataSeg.status == TS_PARSE_STATUS_INVALID) { + if (dataSeg.status == STAT_EVENT_DATA_INVALID) { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID); return; } @@ -580,6 +586,7 @@ bool HtraceParser::ParseDataRecursively(std::deque::iterator& packagesB } if (profilerTraceFileHeader_.data.dataType == ProfilerTraceFileHeader::HIPERF_DATA) { if (packagesBuffer_.size() >= profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH) { +#if WITH_PERF auto size = profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH; perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, size); currentLength -= size; @@ -587,6 +594,7 @@ bool HtraceParser::ParseDataRecursively(std::deque::iterator& packagesB profilerTraceFileHeader_.data.dataType = ProfilerTraceFileHeader::UNKNOW_TYPE; hasGotHeader_ = false; return true; +#endif } return false; } @@ -636,7 +644,7 @@ bool HtraceParser::ParseDataRecursively(std::deque::iterator& packagesB packagesBegin += nextLength_; currentLength -= nextLength_; if (nextLength_ > htraceCurentLength_) { - TS_LOGE("fatal error, data length not match nextLength_:%u, htraceCurentLength_:%" PRIu64"", nextLength_, + TS_LOGE("fatal error, data length not match nextLength_:%u, htraceCurentLength_:%llu", nextLength_, htraceCurentLength_); } htraceCurentLength_ -= nextLength_; @@ -686,7 +694,7 @@ bool HtraceParser::InitProfilerTraceFileHeader() } auto ret = memcpy_s(&profilerTraceFileHeader_, sizeof(profilerTraceFileHeader_), buffer, PACKET_HEADER_LENGTH); if (ret == -1 || profilerTraceFileHeader_.data.magic != ProfilerTraceFileHeader::HEADER_MAGIC) { - TS_LOGE("Get profiler trace file header failed! ret = %d, magic = %llx", ret, + TS_LOGE("Get profiler trace file header failed! ret = %d, magic = %lx", ret, profilerTraceFileHeader_.data.magic); return false; } @@ -694,7 +702,7 @@ bool HtraceParser::InitProfilerTraceFileHeader() TS_LOGE("Profiler Trace data is truncated!!!"); return false; } - TS_LOGI("magic = %llx, length = %" PRIu64", dataType = %x, boottime = %" PRIu64"", profilerTraceFileHeader_.data.magic, + TS_LOGI("magic = %lx, length = %llx, dataType = %llx, boottime = %llx", profilerTraceFileHeader_.data.magic, profilerTraceFileHeader_.data.length, profilerTraceFileHeader_.data.dataType, profilerTraceFileHeader_.data.boottime); #if IS_WASM diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.h b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.h index cc7041821..44d4a0319 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.h +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.h @@ -42,7 +42,9 @@ #include "htrace_symbols_detail_parser.h" #include "log.h" #include "parser_base.h" +#if WITH_PERF #include "perf_data_parser.h" +#endif #include "proto_reader_help.h" #include "string_help.h" #include "trace_data/trace_data_cache.h" @@ -53,7 +55,9 @@ namespace SysTuning { namespace TraceStreamer { using namespace SysTuning::base; using namespace OHOS::Developtools::HiPerf::ELF; +#if WITH_PERF using namespace OHOS::Developtools::HiPerf; +#endif class HtraceParser : public ParserBase { public: HtraceParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters); @@ -115,7 +119,9 @@ private: std::unique_ptr processParser_; std::unique_ptr hisyseventParser_; std::unique_ptr jsMemoryParser_; +#if WITH_PERF std::unique_ptr perfDataParser_; +#endif std::unique_ptr ebpfDataParser_; std::atomic filterThreadStarted_{false}; const int32_t MAX_SEG_ARRAY_SIZE = 10000; @@ -125,6 +131,7 @@ private: bool exited_ = false; int32_t filterHead_ = 0; int32_t parseHead_ = 0; + size_t sizeAll_ = 0; size_t htraceLength_ = 1024; const int32_t sleepDur_ = 100; bool parseThreadStarted_ = false; diff --git a/trace_streamer/src/parser/print_event_parser.cpp b/trace_streamer/src/parser/print_event_parser.cpp index 7b9f862ea..b3accb583 100644 --- a/trace_streamer/src/parser/print_event_parser.cpp +++ b/trace_streamer/src/parser/print_event_parser.cpp @@ -17,7 +17,6 @@ #include "frame_filter.h" #include "stat_filter.h" #include "string_to_numerical.h" -#include namespace SysTuning { namespace TraceStreamer { PrintEventParser::PrintEventParser(TraceDataCache* dataCache, const TraceStreamerFilters* filter) @@ -62,6 +61,7 @@ bool PrintEventParser::ParsePrintEvent(const std::string& comm, if (pid == point.tgid_) { HandleFrameSliceBeginEvent(point.funcPrefixId_, index, point.funcArgs_, line); } + streamFilters_->taskPoolFilter_->TaskPoolEvent(point.name_, index); } else { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_LOST); } @@ -307,10 +307,10 @@ void PrintEventParser::HandleFrameSliceEndEvent(uint64_t ts, uint64_t pid, uint6 auto iTid = streamFilters_->processFilter_->GetInternalTid(tid); auto pos = std::find(vsyncSliceIds_.begin(), vsyncSliceIds_.end(), callStackRow); if (pos != vsyncSliceIds_.end()) { - TS_LOGD("ts:%" PRIu64", RenderSliceEnd:%" PRIu64", callStackRow:%zu", ts, tid, callStackRow); + TS_LOGD("ts:%llu, RenderSliceEnd:%llu, callStackRow:%zu", ts, tid, callStackRow); if (!streamFilters_->frameFilter_->EndVsyncEvent(ts, iTid)) { streamFilters_->statFilter_->IncreaseStat(TRACE_VSYNC, STAT_EVENT_NOTMATCH); - TS_LOGW("ts:%" PRIu64", RenderSliceEnd:%" PRIu64", callStackRow:%zu failed", ts, tid, callStackRow); + TS_LOGW("ts:%llu, RenderSliceEnd:%llu, callStackRow:%zu failed", ts, tid, callStackRow); } vsyncSliceIds_.erase(pos); } @@ -323,10 +323,10 @@ void PrintEventParser::HandleFrameQueueEndEvent(uint64_t ts, uint64_t pid, uint6 auto iTid = streamFilters_->processFilter_->GetInternalTid(tid); auto pos = std::find(frameCallIds_.begin(), frameCallIds_.end(), callStackRow); if (pos != frameCallIds_.end()) { - TS_LOGD("ts:%" PRIu64", frameSliceEnd:%" PRIu64"", ts, tid); + TS_LOGD("ts:%llu, frameSliceEnd:%u", ts, tid); if (!streamFilters_->frameFilter_->EndFrameQueue(ts, iTid)) { streamFilters_->statFilter_->IncreaseStat(TRACE_FRAMEQUEUE, STAT_EVENT_NOTMATCH); - TS_LOGW("ts:%" PRIu64", frameSliceEnd:%" PRIu64" failed", ts, tid); + TS_LOGW("ts:%llu, frameSliceEnd:%lu failed", ts, tid); } frameCallIds_.erase(pos); } diff --git a/trace_streamer/src/parser/print_event_parser.h b/trace_streamer/src/parser/print_event_parser.h index fca52f7da..b6a3dda25 100644 --- a/trace_streamer/src/parser/print_event_parser.h +++ b/trace_streamer/src/parser/print_event_parser.h @@ -21,6 +21,7 @@ #include "filter/measure_filter.h" #include "filter/process_filter.h" #include "filter/slice_filter.h" +#include "filter/task_pool_filter.h" #include "string_to_numerical.h" #include "trace_streamer_config.h" namespace SysTuning { diff --git a/trace_streamer/src/proto_reader/BUILD.gn b/trace_streamer/src/proto_reader/BUILD.gn index 5768c79bf..d97d7de56 100755 --- a/trace_streamer/src/proto_reader/BUILD.gn +++ b/trace_streamer/src/proto_reader/BUILD.gn @@ -14,10 +14,12 @@ import("//build/ohos.gni") import("../../build/ts.gni") ohos_source_set("proto_reader") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" + public_configs = [ "../../gn:default_config" ] public_deps = [] include_dirs = [ "include" ] + deps = [ "../../gn:default_deps" ] sources = [ "proto_reader.cpp" ] include_dirs += [ "../include", diff --git a/trace_streamer/src/proto_reader/include/data_area.h b/trace_streamer/src/proto_reader/include/data_area.h index f5b8a1913..1a3ac3fec 100644 --- a/trace_streamer/src/proto_reader/include/data_area.h +++ b/trace_streamer/src/proto_reader/include/data_area.h @@ -83,14 +83,14 @@ public: { float res; uint32_t value32 = static_cast(intValue_); - (void)memcpy_s(&res, sizeof(res), &value32, sizeof(value32)); + (void*)memcpy_s(&res, sizeof(res), &value32, sizeof(value32)); return res; } double ToDouble() const { double res; - (void)memcpy_s(&res, sizeof(res), &intValue_, sizeof(intValue_)); + (void*)memcpy_s(&res, sizeof(res), &intValue_, sizeof(intValue_)); return res; } diff --git a/trace_streamer/src/proto_reader/proto_reader.cpp b/trace_streamer/src/proto_reader/proto_reader.cpp index 53c993b64..7c0db3284 100644 --- a/trace_streamer/src/proto_reader/proto_reader.cpp +++ b/trace_streamer/src/proto_reader/proto_reader.cpp @@ -109,7 +109,7 @@ bool ProtoReaderBase::ParseFixed64Value(ParseDataAreaResult& result, return false; } - (void)memcpy_s(&intValue, sizeof(uint64_t), startAddr, sizeof(uint64_t)); + (void*)memcpy_s(&intValue, sizeof(uint64_t), startAddr, sizeof(uint64_t)); result.dataArea.SetDataAreaIntValue(intValue); result.next = cursor; result.status = OK; @@ -125,7 +125,7 @@ bool ProtoReaderBase::ParseFixed32Value(ParseDataAreaResult& result, if (cursor > endAddr) { return false; } - (void)memcpy_s(&intValue, sizeof(uint64_t), startAddr, sizeof(uint32_t)); + (void*)memcpy_s(&intValue, sizeof(uint64_t), startAddr, sizeof(uint32_t)); result.dataArea.SetDataAreaIntValue(intValue); result.next = cursor; result.status = OK; @@ -227,7 +227,7 @@ void ProtoReaderBase::MoveToLargerHeapStorage() { uint32_t largerVolume = volume_ << 1; std::unique_ptr largerVolumeStorage(new DataArea[largerVolume]); - (void)memcpy_s(&largerVolumeStorage[0], sizeof(DataArea) * largerVolume, dataAreas_, sizeof(DataArea) * size_); + (void*)memcpy_s(&largerVolumeStorage[0], sizeof(DataArea) * largerVolume, dataAreas_, sizeof(DataArea) * size_); lagerHeapStorage_ = std::move(largerVolumeStorage); dataAreas_ = &lagerHeapStorage_[0]; volume_ = largerVolume; diff --git a/trace_streamer/src/proto_reader/protoc_plugin/BUILD.gn b/trace_streamer/src/proto_reader/protoc_plugin/BUILD.gn index b88c8db0a..051400fd6 100755 --- a/trace_streamer/src/proto_reader/protoc_plugin/BUILD.gn +++ b/trace_streamer/src/proto_reader/protoc_plugin/BUILD.gn @@ -13,13 +13,12 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_executable("protoreader_plugin") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "proto_reader_plugin.cpp" ] deps = [ "${SRC}/base:string_help", - "${THIRD_PARTY}/protobuf:protobuf(${host_toolchain})", - "${THIRD_PARTY}/protobuf:protoc_lib(${host_toolchain})", + "${THIRD_PARTY}/protobuf:protoc_lib", ] include_dirs = [ "${SRC}/base", diff --git a/trace_streamer/src/proto_reader/protoc_plugin/proto_reader_plugin.cpp b/trace_streamer/src/proto_reader/protoc_plugin/proto_reader_plugin.cpp index 63dfbdea1..d95bf7a43 100644 --- a/trace_streamer/src/proto_reader/protoc_plugin/proto_reader_plugin.cpp +++ b/trace_streamer/src/proto_reader/protoc_plugin/proto_reader_plugin.cpp @@ -18,6 +18,7 @@ namespace SysTuning { namespace ProtoReader { const std::string SYS_NAMESPACE = "SysTuning"; +const int32_t MAX_DECODER_FIELDID = 999; const int32_t MIN_OPTIONS_SIZE = 2; bool ProtoReaderPlugin::Generate(const FileDescriptor* file, diff --git a/trace_streamer/src/protos/protos.gni b/trace_streamer/src/protos/protos.gni index 142b06ffc..b4c7ee794 100755 --- a/trace_streamer/src/protos/protos.gni +++ b/trace_streamer/src/protos/protos.gni @@ -11,7 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("../../build/ts.gni") +import("../../build/config.gni") subsys_name = OHOS_PROFILER_SUBSYS_NAME part_name = OHOS_PROFILER_PART_NAME diff --git a/trace_streamer/src/protos/services/BUILD.gn b/trace_streamer/src/protos/services/BUILD.gn index 1b7ef2ac0..a377364b5 100755 --- a/trace_streamer/src/protos/services/BUILD.gn +++ b/trace_streamer/src/protos/services/BUILD.gn @@ -44,7 +44,7 @@ all_type_codegen_all += all_type_codegen all_type_codegen_all += all_type_codegen_standard all_type_codegen_all += all_type_codegen_reader -action("ts_all_type_gen") { +action("all_type_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = all_type_proto outputs = all_type_codegen_all @@ -60,14 +60,14 @@ action("ts_all_type_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", ] } } -ohos_source_set("ts_all_type_cpp_standard") { - deps = [ ":ts_all_type_gen" ] +ohos_source_set("all_type_cpp_standard") { + deps = [ ":all_type_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -75,6 +75,6 @@ ohos_source_set("ts_all_type_cpp_standard") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":public_configs" ] sources = all_type_codegen_standard - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/agent_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/agent_data/BUILD.gn index bf6d8bc24..855f2e164 100755 --- a/trace_streamer/src/protos/types/plugins/agent_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/agent_data/BUILD.gn @@ -49,7 +49,7 @@ config("agent_include_config") { } ####################################################### -action("ts_agent_data_cpp_gen") { +action("agent_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = agent_sources outputs = agent_data_codegen_all @@ -65,16 +65,14 @@ action("ts_agent_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", ] } } -ohos_source_set("ts_agent_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_agent_data_cpp_gen" ] +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", @@ -82,4 +80,6 @@ ohos_source_set("ts_agent_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":agent_include_config" ] sources = agent_data_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/bytrace_plugin/BUILD.gn b/trace_streamer/src/protos/types/plugins/bytrace_plugin/BUILD.gn index beb68553e..d40d7c647 100755 --- a/trace_streamer/src/protos/types/plugins/bytrace_plugin/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/bytrace_plugin/BUILD.gn @@ -38,7 +38,7 @@ foreach(proto, bytrace_plugin_protos_defines) { bytrace_plugin_protos_codegen_all += bytrace_plugin_protos_codegen bytrace_plugin_protos_codegen_all += bytrace_plugin_protos_codegen_standard -action("ts_bytrace_plugin_protos_protoc") { +action("bytrace_plugin_protos_protoc") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = bytrace_plugin_protos_defines outputs = bytrace_plugin_protos_codegen_all @@ -58,10 +58,8 @@ config("bytrace_plugin_protos_config") { include_dirs = [ "$proto_out_dir" ] } -ohos_source_set("ts_bytrace_plugin_protos_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_bytrace_plugin_protos_protoc" ] +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", @@ -69,12 +67,12 @@ ohos_source_set("ts_bytrace_plugin_protos_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":bytrace_plugin_protos_config" ] sources = bytrace_plugin_protos_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } -ohos_source_set("ts_bytrace_plugin_protos_cpp_standard") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_bytrace_plugin_protos_protoc" ] +ohos_source_set("bytrace_plugin_protos_cpp_standard") { + deps = [ ":bytrace_plugin_protos_protoc" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -82,4 +80,6 @@ ohos_source_set("ts_bytrace_plugin_protos_cpp_standard") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":bytrace_plugin_protos_config" ] sources = bytrace_plugin_protos_codegen_standard + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/cpu_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/cpu_data/BUILD.gn index b25017e4c..14cab6be2 100755 --- a/trace_streamer/src/protos/types/plugins/cpu_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/cpu_data/BUILD.gn @@ -42,7 +42,7 @@ config("cpu_include_config") { } ####################################################### -action("ts_cpu_data_cpp_gen") { +action("cpu_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = cpu_data_sources outputs = cpu_data_codegen_all @@ -58,16 +58,14 @@ action("ts_cpu_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", ] } } -ohos_source_set("ts_cpu_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_cpu_data_cpp_gen" ] +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", @@ -75,13 +73,15 @@ ohos_source_set("ts_cpu_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":cpu_include_config" ] sources = cpu_data_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } -ohos_source_set("cpu_data_reader") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_cpu_data_cpp_gen" ] +ohos_source_set("cpu_data_encoder") { + deps = [ ":cpu_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":cpu_include_config" ] sources = cpu_data_codegen_reader + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/diskio_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/diskio_data/BUILD.gn index 3e10a2ded..f2941ec73 100755 --- a/trace_streamer/src/protos/types/plugins/diskio_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/diskio_data/BUILD.gn @@ -42,7 +42,7 @@ config("diskio_include_config") { } ####################################################### -action("ts_diskio_data_cpp_gen") { +action("diskio_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = diskio_data_sources outputs = diskio_data_codegen_all @@ -58,16 +58,14 @@ action("ts_diskio_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", ] } } -ohos_source_set("ts_diskio_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_diskio_data_cpp_gen" ] +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", @@ -75,13 +73,15 @@ ohos_source_set("ts_diskio_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":diskio_include_config" ] sources = diskio_data_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } -ohos_source_set("diskio_data_reader") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_diskio_data_cpp_gen" ] +ohos_source_set("diskio_data_encoder") { + deps = [ ":diskio_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":diskio_include_config" ] sources = diskio_data_codegen_reader + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/ftrace_data/default/BUILD.gn b/trace_streamer/src/protos/types/plugins/ftrace_data/default/BUILD.gn index 8979ba664..b22b0394a 100755 --- a/trace_streamer/src/protos/types/plugins/ftrace_data/default/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/ftrace_data/default/BUILD.gn @@ -40,7 +40,7 @@ foreach(proto, ftrace_data_proto) { all_proto_codegen = ftrace_data_codegen all_proto_codegen += ftrace_data_codegen_reader -action("ts_all_proto_gen") { +action("all_proto_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = all_proto outputs = all_proto_codegen @@ -56,8 +56,8 @@ action("ts_all_proto_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", ] } } @@ -66,10 +66,8 @@ config("public_configs") { include_dirs = [ "$proto_out_dir" ] } -ohos_source_set("ts_ftrace_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_all_proto_gen" ] +ohos_source_set("ftrace_data_cpp") { + deps = [ ":all_proto_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -79,10 +77,8 @@ ohos_source_set("ts_ftrace_data_cpp") { sources = ftrace_data_codegen } -ohos_source_set("ftrace_data_reader") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_all_proto_gen" ] +ohos_source_set("ftrace_data_encoder") { + deps = [ ":all_proto_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":public_configs" ] sources = ftrace_data_codegen_reader diff --git a/trace_streamer/src/protos/types/plugins/hidump_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/hidump_data/BUILD.gn index 36bb4f6c6..7eea96a9b 100755 --- a/trace_streamer/src/protos/types/plugins/hidump_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/hidump_data/BUILD.gn @@ -42,7 +42,7 @@ config("hidump_include_config") { } ####################################################### -action("ts_hidump_data_cpp_gen") { +action("hidump_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = hidump_data_sources outputs = hidump_data_codegen_all @@ -58,16 +58,14 @@ action("ts_hidump_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", ] } } -ohos_source_set("ts_hidump_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_hidump_data_cpp_gen" ] +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", @@ -75,13 +73,15 @@ ohos_source_set("ts_hidump_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hidump_include_config" ] sources = hidump_data_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } -ohos_source_set("hidump_data_reader") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_hidump_data_cpp_gen" ] +ohos_source_set("hidump_data_encoder") { + deps = [ ":hidump_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hidump_include_config" ] sources = hidump_data_codegen_reader + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/hiebpf_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/hiebpf_data/BUILD.gn index d6e71f41e..7dcc52c5c 100755 --- a/trace_streamer/src/protos/types/plugins/hiebpf_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/hiebpf_data/BUILD.gn @@ -61,8 +61,6 @@ action("hiebpf_data_cpp_gen") { } ohos_source_set("hiebpf_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":hiebpf_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", @@ -71,11 +69,11 @@ ohos_source_set("hiebpf_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hiebpf_include_config" ] sources = hiebpf_data_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } ohos_source_set("hiebpf_data_cpp_standard") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":hiebpf_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", @@ -84,4 +82,6 @@ ohos_source_set("hiebpf_data_cpp_standard") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hiebpf_include_config" ] sources = hiebpf_data_codegen_standard + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/hilog_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/hilog_data/BUILD.gn index 7b6f2a8df..2ec5dab79 100755 --- a/trace_streamer/src/protos/types/plugins/hilog_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/hilog_data/BUILD.gn @@ -42,7 +42,7 @@ config("hilog_include_config") { } ####################################################### -action("ts_hilog_data_cpp_gen") { +action("hilog_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = hilog_data_sources outputs = hilog_data_codegen_all @@ -58,16 +58,14 @@ action("ts_hilog_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", ] } } -ohos_source_set("ts_hilog_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_hilog_data_cpp_gen" ] +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", @@ -75,13 +73,15 @@ ohos_source_set("ts_hilog_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hilog_include_config" ] sources = hilog_data_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } -ohos_source_set("hilog_data_reader") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_hilog_data_cpp_gen" ] +ohos_source_set("hilog_data_encoder") { + deps = [ ":hilog_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hilog_include_config" ] sources = hilog_data_codegen_reader + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/BUILD.gn b/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/BUILD.gn index d597fe409..7ddfa159e 100755 --- a/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/BUILD.gn @@ -31,7 +31,7 @@ foreach(proto, hiperf_call_plugin_protos_defines) { ] } -action("ts_hiperf_call_plugin_protos_protoc") { +action("hiperf_call_plugin_protos_protoc") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = hiperf_call_plugin_protos_defines outputs = hiperf_call_plugin_protos_codegen @@ -50,10 +50,8 @@ config("hiperf_call_plugin_protos_config") { include_dirs = [ "$proto_out_dir" ] } -source_set("ts_hiperf_call_plugin_protos_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_hiperf_call_plugin_protos_protoc" ] +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", @@ -61,4 +59,6 @@ source_set("ts_hiperf_call_plugin_protos_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hiperf_call_plugin_protos_config" ] sources = hiperf_call_plugin_protos_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/hiperf_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/hiperf_data/BUILD.gn index 175cd2dba..eacc01021 100755 --- a/trace_streamer/src/protos/types/plugins/hiperf_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/hiperf_data/BUILD.gn @@ -38,7 +38,7 @@ foreach(proto, hiperf_data_protos_defines) { hiperf_data_protos_codegen_all += hiperf_data_protos_codegen hiperf_data_protos_codegen_all += hiperf_data_protos_codegen_standard -action("ts_hiperf_data_protos_protoc") { +action("hiperf_data_protos_protoc") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = hiperf_data_protos_defines outputs = hiperf_data_protos_codegen_all @@ -58,10 +58,8 @@ config("hiperf_data_protos_config") { include_dirs = [ "$proto_out_dir" ] } -ohos_source_set("ts_hiperf_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_hiperf_data_protos_protoc" ] +ohos_source_set("hiperf_data_cpp") { + deps = [ ":hiperf_data_protos_protoc" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -69,12 +67,12 @@ ohos_source_set("ts_hiperf_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hiperf_data_protos_config" ] sources = hiperf_data_protos_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } -ohos_source_set("ts_hiperf_data_cpp_standard") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_hiperf_data_protos_protoc" ] +ohos_source_set("hiperf_data_cpp_standard") { + deps = [ ":hiperf_data_protos_protoc" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -82,4 +80,6 @@ ohos_source_set("ts_hiperf_data_cpp_standard") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hiperf_data_protos_config" ] sources = hiperf_data_protos_codegen_standard + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/hisysevent_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/hisysevent_data/BUILD.gn index 933ef5c5e..679d3aeef 100644 --- a/trace_streamer/src/protos/types/plugins/hisysevent_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/hisysevent_data/BUILD.gn @@ -44,7 +44,7 @@ config("hisysevent_include_config") { } ####################################################### -action("ts_hisysevent_data_cpp_gen") { +action("hisysevent_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = hisysevent_data_sources outputs = hisysevent_data_codegen_all @@ -60,16 +60,14 @@ action("ts_hisysevent_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", ] } } -ohos_source_set("ts_hisysevent_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_hisysevent_data_cpp_gen" ] +ohos_source_set("hisysevent_data_cpp") { + deps = [ ":hisysevent_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -77,13 +75,15 @@ ohos_source_set("ts_hisysevent_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hisysevent_include_config" ] sources = hisysevent_data_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } -ohos_source_set("hisysevent_data_reader") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_hisysevent_data_cpp_gen" ] +ohos_source_set("hisysevent_data_encoder") { + deps = [ ":hisysevent_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hisysevent_include_config" ] sources = hisysevent_data_codegen_reader + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/js_memory/BUILD.gn b/trace_streamer/src/protos/types/plugins/js_memory/BUILD.gn index 959ac455f..c55f7b468 100755 --- a/trace_streamer/src/protos/types/plugins/js_memory/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/js_memory/BUILD.gn @@ -42,7 +42,7 @@ config("js_memory_include_config") { } ####################################################### -action("ts_js_memory_data_cpp_gen") { +action("js_memory_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = js_memory_data_sources outputs = js_memory_data_codegen_all @@ -58,16 +58,14 @@ action("ts_js_memory_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", ] } } -ohos_source_set("ts_js_memory_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_js_memory_data_cpp_gen" ] +ohos_source_set("js_memory_data_cpp") { + deps = [ ":js_memory_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -75,13 +73,15 @@ ohos_source_set("ts_js_memory_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":js_memory_include_config" ] sources = js_memory_data_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } -ohos_source_set("js_memory_data_reader") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_js_memory_data_cpp_gen" ] +ohos_source_set("js_memory_data_encoder") { + deps = [ ":js_memory_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":js_memory_include_config" ] sources = js_memory_data_codegen_reader + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/memory_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/memory_data/BUILD.gn index df62e2add..64b042c45 100755 --- a/trace_streamer/src/protos/types/plugins/memory_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/memory_data/BUILD.gn @@ -44,7 +44,7 @@ config("memory_include_config") { } ####################################################### -action("ts_memory_data_cpp_gen") { +action("memory_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = memory_data_sources outputs = memory_data_codegen_all @@ -60,16 +60,14 @@ action("ts_memory_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", ] } } -ohos_source_set("ts_memory_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_memory_data_cpp_gen" ] +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", @@ -77,13 +75,15 @@ ohos_source_set("ts_memory_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":memory_include_config" ] sources = memory_data_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } -ohos_source_set("memory_data_reader") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_memory_data_cpp_gen" ] +ohos_source_set("memory_data_encoder") { + deps = [ ":memory_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":memory_include_config" ] sources = memory_data_codegen_reader + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/native_hook/BUILD.gn b/trace_streamer/src/protos/types/plugins/native_hook/BUILD.gn index 4007a7b1d..be9f73882 100755 --- a/trace_streamer/src/protos/types/plugins/native_hook/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/native_hook/BUILD.gn @@ -42,7 +42,7 @@ config("native_hook_include_config") { } ####################################################### -action("ts_native_hook_cpp_gen") { +action("native_hook_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = native_hook_sources outputs = native_hook_codegen_all @@ -58,16 +58,14 @@ action("ts_native_hook_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", ] } } -ohos_source_set("ts_native_hook_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_native_hook_cpp_gen" ] +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", @@ -75,11 +73,11 @@ ohos_source_set("ts_native_hook_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":native_hook_include_config" ] sources = native_hook_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } -ohos_source_set("native_hook_data_reader") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_native_hook_cpp_gen" ] +ohos_source_set("native_hook_data_encoder") { + deps = [ ":native_hook_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -87,4 +85,6 @@ ohos_source_set("native_hook_data_reader") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":native_hook_include_config" ] sources = native_hook_codegen_reader + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/network_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/network_data/BUILD.gn index 5cff948a7..08f5f5e2b 100755 --- a/trace_streamer/src/protos/types/plugins/network_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/network_data/BUILD.gn @@ -42,7 +42,7 @@ config("network_include_config") { } ####################################################### -action("ts_network_data_cpp_gen") { +action("network_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = network_data_sources outputs = network_data_codegen_all @@ -58,16 +58,14 @@ action("ts_network_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", ] } } -ohos_source_set("ts_network_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_network_data_cpp_gen" ] +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", @@ -75,13 +73,15 @@ ohos_source_set("ts_network_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":network_include_config" ] sources = network_data_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } -ohos_source_set("network_data_reader") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_network_data_cpp_gen" ] +ohos_source_set("network_data_encoder") { + deps = [ ":network_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":network_include_config" ] sources = network_data_codegen_reader + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/process_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/process_data/BUILD.gn index 4a6c27aed..12ec2bf95 100755 --- a/trace_streamer/src/protos/types/plugins/process_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/process_data/BUILD.gn @@ -42,7 +42,7 @@ config("process_include_config") { } ####################################################### -action("ts_process_data_cpp_gen") { +action("process_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = process_data_sources outputs = process_data_codegen_all @@ -58,16 +58,14 @@ action("ts_process_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", ] } } -ohos_source_set("ts_process_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_process_data_cpp_gen" ] +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", @@ -75,13 +73,15 @@ ohos_source_set("ts_process_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":process_include_config" ] sources = process_data_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } -ohos_source_set("process_data_reader") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - deps = [ ":ts_process_data_cpp_gen" ] +ohos_source_set("process_data_encoder") { + deps = [ ":process_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":process_include_config" ] sources = process_data_codegen_reader + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/sample_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/sample_data/BUILD.gn index 21a6aa648..39bb0e7ad 100755 --- a/trace_streamer/src/protos/types/plugins/sample_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/sample_data/BUILD.gn @@ -66,8 +66,6 @@ action("sample_data_cpp_gen") { } ohos_source_set("sample_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":sample_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", @@ -76,13 +74,15 @@ ohos_source_set("sample_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":sample_include_config" ] sources = sample_data_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } ohos_source_set("sample_data_encoder") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":sample_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":sample_include_config" ] sources = sample_data_codegen_reader + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/stream_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/stream_data/BUILD.gn index f385b92e7..b5ca47f39 100755 --- a/trace_streamer/src/protos/types/plugins/stream_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/stream_data/BUILD.gn @@ -66,8 +66,6 @@ action("stream_data_cpp_gen") { } ohos_source_set("stream_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":stream_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", @@ -76,13 +74,15 @@ ohos_source_set("stream_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":stream_include_config" ] sources = stream_data_codegen + subsystem_name = "developtools" + part_name = "smartperf_host" } ohos_source_set("stream_data_encoder") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":stream_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":stream_include_config" ] sources = stream_data_codegen_reader + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/test_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/test_data/BUILD.gn index 4c00f9033..64c82e949 100644 --- a/trace_streamer/src/protos/types/plugins/test_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/test_data/BUILD.gn @@ -55,15 +55,13 @@ action("test_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", ] } } -source_set("test_data_cpp") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" +ohos_source_set("test_data_cpp") { deps = [ ":test_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", @@ -75,10 +73,10 @@ source_set("test_data_cpp") { } ohos_source_set("test_data_encoder") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":test_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":test_include_config" ] sources = test_data_codegen_reader + subsystem_name = "developtools" + part_name = "smartperf_host" } diff --git a/trace_streamer/src/rpc/rpc_server.cpp b/trace_streamer/src/rpc/rpc_server.cpp index 7b66cfd84..d6d6c7372 100644 --- a/trace_streamer/src/rpc/rpc_server.cpp +++ b/trace_streamer/src/rpc/rpc_server.cpp @@ -31,6 +31,7 @@ } while (0) namespace SysTuning { namespace TraceStreamer { +const int32_t MAX_LEN_STR = 100; uint32_t g_fileLen = 0; FILE* g_importFileFd = nullptr; bool RpcServer::ParseData(const uint8_t* data, size_t len, ResultCallBack resultCallBack) diff --git a/trace_streamer/src/table/BUILD.gn b/trace_streamer/src/table/BUILD.gn index 212c7e651..ed2a3ffd2 100644 --- a/trace_streamer/src/table/BUILD.gn +++ b/trace_streamer/src/table/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../build/ts.gni") ohos_source_set("table") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" include_dirs = [ "${THIRD_PARTY}/sqlite/include", "${SRC}/base", @@ -50,6 +50,8 @@ ohos_source_set("table") { "js_memory:js_memory_tables", "monitor:monitor_tables", "native_hook:native_hook_tables", - "hiperf:hiperf_tables", ] + if (with_perf) { + deps += [ "hiperf:hiperf_tables" ] + } } diff --git a/trace_streamer/src/table/base/BUILD.gn b/trace_streamer/src/table/base/BUILD.gn index 5300f7421..065bdd20b 100644 --- a/trace_streamer/src/table/base/BUILD.gn +++ b/trace_streamer/src/table/base/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("base_tables") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "args_table.cpp", "args_table.h", diff --git a/trace_streamer/src/table/ebpf/BUILD.gn b/trace_streamer/src/table/ebpf/BUILD.gn index 677666263..2ea5df1cf 100644 --- a/trace_streamer/src/table/ebpf/BUILD.gn +++ b/trace_streamer/src/table/ebpf/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("ebpf_tables") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "bio_latency_sample_table.cpp", "bio_latency_sample_table.h", diff --git a/trace_streamer/src/table/ftrace/BUILD.gn b/trace_streamer/src/table/ftrace/BUILD.gn index 1565672aa..11ecec57d 100644 --- a/trace_streamer/src/table/ftrace/BUILD.gn +++ b/trace_streamer/src/table/ftrace/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("ftrace_tables") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "app_startup_table.cpp", "app_startup_table.h", @@ -62,6 +62,8 @@ ohos_source_set("ftrace_tables") { "system_call_table.h", "system_event_filter_table.cpp", "system_event_filter_table.h", + "task_pool_table.cpp", + "task_pool_table.h", "thread_filter_table.cpp", "thread_filter_table.h", "thread_state_table.cpp", diff --git a/trace_streamer/src/table/ftrace/process_table.cpp b/trace_streamer/src/table/ftrace/process_table.cpp index 9be2d5b02..e626528f7 100644 --- a/trace_streamer/src/table/ftrace/process_table.cpp +++ b/trace_streamer/src/table/ftrace/process_table.cpp @@ -294,6 +294,7 @@ void ProcessTable::Cursor::FilterPid(unsigned char op, uint64_t value) } void ProcessTable::Cursor::FilterIndex(int32_t col, unsigned char op, sqlite3_value* argv) { + auto type = sqlite3_value_type(argv); switch (col) { case PID: /* code */ @@ -306,6 +307,7 @@ void ProcessTable::Cursor::FilterIndex(int32_t col, unsigned char op, sqlite3_va } void ProcessTable::Cursor::FilterId(unsigned char op, sqlite3_value* argv) { + auto type = sqlite3_value_type(argv); auto v = static_cast(sqlite3_value_int64(argv)); switch (op) { case SQLITE_INDEX_CONSTRAINT_EQ: diff --git a/trace_streamer/src/table/ftrace/task_pool_table.cpp b/trace_streamer/src/table/ftrace/task_pool_table.cpp new file mode 100644 index 000000000..0e8c287a5 --- /dev/null +++ b/trace_streamer/src/table/ftrace/task_pool_table.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "task_pool_table.h" + +namespace SysTuning { +namespace TraceStreamer { +enum Index { + ID = 0, + ALLOCATION_TASK_ROW, + EXECUTE_TASK_ROW, + RETURN_TASK_ROW, + ALLOCATION_TASK_ID, + EXECUTE_TASK_ID, + RETURN_TASK_ID, + EXECUTE_ID, + PRIORITY, + EXECUTE_STATE, + RETURN_STATE +}; +TaskPoolTable::TaskPoolTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("allocation_task_row", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("execute_task_row", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("return_task_row", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("allocation_task_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("execute_task_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("return_task_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("execute_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("priority", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("execute_state", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("return_state", "INTEGER")); + tablePriKey_.push_back("id"); +} + +TaskPoolTable::~TaskPoolTable() {} + +std::unique_ptr TaskPoolTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +TaskPoolTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstTaskPoolData().Size())), + taskPoolObj_(dataCache->GetConstTaskPoolData()) +{ +} + +TaskPoolTable::Cursor::~Cursor() {} + +int32_t TaskPoolTable::Cursor::Column(int32_t column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(CurrentRow())); + break; + case ALLOCATION_TASK_ROW: + if (taskPoolObj_.AllocationTaskRows()[CurrentRow()] != INVALID_INT32) { + sqlite3_result_int64( + context_, + static_cast(dataCache_->GetConstTaskPoolData().AllocationTaskRows()[CurrentRow()])); + } + break; + case EXECUTE_TASK_ROW: + if (taskPoolObj_.ExecuteTaskRows()[CurrentRow()] != INVALID_INT32) { + sqlite3_result_int64(context_, static_cast( + dataCache_->GetConstTaskPoolData().ExecuteTaskRows()[CurrentRow()])); + } + break; + case RETURN_TASK_ROW: + if (taskPoolObj_.ReturnTaskRows()[CurrentRow()] != INVALID_INT32) { + sqlite3_result_int64(context_, static_cast( + dataCache_->GetConstTaskPoolData().ReturnTaskRows()[CurrentRow()])); + } + break; + case ALLOCATION_TASK_ID: + if (taskPoolObj_.AllocationTaskIds()[CurrentRow()] != INVALID_INT32) { + sqlite3_result_int64( + context_, + static_cast(dataCache_->GetConstTaskPoolData().AllocationTaskIds()[CurrentRow()])); + } + break; + case EXECUTE_TASK_ID: + if (taskPoolObj_.ExecuteTaskIds()[CurrentRow()] != INVALID_INT32) { + sqlite3_result_int64(context_, static_cast( + dataCache_->GetConstTaskPoolData().ExecuteTaskIds()[CurrentRow()])); + } + break; + case RETURN_TASK_ID: + if (taskPoolObj_.ReturnTaskIds()[CurrentRow()] != INVALID_INT32) { + sqlite3_result_int64(context_, static_cast( + dataCache_->GetConstTaskPoolData().ReturnTaskIds()[CurrentRow()])); + } + break; + case EXECUTE_ID: + if (taskPoolObj_.ExecuteIds()[CurrentRow()] != INVALID_INT32) { + sqlite3_result_int64(context_, static_cast( + dataCache_->GetConstTaskPoolData().ExecuteIds()[CurrentRow()])); + } + break; + case PRIORITY: + if (taskPoolObj_.Prioritys()[CurrentRow()] != INVALID_INT32) { + sqlite3_result_int64( + context_, static_cast(dataCache_->GetConstTaskPoolData().Prioritys()[CurrentRow()])); + } + break; + case EXECUTE_STATE: + if (taskPoolObj_.ExecuteStates()[CurrentRow()] != INVALID_INT32) { + sqlite3_result_int64(context_, static_cast( + dataCache_->GetConstTaskPoolData().ExecuteStates()[CurrentRow()])); + } + break; + case RETURN_STATE: + if (taskPoolObj_.ReturnStates()[CurrentRow()] != INVALID_INT32) { + sqlite3_result_int64(context_, static_cast( + dataCache_->GetConstTaskPoolData().ReturnStates()[CurrentRow()])); + } + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/src/table/ftrace/task_pool_table.h b/trace_streamer/src/table/ftrace/task_pool_table.h new file mode 100644 index 000000000..ff42ac4a0 --- /dev/null +++ b/trace_streamer/src/table/ftrace/task_pool_table.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 TASK_POOL_TABLE_H +#define TASK_POOL_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class TaskPoolTable : public TableBase { +public: + explicit TaskPoolTable(const TraceDataCache* dataCache); + ~TaskPoolTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int32_t Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + + int32_t Column(int32_t column) const override; + + private: + const TaskPoolInfo& taskPoolObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TASK_POOL_TABLE_H diff --git a/trace_streamer/src/table/hi_sysevent/BUILD.gn b/trace_streamer/src/table/hi_sysevent/BUILD.gn index fcf1a758f..5376f8207 100644 --- a/trace_streamer/src/table/hi_sysevent/BUILD.gn +++ b/trace_streamer/src/table/hi_sysevent/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("hi_sysevent_tables") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "device_state_table.cpp", "device_state_table.h", diff --git a/trace_streamer/src/table/hiperf/BUILD.gn b/trace_streamer/src/table/hiperf/BUILD.gn index 1e282312d..f9dbab769 100644 --- a/trace_streamer/src/table/hiperf/BUILD.gn +++ b/trace_streamer/src/table/hiperf/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("hiperf_tables") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "perf_call_chain_table.cpp", "perf_call_chain_table.h", diff --git a/trace_streamer/src/table/js_memory/BUILD.gn b/trace_streamer/src/table/js_memory/BUILD.gn index 9e242cbf3..2138c540a 100644 --- a/trace_streamer/src/table/js_memory/BUILD.gn +++ b/trace_streamer/src/table/js_memory/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("js_memory_tables") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "appname_table.cpp", "appname_table.h", diff --git a/trace_streamer/src/table/monitor/BUILD.gn b/trace_streamer/src/table/monitor/BUILD.gn index db680eb24..e659fc2b8 100644 --- a/trace_streamer/src/table/monitor/BUILD.gn +++ b/trace_streamer/src/table/monitor/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("monitor_tables") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "cpu_usage_info_table.cpp", "cpu_usage_info_table.h", diff --git a/trace_streamer/src/table/native_hook/BUILD.gn b/trace_streamer/src/table/native_hook/BUILD.gn index 10a75c6c0..4349bed8e 100644 --- a/trace_streamer/src/table/native_hook/BUILD.gn +++ b/trace_streamer/src/table/native_hook/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("native_hook_tables") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "native_hook_frame_table.cpp", "native_hook_frame_table.h", diff --git a/trace_streamer/src/trace_data/BUILD.gn b/trace_streamer/src/trace_data/BUILD.gn index a21f04aae..3cd8a2395 100644 --- a/trace_streamer/src/trace_data/BUILD.gn +++ b/trace_streamer/src/trace_data/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../build/ts.gni") ohos_source_set("trace_data") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" + subsystem_name = "developtools" + part_name = "smartperf_host" sources = [ "trace_data_cache.cpp", "trace_data_cache.h", diff --git a/trace_streamer/src/trace_data/trace_data_cache.cpp b/trace_streamer/src/trace_data/trace_data_cache.cpp index e6ea3cdf5..9d86803fe 100644 --- a/trace_streamer/src/trace_data/trace_data_cache.cpp +++ b/trace_streamer/src/trace_data/trace_data_cache.cpp @@ -63,11 +63,13 @@ #include "native_hook_statistic_table.h" #include "network_table.h" #include "paged_memory_sample_table.h" +#if WITH_PERF #include "perf_call_chain_table.h" #include "perf_files_table.h" #include "perf_report_table.h" #include "perf_sample_table.h" #include "perf_thread_table.h" +#endif #include "process_filter_table.h" #include "process_measure_filter_table.h" #include "process_table.h" @@ -84,6 +86,7 @@ #include "system_call_table.h" #include "system_event_filter_table.h" #include "table_base.h" +#include "task_pool_table.h" #include "thread_filter_table.h" #include "thread_state_table.h" #include "thread_table.h" @@ -141,6 +144,7 @@ void TraceDataCache::InitDB() TableBase::TableDeclare(*db_, this, "process_measure_filter"); TableBase::TableDeclare(*db_, this, "clock_event_filter"); TableBase::TableDeclare(*db_, this, "clk_event_filter"); + TableBase::TableDeclare(*db_, this, "task_pool"); TableBase::TableDeclare(*db_, this, "js_heap_files"); TableBase::TableDeclare(*db_, this, "js_heap_edges"); TableBase::TableDeclare(*db_, this, "js_heap_info"); @@ -178,11 +182,13 @@ void TraceDataCache::InitDB() TableBase::TableDeclare(*db_, this, "app_startup"); TableBase::TableDeclare(*db_, this, "static_initalize"); +#if WITH_PERF TableBase::TableDeclare(*db_, this, "perf_report"); TableBase::TableDeclare(*db_, this, "perf_sample"); TableBase::TableDeclare(*db_, this, "perf_callchain"); TableBase::TableDeclare(*db_, this, "perf_thread"); TableBase::TableDeclare(*db_, this, "perf_files"); +#endif #else TableBase::TableDeclare(*db_, this, "_process"); TableBase::TableDeclare(*db_, this, "_sched_slice"); @@ -221,6 +227,7 @@ void TraceDataCache::InitDB() TableBase::TableDeclare(*db_, this, "_process_measure_filter"); TableBase::TableDeclare(*db_, this, "_clock_event_filter"); TableBase::TableDeclare(*db_, this, "_clk_event_filter"); + TableBase::TableDeclare(*db_, this, "_task_pool"); TableBase::TableDeclare(*db_, this, "_js_heap_files"); TableBase::TableDeclare(*db_, this, "_js_heap_edges"); TableBase::TableDeclare(*db_, this, "_js_heap_info"); @@ -256,11 +263,13 @@ void TraceDataCache::InitDB() TableBase::TableDeclare(*db_, this, "_hisys_event_measure"); TableBase::TableDeclare(*db_, this, "_device_state"); TableBase::TableDeclare(*db_, this, "_trace_config"); +#if WITH_PERF TableBase::TableDeclare(*db_, this, "_perf_report"); TableBase::TableDeclare(*db_, this, "_perf_sample"); TableBase::TableDeclare(*db_, this, "_perf_callchain"); TableBase::TableDeclare(*db_, this, "_perf_thread"); TableBase::TableDeclare(*db_, this, "_perf_files"); +#endif #endif dbInited = true; } diff --git a/trace_streamer/src/trace_data/trace_data_cache_base.h b/trace_streamer/src/trace_data/trace_data_cache_base.h index 782328604..78a842c9e 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_base.h +++ b/trace_streamer/src/trace_data/trace_data_cache_base.h @@ -152,6 +152,7 @@ public: FrameSlice frameSliceData_; FrameMaps frameMapsData_; GPUSlice gpuSliceData_; + TaskPoolInfo taskPoolInfo_; JsHeapFiles jsHeapFilesData_; JsHeapEdges jsHeapEdgesData_; JsHeapInfo jsHeapInfoData_; diff --git a/trace_streamer/src/trace_data/trace_data_cache_reader.cpp b/trace_streamer/src/trace_data/trace_data_cache_reader.cpp index e824fd4c4..48cfcd80c 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_reader.cpp +++ b/trace_streamer/src/trace_data/trace_data_cache_reader.cpp @@ -192,6 +192,10 @@ const ArgSet& TraceDataCacheReader::GetConstArgSetData() const { return argSet_; } +const TaskPoolInfo& TraceDataCacheReader::GetConstTaskPoolData() const +{ + return taskPoolInfo_; +} const JsHeapFiles& TraceDataCacheReader::GetConstJsHeapFilesData() const { return jsHeapFilesData_; diff --git a/trace_streamer/src/trace_data/trace_data_cache_reader.h b/trace_streamer/src/trace_data/trace_data_cache_reader.h index 675924fbe..e4085551b 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_reader.h +++ b/trace_streamer/src/trace_data/trace_data_cache_reader.h @@ -96,6 +96,7 @@ public: const FrameSlice& GetConstFameSliceData() const; const FrameMaps& GetConstFameMapsData() const; const GPUSlice& GetConstGPUSliceData() const; + const TaskPoolInfo& GetConstTaskPoolData() const; const JsHeapFiles& GetConstJsHeapFilesData() const; const JsHeapEdges& GetConstJsHeapEdgesData() const; const JsHeapInfo& GetConstJsHeapInfoData() const; diff --git a/trace_streamer/src/trace_data/trace_data_cache_writer.cpp b/trace_streamer/src/trace_data/trace_data_cache_writer.cpp index a2122be30..394f2f61c 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_writer.cpp +++ b/trace_streamer/src/trace_data/trace_data_cache_writer.cpp @@ -334,7 +334,10 @@ GPUSlice* TraceDataCacheWriter::GetGPUSliceData() { return &gpuSliceData_; } - +TaskPoolInfo* TraceDataCacheWriter::GetTaskPoolData() +{ + return &taskPoolInfo_; +} JsHeapFiles* TraceDataCacheWriter::GetJsHeapFilesData() { return &jsHeapFilesData_; @@ -449,6 +452,7 @@ void TraceDataCacheWriter::Clear() deviceStateData_.Clear(); smapsData_.Clear(); bioLatencySampleData_.Clear(); + taskPoolInfo_.Clear(); } } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/trace_data/trace_data_cache_writer.h b/trace_streamer/src/trace_data/trace_data_cache_writer.h index cb0ea8af2..067988ba2 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_writer.h +++ b/trace_streamer/src/trace_data/trace_data_cache_writer.h @@ -95,6 +95,7 @@ public: FrameSlice* GetFrameSliceData(); FrameMaps* GetFrameMapsData(); GPUSlice* GetGPUSliceData(); + TaskPoolInfo* GetTaskPoolData(); JsHeapFiles* GetJsHeapFilesData(); JsHeapEdges* GetJsHeapEdgesData(); JsHeapInfo* GetJsHeapInfoData(); diff --git a/trace_streamer/src/trace_data/trace_stdtype.cpp b/trace_streamer/src/trace_data/trace_stdtype.cpp index bf2335ecd..f90012bda 100644 --- a/trace_streamer/src/trace_data/trace_stdtype.cpp +++ b/trace_streamer/src/trace_data/trace_stdtype.cpp @@ -2271,13 +2271,15 @@ size_t FrameMaps::AppendNew(FrameSlice* frameSlice, uint64_t src, uint64_t dst) ids_.emplace_back(ids_.size()); srcs_.push_back(src); dsts_.push_back(dst); - uint64_t rsStartTime = frameSlice->TimeStampData().at(dst); - uint64_t appEndTime = frameSlice->TimeStampData().at(src) + frameSlice->Durs().at(src); - auto typeDesc = frameSlice->Types().at(dst); - if (typeDesc == FrameSlice::ACTURAL_SLICE && - std::abs(static_cast(rsStartTime - appEndTime)) >= ONE_MILLION_NANOSECONDS) { - frameSlice->SetFlags(dst, FrameSlice::ABNORMAL_START_END_TIME); + if (frameSlice->Types().at(dst) == FrameSlice::EXPECT_SLICE) { + uint64_t expRsStartTime = frameSlice->TimeStampData().at(dst); + uint64_t expUiEndTime = frameSlice->TimeStampData().at(src) + frameSlice->Durs().at(src); + if (std::abs(static_cast(expRsStartTime - expUiEndTime)) >= ONE_MILLION_NANOSECONDS) { + auto acturalRow = dst - 1; + frameSlice->SetFlags(acturalRow, FrameSlice::ABNORMAL_START_END_TIME); + } } + return Size() - 1; } const std::deque& FrameMaps::SrcIndexs() const @@ -2303,7 +2305,7 @@ const std::deque& GPUSlice::Durs() const { return durs_; } -size_t GPUSlice::Size() const +const size_t GPUSlice::Size() const { return durs_.size(); } @@ -2753,5 +2755,128 @@ const std::deque& JsHeapTraceNode::ParentIds() const return parentIds_; } +size_t TaskPoolInfo::AppendAllocationTaskData(uint32_t allocationTaskRow, + uint32_t allocationTaskId, + uint32_t executeId, + uint32_t priority, + uint32_t executeState) +{ + allocationTaskRows_.emplace_back(allocationTaskRow); + executeTaskRows_.emplace_back(INVALID_INT32); + returnTaskRows_.emplace_back(INVALID_INT32); + allocationTaskIds_.emplace_back(allocationTaskId); + executeTaskIds_.emplace_back(INVALID_INT32); + returnTaskIds_.emplace_back(INVALID_INT32); + executeIds_.emplace_back(executeId); + prioritys_.emplace_back(priority); + executeStates_.emplace_back(executeState); + returnStates_.emplace_back(INVALID_INT32); + ids_.emplace_back(Size()); + return Size() - 1; +} +size_t TaskPoolInfo::AppendExecuteTaskData(uint32_t executeTaskRow, uint32_t executeTaskId, uint32_t executeId) +{ + allocationTaskRows_.emplace_back(INVALID_INT32); + executeTaskRows_.emplace_back(executeTaskRow); + returnTaskRows_.emplace_back(INVALID_INT32); + allocationTaskIds_.emplace_back(INVALID_INT32); + executeTaskIds_.emplace_back(executeTaskId); + returnTaskIds_.emplace_back(INVALID_INT32); + executeIds_.emplace_back(executeId); + prioritys_.emplace_back(INVALID_INT32); + executeStates_.emplace_back(INVALID_INT32); + returnStates_.emplace_back(INVALID_INT32); + ids_.emplace_back(Size()); + return Size() - 1; +} +size_t TaskPoolInfo::AppendReturnTaskData(uint32_t returnTaskRow, + uint32_t returnTaskId, + uint32_t executeId, + uint32_t returnState) +{ + allocationTaskRows_.emplace_back(INVALID_INT32); + executeTaskRows_.emplace_back(INVALID_INT32); + returnTaskRows_.emplace_back(returnTaskRow); + allocationTaskIds_.emplace_back(INVALID_INT32); + executeTaskIds_.emplace_back(INVALID_INT32); + returnTaskIds_.emplace_back(returnTaskId); + executeIds_.emplace_back(executeId); + prioritys_.emplace_back(INVALID_INT32); + executeStates_.emplace_back(INVALID_INT32); + returnStates_.emplace_back(returnState); + ids_.emplace_back(Size()); + return Size() - 1; +} +const std::deque& TaskPoolInfo::AllocationTaskRows() const +{ + return allocationTaskRows_; +} +const std::deque& TaskPoolInfo::ExecuteTaskRows() const +{ + return executeTaskRows_; +} +const std::deque& TaskPoolInfo::ReturnTaskRows() const +{ + return returnTaskRows_; +} +const std::deque& TaskPoolInfo::AllocationTaskIds() const +{ + return allocationTaskIds_; +} +const std::deque& TaskPoolInfo::ExecuteTaskIds() const +{ + return executeTaskIds_; +} +const std::deque& TaskPoolInfo::ReturnTaskIds() const +{ + return returnTaskIds_; +} +const std::deque& TaskPoolInfo::ExecuteIds() const +{ + return executeIds_; +} +const std::deque& TaskPoolInfo::Prioritys() const +{ + return prioritys_; +} +const std::deque& TaskPoolInfo::ExecuteStates() const +{ + return executeStates_; +} +const std::deque& TaskPoolInfo::ReturnStates() const +{ + return returnStates_; +} +void TaskPoolInfo::UpdateAllocationTaskData(uint32_t index, + uint32_t allocationTaskRow, + uint32_t allocationTaskId, + uint32_t priority, + uint32_t executeState) +{ + if (index < Size()) { + allocationTaskRows_[index] = allocationTaskRow; + allocationTaskIds_[index] = allocationTaskId; + prioritys_[index] = priority; + executeStates_[index] = executeState; + } +} +void TaskPoolInfo::UpdateExecuteTaskData(uint32_t index, uint32_t executeTaskRow, uint32_t executeTaskId) +{ + if (index < Size()) { + executeTaskRows_[index] = executeTaskRow; + executeTaskIds_[index] = executeTaskId; + } +} +void TaskPoolInfo::UpdateReturnTaskData(uint32_t index, + uint32_t returnTaskRow, + uint32_t returnTaskId, + uint32_t returnState) +{ + if (index < Size()) { + returnTaskRows_[index] = returnTaskRow; + returnTaskIds_[index] = returnTaskId; + returnStates_[index] = returnState; + } +} } // namespace TraceStdtype } // namespace SysTuning diff --git a/trace_streamer/src/trace_data/trace_stdtype.h b/trace_streamer/src/trace_data/trace_stdtype.h index 2e7b21578..f714a2735 100644 --- a/trace_streamer/src/trace_data/trace_stdtype.h +++ b/trace_streamer/src/trace_data/trace_stdtype.h @@ -139,7 +139,7 @@ public: states_.clear(); cpus_.clear(); } - uint32_t Size() const + const uint32_t Size() const { return itids_.size(); } @@ -869,6 +869,8 @@ private: std::deque symbolOffsets_ = {}; std::deque vaddrs_ = {}; std::map symbolIdToSymbolName_ = {}; + DataIndex libcFilePathIndex_ = INVALID_UINT64; + DataIndex muslFilePathIndex_ = INVALID_UINT64; }; class NativeHookStatistic : public CacheBase { @@ -1548,6 +1550,7 @@ private: std::deque flags_ = {}; std::deque appNames_ = {}; std::deque keyNames_ = {}; + uint32_t rowCount_ = 0; }; class SysEventMeasureData : public CacheBase { public: @@ -1819,7 +1822,7 @@ public: names_.emplace_back(name); return ts_.size(); } - size_t Size() const + const size_t Size() const { return ts_.size(); } @@ -1850,7 +1853,7 @@ public: clockIds_.emplace_back(clockId); return dataSourceNames_.size(); } - size_t Size() const + const size_t Size() const { return dataSourceNames_.size(); } @@ -2300,12 +2303,70 @@ public: size_t AppendNew(uint32_t frameRow, uint64_t dur); const std::deque& FrameRows() const; const std::deque& Durs() const; - size_t Size() const; + const size_t Size() const; private: std::deque frameRows_ = {}; std::deque durs_ = {}; }; + +class TaskPoolInfo : public CacheBase { +public: + size_t AppendAllocationTaskData(uint32_t allocationTaskRow, + uint32_t allocationTaskId, + uint32_t executeId, + uint32_t priority, + uint32_t executeState); + size_t AppendExecuteTaskData(uint32_t executeTaskRow, uint32_t executeTaskId, uint32_t executeId); + size_t AppendReturnTaskData(uint32_t returnTaskRow, + uint32_t returnTaskId, + uint32_t executeId, + uint32_t returnState); + void UpdateAllocationTaskData(uint32_t index, + uint32_t allocationTaskRow, + uint32_t allocationTaskId, + uint32_t priority, + uint32_t executeState); + void UpdateExecuteTaskData(uint32_t index, uint32_t executeTaskRow, uint32_t executeTaskId); + void UpdateReturnTaskData(uint32_t index, uint32_t returnTaskRow, uint32_t returnTaskId, uint32_t returnState); + + const std::deque& AllocationTaskRows() const; + const std::deque& ExecuteTaskRows() const; + const std::deque& ReturnTaskRows() const; + const std::deque& AllocationTaskIds() const; + const std::deque& ExecuteTaskIds() const; + const std::deque& ReturnTaskIds() const; + const std::deque& ExecuteIds() const; + const std::deque& Prioritys() const; + const std::deque& ExecuteStates() const; + const std::deque& ReturnStates() const; + void Clear() override + { + TaskPoolInfo::Clear(); + allocationTaskRows_.clear(); + executeTaskRows_.clear(); + returnTaskRows_.clear(); + allocationTaskIds_.clear(); + executeTaskIds_.clear(); + returnTaskIds_.clear(); + executeIds_.clear(); + prioritys_.clear(); + executeStates_.clear(); + returnStates_.clear(); + } + +private: + std::deque allocationTaskRows_ = {}; + std::deque executeTaskRows_ = {}; + std::deque returnTaskRows_ = {}; + std::deque allocationTaskIds_ = {}; + std::deque executeTaskIds_ = {}; + std::deque returnTaskIds_ = {}; + std::deque executeIds_ = {}; + std::deque prioritys_ = {}; + std::deque executeStates_ = {}; + std::deque returnStates_ = {}; +}; } // namespace TraceStdtype } // namespace SysTuning diff --git a/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp b/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp index f25e3ebe1..c18fc7700 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp +++ b/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp @@ -30,6 +30,7 @@ #include "stat_filter.h" #include "symbols_filter.h" #include "system_event_measure_filter.h" +#include "task_pool_filter.h" namespace SysTuning { namespace TraceStreamer { diff --git a/trace_streamer/src/trace_streamer/trace_streamer_filters.h b/trace_streamer/src/trace_streamer/trace_streamer_filters.h index 3cf61ad52..09dd1ec7d 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_filters.h +++ b/trace_streamer/src/trace_streamer/trace_streamer_filters.h @@ -34,7 +34,10 @@ class SystemEventMeasureFilter; class HiSysEventMeasureFilter; class FrameFilter; class APPStartupFilter; +class TaskPoolFilter; +#if WITH_PERF class PerfDataFilter; +#endif class TraceStreamerFilters { public: TraceStreamerFilters(); @@ -66,7 +69,10 @@ public: std::unique_ptr hiSysEventMeasureFilter_; std::unique_ptr frameFilter_; std::unique_ptr appStartupFilter_; + std::unique_ptr taskPoolFilter_; +#if WITH_PERF std::unique_ptr perfDataFilter_; +#endif }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp index d465a5e8c..e9ed06e76 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp +++ b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp @@ -29,9 +29,12 @@ #include "hi_sysevent_measure_filter.h" #include "irq_filter.h" #include "measure_filter.h" +#include "task_pool_filter.h" #include "parser/bytrace_parser/bytrace_parser.h" #include "parser/htrace_pbreader_parser/htrace_parser.h" +#if WITH_PERF #include "perf_data_filter.h" +#endif #include "process_filter.h" #include "slice_filter.h" #include "stat_filter.h" @@ -141,11 +144,14 @@ void TraceStreamerSelector::InitFilter() streamFilters_->sysEventVMemMeasureFilter_ = std::make_unique( traceDataCache_.get(), streamFilters_.get(), E_SYS_VIRTUAL_MEMORY_FILTER); streamFilters_->appStartupFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); +#if WITH_PERF streamFilters_->perfDataFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); +#endif streamFilters_->sysEventSourceFilter_ = std::make_unique( traceDataCache_.get(), streamFilters_.get(), E_SYS_EVENT_SOURCE_FILTER); streamFilters_->hiSysEventMeasureFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + streamFilters_->taskPoolFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); } void TraceStreamerSelector::WaitForParserEnd() diff --git a/trace_streamer/test/BUILD.gn b/trace_streamer/test/BUILD.gn index 438141772..ce7ca3e1c 100755 --- a/trace_streamer/test/BUILD.gn +++ b/trace_streamer/test/BUILD.gn @@ -61,23 +61,23 @@ if (is_test) { ] deps = [ - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:ts_cpu_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/diskio_data:ts_diskio_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/ftrace_data/${device_kernel_version}:ts_ftrace_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hidump_data:ts_hidump_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:ts_hilog_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:ts_hisysevent_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/js_memory:ts_js_memory_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:ts_memory_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:ts_native_hook_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/network_data:ts_network_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/process_data:ts_process_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:cpu_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/diskio_data:diskio_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/ftrace_data/${device_kernel_version}:ftrace_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hidump_data:hidump_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:hilog_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:hisysevent_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/js_memory:js_memory_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/network_data:network_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/process_data:process_data_cpp", "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/test_data:test_data_cpp", "${THIRD_PARTY}/googletest:gtest", "${THIRD_PARTY}/googletest:gtest_main", "${THIRD_PARTY}/protobuf:protobuf", "${THIRD_PARTY}/protobuf:protobuf_lite", - # "${THIRD_PARTY}/sqlite:sqlite", + "${THIRD_PARTY}/sqlite:sqlite", "../src:trace_streamer_source", "../src/parser/htrace_pbreader_parser:htrace_pbreader_parser", "../src/proto_reader:proto_reader", @@ -107,7 +107,6 @@ if (is_test) { "${THIRD_PARTY}/protobuf/src/google/protobuf", "${THIRD_PARTY}/json-master/single_include/nlohmann", "${THIRD_PARTY}/perf_include/musl", - "${THIRD_PARTY}/sqlite/include", "../src/parser/htrace_pbreader_parser", "../src/parser/htrace_pbreader_parser/htrace_event_parser", "../src/parser/htrace_pbreader_parser/htrace_cpu_parser", diff --git a/trace_streamer/test/test_fuzzer/bytrace_fuzzer/BUILD.gn b/trace_streamer/test/test_fuzzer/bytrace_fuzzer/BUILD.gn index 1c1ad9e31..97ed18a9a 100644 --- a/trace_streamer/test/test_fuzzer/bytrace_fuzzer/BUILD.gn +++ b/trace_streamer/test/test_fuzzer/bytrace_fuzzer/BUILD.gn @@ -48,7 +48,7 @@ ohos_fuzztest("ts_bytrace_fuzz_test") { deps = [ "${THIRD_PARTY}/protobuf:protobuf", "${THIRD_PARTY}/protobuf:protobuf_lite", - # "${THIRD_PARTY}/sqlite:sqlite", + "${THIRD_PARTY}/sqlite:sqlite", "../../../src:trace_streamer_source", "../../../src/proto_reader:proto_reader", ] diff --git a/trace_streamer/test/test_fuzzer/htrace_fuzzer/BUILD.gn b/trace_streamer/test/test_fuzzer/htrace_fuzzer/BUILD.gn index 1dcb3bace..1bdfaf6d1 100644 --- a/trace_streamer/test/test_fuzzer/htrace_fuzzer/BUILD.gn +++ b/trace_streamer/test/test_fuzzer/htrace_fuzzer/BUILD.gn @@ -48,7 +48,7 @@ ohos_fuzztest("ts_htrace_fuzz_test") { deps = [ "${THIRD_PARTY}/protobuf:protobuf", "${THIRD_PARTY}/protobuf:protobuf_lite", - # "${THIRD_PARTY}/sqlite:sqlite", + "${THIRD_PARTY}/sqlite:sqlite", "../../../src:trace_streamer_source", "../../../src/proto_reader:proto_reader", ] diff --git a/trace_streamer/test/test_fuzzer/selector_fuzzer/BUILD.gn b/trace_streamer/test/test_fuzzer/selector_fuzzer/BUILD.gn index 511d61d2e..146e2c734 100644 --- a/trace_streamer/test/test_fuzzer/selector_fuzzer/BUILD.gn +++ b/trace_streamer/test/test_fuzzer/selector_fuzzer/BUILD.gn @@ -48,7 +48,7 @@ ohos_fuzztest("ts_selector_fuzz_test") { deps = [ "${THIRD_PARTY}/protobuf:protobuf", "${THIRD_PARTY}/protobuf:protobuf_lite", - # "${THIRD_PARTY}/sqlite:sqlite", + "${THIRD_PARTY}/sqlite:sqlite", "../../../src:trace_streamer_source", "../../../src/proto_reader:proto_reader", ] diff --git a/trace_streamer/test/test_ts.gni b/trace_streamer/test/test_ts.gni index 4a051f46f..e67c6457f 100755 --- a/trace_streamer/test/test_ts.gni +++ b/trace_streamer/test/test_ts.gni @@ -13,6 +13,7 @@ OHOS_PROTO_DIR = "" kernel_version = "." THIRD_PARTY = "//third_party" +SRC = "//src" PREBUILTS = "//prebuilts" if (target_os == "linux" || target_os == "windows" || target_os == "macx") { if (is_test) { -- Gitee From d9a439b726310e1d4f0319d53b83b94bb6f3c901 Mon Sep 17 00:00:00 2001 From: jichuan Date: Thu, 27 Jul 2023 14:55:49 +0800 Subject: [PATCH 03/14] =?UTF-8?q?Fix:=E5=BA=94=E7=94=A8=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E9=98=B6=E6=AE=B5=E6=B3=B3=E9=81=93=E5=9B=BE=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=8C=81=E7=BB=AD=E6=97=B6=E9=95=BF=E4=BF=A1=E6=81=AF=E5=B1=95?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: jichuan --- ide/src/trace/database/SqlLite.ts | 19 ++++++++++++------- .../ui-worker/ProcedureWorkerAppStartup.ts | 6 +++++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/ide/src/trace/database/SqlLite.ts b/ide/src/trace/database/SqlLite.ts index f8ace2b35..41774cb2d 100644 --- a/ide/src/trace/database/SqlLite.ts +++ b/ide/src/trace/database/SqlLite.ts @@ -1299,7 +1299,9 @@ export const queryStartupPidArray = (): Promise> => query( 'queryStartupPidArray', ` - select distinct pid from app_startup A left join process P on A.ipid = p.ipid;`, + select distinct pid +from app_startup A,trace_range B left join process P on A.ipid = p.ipid +where A.start_time between B.start_ts and B.end_ts;`, {} ); @@ -1328,7 +1330,8 @@ export const queryProcessSoMaxDepth = (): Promise Date: Thu, 27 Jul 2023 14:57:34 +0800 Subject: [PATCH 04/14] =?UTF-8?q?Feat:TaskPool=E6=A8=A1=E6=9D=BF=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: jichuan --- ide/server/server-config.txt | 2 +- ide/src/trace/SpApplication.ts | 30 ++ ide/src/trace/bean/BoxSelection.ts | 2 + ide/src/trace/component/SpFlags.ts | 326 +++++++++++++ .../trace/component/SpRecyclerSystemTrace.ts | 2 +- ide/src/trace/component/SpSystemTrace.ts | 456 ++++++++++++++---- .../trace/component/chart/SpChartManager.ts | 5 +- .../component/setting/SpRecordTemplate.ts | 41 +- .../trace/component/trace/base/TraceSheet.ts | 4 +- .../component/trace/base/TraceSheetConfig.ts | 6 + .../trace/sheet/TabPaneCurrentSelection.ts | 6 +- .../trace/sheet/task/TabPaneTaskFrames.ts | 391 +++++++++++++++ ide/src/trace/database/SqlLite.ts | 124 ++++- .../ProcedureLogicWorkerFileSystem.ts | 2 + .../logic-worker/ProcedureLogicWorkerPerf.ts | 4 + .../ui-worker/ProcedureWorkerCommon.ts | 243 +++++++--- .../database/ui-worker/ProcedureWorkerFunc.ts | 17 + 17 files changed, 1486 insertions(+), 175 deletions(-) create mode 100644 ide/src/trace/component/SpFlags.ts create mode 100644 ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts diff --git a/ide/server/server-config.txt b/ide/server/server-config.txt index 2c740bc33..fde296819 100644 --- a/ide/server/server-config.txt +++ b/ide/server/server-config.txt @@ -1 +1 @@ -127.0.0.1:9100 \ No newline at end of file +127.0.0.1:9100/statistics \ No newline at end of file diff --git a/ide/src/trace/SpApplication.ts b/ide/src/trace/SpApplication.ts index 2a4dc45f3..cc96ac3da 100644 --- a/ide/src/trace/SpApplication.ts +++ b/ide/src/trace/SpApplication.ts @@ -49,6 +49,8 @@ import './component/trace/base/TraceRowConfig.js'; import { TraceRowConfig } from './component/trace/base/TraceRowConfig.js'; import { ColorUtils } from './component/trace/base/ColorUtils.js'; import { SpStatisticsHttpUtil } from '../statistics/util/SpStatisticsHttpUtil.js'; +import { SpFlags } from './component/SpFlags.js'; +import './component/SpFlags.js'; @element('sp-application') export class SpApplication extends BaseElement { @@ -384,6 +386,8 @@ export class SpApplication extends BaseElement { + @@ -402,6 +406,7 @@ export class SpApplication extends BaseElement { let spInfoAndStats = this.shadowRoot!.querySelector('#sp-info-and-stats') as SpInfoAndStats; // new SpInfoAndStats(); let spSystemTrace = this.shadowRoot!.querySelector('#sp-system-trace'); this.spHelp = this.shadowRoot!.querySelector('#sp-help'); + let spFlags = this.shadowRoot!.querySelector('#sp-flags') as SpFlags; let spRecordTrace = this.shadowRoot!.querySelector('#sp-record-trace'); let spRecordTemplate = this.shadowRoot!.querySelector('#sp-record-template'); let spSchedulingAnalysis = this.shadowRoot!.querySelector( @@ -425,6 +430,7 @@ export class SpApplication extends BaseElement { spInfoAndStats, this.spHelp, spRecordTemplate, + spFlags, ]; let sideColor = mainMenu.shadowRoot?.querySelector('.color') as HTMLDivElement; //修改侧边导航栏配色 @@ -859,6 +865,18 @@ export class SpApplication extends BaseElement { showContent(that.spHelp!); }, }, + { + title: 'Flags', + icon: 'menu', + clickHandler: function (item: MenuItem) { + SpStatisticsHttpUtil.addOrdinaryVisitAction({ + event: 'flags', + action: 'flags', + }); + that.search = false; + showContent(spFlags); + }, + }, ], }); if (res.status) { @@ -1073,6 +1091,18 @@ export class SpApplication extends BaseElement { showContent(that.spHelp!); }, }, + { + title: 'Flags', + icon: 'menu', + clickHandler: function (item: MenuItem) { + SpStatisticsHttpUtil.addOrdinaryVisitAction({ + event: 'flags', + action: 'flags', + }); + that.search = false; + showContent(spFlags); + }, + }, ], }, ]; diff --git a/ide/src/trace/bean/BoxSelection.ts b/ide/src/trace/bean/BoxSelection.ts index d97a448df..41ec197ca 100644 --- a/ide/src/trace/bean/BoxSelection.ts +++ b/ide/src/trace/bean/BoxSelection.ts @@ -16,6 +16,7 @@ import { CpuFreqLimitsStruct } from '../database/ui-worker/ProcedureWorkerCpuFreqLimits.js'; import { ClockStruct } from '../database/ui-worker/ProcedureWorkerClock.js'; import { IrqStruct } from '../database/ui-worker/ProcedureWorkerIrq.js'; +import { FuncStruct } from '../database/ui-worker/ProcedureWorkerFunc.js'; export class SelectionParam { recordStartNs: number = 0; @@ -70,6 +71,7 @@ export class SelectionParam { promiseList: Array> = []; jankFramesData: Array = []; jsMemory: Array = []; + taskFramesData: Array> = []; } export class BoxJumpParam { diff --git a/ide/src/trace/component/SpFlags.ts b/ide/src/trace/component/SpFlags.ts new file mode 100644 index 000000000..b01f16e7f --- /dev/null +++ b/ide/src/trace/component/SpFlags.ts @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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-flags') +export class SpFlags extends BaseElement { + private bodyEl: HTMLElement | undefined | null; + + initElements(): void { + let parentElement = this.parentNode as HTMLElement; + parentElement.style.overflow = 'hidden'; + this.bodyEl = this.shadowRoot?.querySelector('.body'); + this.initConfigList(); + } + + initHtml(): string { + return ` + ${this.initHtmlStyle()} +
+
+

Feature flags

+
+
+ `; + } + + private initHtmlStyle(): string { + return ` + + `; + } + + private createConfigDiv(): HTMLDivElement { + let configDiv = document.createElement('div'); + configDiv.className = 'flag-widget'; + return configDiv; + } + + private createCustomDiv(config: FlagConfigItem, configDiv: HTMLDivElement): void { + let configHadDiv = document.createElement('div'); + configHadDiv.className = 'flag-head-div'; + let titleLabel = document.createElement('label'); + titleLabel.textContent = config.title; + titleLabel.className = 'flag-title-label'; + let configSelect = document.createElement('select'); + configSelect.className = 'flag-select'; + configSelect.setAttribute('title', config.title); + config.switchOptions.forEach((optionItem) => { + let configOption = document.createElement('option'); + configOption.value = optionItem.option; + configOption.textContent = optionItem.option; + if (optionItem.selected) { + configOption.selected = true; + } + configSelect.appendChild(configOption); + }); + configSelect.addEventListener('change', () => { + let title = configSelect.getAttribute('title'); + FlagsConfig.updateFlagsConfig(title!, configSelect.selectedOptions[0].value); + }); + let description = document.createElement('div'); + description.className = 'flag-des-div'; + description.textContent = config.describeContent; + configHadDiv.appendChild(titleLabel); + configHadDiv.appendChild(configSelect); + configDiv.appendChild(configHadDiv); + configDiv.appendChild(description); + } + + private initConfigList(): void { + let allConfig = FlagsConfig.getAllFlagConfig(); + allConfig.forEach((config) => { + let configDiv = this.createConfigDiv(); + this.createCustomDiv(config, configDiv); + if (config.title === 'DynamicAnalysis') { + let configFooterDiv = document.createElement('div'); + configFooterDiv.className = 'config_footer'; + let deviceWidthLabelEl = document.createElement('label'); + deviceWidthLabelEl.className = 'device_label'; + deviceWidthLabelEl.textContent = 'PhysicalWidth :'; + let deviceWidthEl = document.createElement('input'); + deviceWidthEl.value = config.addInfo!.physicalWidth; + deviceWidthEl.addEventListener('keyup', () => { + deviceWidthEl.value = deviceWidthEl.value.replace(/\D/g, ''); + }); + deviceWidthEl.addEventListener('blur', () => { + if (deviceWidthEl.value !== '') { + FlagsConfig.updateFlagsConfig('physicalWidth', Number(deviceWidthEl.value)); + } + }); + deviceWidthEl.className = 'device_input'; + let deviceHeightLabelEl = document.createElement('label'); + deviceHeightLabelEl.textContent = 'PhysicalHeight :'; + deviceHeightLabelEl.className = 'device_label'; + let deviceHeightEl = document.createElement('input'); + deviceHeightEl.className = 'device_input'; + deviceHeightEl.value = config.addInfo!.physicalHeight; + deviceHeightEl.addEventListener('keyup', () => { + deviceHeightEl.value = deviceHeightEl.value.replace(/\D/g, ''); + }); + deviceHeightEl.addEventListener('blur', () => { + if (deviceWidthEl.value !== '') { + FlagsConfig.updateFlagsConfig('physicalHeight', Number(deviceHeightEl.value)); + } + }); + configFooterDiv.appendChild(deviceWidthLabelEl); + configFooterDiv.appendChild(deviceWidthEl); + configFooterDiv.appendChild(deviceHeightLabelEl); + configFooterDiv.appendChild(deviceHeightEl); + configDiv.appendChild(configFooterDiv); + } + this.bodyEl!.appendChild(configDiv); + }); + } +} + +export type Params = { + [key: string]: unknown; +}; + +export class FlagsConfig { + static FLAGS_CONFIG_KEY = 'FlagsConfig'; + static DEFAULT_CONFIG: Array = [ + { + title: 'TaskPool', + switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }], + describeContent: 'Analyze TaskPool templates', + }, + ]; + + static getAllFlagConfig(): Array { + let flagsConfigStr = window.localStorage.getItem(FlagsConfig.FLAGS_CONFIG_KEY); + if (flagsConfigStr === null) { + let flagConfigObj: Params = {}; + FlagsConfig.DEFAULT_CONFIG.forEach((config) => { + let selectedOption = config.switchOptions.filter((option) => { + return option.selected; + }); + let value = config.switchOptions[0].option; + if (selectedOption[0] !== undefined) { + value = selectedOption[0].option; + } + flagConfigObj[config.title] = value; + if (config.addInfo) { + for (const [key, value] of Object.entries(config.addInfo)) { + flagConfigObj[key] = value; + } + } + }); + window.localStorage.setItem(FlagsConfig.FLAGS_CONFIG_KEY, JSON.stringify(flagConfigObj)); + return FlagsConfig.DEFAULT_CONFIG; + } else { + let flagsConfig = JSON.parse(flagsConfigStr); + FlagsConfig.DEFAULT_CONFIG.forEach((config) => { + let cfg = flagsConfig[config.title]; + if (cfg) { + config.switchOptions.forEach((option) => { + if (option.option === cfg) { + option.selected = true; + } else { + option.selected = false; + } + }); + } + if (config.addInfo) { + for (const [key, value] of Object.entries(config.addInfo)) { + let cfg = flagsConfig[key]; + if (cfg) { + config.addInfo[key] = cfg; + } + } + } + }); + } + return FlagsConfig.DEFAULT_CONFIG; + } + + static getFlagsConfig(flagName: string): Params | undefined { + let flagConfigObj: Params = {}; + let configItem = FlagsConfig.getAllFlagConfig().find((config) => { + return config.title === flagName; + }); + if (configItem) { + let selectedOption = configItem.switchOptions.filter((option) => { + return option.selected; + }); + let value = configItem.switchOptions[0].option; + if (selectedOption[0] !== undefined) { + value = selectedOption[0].option; + } + flagConfigObj[configItem.title] = value; + if (configItem.addInfo) { + for (const [key, value] of Object.entries(configItem.addInfo)) { + flagConfigObj[key] = value; + } + } + return flagConfigObj; + } else { + return configItem; + } + } + + static updateFlagsConfig(key: string, value: unknown): void { + let flagsConfigStr = window.localStorage.getItem(FlagsConfig.FLAGS_CONFIG_KEY); + let flagConfigObj: Params = {}; + if (flagsConfigStr !== null) { + flagConfigObj = JSON.parse(flagsConfigStr); + } + flagConfigObj[key] = value; + window.localStorage.setItem(FlagsConfig.FLAGS_CONFIG_KEY, JSON.stringify(flagConfigObj)); + } +} + +export interface FlagConfigItem { + title: string; + switchOptions: OptionItem[]; + describeContent: string; + addInfo?: Params; +} + +export interface OptionItem { + option: string; + selected?: boolean; +} diff --git a/ide/src/trace/component/SpRecyclerSystemTrace.ts b/ide/src/trace/component/SpRecyclerSystemTrace.ts index 87197e75c..e42a6d0cb 100644 --- a/ide/src/trace/component/SpRecyclerSystemTrace.ts +++ b/ide/src/trace/component/SpRecyclerSystemTrace.ts @@ -258,7 +258,7 @@ export class SpRecyclerSystemTrace extends BaseElement { this.traceSheetEL?.displayThreadData(ThreadStruct.hoverThreadStruct); } else if (FuncStruct.hoverFuncStruct) { FuncStruct.selectFuncStruct = FuncStruct.hoverFuncStruct; - this.traceSheetEL?.displayFuncData(FuncStruct.hoverFuncStruct); + this.traceSheetEL?.displayFuncData(['current-selection'], FuncStruct.hoverFuncStruct); } else if (SportRuler.rulerFlagObj) { } else { this.traceSheetEL?.setAttribute('mode', 'hidden'); diff --git a/ide/src/trace/component/SpSystemTrace.ts b/ide/src/trace/component/SpSystemTrace.ts index db1dd58df..d6122bc04 100644 --- a/ide/src/trace/component/SpSystemTrace.ts +++ b/ide/src/trace/component/SpSystemTrace.ts @@ -16,7 +16,14 @@ import { BaseElement, element } from '../../base-ui/BaseElement.js'; import './trace/TimerShaftElement.js'; import './trace/base/TraceRow.js'; -import { queryEbpfSamplesCount, querySceneSearchFunc, querySearchFunc, threadPool } from '../database/SqlLite.js'; +import { + queryBySelectAllocationOrReturn, + queryBySelectExecute, + queryEbpfSamplesCount, + querySceneSearchFunc, + querySearchFunc, + threadPool, +} from '../database/SqlLite.js'; import { RangeSelectStruct, TraceRow } from './trace/base/TraceRow.js'; import { TimerShaftElement } from './trace/TimerShaftElement.js'; import './trace/base/TraceSheet.js'; @@ -37,6 +44,7 @@ import { drawWakeUp, drawWakeUpList, isFrameContainPoint, + LineType, ns2x, ns2xByTimeShaft, PairPoint, @@ -80,6 +88,8 @@ import { HeapTimelineStruct } from '../database/ui-worker/ProcedureWorkerHeapTim import { TabPaneCurrentSelection } from './trace/sheet/TabPaneCurrentSelection.js'; import { AppStartupStruct } from '../database/ui-worker/ProcedureWorkerAppStartup.js'; import { SoStruct } from '../database/ui-worker/ProcedureWorkerSoInit.js'; +import { TabPaneTaskFrames } from './trace/sheet/task/TabPaneTaskFrames.js'; +import { FlagsConfig } from './SpFlags.js'; function dpr() { return window.devicePixelRatio || 1; @@ -98,7 +108,7 @@ function throttle(fn: any, t: number, ev: any): any { timer = null; }, t); } - } + }; } @element('sp-system-trace') @@ -109,6 +119,10 @@ export class SpSystemTrace extends BaseElement { static scrollViewWidth = 0; static isCanvasOffScreen = true; static DATA_DICT: Map = new Map(); + static DATA_TASK_POOL_CALLSTACK: Map = new Map< + number, + { id: number; ts: number; dur: number; name: string } + >(); static SDK_CONFIG_MAP: any; static sliceRangeMark: any; static wakeupList: Array = []; @@ -172,6 +186,30 @@ export class SpSystemTrace extends BaseElement { this.linkNodes.length = 0; } + removeLinkLinesByBusinessType(...businessTypes: string[]) { + this.linkNodes = this.linkNodes.filter((pointPair) => { + return !(businessTypes.indexOf(pointPair[0].business) > -1); + }); + } + + hiddenLinkLinesByBusinessType(...businessTypes: string[]) { + this.linkNodes.map((value) => { + if (businessTypes.indexOf(value[0].business) !== -1) { + value[0].hidden = true; + value[1].hidden = true; + } + }); + } + + showLinkLinesByBusinessType(...businessTypes: string[]) { + this.linkNodes.map((value) => { + if (businessTypes.indexOf(value[0].business) !== -1) { + value[0].hidden = false; + value[1].hidden = false; + } + }); + } + initElements(): void { let sideColor = document!.querySelector("body > sp-application")!.shadowRoot!.querySelector!("#main-menu")?. shadowRoot?.querySelector("div.bottom > div.color"); @@ -260,17 +298,20 @@ export class SpSystemTrace extends BaseElement { replaceRow.style.display = 'none'; currentRow.rowHidden = !currentRow.hasAttribute('scene'); // 添加收藏时,在线程名前面追加父亲ID - let rowParentId = currentRow.rowParentId + let rowParentId = currentRow.rowParentId; if (rowParentId) { - let parentRows = this.shadowRoot?.querySelectorAll>( - `trace-row[row-id='${rowParentId}']` - ); + let parentRows = this.shadowRoot?.querySelectorAll>(`trace-row[row-id='${rowParentId}']`); parentRows?.forEach((parentRow) => { - if (parentRow?.name && parentRow?.name != currentRow.name && !parentRow.rowType!.startsWith('cpu') - && !parentRow.rowType!.startsWith('thread') && !parentRow.rowType!.startsWith('func')) { - currentRow.name += "(" + parentRow.name + ")" + if ( + parentRow?.name && + parentRow?.name != currentRow.name && + !parentRow.rowType!.startsWith('cpu') && + !parentRow.rowType!.startsWith('thread') && + !parentRow.rowType!.startsWith('func') + ) { + currentRow.name += '(' + parentRow.name + ')'; } - }) + }); } if (this.rowsEL!.contains(currentRow)) { this.rowsEL!.replaceChild(replaceRow, currentRow); @@ -307,9 +348,9 @@ export class SpSystemTrace extends BaseElement { ); if (replaceRow != null) { // 取消收藏时,删除父亲ID - let rowNameArr = currentRow.name.split("("); + let rowNameArr = currentRow.name.split('('); if (rowNameArr.length > 1) { - let tempName = ""; + let tempName = ''; tempName += rowNameArr[0]; currentRow.name = tempName; } else { @@ -516,6 +557,7 @@ export class SpSystemTrace extends BaseElement { selection.threadIds.push(parseInt(it.rowId!)); info('load thread traceRow id is : ', it.rowId); } else if (it.rowType == TraceRow.ROW_TYPE_FUNC) { + TabPaneTaskFrames.TaskArray = []; this.pushPidToSelection(selection, it.rowParentId!); if (it.asyncFuncName) { selection.funAsync.push({ @@ -525,6 +567,17 @@ export class SpSystemTrace extends BaseElement { } else { selection.funTids.push(parseInt(it.rowId!)); } + + let isIntersect = (a: FuncStruct, b: RangeSelectStruct) => + Math.max(a.startTs! + a.dur!, b!.endNS || 0) - Math.min(a.startTs!, b!.startNS || 0) < + a.dur! + (b!.endNS || 0) - (b!.startNS || 0) && a.funName!.indexOf('H:Task ') >= 0; + let taskData = it.dataList.filter((taskData: FuncStruct) => { + taskData!.tid = parseInt(it.rowId!); + return isIntersect(taskData, TraceRow.rangeSelectObject!); + }); + if (taskData.length > 0) { + selection.taskFramesData.push(taskData); + } info('load func traceRow id is : ', it.rowId); } else if (it.rowType == TraceRow.ROW_TYPE_MEM || it.rowType == TraceRow.ROW_TYPE_VIRTUAL_MEMORY) { if (it.rowType == TraceRow.ROW_TYPE_MEM) { @@ -699,8 +752,8 @@ export class SpSystemTrace extends BaseElement { }); } else if (it.rowType == TraceRow.ROW_TYPE_JANK) { let isIntersect = (a: JanksStruct, b: RangeSelectStruct) => - Math.max(a.ts! + a.dur!, b!.endNS || 0) - Math.min(a.ts!, b!.startNS || 0) < - a.dur! + (b!.endNS || 0) - (b!.startNS || 0); + Math.max(a.ts! + a.dur!, b!.endNS || 0) - Math.min(a.ts!, b!.startNS || 0) < + a.dur! + (b!.endNS || 0) - (b!.startNS || 0); if (it.name == 'Actual Timeline') { selection.jankFramesData = []; let jankDatas = it.dataList.filter((jankData: any) => { @@ -709,14 +762,14 @@ export class SpSystemTrace extends BaseElement { selection.jankFramesData.push(jankDatas); } else if (it.folder) { selection.jankFramesData = []; - it.childrenList.forEach(child => { + it.childrenList.forEach((child) => { if (child.rowType == TraceRow.ROW_TYPE_JANK && child.name == 'Actual Timeline') { let jankDatas = child.dataList.filter((jankData: any) => { return isIntersect(jankData, TraceRow.rangeSelectObject!); }); selection.jankFramesData.push(jankDatas); } - }) + }); } } else if (it.rowType === TraceRow.ROW_TYPE_HEAP_TIMELINE || it.rowType === TraceRow.ROW_TYPE_JS_MEMORY) { selection.jsMemory.push(it.rowId); @@ -809,7 +862,7 @@ export class SpSystemTrace extends BaseElement { } else { this.traceSheetEL?.rangeSelect(selection); } - this.timerShaftEL!.selectionList.push(selection);// 保持选中对象,为后面的再次选中该框选区域做准备。 + this.timerShaftEL!.selectionList.push(selection); // 保持选中对象,为后面的再次选中该框选区域做准备。 this.selectionParam = selection; }; // @ts-ignore @@ -860,7 +913,11 @@ export class SpSystemTrace extends BaseElement { tr.sleeping = true; this.visibleRows = this.visibleRows.filter((it) => !it.sleeping); } else { - if (!this.visibleRows.find( vr => vr.rowId === tr.rowId && vr.rowType === tr.rowType && vr.rowParentId === tr.rowParentId)) { + if ( + !this.visibleRows.find( + (vr) => vr.rowId === tr.rowId && vr.rowType === tr.rowType && vr.rowParentId === tr.rowParentId + ) + ) { this.visibleRows.push(tr); } tr.sleeping = false; @@ -879,7 +936,7 @@ export class SpSystemTrace extends BaseElement { this.selectStructNull(); this.timerShaftEL?.setSlicesMark(); this.traceSheetEL?.setAttribute('mode', 'hidden'); - this.clearPointPair(); + this.removeLinkLinesByBusinessType('janks', 'task'); } }); this.chartManager = new SpChartManager(this); @@ -1043,8 +1100,8 @@ export class SpSystemTrace extends BaseElement { this.traceSheetEL?.displayCurrent(sliceTime); // 给当前pane准备数据 let selection = this.timerShaftEL!.selectionMap.get(sliceTime.id); if (selection) { - selection.isCurrentPane = true; // 设置当前面板为可以显示的状态 - this.traceSheetEL?.rangeSelect(selection); // 显示选中区域对应的面板 + selection.isCurrentPane = true; // 设置当前面板为可以显示的状态 + this.traceSheetEL?.rangeSelect(selection); // 显示选中区域对应的面板 } }, 0); } @@ -1161,7 +1218,11 @@ export class SpSystemTrace extends BaseElement { v.draw(cache); }); //draw flag line segment for canvas - drawFlagLineSegment(this.canvasPanelCtx, this.hoverFlag, this.selectFlag, { + drawFlagLineSegment( + this.canvasPanelCtx, + this.hoverFlag, + this.selectFlag, + { x: 0, y: 0, width: this.timerShaftEL?.canvas?.clientWidth, @@ -1170,7 +1231,11 @@ export class SpSystemTrace extends BaseElement { this.timerShaftEL! ); //draw flag line segment for favorite canvas - drawFlagLineSegment(this.canvasFavoritePanelCtx, this.hoverFlag, this.selectFlag, { + drawFlagLineSegment( + this.canvasFavoritePanelCtx, + this.hoverFlag, + this.selectFlag, + { x: 0, y: 0, width: this.timerShaftEL?.canvas?.clientWidth, @@ -1209,7 +1274,7 @@ export class SpSystemTrace extends BaseElement { // draw wakeuplist for main canvas for (let i = 0; i < SpSystemTrace.wakeupList.length; i++) { if (i + 1 == SpSystemTrace.wakeupList.length) { - return + return; } drawWakeUpList( this.canvasPanelCtx, @@ -1222,8 +1287,8 @@ export class SpSystemTrace extends BaseElement { y: 0, width: this.timerShaftEL!.canvas!.clientWidth, height: this.canvasPanel!.clientHeight!, - } as Rect, - ) + } as Rect + ); drawWakeUpList( this.canvasFavoritePanelCtx, SpSystemTrace.wakeupList[i + 1], @@ -1235,9 +1300,9 @@ export class SpSystemTrace extends BaseElement { y: 0, width: this.timerShaftEL!.canvas!.clientWidth, height: this.canvasFavoritePanel!.clientHeight!, - } as Rect, - ) - }; + } as Rect + ); + } // Draw the connection curve if (this.linkNodes) { drawLinkLines(this.canvasPanelCtx!, this.linkNodes, this.timerShaftEL!, false); @@ -1265,11 +1330,11 @@ export class SpSystemTrace extends BaseElement { x < (TraceRow.rangeSelectObject?.endX || 0) ) { let findSlicestime = this.timerShaftEL!.sportRuler?.findSlicesTime(x, y); // 查找帽子 - if (!findSlicestime) { // 如果没有找到帽子,则绘制一个三角形的旗子 + if (!findSlicestime) { + // 如果没有找到帽子,则绘制一个三角形的旗子 let time = Math.round( - (x * (TraceRow.range?.endNS! - TraceRow.range?.startNS!)) / - this.timerShaftEL!.canvas!.offsetWidth + - TraceRow.range?.startNS! + (x * (TraceRow.range?.endNS! - TraceRow.range?.startNS!)) / this.timerShaftEL!.canvas!.offsetWidth + + TraceRow.range?.startNS! ); this.timerShaftEL!.sportRuler!.drawTriangle(time, 'triangle'); } @@ -1341,7 +1406,7 @@ export class SpSystemTrace extends BaseElement { this.traceSheetEL = this.shadowRoot?.querySelector('.trace-sheet'); let currentPane = this.traceSheetEL?.displayTab('tabpane-current'); if (this.slicestime) { - currentPane?.setCurrentSlicesTime(this.slicestime) + currentPane?.setCurrentSlicesTime(this.slicestime); } // 显示对应的面板信息 this.timerShaftEL!.selectionList.forEach((selection, index) => { @@ -1370,29 +1435,25 @@ export class SpSystemTrace extends BaseElement { if (CpuStruct.selectCpuStruct) { this.slicestime = this.timerShaftEL?.setSlicesMark( CpuStruct.selectCpuStruct.startTime || 0, - (CpuStruct.selectCpuStruct.startTime || 0) + - (CpuStruct.selectCpuStruct.dur || 0), + (CpuStruct.selectCpuStruct.startTime || 0) + (CpuStruct.selectCpuStruct.dur || 0), shiftKey ); } else if (ThreadStruct.selectThreadStruct) { this.slicestime = this.timerShaftEL?.setSlicesMark( ThreadStruct.selectThreadStruct.startTime || 0, - (ThreadStruct.selectThreadStruct.startTime || 0) + - (ThreadStruct.selectThreadStruct.dur || 0), + (ThreadStruct.selectThreadStruct.startTime || 0) + (ThreadStruct.selectThreadStruct.dur || 0), shiftKey ); } else if (FuncStruct.selectFuncStruct) { this.slicestime = this.timerShaftEL?.setSlicesMark( FuncStruct.selectFuncStruct.startTs || 0, - (FuncStruct.selectFuncStruct.startTs || 0) + - (FuncStruct.selectFuncStruct.dur || 0), + (FuncStruct.selectFuncStruct.startTs || 0) + (FuncStruct.selectFuncStruct.dur || 0), shiftKey ); } else if (IrqStruct.selectIrqStruct) { this.slicestime = this.timerShaftEL?.setSlicesMark( IrqStruct.selectIrqStruct.startNS || 0, - (IrqStruct.selectIrqStruct.startNS || 0) + - (IrqStruct.selectIrqStruct.dur || 0), + (IrqStruct.selectIrqStruct.startNS || 0) + (IrqStruct.selectIrqStruct.dur || 0), shiftKey ); } else if (TraceRow.rangeSelectObject) { @@ -1404,22 +1465,19 @@ export class SpSystemTrace extends BaseElement { } else if (JankStruct.selectJankStruct) { this.slicestime = this.timerShaftEL?.setSlicesMark( JankStruct.selectJankStruct.ts || 0, - (JankStruct.selectJankStruct.ts || 0) + - (JankStruct.selectJankStruct.dur || 0), + (JankStruct.selectJankStruct.ts || 0) + (JankStruct.selectJankStruct.dur || 0), shiftKey ); } else if (AppStartupStruct.selectStartupStruct) { this.slicestime = this.timerShaftEL?.setSlicesMark( AppStartupStruct.selectStartupStruct.startTs || 0, - (AppStartupStruct.selectStartupStruct.startTs || 0) + - (AppStartupStruct.selectStartupStruct.dur || 0), + (AppStartupStruct.selectStartupStruct.startTs || 0) + (AppStartupStruct.selectStartupStruct.dur || 0), shiftKey ); } else if (SoStruct.selectSoStruct) { this.slicestime = this.timerShaftEL?.setSlicesMark( SoStruct.selectSoStruct.startTs || 0, - (SoStruct.selectSoStruct.startTs || 0) + - (SoStruct.selectSoStruct.dur || 0), + (SoStruct.selectSoStruct.startTs || 0) + (SoStruct.selectSoStruct.dur || 0), shiftKey ); } else { @@ -1657,7 +1715,7 @@ export class SpSystemTrace extends BaseElement { let inFavoriteArea = this.favoriteRowsEL?.containPoint(ev); let rows = this.visibleRows.filter((it) => it.focusContain(ev, inFavoriteArea!) && it.collect == inFavoriteArea); if (JankStruct.delJankLineFlag) { - this.clearPointPair(); + this.removeLinkLinesByBusinessType('janks'); } if (rows && rows[0] && this.traceRowClickJudgmentConditions.get(rows[0]!.rowType!)?.()) { this.onClickHandler(rows[0]!.rowType!, rows[0]); @@ -1682,6 +1740,7 @@ export class SpSystemTrace extends BaseElement { this.selectFlag = null; this.timerShaftEL?.removeTriangle('inverted'); this.traceSheetEL?.setAttribute('mode', 'hidden'); + this.removeLinkLinesByBusinessType('task'); this.refreshCanvas(true); JankStruct.delJankLineFlag = true; } @@ -1713,7 +1772,10 @@ export class SpSystemTrace extends BaseElement { () => ClockStruct.hoverClockStruct !== null && ClockStruct.hoverClockStruct !== undefined, ], [TraceRow.ROW_TYPE_IRQ, () => IrqStruct.hoverIrqStruct !== null && IrqStruct.hoverIrqStruct !== undefined], - [TraceRow.ROW_TYPE_APP_STARTUP, () => AppStartupStruct.hoverStartupStruct !== null && AppStartupStruct.hoverStartupStruct !== undefined], + [ + TraceRow.ROW_TYPE_APP_STARTUP, + () => AppStartupStruct.hoverStartupStruct !== null && AppStartupStruct.hoverStartupStruct !== undefined, + ], [TraceRow.ROW_TYPE_STATIC_INIT, () => SoStruct.hoverSoStruct !== null && SoStruct.hoverSoStruct !== undefined], [TraceRow.ROW_TYPE_JANK, () => JankStruct.hoverJankStruct !== null && JankStruct.hoverJankStruct !== undefined], [TraceRow.ROW_TYPE_HEAP, () => HeapStruct.hoverHeapStruct !== null && HeapStruct.hoverHeapStruct !== undefined], @@ -1852,7 +1914,7 @@ export class SpSystemTrace extends BaseElement { this.traceSheetEL?.displayJankData( JankStruct.selectJankStruct!, (datas) => { - this.clearPointPair(); + this.removeLinkLinesByBusinessType('janks'); // 绘制跟自己关联的线 datas.forEach((data) => { let endParentRow = this.shadowRoot?.querySelector>( @@ -1877,7 +1939,7 @@ export class SpSystemTrace extends BaseElement { this.observerScrollHeightEnable = true; this.moveRangeToCenter(funcStract.startTime!, funcStract.dur!); this.scrollToActFunc(funcStract, false); - } + }; snapshotClickHandler = (d: HeapSnapshotStruct) => { this.observerScrollHeightEnable = true; @@ -1920,11 +1982,23 @@ export class SpSystemTrace extends BaseElement { this.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct, threadClickHandler, cpuClickHandler); this.timerShaftEL?.modifyFlagList(undefined); } else if (clickRowType === TraceRow.ROW_TYPE_FUNC && FuncStruct.hoverFuncStruct) { + TabPaneTaskFrames.TaskArray = []; + this.removeLinkLinesByBusinessType('task'); FuncStruct.selectFuncStruct = FuncStruct.hoverFuncStruct; let hoverFuncStruct = FuncStruct.hoverFuncStruct; this.timerShaftEL?.drawTriangle(FuncStruct.selectFuncStruct!.startTs || 0, 'inverted'); FuncStruct.selectFuncStruct = hoverFuncStruct; - this.traceSheetEL?.displayFuncData(FuncStruct.selectFuncStruct, scrollToFuncHandler); + let flagConfig = FlagsConfig.getFlagsConfig('TaskPool'); + let showTabArray: Array = ['current-selection']; + if (flagConfig!.TaskPool === 'Enabled') { + if (FuncStruct.selectFuncStruct !== undefined && FuncStruct.selectFuncStruct.funName !== undefined) { + if (FuncStruct.selectFuncStruct.funName.indexOf('H:Task ') >= 0) { + showTabArray.push('box-task-frames'); + this.drawTaskPollLine(row); + } + } + } + this.traceSheetEL?.displayFuncData(showTabArray, FuncStruct.selectFuncStruct, scrollToFuncHandler); this.timerShaftEL?.modifyFlagList(undefined); } else if (clickRowType === TraceRow.ROW_TYPE_CPU_FREQ && CpuFreqStruct.hoverCpuFreqStruct) { CpuFreqStruct.selectCpuFreqStruct = CpuFreqStruct.hoverCpuFreqStruct; @@ -1957,7 +2031,7 @@ export class SpSystemTrace extends BaseElement { this.timerShaftEL?.modifyFlagList(undefined); } else if (clickRowType === TraceRow.ROW_TYPE_JANK && JankStruct.hoverJankStruct) { JankStruct.selectJankStructList.length = 0; - this.clearPointPair(); + this.removeLinkLinesByBusinessType('janks'); JankStruct.selectJankStruct = JankStruct.hoverJankStruct; this.timerShaftEL?.drawTriangle(JankStruct.selectJankStruct!.ts || 0, 'inverted'); this.traceSheetEL?.displayJankData( @@ -1997,7 +2071,7 @@ export class SpSystemTrace extends BaseElement { this.timerShaftEL?.modifyFlagList(undefined); } else { if (!JankStruct.hoverJankStruct && JankStruct.delJankLineFlag) { - this.clearPointPair(); + this.removeLinkLinesByBusinessType('janks'); } this.observerScrollHeightEnable = false; this.selectFlag = null; @@ -2008,7 +2082,7 @@ export class SpSystemTrace extends BaseElement { } } if (!JankStruct.selectJankStruct) { - this.clearPointPair(); + this.removeLinkLinesByBusinessType('janks'); } if (row) { let pointEvent = this.createPointEvent(row); @@ -2019,6 +2093,231 @@ export class SpSystemTrace extends BaseElement { } } + makePoint( + ts: number, + dur: number, + translateY: number, + rowStruct: any, + offsetY: number, + business: string, + lineType: LineType, + isRight: boolean + ): PairPoint { + return { + x: ns2xByTimeShaft(ts + dur, this.timerShaftEL!), + y: translateY!, + offsetY: offsetY, + ns: ts + dur, + rowEL: rowStruct!, + isRight: isRight, + business: business, + lineType: lineType, + }; + } + + drawTaskPollLine(row?: TraceRow) { + let executeID = TabPaneTaskFrames.getExecuteId(FuncStruct.selectFuncStruct!.funName!); + TabPaneTaskFrames.TaskArray.push(FuncStruct.selectFuncStruct!); + if (!row) { + return; + } + if (FuncStruct.selectFuncStruct!.funName!.indexOf('H:Task Perform:') >= 0) { + TabPaneTaskFrames.IsShowConcurrency = true; + queryBySelectExecute(executeID).then((res) => { + if (res.length === 1) { + let allocationRowId = res[0].tid; + let selectRow = this.shadowRoot?.querySelector>( + `trace-row[row-id='${allocationRowId}'][row-type=\'func\']` + ); + selectRow!.dataList.forEach((value) => { + // allocation to execute + if (value.id === res[0].allocation_task_row) { + TabPaneTaskFrames.TaskArray.push(value); + this.addPointPair( + this.makePoint( + value.startTs!, + 0, + selectRow?.translateY!, + selectRow, + (value.depth! + 0.5) * 20, + 'task', + LineType.bezierCurve, + true + ), + this.makePoint( + FuncStruct.selectFuncStruct!.startTs!, + 0, + row?.translateY!, + row, + 25, + 'task', + LineType.bezierCurve, + true + ) + ); + } + // execute to return + if (value.id === res[0].return_task_row) { + TabPaneTaskFrames.TaskArray.push(value); + this.addPointPair( + this.makePoint( + FuncStruct.selectFuncStruct!.startTs!, + FuncStruct.selectFuncStruct!.dur!, + row?.translateY!, + row, + 25, + 'task', + LineType.bezierCurve, + false + ), + this.makePoint( + value.startTs!, + value.dur!, + selectRow?.translateY!, + selectRow, + (value.depth! + 0.5) * 20, + 'task', + LineType.bezierCurve, + false + ) + ); + } + }); + this.refreshCanvas(true); + } + }); + } else { + TabPaneTaskFrames.IsShowConcurrency = false; + queryBySelectAllocationOrReturn(executeID).then((res) => { + if (FuncStruct.selectFuncStruct!.funName!.indexOf('H:Task Allocation:') >= 0 && res.length > 0) { + let executeRow = this.shadowRoot?.querySelector>( + `trace-row[row-id='${res[0].tid}'][row-type='func']` + ); + let endStruct: FuncStruct; + row!.dataList.forEach((value) => { + if (value.id === res[0].return_task_row) { + TabPaneTaskFrames.TaskArray.push(value); + endStruct = value; + } + }); + if (!executeRow) { + return; + } + executeRow!.dataList.forEach((value) => { + if (value.id === res[0].execute_task_row) { + TabPaneTaskFrames.TaskArray.push(value); + this.addPointPair( + this.makePoint( + FuncStruct.selectFuncStruct!.startTs!, + 0, + row?.translateY!, + row, + (FuncStruct.selectFuncStruct!.depth! + 0.5) * 20, + 'task', + LineType.bezierCurve, + true + ), + this.makePoint( + value.startTs!, + 0, + executeRow?.translateY!, + executeRow, + (value.depth! + 0.5) * 20, + 'task', + LineType.bezierCurve, + true + ) + ); + this.addPointPair( + this.makePoint( + value.startTs!, + value.dur!, + executeRow?.translateY!, + executeRow, + (value.depth! + 0.5) * 20, + 'task', + LineType.bezierCurve, + false + ), + this.makePoint( + endStruct.startTs!, + endStruct.dur!, + row?.translateY!, + row, + (value.depth! + 0.5) * 20, + 'task', + LineType.bezierCurve, + false + ) + ); + } + }); + } else if (FuncStruct.selectFuncStruct!.funName!.indexOf('H:Task PerformTask End:') >= 0) { + let executeRow = this.shadowRoot?.querySelector>( + `trace-row[row-id='${res[0].tid}'][row-type='func']` + ); + TabPaneTaskFrames.TaskArray.push(FuncStruct.selectFuncStruct!); + let startStruct: FuncStruct; + row!.dataList.forEach((value) => { + if (value.id === res[0].allocation_task_row) { + TabPaneTaskFrames.TaskArray.push(value); + startStruct = value; + } + }); + executeRow!.dataList.forEach((value) => { + if (value.id === res[0].execute_task_row) { + TabPaneTaskFrames.TaskArray.push(value); + this.addPointPair( + this.makePoint( + startStruct!.startTs!, + 0, + row?.translateY!, + row, + (startStruct!.depth! + 0.5) * 20, + 'task', + LineType.bezierCurve, + true + ), + this.makePoint( + value.startTs!, + 0, + executeRow?.translateY!, + executeRow, + (value.depth! + 0.5) * 20, + 'task', + LineType.bezierCurve, + true + ) + ); + this.addPointPair( + this.makePoint( + value.startTs!, + value.dur!, + executeRow?.translateY!, + executeRow, + (value.depth! + 0.5) * 20, + 'task', + LineType.bezierCurve, + false + ), + this.makePoint( + FuncStruct.selectFuncStruct!.startTs!, + FuncStruct.selectFuncStruct!.dur!, + row?.translateY!, + row, + (value.depth! + 0.5) * 20, + 'task', + LineType.bezierCurve, + false + ) + ); + } + }); + } + this.refreshCanvas(true); + }); + } + } drawJankLine(endParentRow: any, selectJankStruct: JankStruct, data: any) { let startRow: any; if (selectJankStruct == undefined || selectJankStruct == null) { @@ -2026,11 +2325,11 @@ export class SpSystemTrace extends BaseElement { } if (selectJankStruct.frame_type == 'frameTime') { startRow = this.shadowRoot?.querySelector>( - `trace-row[row-id='actual frameTime'][row-type='janks']` + "trace-row[row-id='actual frameTime'][row-type='janks']" ); } else { startRow = this.shadowRoot?.querySelector>( - `trace-row[row-id='${selectJankStruct?.type + '-' + selectJankStruct?.pid}'][row-type='janks']` + `trace-row[row-id='${`${selectJankStruct?.type}-${selectJankStruct?.pid}`}'][row-type='janks']` ); } if (endParentRow) { @@ -2039,11 +2338,11 @@ export class SpSystemTrace extends BaseElement { //泳道展开的情况,查找endRowStruct if (data.frame_type == 'frameTime') { endRowStruct = this.shadowRoot?.querySelector>( - `trace-row[row-id='actual frameTime'][row-type='janks']` + "trace-row[row-id='actual frameTime'][row-type='janks']" ); } else { endRowStruct = this.shadowRoot?.querySelector>( - `trace-row[row-id='${data.type + '-' + data.pid}'][row-type='janks']` + `trace-row[row-id='${`${data.type}-${data.pid}`}'][row-type='janks']` ); } //泳道未展开的情况,查找endRowStruct @@ -2057,7 +2356,7 @@ export class SpSystemTrace extends BaseElement { //frameTime未展开 if (!endRowStruct) { endParentRow = this.shadowRoot?.querySelector>( - `trace-row[row-id='frameTime'][folder]` + "trace-row[row-id='frameTime'][folder]" ); endParentRow?.childrenList?.forEach((item: TraceRow) => { if (item.rowId === 'actual frameTime' && item.rowType === 'janks') { @@ -2067,7 +2366,7 @@ export class SpSystemTrace extends BaseElement { } } else { endParentRow.childrenList.forEach((item: TraceRow) => { - if (item.rowId === data.type + '-' + data.pid && item.rowType === 'janks') { + if (item.rowId === `${data.type}-${data.pid}` && item.rowType === 'janks') { endRowStruct = item; } }); @@ -2118,6 +2417,7 @@ export class SpSystemTrace extends BaseElement { ns: tts, rowEL: startRowEl!, isRight: selectJankStruct.ts == tts, + business: 'janks', }, { x: ns2xByTimeShaft(findJankEntry.ts!, this.timerShaftEL!), @@ -2126,6 +2426,7 @@ export class SpSystemTrace extends BaseElement { ns: findJankEntry.ts!, rowEL: endRowEl, isRight: true, + business: 'janks', } ); } @@ -2159,6 +2460,7 @@ export class SpSystemTrace extends BaseElement { ns: selectJankStruct.ts!, rowEL: startRowEl!, isRight: true, + business: 'janks', }, { x: ns2xByTimeShaft(tts, this.timerShaftEL!), @@ -2167,13 +2469,14 @@ export class SpSystemTrace extends BaseElement { ns: tts, rowEL: endRowEl!, isRight: selectJankStruct.ts == tts, + business: 'janks', } ); } if (data.children.length >= 1) { let endP; if (data.children[0].frame_type == 'frameTime') { - endP = this.shadowRoot?.querySelector>(`trace-row[row-id='frameTime']`); + endP = this.shadowRoot?.querySelector>("trace-row[row-id='frameTime']"); } else { endP = this.shadowRoot?.querySelector>( `trace-row[row-id='${data.children[0].pid}'][folder]` @@ -2190,8 +2493,7 @@ export class SpSystemTrace extends BaseElement { myMouseMove = (ev: MouseEvent) => { if (ev.ctrlKey) { ev.preventDefault(); - SpSystemTrace.offsetMouse = - ev.clientX - SpSystemTrace.mouseCurrentPosition; + SpSystemTrace.offsetMouse = ev.clientX - SpSystemTrace.mouseCurrentPosition; let eventA = new KeyboardEvent('keypress', { key: 'a', code: '65', @@ -2203,20 +2505,14 @@ export class SpSystemTrace extends BaseElement { keyCode: 68, }); if (ev.button == 0) { - if ( - SpSystemTrace.offsetMouse < 0 && - SpSystemTrace.moveable - ) { + if (SpSystemTrace.offsetMouse < 0 && SpSystemTrace.moveable) { // 向右拖动,则泳道图右移 this.timerShaftEL!.documentOnKeyPress(eventD); setTimeout(() => { this.timerShaftEL!.documentOnKeyUp(eventD); }, 350); } - if ( - SpSystemTrace.offsetMouse > 0 && - SpSystemTrace.moveable - ) { + if (SpSystemTrace.offsetMouse > 0 && SpSystemTrace.moveable) { // 向左拖动,则泳道图左移 this.timerShaftEL!.documentOnKeyPress(eventA); setTimeout(() => { @@ -2226,7 +2522,7 @@ export class SpSystemTrace extends BaseElement { } SpSystemTrace.moveable = false; } - } + }; connectedCallback() { this.initPointToEvent(); @@ -2234,7 +2530,7 @@ export class SpSystemTrace extends BaseElement { * 监听时间轴区间变化 */ this.timerShaftEL!.rangeChangeHandler = this.timerShaftELRangeChange; - this.timerShaftEL!.rangeClickHandler = this.timerShaftELRangeClick + this.timerShaftEL!.rangeClickHandler = this.timerShaftELRangeClick; this.timerShaftEL!.flagChangeHandler = this.timerShaftELFlagChange; this.timerShaftEL!.flagClickHandler = this.timerShaftELFlagClickHandler; /** @@ -2279,11 +2575,7 @@ export class SpSystemTrace extends BaseElement { /** * ctrl+鼠标移动,实现泳道图左移或者右移。 */ - this.addEventListener( - 'mousemove', - ev => throttle(this.myMouseMove, 350, ev)(), - { passive: false } - ); + this.addEventListener('mousemove', (ev) => throttle(this.myMouseMove, 350, ev)(), { passive: false }); this.addEventListener( 'mouseup', @@ -2487,7 +2779,7 @@ export class SpSystemTrace extends BaseElement { this.selectStructNull(); this.wakeupListNull(); this.traceSheetEL?.setAttribute('mode', 'hidden'); - this.clearPointPair(); + this.removeLinkLinesByBusinessType('janks'); TraceRow.range!.refresh = true; this.refreshCanvas(false); } @@ -3114,7 +3406,7 @@ export class SpSystemTrace extends BaseElement { queryCPUWakeUpList(data: WakeupBean) { TabPaneCurrentSelection.queryCPUWakeUpListFromBean(data).then((a: any) => { if (a === null) { - return null + return null; } SpSystemTrace.wakeupList.push(a); this.queryCPUWakeUpList(a); diff --git a/ide/src/trace/component/chart/SpChartManager.ts b/ide/src/trace/component/chart/SpChartManager.ts index 68ca84d11..6e6fa5a6c 100644 --- a/ide/src/trace/component/chart/SpChartManager.ts +++ b/ide/src/trace/component/chart/SpChartManager.ts @@ -20,7 +20,7 @@ import { SpFreqChart } from './SpFreqChart.js'; import { SpFpsChart } from './SpFpsChart.js'; import { getCpuUtilizationRate, - queryDataDICT, + queryDataDICT, queryTaskPoolCallStack, queryThreadAndProcessName, queryTotalTime, } from '../../database/SqlLite.js'; @@ -87,6 +87,9 @@ export class SpChartManager { SpSystemTrace.DATA_DICT.clear(); let dict = await queryDataDICT(); dict.map((d) => SpSystemTrace.DATA_DICT.set(d['id'], d['data'])); + SpSystemTrace.DATA_TASK_POOL_CALLSTACK.clear(); + let taskPoolCallStack = await queryTaskPoolCallStack(); + taskPoolCallStack.map((d) => SpSystemTrace.DATA_TASK_POOL_CALLSTACK.set(d.id, d)); progress('time range', 65); await this.initTotalTime(); let ptArr = await queryThreadAndProcessName(); diff --git a/ide/src/trace/component/setting/SpRecordTemplate.ts b/ide/src/trace/component/setting/SpRecordTemplate.ts index 57385e528..12bb74da1 100644 --- a/ide/src/trace/component/setting/SpRecordTemplate.ts +++ b/ide/src/trace/component/setting/SpRecordTemplate.ts @@ -79,31 +79,26 @@ export class SpRecordTemplate extends BaseElement { private frameTimeline: LitSwitch | undefined | null; private schedulingAnalysis: LitSwitch | undefined | null; private appStartup: LitSwitch | undefined | null; + private taskPoolEl: LitSwitch | undefined | null; initElements(): void { this.frameTimeline = this.shadowRoot?.querySelector('#frame_timeline'); this.schedulingAnalysis = this.shadowRoot?.querySelector('#scheduling_analysis'); this.appStartup = this.shadowRoot?.querySelector('#app_startup'); - this.frameTimeline!.addEventListener('change', (event: CustomEventInit) => { - let detail = event.detail; - if (detail!.checked) { - this.dispatchEvent(new CustomEvent('addProbe', {})); - } - }); - this.appStartup!.addEventListener('change', (event: CustomEventInit) => { - let detail = event.detail; - if (detail!.checked) { - this.dispatchEvent(new CustomEvent('addProbe', {})); - } - }); - this.schedulingAnalysis!.addEventListener('change', (event: CustomEventInit) => { - let detail = event.detail; - if (detail!.checked) { - this.dispatchEvent(new CustomEvent('addProbe', {})); - } - }); + this.taskPoolEl = this.shadowRoot?.querySelector('#task_pool'); + this.addProbeListener(this.frameTimeline!, this.schedulingAnalysis!, this.appStartup!, this.taskPoolEl!) } + addProbeListener(...elements: HTMLElement[]) { + elements.forEach(element => { + element.addEventListener('change', (event: CustomEventInit) => { + let detail = event.detail; + if (detail!.checked) { + this.dispatchEvent(new CustomEvent('addProbe', {})); + } + }) + }) + } getTemplateConfig(): Array> { let config: Array> = []; let traceEventSet = new Array(); @@ -130,6 +125,10 @@ export class SpRecordTemplate extends BaseElement { } }); } + if (this.taskPoolEl!.checked) { + useFtracePlugin = true; + traceEventSet.push('commonlibrary') + } if (useFtracePlugin) { let tracePluginConfig: TracePluginConfig = { ftraceEvents: traceEventSet, @@ -217,6 +216,12 @@ export class SpRecordTemplate extends BaseElement { +
+
+ Task pool + +
+
`; } diff --git a/ide/src/trace/component/trace/base/TraceSheet.ts b/ide/src/trace/component/trace/base/TraceSheet.ts index 42b74b256..80ac2f646 100644 --- a/ide/src/trace/component/trace/base/TraceSheet.ts +++ b/ide/src/trace/component/trace/base/TraceSheet.ts @@ -377,8 +377,8 @@ export class TraceSheet extends BaseElement { this.showUploadSoBt(val); }; - displayFuncData = (data: FuncStruct, scrollCallback: Function) => - this.displayTab('current-selection').setFunctionData(data, scrollCallback); + displayFuncData = (names: string[], data: FuncStruct, scrollCallback: Function) => + this.displayTab(...names).setFunctionData(data, scrollCallback); displayCpuData = ( data: CpuStruct, callback: ((data: WakeupBean | null) => void) | undefined = undefined, diff --git a/ide/src/trace/component/trace/base/TraceSheetConfig.ts b/ide/src/trace/component/trace/base/TraceSheetConfig.ts index 55f9fe799..b06586278 100644 --- a/ide/src/trace/component/trace/base/TraceSheetConfig.ts +++ b/ide/src/trace/component/trace/base/TraceSheetConfig.ts @@ -76,6 +76,7 @@ import { TabPaneVirtualMemoryStatisticsAnalysis } from '../sheet/file-system/Tab import { TabPaneCurrent } from '../sheet/TabPaneCurrent.js'; import { TabPaneStartup } from '../sheet/process/TabPaneStartup.js'; import { TabPaneStaticInit } from '../sheet/process/TabPaneStaticInit.js'; +import { TabPaneTaskFrames } from '../sheet/task/TabPaneTaskFrames.js'; export let tabConfig: any = { 'tabpane-current': { @@ -394,4 +395,9 @@ export let tabConfig: any = { title: 'Comparison', type: TabPaneComparison, }, // snapshot data click + 'box-task-frames': { + title: 'Frames', + type: TabPaneTaskFrames, + require: (param: SelectionParam) => param.taskFramesData.length > 0, + }, }; diff --git a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts index 552de8fc4..1bb5ec67d 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts @@ -48,6 +48,7 @@ import { Utils } from '../base/Utils.js'; import { SpSystemTrace } from '../../SpSystemTrace.js'; import { AppStartupStruct } from '../../../database/ui-worker/ProcedureWorkerAppStartup.js'; import { SoStruct } from '../../../database/ui-worker/ProcedureWorkerSoInit.js'; +import { SelectionParam } from '../../../bean/BoxSelection.js'; 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.'; @@ -99,7 +100,10 @@ export class TabPaneCurrentSelection extends BaseElement { private dpr: any = window.devicePixelRatio || window.webkitDevicePixelRatio || window.mozDevicePixelRatio || 1; set data(currentSelectionValue: any) { - this.setCpuData(currentSelectionValue); + if (currentSelectionValue !== undefined && currentSelectionValue.constructor + && currentSelectionValue.constructor.name !== 'SelectionParam') { + this.setCpuData(currentSelectionValue); + } } setCpuData( diff --git a/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts b/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts new file mode 100644 index 000000000..c0acb0223 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts @@ -0,0 +1,391 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { SelectionParam } from '../../../../bean/BoxSelection'; +import { LitTable } from '../../../../../base-ui/table/lit-table'; +import { resizeObserver } from '../SheetUtils.js'; +import { FuncStruct } from '../../../../database/ui-worker/ProcedureWorkerFunc.js'; +import { + queryConcurrencyTask, + queryTaskListByExecuteTaskIds, + queryTaskPoolTotalNum +} from '../../../../database/SqlLite.js'; +import { BaseStruct } from '../../../../database/ui-worker/ProcedureWorkerCommon.js'; +import { SpSystemTrace } from '../../../SpSystemTrace.js'; +import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; + +@element('tabpane-task-frames') +export class TabPaneTaskFrames extends BaseElement { + private taskFramesTbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private taskFramesSource: Array = []; + private progressEL: LitProgressBar | null | undefined; + static TaskArray: Array = []; + static IsShowConcurrency: boolean = false; + + set data(framesParam: SelectionParam) { + if (TabPaneTaskFrames.TaskArray && TabPaneTaskFrames.TaskArray.length > 0) { + //点选 + this.setTaskData(TabPaneTaskFrames.TaskArray, framesParam, true); + } else { + if (!framesParam) { + this.taskFramesTbl!!.recycleDataSource = []; + return; + } + //框选 + this.range!.textContent = `Selected range: + ${ parseFloat(((framesParam.rightNs - framesParam.leftNs) / 1000000.0).toFixed(5)) } ms`; + this.progressEL!.loading = true; + this.queryDataByDB(framesParam, false); + } + } + + setTaskData(taskArray: Array, framesParam: SelectionParam, isClick: boolean) { + if (taskArray.length < 3) { + this.taskFramesTbl!!.recycleDataSource = []; + return; + } else { + let sTime = 0, eTime = 0, rTime = 0; + let aStartTime = 0, pStartTime = 0, rEndTime = 0; + let priorityId = 1; + let executeId = ''; + let executeStruct; + taskArray.forEach((item) => { + if (item.funName!.indexOf('H:Task Allocation:') >= 0) { + aStartTime = item.startTs!; + priorityId = TabPaneTaskFrames.getPriorityId(item.funName!); + executeId = TabPaneTaskFrames.getExecuteId(item.funName!); + } else if (item.funName!.indexOf('H:Task Perform:') >= 0) { + executeStruct = item; + pStartTime = item.startTs!; + eTime = item.dur!; + } else if (item.funName!.indexOf('H:Task PerformTask End:') >= 0) { + rEndTime = item.startTs! + item.dur!; + } + }); + sTime = pStartTime - aStartTime; + rTime = rEndTime - (pStartTime + eTime); + if (TabPaneTaskFrames.IsShowConcurrency) { + let tableList: TaskTabStruct[] = []; + let countConcurrencyPromise = this.countConcurrency(executeStruct, tableList, framesParam, isClick); + countConcurrencyPromise.then(result => { + let concurrencyColumn: TaskTabStruct = new TaskTabStruct(); + concurrencyColumn.executeId = 'Task Concurrency'; + concurrencyColumn.taskPriority = `${ result }`; + tableList.push(concurrencyColumn); + let filterList = []; + let map = new Map(); + for (const item of tableList) { + if (!map.has(item.executeId)) { + map.set(item.executeId, true); + filterList.push(item); + } + } + this.taskFramesSource = filterList; + this.taskFramesTbl!!.recycleDataSource = this.taskFramesSource; + }); + } else { + let task: TaskTabStruct = new TaskTabStruct(); + task.executeId = executeId; + task.taskPriority = Priority[priorityId]; + task.taskST = this.getMsTime(sTime); + task.taskET = this.getMsTime(eTime); + task.taskRT = this.getMsTime(rTime); + this.taskFramesSource = [task]; + this.taskFramesTbl!!.recycleDataSource = this.taskFramesSource; + } + } + } + + queryDataByDB(framesParam: SelectionParam, isClick: boolean): void { + let tableList: TaskTabStruct[] = []; + let executeTaskList: FuncStruct[] = []; + let executeTaskIds: number[] = []; + this.taskFramesTbl!.recycleDataSource = []; + for (let index = 0 ; index < framesParam.taskFramesData.length ; index++) { + let data = framesParam.taskFramesData[index]; + for (let y = 0 ; y < data.length ; y++) { + let executeId = TabPaneTaskFrames.getExecuteId(data[y].funName!); + if (data[y].funName!.indexOf('H:Task Perform:') >= 0) { + executeTaskList.push(data[y]); + } + executeTaskIds.push(parseInt(executeId)); + } + } + queryTaskListByExecuteTaskIds(executeTaskIds).then((taskList) => { + for (let index = 0 ; index < taskList.length ; index++) { + this.pushTaskToList(taskList[index], tableList); + } + this.handleConcurrency(executeTaskList, tableList, framesParam, isClick); + }); + } + + + initElements(): void { + this.taskFramesTbl = this.shadowRoot?.querySelector('#tb-frames'); + this.range = this.shadowRoot?.querySelector('#task-frames-time-range'); + this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar; + this.taskFramesTbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail); + }); + } + + getMsTime(ts: number): number { + return parseFloat((ts / 1000000.0).toFixed(6)); + } + + connectedCallback(): void { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.taskFramesTbl!); + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + `; + } + + sortByColumn(framesDetail: any) { + // @ts-ignore + let compare = function (property, sort, type) { + return function (taskFramesLeftData: TaskTabStruct, taskFramesRightData: TaskTabStruct) { + if (taskFramesLeftData.executeId === 'Task Concurrency') { + return 0; + } + if (type === 'number') { + // @ts-ignore + let forwardNum = parseFloat(taskFramesRightData[property]) - parseFloat(taskFramesLeftData[property]); + // @ts-ignore + let reserveNum = parseFloat(taskFramesLeftData[property]) - parseFloat(taskFramesRightData[property]); + return sort === 2 ? forwardNum : reserveNum; + } else { + // @ts-ignore + if (taskFramesRightData[property] > taskFramesLeftData[property]) { + return sort === 2 ? 1 : -1; + } else { + // @ts-ignore + if (taskFramesRightData[property] === taskFramesLeftData[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + }; + }; + if (framesDetail.key === 'taskPriority') { + this.taskFramesSource.sort(compare(framesDetail.key, framesDetail.sort, 'string')); + } else { + this.taskFramesSource.sort(compare(framesDetail.key, framesDetail.sort, 'number')); + } + this.taskFramesTbl!.recycleDataSource = this.taskFramesSource; + } + + static getExecuteId(funName: string): string { + let strArray = funName.split(','); + let executeStr = ''; + let executeId = ''; + let endStr = ''; + if (strArray.length >= 2) { + executeStr = strArray[1]; + if (funName.indexOf('H:Task Allocation:') >= 0 || funName.indexOf('H:Task Perform:') >= 0) { + executeId = executeStr.split(':')[1].trim(); + } else if (funName.indexOf('H:Task PerformTask End:') >= 0) { + endStr = executeStr.split(':')[1].trim(); + if (endStr.indexOf('[') >= 0) { + executeId = endStr.substring(0, endStr.indexOf('[')); + } else { + executeId = endStr; + } + } + } + return executeId; + } + + static getPriorityId(funName: string): number { + let strArray = funName.split(','); + let priorityId = ''; + if (strArray.length >= 2) { + let executeStr = strArray[2]; + if (funName.indexOf('H:Task Allocation:') >= 0) { + priorityId = executeStr.split(':')[1].trim(); + } + } + return parseInt(priorityId); + } + + private async countConcurrency(selectFuncStruct: FuncStruct | undefined, + tableList: TaskTabStruct[], framesParam: SelectionParam, isClick: boolean): Promise { + let selectStartTime = selectFuncStruct!.startTs! + (window as any).recordStartNS; + let selectEndTime = selectFuncStruct!.startTs! + selectFuncStruct!.dur! + (window as any).recordStartNS; + if (!isClick) { + let startTime = framesParam.recordStartNs + framesParam.leftNs; + let endTime = framesParam.recordStartNs + framesParam.rightNs; + if ((selectStartTime <= startTime && startTime <= selectEndTime) || + (selectStartTime <= endTime && endTime <= selectEndTime)) { + selectStartTime = startTime; + selectEndTime = endTime; + } + } + let maxConcurrency = 0; + await Promise.all([queryTaskPoolTotalNum(selectFuncStruct!.funName!), + queryConcurrencyTask(selectFuncStruct!.funName!, selectStartTime, selectEndTime)]).then( + (res) => { + let currentConcurrency = 0; + let tasks:Array = res[1] + for (let i = 0; i < tasks.length; i++) { + const task = tasks[i]; + // @ts-ignore + const endTime = task!.startTs + task!.dur; + currentConcurrency++; + for (let j = i + 1; j < tasks.length; j++) { + const nextTask = tasks[j]; + // @ts-ignore + if (nextTask.startTs < endTime) { + currentConcurrency++; + } + } + // 更新最大并发度 + if (currentConcurrency > maxConcurrency) { + maxConcurrency = currentConcurrency; + if (maxConcurrency === res[0].length) { + break; + } + } + // 重置当前并发度 + currentConcurrency = 0; + } + for (const item of res[1]) { + this.pushTaskToList(item, tableList); + } + } + ); + return maxConcurrency; + } + + private handleConcurrency(executeTaskList: FuncStruct[], tableList: TaskTabStruct[], framesParam: SelectionParam, isClick: boolean): void { + let maxNumConcurrency = 0; + if (executeTaskList.length > 0) { + let handleConcurrency = async (): Promise => { + for (let i = 0 ; i < executeTaskList.length ; i++) { + let countConcurrencyPromise = await this.countConcurrency(executeTaskList[i], tableList, framesParam, isClick); + if (countConcurrencyPromise > maxNumConcurrency) { + maxNumConcurrency = countConcurrencyPromise; + } + } + }; + handleConcurrency().then(() => { + let concurrencyColumn: TaskTabStruct = new TaskTabStruct(); + concurrencyColumn.executeId = 'Task Concurrency'; + concurrencyColumn.taskPriority = `${ maxNumConcurrency }`; + tableList.push(concurrencyColumn); + //去重 + let filterList = []; + let map = new Map(); + for (const item of tableList) { + if (!map.has(item.executeId)) { + map.set(item.executeId, true); + filterList.push(item); + } + } + this.taskFramesSource = filterList; + this.taskFramesTbl!.recycleDataSource = filterList; + this.progressEL!.loading = false; + }); + } else { + this.taskFramesSource = tableList; + this.taskFramesTbl!.recycleDataSource = tableList; + this.progressEL!.loading = false; + } + } + + private pushTaskToList(value: TaskTabStruct, tableList: TaskTabStruct[]): void { + let allocationTask = SpSystemTrace.DATA_TASK_POOL_CALLSTACK.get(value.allocationTaskRow!); + let executeTask = SpSystemTrace.DATA_TASK_POOL_CALLSTACK.get(value.executeTaskRow!); + let returnTask = SpSystemTrace.DATA_TASK_POOL_CALLSTACK.get(value.returnTaskRow!); + let tempTask: TaskTabStruct = new TaskTabStruct(); + let executeStartTime = executeTask!.ts!; + let executeTime = executeTask!.dur!; + let aStartTime = allocationTask!.ts!; + let rEndTime = returnTask!.ts! + returnTask!.dur!; + tempTask.executeId = value.executeId; + tempTask.taskPriority = Priority[value.priority!]; + tempTask.taskST = this.getMsTime(executeStartTime - aStartTime); + tempTask.taskET = this.getMsTime(executeTime); + tempTask.taskRT = this.getMsTime(rEndTime - (executeStartTime + executeTime)); + tableList.push(tempTask); + } +} + +enum Priority { + HIGH, + MEDIUM, + LOW +} + +export class TaskTabStruct extends BaseStruct { + static maxValue: number = 0; + static maxName: string = ''; + static index = 0; + id: number | undefined; + tid: number | undefined; + ipid: number | undefined; + executeId: string | undefined; + startTs: number | undefined; + funName: string | undefined; + dur: number | undefined; + taskST: number | undefined; + taskET: number | undefined; + taskRT: number | undefined; + allocationTaskRow: number | undefined; + executeTaskRow: number | undefined; + returnTaskRow: number | undefined; + priority: number | undefined; + taskPriority: string | undefined; + isUse: boolean = false; + isTimeOut: boolean | undefined; +} diff --git a/ide/src/trace/database/SqlLite.ts b/ide/src/trace/database/SqlLite.ts index 41774cb2d..f054f3ec3 100644 --- a/ide/src/trace/database/SqlLite.ts +++ b/ide/src/trace/database/SqlLite.ts @@ -79,6 +79,7 @@ import { FileInfo } from '../../js-heap/model/UiStruct.js'; import { AppStartupStruct } from './ui-worker/ProcedureWorkerAppStartup.js'; import { SoStruct } from './ui-worker/ProcedureWorkerSoInit.js'; import { HeapTreeDataBean } from './logic-worker/ProcedureLogicWorkerCommon.js'; +import { TaskTabStruct } from '../component/trace/sheet/task/TabPaneTaskFrames.js'; class DataWorkerThread extends Worker { taskMap: any = {}; @@ -531,7 +532,8 @@ export const getFunDataByTid = (tid: number, ipid: number): Promise> => +export const queryThreadByItid = (itid: number, ts: number): Promise> => query( 'queryThreadByItid', `select tid,pid,c.dur,c.depth,c.name @@ -4217,3 +4219,121 @@ export const queryHiPerfProcessCount = ( { $leftNs: leftNs, $rightNs: rightNs } ); }; + +export const queryConcurrencyTask = (funName: string, selectStartTime: number, selectEndTime: number) => + query( + 'queryConcurrencyTask', + `SELECT thread.tid, + thread.ipid, + callstack.name AS funName, + callstack.ts AS startTs, + callstack.dur, + callstack.id, + task_pool.priority, + task_pool.allocation_task_row AS allocationTaskRow, + task_pool.execute_task_row AS executeTaskRow, + task_pool.return_task_row AS returnTaskRow, + task_pool.execute_id AS executeId + FROM thread + LEFT JOIN callstack ON thread.id = callstack.callid + LEFT JOIN task_pool ON callstack.id = task_pool.execute_task_row + WHERE ipid = (SELECT thread.ipid + FROM thread + LEFT JOIN callstack ON thread.id = callstack.callid + WHERE callstack.name = $funName) + AND thread.name = 'TaskWorkThread' + AND -- 左包含 + ($selectStartTime <= callstack.ts AND $selectEndTime > callstack.ts AND callstack.name LIKE 'H:Task Perform:%') + OR -- 右包含 + ($selectStartTime < callstack.ts + callstack.dur AND $selectEndTime >= callstack.ts + callstack.dur AND callstack.name LIKE 'H:Task Perform:%') + OR -- 包含 + ($selectStartTime >= callstack.ts AND $selectEndTime <= callstack.ts + callstack.dur AND callstack.name LIKE 'H:Task Perform:%') + OR -- 被包含 + ($selectStartTime <= callstack.ts AND $selectEndTime >= callstack.ts + callstack.dur AND callstack.name LIKE 'H:Task Perform:%') + ORDER BY callstack.ts;`, + { $funName: funName, $selectStartTime: selectStartTime, $selectEndTime: selectEndTime} + ); + +export const queryBySelectExecute = ( + executeId: string +): Promise< + Array<{ + tid: number; + allocation_task_row: number; + execute_task_row: number; + return_task_row: number; + priority: number; + }> +> => { + let sqlStr = `SELECT thread.tid, + task_pool.allocation_task_row, + task_pool.execute_task_row, + task_pool.return_task_row, + task_pool.priority + FROM task_pool + LEFT JOIN callstack ON callstack.id = task_pool.allocation_task_row + LEFT JOIN thread ON thread.id = callstack.callid + WHERE task_pool.execute_id = $executeId; + `; + return query('queryBySelectExecute', sqlStr, { $executeId: executeId }); +}; + +export const queryBySelectAllocationOrReturn = ( + executeId: string +): Promise< + Array<{ + tid: number; + allocation_task_row: number; + execute_task_row: number; + return_task_row: number; + priority: number; + }> +> => { + let sqlStr = `SELECT thread.tid, + task_pool.allocation_task_row, + task_pool.execute_task_row, + task_pool.return_task_row, + task_pool.priority + FROM task_pool + LEFT JOIN callstack ON callstack.id = task_pool.execute_task_row + LEFT JOIN thread ON thread.id = callstack.callid + WHERE task_pool.execute_task_row IS NOT NULL AND task_pool.execute_id = $executeId; + `; + return query('queryBySelectAllocationOrReturn', sqlStr, { $executeId: executeId }); +}; + +export const queryTaskListByExecuteTaskIds = (executeTaskIds: Array): Promise> => { + let sqlStr = ` + SELECT + task_pool.allocation_task_row as allocationTaskRow, + task_pool.execute_task_row as executeTaskRow, + task_pool.return_task_row as returnTaskRow, + task_pool.execute_id as executeId, + task_pool.priority + FROM task_pool + LEFT JOIN callstack ON callstack.id = task_pool.allocation_task_row + WHERE task_pool.execute_id IN (${executeTaskIds.join(',')}) AND task_pool.execute_task_row IS NOT NULL; + `; + return query('queryTaskListByExecuteTaskIds', sqlStr, { $executeTaskIds: executeTaskIds }); +}; + +export const queryTaskPoolCallStack = (): Promise> => { + let sqlStr = `select * from callstack where name like 'H:Task%';`; + return query('queryTaskPoolCallStack', sqlStr, {}); +}; + + +export const queryTaskPoolTotalNum = (funName: string) => + query( + 'queryTaskPoolTotalNum', + `SELECT thread.tid + FROM thread + LEFT JOIN callstack ON thread.id = callstack.callid + WHERE ipid = (SELECT thread.ipid + FROM thread + LEFT JOIN callstack ON thread.id = callstack.callid + WHERE callstack.name = $funName) + AND thread.name = 'TaskWorkThread' + GROUP BY thread.tid;`, + { $funName: funName} + ); diff --git a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerFileSystem.ts b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerFileSystem.ts index b53e61d3c..1d3a88cca 100644 --- a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerFileSystem.ts +++ b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerFileSystem.ts @@ -777,6 +777,8 @@ where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${sql} currentNode.symbol = dataCache.dataDict?.get(currentNode.symbolsId) || currentNode.ip || 'unknown'; currentNode.path = dataCache.dataDict?.get(currentNode.pathId) || 'unknown'; currentNode.libName = setFileName(currentNode.path); + currentNode.lib = currentNode.libName; + currentNode.addr = currentNode.ip; currentNode.symbolName = `${currentNode.symbol} (${currentNode.libName})`; } } diff --git a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts index eeb8534f6..0984f5e63 100644 --- a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts +++ b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts @@ -892,6 +892,8 @@ export class PerfCallChainMerageData extends ChartStruct { currentNode.tid = callChain.tid; currentNode.libName = callChain.fileName; currentNode.vaddrInFile = callChain.vaddrInFile; + currentNode.addr = `${'0x'}${callChain.vaddrInFile.toString(16)}`; + currentNode.lib = currentNode.libName; currentNode.canCharge = callChain.canCharge; if (callChain.path) { currentNode.path = callChain.path; @@ -918,6 +920,8 @@ export class PerfCallChainMerageData extends ChartStruct { currentNode.tid = sample.tid; currentNode.libName = callChain.fileName; currentNode.vaddrInFile = callChain.vaddrInFile; + currentNode.lib = callChain.fileName; + currentNode.addr = `${'0x'}${callChain.vaddrInFile.toString(16)}`; currentNode.canCharge = callChain.canCharge; if (callChain.path) { currentNode.path = callChain.path; diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts index 38fbfb86c..e815fd529 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts @@ -366,6 +366,11 @@ export class Point { } } +export enum LineType { + brokenLine, + bezierCurve, +} + export class PairPoint { x: number = 0; ns: number = 0; @@ -373,14 +378,25 @@ export class PairPoint { offsetY: number = 0; rowEL: TraceRow; isRight: boolean = true; - - constructor(rowEL: TraceRow, x: number, y: number, ns: number, offsetY: number, isRight: boolean) { + lineType?: LineType; + business: string = ''; + hidden?: boolean = false; + constructor( + rowEL: TraceRow, + x: number, + y: number, + ns: number, + offsetY: number, + isRight: boolean, + business: string + ) { this.rowEL = rowEL; this.x = x; this.y = y; this.ns = ns; this.offsetY = offsetY; this.isRight = isRight; + this.business = business; } } @@ -639,81 +655,174 @@ export function drawLinkLines( let maxWidth = tm.getBoundingClientRect().width - 268; for (let i = 0; i < nodes.length; i++) { let it = nodes[i]; + if (it[0].hidden) { + continue; + } if (isFavorite) { if (!it[0].rowEL.collect && !it[1].rowEL.collect) { continue; } } - let start = it[0].x > it[1].x ? it[1] : it[0]; - let end = it[0].x > it[1].x ? it[0] : it[1]; - if (start && end) { - //左移到边界,不画线 - if (start.x <= 0) { - start.x = -100; - } - if (end.x <= 0) { - end.x = -100; - } - //右移到边界,不画线 - if (start.x >= maxWidth) { - start.x = maxWidth + 100; - } - if (end.x >= maxWidth) { - end.x = maxWidth + 100; - } - context.beginPath(); - context.lineWidth = 2; - context.fillStyle = linkLineColor; - context.strokeStyle = linkLineColor; - let x0, y0, x1, x2, y1, y2, x3, y3; - x0 = start.x ?? 0; - y0 = start.y ?? 0; - x3 = end.x ?? 0; - y3 = end.y ?? 0; - if (end.isRight) { - x2 = x3 - 100 * percentage; - } else { - x2 = x3 + 100 * percentage; - } - y2 = y3 - 40 * percentage; - if (start.isRight) { - x1 = x0 - 100 * percentage; - } else { - x1 = x0 + 100 * percentage; - } - y1 = y0 + 40 * percentage; - //向右箭头终点在x轴正向有偏移 - if (!start.isRight) { - x0 -= 5; - } + switch (it[0].lineType) { + case LineType.brokenLine: + drawBrokenLine(it, maxWidth, context); + break; + case LineType.bezierCurve: + drawBezierCurve(it, maxWidth, context, percentage); + break; + default: + drawBezierCurve(it, maxWidth, context, percentage); + } + } +} + +function drawBezierCurve(it: PairPoint[], maxWidth: number, context: CanvasRenderingContext2D, percentage: number) { + let start = it[0].x > it[1].x ? it[1] : it[0]; + let end = it[0].x > it[1].x ? it[0] : it[1]; + if (start && end) { + //左移到边界,不画线 + if (start.x <= 0) { + start.x = -100; + } + if (end.x <= 0) { + end.x = -100; + } + //右移到边界,不画线 + if (start.x >= maxWidth) { + start.x = maxWidth + 100; + } + if (end.x >= maxWidth) { + end.x = maxWidth + 100; + } + context.beginPath(); + context.lineWidth = 2; + context.fillStyle = linkLineColor; + context.strokeStyle = linkLineColor; + let x0; + let y0; + let x1; + let x2; + let y1; + let y2; + let x3; + let y3; + x0 = start.x ?? 0; + y0 = start.y ?? 0; + x3 = end.x ?? 0; + y3 = end.y ?? 0; + if (end.isRight) { + x2 = x3 - 100 * percentage; + } else { + x2 = x3 + 100 * percentage; + } + y2 = y3 - 40 * percentage; + if (start.isRight) { + x1 = x0 - 100 * percentage; + } else { + x1 = x0 + 100 * percentage; + } + y1 = y0 + 40 * percentage; + //向右箭头终点在x轴正向有偏移 + if (!start.isRight) { + x0 -= 5; + } + context.moveTo(x0, y0); + //箭头向左还是向右 + if (start.isRight) { + context.lineTo(x0 - wid, y0 + wid); context.moveTo(x0, y0); - //箭头向左还是向右 - if (start.isRight) { - context.lineTo(x0 - wid, y0 + wid); - context.moveTo(x0, y0); - context.lineTo(x0 - wid, y0 - wid); - } else { - context.lineTo(x0 + wid, y0 + wid); - context.moveTo(x0, y0); - context.lineTo(x0 + wid, y0 - wid); - } + context.lineTo(x0 - wid, y0 - wid); + } else { + context.lineTo(x0 + wid, y0 + wid); context.moveTo(x0, y0); - context.bezierCurveTo(x1, y1, x2, y2, x3, y3); + context.lineTo(x0 + wid, y0 - wid); + } + context.moveTo(x0, y0); + context.bezierCurveTo(x1, y1, x2, y2, x3, y3); + context.moveTo(x3, y3); + //箭头向左还是向右 + if (end.isRight) { + context.lineTo(x3 - wid, y3 + wid); context.moveTo(x3, y3); - //箭头向左还是向右 - if (end.isRight) { - context.lineTo(x3 - wid, y3 + wid); - context.moveTo(x3, y3); - context.lineTo(x3 - wid, y3 - wid); - } else { - context.lineTo(x3 + wid, y3 + wid); - context.moveTo(x3, y3); - context.lineTo(x3 + wid, y3 - wid); - } + context.lineTo(x3 - wid, y3 - wid); + } else { + context.lineTo(x3 + wid, y3 + wid); context.moveTo(x3, y3); - context.stroke(); - context.closePath(); + context.lineTo(x3 + wid, y3 - wid); + } + context.moveTo(x3, y3); + context.stroke(); + context.closePath(); + } +} + +function drawBrokenLine(it: PairPoint[], maxWidth: number, context: CanvasRenderingContext2D) { + let start = it[0].x > it[1].x ? it[1] : it[0]; + let end = it[0].x > it[1].x ? it[0] : it[1]; + if (start && end) { + if (start.x <= 0) { + start.x = -100; + } + if (end.x <= 0) { + end.x = -100; + } + //右移到边界,不画线 + if (start.x >= maxWidth) { + start.x = maxWidth + 100; + } + if (end.x >= maxWidth) { + end.x = maxWidth + 100; + } + context.beginPath(); + context.lineWidth = 2; + context.fillStyle = '#46B1E3'; + context.strokeStyle = '#46B1E3'; + let x0; + let y0; + let x1; + let y1; + let x2; + let y2; + x0 = start.x ?? 0; + y0 = start.y ?? 0; + y2 = end.y ?? 0; + x2 = end.x ?? 0; + let leftEndpointX; + let leftEndpointY; + let rightEndpointX; + let rightEndpointY; + + if (start.y < end.y) { + x1 = start.x ?? 0; + y1 = end.y ?? 0; + leftEndpointX = x2 - wid; + leftEndpointY = y2 - wid; + rightEndpointX = x2 - wid; + rightEndpointY = y2 + wid; + } else { + x2 = end.x - wid ?? 0; + x1 = end.x - wid ?? 0; + y1 = start.y ?? 0; + leftEndpointX = x2 - wid; + leftEndpointY = y2 + wid; + rightEndpointX = x2 + wid; + rightEndpointY = y2 + wid; } + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + context.stroke(); + context.closePath(); + context.beginPath(); + context.lineWidth = 2; + context.fillStyle = '#46B1E3'; + context.strokeStyle = '#46B1E3'; + context.moveTo(x2, y2); + context.lineTo(leftEndpointX, leftEndpointY); + context.lineTo(rightEndpointX, rightEndpointY); + context.lineTo(x2, y2); + context.fill(); + context.closePath(); } } diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerFunc.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerFunc.ts index a3c0bd126..6e960ff53 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerFunc.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerFunc.ts @@ -170,10 +170,27 @@ export class FuncStruct extends BaseFuncStruct { ctx.lineWidth = 2; ctx.strokeRect(data.frame.x, data.frame.y + 1, data.frame.width, miniHeight - padding * 2 - 2); } + if (data.funName!.indexOf('H:Task PerformTask End:') >= 0 && data.funName!.indexOf('Successful') < 0) { + if (data.frame!.width < 10) { + FuncStruct.drawRoundRectPath(ctx, data.frame!.x, 30, 3, data!); + } else { + FuncStruct.drawRoundRectPath(ctx, data.frame!.x, 28, 6, data!); + } + } } } } + static drawRoundRectPath(ctx: CanvasRenderingContext2D, x: number, y: number, radius: number, data: FuncStruct) { + ctx.beginPath(); + ctx.arc(x + data.frame!.width, y, radius, 0, Math.PI * 2); + ctx.closePath(); + // 填充背景颜色 + ctx.fillStyle = '#E64566'; + ctx.fill(); + ctx.stroke(); + } + static isSelected(data: FuncStruct): boolean { return ( FuncStruct.selectFuncStruct != undefined && -- Gitee From c33333af3445a9cb7022578ca6c18e4ef45f1a85 Mon Sep 17 00:00:00 2001 From: jichuan Date: Thu, 27 Jul 2023 14:59:42 +0800 Subject: [PATCH 05/14] support parse animation data Signed-off-by: jichuan --- trace_streamer/src/filter/BUILD.gn | 3 + .../src/filter/animation_filter.cpp | 186 +++++++++++++ trace_streamer/src/filter/animation_filter.h | 52 ++++ .../src/filter/app_start_filter.cpp | 82 ++++-- trace_streamer/src/filter/app_start_filter.h | 12 +- .../src/filter/task_pool_filter.cpp | 9 +- trace_streamer/src/filter/task_pool_filter.h | 2 +- .../src/parser/print_event_parser.cpp | 45 ++- .../src/parser/print_event_parser.h | 7 +- trace_streamer/src/table/base/BUILD.gn | 2 + trace_streamer/src/table/base/device_info.cpp | 68 +++++ trace_streamer/src/table/base/device_info.h | 52 ++++ trace_streamer/src/table/ftrace/BUILD.gn | 4 + .../src/table/ftrace/animation_table.cpp | 235 ++++++++++++++++ .../src/table/ftrace/animation_table.h | 52 ++++ .../src/table/ftrace/dynamic_frame_table.cpp | 260 +++++++++++++++++ .../src/table/ftrace/dynamic_frame_table.h | 52 ++++ .../src/trace_data/trace_data_cache.cpp | 21 +- .../src/trace_data/trace_data_cache.h | 6 +- .../src/trace_data/trace_data_cache_base.h | 3 + .../trace_data/trace_data_cache_reader.cpp | 12 + .../src/trace_data/trace_data_cache_reader.h | 3 + .../trace_data/trace_data_cache_writer.cpp | 15 + .../src/trace_data/trace_data_cache_writer.h | 3 + .../src/trace_data/trace_stdtype.cpp | 161 ++++++++++- trace_streamer/src/trace_data/trace_stdtype.h | 63 +++++ .../trace_streamer/trace_streamer_filters.cpp | 1 + .../trace_streamer/trace_streamer_filters.h | 2 + .../trace_streamer_selector.cpp | 9 + .../trace_streamer/trace_streamer_selector.h | 1 + trace_streamer/src/version.cpp | 4 +- trace_streamer/test.sh | 2 +- trace_streamer/test/BUILD.gn | 3 + .../test/unittest/animation_filter_test.cpp | 262 ++++++++++++++++++ .../test/unittest/app_start_filter_test.cpp | 184 ++++++++++++ .../test/unittest/task_pool_filter_test.cpp | 244 ++++++++++++++++ 36 files changed, 2072 insertions(+), 50 deletions(-) create mode 100644 trace_streamer/src/filter/animation_filter.cpp create mode 100644 trace_streamer/src/filter/animation_filter.h create mode 100644 trace_streamer/src/table/base/device_info.cpp create mode 100644 trace_streamer/src/table/base/device_info.h create mode 100644 trace_streamer/src/table/ftrace/animation_table.cpp create mode 100644 trace_streamer/src/table/ftrace/animation_table.h create mode 100644 trace_streamer/src/table/ftrace/dynamic_frame_table.cpp create mode 100644 trace_streamer/src/table/ftrace/dynamic_frame_table.h create mode 100644 trace_streamer/test/unittest/animation_filter_test.cpp create mode 100755 trace_streamer/test/unittest/app_start_filter_test.cpp create mode 100644 trace_streamer/test/unittest/task_pool_filter_test.cpp diff --git a/trace_streamer/src/filter/BUILD.gn b/trace_streamer/src/filter/BUILD.gn index 323250f2b..5073653b1 100644 --- a/trace_streamer/src/filter/BUILD.gn +++ b/trace_streamer/src/filter/BUILD.gn @@ -18,6 +18,8 @@ ohos_source_set("filter") { subsystem_name = "developtools" part_name = "smartperf_host" sources = [ + "animation_filter.cpp", + "animation_filter.h", "app_start_filter.cpp", "app_start_filter.h", "args_filter.cpp", @@ -76,6 +78,7 @@ ohos_source_set("filter") { "${SRC}/base", "${SRC}/trace_streamer", "${SRC}/trace_data", + "${SRC}/parser", "${SRC}/include", "${SRC}/filter", "${SRC}/cfg", diff --git a/trace_streamer/src/filter/animation_filter.cpp b/trace_streamer/src/filter/animation_filter.cpp new file mode 100644 index 000000000..6b0c042d0 --- /dev/null +++ b/trace_streamer/src/filter/animation_filter.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "animation_filter.h" +#include +#include +#include "string_help.h" +#include "string_to_numerical.h" + +namespace SysTuning { +namespace TraceStreamer { +constexpr uint8_t GENERATE_VSYNC_EVENT_MAX = 6; +constexpr uint8_t DYNAMIC_STACK_DEPTH_MIN = 4; +constexpr uint16_t FPS_60 = 60; +constexpr uint16_t FPS_70 = 70; +constexpr uint16_t FPS_90 = 90; +constexpr uint16_t FPS_100 = 100; +constexpr uint16_t FPS_120 = 120; + +AnimationFilter::AnimationFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : FilterBase(dataCache, filter) +{ +} + +AnimationFilter::~AnimationFilter() {} + +bool AnimationFilter::UpdateDeviceInfoEvent(const TracePoint& point, const BytraceLine& line) +{ + if (traceDataCache_->GetConstDeviceInfo().PhysicalFrameRate() == INVALID_UINT32 && + StartWith(point.name_, generateVsyncCmd_)) { + if (generateCurTimePoint_ == 0) { + generateCurTimePoint_ = line.ts; + } + generateVsyncCnt_++; + // calculate the average frame rate + if (generateVsyncCnt_ == GENERATE_VSYNC_EVENT_MAX) { + uint64_t generateTimePeriod = (line.ts - generateCurTimePoint_) / (GENERATE_VSYNC_EVENT_MAX - 1); + uint32_t fps = BILLION_NANOSECONDS / generateTimePeriod; + if (fps < FPS_70) { + traceDataCache_->GetDeviceInfo()->UpdateFrameRate(FPS_60); + } else if (fps < FPS_100) { + traceDataCache_->GetDeviceInfo()->UpdateFrameRate(FPS_90); + } else { + traceDataCache_->GetDeviceInfo()->UpdateFrameRate(FPS_120); + } + TS_LOGI("physical frame rate is %u", fps); + } + return true; + } else if (traceDataCache_->GetConstDeviceInfo().PhysicalWidth() == INVALID_UINT32 && + point.funcPrefixId_ == entryViewCmd_) { + // get width and height, eg:funcArgs=(0, 0, 1344, 2772) Alpha: 1.00 + std::smatch matcheLine; + std::regex entryViewArgsPattern(R"(\(\d+,\s*\d+,\s*(\d+),\s*(\d+)\))"); + if (std::regex_search(point.funcArgs_, matcheLine, entryViewArgsPattern)) { + uint8_t index = 0; + uint32_t width = base::StrToInt(matcheLine[++index].str()).value(); + uint32_t height = base::StrToInt(matcheLine[++index].str()).value(); + traceDataCache_->GetDeviceInfo()->UpdateWidthAndHeight(width, height); + TS_LOGI("physical width is %u, height is %u", width, height); + } else { + TS_LOGE("Not support this event: %s\n", point.name_.data()); + return false; + } + return true; + } + return false; +} +bool AnimationFilter::BeginDynamicFrameEvent(const TracePoint& point, size_t callStackRow) +{ + // matches the 'H:RSUniRender::Process:[' event + if (StartWith(point.funcPrefix_, rsUniProcessCmd_)) { + // get the parent frame of data + CallStack* callStackSlice = traceDataCache_->GetInternalSlicesData(); + const std::optional& parentId = callStackSlice->ParentIdData()[callStackRow]; + uint8_t depth = callStackSlice->Depths()[callStackRow]; + if (depth >= DYNAMIC_STACK_DEPTH_MIN && parentId.has_value()) { + const std::string& curStackName = + traceDataCache_->GetDataFromDict(callStackSlice->NamesData()[callStackRow]); + const std::string& parentStackName = + traceDataCache_->GetDataFromDict(callStackSlice->NamesData()[parentId.value()]); + // get name 'xxx' from [xxx], eg:H:RSUniRender::Process:[xxx] + auto nameSize = point.funcPrefix_.size() - rsUniProcessCmd_.size() - 1; + if (nameSize <= 0) { + return false; + } + auto nameIndex = traceDataCache_->GetDataIndex(point.funcPrefix_.substr(rsUniProcessCmd_.size(), nameSize)); + if (StartWith(curStackName, leashWindowCmd_)) { + auto dynamicFramRow = traceDataCache_->GetDynamicFrame()->AppendDynamicFrame(nameIndex); + callStackRowMap_.emplace(callStackRow, dynamicFramRow); + return true; + } else if (StartWith(parentStackName, leashWindowCmd_)) { + auto iter = callStackRowMap_.find(parentId.value()); + if (iter != callStackRowMap_.end()) { + auto dynamicFramRow = iter->second; + traceDataCache_->GetDynamicFrame()->UpdateNameIndex(dynamicFramRow, nameIndex); + return true; + } else { + TS_LOGE("Can't find the dynamicFramRow from callStackRowMap_"); + } + } + } + } + return false; +} +void AnimationFilter::StartAnimationEvent(const BytraceLine& line, size_t callStackRow) +{ + auto animationRow = traceDataCache_->GetAnimation()->AppendAnimation(line.ts); + animationCallIds_.emplace(callStackRow, animationRow); +} +bool AnimationFilter::FinishAnimationEvent(const BytraceLine& line, size_t callStackRow) +{ + auto iter = animationCallIds_.find(callStackRow); + if (iter != animationCallIds_.end()) { + auto animationRow = iter->second; + traceDataCache_->GetAnimation()->UpdateEndPoint(animationRow, line.ts); + animationCallIds_.erase(iter); + return true; + } + return false; +} +void AnimationFilter::UpdateDynamicFrameInfo() +{ + std::smatch matcheLine; + std::regex leashWindowPattern(R"((\d+),\s*(\d+),\s*(\d+),\s*(\d+)\)\s+Alpha:\s+-*(\d+\.\d+))"); + DynamicFrame* dynamicFrame = traceDataCache_->GetDynamicFrame(); + CallStack* callStackSlice = traceDataCache_->GetInternalSlicesData(); + uint64_t curStackRow = INVALID_UINT64; + uint64_t curFrameRow = INVALID_UINT64; + for (const auto& it : callStackRowMap_) { + curStackRow = it.first; + curFrameRow = it.second; + uint8_t stackDepth = callStackSlice->Depths()[curStackRow]; + // update dynamicFrame pos, eg:H:RSUniRender::Process:[leashWindow25] (0, 0, 1344, 2772) Alpha: 1.00 + auto nameDataIndex = callStackSlice->NamesData()[curStackRow]; + const std::string& curStackName = traceDataCache_->GetDataFromDict(nameDataIndex); + const std::string& funcArgs = curStackName.substr(leashWindowCmd_.size()); + if (std::regex_search(funcArgs, matcheLine, leashWindowPattern)) { + uint8_t index = 0; + dynamicFrame->UpdatePosition(curFrameRow, base::StrToInt(matcheLine[++index].str()).value(), // x + base::StrToInt(matcheLine[++index].str()).value(), // y + base::StrToInt(matcheLine[++index].str()).value(), // width + base::StrToInt(matcheLine[++index].str()).value(), // height + traceDataCache_->GetDataIndex((matcheLine[++index].str()))); // alpha + } else { + TS_LOGE("Not support this event: %s\n", funcArgs.data()); + break; + } + // update dynamicFrame endTime, filter up from the curStackRow, until reach the top + for (uint8_t stackCurDepth = stackDepth; stackCurDepth > 0; stackCurDepth--) { + if (callStackSlice->ParentIdData()[curStackRow].has_value()) { + curStackRow = callStackSlice->ParentIdData()[curStackRow].value(); + } else { + break; + } + // use 'H:RSMainThread::DoComposition' endTime as dynamicFrame endTime + if (rsDoCompCmd_ == callStackSlice->NamesData()[curStackRow]) { + auto endTime = callStackSlice->TimeStampData()[curStackRow] + callStackSlice->DursData()[curStackRow]; + dynamicFrame->UpdateEndTime(curFrameRow, endTime); + break; + } + } + } + TS_LOGI("UpdateDynamicFrame (%zu) endTime and pos finish", callStackRowMap_.size()); + // this can only be cleared by the UpdateDynamicFrameInfo function + callStackRowMap_.clear(); +} +void AnimationFilter::Clear() +{ + generateCurTimePoint_ = 0; + generateVsyncCnt_ = 0; + animationCallIds_.clear(); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/src/filter/animation_filter.h b/trace_streamer/src/filter/animation_filter.h new file mode 100644 index 000000000..7a0a8d83c --- /dev/null +++ b/trace_streamer/src/filter/animation_filter.h @@ -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. + */ + +#ifndef ANIMATION_FILTER_H +#define ANIMATION_FILTER_H + +#include +#include "common_types.h" +#include "filter_base.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +class AnimationFilter : private FilterBase { +public: + AnimationFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + ~AnimationFilter() override; + bool UpdateDeviceInfoEvent(const TracePoint& point, const BytraceLine& line); + bool BeginDynamicFrameEvent(const TracePoint& point, size_t callStackRow); + void StartAnimationEvent(const BytraceLine& line, size_t callStackRow); + bool FinishAnimationEvent(const BytraceLine& line, size_t callStackRow); + void UpdateDynamicFrameInfo(); + void Clear(); + +private: + const std::string generateVsyncCmd_ = "H:GenerateVsyncCount"; + const std::string leashWindowCmd_ = "H:RSUniRender::Process:[leashWindow"; + const std::string rsUniProcessCmd_ = "H:RSUniRender::Process:["; + const DataIndex rsDoCompCmd_ = traceDataCache_->GetDataIndex("H:RSMainThread::DoComposition"); + const DataIndex entryViewCmd_ = traceDataCache_->GetDataIndex("H:RSUniRender::Process:[EntryView]"); + // for update dynamicFrameInfo at the end, first is callStackRow, second is dynamicFramRow + std::map callStackRowMap_ = {}; + // for update animationInfo, first is callStackRow, second is animationRow + std::unordered_map animationCallIds_ = {}; + uint64_t generateCurTimePoint_ = 0; + uint8_t generateVsyncCnt_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // ANIMATION_FILTER_H diff --git a/trace_streamer/src/filter/app_start_filter.cpp b/trace_streamer/src/filter/app_start_filter.cpp index b8940d746..e86f79313 100644 --- a/trace_streamer/src/filter/app_start_filter.cpp +++ b/trace_streamer/src/filter/app_start_filter.cpp @@ -35,6 +35,9 @@ bool APPStartupFilter::GetProcessCreate(uint32_t row, uint64_t& startTime, std:: { auto sliceData = traceDataCache_->GetConstInternalSlicesData(); auto parentId = sliceData.ParentIdData()[row].value(); + if (parentId == INVALID_UINT32) { + return false; + } auto depth = sliceData.Depths()[row]; auto name = traceDataCache_->GetDataFromDict(sliceData.NamesData()[parentId]); while (depth--) { @@ -48,12 +51,12 @@ bool APPStartupFilter::GetProcessCreate(uint32_t row, uint64_t& startTime, std:: return false; } -bool APPStartupFilter::CaclRsDataByPid() +bool APPStartupFilter::CaclRsDataByPid(appMap& mAPPStartupData) { auto frameSliceData = traceDataCache_->GetFrameSliceData(); auto sliceData = traceDataCache_->GetConstInternalSlicesData(); - auto itor = mAPPStartupData_.begin(); - for (const auto& item : mAPPStartupData_) { + auto itor = mAPPStartupData.begin(); + for (const auto& item : mAPPStartupData) { if (item.second.empty()) { continue; } @@ -66,7 +69,10 @@ bool APPStartupFilter::CaclRsDataByPid() auto startTime = sliceData.TimeStampData()[frameSliceData->CallStackIds()[m]]; auto callId = sliceData.CallIds()[frameSliceData->CallStackIds()[m]]; auto endTime = startTime + frameSliceData->Durs()[m]; - mAPPStartupData_[dataIndex].emplace( + if (frameSliceData->Durs()[m] == INVALID_UINT64) { + endTime = INVALID_UINT64; + } + mAPPStartupData[dataIndex].emplace( FIRST_FRAME_APP_PHASE, std::move(std::make_unique(callId, itorSecond->second->ipid_, itorSecond->second->tid_, startTime, endTime))); @@ -77,7 +83,7 @@ bool APPStartupFilter::CaclRsDataByPid() callId = sliceData.CallIds()[frameSliceData->CallStackIds()[dstId]]; startTime = frameSliceData->TimeStampData()[dstId]; endTime = startTime + frameSliceData->Durs()[dstId]; - mAPPStartupData_[dataIndex].emplace( + mAPPStartupData[dataIndex].emplace( FIRST_FRAME_RENDER_PHASE, std::move(std::make_unique(callId, itorSecond->second->ipid_, itorSecond->second->tid_, startTime, endTime))); @@ -89,15 +95,15 @@ bool APPStartupFilter::CaclRsDataByPid() return false; } -void APPStartupFilter::UpdatePidByNameIndex() +void APPStartupFilter::UpdatePidByNameIndex(const appMap& mAPPStartupData) { auto threadData = traceDataCache_->GetConstThreadData(); - for (const auto& item : mAPPStartupData_) { + for (const auto& item : mAPPStartupData) { auto ipid = INVALID_UINT32; auto tid = INVALID_UINT32; - if (item.second.count(UI_ABILITY_ONFOREGROUND)) { - ipid = item.second.at(UI_ABILITY_ONFOREGROUND)->ipid_; - tid = item.second.at(UI_ABILITY_ONFOREGROUND)->tid_; + if (item.second.count(UI_ABILITY_LAUNCHING)) { + ipid = item.second.at(UI_ABILITY_LAUNCHING)->ipid_; + tid = item.second.at(UI_ABILITY_LAUNCHING)->tid_; } else { for (int i = 0; i < threadData.size(); ++i) { if (item.first == threadData[i].nameIndex_) { @@ -113,9 +119,12 @@ void APPStartupFilter::UpdatePidByNameIndex() } } -void APPStartupFilter::AppendData() +void APPStartupFilter::AppendData(const appMap& mAPPStartupData) { - for (auto itor = mAPPStartupData_.begin(); itor != mAPPStartupData_.end(); ++itor) { + for (auto itor = mAPPStartupData.begin(); itor != mAPPStartupData.end(); ++itor) { + if (!(itor->second).count(UI_ABILITY_LAUNCHING)) { + continue; + } for (auto itorSecond = itor->second.begin(); itorSecond != itor->second.end(); ++itorSecond) { auto item = itorSecond; auto endTime = INVALID_UINT64; @@ -134,14 +143,12 @@ void APPStartupFilter::AppendData() } } -DataIndex APPStartupFilter::GetThreadNameAndUpdateAPPStartupData(uint32_t row, - const std::string& nameString, - uint32_t startIndex) +void APPStartupFilter::UpdateAPPStartupData(uint32_t row, const std::string& nameString, uint32_t startIndex) { auto sliceData = traceDataCache_->GetConstInternalSlicesData(); auto vNameString = SplitStringToVec(nameString, "##"); if (vNameString.size() < MIN_VECTOR_SIZE_) { - return INVALID_DATAINDEX; + return; } auto dataIndex = traceDataCache_->GetDataIndex(vNameString[1].c_str()); auto callId = sliceData.CallIds()[row]; @@ -149,7 +156,6 @@ DataIndex APPStartupFilter::GetThreadNameAndUpdateAPPStartupData(uint32_t row, mAPPStartupData_[dataIndex].insert( std::make_pair(startIndex, std::move(std::make_unique(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64)))); - return dataIndex; } void APPStartupFilter::ParserAppStartup() @@ -174,17 +180,30 @@ void APPStartupFilter::ParserAppStartup() continue; } callId = sliceData.CallIds()[i]; - mAPPStartupData_[traceDataCache_->GetDataIndex(mainThreadName.c_str())].insert(std::make_pair( + auto dataIndex = traceDataCache_->GetDataIndex(mainThreadName.c_str()); + mAPPStartupData_[dataIndex].insert(std::make_pair( PROCESS_CREATING, std::move(std::make_unique(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64)))); } else if (StartWith(nameString, APP_LAUNCH)) { - GetThreadNameAndUpdateAPPStartupData(i, nameString, APPLICATION_LAUNCHING); + UpdateAPPStartupData(i, nameString, APPLICATION_LAUNCHING); } else if (StartWith(nameString, LAUNCH)) { - auto nameIndex = GetThreadNameAndUpdateAPPStartupData(i, nameString, UI_ABILITY_LAUNCHING); - if (nameIndex != INVALID_DATAINDEX) { - auto thread = traceDataCache_->GetThreadData(sliceData.CallIds()[i]); - thread->nameIndex_ = nameIndex; + auto sliceData = traceDataCache_->GetConstInternalSlicesData(); + auto vNameString = SplitStringToVec(nameString, "##"); + if (vNameString.size() < MIN_VECTOR_SIZE_) { + continue; } + auto dataIndex = traceDataCache_->GetDataIndex(vNameString[1].c_str()); + callId = sliceData.CallIds()[i]; + startTime = sliceData.TimeStampData()[i]; + if (dataIndex == INVALID_DATAINDEX) { + continue; + } + auto thread = traceDataCache_->GetThreadData(sliceData.CallIds()[i]); + thread->nameIndex_ = dataIndex; + mAPPStartupData_[dataIndex].insert(std::make_pair( + UI_ABILITY_LAUNCHING, std::move(std::make_unique( + callId, thread->internalPid_, thread->tid_, startTime, INVALID_UINT64)))); + mAPPStartupDataWithPid_.insert(std::make_pair(thread->internalPid_, std::move(mAPPStartupData_))); } else if (StartWith(nameString, ONFOREGROUND)) { // callid is thread table->itid callId = sliceData.CallIds()[i]; @@ -193,14 +212,19 @@ void APPStartupFilter::ParserAppStartup() auto nameindex = threadData[callId].nameIndex_; auto ipid = threadData[callId].internalPid_; auto tid = threadData[callId].tid_; - mAPPStartupData_[nameindex].insert(std::make_pair( - UI_ABILITY_ONFOREGROUND, - std::move(std::make_unique(callId, ipid, tid, startTime, INVALID_UINT64)))); + if (mAPPStartupDataWithPid_.count(ipid) && mAPPStartupDataWithPid_[ipid].count(nameindex) && + !mAPPStartupDataWithPid_[ipid][nameindex].count(UI_ABILITY_ONFOREGROUND)) { + mAPPStartupDataWithPid_[ipid][nameindex].insert(std::make_pair( + UI_ABILITY_ONFOREGROUND, + std::move(std::make_unique(callId, ipid, tid, startTime, INVALID_UINT64)))); + } } } - UpdatePidByNameIndex(); - CaclRsDataByPid(); - AppendData(); + for (auto& item : mAPPStartupDataWithPid_) { + UpdatePidByNameIndex(item.second); + CaclRsDataByPid(item.second); + AppendData(item.second); + } return; } diff --git a/trace_streamer/src/filter/app_start_filter.h b/trace_streamer/src/filter/app_start_filter.h index 447da95eb..cc5d4d8a4 100644 --- a/trace_streamer/src/filter/app_start_filter.h +++ b/trace_streamer/src/filter/app_start_filter.h @@ -75,12 +75,14 @@ private: uint64_t endTime, uint64_t startTime); void ParserAppStartup(); - bool CaclRsDataByPid(); bool GetProcessCreate(uint32_t row, uint64_t& startTime, std::string nameString); - void UpdatePidByNameIndex(); - void AppendData(); - DataIndex GetThreadNameAndUpdateAPPStartupData(uint32_t row, const std::string& nameString, uint32_t startIndex); - std::unordered_map>> mAPPStartupData_; + using appMap = std::unordered_map>>; + void UpdatePidByNameIndex(const appMap& mAPPStartupData); + bool CaclRsDataByPid(appMap& mAPPStartupData); + void AppendData(const appMap& mAPPStartupData); + void UpdateAPPStartupData(uint32_t row, const std::string& nameString, uint32_t startIndex); + appMap mAPPStartupData_; + std::unordered_map mAPPStartupDataWithPid_; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/filter/task_pool_filter.cpp b/trace_streamer/src/filter/task_pool_filter.cpp index b9ef89fc8..da4f75289 100644 --- a/trace_streamer/src/filter/task_pool_filter.cpp +++ b/trace_streamer/src/filter/task_pool_filter.cpp @@ -52,7 +52,7 @@ void TaskPoolFilter::TaskPoolFieldSegmentation(const std::string& taskPoolStr, } } -void TaskPoolFilter::TaskPoolEvent(const std::string& taskPoolStr, int32_t index) +bool TaskPoolFilter::TaskPoolEvent(const std::string& taskPoolStr, int32_t index) { std::string targetStr = "H:Task "; if (!taskPoolStr.compare(0, targetStr.length(), targetStr)) { @@ -62,23 +62,24 @@ void TaskPoolFilter::TaskPoolEvent(const std::string& taskPoolStr, int32_t index allocationStr = taskPoolStr.substr(allocationStr.length(), taskPoolStr.length()); TaskPoolFieldSegmentation(allocationStr, args); UpdateAssignData(args, index); - return; + return true; } std::string executeStr = "H:Task Perform: "; if (StartWith(taskPoolStr, executeStr)) { executeStr = taskPoolStr.substr(executeStr.length(), taskPoolStr.length()); TaskPoolFieldSegmentation(executeStr, args); UpdateExecuteData(args, index); - return; + return true; } std::string returnStr = "H:Task PerformTask End: "; if (StartWith(taskPoolStr, returnStr)) { returnStr = taskPoolStr.substr(returnStr.length(), taskPoolStr.length()); TaskPoolFieldSegmentation(returnStr, args); UpdateReturnData(args, index); - return; + return true; } } + return false; } void TaskPoolFilter::UpdateAssignData(const std::unordered_map& args, int32_t index) diff --git a/trace_streamer/src/filter/task_pool_filter.h b/trace_streamer/src/filter/task_pool_filter.h index 1ed65caf8..2b0a8b323 100644 --- a/trace_streamer/src/filter/task_pool_filter.h +++ b/trace_streamer/src/filter/task_pool_filter.h @@ -33,7 +33,7 @@ public: TaskPoolFilter(const TaskPoolFilter&) = delete; ~TaskPoolFilter() override; uint32_t CheckTheSameTask(int32_t executeId); - void TaskPoolEvent(const std::string& taskPoolStr, int32_t index); + bool TaskPoolEvent(const std::string& taskPoolStr, int32_t index); void TaskPoolFieldSegmentation(const std::string& taskPoolStr, std::unordered_map& args); void UpdateAssignData(const std::unordered_map& args, int32_t index); void UpdateExecuteData(const std::unordered_map& args, int32_t index); diff --git a/trace_streamer/src/parser/print_event_parser.cpp b/trace_streamer/src/parser/print_event_parser.cpp index b3accb583..e06f885e3 100644 --- a/trace_streamer/src/parser/print_event_parser.cpp +++ b/trace_streamer/src/parser/print_event_parser.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include "print_event_parser.h" +#include "animation_filter.h" #include "clock_filter_ex.h" #include "frame_filter.h" #include "stat_filter.h" @@ -59,9 +60,13 @@ bool PrintEventParser::ParsePrintEvent(const std::string& comm, traceDataCache_->GetInternalSlicesData()->SetDistributeInfo( index, point.chainId_, point.spanId_, point.parentSpanId_, point.flag_, point.args_); if (pid == point.tgid_) { - HandleFrameSliceBeginEvent(point.funcPrefixId_, index, point.funcArgs_, line); + if (HandleFrameSliceBeginEvent(point.funcPrefixId_, index, point.funcArgs_, line)) { + break; + } + } + if (!streamFilters_->taskPoolFilter_->TaskPoolEvent(point.name_, index)) { + HandleAnimationBeginEvent(point, index, line); } - streamFilters_->taskPoolFilter_->TaskPoolEvent(point.name_, index); } else { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_LOST); } @@ -80,6 +85,9 @@ bool PrintEventParser::ParsePrintEvent(const std::string& comm, traceDataCache_->GetDataIndex(point.name_)); if (point.name_ == onFrameQueeuStartEvent_ && index != INVALID_UINT64) { OnFrameQueueStart(ts, index, point.tgid_); + } else if (index != INVALID_UINT64 && EndWith(comm, onLauncherVsyncEvent_) && // the comm is taskName + onAnimationStartEvent_ == traceDataCache_->GetDataIndex(point.name_)) { + HandleAnimationStartEvent(line, index); } break; } @@ -88,6 +96,7 @@ bool PrintEventParser::ParsePrintEvent(const std::string& comm, auto index = streamFilters_->sliceFilter_->FinishAsyncSlice(ts, pid, point.tgid_, cookie, traceDataCache_->GetDataIndex(point.name_)); HandleFrameQueueEndEvent(ts, point.tgid_, point.tgid_, index); + HandleAnimationFinishEvent(line, index); break; } case 'C': { @@ -107,6 +116,31 @@ bool PrintEventParser::ParsePrintEvent(const std::string& comm, } return true; } +bool PrintEventParser::HandleAnimationBeginEvent(const TracePoint& point, size_t callStackRow, const BytraceLine& line) +{ + if (traceDataCache_->AnimationTraceEnabled()) { + if (!streamFilters_->animationFilter_->UpdateDeviceInfoEvent(point, line)) { + return streamFilters_->animationFilter_->BeginDynamicFrameEvent(point, callStackRow); + } + return true; + } + return false; +} +bool PrintEventParser::HandleAnimationStartEvent(const BytraceLine& line, size_t callStackRow) +{ + if (traceDataCache_->AnimationTraceEnabled()) { + streamFilters_->animationFilter_->StartAnimationEvent(line, callStackRow); + return true; + } + return false; +} +bool PrintEventParser::HandleAnimationFinishEvent(const BytraceLine& line, size_t callStackRow) +{ + if (traceDataCache_->AnimationTraceEnabled()) { + return streamFilters_->animationFilter_->FinishAnimationEvent(line, callStackRow); + } + return false; +} void PrintEventParser::SetTraceType(TraceFileType traceType) { traceType_ = traceType; @@ -122,6 +156,7 @@ void PrintEventParser::Finish() eventToFrameFunctionMap_.clear(); frameCallIds_.clear(); vsyncSliceIds_.clear(); + streamFilters_->animationFilter_->Clear(); streamFilters_->frameFilter_->Finish(); } ParseResult PrintEventParser::CheckTracePoint(std::string_view pointStr) const @@ -164,6 +199,8 @@ std::string_view PrintEventParser::GetPointNameForBegin(std::string_view pointSt size_t length = pointStr.size() - index - ((pointStr.back() == '\n') ? 1 : 0); std::string_view name = std::string_view(pointStr.data() + index, length); + // remove space at the end + name = std::string_view(name.data(), name.find_last_not_of(" ") + 1); return name; } @@ -206,7 +243,7 @@ ParseResult PrintEventParser::HandlerB(std::string_view pointStr, TracePoint& ou return PARSE_SUCCESS; } -void PrintEventParser::HandleFrameSliceBeginEvent(DataIndex eventName, +bool PrintEventParser::HandleFrameSliceBeginEvent(DataIndex eventName, size_t callStackRow, std::string& args, const BytraceLine& line) @@ -214,7 +251,9 @@ void PrintEventParser::HandleFrameSliceBeginEvent(DataIndex eventName, auto it = eventToFrameFunctionMap_.find(eventName); if (it != eventToFrameFunctionMap_.end()) { it->second(callStackRow, args, line); + return true; } + return false; } bool PrintEventParser::ReciveVsync(size_t callStackRow, std::string& args, const BytraceLine& line) { diff --git a/trace_streamer/src/parser/print_event_parser.h b/trace_streamer/src/parser/print_event_parser.h index b6a3dda25..7c3518add 100644 --- a/trace_streamer/src/parser/print_event_parser.h +++ b/trace_streamer/src/parser/print_event_parser.h @@ -45,12 +45,15 @@ private: 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; - void HandleFrameSliceBeginEvent(DataIndex eventName, + bool HandleFrameSliceBeginEvent(DataIndex eventName, size_t callStackRow, std::string& args, const BytraceLine& line); void HandleFrameSliceEndEvent(uint64_t ts, uint64_t pid, uint64_t tid, size_t callStackRow); void HandleFrameQueueEndEvent(uint64_t ts, uint64_t pid, uint64_t tid, size_t callStackRow); + bool HandleAnimationBeginEvent(const TracePoint& point, size_t callStackRow, const BytraceLine& line); + bool HandleAnimationStartEvent(const BytraceLine& line, size_t callStackRow); + bool HandleAnimationFinishEvent(const BytraceLine& line, size_t callStackRow); static ParseResult HandlerE(void); ParseResult HandlerCSF(std::string_view pointStr, TracePoint& outPoint, size_t tGidlength) const; static size_t GetNameLength(std::string_view pointStr, size_t nameIndex); @@ -69,8 +72,10 @@ private: const DataIndex recvievVsync_ = traceDataCache_->GetDataIndex("H:ReceiveVsync"); const DataIndex rsOnVsyncEvent_ = traceDataCache_->GetDataIndex("H:RSMainThread::OnVsync"); const std::string onFrameQueeuStartEvent_ = "H:M: Frame queued"; + const std::string onLauncherVsyncEvent_ = "launcher"; const DataIndex marshRwTransactionData_ = traceDataCache_->GetDataIndex("H:MarshRSTransactionData"); const DataIndex rsMainThreadProcessCmd_ = traceDataCache_->GetDataIndex("H:RSMainThread::ProcessCommandUni"); + const DataIndex onAnimationStartEvent_ = traceDataCache_->GetDataIndex("H:L:TracestartAppAnimation"); const std::regex recvVsyncPattern_ = std::regex("(\\w+):(\\w+)"); const std::regex transFlagPattern_ = std::regex("transactionFlag:\\[(\\d+),(\\d+)\\]"); const std::regex mainProcessCmdPattern = std::regex("\\[(\\d+),(\\d+)\\]"); diff --git a/trace_streamer/src/table/base/BUILD.gn b/trace_streamer/src/table/base/BUILD.gn index 065bdd20b..30a15a4de 100644 --- a/trace_streamer/src/table/base/BUILD.gn +++ b/trace_streamer/src/table/base/BUILD.gn @@ -26,6 +26,8 @@ ohos_source_set("base_tables") { "data_type_table.h", "datasource_clockid_table.cpp", "datasource_clockid_table.h", + "device_info.cpp", + "device_info.h", "meta_table.cpp", "meta_table.h", "range_table.cpp", diff --git a/trace_streamer/src/table/base/device_info.cpp b/trace_streamer/src/table/base/device_info.cpp new file mode 100644 index 000000000..983b93b80 --- /dev/null +++ b/trace_streamer/src/table/base/device_info.cpp @@ -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. + */ + +#include "device_info.h" + +namespace SysTuning { +namespace TraceStreamer { +enum Index { PHYSICAL_WIDTH = 0, PHYSICAL_HEIGHT, PHYSICAL_FRAME_RATE }; +DeviceInfoTable::DeviceInfoTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("physical_width", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("physical_height", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("physical_frame_rate", "INTEGER")); + tablePriKey_.push_back("physical_width"); +} + +DeviceInfoTable::~DeviceInfoTable() {} + +std::unique_ptr DeviceInfoTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +DeviceInfoTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, 1), deviceInfoObj_(dataCache->GetConstDeviceInfo()) +{ +} + +DeviceInfoTable::Cursor::~Cursor() {} + +int32_t DeviceInfoTable::Cursor::Column(int32_t column) const +{ + switch (column) { + case PHYSICAL_WIDTH: + if (deviceInfoObj_.PhysicalWidth() != INVALID_UINT32) { + sqlite3_result_int(context_, static_cast(deviceInfoObj_.PhysicalWidth())); + } + break; + case PHYSICAL_HEIGHT: + if (deviceInfoObj_.PhysicalHeight() != INVALID_UINT32) { + sqlite3_result_int(context_, static_cast(deviceInfoObj_.PhysicalHeight())); + } + break; + case PHYSICAL_FRAME_RATE: + if (deviceInfoObj_.PhysicalFrameRate() != INVALID_UINT32) { + sqlite3_result_int(context_, static_cast(deviceInfoObj_.PhysicalFrameRate())); + } + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/src/table/base/device_info.h b/trace_streamer/src/table/base/device_info.h new file mode 100644 index 000000000..9db2a635e --- /dev/null +++ b/trace_streamer/src/table/base/device_info.h @@ -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. + */ + +#ifndef DEVICE_INFO +#define DEVICE_INFO + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class DeviceInfoTable : public TableBase { +public: + explicit DeviceInfoTable(const TraceDataCache* dataCache); + ~DeviceInfoTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int32_t Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + + int32_t Column(int32_t column) const override; + + private: + const DeviceInfo& deviceInfoObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // DEVICE_INFO diff --git a/trace_streamer/src/table/ftrace/BUILD.gn b/trace_streamer/src/table/ftrace/BUILD.gn index 11ecec57d..2c2a0008e 100644 --- a/trace_streamer/src/table/ftrace/BUILD.gn +++ b/trace_streamer/src/table/ftrace/BUILD.gn @@ -18,6 +18,8 @@ ohos_source_set("ftrace_tables") { subsystem_name = "developtools" part_name = "smartperf_host" sources = [ + "animation_table.cpp", + "animation_table.h", "app_startup_table.cpp", "app_startup_table.h", "callstack_table.cpp", @@ -30,6 +32,8 @@ ohos_source_set("ftrace_tables") { "clock_snapshot_table.h", "cpu_measure_filter_table.cpp", "cpu_measure_filter_table.h", + "dynamic_frame_table.cpp", + "dynamic_frame_table.h", "filter_table.cpp", "filter_table.h", "frame_maps_table.cpp", diff --git a/trace_streamer/src/table/ftrace/animation_table.cpp b/trace_streamer/src/table/ftrace/animation_table.cpp new file mode 100644 index 000000000..b705990b7 --- /dev/null +++ b/trace_streamer/src/table/ftrace/animation_table.cpp @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "animation_table.h" + +#include + +namespace SysTuning { +namespace TraceStreamer { +enum Index { ID = 0, INPUT_TIME, START_POINT, END_POINT }; +AnimationTable::AnimationTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("input_time", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("start_point", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("end_point", "INTEGER")); + tablePriKey_.push_back("id"); +} + +AnimationTable::~AnimationTable() {} + +void AnimationTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstAnimation().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void AnimationTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int32_t i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + auto oldRowCount = rowCount; + if (CanFilterSorted(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += log2(oldRowCount); // binary search + } else { + filterCost += oldRowCount; + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool AnimationTable::CanFilterSorted(const char op, size_t& rowCount) const +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = rowCount / log2(rowCount); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr AnimationTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +AnimationTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstAnimation().Size())), + animationObj_(dataCache->GetConstAnimation()) +{ +} + +AnimationTable::Cursor::~Cursor() {} + +int32_t AnimationTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterSorted(c.col, c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int32_t AnimationTable::Cursor::Column(int32_t col) const +{ + switch (col) { + case ID: + sqlite3_result_int64(context_, static_cast(animationObj_.IdsData()[CurrentRow()])); + break; + case INPUT_TIME: { + if (animationObj_.InputTimes()[CurrentRow()] != INVALID_TIME) { + sqlite3_result_int64(context_, static_cast(animationObj_.InputTimes()[CurrentRow()])); + } + break; + } + case START_POINT: { + if (animationObj_.StartPoints()[CurrentRow()] != INVALID_TIME) { + sqlite3_result_int64(context_, static_cast(animationObj_.StartPoints()[CurrentRow()])); + } + break; + } + case END_POINT: + if (animationObj_.EndPoints()[CurrentRow()] != INVALID_TIME) { + sqlite3_result_int64(context_, static_cast(animationObj_.EndPoints()[CurrentRow()])); + } + break; + default: + TS_LOGF("Unregistered column : %d", col); + break; + } + return SQLITE_OK; +} + +void AnimationTable::Cursor::FilterSorted(int32_t col, unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL, filter out nothing + indexMap_->Intersect(0, 0); + return; + } + + switch (col) { + case ID: { + auto v = static_cast(sqlite3_value_int64(argv)); + auto getValue = [](const uint32_t& row) { return row; }; + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->IntersectabcEqual(animationObj_.IdsData(), v, getValue); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + case SQLITE_INDEX_CONSTRAINT_GE: { + indexMap_->IntersectGreaterEqual(animationObj_.IdsData(), v, getValue); + break; + } + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + case SQLITE_INDEX_CONSTRAINT_LT: { + indexMap_->IntersectLessEqual(animationObj_.IdsData(), v, getValue); + break; + } + default: + break; + } // end of switch (op) + } // end of case TS + default: + // can't filter, all rows + break; + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/src/table/ftrace/animation_table.h b/trace_streamer/src/table/ftrace/animation_table.h new file mode 100644 index 000000000..5830b51d0 --- /dev/null +++ b/trace_streamer/src/table/ftrace/animation_table.h @@ -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. + */ + +#ifndef ANIMATION__TABLE_H +#define ANIMATION__TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class AnimationTable : public TableBase { +public: + explicit AnimationTable(const TraceDataCache*); + ~AnimationTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // the column is sorted + bool CanFilterSorted(const char op, size_t& rowCount) const; + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int32_t Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int32_t Column(int32_t col) const override; + + void FilterSorted(int32_t col, unsigned char op, sqlite3_value* argv); + + private: + const Animation& animationObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // ANIMATION__TABLE_H diff --git a/trace_streamer/src/table/ftrace/dynamic_frame_table.cpp b/trace_streamer/src/table/ftrace/dynamic_frame_table.cpp new file mode 100644 index 000000000..9fa134a37 --- /dev/null +++ b/trace_streamer/src/table/ftrace/dynamic_frame_table.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "dynamic_frame_table.h" + +#include + +namespace SysTuning { +namespace TraceStreamer { +enum Index { ID = 0, X, Y, WIDTH, HEIGHT, ALPHA, NAME, END_TIME }; +DynamicFrameTable::DynamicFrameTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("x", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("y", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("width", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("height", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("alpha", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("end_time", "INTEGER")); + tablePriKey_.push_back("id"); +} + +DynamicFrameTable::~DynamicFrameTable() {} + +void DynamicFrameTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstDynamicFrame().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void DynamicFrameTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int32_t i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + auto oldRowCount = rowCount; + if (CanFilterSorted(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += log2(oldRowCount); // binary search + } else { + filterCost += oldRowCount; + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool DynamicFrameTable::CanFilterSorted(const char op, size_t& rowCount) const +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = rowCount / log2(rowCount); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr DynamicFrameTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +DynamicFrameTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstDynamicFrame().Size())), + dynamicFrameObj_(dataCache->GetConstDynamicFrame()) +{ +} + +DynamicFrameTable::Cursor::~Cursor() {} + +int32_t DynamicFrameTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterSorted(c.col, c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int32_t DynamicFrameTable::Cursor::Column(int32_t col) const +{ + switch (col) { + case ID: + sqlite3_result_int64(context_, static_cast(dynamicFrameObj_.IdsData()[CurrentRow()])); + break; + case X: { + sqlite3_result_int(context_, static_cast(dynamicFrameObj_.Xs()[CurrentRow()])); + break; + } + case Y: { + sqlite3_result_int(context_, static_cast(dynamicFrameObj_.Ys()[CurrentRow()])); + break; + } + case WIDTH: { + sqlite3_result_int(context_, static_cast(dynamicFrameObj_.Widths()[CurrentRow()])); + break; + } + case HEIGHT: { + sqlite3_result_int(context_, static_cast(dynamicFrameObj_.Heights()[CurrentRow()])); + break; + } + case ALPHA: { + if (dynamicFrameObj_.Alphas()[CurrentRow()] != INVALID_UINT64) { + const std::string& str = + dataCache_->GetDataFromDict(static_cast(dynamicFrameObj_.Alphas()[CurrentRow()])); + sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr); + } + + break; + } + case NAME: { + if (dynamicFrameObj_.Names()[CurrentRow()] != INVALID_UINT64) { + const std::string& str = + dataCache_->GetDataFromDict(static_cast(dynamicFrameObj_.Names()[CurrentRow()])); + sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr); + } + break; + } + case END_TIME: + if (dynamicFrameObj_.EndTimes()[CurrentRow()] != INVALID_TIME) { + sqlite3_result_int64(context_, static_cast(dynamicFrameObj_.EndTimes()[CurrentRow()])); + } + break; + default: + TS_LOGF("Unregistered column : %d", col); + break; + } + return SQLITE_OK; +} + +void DynamicFrameTable::Cursor::FilterSorted(int32_t col, unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL, filter out nothing + indexMap_->Intersect(0, 0); + return; + } + + switch (col) { + case ID: { + auto v = static_cast(sqlite3_value_int64(argv)); + auto getValue = [](const uint32_t& row) { return row; }; + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->IntersectabcEqual(dynamicFrameObj_.IdsData(), v, getValue); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + case SQLITE_INDEX_CONSTRAINT_GE: { + indexMap_->IntersectGreaterEqual(dynamicFrameObj_.IdsData(), v, getValue); + break; + } + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + case SQLITE_INDEX_CONSTRAINT_LT: { + indexMap_->IntersectLessEqual(dynamicFrameObj_.IdsData(), v, getValue); + break; + } + default: + break; + } // end of switch (op) + } // end of case TS + default: + // can't filter, all rows + break; + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/src/table/ftrace/dynamic_frame_table.h b/trace_streamer/src/table/ftrace/dynamic_frame_table.h new file mode 100644 index 000000000..4ef53096e --- /dev/null +++ b/trace_streamer/src/table/ftrace/dynamic_frame_table.h @@ -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. + */ + +#ifndef DYNAMIC__FRAME__TABLE_H +#define DYNAMIC__FRAME__TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class DynamicFrameTable : public TableBase { +public: + explicit DynamicFrameTable(const TraceDataCache*); + ~DynamicFrameTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // the column is sorted + bool CanFilterSorted(const char op, size_t& rowCount) const; + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int32_t Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int32_t Column(int32_t col) const override; + + void FilterSorted(int32_t col, unsigned char op, sqlite3_value* argv); + + private: + const DynamicFrame& dynamicFrameObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // DYNAMIC__FRAME__TABLE_H diff --git a/trace_streamer/src/trace_data/trace_data_cache.cpp b/trace_streamer/src/trace_data/trace_data_cache.cpp index 9d86803fe..903876c95 100644 --- a/trace_streamer/src/trace_data/trace_data_cache.cpp +++ b/trace_streamer/src/trace_data/trace_data_cache.cpp @@ -14,6 +14,7 @@ */ #include "trace_data_cache.h" +#include "animation_table.h" #include "app_startup_table.h" #include "appname_table.h" #include "args_table.h" @@ -27,8 +28,10 @@ #include "data_dict_table.h" #include "data_type_table.h" #include "datasource_clockid_table.h" +#include "device_info.h" #include "device_state_table.h" #include "disk_io_table.h" +#include "dynamic_frame_table.h" #include "ebpf_callstack_table.h" #if WITH_EBPF_HELP #include "ebpf_elf_symbol_table.h" @@ -103,10 +106,12 @@ TraceDataCache::~TraceDataCache() {} void TraceDataCache::InitDB() { - if (dbInited) { + if (dbInited_) { return; } #ifdef USE_VTABLE + TableBase::TableDeclare(*db_, this, "animation"); + TableBase::TableDeclare(*db_, this, "dynamic_frame"); TableBase::TableDeclare(*db_, this, "process"); TableBase::TableDeclare(*db_, this, "sched_slice"); TableBase::TableDeclare(*db_, this, "callstack"); @@ -127,6 +132,7 @@ void TraceDataCache::InitDB() TableBase::TableDeclare(*db_, this, "span_join"); // no id + TableBase::TableDeclare(*db_, this, "device_info"); TableBase::TableDeclare(*db_, this, "instant"); TableBase::TableDeclare(*db_, this, "measure"); TableBase::TableDeclare(*db_, this, "sys_mem_measure"); @@ -190,6 +196,8 @@ void TraceDataCache::InitDB() TableBase::TableDeclare(*db_, this, "perf_files"); #endif #else + TableBase::TableDeclare(*db_, this, "_animation"); + TableBase::TableDeclare(*db_, this, "_dynamic_frame"); TableBase::TableDeclare(*db_, this, "_process"); TableBase::TableDeclare(*db_, this, "_sched_slice"); TableBase::TableDeclare(*db_, this, "_callstack"); @@ -210,6 +218,7 @@ void TraceDataCache::InitDB() TableBase::TableDeclare(*db_, this, "_span_join"); // no id + TableBase::TableDeclare(*db_, this, "_device_info"); TableBase::TableDeclare(*db_, this, "_instant"); TableBase::TableDeclare(*db_, this, "_measure"); TableBase::TableDeclare(*db_, this, "_sys_mem_measure"); @@ -271,7 +280,15 @@ void TraceDataCache::InitDB() TableBase::TableDeclare(*db_, this, "_perf_files"); #endif #endif - dbInited = true; + dbInited_ = true; +} +bool TraceDataCache::AnimationTraceEnabled() +{ + return animationTraceEnabled_; +} +void TraceDataCache::UpdateAnimationTraceStatus(bool status) +{ + animationTraceEnabled_ = status; } } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/trace_data/trace_data_cache.h b/trace_streamer/src/trace_data/trace_data_cache.h index a53e2ae0a..efdaea23d 100644 --- a/trace_streamer/src/trace_data/trace_data_cache.h +++ b/trace_streamer/src/trace_data/trace_data_cache.h @@ -31,9 +31,13 @@ public: TraceDataCache* operator=(const TraceDataCache* dataCache) = delete; ~TraceDataCache() override; + bool AnimationTraceEnabled(); + void UpdateAnimationTraceStatus(bool status); + private: void InitDB() override; - bool dbInited = false; + bool dbInited_ = false; + bool animationTraceEnabled_ = true; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/trace_data/trace_data_cache_base.h b/trace_streamer/src/trace_data/trace_data_cache_base.h index 78a842c9e..7e9e573f8 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_base.h +++ b/trace_streamer/src/trace_data/trace_data_cache_base.h @@ -164,6 +164,9 @@ public: JsHeapTraceNode jsHeapTraceNodeData_; AppStartup appStartupData_; SoStaticInitalization staticInitalizationData_; + Animation animation_; + DeviceInfo deviceInfo_; + DynamicFrame dynamicFrame_; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/trace_data/trace_data_cache_reader.cpp b/trace_streamer/src/trace_data/trace_data_cache_reader.cpp index 48cfcd80c..1491e2fc1 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_reader.cpp +++ b/trace_streamer/src/trace_data/trace_data_cache_reader.cpp @@ -338,5 +338,17 @@ const SoStaticInitalization& TraceDataCacheReader::GetConstStaticInitalizationDa { return staticInitalizationData_; } +const Animation& TraceDataCacheReader::GetConstAnimation() const +{ + return animation_; +} +const DeviceInfo& TraceDataCacheReader::GetConstDeviceInfo() const +{ + return deviceInfo_; +} +const DynamicFrame& TraceDataCacheReader::GetConstDynamicFrame() const +{ + return dynamicFrame_; +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/trace_data/trace_data_cache_reader.h b/trace_streamer/src/trace_data/trace_data_cache_reader.h index e4085551b..d1d1b14d9 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_reader.h +++ b/trace_streamer/src/trace_data/trace_data_cache_reader.h @@ -108,6 +108,9 @@ public: const JsHeapTraceNode& GetConstJsHeapTraceNodeData() const; const AppStartup& GetConstAppStartupData() const; const SoStaticInitalization& GetConstStaticInitalizationData() const; + const Animation& GetConstAnimation() const; + const DeviceInfo& GetConstDeviceInfo() const; + const DynamicFrame& GetConstDynamicFrame() const; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/trace_data/trace_data_cache_writer.cpp b/trace_streamer/src/trace_data/trace_data_cache_writer.cpp index 394f2f61c..41844cc4c 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_writer.cpp +++ b/trace_streamer/src/trace_data/trace_data_cache_writer.cpp @@ -382,6 +382,18 @@ SoStaticInitalization* TraceDataCacheWriter::GetStaticInitalizationData() { return &staticInitalizationData_; } +Animation* TraceDataCacheWriter::GetAnimation() +{ + return &animation_; +} +DeviceInfo* TraceDataCacheWriter::GetDeviceInfo() +{ + return &deviceInfo_; +} +DynamicFrame* TraceDataCacheWriter::GetDynamicFrame() +{ + return &dynamicFrame_; +} void TraceDataCacheWriter::Clear() { rawData_.Clear(); @@ -441,6 +453,9 @@ void TraceDataCacheWriter::Clear() jsHeapTraceNodeData_.Clear(); appStartupData_.Clear(); staticInitalizationData_.Clear(); + animation_.Clear(); + deviceInfo_.Clear(); + dynamicFrame_.Clear(); #if WITH_EBPF_HELP ebpfProcessMaps_.Clear(); diff --git a/trace_streamer/src/trace_data/trace_data_cache_writer.h b/trace_streamer/src/trace_data/trace_data_cache_writer.h index 067988ba2..a98a92c9b 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_writer.h +++ b/trace_streamer/src/trace_data/trace_data_cache_writer.h @@ -107,6 +107,9 @@ public: JsHeapTraceNode* GetJsHeapTraceNodeData(); AppStartup* GetAppStartupData(); SoStaticInitalization* GetStaticInitalizationData(); + Animation* GetAnimation(); + DeviceInfo* GetDeviceInfo(); + DynamicFrame* GetDynamicFrame(); }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/trace_data/trace_stdtype.cpp b/trace_streamer/src/trace_data/trace_stdtype.cpp index f90012bda..ac133b484 100644 --- a/trace_streamer/src/trace_data/trace_stdtype.cpp +++ b/trace_streamer/src/trace_data/trace_stdtype.cpp @@ -20,7 +20,6 @@ namespace SysTuning { namespace TraceStdtype { const int32_t MAX_SIZE_LEN = 80; -const int32_t ONE_MILLION_NANOSECONDS = 1000000; #define UNUSED(expr) \ do { \ static_cast(expr); \ @@ -2878,5 +2877,165 @@ void TaskPoolInfo::UpdateReturnTaskData(uint32_t index, returnStates_[index] = returnState; } } +TableRowId Animation::AppendAnimation(InternalTime startPoint) +{ + inputTimes_.emplace_back(INVALID_TIME); + startPoints_.emplace_back(startPoint); + endPoins_.emplace_back(INVALID_TIME); + ids_.emplace_back(Size()); + return ids_.size() - 1; +} +void Animation::UpdateStartPoint(TableRowId index, InternalTime startPoint) +{ + if (index <= Size()) { + startPoints_[index] = startPoint; + } +} +void Animation::UpdateEndPoint(TableRowId index, InternalTime endPoint) +{ + if (index <= Size()) { + endPoins_[index] = endPoint; + } +} +size_t Animation::Size() const +{ + return ids_.size(); +} +const std::deque& Animation::InputTimes() const +{ + return inputTimes_; +} +const std::deque& Animation::StartPoints() const +{ + return startPoints_; +} +const std::deque& Animation::EndPoints() const +{ + return endPoins_; +} +const std::deque& Animation::IdsData() const +{ + return ids_; +} +void Animation::Clear() +{ + inputTimes_.clear(); + startPoints_.clear(); + endPoins_.clear(); + ids_.clear(); +} +const uint32_t DeviceInfo::PhysicalWidth() const +{ + return physicalWidth_; +} +const uint32_t DeviceInfo::PhysicalHeight() const +{ + return physicalHeight_; +} +const uint32_t DeviceInfo::PhysicalFrameRate() const +{ + return physicalFrameRate_; +} +void DeviceInfo::UpdateWidthAndHeight(uint32_t width, uint32_t height) +{ + physicalWidth_ = width; + physicalHeight_ = height; +} +void DeviceInfo::UpdateFrameRate(uint32_t frameRate) +{ + physicalFrameRate_ = frameRate; +} +void DeviceInfo::Clear() +{ + physicalWidth_ = INVALID_UINT32; + physicalHeight_ = INVALID_UINT32; + physicalFrameRate_ = INVALID_UINT32; +} +TableRowId DynamicFrame::AppendDynamicFrame(DataIndex nameId) +{ + names_.emplace_back(nameId); + ids_.emplace_back(Size()); + xs_.emplace_back(INVALID_UINT32); + ys_.emplace_back(INVALID_UINT32); + widths_.emplace_back(INVALID_UINT32); + heights_.emplace_back(INVALID_UINT32); + alphas_.emplace_back(INVALID_UINT64); + endTimes_.emplace_back(INVALID_TIME); + return ids_.size() - 1; +} +void DynamicFrame::UpdateNameIndex(TableRowId index, DataIndex nameId) +{ + if (index <= Size()) { + names_[index] = nameId; + } +} +void DynamicFrame::UpdatePosition(TableRowId index, + uint32_t x, + uint32_t y, + uint32_t width, + uint32_t height, + DataIndex alpha) +{ + if (index <= Size()) { + xs_[index] = x; + ys_[index] = y; + widths_[index] = width; + heights_[index] = height; + alphas_[index] = alpha; + } +} +void DynamicFrame::UpdateEndTime(TableRowId index, InternalTime endTime) +{ + if (index <= Size()) { + endTimes_[index] = endTime; + } +} +size_t DynamicFrame::Size() const +{ + return ids_.size(); +} +const std::deque& DynamicFrame::IdsData() const +{ + return ids_; +} +const std::deque& DynamicFrame::Xs() const +{ + return xs_; +} +const std::deque& DynamicFrame::Ys() const +{ + return ys_; +} +const std::deque& DynamicFrame::Widths() const +{ + return widths_; +} +const std::deque& DynamicFrame::Heights() const +{ + return heights_; +} +const std::deque& DynamicFrame::Alphas() const +{ + return alphas_; +} +const std::deque& DynamicFrame::Names() const +{ + return names_; +} +const std::deque& DynamicFrame::EndTimes() const +{ + return endTimes_; +} +void DynamicFrame::Clear() +{ + xs_.clear(); + ys_.clear(); + widths_.clear(); + heights_.clear(); + alphas_.clear(); + names_.clear(); + endTimes_.clear(); + ids_.clear(); +} } // namespace TraceStdtype } // namespace SysTuning diff --git a/trace_streamer/src/trace_data/trace_stdtype.h b/trace_streamer/src/trace_data/trace_stdtype.h index f714a2735..93ebdece5 100644 --- a/trace_streamer/src/trace_data/trace_stdtype.h +++ b/trace_streamer/src/trace_data/trace_stdtype.h @@ -37,6 +37,8 @@ namespace SysTuning { namespace TraceStdtype { using namespace SysTuning::TraceCfg; using namespace SysTuning::TraceStreamer; +constexpr uint32_t ONE_MILLION_NANOSECONDS = 1000000; +constexpr uint32_t BILLION_NANOSECONDS = 1000000000; class CacheBase { public: size_t Size() const @@ -2367,6 +2369,67 @@ private: std::deque executeStates_ = {}; std::deque returnStates_ = {}; }; +class Animation { +public: + TableRowId AppendAnimation(InternalTime startPoint); + void UpdateStartPoint(TableRowId index, InternalTime startPoint); + void UpdateEndPoint(TableRowId index, InternalTime endPoint); + size_t Size() const; + const std::deque& InputTimes() const; + const std::deque& StartPoints() const; + const std::deque& EndPoints() const; + const std::deque& IdsData() const; + void Clear(); + +private: + std::deque inputTimes_ = {}; + std::deque startPoints_ = {}; + std::deque endPoins_ = {}; + std::deque ids_ = {}; +}; +class DeviceInfo { +public: + const uint32_t PhysicalWidth() const; + const uint32_t PhysicalHeight() const; + const uint32_t PhysicalFrameRate() const; + void UpdateWidthAndHeight(uint32_t width, uint32_t height); + void UpdateFrameRate(uint32_t frameRate); + + void Clear(); + +private: + uint32_t physicalWidth_ = INVALID_UINT32; + uint32_t physicalHeight_ = INVALID_UINT32; + uint32_t physicalFrameRate_ = INVALID_UINT32; +}; +class DynamicFrame { +public: + TableRowId AppendDynamicFrame(DataIndex nameId); + void UpdateNameIndex(TableRowId index, DataIndex nameId); + void UpdatePosition(TableRowId index, uint32_t x, uint32_t y, uint32_t width, uint32_t height, DataIndex alpha); + void UpdateEndTime(TableRowId index, InternalTime endTime); + + size_t Size() const; + const std::deque& IdsData() const; + const std::deque& Xs() const; + const std::deque& Ys() const; + const std::deque& Widths() const; + const std::deque& Heights() const; + const std::deque& Alphas() const; + const std::deque& Names() const; + const std::deque& EndTimes() const; + void Clear(); + +private: + std::deque xs_ = {}; + std::deque ys_ = {}; + std::deque widths_ = {}; + std::deque heights_ = {}; + std::deque alphas_ = {}; + std::deque names_ = {}; + std::deque endTimes_ = {}; + std::deque ids_ = {}; +}; } // namespace TraceStdtype } // namespace SysTuning diff --git a/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp b/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp index c18fc7700..921f3a1c6 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp +++ b/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp @@ -14,6 +14,7 @@ */ #include "trace_streamer_filters.h" +#include "animation_filter.h" #include "app_start_filter.h" #include "args_filter.h" #include "binder_filter.h" diff --git a/trace_streamer/src/trace_streamer/trace_streamer_filters.h b/trace_streamer/src/trace_streamer/trace_streamer_filters.h index 09dd1ec7d..e711f8751 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_filters.h +++ b/trace_streamer/src/trace_streamer/trace_streamer_filters.h @@ -19,6 +19,7 @@ #include namespace SysTuning { namespace TraceStreamer { +class AnimationFilter; class SliceFilter; class ProcessFilter; class CpuFilter; @@ -42,6 +43,7 @@ class TraceStreamerFilters { public: TraceStreamerFilters(); ~TraceStreamerFilters(); + std::unique_ptr animationFilter_; std::unique_ptr clockFilter_; std::unique_ptr filterFilter_; std::unique_ptr sliceFilter_; diff --git a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp index e9ed06e76..cd90b1b43 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp +++ b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp @@ -18,6 +18,7 @@ #include #include #include +#include "animation_filter.h" #include "app_start_filter.h" #include "args_filter.h" #include "binder_filter.h" @@ -104,6 +105,7 @@ void TraceStreamerSelector::InitFilter() { streamFilters_ = std::make_unique(); traceDataCache_ = std::make_unique(); + streamFilters_->animationFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); streamFilters_->cpuFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); streamFilters_->sliceFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); @@ -167,6 +169,9 @@ void TraceStreamerSelector::WaitForParserEnd() htraceParser_->WaitForParserEnd(); } traceDataCache_->UpdateTraceRange(); + if (traceDataCache_->AnimationTraceEnabled()) { + streamFilters_->animationFilter_->UpdateDynamicFrameInfo(); + } } MetaData* TraceStreamerSelector::GetMetaData() @@ -288,5 +293,9 @@ void TraceStreamerSelector::SetCancel(bool cancel) { traceDataCache_->SetCancel(cancel); } +void TraceStreamerSelector::UpdateAnimationTraceStatus(bool status) +{ + traceDataCache_->UpdateAnimationTraceStatus(status); +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/trace_streamer/trace_streamer_selector.h b/trace_streamer/src/trace_streamer/trace_streamer_selector.h index f084f7a55..30f44a171 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_selector.h +++ b/trace_streamer/src/trace_streamer/trace_streamer_selector.h @@ -49,6 +49,7 @@ public: { return fileType_; } + void UpdateAnimationTraceStatus(bool status); private: void InitFilter(); diff --git a/trace_streamer/src/version.cpp b/trace_streamer/src/version.cpp index 4a3a849f1..2d8fa8666 100644 --- a/trace_streamer/src/version.cpp +++ b/trace_streamer/src/version.cpp @@ -14,5 +14,5 @@ */ #include "version.h" size_t g_loadSize = 0; -std::string TRACE_STREAM_VERSION = "3.2.10"; // version -std::string TRACE_STREAM_PUBLISHVERSION = "2023/6/25"; // publish datetime +std::string TRACE_STREAM_VERSION = "3.4.3"; // version +std::string TRACE_STREAM_PUBLISHVERSION = "2023/7/14"; // publish datetime diff --git a/trace_streamer/test.sh b/trace_streamer/test.sh index 3ecc3a132..b58ed155d 100755 --- a/trace_streamer/test.sh +++ b/trace_streamer/test.sh @@ -22,5 +22,5 @@ mkdir -p out/test/data/resource mkdir -p out/test_debug/data/resource cp test/resource/* out/test/data/resource/ cp test/resource/* out/test_debug/data/resource/ -cd out/test +cd out/test/clang_x64/developtools/profiler ./trace_streamer_ut diff --git a/trace_streamer/test/BUILD.gn b/trace_streamer/test/BUILD.gn index ce7ca3e1c..26d80dea0 100755 --- a/trace_streamer/test/BUILD.gn +++ b/trace_streamer/test/BUILD.gn @@ -19,6 +19,7 @@ import("test_ts.gni") if (is_test) { ohos_unittest("trace_streamer_ut") { sources = [ + "unittest/animation_filter_test.cpp", "unittest/binder_filter_test.cpp", "unittest/bio_parser_test.cpp", "unittest/bytrace_parser_test.cpp", @@ -57,7 +58,9 @@ if (is_test) { "unittest/smaps_parser_test.cpp", "unittest/span_join_test.cpp", "unittest/table_test.cpp", + "unittest/task_pool_filter_test.cpp", "unittest/wasm_func_test.cpp", + "unittest/app_start_filter_test.cpp", ] deps = [ diff --git a/trace_streamer/test/unittest/animation_filter_test.cpp b/trace_streamer/test/unittest/animation_filter_test.cpp new file mode 100644 index 000000000..ee53d39c8 --- /dev/null +++ b/trace_streamer/test/unittest/animation_filter_test.cpp @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "animation_filter.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +constexpr uint8_t GENERATE_VSYNC_EVENT_MAX = 6; +constexpr uint16_t FPS_60 = 60; +constexpr uint16_t FPS_90 = 90; +constexpr uint16_t FPS_120 = 120; +class AnimationFilterTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + TraceStreamerSelector stream_; +}; + +/** + * @tc.name: NonRsUniProcessEvent + * @tc.desc: the current event isn't RsUniProcessEvent + * @tc.type: FUNC + */ +HWTEST_F(AnimationFilterTest, NonRsUniProcessEvent, TestSize.Level1) +{ + TS_LOGI("test36-1"); + TracePoint point; + const size_t CALLSTACK_SLICE_ID = 1; + std::vector nonRsUniProcessEvents{ + "H:RSUniRender::Prepare:[xxx]", + "H:RSUniRender:DrivenRenderPrepare", + "H:RSDrivenRender:DoPrepareRenderTask", + "H:ProcessDisplayRenderNode[0](0,", + "H:RSBaseRenderEngine::RequestFrame(RSSurface)", + "H:DisplayNode:4", + "H:AddContainerDirtyToGlobalDirty", + "H:EntryView", + }; + for (size_t i = 0; i < nonRsUniProcessEvents.size(); i++) { + point.funcPrefix_ = nonRsUniProcessEvents[i]; + auto res = stream_.streamFilters_->animationFilter_->BeginDynamicFrameEvent(point, CALLSTACK_SLICE_ID); + EXPECT_FALSE(res); + } +} + +/** + * @tc.name: InvalidCallStack + * @tc.desc: the current event isn't RsUniProcessEvent + * @tc.type: FUNC + */ +HWTEST_F(AnimationFilterTest, InvalidCallStack, TestSize.Level1) +{ + TS_LOGI("test36-2"); + TracePoint point; + const size_t CALLSTACK_SLICE_ID = 1; + CallStack* callStackSlice = stream_.traceDataCache_->GetInternalSlicesData(); + std::vector callStackNames{ + stream_.traceDataCache_->GetDataIndex("H:RSMainThread::OnVsync"), + stream_.traceDataCache_->GetDataIndex("H:RSMainThread::DoComposition"), + stream_.traceDataCache_->GetDataIndex("H:ProcessDisplayRenderNode[0](0,0,0,0)"), + stream_.traceDataCache_->GetDataIndex("H:RSUniRender::Process:[leashWindow25] (0, 0, 1344, 2772) Alpha: 1.00"), + stream_.traceDataCache_->GetDataIndex("H:RSUniRender::Process:[taobao0] (0, 0, 1344, 2772) Alpha: 1.00"), + }; + std::vector funcPrefixs{ + "H:RSUniRender::Process:[leashWindow25]", + "H:RSUniRender::Process:[taobao0]", + }; + // invalid depth + uint8_t depth = 1; + for (size_t i = 0; i < callStackNames.size() - 1; i++) { + std::optional parentId = 0; + callStackSlice->AppendInternalSlice(INVALID_TIME, INVALID_TIME, INVALID_UINT32, INVALID_UINT64, INVALID_UINT16, + callStackNames[i], depth, parentId); + point.funcPrefix_ = funcPrefixs[1]; + auto res = stream_.streamFilters_->animationFilter_->BeginDynamicFrameEvent(point, CALLSTACK_SLICE_ID); + EXPECT_FALSE(res); + depth++; + } + // invalid parentId + depth = 4; + for (size_t i = 0; i < callStackNames.size() - 1; i++) { + std::optional parentId; + auto callStackId = + callStackSlice->AppendInternalSlice(INVALID_TIME, INVALID_TIME, INVALID_UINT32, INVALID_UINT64, + INVALID_UINT16, callStackNames[i], depth, parentId); + point.funcPrefix_ = funcPrefixs[1]; + auto res = stream_.streamFilters_->animationFilter_->BeginDynamicFrameEvent(point, callStackId); + EXPECT_FALSE(res); + } + callStackSlice->Clear(); + callStackSlice->parentIds_.clear(); + // the current or the parent callStackNames haven't leashWindow + uint64_t index = INVALID_UINT64; + for (size_t i = 0; i < callStackNames.size(); i++) { + std::optional parentId; + if (index != INVALID_UINT64) { + parentId = index; + } + depth = i + 1; + index = callStackSlice->AppendInternalSlice(INVALID_TIME, INVALID_TIME, INVALID_UINT32, INVALID_UINT64, + INVALID_UINT16, callStackNames[i], depth, parentId); + } + point.funcPrefix_ = funcPrefixs[0]; + auto curStackRow = 2; + auto res = stream_.streamFilters_->animationFilter_->BeginDynamicFrameEvent(point, curStackRow); + EXPECT_FALSE(res); + // valid callStack + point.funcPrefix_ = funcPrefixs[1]; + curStackRow = 4; + res = stream_.streamFilters_->animationFilter_->BeginDynamicFrameEvent(point, curStackRow - 1); + EXPECT_TRUE(res); + res = stream_.streamFilters_->animationFilter_->BeginDynamicFrameEvent(point, curStackRow); + EXPECT_TRUE(res); +} + +/** + * @tc.name: UpdateDevicePos + * @tc.desc: update device pos + * @tc.type: FUNC + */ +HWTEST_F(AnimationFilterTest, UpdateDevicePos, TestSize.Level1) +{ + TS_LOGI("test36-3"); + TracePoint point; + BytraceLine line; + + std::string validFuncPrefix{"H:RSUniRender::Process:[EntryView]"}; + + std::vector invalidFuncArgs{ + "()", + "(1,)", + "[1,2]", + }; + stream_.traceDataCache_->GetDeviceInfo()->Clear(); + for (size_t i = 0; i < invalidFuncArgs.size(); i++) { + point.funcPrefix_ = validFuncPrefix; + point.funcArgs_ = invalidFuncArgs[i]; + point.name_ = point.funcPrefix_ + " " + point.funcArgs_; + point.funcPrefixId_ = stream_.traceDataCache_->GetDataIndex(point.funcPrefix_); + auto res = stream_.streamFilters_->animationFilter_->UpdateDeviceInfoEvent(point, line); + EXPECT_FALSE(res); + } +} +/** + * @tc.name: UpdateDeviceFps + * @tc.desc: update device fps + * @tc.type: FUNC + */ +HWTEST_F(AnimationFilterTest, UpdateDeviceFps, TestSize.Level1) +{ + TS_LOGI("test36-3"); + TracePoint point; + BytraceLine line; + + std::string validName{"H:GenerateVsyncCount:1"}; + auto timeDiffFps60 = (1000 * ONE_MILLION_NANOSECONDS) / FPS_60; + line.ts = 59557002299000; + for (size_t i = 0; i < GENERATE_VSYNC_EVENT_MAX; i++) { + point.name_ = validName; + point.funcPrefixId_ = stream_.traceDataCache_->GetDataIndex(point.name_); + line.ts += timeDiffFps60; + auto res = stream_.streamFilters_->animationFilter_->UpdateDeviceInfoEvent(point, line); + EXPECT_TRUE(res); + } + auto fps = stream_.traceDataCache_->GetDeviceInfo()->PhysicalFrameRate(); + EXPECT_EQ(fps, FPS_60); + + stream_.traceDataCache_->GetDeviceInfo()->Clear(); + stream_.streamFilters_->animationFilter_->Clear(); + auto timeDiffFps90 = (1000 * ONE_MILLION_NANOSECONDS) / FPS_90; + for (size_t i = 0; i < GENERATE_VSYNC_EVENT_MAX; i++) { + point.name_ = validName; + point.funcPrefixId_ = stream_.traceDataCache_->GetDataIndex(point.name_); + line.ts += timeDiffFps90; + auto res = stream_.streamFilters_->animationFilter_->UpdateDeviceInfoEvent(point, line); + EXPECT_TRUE(res); + } + fps = stream_.traceDataCache_->GetDeviceInfo()->PhysicalFrameRate(); + EXPECT_EQ(fps, FPS_90); + + stream_.traceDataCache_->GetDeviceInfo()->Clear(); + stream_.streamFilters_->animationFilter_->Clear(); + auto timeDiffFps120 = (1000 * ONE_MILLION_NANOSECONDS) / FPS_120; + for (size_t i = 0; i < GENERATE_VSYNC_EVENT_MAX; i++) { + point.name_ = validName; + point.funcPrefixId_ = stream_.traceDataCache_->GetDataIndex(point.name_); + line.ts += timeDiffFps120; + auto res = stream_.streamFilters_->animationFilter_->UpdateDeviceInfoEvent(point, line); + EXPECT_TRUE(res); + } + fps = stream_.traceDataCache_->GetDeviceInfo()->PhysicalFrameRate(); + EXPECT_EQ(fps, FPS_120); +} +/** + * @tc.name: UpdateDynamicFrameInfo + * @tc.desc: update Dynamic Frame pos and endTime + * @tc.type: FUNC + */ +HWTEST_F(AnimationFilterTest, UpdateDynamicFrameInfo, TestSize.Level1) +{ + TS_LOGI("test36-4"); + TracePoint point; + + CallStack* callStackSlice = stream_.traceDataCache_->GetInternalSlicesData(); + std::vector callStackNames{ + stream_.traceDataCache_->GetDataIndex("H:RSMainThread::OnVsync"), + stream_.traceDataCache_->GetDataIndex("H:RSMainThread::DoComposition"), + stream_.traceDataCache_->GetDataIndex("H:ProcessDisplayRenderNode[0](0,0,0,0)"), + stream_.traceDataCache_->GetDataIndex("H:RSUniRender::Process:[leashWindow25] (0, 0, 1344, 2772) Alpha: 1.00"), + stream_.traceDataCache_->GetDataIndex("H:RSUniRender::Process:[xxx] (0, 0, 1344, 2772) Alpha: 1.00"), + }; + std::string funcPrefix("H:RSUniRender::Process:[xxx]"); + uint8_t depth = 1; + uint64_t index = INVALID_UINT64; + uint64_t startTime = 59557002299000; + uint64_t dur = ONE_MILLION_NANOSECONDS; + for (size_t i = 0; i < callStackNames.size(); i++) { + std::optional parentId; + if (index != INVALID_UINT64) { + parentId = index; + } + depth = i + 1; + index = callStackSlice->AppendInternalSlice(startTime, dur, INVALID_UINT32, INVALID_UINT64, INVALID_UINT16, + callStackNames[i], depth, parentId); + } + point.funcPrefix_ = funcPrefix; + auto res = stream_.streamFilters_->animationFilter_->BeginDynamicFrameEvent(point, index - 1); // for leashWindow + EXPECT_TRUE(res); + res = stream_.streamFilters_->animationFilter_->BeginDynamicFrameEvent(point, index); // for xxx + EXPECT_TRUE(res); + stream_.streamFilters_->animationFilter_->UpdateDynamicFrameInfo(); + for (size_t i = 0; i < stream_.traceDataCache_->GetDynamicFrame()->Size(); i++) { + EXPECT_TRUE(stream_.traceDataCache_->GetDynamicFrame()->EndTimes()[i] != INVALID_TIME); + EXPECT_TRUE(stream_.traceDataCache_->GetDynamicFrame()->Xs()[i] != INVALID_UINT32); + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/test/unittest/app_start_filter_test.cpp b/trace_streamer/test/unittest/app_start_filter_test.cpp new file mode 100755 index 000000000..c7d7679e4 --- /dev/null +++ b/trace_streamer/test/unittest/app_start_filter_test.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "app_start_filter.h" +#include "slice_filter.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class AppStartFilterTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + void TearDown() {} + +public: + TraceStreamerSelector stream_ = {}; +}; + +/** + * @tc.name: ProcessCreateTest + * @tc.desc: Process Create TEST + * @tc.type: FUNC + */ +HWTEST_F(AppStartFilterTest, ProcessCreateTest, TestSize.Level1) +{ + TS_LOGI("test40-1"); + + const std::string parent_str = "H:virtual int OHOS::AAFwk::AbilityManagerService::StartAbility(" + "const OHOS::AAFwk::Want &, const sptr &, int32_t, int)"; + const std::string process_create_str = "H:int OHOS::AAFwk::MissionListManager::StartAbilityLocked(" + "const std::shared_ptr &, const std::shared_ptr &, " + "const OHOS::AAFwk::AbilityRequest &)##com.ohos.smartperf##MainAbility"; + uint64_t ts1 = 168758662957000; + uint64_t ts2 = 168758663011000; + uint64_t ts3 = 168758663057000; + uint64_t ts4 = 168758663111000; + uint32_t pid1 = 1655; + uint32_t threadGroupId1 = 1127; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); + DataIndex parent_splitStrIndex = stream_.traceDataCache_->GetDataIndex(parent_str.c_str()); + DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex(process_create_str.c_str()); + + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts1, pid1, threadGroupId1, cat, parent_splitStrIndex); + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts2, pid1, threadGroupId1, cat, splitStrIndex); + stream_.streamFilters_->sliceFilter_->EndSlice(ts3, pid1, threadGroupId1); + stream_.streamFilters_->sliceFilter_->EndSlice(ts4, pid1, threadGroupId1); + + stream_.streamFilters_->appStartupFilter_->FilterAllAPPStartupData(); + + auto dataIndex = stream_.traceDataCache_->GetDataIndex("com.ohos.smartperf"); + EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.size() == 1); + EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.find(dataIndex) != nullptr); +} + +/** + * @tc.name: AppLunchTest + * @tc.desc: App Lunch TEST + * @tc.type: FUNC + */ +HWTEST_F(AppStartFilterTest, AppLunchTest, TestSize.Level1) +{ + TS_LOGI("test40-2"); + + const std::string process_create_str = "H:virtual void OHOS::AppExecFwk::AppMgrServiceInner::AttachApplication(" + "const pid_t, const sptr &)##com.ohos.smartperf"; + uint64_t ts1 = 168758662957000; + uint64_t ts2 = 168758663011000; + uint32_t pid1 = 1655; + uint32_t threadGroupId1 = 1127; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); + DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex(process_create_str.c_str()); + + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts1, pid1, threadGroupId1, cat, splitStrIndex); + stream_.streamFilters_->sliceFilter_->EndSlice(ts2, pid1, threadGroupId1); + + stream_.streamFilters_->appStartupFilter_->FilterAllAPPStartupData(); + + auto dataIndex = stream_.traceDataCache_->GetDataIndex("com.ohos.smartperf"); + EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.size() == 1); + EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.find(dataIndex) != nullptr); +} + +/** + * @tc.name: LunchTest + * @tc.desc: Lunch TEST + * @tc.type: FUNC + */ +HWTEST_F(AppStartFilterTest, LunchTest, TestSize.Level1) +{ + TS_LOGI("test40-3"); + + const std::string process_create_str = "H:void OHOS::AppExecFwk::MainThread::HandleLaunchAbility(" + "const std::shared_ptr &)##com.ohos.smartperf"; + uint64_t ts1 = 168758662957000; + uint64_t ts2 = 168758663011000; + uint32_t pid1 = 1655; + uint32_t threadGroupId1 = 1127; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); + DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex(process_create_str.c_str()); + + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts1, pid1, threadGroupId1, cat, splitStrIndex); + stream_.streamFilters_->sliceFilter_->EndSlice(ts2, pid1, threadGroupId1); + + stream_.streamFilters_->appStartupFilter_->FilterAllAPPStartupData(); + + auto dataIndex = stream_.traceDataCache_->GetDataIndex("com.ohos.smartperf"); + EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.size() == 1); + EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.find(dataIndex) != nullptr); +} + +/** + * @tc.name: OnforegroundTest + * @tc.desc: Onforeground TEST + * @tc.type: FUNC + */ +HWTEST_F(AppStartFilterTest, OnforegroundTest, TestSize.Level1) +{ + TS_LOGI("test40-4"); + + const std::string process_create_str = "H:void OHOS::AppExecFwk::AbilityThread::HandleAbilityTransaction(" + "const OHOS::AppExecFwk::Want &, const OHOS::AppExecFwk::LifeCycleStateInfo &, sptr)##"; + uint64_t ts1 = 168758662957000; + uint64_t ts2 = 168758663011000; + uint32_t pid1 = 1655; + uint32_t threadGroupId1 = 1127; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); + DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex(process_create_str.c_str()); + + stream_.streamFilters_->sliceFilter_->BeginSlice(".ohos.smartperf", ts1, pid1, threadGroupId1, cat, splitStrIndex); + stream_.streamFilters_->sliceFilter_->EndSlice(ts2, pid1, threadGroupId1); + + stream_.streamFilters_->appStartupFilter_->FilterAllAPPStartupData(); + + auto dataIndex = stream_.traceDataCache_->GetDataIndex(".ohos.smartperf"); + EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.size() == 1); + EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.find(dataIndex) != nullptr); +} + +/** + * @tc.name: SoInitalizationTest + * @tc.desc: SoInitalization TEST + * @tc.type: FUNC + */ +HWTEST_F(AppStartFilterTest, SoInitalizationTest, TestSize.Level1) +{ + TS_LOGI("test40-5"); + + const std::string process_create_str = "dlopen: /system/lib64/libcpudataplugin.z.so"; + uint64_t ts1 = 168758614489000; + uint64_t ts2 = 168758663011000; + uint32_t pid1 = 2235; + uint32_t threadGroupId1 = 2221; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); + DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex(process_create_str.c_str()); + + stream_.streamFilters_->sliceFilter_->BeginSlice("UnixSocketRecv", ts1, pid1, threadGroupId1, cat, splitStrIndex); + stream_.streamFilters_->sliceFilter_->EndSlice(ts2, pid1, threadGroupId1); + stream_.streamFilters_->appStartupFilter_->FilterAllAPPStartupData(); + + EXPECT_TRUE(stream_.traceDataCache_->GetConstStaticInitalizationData().Size() == 1); +} + +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/test/unittest/task_pool_filter_test.cpp b/trace_streamer/test/unittest/task_pool_filter_test.cpp new file mode 100644 index 000000000..f9da3ffe0 --- /dev/null +++ b/trace_streamer/test/unittest/task_pool_filter_test.cpp @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "task_pool_filter.h" +#include "trace_streamer_filters.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class TaskPoolFilterTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + void TearDown() {} + +public: + TraceStreamerSelector stream_ = {}; +}; + +/** + * @tc.name: CheckTheSameTaskTest + * @tc.desc: CheckTheSameTask function Test + * @tc.type: FUNC + */ +HWTEST_F(TaskPoolFilterTest, CheckTheSameTaskTest, TestSize.Level1) +{ + TS_LOGI("test37-1"); + std::unordered_map executeMap; + int32_t executeId = 0; + uint32_t res = stream_.streamFilters_->taskPoolFilter_->CheckTheSameTask(executeId); + EXPECT_EQ(res, INVALID_INT32); + +} + +/** + * @tc.name: TaskPoolEventTest1 + * @tc.desc: TaskPoolEvent function Test + * @tc.type: FUNC + */ +HWTEST_F(TaskPoolFilterTest, TaskPoolEventTest1, TestSize.Level1) +{ + TS_LOGI("test37-2"); + std::string taskPoolStr = "H:Task Allocation: taskId : 1, executeId : 1, priority : 1, executeState : 1"; + int32_t index = 1; + stream_.streamFilters_->taskPoolFilter_->TaskPoolEvent(taskPoolStr, index); + auto res = stream_.traceDataCache_->GetTaskPoolData()->allocationTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeTaskIds_[0]; + EXPECT_EQ(res, INVALID_INT32); + res = stream_.traceDataCache_->GetTaskPoolData()->returnTaskIds_[0]; + EXPECT_EQ(res, INVALID_INT32); + res = stream_.traceDataCache_->GetTaskPoolData()->executeIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->prioritys_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeStates_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->returnStates_[0]; + EXPECT_EQ(res, INVALID_INT32); + + taskPoolStr = "H:Task Perform: taskId : 1, executeId : 1"; + index = 1; + stream_.streamFilters_->taskPoolFilter_->TaskPoolEvent(taskPoolStr, index); + res = stream_.traceDataCache_->GetTaskPoolData()->allocationTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->returnTaskIds_[0]; + EXPECT_EQ(res, INVALID_INT32); + res = stream_.traceDataCache_->GetTaskPoolData()->executeIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->prioritys_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeStates_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->returnStates_[0]; + EXPECT_EQ(res, INVALID_INT32); + + taskPoolStr = "H:Task PerformTask End: taskId : 1, executeId : 1, performResult : IsCanceled"; + index = 1; + stream_.streamFilters_->taskPoolFilter_->TaskPoolEvent(taskPoolStr, index); + res = stream_.traceDataCache_->GetTaskPoolData()->allocationTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->returnTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->prioritys_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeStates_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->returnStates_[0]; + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: TaskPoolEventTest2 + * @tc.desc: TaskPoolEvent function Test + * @tc.type: FUNC + */ +HWTEST_F(TaskPoolFilterTest, TaskPoolEventTest2, TestSize.Level1) +{ + TS_LOGI("test37-3"); + std::string taskPoolStr = "H:Task Perform: taskId : 1, executeId : 1"; + int32_t index = 1; + stream_.streamFilters_->taskPoolFilter_->TaskPoolEvent(taskPoolStr, index); + auto res = stream_.traceDataCache_->GetTaskPoolData()->allocationTaskIds_[0]; + EXPECT_EQ(res, INVALID_INT32); + res = stream_.traceDataCache_->GetTaskPoolData()->executeTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->returnTaskIds_[0]; + EXPECT_EQ(res, INVALID_INT32); + res = stream_.traceDataCache_->GetTaskPoolData()->executeIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->prioritys_[0]; + EXPECT_EQ(res, INVALID_INT32); + res = stream_.traceDataCache_->GetTaskPoolData()->executeStates_[0]; + EXPECT_EQ(res, INVALID_INT32); + res = stream_.traceDataCache_->GetTaskPoolData()->returnStates_[0]; + EXPECT_EQ(res, INVALID_INT32); + + taskPoolStr = "H:Task Allocation: taskId : 1, executeId : 1, priority : 1, executeState : 1"; + index = 1; + stream_.streamFilters_->taskPoolFilter_->TaskPoolEvent(taskPoolStr, index); + res = stream_.traceDataCache_->GetTaskPoolData()->allocationTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->returnTaskIds_[0]; + EXPECT_EQ(res, INVALID_INT32); + res = stream_.traceDataCache_->GetTaskPoolData()->executeIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->prioritys_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeStates_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->returnStates_[0]; + EXPECT_EQ(res, INVALID_INT32); + + taskPoolStr = "H:Task PerformTask End: taskId : 1, executeId : 1, performResult : IsCanceled"; + index = 1; + stream_.streamFilters_->taskPoolFilter_->TaskPoolEvent(taskPoolStr, index); + res = stream_.traceDataCache_->GetTaskPoolData()->allocationTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->returnTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->prioritys_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeStates_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->returnStates_[0]; + EXPECT_EQ(res, 0); +} + +/** + * @tc.name: TaskPoolEventTest3 + * @tc.desc: TaskPoolEvent function Test + * @tc.type: FUNC + */ +HWTEST_F(TaskPoolFilterTest, TaskPoolEventTest3, TestSize.Level1) +{ + TS_LOGI("test37-4"); + std::string taskPoolStr = "H:Task PerformTask End: taskId : 1, executeId : 1, performResult : Successful"; + int32_t index = 1; + stream_.streamFilters_->taskPoolFilter_->TaskPoolEvent(taskPoolStr, index); + auto res = stream_.traceDataCache_->GetTaskPoolData()->allocationTaskIds_[0]; + EXPECT_EQ(res, INVALID_INT32); + res = stream_.traceDataCache_->GetTaskPoolData()->executeTaskIds_[0]; + EXPECT_EQ(res, INVALID_INT32); + res = stream_.traceDataCache_->GetTaskPoolData()->returnTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->prioritys_[0]; + EXPECT_EQ(res, INVALID_INT32); + res = stream_.traceDataCache_->GetTaskPoolData()->executeStates_[0]; + EXPECT_EQ(res, INVALID_INT32); + res = stream_.traceDataCache_->GetTaskPoolData()->returnStates_[0]; + EXPECT_EQ(res, 1); + + taskPoolStr = "H:Task Allocation: taskId : 1, executeId : 1, priority : 1, executeState : 1"; + index = 1; + stream_.streamFilters_->taskPoolFilter_->TaskPoolEvent(taskPoolStr, index); + res = stream_.traceDataCache_->GetTaskPoolData()->allocationTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeTaskIds_[0]; + EXPECT_EQ(res, INVALID_INT32); + res = stream_.traceDataCache_->GetTaskPoolData()->returnTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->prioritys_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeStates_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->returnStates_[0]; + EXPECT_EQ(res, 1); + + taskPoolStr = "H:Task Perform: taskId : 1, executeId : 1"; + index = 1; + stream_.streamFilters_->taskPoolFilter_->TaskPoolEvent(taskPoolStr, index); + res = stream_.traceDataCache_->GetTaskPoolData()->allocationTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->returnTaskIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeIds_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->prioritys_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->executeStates_[0]; + EXPECT_EQ(res, 1); + res = stream_.traceDataCache_->GetTaskPoolData()->returnStates_[0]; + EXPECT_EQ(res, 1); +} +} // namespace TraceStreamer +} // namespace SysTuning -- Gitee From 628b21f0fb94d6d7b1d4f302a3d6c3ffebd7036e Mon Sep 17 00:00:00 2001 From: jichuan Date: Thu, 27 Jul 2023 15:02:11 +0800 Subject: [PATCH 06/14] =?UTF-8?q?Feat:=E5=8A=A8=E6=95=88=E5=88=86=E6=9E=90?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: jichuan --- ide/src/base-ui/table/lit-table.ts | 4 +- ide/src/base-ui/utils/CSVFormater.ts | 110 ++- ide/src/trace/bean/BoxSelection.ts | 6 + ide/src/trace/bean/FrameComponentBean.ts | 39 + ide/src/trace/component/SpFlags.ts | 13 +- ide/src/trace/component/SpSystemTrace.ts | 59 +- .../trace/component/chart/SpChartManager.ts | 2 +- .../trace/component/chart/SpFrameTimeChart.ts | 724 +++++++++++++----- .../trace/component/chart/SpProcessChart.ts | 32 +- .../component/setting/SpRecordTemplate.ts | 18 +- .../trace/component/trace/base/ColorUtils.ts | 16 +- .../trace/component/trace/base/TraceRow.ts | 17 + .../trace/component/trace/base/TraceSheet.ts | 16 + .../component/trace/base/TraceSheetConfig.ts | 18 + .../trace/sheet/TabPaneCurrentSelection.ts | 26 +- .../trace/sheet/frame/TabFrameSpacing.ts | 184 +++++ .../sheet/frame/TabPaneFrameAnimation.ts | 127 +++ .../trace/sheet/frame/TabPaneFrameDynamic.ts | 137 ++++ .../trace/sheet/task/TabPaneTaskFrames.ts | 11 +- ide/src/trace/database/SqlLite.ts | 114 ++- .../database/ui-worker/ProcedureWorker.ts | 6 + .../ui-worker/ProcedureWorkerAppStartup.ts | 6 +- .../ui-worker/ProcedureWorkerCommon.ts | 4 +- .../ProcedureWorkerFrameAnimation.ts | 183 +++++ .../ui-worker/ProcedureWorkerFrameDynamic.ts | 354 +++++++++ .../ui-worker/ProcedureWorkerFrameSpacing.ts | 385 ++++++++++ 26 files changed, 2338 insertions(+), 273 deletions(-) create mode 100644 ide/src/trace/bean/FrameComponentBean.ts create mode 100644 ide/src/trace/component/trace/sheet/frame/TabFrameSpacing.ts create mode 100644 ide/src/trace/component/trace/sheet/frame/TabPaneFrameAnimation.ts create mode 100644 ide/src/trace/component/trace/sheet/frame/TabPaneFrameDynamic.ts create mode 100644 ide/src/trace/database/ui-worker/ProcedureWorkerFrameAnimation.ts create mode 100644 ide/src/trace/database/ui-worker/ProcedureWorkerFrameDynamic.ts create mode 100644 ide/src/trace/database/ui-worker/ProcedureWorkerFrameSpacing.ts diff --git a/ide/src/base-ui/table/lit-table.ts b/ide/src/base-ui/table/lit-table.ts index 27f974ea1..5c27a75a6 100644 --- a/ide/src/base-ui/table/lit-table.ts +++ b/ide/src/base-ui/table/lit-table.ts @@ -19,7 +19,7 @@ import { element } from '../BaseElement.js'; import '../utils/Template.js'; import { TableRowObject } from './TableRowObject.js'; import { ExcelFormater } from '../utils/ExcelFormater.js'; -import { JSonToCSV } from '../utils/CSVFormater.js'; +import { JSONToCSV } from '../utils/CSVFormater.js'; import { NodeType } from '../../js-heap/model/DatabaseStruct.js'; import { ConstructorType } from '../../js-heap/model/UiStruct.js'; @@ -370,7 +370,7 @@ export class LitTable extends HTMLElement { this.exportLoading = true; this.exportProgress!.loading = true; let date = new Date(); - JSonToCSV.csvExport({ + JSONToCSV.csvExport({ columns: this.columns as any[], tables: this.ds, fileName: date.getTime() + '', diff --git a/ide/src/base-ui/utils/CSVFormater.ts b/ide/src/base-ui/utils/CSVFormater.ts index 6cae263bb..71fa3e57d 100644 --- a/ide/src/base-ui/utils/CSVFormater.ts +++ b/ide/src/base-ui/utils/CSVFormater.ts @@ -13,25 +13,23 @@ * limitations under the License. */ -export class JSonToCSV { - static setDataConver(obj: any) { +export class JSONToCSV { + static setCsvData(obj: any) { let that = this; - let bw = this.browser(); - if (bw['ie'] < 9) return; - let data = obj['data'], - Show = typeof obj['showLabel'] === 'undefined' ? true : obj['showLabel'], - fileName = (obj['fileName'] || 'UserExport') + '.csv', - columns = obj['columns'] || { - title: [], - key: [], - formatter: undefined, - }; - let ShowLabel = typeof Show === 'undefined' ? true : Show; - let row = '', - CSV = '', - key; + let browserType = this.browserType(); + if (browserType['ie'] < 9) return; + let data = obj['data']; + let isShowLabel = typeof obj['showLabel'] === 'undefined' ? true : obj['showLabel']; + let fileName = (obj['fileName'] || 'UserExport') + '.csv'; + let columns = obj['columns'] || { + title: [], + key: [], + formatter: undefined, + }; + let showLabel = typeof isShowLabel === 'undefined' ? true : isShowLabel; + let row = '', csv = '', key; // 如果要现实表头文字 - if (ShowLabel) { + if (showLabel) { // 如果有传入自定义的表头文字 if (columns.title.length) { columns.title.map(function (n: any) { @@ -42,7 +40,7 @@ export class JSonToCSV { for (key in data[0]) row += key + ','; } row = row.slice(0, -1); - CSV += row + '\r\n'; + csv += row + '\r\n'; } // 具体的数据处理 data.map(function (n: any) { @@ -75,29 +73,27 @@ export class JSonToCSV { } } row.slice(0, row.length - 1); // 删除最后一个, - CSV += row + '\r\n'; // 添加换行符号 + csv += row + '\r\n'; // 添加换行符号 }); - if (!CSV) return; - this.SaveAs(fileName, CSV); + if (!csv) return; + this.saveCsvFile(fileName, csv); } - static SaveAs(fileName: any, csvData: any) { - let bw: any = this.browser(); - if (!bw['edge'] || !bw['ie']) { + static saveCsvFile(fileName: any, csvData: any) { + let browserType: any = this.browserType(); + if (!browserType['edge'] || !browserType['ie']) { let alink: any = document.createElement('a'); - alink.id = 'linkDwnldLink'; + alink.id = 'csvDownloadLink'; alink.href = this.getDownloadUrl(csvData); document.body.appendChild(alink); - let linkDom: any = document.getElementById('linkDwnldLink'); + let linkDom: any = document.getElementById('csvDownloadLink'); linkDom.setAttribute('download', fileName); linkDom.click(); document.body.removeChild(linkDom); - } else if (bw['ie'] >= 10 || bw['edge'] == 'edge') { - let _utf = '\uFEFF'; - let _csvData = new Blob([_utf + csvData], { + } else if (browserType['ie'] >= 10 || browserType['edge'] == 'edge') { + (navigator as any).msSaveBlob(new Blob(['\uFEFF' + csvData], { type: 'text/csv', - }); - (navigator as any).msSaveBlob(_csvData, fileName); + }), fileName); } else { let oWin: any = window.top?.open('about:blank', '_blank'); oWin.document.write('sep=,\r\n' + csvData); @@ -108,33 +104,31 @@ export class JSonToCSV { } static getDownloadUrl(csvData: any) { - let _utf = '\uFEFF'; if (window.Blob && window.URL && (window.URL as any).createObjectURL) { - var csvData: any = new Blob([_utf + csvData], { + return URL.createObjectURL(new Blob(['\uFEFF' + csvData], { type: 'text/csv', - }); - return URL.createObjectURL(csvData); + })); } } - static browser() { - let Sys: any = {}; - let ua = navigator.userAgent.toLowerCase(); - let s; - (s = ua.indexOf('edge') !== -1 ? (Sys.edge = 'edge') : ua.match(/rv:([\d.]+)\) like gecko/)) - ? (Sys.ie = s[1]) - : (s = ua.match(/msie ([\d.]+)/)) - ? (Sys.ie = s[1]) - : (s = ua.match(/firefox\/([\d.]+)/)) - ? (Sys.firefox = s[1]) - : (s = ua.match(/chrome\/([\d.]+)/)) - ? (Sys.chrome = s[1]) - : (s = ua.match(/opera.([\d.]+)/)) - ? (Sys.opera = s[1]) - : (s = ua.match(/version\/([\d.]+).*safari/)) - ? (Sys.safari = s[1]) - : 0; - return Sys; + static browserType() { + let type: any = {}; + let agent = navigator.userAgent.toLowerCase(); + let has; + (has = agent.indexOf('edge') !== -1 ? (type.edge = 'edge') : agent.match(/rv:([\d.]+)\) like gecko/)) + ? (type.ie = has[1]) + : (has = agent.match(/msie ([\d.]+)/)) + ? (type.ie = has[1]) + : (has = agent.match(/firefox\/([\d.]+)/)) + ? (type.firefox = has[1]) + : (has = agent.match(/chrome\/([\d.]+)/)) + ? (type.chrome = has[1]) + : (has = agent.match(/opera.([\d.]+)/)) + ? (type.opera = has[1]) + : (has = agent.match(/version\/([\d.]+).*safari/)) + ? (type.safari = has[1]) + : 0; + return type; } static treeDepth(depth: number) { @@ -150,7 +144,7 @@ export class JSonToCSV { data.forEach((item: any) => { let depthCSV = 0; const loop = (data: any, depth: any) => { - result.push({ depthCSV: depth, ...data }); + result.push({depthCSV: depth, ...data}); let child = data.children; if (child) { for (let i = 0; i < child.length; i++) { @@ -163,7 +157,7 @@ export class JSonToCSV { return result; } - static columnDatas(columns: Array) { + static columnsData(columns: Array) { let titleList: Array = []; let ketList: Array = []; columns.forEach((column) => { @@ -185,9 +179,9 @@ export class JSonToCSV { static async csvExport(dataSource: { columns: any[]; tables: any[]; fileName: string }): Promise { return new Promise((resolve) => { - let data: any = this.columnDatas(dataSource.columns); - let resultArr = JSonToCSV.treeToArr(dataSource.tables); - JSonToCSV.setDataConver({ + let data: any = this.columnsData(dataSource.columns); + let resultArr = JSONToCSV.treeToArr(dataSource.tables); + JSONToCSV.setCsvData({ data: resultArr, fileName: dataSource.fileName, columns: { diff --git a/ide/src/trace/bean/BoxSelection.ts b/ide/src/trace/bean/BoxSelection.ts index 41ec197ca..142944f02 100644 --- a/ide/src/trace/bean/BoxSelection.ts +++ b/ide/src/trace/bean/BoxSelection.ts @@ -17,6 +17,9 @@ import { CpuFreqLimitsStruct } from '../database/ui-worker/ProcedureWorkerCpuFre import { ClockStruct } from '../database/ui-worker/ProcedureWorkerClock.js'; import { IrqStruct } from '../database/ui-worker/ProcedureWorkerIrq.js'; import { FuncStruct } from '../database/ui-worker/ProcedureWorkerFunc.js'; +import { FrameDynamicStruct } from '../database/ui-worker/ProcedureWorkerFrameDynamic.js'; +import { FrameAnimationStruct } from '../database/ui-worker/ProcedureWorkerFrameAnimation.js'; +import { FrameSpacingStruct } from '../database/ui-worker/ProcedureWorkerFrameSpacing.js'; export class SelectionParam { recordStartNs: number = 0; @@ -72,6 +75,9 @@ export class SelectionParam { jankFramesData: Array = []; jsMemory: Array = []; taskFramesData: Array> = []; + frameDynamic: Array = []; + frameAnimation: Array = []; + frameSpacing: Array = []; } export class BoxJumpParam { diff --git a/ide/src/trace/bean/FrameComponentBean.ts b/ide/src/trace/bean/FrameComponentBean.ts new file mode 100644 index 000000000..fdc9476b8 --- /dev/null +++ b/ide/src/trace/bean/FrameComponentBean.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. + */ + +export interface ComponentAttribute { + x: string; + y: string; + width: string; + height: string; + alpha: string; +} + +export interface AnimationRanges { + start: number; + end: number; +} + +export interface FrameAnimationSelect { + id: number | undefined; + value: number | undefined; + timestamp: string | undefined; +} + +export interface DeviceStruct { + physicalWidth: number; + physicalHeight: number; + physicalFrameRate: number; +} \ No newline at end of file diff --git a/ide/src/trace/component/SpFlags.ts b/ide/src/trace/component/SpFlags.ts index b01f16e7f..17506172a 100644 --- a/ide/src/trace/component/SpFlags.ts +++ b/ide/src/trace/component/SpFlags.ts @@ -174,7 +174,7 @@ export class SpFlags extends BaseElement { allConfig.forEach((config) => { let configDiv = this.createConfigDiv(); this.createCustomDiv(config, configDiv); - if (config.title === 'DynamicAnalysis') { + if (config.title === 'AnimationAnalysis') { let configFooterDiv = document.createElement('div'); configFooterDiv.className = 'config_footer'; let deviceWidthLabelEl = document.createElement('label'); @@ -228,6 +228,17 @@ export class FlagsConfig { switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }], describeContent: 'Analyze TaskPool templates', }, + { + title: 'AnimationAnalysis', + switchOptions: [{option: 'Enabled'}, {option: 'Disabled', selected: true}], + describeContent: 'Analyze Animation effect templates', + addInfo: {physicalWidth: 0, physicalHeight: 0} + }, + { + title: 'AppStartup', + switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }], + describeContent: 'App Startup templates', + }, ]; static getAllFlagConfig(): Array { diff --git a/ide/src/trace/component/SpSystemTrace.ts b/ide/src/trace/component/SpSystemTrace.ts index d6122bc04..c5bb73637 100644 --- a/ide/src/trace/component/SpSystemTrace.ts +++ b/ide/src/trace/component/SpSystemTrace.ts @@ -90,6 +90,9 @@ import { AppStartupStruct } from '../database/ui-worker/ProcedureWorkerAppStartu import { SoStruct } from '../database/ui-worker/ProcedureWorkerSoInit.js'; import { TabPaneTaskFrames } from './trace/sheet/task/TabPaneTaskFrames.js'; import { FlagsConfig } from './SpFlags.js'; +import { FrameDynamicStruct } from '../database/ui-worker/ProcedureWorkerFrameDynamic.js'; +import { FrameAnimationStruct } from '../database/ui-worker/ProcedureWorkerFrameAnimation.js'; +import { FrameSpacingStruct } from '../database/ui-worker/ProcedureWorkerFrameSpacing.js'; function dpr() { return window.devicePixelRatio || 1; @@ -152,7 +155,7 @@ export class SpSystemTrace extends BaseElement { public timerShaftEL: TimerShaftElement | null | undefined; private traceSheetEL: TraceSheet | undefined | null; private rangeSelect!: RangeSelect; - private chartManager: SpChartManager | undefined | null; + chartManager: SpChartManager | undefined | null; private loadTraceCompleted: boolean = false; private rangeTraceRow: Array> | undefined = []; canvasFavoritePanel: HTMLCanvasElement | null | undefined; //绘制收藏泳道图 @@ -824,6 +827,30 @@ export class SpSystemTrace extends BaseElement { ?.querySelector('#box-heap-summary') ?.querySelector('tabpane-summary') as TabPaneSummary; summary.initSummaryData(SpJsMemoryChart.file, minNodeId, maxNodeId); + } else if (it.rowType == TraceRow.ROW_TYPE_FRAME_ANIMATION) { + let isIntersect = (animationStruct: FrameAnimationStruct, selectStruct: RangeSelectStruct) => + Math.max(animationStruct.ts! + animationStruct.dur!, selectStruct!.endNS || 0) + - Math.min(animationStruct.ts!, selectStruct!.startNS || 0) < animationStruct.dur! + (selectStruct! + .endNS || 0) - (selectStruct!.startNS || 0); + let frameAnimationList = it.dataList.filter((frameAnimationBean: FrameAnimationStruct) => { + return isIntersect(frameAnimationBean, TraceRow.rangeSelectObject!); + }); + selection.frameAnimation.push(...frameAnimationList); + } else if (it.rowType == TraceRow.ROW_TYPE_FRAME_DYNAMIC) { + let isSelect = (dynamicStruct: FrameDynamicStruct, b: RangeSelectStruct) => + (dynamicStruct.ts >= b.startNS! && dynamicStruct.ts <= b.endNS!); + let frameDynamicList = it.dataList.filter((frameAnimationBean: FrameDynamicStruct) => + isSelect(frameAnimationBean, TraceRow.rangeSelectObject!) && frameAnimationBean.groupId !== -1 + ); + selection.frameDynamic.push(...frameDynamicList); + } else if (it.rowType == TraceRow.ROW_TYPE_FRAME_SPACING) { + let isSelect = (a: FrameSpacingStruct, b: RangeSelectStruct) => + (a.currentTs >= b.startNS! && a.currentTs <= b.endNS!); + let frameDatas = it.dataList.filter((frameData: FrameSpacingStruct) => { + return isSelect(frameData, TraceRow.rangeSelectObject!) && frameData.groupId !== -1 + && frameData.frameSpacingResult !== -1; + }); + selection.frameSpacing.push(...frameDatas); } if (this.rangeTraceRow!.length !== rows.length) { let event = this.createPointEvent(it); @@ -1480,6 +1507,12 @@ export class SpSystemTrace extends BaseElement { (SoStruct.selectSoStruct.startTs || 0) + (SoStruct.selectSoStruct.dur || 0), shiftKey ); + } else if (FrameAnimationStruct.selectFrameAnimationStruct) { + this.timerShaftEL?.setSlicesMark( + FrameAnimationStruct.selectFrameAnimationStruct.ts || 0, + (FrameAnimationStruct.selectFrameAnimationStruct.ts || 0) + + (FrameAnimationStruct.selectFrameAnimationStruct.dur || 0) + ); } else { this.slicestime = this.timerShaftEL?.setSlicesMark(); } @@ -1657,6 +1690,9 @@ export class SpSystemTrace extends BaseElement { AppStartupStruct.hoverStartupStruct = undefined; SoStruct.hoverSoStruct = undefined; HeapSnapshotStruct.hoverSnapshotStruct = undefined; + FrameAnimationStruct.hoverFrameAnimationStruct = undefined; + FrameDynamicStruct.hoverFrameDynamicStruct = undefined; + FrameSpacingStruct.hoverFrameSpacingStruct = undefined; } selectStructNull() { @@ -1675,6 +1711,9 @@ export class SpSystemTrace extends BaseElement { AppStartupStruct.selectStartupStruct = undefined; SoStruct.selectSoStruct = undefined; HeapSnapshotStruct.selectSnapshotStruct = undefined; + FrameSpacingStruct.selectFrameSpacingStruct = undefined; + FrameAnimationStruct.selectFrameAnimationStruct = undefined; + FrameDynamicStruct.selectFrameDynamicStruct = undefined; } isWASDKeyPress() { @@ -1783,6 +1822,12 @@ export class SpSystemTrace extends BaseElement { TraceRow.ROW_TYPE_HEAP_SNAPSHOT, () => HeapSnapshotStruct.hoverSnapshotStruct !== null && HeapSnapshotStruct.hoverSnapshotStruct !== undefined, ], + [TraceRow.ROW_TYPE_FRAME_ANIMATION, () => FrameAnimationStruct.hoverFrameAnimationStruct !== null + && FrameAnimationStruct.hoverFrameAnimationStruct !== undefined], + [TraceRow.ROW_TYPE_FRAME_DYNAMIC, () => FrameDynamicStruct.hoverFrameDynamicStruct !== null + && FrameDynamicStruct.hoverFrameDynamicStruct !== undefined], + [TraceRow.ROW_TYPE_FRAME_SPACING, () => FrameSpacingStruct.hoverFrameSpacingStruct !== null + && FrameSpacingStruct.hoverFrameSpacingStruct !== undefined], ]); onClickHandler(clickRowType: string, row?: TraceRow) { @@ -2069,6 +2114,18 @@ export class SpSystemTrace extends BaseElement { SoStruct.selectSoStruct = SoStruct.hoverSoStruct; this.traceSheetEL?.displayStaticInitData(SoStruct.selectSoStruct, scrollToFuncHandler); this.timerShaftEL?.modifyFlagList(undefined); + } else if (clickRowType === TraceRow.ROW_TYPE_FRAME_ANIMATION && FrameAnimationStruct.hoverFrameAnimationStruct) { + FrameAnimationStruct.selectFrameAnimationStruct = FrameAnimationStruct.hoverFrameAnimationStruct; + this.traceSheetEL?.displayFrameAnimationData(FrameAnimationStruct.selectFrameAnimationStruct); + this.timerShaftEL?.modifyFlagList(undefined); + } else if (clickRowType === TraceRow.ROW_TYPE_FRAME_DYNAMIC && FrameDynamicStruct.hoverFrameDynamicStruct) { + FrameDynamicStruct.selectFrameDynamicStruct = FrameDynamicStruct.hoverFrameDynamicStruct; + this.traceSheetEL?.displayFrameDynamicData(row!, FrameDynamicStruct.selectFrameDynamicStruct); + this.timerShaftEL?.modifyFlagList(undefined); + } else if (clickRowType === TraceRow.ROW_TYPE_FRAME_SPACING && FrameSpacingStruct.hoverFrameSpacingStruct) { + FrameSpacingStruct.selectFrameSpacingStruct = FrameSpacingStruct.hoverFrameSpacingStruct; + this.traceSheetEL?.displayFrameSpacingData(FrameSpacingStruct.selectFrameSpacingStruct); + this.timerShaftEL?.modifyFlagList(undefined); } else { if (!JankStruct.hoverJankStruct && JankStruct.delJankLineFlag) { this.removeLinkLinesByBusinessType('janks'); diff --git a/ide/src/trace/component/chart/SpChartManager.ts b/ide/src/trace/component/chart/SpChartManager.ts index 6e6fa5a6c..7c157ede7 100644 --- a/ide/src/trace/component/chart/SpChartManager.ts +++ b/ide/src/trace/component/chart/SpChartManager.ts @@ -59,7 +59,7 @@ export class SpChartManager { private smapsChart: SmapsChart; private clockChart: SpClockChart; private irqChart: SpIrqChart; - private frameTimeChart: SpFrameTimeChart; + frameTimeChart: SpFrameTimeChart; private jsMemory: SpJsMemoryChart; constructor(trace: SpSystemTrace) { diff --git a/ide/src/trace/component/chart/SpFrameTimeChart.ts b/ide/src/trace/component/chart/SpFrameTimeChart.ts index 725b64abf..61824623f 100644 --- a/ide/src/trace/component/chart/SpFrameTimeChart.ts +++ b/ide/src/trace/component/chart/SpFrameTimeChart.ts @@ -17,50 +17,64 @@ import { TraceRow } from '../trace/base/TraceRow.js'; import { renders } from '../../database/ui-worker/ProcedureWorker.js'; import { JankRender, JankStruct } from '../../database/ui-worker/ProcedureWorkerJank.js'; import { SpSystemTrace } from '../SpSystemTrace.js'; -import { queryActualFrameDate, queryExpectedFrameDate, queryFrameTimeData } from '../../database/SqlLite.js'; +import { + queryActualFrameDate, + queryExpectedFrameDate, + queryFrameAnimationData, queryFrameApp, queryFrameDynamicData, queryFrameSpacing, + queryFrameTimeData, queryPhysicalData +} from '../../database/SqlLite.js'; import { JanksStruct } from '../../bean/JanksStruct.js'; -import { ns2xByTimeShaft } from '../../database/ui-worker/ProcedureWorkerCommon.js'; +import { ns2xByTimeShaft, PairPoint } from '../../database/ui-worker/ProcedureWorkerCommon.js'; +import { LitPopover } from '../../../base-ui/popover/LitPopoverV.js'; +import { FrameDynamicRender, FrameDynamicStruct } from '../../database/ui-worker/ProcedureWorkerFrameDynamic.js'; +import { FrameAnimationRender, FrameAnimationStruct } from '../../database/ui-worker/ProcedureWorkerFrameAnimation.js'; +import { BaseStruct } from '../../bean/BaseStruct.js'; +import { FrameSpacingRender, FrameSpacingStruct } from '../../database/ui-worker/ProcedureWorkerFrameSpacing.js'; +import { FlagsConfig, Params } from '../SpFlags.js'; +import { AnimationRanges, DeviceStruct } from '../../bean/FrameComponentBean.js'; export class SpFrameTimeChart { private trace: SpSystemTrace; + private flagConfig: Params | undefined; constructor(trace: SpSystemTrace) { this.trace = trace; } - async init() { + async init(): Promise { let frameTimeData = await queryFrameTimeData(); if (frameTimeData.length > 0) { - let frameTimeLineRow = await this.initFrameTimeLine(); + let frameTimeLineRow: TraceRow = await this.initFrameTimeLine(); await this.initExpectedChart(frameTimeLineRow); await this.initActualChart(frameTimeLineRow); } } - async initFrameTimeLine() { - let frameTimeLineRow = TraceRow.skeleton(); - frameTimeLineRow.rowId = `frameTime`; + async initFrameTimeLine(): Promise> { + let frameTimeLineRow: TraceRow = TraceRow.skeleton(); + frameTimeLineRow.rowId = 'frameTime'; frameTimeLineRow.rowType = TraceRow.ROW_TYPE_JANK; - frameTimeLineRow.rowParentId = ``; - frameTimeLineRow.style.width = `100%`; - frameTimeLineRow.style.height = `40px`; + frameTimeLineRow.rowParentId = ''; + frameTimeLineRow.style.width = '100%'; + frameTimeLineRow.style.height = '40px'; frameTimeLineRow.folder = true; - frameTimeLineRow.name = `FrameTimeline`; + frameTimeLineRow.name = 'FrameTimeline'; frameTimeLineRow.setAttribute('children', ''); - frameTimeLineRow.supplier = () => + frameTimeLineRow.supplier = (): Promise => new Promise((resolve) => { resolve([]); }); frameTimeLineRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; frameTimeLineRow.selectChangeHandler = this.trace.selectChangeHandler; - frameTimeLineRow.onThreadHandler = (useCache) => { - let context = frameTimeLineRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + frameTimeLineRow.onThreadHandler = (useCache: boolean): void => { + let context: CanvasRenderingContext2D = frameTimeLineRow!.collect ? + this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; frameTimeLineRow!.canvasSave(context); - (renders['jank'] as JankRender).renderMainThread( + (renders.jank as JankRender).renderMainThread( { context: context, useCache: useCache, - type: `expected_frame_timeline_slice`, + type: 'expected_frame_timeline_slice' }, frameTimeLineRow! ); @@ -70,68 +84,39 @@ export class SpFrameTimeChart { return frameTimeLineRow; } - async initExpectedChart(frameTimeLineRow: TraceRow) { - let frameExpectedData = await queryExpectedFrameDate(); - if (frameExpectedData.length > 0) { - let isIntersect = (a: JanksStruct, b: JanksStruct) => - Math.max(a.ts! + a.dur!, b.ts! + b.dur!) - Math.min(a.ts!, b.ts!) < a.dur! + b.dur!; - let depths: any = []; - for (let i = 0; i < frameExpectedData.length; i++) { - let it = frameExpectedData[i]; - if (!it.dur || it.dur < 0) { - continue; - } - if (depths.length == 0) { - it.depth = 0; - depths[0] = it; - } else { - let index = 0; - let isContinue = true; - while (isContinue) { - if (isIntersect(depths[index], it)) { - if (depths[index + 1] == undefined || !depths[index + 1]) { - it.depth = index + 1; - depths[index + 1] = it; - isContinue = false; - } - } else { - it.depth = index; - depths[index] = it; - isContinue = false; - } - index++; - } - } - } - } - let max = Math.max(...frameExpectedData.map((it) => it.depth || 0)) + 1; - let maxHeight = max * 20; - let expectedTimeLineRow = TraceRow.skeleton(); - expectedTimeLineRow.rowId = `expected frameTime`; + async initExpectedChart(frameTimeLineRow: TraceRow): Promise { + let frameExpectedData = await this.getExpectedFrameDate(); + let unitIndex: number = 1; + let unitHeight: number = 20; + let max: number = Math.max(...frameExpectedData.map((it) => it.depth || 0)) + unitIndex; + let maxHeight: number = max * unitHeight; + let expectedTimeLineRow = TraceRow.skeleton(); + expectedTimeLineRow.rowId = 'expected frameTime'; expectedTimeLineRow.rowType = TraceRow.ROW_TYPE_JANK; expectedTimeLineRow.rowHidden = !frameTimeLineRow.expansion; - expectedTimeLineRow.rowParentId = `frameTime`; - expectedTimeLineRow.style.width = `100%`; - expectedTimeLineRow.style.height = `40px`; + expectedTimeLineRow.rowParentId = 'frameTime'; + expectedTimeLineRow.style.width = '100%'; + expectedTimeLineRow.style.height = '40px'; expectedTimeLineRow.style.height = `${maxHeight}px`; - expectedTimeLineRow.name = `Expected Timeline`; + expectedTimeLineRow.name = 'Expected Timeline'; expectedTimeLineRow.addTemplateTypes('FrameTimeline'); expectedTimeLineRow.setAttribute('height', `${maxHeight}`); expectedTimeLineRow.setAttribute('children', ''); - expectedTimeLineRow.supplier = () => - new Promise((resolve) => { + expectedTimeLineRow.supplier = (): Promise => + new Promise((resolve): void => { resolve(frameExpectedData); }); expectedTimeLineRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; expectedTimeLineRow.selectChangeHandler = this.trace.selectChangeHandler; - expectedTimeLineRow.onThreadHandler = (useCache) => { - let context = expectedTimeLineRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + expectedTimeLineRow.onThreadHandler = (useCache: boolean): void => { + let context: CanvasRenderingContext2D = expectedTimeLineRow!.collect ? + this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; expectedTimeLineRow!.canvasSave(context); - (renders['jank'] as JankRender).renderMainThread( + (renders.jank as JankRender).renderMainThread( { context: context, useCache: useCache, - type: `expected_frame_timeline_slice`, + type: 'expected_frame_timeline_slice' }, expectedTimeLineRow! ); @@ -140,151 +125,530 @@ export class SpFrameTimeChart { frameTimeLineRow.addChildTraceRow(expectedTimeLineRow); } - async initActualChart(frameTimeLineRow: TraceRow) { - let frameActualData = await queryActualFrameDate(); - if (frameActualData.length > 0) { - let isIntersect = (a: JanksStruct, b: JanksStruct) => - Math.max(a.ts! + a.dur!, b.ts! + b.dur!) - Math.min(a.ts!, b.ts!) < a.dur! + b.dur!; - let depthArray: any = []; - for (let i = 0; i < frameActualData.length; i++) { - let it = frameActualData[i]; - if (!it.dur || it.dur < 0) { - continue; - } - if (depthArray.length == 0) { - it.depth = 0; - depthArray[0] = it; - } else { - let index = 0; - let isContinue = true; - while (isContinue) { - if (isIntersect(depthArray[index], it)) { - if (depthArray[index + 1] == undefined || !depthArray[index + 1]) { - it.depth = index + 1; - depthArray[index + 1] = it; - isContinue = false; - } - } else { - it.depth = index; - depthArray[index] = it; - isContinue = false; - } - index++; - } - } - } - } - - let max = Math.max(...frameActualData.map((it) => it.depth || 0)) + 1; - let maxHeight = max * 20; - let actualTimeLineRow = TraceRow.skeleton(); - actualTimeLineRow.rowId = `actual frameTime`; + async initActualChart(frameTimeLineRow: TraceRow): Promise { + let frameActualData = await this.getActualFrameDate(); + let unitIndex: number = 1; + let unitHeight: number = 20; + let maxHeight: number = (Math.max(...frameActualData.map((it) => it.depth || 0)) + unitIndex) * unitHeight; + let actualTimeLineRow = TraceRow.skeleton(); + actualTimeLineRow.rowId = 'actual frameTime'; actualTimeLineRow.rowType = TraceRow.ROW_TYPE_JANK; actualTimeLineRow.rowHidden = !frameTimeLineRow.expansion; - actualTimeLineRow.rowParentId = `frameTime`; - actualTimeLineRow.style.width = `100%`; + actualTimeLineRow.rowParentId = 'frameTime'; + actualTimeLineRow.style.width = '100%'; actualTimeLineRow.style.height = `${maxHeight}px`; - actualTimeLineRow.name = `Actual Timeline`; + actualTimeLineRow.name = 'Actual Timeline'; actualTimeLineRow.addTemplateTypes('FrameTimeline'); actualTimeLineRow.setAttribute('height', `${maxHeight}`); actualTimeLineRow.setAttribute('children', ''); actualTimeLineRow.dataList = frameActualData; - actualTimeLineRow.supplier = () => - new Promise((resolve) => { - resolve(frameActualData); - }); + actualTimeLineRow.supplier = (): Promise => new Promise((resolve): void => { + resolve(frameActualData); + }); actualTimeLineRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; actualTimeLineRow.selectChangeHandler = this.trace.selectChangeHandler; - actualTimeLineRow.onThreadHandler = (useCache) => { - let context = actualTimeLineRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + actualTimeLineRow.onThreadHandler = (useCache: boolean): void => { + let context: CanvasRenderingContext2D = actualTimeLineRow!.collect ? this.trace.canvasFavoritePanelCtx! : + this.trace.canvasPanelCtx!; actualTimeLineRow!.canvasSave(context); - (renders['jank'] as JankRender).renderMainThread( + (renders.jank as JankRender).renderMainThread( { context: context, useCache: useCache, - type: `expected_frame_timeline_slice`, + type: 'expected_frame_timeline_slice' }, actualTimeLineRow! ); actualTimeLineRow!.canvasRestore(context); }; frameTimeLineRow.addChildTraceRow(actualTimeLineRow); - let offsetYTimeOut: any = undefined; - frameTimeLineRow.addEventListener('expansion-change', (e: any) => { + let offsetYTimeOut: number = 0; + frameTimeLineRow.addEventListener('expansion-change', (customEventInit: CustomEventInit) => { JankStruct.delJankLineFlag = false; if (offsetYTimeOut) { clearTimeout(offsetYTimeOut); } - if (e.detail.expansion) { - offsetYTimeOut = setTimeout(() => { - this.trace.linkNodes.forEach((linkFrameNode) => { - JankStruct.selectJankStructList?.forEach((dat: any) => { - if (e.detail.rowId == dat.pid) { - JankStruct.selectJankStruct = dat; - JankStruct.hoverJankStruct = dat; - } - }); - if (linkFrameNode[0].rowEL.collect) { - linkFrameNode[0].rowEL.translateY = linkFrameNode[0].rowEL.getBoundingClientRect().top - 195; - } else { - linkFrameNode[0].rowEL.translateY = linkFrameNode[0].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; - } - linkFrameNode[0].y = linkFrameNode[0].rowEL!.translateY! + linkFrameNode[0].offsetY; - if (linkFrameNode[1].rowEL.collect) { - linkFrameNode[1].rowEL.translateY = linkFrameNode[1].rowEL.getBoundingClientRect().top - 195; - } else { - linkFrameNode[1].rowEL.translateY = linkFrameNode[1].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; - } - linkFrameNode[1].y = linkFrameNode[1].rowEL!.translateY! + linkFrameNode[1].offsetY; - if (linkFrameNode[0].rowEL.rowId == e.detail.rowId) { - linkFrameNode[0].x = ns2xByTimeShaft(linkFrameNode[0].ns, this.trace.timerShaftEL!); - linkFrameNode[0].y = actualTimeLineRow!.translateY! + linkFrameNode[0].offsetY * 2; - linkFrameNode[0].offsetY = linkFrameNode[0].offsetY * 2; - linkFrameNode[0].rowEL = actualTimeLineRow; - } else if (linkFrameNode[1].rowEL.rowId == e.detail.rowId) { - linkFrameNode[1].x = ns2xByTimeShaft(linkFrameNode[1].ns, this.trace.timerShaftEL!); - linkFrameNode[1].y = actualTimeLineRow!.translateY! + linkFrameNode[1].offsetY * 2; - linkFrameNode[1].offsetY = linkFrameNode[1].offsetY * 2; - linkFrameNode[1].rowEL = actualTimeLineRow!; - } - }); - }, 300); + if (customEventInit.detail?.expansion) { + offsetYTimeOut = this.frameExpandTimeOut(customEventInit, actualTimeLineRow); } else { - if (JankStruct!.selectJankStruct) { - JankStruct.selectJankStructList?.push(JankStruct!.selectJankStruct); + offsetYTimeOut = this.frameNoExpandTimeOut(customEventInit, frameTimeLineRow); + } + }); + } + + async initAnimatedScenesChart( + processRow: TraceRow, + process: { + pid: number | null; + processName: string | null; + }, + firstRow: TraceRow + ): Promise { + this.flagConfig = FlagsConfig.getFlagsConfig('AnimationAnalysis'); + if (this.flagConfig?.AnimationAnalysis === 'Enabled') { + if (process.processName?.startsWith('render_service')) { + let targetRowList = processRow.childrenList.filter(childRow => + childRow.rowType === 'thread' && childRow.name.startsWith('render_service') + ); + let animationRanges = await this.initAnimationChart(processRow, firstRow); + let nameArr = await queryFrameApp(); + let addRowList: Array> = []; + for (let index = 0; index < nameArr.length; index++) { + let name = nameArr[index].appName; + let dynamicChart = await this.initDynamicCurveChart(processRow, name, animationRanges); + let frameSpacingChart = await this.initFrameSpacing(processRow, name, animationRanges); + addRowList.push(dynamicChart); + addRowList.push(frameSpacingChart); + } + let resultRow = addRowList.reverse(); + resultRow.forEach(row => { + processRow.addChildTraceRowAfter(row, targetRowList[0]); + }); + } + } + } + + async initAnimationChart( + processRow: TraceRow, + firstRow: TraceRow + ): Promise { + let frameAnimationData: FrameAnimationStruct[] = await queryFrameAnimationData(); + let animationRanges: AnimationRanges[] = []; + if (frameAnimationData.length > 0) { + frameAnimationData.forEach(data => { + let range = { + start: data.dynamicStartTs, + end: data.dynamicEndTs + }; + animationRanges.push(range); + }); + } + let frameAnimationRow = TraceRow.skeleton(); + frameAnimationRow.rowId = 'Animation'; + frameAnimationRow.rowType = TraceRow.ROW_TYPE_FRAME_ANIMATION; + frameAnimationRow.rowHidden = !processRow.expansion; + frameAnimationRow.rowParentId = processRow.rowId; + frameAnimationRow.style.width = '100%'; + frameAnimationRow.style.height = '40px'; + frameAnimationRow.name = 'Animation'; + frameAnimationRow.addTemplateTypes('Dynamic'); + frameAnimationRow.setAttribute('children', ''); + frameAnimationRow.supplier = (): Promise => + new Promise((resolve) => { + resolve(frameAnimationData); + }); + frameAnimationRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + frameAnimationRow.selectChangeHandler = this.trace.selectChangeHandler; + frameAnimationRow.onThreadHandler = (useCache): void => { + let context: CanvasRenderingContext2D = frameAnimationRow!.collect ? + this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + frameAnimationRow!.canvasSave(context); + (renders.frameAnimation as FrameAnimationRender).renderMainThread( + { + context: context, + useCache: useCache, + type: 'frameAnimation' + }, + frameAnimationRow! + ); + frameAnimationRow!.canvasRestore(context); + }; + processRow.addChildTraceRowBefore(frameAnimationRow, firstRow); + return animationRanges; + } + + async initDynamicCurveChart( + processRow: TraceRow, + componentName: string, + animationRanges: AnimationRanges[] + ): Promise> { + let frameDynamicCurveData: FrameDynamicStruct[] = await queryFrameDynamicData(componentName); + let systemConfigList: string[] = [' ']; + let dynamicCurveRow: TraceRow = TraceRow.skeleton(); + let systemPopover = this.addSystemConfigButton(dynamicCurveRow, systemConfigList); + dynamicCurveRow.rowId = `animation Effect Curve-${componentName}`; + dynamicCurveRow.rowType = TraceRow.ROW_TYPE_FRAME_DYNAMIC; + dynamicCurveRow.rowHidden = !processRow.expansion; + dynamicCurveRow.rowParentId = processRow.rowId; + dynamicCurveRow.style.width = '100%'; + dynamicCurveRow.style.height = '40px'; + dynamicCurveRow.style.height = '100px'; + let labelName = dynamicCurveRow.shadowRoot?.querySelector('.name') as HTMLLabelElement; + labelName.style.marginRight = '77px'; + dynamicCurveRow.name = `Animation Effect Curve (${componentName})`; + dynamicCurveRow.addTemplateTypes('Dynamic'); + dynamicCurveRow.setAttribute('height', '100px'); + dynamicCurveRow.setAttribute('children', ''); + dynamicCurveRow.supplier = (): Promise => + new Promise((resolve): void => { + resolve(frameDynamicCurveData); + }); + dynamicCurveRow.favoriteChangeHandler = () : void => { + this.favoriteSelect(systemPopover, dynamicCurveRow); + }; + dynamicCurveRow.selectChangeHandler = this.trace.selectChangeHandler; + dynamicCurveRow.onThreadHandler = (useCache: boolean): void => { + let context: CanvasRenderingContext2D = dynamicCurveRow!.collect ? this.trace.canvasFavoritePanelCtx! : + this.trace.canvasPanelCtx!; + dynamicCurveRow!.canvasSave(context); + (renders.frameDynamicCurve as FrameDynamicRender).renderMainThread( + { + context: context, + useCache: useCache, + type: 'dynamicEffectCurve', + animationRanges: animationRanges + }, + dynamicCurveRow! + ); + dynamicCurveRow!.canvasRestore(context); + }; + return dynamicCurveRow; + } + + private favoriteSelect(systemPopover: LitPopover, dynamicCurveRow: TraceRow) : void { + let popover = systemPopover.querySelector('.dynamicPopover') as HTMLDivElement; + if (dynamicCurveRow.collect) { + systemPopover.setAttribute('placement', 'right'); + popover.style.display = 'flex'; + } else { + systemPopover.setAttribute('placement', 'bottomLeft'); + popover.style.display = 'block'; + } + } + + async initFrameSpacing( + processRow: TraceRow, + componentName: string, + animationRanges: AnimationRanges[] + ): Promise> { + let frameData: FrameSpacingStruct[] = await queryFrameSpacing(componentName); + let deviceStructArray = await queryPhysicalData(); + let deviceStruct: DeviceStruct = deviceStructArray[0]; + this.dataProcessing(frameData, deviceStruct); + let frameSpacingRow = TraceRow.skeleton(); + frameSpacingRow.rowId = `frame spacing-${componentName}`; + frameSpacingRow.rowType = TraceRow.ROW_TYPE_FRAME_SPACING; + frameSpacingRow.rowHidden = !processRow.expansion; + frameSpacingRow.rowParentId = processRow.rowId; + frameSpacingRow.style.width = '100%'; + frameSpacingRow.style.height = '140px'; + frameSpacingRow.name = `Frame spacing (${componentName})`; + frameSpacingRow.addTemplateTypes('Dynamic'); + frameSpacingRow.setAttribute('height', '140'); + frameSpacingRow.setAttribute('children', ''); + frameSpacingRow.supplier = (): Promise => + new Promise((resolve): void => { + resolve(frameData); + }); + frameSpacingRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + frameSpacingRow.selectChangeHandler = this.trace.selectChangeHandler; + frameSpacingRow.onThreadHandler = (useCache: boolean): void => { + let context = frameSpacingRow!.collect ? + this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + frameSpacingRow!.canvasSave(context); + (renders.frameSpacing as FrameSpacingRender).renderMainThread( + { + context: context, + useCache: useCache, + type: 'frame_spacing_slice', + frameRate: deviceStruct.physicalFrameRate, + animationRanges: animationRanges + }, + frameSpacingRow! + ); + frameSpacingRow!.canvasRestore(context); + }; + return frameSpacingRow; + } + + dataProcessing(frameData: FrameSpacingStruct[], deviceStruct: DeviceStruct): void { + let unitIndex: number = 1; + let secondToNanosecond: number = 1000_000_000; + let physicalWidth = Number(this.flagConfig!.physicalWidth); + let physicalHeight = Number(this.flagConfig!.physicalHeight); + FrameSpacingStruct.physicalWidth = physicalWidth !== 0 ? physicalWidth : deviceStruct.physicalWidth; + FrameSpacingStruct.physicalHeight = physicalHeight !== 0 ? physicalHeight : deviceStruct.physicalHeight; + for (let index = 0; index < frameData.length; index++) { + if (index > 0) { + let intervalTime = (frameData[index].currentTs - frameData[index - unitIndex].currentTs) / secondToNanosecond; + let widthDifference = frameData[index].currentFrameWidth! - frameData[index - unitIndex].currentFrameWidth!; + let heightDifference = frameData[index].currentFrameHeight! - frameData[index - unitIndex].currentFrameHeight!; + let xDifference = frameData[index].x! - frameData[index - unitIndex].x!; + let yDifference = frameData[index].y! - frameData[index - unitIndex].y!; + let frameWidth = Math.abs(widthDifference / FrameSpacingStruct.physicalWidth / intervalTime); + let frameHeight = Math.abs(heightDifference / FrameSpacingStruct.physicalHeight / intervalTime); + let frameX = Math.abs(xDifference / FrameSpacingStruct.physicalHeight / intervalTime); + let frameY = Math.abs(yDifference / FrameSpacingStruct.physicalHeight / intervalTime); + let result = Math.max(frameWidth, frameHeight, frameX, frameY); + frameData[index].frameSpacingResult = Number(result.toFixed(unitIndex)); + frameData[index].preTs = frameData[index - unitIndex].currentTs; + frameData[index].preFrameWidth = frameData[index - unitIndex].currentFrameWidth; + frameData[index].preFrameHeight = frameData[index - unitIndex].currentFrameHeight; + } + } + } + + addSystemConfigButton(dynamicCurveRow: TraceRow, systemConfigList: Array): LitPopover { + let rowContent: HTMLDivElement = dynamicCurveRow.shadowRoot?.querySelector('.describe') as HTMLDivElement; + let systemPopover: LitPopover = document.createElement('lit-popover') as LitPopover; + systemPopover.style.zIndex = '100'; + systemPopover.style.position = 'absolute'; + systemPopover.style.left = '165px'; + systemPopover.style.display = 'flex'; + systemPopover.setAttribute('placement', 'bottomLeft'); + systemPopover.setAttribute('trigger', 'click'); + systemPopover.setAttribute('haveRadio', 'true'); + systemPopover.innerHTML = ` +
+ ${systemConfigList.map((): string => ` +
+ X +
+
+ Y +
+
+ Width +
+
+ Height +
+
+ Alpha +
`).join('')} +
+ `; + rowContent.appendChild(systemPopover); + let radioList = systemPopover.querySelectorAll('.radio'); + let divElement = systemPopover.querySelectorAll('.option'); + divElement.forEach((divEl, index) => { + divEl.addEventListener('click', () => { + if (radioList[index]) { + radioList[index].checked = true; + dynamicCurveRow.setAttribute('modelType', `${radioList[index].value}`); + systemPopover.blur(); + this.trace.refreshCanvas(false); + this.trace.clickEmptyArea(); + } + }); + }); + return systemPopover; + } + + private frameNoExpandTimeOut(event: CustomEventInit<{ + expansion: boolean, + rowType: string, + rowId: string, + rowParentId: string, + }>, frameTimeLineRow: TraceRow): number { + if (JankStruct!.selectJankStruct) { + JankStruct.selectJankStructList?.push(JankStruct!.selectJankStruct); + } + let topPadding: number = 195; + let halfNumber: number = 2; + let offsetYTime: number = 300; + let refreshTime: number = 360; + let offsetYTimeOut: number = window.setTimeout(() => { + this.trace.linkNodes.forEach((linkNode: PairPoint[]) => { + if (linkNode[0].rowEL.collect) { + linkNode[0].rowEL.translateY = linkNode[0].rowEL.getBoundingClientRect().top - topPadding; + } else { + linkNode[0].rowEL.translateY = linkNode[0].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; + } + linkNode[0].y = linkNode[0].rowEL!.translateY! + linkNode[0].offsetY; + if (linkNode[1].rowEL.collect) { + linkNode[1].rowEL.translateY = linkNode[1].rowEL.getBoundingClientRect().top - topPadding; + } else { + linkNode[1].rowEL.translateY = linkNode[1].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; + } + linkNode[1].y = linkNode[1].rowEL!.translateY! + linkNode[1].offsetY; + if (linkNode[0].rowEL.rowParentId === event.detail?.rowId) { + linkNode[0].x = ns2xByTimeShaft(linkNode[0].ns, this.trace.timerShaftEL!); + linkNode[0].y = frameTimeLineRow!.translateY! + linkNode[0].offsetY / halfNumber; + linkNode[0].offsetY = linkNode[0].offsetY / halfNumber; + linkNode[0].rowEL = frameTimeLineRow; + } else if (linkNode[1].rowEL.rowParentId === event.detail?.rowId) { + linkNode[1].x = ns2xByTimeShaft(linkNode[1].ns, this.trace.timerShaftEL!); + linkNode[1].y = frameTimeLineRow!.translateY! + linkNode[1].offsetY / halfNumber; + linkNode[1].offsetY = linkNode[1].offsetY / halfNumber; + linkNode[1].rowEL = frameTimeLineRow!; + } + }); + }, offsetYTime); + let refreshTimeOut: number = window.setTimeout(() => { + this.trace.refreshCanvas(true); + clearTimeout(refreshTimeOut); + }, refreshTime); + return offsetYTimeOut; + } + + private frameExpandTimeOut(event: CustomEventInit<{ + expansion: boolean, + rowType: string, + rowId: string, + rowParentId: string, + }>, actualTimeLineRow: TraceRow): number { + let topPadding: number = 195; + let halfNumber: number = 2; + let offsetYTime: number = 300; + let refreshTime: number = 360; + let offsetYTimeOut: number = window.setTimeout(() => { + this.trace.linkNodes.forEach((linkFrameNode: PairPoint[]) => { + JankStruct.selectJankStructList?.forEach((dat: JankStruct) => { + if (event.detail?.rowId === dat.pid) { + JankStruct.selectJankStruct = dat; + JankStruct.hoverJankStruct = dat; + } + }); + if (linkFrameNode[0].rowEL.collect) { + linkFrameNode[0].rowEL.translateY = linkFrameNode[0].rowEL.getBoundingClientRect().top - topPadding; + } else { + linkFrameNode[0].rowEL.translateY = linkFrameNode[0].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; + } + linkFrameNode[0].y = linkFrameNode[0].rowEL!.translateY! + linkFrameNode[0].offsetY; + if (linkFrameNode[1].rowEL.collect) { + linkFrameNode[1].rowEL.translateY = linkFrameNode[1].rowEL.getBoundingClientRect().top - topPadding; + } else { + linkFrameNode[1].rowEL.translateY = linkFrameNode[1].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; + } + linkFrameNode[1].y = linkFrameNode[1].rowEL!.translateY! + linkFrameNode[1].offsetY; + if (linkFrameNode[0].rowEL.rowId === event.detail?.rowId) { + linkFrameNode[0].x = ns2xByTimeShaft(linkFrameNode[0].ns, this.trace.timerShaftEL!); + linkFrameNode[0].y = actualTimeLineRow!.translateY! + linkFrameNode[0].offsetY * halfNumber; + linkFrameNode[0].offsetY = linkFrameNode[0].offsetY * halfNumber; + linkFrameNode[0].rowEL = actualTimeLineRow; + } else if (linkFrameNode[1].rowEL.rowId === event.detail?.rowId) { + linkFrameNode[1].x = ns2xByTimeShaft(linkFrameNode[1].ns, this.trace.timerShaftEL!); + linkFrameNode[1].y = actualTimeLineRow!.translateY! + linkFrameNode[1].offsetY * halfNumber; + linkFrameNode[1].offsetY = linkFrameNode[1].offsetY * halfNumber; + linkFrameNode[1].rowEL = actualTimeLineRow!; + } + }); + }, offsetYTime); + let refreshTimeOut: number = window.setTimeout(() => { + this.trace.refreshCanvas(true); + clearTimeout(refreshTimeOut); + }, refreshTime); + return offsetYTimeOut; + } + + private async getExpectedFrameDate(): Promise { + let frameExpectedData = await queryExpectedFrameDate(); + if (frameExpectedData.length > 0) { + let unitIndex: number = 1; + let isIntersect = (a: JanksStruct, b: JanksStruct): boolean => + Math.max(a.ts! + a.dur!, b.ts! + b.dur!) - Math.min(a.ts!, b.ts!) < a.dur! + b.dur!; + let depths = []; + for (let i: number = 0; i < frameExpectedData.length; i++) { + let it = frameExpectedData[i]; + if (!it.dur || it.dur < 0) { + continue; } - offsetYTimeOut = setTimeout(() => { - this.trace.linkNodes.forEach((linkNode) => { - if (linkNode[0].rowEL.collect) { - linkNode[0].rowEL.translateY = linkNode[0].rowEL.getBoundingClientRect().top - 195; + if (depths.length === 0) { + it.depth = 0; + depths[0] = it; + } else { + let index: number = 0; + let isContinue: boolean = true; + while (isContinue) { + if (isIntersect(depths[index], it)) { + if (depths[index + unitIndex] === undefined || !depths[index + unitIndex]) { + it.depth = index + unitIndex; + depths[index + unitIndex] = it; + isContinue = false; + } } else { - linkNode[0].rowEL.translateY = linkNode[0].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; + it.depth = index; + depths[index] = it; + isContinue = false; } - linkNode[0].y = linkNode[0].rowEL!.translateY! + linkNode[0].offsetY; - if (linkNode[1].rowEL.collect) { - linkNode[1].rowEL.translateY = linkNode[1].rowEL.getBoundingClientRect().top - 195; + index++; + } + } + } + } + return frameExpectedData; + } + + private async getActualFrameDate(): Promise { + let frameActualData = await queryActualFrameDate(); + if (frameActualData.length > 0) { + let unitIndex: number = 1; + let isIntersect = (leftStruct: JanksStruct, rightStruct: JanksStruct): boolean => + Math.max(leftStruct.ts! + leftStruct.dur!, rightStruct.ts! + rightStruct.dur!) - + Math.min(leftStruct.ts!, rightStruct.ts!) < leftStruct.dur! + rightStruct.dur!; + let depthArray = []; + for (let index: number = 0; index < frameActualData.length; index++) { + let it = frameActualData[index]; + if (!it.dur || it.dur < 0) { + continue; + } + if (depthArray.length === 0) { + it.depth = 0; + depthArray[0] = it; + } else { + let index: number = 0; + let isContinue: boolean = true; + while (isContinue) { + if (isIntersect(depthArray[index], it)) { + if (depthArray[index + unitIndex] === undefined || !depthArray[index + unitIndex]) { + it.depth = index + unitIndex; + depthArray[index + unitIndex] = it; + isContinue = false; + } } else { - linkNode[1].rowEL.translateY = linkNode[1].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; - } - linkNode[1].y = linkNode[1].rowEL!.translateY! + linkNode[1].offsetY; - if (linkNode[0].rowEL.rowParentId == e.detail.rowId) { - linkNode[0].x = ns2xByTimeShaft(linkNode[0].ns, this.trace.timerShaftEL!); - linkNode[0].y = frameTimeLineRow!.translateY! + linkNode[0].offsetY / 2; - linkNode[0].offsetY = linkNode[0].offsetY / 2; - linkNode[0].rowEL = frameTimeLineRow; - } else if (linkNode[1].rowEL.rowParentId == e.detail.rowId) { - linkNode[1].x = ns2xByTimeShaft(linkNode[1].ns, this.trace.timerShaftEL!); - linkNode[1].y = frameTimeLineRow!.translateY! + linkNode[1].offsetY / 2; - linkNode[1].offsetY = linkNode[1].offsetY / 2; - linkNode[1].rowEL = frameTimeLineRow!; + it.depth = index; + depthArray[index] = it; + isContinue = false; } - }); - }, 300); + index++; + } + } } - let refreshTimeOut = setTimeout(() => { - this.trace.refreshCanvas(true); - clearTimeout(refreshTimeOut); - }, 360); - }); + } + return frameActualData; + } + + private dynamicHoverTip(dynamicCurveRow: TraceRow): void { + if (FrameDynamicStruct.hoverFrameDynamicStruct) { + this.trace?.displayTip( + dynamicCurveRow, + FrameDynamicStruct.hoverFrameDynamicStruct, + `
+
+
prev
+
+
+
+
ts:
+
+ ${(FrameDynamicStruct.hoverFrameDynamicStruct.ts) || ''} +
+
+
x: +
+
+ ${(FrameDynamicStruct.hoverFrameDynamicStruct.x) || ''}
+
+
y: +
+
+ ${(FrameDynamicStruct.hoverFrameDynamicStruct.y) || ''}
+
+
width: +
+
+ ${(FrameDynamicStruct.hoverFrameDynamicStruct.width) || ''}
+
+
height: +
+
+ ${(FrameDynamicStruct.hoverFrameDynamicStruct.height) || ''}
+
+
alpha: +
+
` + ); + } } } diff --git a/ide/src/trace/component/chart/SpProcessChart.ts b/ide/src/trace/component/chart/SpProcessChart.ts index e428958ad..73db082c1 100644 --- a/ide/src/trace/component/chart/SpProcessChart.ts +++ b/ide/src/trace/component/chart/SpProcessChart.ts @@ -50,6 +50,7 @@ import { JankRender, JankStruct } from '../../database/ui-worker/ProcedureWorker import { ns2xByTimeShaft } from '../../database/ui-worker/ProcedureWorkerCommon.js'; import { AppStartupRender, AppStartupStruct } from '../../database/ui-worker/ProcedureWorkerAppStartup.js'; import { SoRender, SoStruct } from '../../database/ui-worker/ProcedureWorkerSoInit.js'; +import { FlagsConfig } from '../SpFlags.js'; export class SpProcessChart { private readonly trace: SpSystemTrace; @@ -175,8 +176,15 @@ export class SpProcessChart { this.processAsyncEvent = await getAsyncEvents(); info('The amount of initialized process Event data is : ', this.processAsyncEvent!.length); this.processMem = await queryProcessMem(); - this.startupProcessArr = await queryStartupPidArray(); - this.processSoMaxDepth = await queryProcessSoMaxDepth(); + let startupConfig = FlagsConfig.getFlagsConfig('AppStartup'); + let loadAppStartup: boolean = false; + if (startupConfig && startupConfig.AppStartup) { + loadAppStartup = startupConfig.AppStartup === 'Enabled'; + } + if (loadAppStartup) { + this.startupProcessArr = await queryStartupPidArray(); + this.processSoMaxDepth = await queryProcessSoMaxDepth(); + } info('The amount of initialized process memory data is : ', this.processMem!.length); let eventCountList: Array = await queryEventCountMap(); this.eventCountMap = eventCountList.reduce((pre, current) => { @@ -247,15 +255,22 @@ export class SpProcessChart { processRow.canvasRestore(this.trace.canvasPanelCtx!); }; this.trace.rowsEL?.appendChild(processRow); + + /** + * App Startup row + */ let startupRow: TraceRow | undefined = undefined; let soRow: TraceRow | undefined = undefined; - if (this.startupProcessArr.find((sp) => sp.pid === it.pid)) { - startupRow = this.addStartUpRow(processRow); - } - let maxSoDepth = this.processSoMaxDepth.find((md) => md.pid === it.pid); - if (maxSoDepth) { - soRow = this.addSoInitRow(processRow, maxSoDepth.maxDepth); + if (loadAppStartup) { + if (this.startupProcessArr.find((sp) => sp.pid === it.pid)) { + startupRow = this.addStartUpRow(processRow); + } + let maxSoDepth = this.processSoMaxDepth.find((md) => md.pid === it.pid); + if (maxSoDepth) { + soRow = this.addSoInitRow(processRow, maxSoDepth.maxDepth); + } } + /** * Janks Frames */ @@ -710,6 +725,7 @@ export class SpProcessChart { processRow.addChildTraceRowAfter(funcRow, threadRow); } } + await this.trace.chartManager?.frameTimeChart.initAnimatedScenesChart(processRow, it, expectedRow!); } let durTime = new Date().getTime() - time; info('The time to load the Process data is: ', durTime); diff --git a/ide/src/trace/component/setting/SpRecordTemplate.ts b/ide/src/trace/component/setting/SpRecordTemplate.ts index 12bb74da1..0ee2ec7ec 100644 --- a/ide/src/trace/component/setting/SpRecordTemplate.ts +++ b/ide/src/trace/component/setting/SpRecordTemplate.ts @@ -80,13 +80,15 @@ export class SpRecordTemplate extends BaseElement { private schedulingAnalysis: LitSwitch | undefined | null; private appStartup: LitSwitch | undefined | null; private taskPoolEl: LitSwitch | undefined | null; + private dynamicEffectEl: LitSwitch | undefined | null; initElements(): void { this.frameTimeline = this.shadowRoot?.querySelector('#frame_timeline'); this.schedulingAnalysis = this.shadowRoot?.querySelector('#scheduling_analysis'); this.appStartup = this.shadowRoot?.querySelector('#app_startup'); this.taskPoolEl = this.shadowRoot?.querySelector('#task_pool'); - this.addProbeListener(this.frameTimeline!, this.schedulingAnalysis!, this.appStartup!, this.taskPoolEl!) + this.dynamicEffectEl = this.shadowRoot?.querySelector('#dynamic_effect'); + this.addProbeListener(this.frameTimeline!, this.schedulingAnalysis!, this.appStartup!, this.taskPoolEl!, this.dynamicEffectEl!); } addProbeListener(...elements: HTMLElement[]) { @@ -96,15 +98,15 @@ export class SpRecordTemplate extends BaseElement { if (detail!.checked) { this.dispatchEvent(new CustomEvent('addProbe', {})); } - }) - }) + }); + }); } getTemplateConfig(): Array> { let config: Array> = []; let traceEventSet = new Array(); let hitraceCategories = new Array(); let useFtracePlugin: boolean = false; - if (this.frameTimeline?.checked || this.appStartup?.checked) { + if (this.frameTimeline?.checked || this.appStartup?.checked || this.dynamicEffectEl?.checked) { useFtracePlugin = true; SpRecordTemplate.FRAME_TIMELINE_CATEGORIES_EVENT.forEach((categories) => { if (hitraceCategories.indexOf(categories) == -1) { @@ -127,7 +129,7 @@ export class SpRecordTemplate extends BaseElement { } if (this.taskPoolEl!.checked) { useFtracePlugin = true; - traceEventSet.push('commonlibrary') + traceEventSet.push('commonlibrary'); } if (useFtracePlugin) { let tracePluginConfig: TracePluginConfig = { @@ -221,6 +223,12 @@ export class SpRecordTemplate extends BaseElement { Task pool
+ +
+
+ Dynamic effect + +
`; diff --git a/ide/src/trace/component/trace/base/ColorUtils.ts b/ide/src/trace/component/trace/base/ColorUtils.ts index b67bd5364..d79ed5fed 100644 --- a/ide/src/trace/component/trace/base/ColorUtils.ts +++ b/ide/src/trace/component/trace/base/ColorUtils.ts @@ -49,9 +49,23 @@ export class ColorUtils { '#E69553', '#7EC6BB', '#8d9171', + + ]; + + public static ANIMATION_COLOR: Array = [ + '#ECECEC', + '#FE3000', + '#61CFBE', + '#000', + '#FFFFFF', + '#C6D9F2', + '#BFEBE5', + '#0A59F7', + '#25ACF5', + '#FFFFFF' ]; - public static JANK_COLOR: Array = ['#42A14D', '#C0CE85', '#FF651D', '#E8BE44', '#009DFA', '#E97978']; + public static JANK_COLOR: Array = ['#42A14D', '#C0CE85', '#FF651D', '#E8BE44', '#009DFA', '#E97978', '#A8D1F4']; public static MD_PALETTE: Array = ColorUtils.FUNC_COLOR_B; public static FUNC_COLOR: Array = ColorUtils.FUNC_COLOR_B; diff --git a/ide/src/trace/component/trace/base/TraceRow.ts b/ide/src/trace/component/trace/base/TraceRow.ts index 021af632f..d2a981865 100644 --- a/ide/src/trace/component/trace/base/TraceRow.ts +++ b/ide/src/trace/component/trace/base/TraceRow.ts @@ -89,6 +89,9 @@ export class TraceRow extends HTMLElement { static ROW_TYPE_IRQ_GROUP = 'irq-group'; static ROW_TYPE_IRQ = 'irq'; static ROW_TYPE_JANK = 'janks'; + static ROW_TYPE_FRAME_ANIMATION = 'frame-animation'; + static ROW_TYPE_FRAME_DYNAMIC = 'frame-dynamic'; + static ROW_TYPE_FRAME_SPACING = 'frame-spacing'; static FRAME_WIDTH: number = 0; static range: TimeRange | undefined | null; static rangeSelectObject: RangeSelectStruct | undefined; @@ -376,6 +379,7 @@ export class TraceRow extends HTMLElement { addChildTraceRowAfter(child: TraceRow, targetRow: TraceRow) { TraceRowConfig.allTraceRowList.push(child); child.parentRowEl = this; + this.toParentAddTemplateType(child); let index = this.childrenList.indexOf(targetRow); child.setAttribute('scene', ''); if (index != -1) { @@ -385,6 +389,19 @@ export class TraceRow extends HTMLElement { } } + addChildTraceRowBefore(child: TraceRow, targetRow: TraceRow) { + TraceRowConfig.allTraceRowList.push(child); + child.parentRowEl = this; + this.toParentAddTemplateType(child); + let index = this.childrenList.indexOf(targetRow); + child.setAttribute('scene', ''); + if (index != -1) { + this.childrenList.splice(index, 0, child); + } else { + this.childrenList.push(child); + } + } + addChildTraceRowSpecifyLocation(child: TraceRow, index: number) { TraceRowConfig.allTraceRowList.push(child); child.parentRowEl = this; diff --git a/ide/src/trace/component/trace/base/TraceSheet.ts b/ide/src/trace/component/trace/base/TraceSheet.ts index 80ac2f646..e9cbf41b0 100644 --- a/ide/src/trace/component/trace/base/TraceSheet.ts +++ b/ide/src/trace/component/trace/base/TraceSheet.ts @@ -45,6 +45,12 @@ import { TabPaneCurrent } from '../sheet/TabPaneCurrent.js'; import { SlicesTime } from '../timer-shaft/SportRuler.js'; import { AppStartupStruct } from '../../../database/ui-worker/ProcedureWorkerAppStartup.js'; import { SoStruct } from '../../../database/ui-worker/ProcedureWorkerSoInit.js'; +import { FrameAnimationStruct } from '../../../database/ui-worker/ProcedureWorkerFrameAnimation.js'; +import { TraceRow } from './TraceRow.js'; +import { FrameDynamicStruct } from '../../../database/ui-worker/ProcedureWorkerFrameDynamic.js'; +import { TabPaneFrameDynamic } from '../sheet/frame/TabPaneFrameDynamic.js'; +import { FrameSpacingStruct } from '../../../database/ui-worker/ProcedureWorkerFrameSpacing.js'; +import { TabFrameSpacing } from '../sheet/frame/TabFrameSpacing.js'; @element('trace-sheet') export class TraceSheet extends BaseElement { private litTabs: LitTabs | undefined | null; @@ -421,6 +427,16 @@ export class TraceSheet extends BaseElement { displayFreqLimitData = () => (this.displayTab('box-freq-limit').data = CpuFreqLimitsStruct.selectCpuFreqLimitsStruct); + displayFrameAnimationData = ( + data: FrameAnimationStruct + ) => this.displayTab('current-selection').setFrameAnimationData(data); + displayFrameDynamicData = ( + row: TraceRow, + data: FrameDynamicStruct + ) => this.displayTab('box-frame-dynamic').buildDynamicTable([data], true); + displayFrameSpacingData = (data: FrameSpacingStruct): void => + this.displayTab('box-frames-spacing').setFrameSpacingData(data); + rangeSelect(selection: SelectionParam, restore = false): boolean { this.selection = selection; this.showUploadSoBt(selection); diff --git a/ide/src/trace/component/trace/base/TraceSheetConfig.ts b/ide/src/trace/component/trace/base/TraceSheetConfig.ts index b06586278..0278d0f4a 100644 --- a/ide/src/trace/component/trace/base/TraceSheetConfig.ts +++ b/ide/src/trace/component/trace/base/TraceSheetConfig.ts @@ -77,6 +77,9 @@ import { TabPaneCurrent } from '../sheet/TabPaneCurrent.js'; import { TabPaneStartup } from '../sheet/process/TabPaneStartup.js'; import { TabPaneStaticInit } from '../sheet/process/TabPaneStaticInit.js'; import { TabPaneTaskFrames } from '../sheet/task/TabPaneTaskFrames.js'; +import { TabPaneFrameDynamic } from '../sheet/frame/TabPaneFrameDynamic.js'; +import { TabPaneFrameAnimation } from '../sheet/frame/TabPaneFrameAnimation.js'; +import { TabFrameSpacing } from '../sheet/frame/TabFrameSpacing.js'; export let tabConfig: any = { 'tabpane-current': { @@ -400,4 +403,19 @@ export let tabConfig: any = { type: TabPaneTaskFrames, require: (param: SelectionParam) => param.taskFramesData.length > 0, }, + 'box-frame-dynamic': { + title: 'Frame Dynamic', + type: TabPaneFrameDynamic, + require: (param: SelectionParam) => param.frameDynamic.length > 0 + }, + 'box-frame-animation': { + title: 'Frame Animation', + type: TabPaneFrameAnimation, + require: (param: SelectionParam) => param.frameAnimation.length > 0 + }, + 'box-frames-spacing': { + title: 'Frame spacing', + type: TabFrameSpacing, + require: (param: SelectionParam) => param.frameSpacing.length > 0, + }, }; diff --git a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts index 1bb5ec67d..38b138dbe 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts @@ -29,7 +29,7 @@ import { queryThreadWakeUp, queryThreadWakeUpFrom, queryCPUWakeUpIdFromBean, - queryThreadByItid, + queryThreadByItid, queryAnimationFrameFps, } from '../../../database/SqlLite.js'; import { WakeupBean } from '../../../bean/WakeupBean.js'; import { SpApplication } from '../../../SpApplication.js'; @@ -49,6 +49,7 @@ import { SpSystemTrace } from '../../SpSystemTrace.js'; import { AppStartupStruct } from '../../../database/ui-worker/ProcedureWorkerAppStartup.js'; import { SoStruct } from '../../../database/ui-worker/ProcedureWorkerSoInit.js'; import { SelectionParam } from '../../../bean/BoxSelection.js'; +import { FrameAnimationStruct } from '../../../database/ui-worker/ProcedureWorkerFrameAnimation.js'; 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.'; @@ -874,6 +875,29 @@ export class TabPaneCurrentSelection extends BaseElement { } } + async setFrameAnimationData( + data: FrameAnimationStruct + ): Promise{ + this.setTableHeight('550px'); + this.tabCurrentSelectionInit('Animation Details'); + let list = []; + let dataTs: number = data.ts < 0 ? 0 : data.ts; + list.push({ name: 'Name', value: data.animationId }); + list.push({ name: 'Start time', value: `${Utils.getTimeString(dataTs)}`}); + list.push({ name: 'End time', value: `${Utils.getTimeString(dataTs + (data.dur || 0))}`}); + list.push({ name: 'Duration', value: `${Utils.getTimeString(data.dur || 0)}`,}); + if (data.status === 'Completion delay') { + let result = await queryAnimationFrameFps(dataTs, dataTs + data.dur); + if (result.length > 0) { + let percentageNumber: number = 1; + let fixedNumber: number = 2; + let fpsValue: number = percentageNumber / result[0].fps; + list.push({ name: 'Frame', value: `${fpsValue.toFixed(fixedNumber) || 0} fps` }); + } + } + this.currentSelectionTbl!.dataSource = list; + } + private setJankType(data: JankStruct, list: any[]) { if (data.jank_tag === 1) { if (data.frame_type === 'render_service') { diff --git a/ide/src/trace/component/trace/sheet/frame/TabFrameSpacing.ts b/ide/src/trace/component/trace/sheet/frame/TabFrameSpacing.ts new file mode 100644 index 000000000..a43fe84ca --- /dev/null +++ b/ide/src/trace/component/trace/sheet/frame/TabFrameSpacing.ts @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { FrameSpacingStruct } from '../../../../database/ui-worker/ProcedureWorkerFrameSpacing.js'; +import { SelectionParam } from '../../../../bean/BoxSelection.js'; +import { LitTable } from '../../../../../base-ui/table/lit-table.js'; +import { resizeObserver } from '../SheetUtils.js'; +import { Utils } from '../../base/Utils.js'; + +@element('tabpane-frames-spacing') +export class TabFrameSpacing extends BaseElement { + private range: HTMLLabelElement | null | undefined; + private framesTbl: LitTable | null | undefined; + private framesSource: Array = []; + + set data(frameSpacingParam: SelectionParam) { + let secondToMillisecond: number = 1000_000.0; + let fixedNumber: number = 5; + this.range!.textContent = `Selected range: ${parseFloat(((frameSpacingParam.rightNs - frameSpacingParam.leftNs) / + secondToMillisecond).toFixed(fixedNumber))} ms`; + let tableList: FrameSpacingTableStruct[] = []; + for (let index = 0; index < frameSpacingParam.frameSpacing.length; index++) { + this.constructTable(frameSpacingParam.frameSpacing[index], tableList); + } + this.framesSource = tableList; + this.framesTbl!.recycleDataSource = tableList; + } + + connectedCallback(): void { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.framesTbl!); + } + + setFrameSpacingData(data: FrameSpacingStruct): void { + let tableList: FrameSpacingTableStruct[] = []; + this.range!.textContent = ''; + this.constructTable(data, tableList); + this.framesSource = tableList; + this.framesTbl!.recycleDataSource = tableList; + } + + private constructTable(structValue: FrameSpacingStruct, tableList: FrameSpacingTableStruct[]): void { + // @ts-ignore + let startNS = window.recordStartNS; + tableList.push(this.getSplitSpacingData(structValue, startNS, 'W')); + tableList.push(this.getSplitSpacingData(structValue, startNS, 'H')); + } + + getSplitSpacingData(structValue: FrameSpacingStruct, startNS: number, propertyStr: string): FrameSpacingTableStruct{ + let frameSpacing: FrameSpacingTableStruct = new FrameSpacingTableStruct(); + let secondToNanosecond: number = 1000_000_000; + frameSpacing.index = structValue.id; + frameSpacing.timestamp = Utils.getTimeString(Number(structValue.currentTs)); + frameSpacing.property = propertyStr; + frameSpacing.value2 = propertyStr === 'W' ? structValue.currentFrameWidth! : structValue.currentFrameHeight!; + frameSpacing.value1 = propertyStr === 'W' ? structValue.preFrameWidth! : structValue.preFrameHeight!; + frameSpacing.screen = propertyStr === 'W' ? FrameSpacingStruct.physicalWidth : FrameSpacingStruct.physicalHeight; + frameSpacing.currentTs = ((structValue.currentTs + startNS) / secondToNanosecond).toString(); + frameSpacing.preTs = (((structValue.preTs || 0) + startNS) / secondToNanosecond).toString(); + if (structValue.preTs === 0) { + frameSpacing.preTs = '-'; + } + frameSpacing.frameSpacingResult = structValue.frameSpacingResult; + return frameSpacing; + } + + initElements(): void { + this.framesTbl = this.shadowRoot?.querySelector('#tb-frame-spacing'); + this.range = this.shadowRoot?.querySelector('#frames-spacing-time-range'); + this.framesTbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail); + }); + } + + sortByColumn(framesDetail: { + sort: number, + key: string, + }): void { + let compare = function (property: string, sort: number, type: string) { + return function ( + frameSpacingLeftData: FrameSpacingTableStruct, + frameSpacingRightData: FrameSpacingTableStruct + ): number { + let firstSortNumber: number = -1; + let SecondSortNumber: number = 1; + let thirdSortNumber: number = 2; + // @ts-ignore + let rightSpacingData = frameSpacingRightData[property]; + // @ts-ignore + let leftSpacingData = frameSpacingLeftData[property]; + if (type === 'number') { + return sort === thirdSortNumber ? parseFloat(rightSpacingData) - parseFloat(leftSpacingData) : + parseFloat(leftSpacingData) - parseFloat(rightSpacingData); + } else { + if (rightSpacingData > leftSpacingData) { + return sort === thirdSortNumber ? SecondSortNumber : firstSortNumber; + } else { + if (rightSpacingData === leftSpacingData) { + return 0; + } else { + return sort === thirdSortNumber ? firstSortNumber : SecondSortNumber; + } + } + } + }; + }; + if (framesDetail.key === 'property') { + this.framesSource.sort(compare(framesDetail.key, framesDetail.sort, 'string')); + } else { + this.framesSource.sort(compare(framesDetail.key, framesDetail.sort, 'number')); + } + this.framesTbl!.recycleDataSource = this.framesSource; + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + + + + + + + + + `; + } +} + +export class FrameSpacingTableStruct { + index: number | undefined; + timestamp: string | undefined; + property: string | undefined; + value2: number | undefined; + value1: number | undefined; + screen: number | undefined; + currentTs: string | undefined; + preTs: string | undefined; + frameSpacingResult: number | undefined; +} diff --git a/ide/src/trace/component/trace/sheet/frame/TabPaneFrameAnimation.ts b/ide/src/trace/component/trace/sheet/frame/TabPaneFrameAnimation.ts new file mode 100644 index 000000000..26fe63048 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/frame/TabPaneFrameAnimation.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 { SelectionParam } from '../../../../bean/BoxSelection.js'; +import { LitTable } from '../../../../../base-ui/table/lit-table.js'; +import { resizeObserver } from '../SheetUtils.js'; +import { FrameAnimationStruct } from '../../../../database/ui-worker/ProcedureWorkerFrameAnimation.js'; + +@element('tabpane-frames-animation') +export class TabPaneFrameAnimation extends BaseElement { + private frameAnimationTbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private frameAnimationSource: Array = []; + + set data(frameAnimationParam: SelectionParam) { + let secondToMillisecond: number = 1000_000.0; + let fixedNumber: number = 5; + this.range!.textContent = `Selected range: ${parseFloat(((frameAnimationParam.rightNs - + frameAnimationParam.leftNs) / secondToMillisecond).toFixed(fixedNumber))} ms`; + this.queryDataByDB(frameAnimationParam); + } + + queryDataByDB(frameAnimationParam: SelectionParam): void { + let tableData: FrameAnimationStruct[] = []; + this.frameAnimationSource = tableData; + this.frameAnimationTbl!.recycleDataSource = tableData; + } + + initElements(): void { + this.frameAnimationTbl = this.shadowRoot?.querySelector('#tb-frame-animation'); + this.range = this.shadowRoot?.querySelector('#frame-animation-time-range'); + this.frameAnimationTbl!.addEventListener('column-click', (evt: CustomEventInit) => { + this.sortByColumn(evt.detail); + }); + } + + connectedCallback(): void { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.frameAnimationTbl!); + } + + initHtml(): string { + return ` + + + + + + + + + + + + + + + `; + } + + private sortByColumn(framesDetail: { + sort: number, + key: string, + }): void { + let compare = function (dateKey: string, sort: number, type: string) { + return function (leftAnimation: FrameAnimationStruct, rightAnimation: FrameAnimationStruct): number { + let firstSortNumber: number = -1; + let SecondSortNumber: number = 1; + let thirdSortNumber: number = 2; + // @ts-ignore + let rightData = rightAnimation[dateKey]; + // @ts-ignore + let leftData = leftAnimation[dateKey]; + if (type === 'number') { + return sort === thirdSortNumber ? parseFloat(rightData) - parseFloat(leftData) : + parseFloat(leftData) - parseFloat(rightData); + } else { + if (leftData > leftData) { + return sort === thirdSortNumber ? SecondSortNumber : firstSortNumber; + } else { + if (leftData === leftData) { + return 0; + } else { + return sort === thirdSortNumber ? firstSortNumber : SecondSortNumber; + } + } + } + }; + }; + + if (framesDetail.key === 'animation') { + this.frameAnimationSource.sort(compare(framesDetail.key, framesDetail.sort, 'string')); + } else { + this.frameAnimationSource.sort(compare(framesDetail.key, framesDetail.sort, 'number')); + } + this.frameAnimationTbl!.recycleDataSource = this.frameAnimationSource; + } +} diff --git a/ide/src/trace/component/trace/sheet/frame/TabPaneFrameDynamic.ts b/ide/src/trace/component/trace/sheet/frame/TabPaneFrameDynamic.ts new file mode 100644 index 000000000..3a18f5811 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/frame/TabPaneFrameDynamic.ts @@ -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 { BaseElement, element } from '../../../../../base-ui/BaseElement.js'; +import { SelectionParam } from '../../../../bean/BoxSelection.js'; +import { LitTable } from '../../../../../base-ui/table/lit-table.js'; +import { resizeObserver } from '../SheetUtils.js'; +import { FrameDynamicStruct } from '../../../../database/ui-worker/ProcedureWorkerFrameDynamic.js'; +import { FrameAnimationSelect } from '../../../../bean/FrameComponentBean.js'; +import { Utils } from '../../base/Utils.js'; + +@element('tabpane-frame-dynamic') +export class TabPaneFrameDynamic extends BaseElement { + private frameDynamicTbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private frameDynamicSource: Array = []; + + set data(frameDynamicParam: SelectionParam) { + let secondToMillisecond: number = 1000_000.0; + let fixedNumber: number = 5; + this.range!.textContent = `Selected range: ${parseFloat(((frameDynamicParam.rightNs - + frameDynamicParam.leftNs) / secondToMillisecond).toFixed(fixedNumber))} ms`; + this.buildDynamicTable(frameDynamicParam.frameDynamic); + } + + buildDynamicTable(dynamicDataList: FrameDynamicStruct[], isClickSelect: boolean = false): void { + if (isClickSelect) { + this.range!.style.visibility = 'hidden'; + } else { + this.range!.style.visibility = 'visible'; + } + let result: FrameAnimationSelect[] = []; + dynamicDataList.forEach(dynamic => { + result.push({ + id: dynamic.id, + value: dynamic.typeValue, + timestamp: Utils.getTimeString(dynamic.ts) + }); + }); + this.frameDynamicSource = result; + this.frameDynamicTbl!.recycleDataSource = result; + } + + initElements(): void { + this.frameDynamicTbl = this.shadowRoot?.querySelector('#tb-frame-dynamic'); + this.range = this.shadowRoot?.querySelector('#frame-dynamic-time-range'); + this.frameDynamicTbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortByColumn(evt.detail); + }); + } + + connectedCallback(): void { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.frameDynamicTbl!); + } + + initHtml(): string { + return ` + + + + + + + + + + + + `; + } + + private sortByColumn(framesDetail: { + sort: number, + key: string, + }): void { + let compare = function (property: string, sort: number, type: string) { + return function (frameDynamicLeft: FrameAnimationSelect, frameDynamicRight: FrameAnimationSelect): number { + let firstSortNumber: number = -1; + let SecondSortNumber: number = 1; + let thirdSortNumber: number = 2; + // @ts-ignore + let rightData = frameDynamicRight[property]; + // @ts-ignore + let leftData = frameDynamicLeft[property]; + if (type === 'number') { + return sort === thirdSortNumber ? parseFloat(rightData) - parseFloat(leftData) : + parseFloat(leftData) - parseFloat(rightData); + } else { + if (rightData > leftData) { + return sort === thirdSortNumber ? SecondSortNumber : firstSortNumber; + } else { + if (rightData === leftData) { + return 0; + } else { + return sort === thirdSortNumber ? firstSortNumber : SecondSortNumber; + } + } + } + }; + }; + + if (framesDetail.key === 'timestamp') { + this.frameDynamicSource.sort(compare(framesDetail.key, framesDetail.sort, 'string')); + } else { + this.frameDynamicSource.sort(compare(framesDetail.key, framesDetail.sort, 'number')); + } + this.frameDynamicTbl!.recycleDataSource = this.frameDynamicSource; + } +} diff --git a/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts b/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts index c0acb0223..677401315 100644 --- a/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts +++ b/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts @@ -25,7 +25,7 @@ import { } from '../../../../database/SqlLite.js'; import { BaseStruct } from '../../../../database/ui-worker/ProcedureWorkerCommon.js'; import { SpSystemTrace } from '../../../SpSystemTrace.js'; -import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; +import {LitProgressBar} from '../../../../../base-ui/progress-bar/LitProgressBar.js'; @element('tabpane-task-frames') export class TabPaneTaskFrames extends BaseElement { @@ -58,7 +58,7 @@ export class TabPaneTaskFrames extends BaseElement { this.taskFramesTbl!!.recycleDataSource = []; return; } else { - let sTime = 0, eTime = 0, rTime = 0; + let sTime, eTime = 0, rTime; let aStartTime = 0, pStartTime = 0, rEndTime = 0; let priorityId = 1; let executeId = ''; @@ -279,13 +279,11 @@ export class TabPaneTaskFrames extends BaseElement { let tasks:Array = res[1] for (let i = 0; i < tasks.length; i++) { const task = tasks[i]; - // @ts-ignore - const endTime = task!.startTs + task!.dur; + const endTime = task!.startTs! + task!.dur!; currentConcurrency++; for (let j = i + 1; j < tasks.length; j++) { const nextTask = tasks[j]; - // @ts-ignore - if (nextTask.startTs < endTime) { + if (nextTask.startTs! < endTime) { currentConcurrency++; } } @@ -387,5 +385,4 @@ export class TaskTabStruct extends BaseStruct { priority: number | undefined; taskPriority: string | undefined; isUse: boolean = false; - isTimeOut: boolean | undefined; } diff --git a/ide/src/trace/database/SqlLite.ts b/ide/src/trace/database/SqlLite.ts index f054f3ec3..8b290e5de 100644 --- a/ide/src/trace/database/SqlLite.ts +++ b/ide/src/trace/database/SqlLite.ts @@ -80,6 +80,10 @@ import { AppStartupStruct } from './ui-worker/ProcedureWorkerAppStartup.js'; import { SoStruct } from './ui-worker/ProcedureWorkerSoInit.js'; import { HeapTreeDataBean } from './logic-worker/ProcedureLogicWorkerCommon.js'; import { TaskTabStruct } from '../component/trace/sheet/task/TabPaneTaskFrames.js'; +import { DeviceStruct } from '../bean/FrameComponentBean.js'; +import { FrameSpacingStruct } from './ui-worker/ProcedureWorkerFrameSpacing.js'; +import { FrameDynamicStruct } from './ui-worker/ProcedureWorkerFrameDynamic.js'; +import { FrameAnimationStruct } from './ui-worker/ProcedureWorkerFrameAnimation.js'; class DataWorkerThread extends Worker { taskMap: any = {}; @@ -4242,14 +4246,15 @@ export const queryConcurrencyTask = (funName: string, selectStartTime: number, s LEFT JOIN callstack ON thread.id = callstack.callid WHERE callstack.name = $funName) AND thread.name = 'TaskWorkThread' + AND callstack.name LIKE 'H:Task Perform:%' AND -- 左包含 - ($selectStartTime <= callstack.ts AND $selectEndTime > callstack.ts AND callstack.name LIKE 'H:Task Perform:%') + (($selectStartTime <= callstack.ts AND $selectEndTime > callstack.ts) OR -- 右包含 - ($selectStartTime < callstack.ts + callstack.dur AND $selectEndTime >= callstack.ts + callstack.dur AND callstack.name LIKE 'H:Task Perform:%') + ($selectStartTime < callstack.ts + callstack.dur AND $selectEndTime >= callstack.ts + callstack.dur) OR -- 包含 - ($selectStartTime >= callstack.ts AND $selectEndTime <= callstack.ts + callstack.dur AND callstack.name LIKE 'H:Task Perform:%') + ($selectStartTime >= callstack.ts AND $selectEndTime <= callstack.ts + callstack.dur) OR -- 被包含 - ($selectStartTime <= callstack.ts AND $selectEndTime >= callstack.ts + callstack.dur AND callstack.name LIKE 'H:Task Perform:%') + ($selectStartTime <= callstack.ts AND $selectEndTime >= callstack.ts + callstack.dur)) ORDER BY callstack.ts;`, { $funName: funName, $selectStartTime: selectStartTime, $selectEndTime: selectEndTime} ); @@ -4337,3 +4342,104 @@ export const queryTaskPoolTotalNum = (funName: string) => GROUP BY thread.tid;`, { $funName: funName} ); + + +export const queryFrameAnimationData = (): Promise> => + query( + 'queryFrameAnimationData', + `SELECT + a.id AS animationId, + (CASE + WHEN a.input_time not null THEN (a.input_time - R.start_ts) + ELSE (a.start_point- R.start_ts) + END) AS ts, + (a.start_point - R.start_ts) AS dynamicStartTs, + (a.end_point - R.start_ts) AS dynamicEndTs + FROM + animation AS a, + trace_range AS R + ORDER BY + ts;` + ); + +export const queryFrameDynamicData = (componentName: string): Promise> => + query( + 'queryFrameDynamicData', + `SELECT + d.id, + d.x, + d.y, + d.width, + d.height, + d.alpha, + d.name AS appName, + (d.end_time - R.start_ts) AS ts + FROM + dynamic_frame AS d, + trace_range AS R + WHERE + d.name = $componentName + ORDER BY + d.end_time;`, {$componentName: componentName} + ); + +export const queryFrameApp = (): Promise> => + query( + 'queryFrameApp', + `SELECT + DISTINCT d.name as appName + FROM + dynamic_frame AS d, + trace_range AS R + WHERE + d.end_time >= R.start_ts + AND + d.end_time <= R.end_ts;` + ); + +export const queryAnimationFrameFps = (startTime: number, endTime: number): Promise> => + query( + 'queryAnimationFrameFps', + `SELECT + count(*) as fps + FROM + dynamic_frame AS d, + trace_range AS R + WHERE + d.end_time >= (${startTime} + R.start_ts) + AND + d.end_time <= (${endTime} + R.start_ts)` + ); + +export const queryFrameSpacing = (appName: string): Promise> => + query( + 'queryFrameSpacing', + `SELECT + d.id, + d.width AS currentFrameWidth, + d.height AS currentFrameHeight, + d.name AS nameId, + (d.end_time - R.start_ts) AS currentTs, + d.x, + d.y + FROM + dynamic_frame AS d, + trace_range AS R + WHERE + d.name = $appName + ORDER BY + d.end_time;`, {$appName: appName} + ); + +export const queryPhysicalData = (): Promise> => + query( + 'queryPhysicalData', + `SELECT physical_width AS physicalWidth, + physical_height AS physicalHeight, + physical_frame_rate AS physicalFrameRate + FROM device_info;` + ); diff --git a/ide/src/trace/database/ui-worker/ProcedureWorker.ts b/ide/src/trace/database/ui-worker/ProcedureWorker.ts index 7d0814d2f..2754ddbbe 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorker.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorker.ts @@ -51,6 +51,9 @@ import { HeapSnapshotRender } from './ProcedureWorkerHeapSnapshot.js'; import { translateJsonString } from '../logic-worker/ProcedureLogicWorkerCommon.js'; import { AppStartupRender } from './ProcedureWorkerAppStartup.js'; import { SoRender } from './ProcedureWorkerSoInit.js'; +import { FrameDynamicRender } from './ProcedureWorkerFrameDynamic.js'; +import { FrameAnimationRender } from './ProcedureWorkerFrameAnimation.js'; +import { FrameSpacingRender } from './ProcedureWorkerFrameSpacing.js'; let dataList: any = {}; let dataList2: any = {}; @@ -99,6 +102,9 @@ export let renders: any = { clock: new ClockRender(), irq: new IrqRender(), jank: new JankRender(), + frameDynamicCurve: new FrameDynamicRender(), + frameAnimation: new FrameAnimationRender(), + frameSpacing: new FrameSpacingRender(), }; function match(type: string, req: RequestMessage) { diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerAppStartup.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerAppStartup.ts index 9f53fc9c8..d0aa7ed7b 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerAppStartup.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerAppStartup.ts @@ -42,7 +42,6 @@ export class AppStartupRender { paddingTop: 5, useCache: req.useCache || !(TraceRow.range?.refresh ?? false), }); - req.context.font = '11px sans-serif'; req.context.globalAlpha = 0.6; let find = false; let offset = 3; @@ -89,12 +88,13 @@ export class AppStartupStruct extends BaseStruct { ctx.fillStyle = ColorUtils.colorForTid(data.startName!); ctx.fillRect(data.frame.x, data.frame.y, data.frame.width, data.frame.height); if(data.frame.width > 7) { - ctx.fillStyle = '#fff'; ctx.textBaseline = 'middle'; - ctx.font = '8px sans-serif'; + ctx.lineWidth = 1; if (data.stepName === undefined) { data.stepName = `${AppStartupStruct.getStartupName(data.startName)} (${(data.dur! / 1000000).toFixed(2)}ms)` } + let textColor = ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.stepName || '', 0, ColorUtils.FUNC_COLOR.length)]; + ctx.fillStyle = ColorUtils.funcTextColor(textColor); drawString(ctx, data.stepName, 2, data.frame, data); } if (data === AppStartupStruct.selectStartupStruct) { diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts index e815fd529..d0fae42bc 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts @@ -91,7 +91,9 @@ export function ns2s(ns: number): string { export function isFrameContainPoint(frame: Rect, x: number, y: number): boolean { return x >= frame.x && x <= frame.x + frame.width && y >= frame.y && y <= frame.y + frame.height; } - +export const isSurroundingPoint = function (pointX: number, currentRect: Rect, unitPointXRange: number): boolean { + return (pointX >= currentRect.x - unitPointXRange) && pointX <= currentRect.x + unitPointXRange; +}; class FilterConfig { startNS: number = 0; endNS: number = 0; diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerFrameAnimation.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerFrameAnimation.ts new file mode 100644 index 000000000..1a3f5e7b9 --- /dev/null +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerFrameAnimation.ts @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { TraceRow } from '../../component/trace/base/TraceRow.js'; +import { BaseStruct, drawString, isFrameContainPoint, ns2x, Rect, Render } from './ProcedureWorkerCommon.js'; + +export class FrameAnimationRender extends Render { + renderMainThread( + req: { + useCache: boolean; + context: CanvasRenderingContext2D; + type: string; + }, + row: TraceRow + ): void { + let frameAnimationList: FrameAnimationStruct[] = row.dataList; + let frameAnimationFilter: FrameAnimationStruct[] = row.dataListCache; + frameAnimation( + frameAnimationList, + frameAnimationFilter, + TraceRow.range!.startNS, + TraceRow.range!.endNS, + TraceRow.range!.totalNS, + row.frame, + req.useCache || !TraceRow.range!.refresh + ); + req.context.beginPath(); + let find: boolean = false; + for (let index: number = 0; index < frameAnimationFilter.length; index++) { + let currentAnimationStruct: FrameAnimationStruct = frameAnimationFilter[index]; + FrameAnimationStruct.draw(req.context, index, currentAnimationStruct, row); + if (row.isHover && currentAnimationStruct.frame && + isFrameContainPoint(currentAnimationStruct.frame, row.hoverX, row.hoverY)) { + FrameAnimationStruct.hoverFrameAnimationStruct = currentAnimationStruct; + find = true; + } + } + if (!find && row.isHover) { + FrameAnimationStruct.hoverFrameAnimationStruct = undefined; + } + req.context.closePath(); + } +} + +let frameAnimation = function ( + frameAnimationList: FrameAnimationStruct[], + frameAnimationFilter: FrameAnimationStruct[], + startNS: number = 0, + endNS: number = 0, + totalNS: number, + frame: Rect, + use: boolean +): void { + if (use && frameAnimationFilter.length > 0) { + for (let index: number = 0; index < frameAnimationFilter.length; index++) { + let frameAnimationNode: FrameAnimationStruct = frameAnimationFilter[index]; + frameAnimationNode.frame = undefined; + FrameAnimationStruct.setFrameAnimation(frameAnimationNode, padding, startNS, endNS, totalNS, frame); + } + return; + } + frameAnimationFilter.length = 0; + if (frameAnimationList) { + for (let index: number = 0; index < frameAnimationList.length; index++) { + let currentFrameAnimation: FrameAnimationStruct = frameAnimationList[index]; + let currentResponseFrame: FrameAnimationStruct = JSON.parse(JSON.stringify(currentFrameAnimation)); + currentResponseFrame.status = 'Response delay'; + currentResponseFrame.dur = currentFrameAnimation.dynamicStartTs - currentFrameAnimation.ts; + if ((currentResponseFrame.ts || 0) + (currentResponseFrame.dur || 0) > startNS && + (currentResponseFrame.ts || 0) < endNS) { + FrameAnimationStruct.setFrameAnimation(currentResponseFrame, padding, startNS, + endNS || 0, totalNS || 0, frame); + frameAnimationFilter.push(currentResponseFrame); + } + let currentCompletionFrame: FrameAnimationStruct = JSON.parse(JSON.stringify(currentFrameAnimation)); + currentCompletionFrame.status = 'Completion delay'; + currentCompletionFrame.ts = currentFrameAnimation.dynamicStartTs; + currentCompletionFrame.dur = currentFrameAnimation.dynamicEndTs - currentFrameAnimation.dynamicStartTs; + if ((currentCompletionFrame.ts || 0) + (currentCompletionFrame.dur || 0) > startNS && + (currentCompletionFrame.ts || 0) < endNS) { + FrameAnimationStruct.setFrameAnimation(currentCompletionFrame, padding, startNS, + endNS || 0, totalNS || 0, frame); + frameAnimationFilter.push(currentCompletionFrame); + } + } + } +}; + +export class FrameAnimationStruct extends BaseStruct { + static hoverFrameAnimationStruct: FrameAnimationStruct | undefined; + static selectFrameAnimationStruct: FrameAnimationStruct | undefined; + ts: number = 0; + dur: number = 0; + status: string = ''; + animationId: number | undefined; + dynamicStartTs: number = 0; + dynamicEndTs: number = 0; + fps: number | undefined; + + static setFrameAnimation( + animationNode: FrameAnimationStruct, + padding: number, + startNS: number, + endNS: number, + totalNS: number, + frame: Rect + ): void { + let stateStartPointX: number; + let stateEndPointX: number; + if ((animationNode.ts || 0) < startNS) { + stateStartPointX = 0; + } else { + stateStartPointX = ns2x(animationNode.ts || 0, startNS, endNS, totalNS, frame); + } + if ((animationNode.ts || 0) + (animationNode.dur || 0) > endNS) { + stateEndPointX = frame.width; + } else { + stateEndPointX = ns2x((animationNode.ts || 0) + (animationNode.dur || 0), startNS, endNS, totalNS, frame); + } + let frameWidth: number = stateEndPointX - stateStartPointX <= unitIndex ? unitIndex : + stateEndPointX - stateStartPointX; + if (!animationNode.frame) { + animationNode.frame = new Rect(0, 0, 0, 0); + } + animationNode.frame.x = Math.floor(stateStartPointX); + animationNode.frame.y = frame.y + padding; + animationNode.frame.width = Math.ceil(frameWidth); + animationNode.frame.height = Math.floor(frame.height - padding * multiple); + } + + static draw( + ctx: CanvasRenderingContext2D, + index: number, + frameAnimationNode: FrameAnimationStruct, + row: TraceRow + ): void { + let isHover: boolean = row.isHover; + if (frameAnimationNode.frame) { + let nsToMillisecond = 1000_000; + ctx.globalAlpha = 1.0; + ctx.lineWidth = 1; + ctx.lineJoin = 'round'; + ctx.fillStyle = ColorUtils.ANIMATION_COLOR[6]; + ctx.fillRect(frameAnimationNode.frame.x, frameAnimationNode.frame.y + (multiple * padding), + frameAnimationNode.frame.width, frameAnimationNode.frame.height); + ctx.fillStyle = ColorUtils.ANIMATION_COLOR[3]; + ctx.textBaseline = 'middle'; + ctx.font = '8px sans-serif'; + drawString(ctx, `${frameAnimationNode.status} (${(frameAnimationNode.dur / nsToMillisecond).toFixed(6)} ms)`, textPadding, + frameAnimationNode.frame, frameAnimationNode); + ctx.lineWidth = 2; + if ((frameAnimationNode === FrameAnimationStruct.hoverFrameAnimationStruct && isHover) || + frameAnimationNode === FrameAnimationStruct.selectFrameAnimationStruct) { + ctx.globalAlpha = 0.8; + ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[3]; + ctx.strokeRect(frameAnimationNode.frame.x + padding, frameAnimationNode.frame.y + (multiple * padding), + frameAnimationNode.frame.width - padding, frameAnimationNode.frame.height - (multiple * padding)); + } else { + ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[2]; + ctx.strokeRect(frameAnimationNode.frame.x + padding, frameAnimationNode.frame.y + (multiple * padding), + frameAnimationNode.frame.width - padding, frameAnimationNode.frame.height - (multiple * padding)); + } + } + } +} + +const padding: number = 2; +const multiple: number = 2; +const unitIndex: number = 1; +const textPadding: number = 5; diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerFrameDynamic.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerFrameDynamic.ts new file mode 100644 index 000000000..bf57572c0 --- /dev/null +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerFrameDynamic.ts @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { TraceRow } from '../../component/trace/base/TraceRow.js'; +import { BaseStruct, isSurroundingPoint, ns2x, Rect, Render } from './ProcedureWorkerCommon.js'; +import { AnimationRanges } from '../../bean/FrameComponentBean.js'; +import { ColorUtils } from '../../component/trace/base/ColorUtils.js'; + +export class FrameDynamicRender extends Render { + renderMainThread( + req: { + useCache: boolean; + context: CanvasRenderingContext2D; + type: string; + animationRanges: AnimationRanges[]; + }, + row: TraceRow + ): void { + let frameDynamicList: FrameDynamicStruct[] = row.dataList; + let frameDynamicFilter: FrameDynamicStruct[] = row.dataListCache; + frameDynamic(frameDynamicList, frameDynamicFilter, row, req.animationRanges, req.useCache); + if (req.animationRanges.length > 0 && req.animationRanges[0] && frameDynamicFilter.length > 0) { + let modelType: string = row.getAttribute('modelType') || 'x'; + let [minValue, maxValue] = this.getMinAndMaxData(frameDynamicFilter, modelType); + let find: boolean = false; + let preDynamic: FrameDynamicStruct = frameDynamicFilter[0]; + let findStructList = frameDynamicFilter.filter(filter => + row.isHover && isSurroundingPoint(row.hoverX, filter.frame!, xScaleNumber)); + if (findStructList.length > 0) { + find = true; + let hoverIndex: number = 0; + if (findStructList.length > unitIndex) { + hoverIndex = Math.ceil(findStructList.length / multiple); + } + FrameDynamicStruct.hoverFrameDynamicStruct = findStructList[hoverIndex]; + } + let isDraw = false; + for (let index: number = 0; index < frameDynamicFilter.length; index++) { + let currDynamic: FrameDynamicStruct = frameDynamicFilter[index]; + this.refreshPointY(currDynamic, row, modelType, minValue, maxValue); + if (currDynamic.groupId === 0) { + if (currDynamic.ts > TraceRow.range!.startNS && currDynamic.ts < TraceRow.range!.endNS) { + isDraw = true; + this.drawSinglePoint(req.context, currDynamic, row, modelType, minValue, maxValue); + } + } else if (currDynamic.groupId !== invalidGroupId && index > 0 && currDynamic.groupId === preDynamic!.groupId) { + isDraw = true; + FrameDynamicStruct.draw(req.context, preDynamic, currDynamic, row, modelType); + } + FrameDynamicStruct.drawSelect(req.context, currDynamic, row); + preDynamic = currDynamic; + } + if(isDraw) { + this.drawDynamicPointYStr(req.context, frameDynamicFilter, row.frame, minValue, maxValue); + } + if (!find && row.isHover) { + FrameDynamicStruct.hoverFrameDynamicStruct = undefined; + } + } + } + + private drawSinglePoint( + ctx: CanvasRenderingContext2D, + currDynamic: FrameDynamicStruct, + row: TraceRow, + modelType: string, + minValue: number, + maxValue: number + ): void { + let smallArcRadius: number = 2; + // @ts-ignore + currDynamic.typeValue = currDynamic[modelType]; + currDynamic.frame!.y = row.frame.height - padding - + ((row.frame.height - padding * multiple) * ((currDynamic.typeValue || 0) - minValue) / (maxValue - minValue)); + ctx.beginPath(); + ctx.lineWidth = 1; + ctx.globalAlpha = 1; + ctx.arc(currDynamic.frame!.x, currDynamic.frame!.y, smallArcRadius, 0, multiple * Math.PI); + ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[2]; + ctx.fillStyle = ColorUtils.ANIMATION_COLOR[2]; + ctx.stroke(); + ctx.fill(); + ctx.closePath(); + } + + private refreshPointY( + curDynamic: FrameDynamicStruct, + row: TraceRow, + modelType: string, + minValue: number, + maxValue: number + ): void { + // @ts-ignore + let currDynamicValue = curDynamic[modelType]; + if (curDynamic.frame) { + let pointY = (row.frame.height - padding * multiple) * ((currDynamicValue - minValue) / (maxValue - minValue)); + curDynamic.frame.y = row.frame.height - padding - pointY; + } + }; + + private drawDynamicPointYStr( + ctx: CanvasRenderingContext2D, + frameDynamicFilter: FrameDynamicStruct[], + frame: Rect, + minValue: number, + maxValue: number + ): void { + if (frameDynamicFilter.length > 0) { + ctx.globalAlpha = 1; + ctx.lineWidth = 1; + ctx.fillStyle = ColorUtils.ANIMATION_COLOR[3]; + let minUnitValue: number = 10; + let totalValue = maxValue - minValue; + let pointYInterval = totalValue / (yScaleNumber - unitIndex); + for (let index = 0; index < yScaleNumber; index++) { + let pointYValue = minValue + pointYInterval * index; + let pointYHeight = (frame.height - padding * multiple) * (pointYValue - minValue) / totalValue; + let pointY = frame.height - multiple * padding - pointYHeight; + if (pointYValue !== 0) { + if (maxValue - minValue <= minUnitValue) { + ctx.fillText(`- ${pointYValue}`, 0, pointY); + } else { + ctx.fillText(`- ${Math.ceil(pointYValue)}`, 0, pointY); + } + } + } + } + }; + + private getMinAndMaxData(frameDynamicFilter: FrameDynamicStruct[], modelType: string): [number, number] { + let min: number = Math.min.apply(Math, frameDynamicFilter.map(filterData => { + // @ts-ignore + return filterData[modelType]; + })); + let max: number = Math.max.apply(Math, frameDynamicFilter.map(filterData => { + // @ts-ignore + return filterData[modelType]; + })); + + let yScaleMinValue: number = 1; + let yScaleMinSpacing: number = 10; + if (min === max) { + if (max <= yScaleMinValue) { + max = yScaleMinValue; + min = 0; + } else if (max <= yScaleMinSpacing) { + max = yScaleMinSpacing; + min = 0; + } else { + max += yScaleMinSpacing; + min -= yScaleMinSpacing; + } + } + return [min, max]; + }; +} + +let refreshDynamicFrame = function ( + frameDynamicFilter: FrameDynamicStruct[], + frame: Rect, + startNS: number, + endNS: number, + totalNS: number): void { + for (let index: number = 0; index < frameDynamicFilter.length; index++) { + let frameDynamicNode: FrameDynamicStruct = frameDynamicFilter[index]; + frameDynamicNode.frame = undefined; + FrameDynamicStruct.setFrameDynamic(frameDynamicNode, padding, startNS, endNS, totalNS, frame); + } +}; + +let refreshFilterDynamicFrame = function ( + frameDynamicFilter: FrameDynamicStruct[], + currentFrameDynamic: FrameDynamicStruct, + frame: Rect, + startNS: number, + endNS: number, + totalNS: number, + groupIdList: number[] +): void { + groupIdList.push(currentFrameDynamic.groupId!); + frameDynamicFilter.push(currentFrameDynamic); + FrameDynamicStruct.setFrameDynamic(currentFrameDynamic, padding, startNS, endNS, totalNS, frame); +}; + +let frameDynamic = function ( + frameDynamicList: FrameDynamicStruct[], + frameDynamicFilter: FrameDynamicStruct[], + row: TraceRow, + animationRanges: AnimationRanges[], + use: boolean +): void { + let startNS: number = TraceRow.range!.startNS; + let endNS: number = TraceRow.range!.endNS; + let totalNS: number = TraceRow.range!.totalNS; + let frame: Rect = row.frame; + if (use && !TraceRow.range!.refresh && frameDynamicFilter.length > 0) { + refreshDynamicFrame(frameDynamicFilter, frame, startNS, endNS, totalNS); + return; + } + frameDynamicFilter.length = 0; + if (frameDynamicList) { + let groupIdList: number[] = []; + for (let dataIndex: number = 0; dataIndex < frameDynamicList.length; dataIndex++) { + let currentDynamic: FrameDynamicStruct = frameDynamicList[dataIndex]; + currentDynamic.groupId = invalidGroupId; + for (let rangeIndex = 0; rangeIndex < animationRanges.length; rangeIndex++) { + let currentRange = animationRanges[rangeIndex]; + if (currentDynamic.ts >= currentRange.start && currentDynamic.ts <= currentRange.end) { + currentDynamic.groupId = currentRange.start; + break; + } + } + if (currentDynamic.ts < startNS && (dataIndex + unitIndex) < frameDynamicList.length && + frameDynamicList[dataIndex + unitIndex].ts >= startNS && currentDynamic.groupId !== invalidGroupId) { + refreshFilterDynamicFrame(frameDynamicFilter, currentDynamic, row.frame, startNS, endNS, totalNS, groupIdList); + } + if (currentDynamic.ts >= startNS && currentDynamic.ts <= endNS && currentDynamic.groupId !== invalidGroupId) { + refreshFilterDynamicFrame(frameDynamicFilter, currentDynamic, row.frame, startNS, endNS, totalNS, groupIdList); + } + if (currentDynamic.ts >= endNS && currentDynamic.groupId !== invalidGroupId) { + refreshFilterDynamicFrame(frameDynamicFilter, currentDynamic, row.frame, startNS, endNS, totalNS, groupIdList); + break; + } + } + let simpleGroup = groupIdList.filter(groupId => { + return groupId !== invalidGroupId && groupIdList.indexOf(groupId) === groupIdList.lastIndexOf(groupId); + }); + frameDynamicFilter.forEach(dynamic => { + if (simpleGroup.indexOf(dynamic.groupId!) > invalidGroupId) { + dynamic.groupId = 0; + } + }); + } +}; + +export class FrameDynamicStruct extends BaseStruct { + static hoverFrameDynamicStruct: FrameDynamicStruct | undefined; + static selectFrameDynamicStruct: FrameDynamicStruct | undefined; + ts: number = 0; + id: number | undefined; + x: number | undefined; + y: number | undefined; + width: number | undefined; + height: number | undefined; + alpha: number = 0; + appName: string | undefined; + groupId: number | undefined; + typeValue: number | undefined; + + static setFrameDynamic( + dynamicNode: FrameDynamicStruct, + padding: number, + startNS: number, + endNS: number, + totalNS: number, + frame: Rect + ): void { + let pointX: number = ns2x(dynamicNode.ts || 0, startNS, endNS, totalNS, frame); + if (!dynamicNode.frame) { + dynamicNode.frame = new Rect(0, 0, 0, 0); + } + dynamicNode.frame.x = Math.floor(pointX); + dynamicNode.frame.height = frame.height; + } + + static draw( + ctx: CanvasRenderingContext2D, + preDynamicStruct: FrameDynamicStruct, + currDynamicStruct: FrameDynamicStruct, + row: TraceRow, + modelType: string + ): void { + if (preDynamicStruct.frame && currDynamicStruct.frame) { + // @ts-ignore + preDynamicStruct.typeValue = preDynamicStruct[modelType]; + // @ts-ignore + currDynamicStruct.typeValue = currDynamicStruct[modelType]; + if (preDynamicStruct.typeValue === currDynamicStruct.typeValue) { + ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[1]; + } else { + ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[2]; + } + ctx.beginPath(); + ctx.globalAlpha = 1; + ctx.lineWidth = 3; + ctx.lineJoin = 'round'; + ctx.moveTo(preDynamicStruct.frame.x, preDynamicStruct.frame.y); + ctx.lineTo(currDynamicStruct.frame.x, currDynamicStruct.frame.y); + ctx.stroke(); + ctx.closePath(); + FrameDynamicStruct.drawSelect(ctx, preDynamicStruct, row); + } + } + + static drawSelect( + ctx: CanvasRenderingContext2D, + currDynamicStruct: FrameDynamicStruct, + row: TraceRow + ): void { + if ((currDynamicStruct === FrameDynamicStruct.hoverFrameDynamicStruct && row.isHover) || + currDynamicStruct === FrameDynamicStruct.selectFrameDynamicStruct) { + FrameDynamicStruct.drawSelectOrHoverArc(ctx, currDynamicStruct); + } + if (row.getAttribute('check-type') === '2' && FrameDynamicStruct.isSelect(currDynamicStruct)) { + FrameDynamicStruct.drawSelectOrHoverArc(ctx, currDynamicStruct); + } + } + + static drawSelectOrHoverArc( + ctx: CanvasRenderingContext2D, + currDynamicStruct: FrameDynamicStruct + ): void { + if (currDynamicStruct.frame && + currDynamicStruct.ts > TraceRow.range!.startNS && + currDynamicStruct.ts < TraceRow.range!.endNS) { + let bigArcRadius: number = 3; + ctx.beginPath(); + ctx.lineWidth = 3; + ctx.globalAlpha = 1; + ctx.arc(currDynamicStruct.frame.x, currDynamicStruct.frame.y, bigArcRadius, 0, multiple * Math.PI); + ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[7]; + ctx.fillStyle = ColorUtils.ANIMATION_COLOR[9]; + ctx.stroke(); + ctx.fill(); + } + } + + static isSelect(currDynamicStruct: FrameDynamicStruct): boolean | 0 | undefined { + return TraceRow.rangeSelectObject && + TraceRow.rangeSelectObject.startNS && + TraceRow.rangeSelectObject.endNS && + currDynamicStruct.ts >= TraceRow.rangeSelectObject.startNS && + currDynamicStruct.ts <= TraceRow.rangeSelectObject.endNS; + } +} + +const padding: number = 3; +const invalidGroupId: number = -1; +const multiple: number = 2; +const unitIndex: number = 1; +const yScaleNumber: number = 5; +const xScaleNumber: number = 2; diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerFrameSpacing.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerFrameSpacing.ts new file mode 100644 index 000000000..e59f6d5cb --- /dev/null +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerFrameSpacing.ts @@ -0,0 +1,385 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 { TraceRow } from '../../component/trace/base/TraceRow.js'; +import { BaseStruct, isSurroundingPoint, ns2x, Rect, Render } from './ProcedureWorkerCommon.js'; +import { AnimationRanges } from '../../bean/FrameComponentBean.js'; +import { ColorUtils } from '../../component/trace/base/ColorUtils.js'; + +export class FrameSpacingRender extends Render { + renderMainThread( + req: { + useCache: boolean; + context: CanvasRenderingContext2D; + type: string; + frameRate: number + animationRanges: AnimationRanges[] + }, + row: TraceRow + ): void { + let frameSpacingList = row.dataList; + let frameSpacingFilter = row.dataListCache; + this.frameSpacing( + frameSpacingList, + frameSpacingFilter, + TraceRow.range!.startNS, + TraceRow.range!.endNS, + TraceRow.range!.totalNS, + row.frame, + req.animationRanges, + req.useCache || !TraceRow.range!.refresh + ); + this.render(req, frameSpacingFilter, row); + } + + private render(req: { useCache: boolean; context: CanvasRenderingContext2D; type: string; frameRate: number; + animationRanges: AnimationRanges[] }, frameSpacingFilter: Array, + row: TraceRow) : void { + if (req.animationRanges.length > 0 && req.animationRanges[0] && frameSpacingFilter.length > 0) { + let find = false; + let preFrameSpacing: FrameSpacingStruct = frameSpacingFilter[0]; + // @ts-ignore + let smallTickStandard = smallTick[req.frameRate]; + let [minValue, maxValue] = this.maxMinData(smallTickStandard.firstLine, + smallTickStandard.thirdLine, frameSpacingFilter); + let findStructList = frameSpacingFilter.filter(filter => + row.isHover && isSurroundingPoint(row.hoverX, filter.frame!, xScaleNumber)); + if (findStructList.length > 0) { + find = true; + let hoverIndex: number = 0; + if (findStructList.length > unitIndex) { + hoverIndex = Math.ceil(findStructList.length / multiple); + } + FrameSpacingStruct.hoverFrameSpacingStruct = findStructList[hoverIndex]; + } + let isDraw = false; + for (let index: number = 0; index < frameSpacingFilter.length; index++) { + let currentStruct = frameSpacingFilter[index]; + FrameSpacingStruct.refreshHoverStruct(preFrameSpacing, currentStruct, row, minValue, maxValue); + if (currentStruct.groupId === 0) { + if (currentStruct.currentTs > TraceRow.range!.startNS && currentStruct.currentTs < TraceRow.range!.endNS) { + isDraw = true; + this.drawPoint(req.context, currentStruct, row, minValue, maxValue); + } + this.resetData(currentStruct); + } else if (currentStruct.groupId !== invalidGroupId) { + if (index === 0 || currentStruct.groupId !== preFrameSpacing!.groupId) { + this.resetData(currentStruct); + } else { + isDraw = true; + FrameSpacingStruct.draw(req.context, preFrameSpacing, currentStruct, row, minValue, maxValue); + } + } + FrameSpacingStruct.drawSelect(currentStruct, req.context, row); + preFrameSpacing = currentStruct; + } + if (isDraw) { + this.drawDashedLines(Object.values(smallTickStandard), req, row, minValue, maxValue); + } + if (!find && row.isHover) { + FrameSpacingStruct.hoverFrameSpacingStruct = undefined; + } + } + } + + private resetData(currentStruct: FrameSpacingStruct): void { + currentStruct.frameSpacingResult = 0; + currentStruct.preFrameWidth = 0; + currentStruct.preFrameHeight = 0; + currentStruct.preTs = 0; + } + + private drawPoint(ctx: CanvasRenderingContext2D, currentStruct: FrameSpacingStruct, + row: TraceRow, minValue: number, maxValue: number): void { + let currentPointY = row.frame.height - Math.floor((currentStruct.frameSpacingResult! - + minValue) * (row.frame.height - padding * multiple) / + (maxValue - minValue)) - padding; + ctx.beginPath(); + ctx.lineWidth = 1; + ctx.globalAlpha = 1; + ctx.arc(currentStruct.frame!.x, currentPointY, multiple, 0, multiple * Math.PI); + ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[2]; + ctx.fillStyle = ColorUtils.ANIMATION_COLOR[2]; + ctx.stroke(); + ctx.fill(); + ctx.closePath(); + } + + private drawDashedLines( + dashedLines: number[], + req: { useCache: boolean; context: CanvasRenderingContext2D; type: string; frameRate: number }, + row: TraceRow, + minVale: number, + maxValue: number + ): void { + for (let i = 0; i < dashedLines.length; i++) { + FrameSpacingStruct.drawParallelLine(req.context, row.frame, dashedLines, i, minVale, maxValue); + } + } + + private frameSpacing( + frameSpacingList: Array, + frameSpacingFilter: Array, + startNS: number, + endNS: number, + totalNS: number, + frame: Rect, + animationRanges: AnimationRanges[], + use: boolean + ): void { + if (use && frameSpacingFilter.length > 0) { + for (let index = 0, len = frameSpacingFilter.length; index < len; index++) { + FrameSpacingStruct.setFrameSpacingFrame(frameSpacingFilter[index], startNS, endNS, totalNS, frame); + } + return; + } + frameSpacingFilter.length = 0; + if (frameSpacingList) { + let groupIdList: number[] = []; + for (let index = 0; index < frameSpacingList.length; index++) { + let item = frameSpacingList[index]; + item.groupId = invalidGroupId; + for (let rangeIndex = 0; rangeIndex < animationRanges.length; rangeIndex++) { + let currentRange = animationRanges[rangeIndex]; + if (item.currentTs >= currentRange.start && item.currentTs <= currentRange.end) { + item.groupId = currentRange.start; + break; + } + } + if (item.currentTs < startNS && index + unitIndex < frameSpacingList.length && + frameSpacingList[index + unitIndex].currentTs >= startNS && item.groupId !== invalidGroupId) { + this.refreshFrame(frameSpacingFilter, item, startNS, endNS, totalNS, frame, groupIdList); + } + if (item.currentTs >= startNS && item.currentTs <= endNS && item.groupId !== invalidGroupId) { + this.refreshFrame(frameSpacingFilter, item, startNS, endNS, totalNS, frame, groupIdList); + } + if (item.currentTs > endNS && item.groupId !== invalidGroupId) { + this.refreshFrame(frameSpacingFilter, item, startNS, endNS, totalNS, frame, groupIdList); + break; + } + } + this.grouping(groupIdList, frameSpacingFilter); + } + } + + private grouping(groupIdList: number[], frameSpacingFilter: Array): void { + let simpleGroup = groupIdList.filter(groupId => { + return groupId !== invalidGroupId && groupIdList.indexOf(groupId) === groupIdList.lastIndexOf(groupId); + }); + frameSpacingFilter.forEach(frameSpacing => { + if (simpleGroup.indexOf(frameSpacing.groupId!) > invalidGroupId) { + frameSpacing.groupId = 0; + } + }); + } + + private refreshFrame(frameSpacingFilter: Array, item: FrameSpacingStruct, + startNS: number, endNS: number, totalNS: number, frame: Rect, groupIdList: number[]): void { + frameSpacingFilter.push(item); + FrameSpacingStruct.setFrameSpacingFrame(item, startNS, endNS, totalNS, frame); + groupIdList.push(item.groupId!); + } + + private maxMinData(tickStandardMin: number, tickStandardMax: number, filter: FrameSpacingStruct[]): [number, number] { + let min = Math.min.apply(Math, filter.map(filterData => { + return filterData.frameSpacingResult!; + })); + let max = Math.max.apply(Math, filter.map(filterData => { + return filterData.frameSpacingResult!; + })); + if (max < tickStandardMax) { + max = tickStandardMax + 3; + } + if (min > tickStandardMin) { + min = tickStandardMin; + } + return [min, max]; + } +} + +export class FrameSpacingStruct extends BaseStruct { + static hoverFrameSpacingStruct: FrameSpacingStruct | undefined; + static selectFrameSpacingStruct: FrameSpacingStruct | undefined; + static physicalWidth: number | undefined; + static physicalHeight: number | undefined; + preTs: number | undefined; + currentTs: number = 0; + frameSpacingResult: number | undefined; + id: number = 0; + groupId: number | undefined; + currentFrameWidth: number | undefined; + preFrameWidth: number | undefined; + currentFrameHeight: number | undefined; + preFrameHeight: number | undefined; + x: number | undefined; + y: number | undefined; + + static setFrameSpacingFrame( + frameSpacingNode: FrameSpacingStruct, + startNS: number, + endNS: number, + totalNS: number, + row: Rect + ): void { + let pointX = ns2x(frameSpacingNode.currentTs || 0, startNS, endNS, totalNS, row); + if (!frameSpacingNode.frame) { + frameSpacingNode.frame = new Rect(0, 0, 0, 0); + } + frameSpacingNode.frame.x = Math.floor(pointX); + } + + static isSelect(currSpacingStruct: FrameSpacingStruct) : boolean | 0 | undefined { + return TraceRow.rangeSelectObject && + TraceRow.rangeSelectObject.startNS && + TraceRow.rangeSelectObject.endNS && + currSpacingStruct.currentTs >= TraceRow.rangeSelectObject.startNS && + currSpacingStruct.currentTs <= TraceRow.rangeSelectObject.endNS; + } + + static refreshHoverStruct(preFrameSpacing: FrameSpacingStruct, frameSpacing: FrameSpacingStruct, + row: TraceRow, minValue: number, maxValue: number): void { + if (frameSpacing.frame) { + let currentPointY = row.frame.height - Math.floor((frameSpacing.frameSpacingResult! - + minValue) * (row.frame.height - padding * multiple) / + (maxValue - minValue)) - padding; + frameSpacing.frame.y = currentPointY; + } + }; + + static draw( + ctx: CanvasRenderingContext2D, + preFrameSpacing: FrameSpacingStruct, + currentStruct: FrameSpacingStruct, + rowFrame: TraceRow, + minValue: number, + maxValue: number + ): void { + if (currentStruct.frame && preFrameSpacing.frame) { + this.drawPolyline(ctx, preFrameSpacing, currentStruct, rowFrame, minValue, maxValue); + } + } + + static drawSelect(currentStruct: FrameSpacingStruct, ctx: CanvasRenderingContext2D, + rowFrame: TraceRow): void { + if (currentStruct.frame && + currentStruct.currentTs > TraceRow.range!.startNS && + currentStruct.currentTs < TraceRow.range!.endNS) { + if ((currentStruct === FrameSpacingStruct.hoverFrameSpacingStruct && rowFrame.isHover) || + currentStruct === FrameSpacingStruct.selectFrameSpacingStruct) { + ctx.lineWidth = 3; + ctx.beginPath(); + ctx.arc(currentStruct.frame.x, currentStruct.frame.y, selectRadius, 0, multiple * Math.PI); + ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[7]; + ctx.lineWidth = 2; + ctx.globalAlpha = 1; + ctx.fillStyle = ColorUtils.ANIMATION_COLOR[9]; + ctx.stroke(); + ctx.fill(); + ctx.closePath(); + } + } + if (rowFrame.getAttribute('check-type') === '2' && FrameSpacingStruct.isSelect(currentStruct)) { + ctx.beginPath(); + ctx.lineWidth = 3; + ctx.arc(currentStruct.frame!.x, currentStruct.frame!.y, selectRadius, 0, multiple * Math.PI); + ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[7]; + ctx.fillStyle = ColorUtils.ANIMATION_COLOR[9]; + ctx.lineWidth = 2; + ctx.globalAlpha = 1; + ctx.stroke(); + ctx.fill(); + ctx.closePath(); + } + } + + static drawParallelLine( + ctx: CanvasRenderingContext2D, + rowFrame: Rect, + dashedLines: number[], + index: number, + minValue: number, + maxValue: number + ): void { + let pointY = rowFrame.height - Math.floor((dashedLines[index] - minValue) * + (rowFrame.height - padding * multiple) / (maxValue - minValue)) - padding; + let lineDash = 10; + let textPadding = 5; + ctx.beginPath(); + ctx.lineWidth = 2; + ctx.setLineDash([lineDash]); + ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[6]; + ctx.fillStyle = ColorUtils.ANIMATION_COLOR[6]; + ctx.moveTo(0, pointY); + ctx.lineTo(rowFrame.width, pointY); + ctx.stroke(); + ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[8]; + ctx.fillStyle = ColorUtils.ANIMATION_COLOR[8]; + ctx.fillText(dashedLines[index].toString(), 0, pointY - textPadding); + ctx.closePath(); + } + + static drawPolyline( + ctx: CanvasRenderingContext2D, + preFrameSpacing: FrameSpacingStruct, + currentStruct: FrameSpacingStruct, + rowFrame: TraceRow, + minValue: number, + maxValue: number + ): void { + ctx.beginPath(); + let prePointY = rowFrame.frame.height - Math.floor((preFrameSpacing.frameSpacingResult! - + minValue) * (rowFrame.frame.height - padding * multiple) / + (maxValue - minValue)) - padding; + let currentPointY = rowFrame.frame.height - Math.floor((currentStruct.frameSpacingResult! - + minValue) * (rowFrame.frame.height - padding * multiple) / + (maxValue - minValue)) - padding; + if (preFrameSpacing.frame && currentStruct.frame) { + ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[2]; + ctx.fillStyle = ColorUtils.ANIMATION_COLOR[2]; + ctx.lineWidth = 2; + ctx.setLineDash([0]); + ctx.moveTo(preFrameSpacing.frame.x, prePointY); + ctx.lineTo(currentStruct.frame.x, currentPointY); + ctx.stroke(); + ctx.closePath(); + FrameSpacingStruct.drawSelect(preFrameSpacing, ctx, rowFrame); + } + } +} + +const padding = 3; +const invalidGroupId: number = -1; +const multiple: number = 2; +const unitIndex: number = 1; +const selectRadius: number = 3; +const xScaleNumber: number = 2; + +const smallTick = { + 60: { + firstLine: 11.4, + secondLine: 13, + thirdLine: 14.6 + }, + 90: { + firstLine: 13.7, + secondLine: 19.4, + thirdLine: 25 + }, + 120: { + firstLine: 13.7, + secondLine: 19.4, + thirdLine: 25 + } +}; -- Gitee From 8f42c6356d65d7511a400af964d852f501b7dd8c Mon Sep 17 00:00:00 2001 From: jichuan Date: Thu, 27 Jul 2023 15:03:59 +0800 Subject: [PATCH 07/14] Solving the Compilation Problem Signed-off-by: jichuan --- trace_streamer/build_operator.sh | 2 -- trace_streamer/gn/CONFIG.gn | 3 ++- trace_streamer/prebuilts/patch_hiperf/BUILD.gn | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/trace_streamer/build_operator.sh b/trace_streamer/build_operator.sh index ac4a134e4..3d46b718c 100755 --- a/trace_streamer/build_operator.sh +++ b/trace_streamer/build_operator.sh @@ -80,8 +80,6 @@ if [ "$is_clean" == "true" ];then else prebuilts/$gn_path/$gn gen out/"$target_dir""$ext"/$subsys_name/$part_name --args='is_debug='"$is_debug"' target="'"$target"'" target_os="'"$target_os"'"' echo "begin to build ..." - mkdir -p out/windows - touch out/windows/trace_streamer.exe prebuilts/$gn_path/$ninja -C out/"$target_dir""$ext"/$subsys_name/$part_name if [ $target_dir == "linux" ] && [ -f "out/$target_dir$ext/$subsys_name/$part_name/trace_streamer" ];then mkdir -p out/linux diff --git a/trace_streamer/gn/CONFIG.gn b/trace_streamer/gn/CONFIG.gn index 8b4791d99..cf03004e2 100755 --- a/trace_streamer/gn/CONFIG.gn +++ b/trace_streamer/gn/CONFIG.gn @@ -78,11 +78,12 @@ if (target == "wasm") { exit(-1) } +trace_cfg_path = "//gn:trace_cfg" print("platform " + target_os) default_configs = [ "//gn:symbols", "//gn:default", - "//gn:trace_cfg", + trace_cfg_path, ] hiperf_default_configs = [ "//gn:symbols", diff --git a/trace_streamer/prebuilts/patch_hiperf/BUILD.gn b/trace_streamer/prebuilts/patch_hiperf/BUILD.gn index 252d1d034..4767b9b63 100644 --- a/trace_streamer/prebuilts/patch_hiperf/BUILD.gn +++ b/trace_streamer/prebuilts/patch_hiperf/BUILD.gn @@ -16,7 +16,7 @@ import("../../build/ts.gni") ohos_source_set("elf") { subsystem_name = "developtools" part_name = "smartperf_host" - configs -= [ "../../gn:trace_cfg" ] + configs -= [ trace_cfg_path ] configs += [ "../../gn:hiperf_trace_cfg" ] sources = [ "include/elf_parser.h", @@ -36,7 +36,7 @@ ohos_source_set("elf") { ] } ohos_source_set("hiperf_src") { - configs -= [ "../../gn:trace_cfg" ] + configs -= [ trace_cfg_path ] configs += [ "../../gn:hiperf_trace_cfg" ] subsystem_name = "developtools" part_name = "smartperf_host" -- Gitee From 654d72a0c10fc4208c99a57443ea848e67e8cbd2 Mon Sep 17 00:00:00 2001 From: jichuan Date: Thu, 27 Jul 2023 15:06:48 +0800 Subject: [PATCH 08/14] support parse arkts && fix code style Signed-off-by: jichuan --- trace_streamer/.gn | 0 trace_streamer/BUILD.gn | 2 +- trace_streamer/build.sh | 16 +- trace_streamer/build/config.gni | 21 -- trace_streamer/build/protoc.sh | 10 +- trace_streamer/build/protoc_w.sh | 2 +- trace_streamer/build/ts.gni | 83 +++--- trace_streamer/build_operator.sh | 24 +- trace_streamer/doc/app_startup.md | 23 ++ trace_streamer/doc/des_tables.md | 133 ++++++++- .../doc/image/app_startup/1689415472707.png | Bin 0 -> 144045 bytes trace_streamer/gn/BUILD.gn | 3 - trace_streamer/gn/CONFIG.gn | 1 - trace_streamer/gn/toolchain/BUILD.gn | 6 +- trace_streamer/pare_third_party.sh | 6 +- .../prebuilts/patch_hiperf/BUILD.gn | 2 +- trace_streamer/sdk/demo_sdk/BUILD.gn | 11 +- trace_streamer/sdk/demo_sdk/test/BUILD.gn | 2 +- trace_streamer/sdk/dubai_sdk/BUILD.gn | 11 +- trace_streamer/sdk/dubai_sdk/test/BUILD.gn | 2 +- trace_streamer/src/BUILD.gn | 259 +++++++++--------- trace_streamer/src/base/BUILD.gn | 20 +- trace_streamer/src/base/clock_filter.cpp | 31 ++- trace_streamer/src/base/clock_filter.h | 8 +- trace_streamer/src/base/file.cpp | 2 +- trace_streamer/src/base/file.h | 4 +- .../src/base/htrace_plugin_time_parser.cpp | 6 +- .../src/base/htrace_plugin_time_parser.h | 4 +- trace_streamer/src/base/index_map.cpp | 4 +- trace_streamer/src/base/index_map.h | 5 +- trace_streamer/src/base/log.h | 4 +- trace_streamer/src/base/parting_string.cpp | 6 +- trace_streamer/src/base/parting_string.h | 2 +- .../src/base/sqlite_ext/sqlite_ext_funcs.cpp | 26 +- trace_streamer/src/base/string_to_numerical.h | 2 +- trace_streamer/src/base/ts_common.cpp | 3 +- trace_streamer/src/base/ts_common.h | 2 +- trace_streamer/src/filter/BUILD.gn | 15 +- .../src/filter/animation_filter.cpp | 11 +- .../src/filter/app_start_filter.cpp | 30 +- trace_streamer/src/filter/clock_filter_ex.h | 18 +- trace_streamer/src/filter/frame_filter.cpp | 11 +- trace_streamer/src/filter/frame_filter.h | 1 - .../src/filter/native_hook_filter.cpp | 14 +- .../filter/offline_symbolization_filter.cpp | 6 +- .../src/filter/offline_symbolization_filter.h | 12 +- trace_streamer/src/filter/process_filter.cpp | 2 +- trace_streamer/src/include/BUILD.gn | 4 +- trace_streamer/src/main.cpp | 19 +- trace_streamer/src/parser/BUILD.gn | 26 +- .../bytrace_parser/bytrace_event_parser.cpp | 2 +- .../src/parser/ebpf_parser/BUILD.gn | 6 +- .../ebpf_parser/bio_latency_data_parser.cpp | 4 +- .../parser/ebpf_parser/ebpf_data_reader.cpp | 15 +- .../ebpf_parser/file_system_data_parser.cpp | 2 +- .../ebpf_parser/paged_memory_data_parser.cpp | 4 +- .../src/parser/hiperf_parser/BUILD.gn | 15 +- .../parser/hiperf_parser/perf_data_parser.cpp | 7 +- .../parser/htrace_pbreader_parser/BUILD.gn | 58 ++-- .../htrace_clock_detail_parser.cpp | 18 +- .../htrace_cpu_data_parser.cpp | 1 - .../htrace_cpu_data_parser.h | 1 - .../htrace_event_parser.cpp | 7 +- .../htrace_js_cpu_profiler_parser.cpp | 118 ++++++++ .../htrace_js_cpu_profiler_parser.h | 39 +++ .../htrace_js_memory_parser.cpp | 45 ++- .../htrace_js_memory_parser.h | 6 + .../htrace_network_parser.cpp | 2 +- .../htrace_pbreader_parser/htrace_parser.cpp | 21 +- .../htrace_pbreader_parser/htrace_parser.h | 7 - .../src/parser/print_event_parser.cpp | 9 +- trace_streamer/src/proto_reader/BUILD.gn | 5 +- .../src/proto_reader/include/data_area.h | 4 +- .../src/proto_reader/proto_reader.cpp | 6 +- .../src/proto_reader/protoc_plugin/BUILD.gn | 7 +- .../protoc_plugin/proto_reader_plugin.cpp | 1 - trace_streamer/src/protos/protogen.sh | 12 +- trace_streamer/src/protos/protos.gni | 2 +- trace_streamer/src/protos/services/BUILD.gn | 10 +- .../protos/types/plugins/agent_data/BUILD.gn | 12 +- .../types/plugins/bytrace_plugin/BUILD.gn | 16 +- .../protos/types/plugins/cpu_data/BUILD.gn | 22 +- .../protos/types/plugins/diskio_data/BUILD.gn | 22 +- .../plugins/ftrace_data/default/BUILD.gn | 18 +- .../protos/types/plugins/hidump_data/BUILD.gn | 22 +- .../protos/types/plugins/hiebpf_data/BUILD.gn | 8 +- .../protos/types/plugins/hilog_data/BUILD.gn | 22 +- .../types/plugins/hiperf_call_plugin/BUILD.gn | 10 +- .../protos/types/plugins/hiperf_data/BUILD.gn | 18 +- .../types/plugins/hisysevent_data/BUILD.gn | 22 +- .../protos/types/plugins/js_memory/BUILD.gn | 22 +- .../plugins/js_memory/js_heap_config.proto | 5 +- .../protos/types/plugins/memory_data/BUILD.gn | 22 +- .../protos/types/plugins/native_hook/BUILD.gn | 22 +- .../types/plugins/network_data/BUILD.gn | 22 +- .../types/plugins/process_data/BUILD.gn | 22 +- .../protos/types/plugins/sample_data/BUILD.gn | 8 +- .../protos/types/plugins/stream_data/BUILD.gn | 8 +- .../protos/types/plugins/test_data/BUILD.gn | 10 +- trace_streamer/src/rpc/rpc_server.cpp | 1 - trace_streamer/src/rpc/rpc_server.h | 2 +- trace_streamer/src/table/BUILD.gn | 8 +- trace_streamer/src/table/base/BUILD.gn | 4 +- trace_streamer/src/table/base/span_join.h | 2 +- trace_streamer/src/table/ftrace/BUILD.gn | 4 +- .../src/table/ftrace/process_table.cpp | 2 - trace_streamer/src/table/hi_sysevent/BUILD.gn | 4 +- trace_streamer/src/table/js_memory/BUILD.gn | 6 + .../src/table/js_memory/js_config_table.cpp | 79 ++++++ .../src/table/js_memory/js_config_table.h | 55 ++++ .../js_memory/js_cpu_profiler_node_table.cpp | 99 +++++++ .../js_memory/js_cpu_profiler_node_table.h | 55 ++++ .../js_cpu_profiler_sample_table.cpp | 71 +++++ .../js_memory/js_cpu_profiler_sample_table.h | 55 ++++ .../table/js_memory/js_heap_files_table.cpp | 6 +- trace_streamer/src/table/monitor/BUILD.gn | 4 +- trace_streamer/src/table/native_hook/BUILD.gn | 4 +- trace_streamer/src/trace_data/BUILD.gn | 4 +- .../src/trace_data/trace_data_cache.cpp | 15 +- .../src/trace_data/trace_data_cache_base.h | 3 + .../trace_data/trace_data_cache_reader.cpp | 13 + .../src/trace_data/trace_data_cache_reader.h | 5 +- .../trace_data/trace_data_cache_writer.cpp | 15 + .../src/trace_data/trace_data_cache_writer.h | 5 +- .../src/trace_data/trace_stdtype.cpp | 172 ++++++++++-- trace_streamer/src/trace_data/trace_stdtype.h | 135 +++++++-- .../trace_streamer/trace_streamer_filters.h | 4 - .../trace_streamer_selector.cpp | 4 - trace_streamer/src/version.cpp | 4 +- trace_streamer/src/version.h | 4 +- trace_streamer/test/BUILD.gn | 28 +- .../test/test_fuzzer/bytrace_fuzzer/BUILD.gn | 1 - .../test/test_fuzzer/htrace_fuzzer/BUILD.gn | 1 - .../test/test_fuzzer/selector_fuzzer/BUILD.gn | 1 - trace_streamer/test/test_ts.gni | 1 - .../test/unittest/app_start_filter_test.cpp | 34 ++- .../test/unittest/bytrace_parser_test.cpp | 2 +- .../test/unittest/event_parser_test.cpp | 2 +- .../test/unittest/hidump_parser_test.cpp | 2 +- .../unittest/htrace_event_parser_test.cpp | 1 - .../test/unittest/htrace_mem_parser_test.cpp | 2 +- .../unittest/htrace_sys_mem_parser_test.cpp | 2 +- .../unittest/htrace_sys_vmem_parser_test.cpp | 2 +- .../test/unittest/parser_pbreader_test.cpp | 24 +- .../test/unittest/smaps_parser_test.cpp | 2 +- trace_streamer/test/unittest/table_test.cpp | 6 +- .../test/unittest/task_pool_filter_test.cpp | 1 - 147 files changed, 1807 insertions(+), 831 deletions(-) mode change 100644 => 100755 trace_streamer/.gn create mode 100644 trace_streamer/doc/app_startup.md create mode 100644 trace_streamer/doc/image/app_startup/1689415472707.png create mode 100644 trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_cpu_profiler_parser.cpp create mode 100644 trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_cpu_profiler_parser.h create mode 100644 trace_streamer/src/table/js_memory/js_config_table.cpp create mode 100644 trace_streamer/src/table/js_memory/js_config_table.h create mode 100644 trace_streamer/src/table/js_memory/js_cpu_profiler_node_table.cpp create mode 100644 trace_streamer/src/table/js_memory/js_cpu_profiler_node_table.h create mode 100644 trace_streamer/src/table/js_memory/js_cpu_profiler_sample_table.cpp create mode 100644 trace_streamer/src/table/js_memory/js_cpu_profiler_sample_table.h mode change 100755 => 100644 trace_streamer/test/unittest/app_start_filter_test.cpp diff --git a/trace_streamer/.gn b/trace_streamer/.gn old mode 100644 new mode 100755 diff --git a/trace_streamer/BUILD.gn b/trace_streamer/BUILD.gn index 1bcdb155d..557e4405a 100644 --- a/trace_streamer/BUILD.gn +++ b/trace_streamer/BUILD.gn @@ -21,7 +21,7 @@ group("trace_streamer") { } else if (is_protoc) { deps = [ "${THIRD_PARTY}/protobuf:protoc" ] } else if (is_spb) { - deps = [ "src/proto_reader/protoc_plugin:protoreader_plugin" ] + deps = [ "src/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})" ] } else if (is_sdkdemo) { deps = [ "sdk/demo_sdk:trace_streamer_sdk_builtin" ] } else if (is_dubai_sdk) { diff --git a/trace_streamer/build.sh b/trace_streamer/build.sh index e1cb2f2ab..1a2737acc 100755 --- a/trace_streamer/build.sh +++ b/trace_streamer/build.sh @@ -39,15 +39,19 @@ usage="Usage: $basename $0 wasm/test/fuzz/protoc debug/release/clean" ./dl_tools.sh $gn_path if { [ "$1" == "dubaisdk" ] || [ "$1" == "sdkdemo" ] || [ "$1" == "wasm" ] || [ "$1" == "test" ] || [ "$1" == "fuzz" ]; } && [ "$#" -ne 0 ];then - if [ ! -f "out/$1/clang_x64/developtools/profiler/protoc" ] && [ "$1" != "protoc" ];then + TARGET_DIR=$1 + if [[ $PARAMS == *"debug"* ]]; then + TARGET_DIR=$1"_debug" + fi + if [ ! -f "out/$TARGET_DIR/clang_x64/developtools/smartperf_host/protoc" ] && [ "$1" != "protoc" ];then ./build.sh protoc - mkdir -p out/$1/clang_x64/developtools/profiler - cp out/$target_os/clang_x64/developtools/profiler/protoc out/$1/clang_x64/developtools/profiler/protoc + mkdir -p out/$TARGET_DIR/clang_x64/developtools/smartperf_host + cp out/$target_os/clang_x64/developtools/smartperf_host/protoc out/$TARGET_DIR/clang_x64/developtools/smartperf_host/protoc fi - if [ ! -f "out/$1/clang_x64/developtools/profiler/protoreader_plugin" ] && [ "$1" != "spb" ] && [ -f "out/$1/clang_x64/developtools/profiler/protoc" ];then + if [ ! -f "out/$TARGET_DIR/clang_x64/developtools/smartperf_host/protoreader_plugin" ] && [ "$1" != "spb" ] && [ -f "out/$TARGET_DIR/clang_x64/developtools/smartperf_host/protoc" ];then ./build.sh spb - mkdir -p out/$1/clang_x64/developtools/profiler - cp out/$target_os/clang_x64/developtools/profiler/protoreader_plugin out/$1/clang_x64/developtools/profiler/protoreader_plugin + mkdir -p out/$TARGET_DIR/clang_x64/developtools/smartperf_host + cp out/$target_os/clang_x64/developtools/smartperf_host/protoreader_plugin out/$TARGET_DIR/clang_x64/developtools/smartperf_host/protoreader_plugin fi fi if [ $target_os == "windows" ];then diff --git a/trace_streamer/build/config.gni b/trace_streamer/build/config.gni index 3e7f08f25..f287cf244 100644 --- a/trace_streamer/build/config.gni +++ b/trace_streamer/build/config.gni @@ -11,24 +11,3 @@ # See the License for the specific language governing permissions and # limitations under the License. import("ts.gni") -asdk_libs_dir = "." -host_toolchain = "" -OHOS_TRACE_STREAMER_PROTOS_DIR = get_path_info("../src", "abspath") -OHOS_PROFILER_3RDPARTY_DIR = get_path_info("../third_party/", "abspath") -OHOS_PROFILER_3RDPARTY_GRPC_DIR = "${OHOS_PROFILER_3RDPARTY_DIR}/grpc" -OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR = "${OHOS_PROFILER_3RDPARTY_DIR}/protobuf" -OHOS_PROFILER_3RDPARTY_GOOGLETEST_DIR = - "${OHOS_PROFILER_3RDPARTY_DIR}/googletest" - -OHOS_PROFILER_SUBSYS_NAME = "developtools" -OHOS_PROFILER_PART_NAME = "profiler" -OHOS_PROFILER_TEST_MODULE_OUTPUT_PATH = "profiler" - -build_l2 = false -if (getenv("BUILD_L2") == "true") { - build_l2 = true -} - -declare_args() { - profiler_SmartPerf = true -} diff --git a/trace_streamer/build/protoc.sh b/trace_streamer/build/protoc.sh index 2dfdf6344..7537db2c8 100755 --- a/trace_streamer/build/protoc.sh +++ b/trace_streamer/build/protoc.sh @@ -14,10 +14,12 @@ set -e THIS_DIR=$(dirname ${BASH_SOURCE[0]}) -PROJECT_TOP=$(realpath $THIS_DIR/../../..) -TAIL_DIR="developtools/profiler" +PROJECT_TOP=$(realpath $THIS_DIR/../../../..) +TAIL_DIR="thirdparty/protobuf" +SUBSYS_DIR="developtools/smartperf_host" if [[ $2 == *"developtools"* ]]; then TAIL_DIR="." + SUBSYS_DIR="." PROJECT_TOP=$(realpath $THIS_DIR/..) fi OHOS_X64_OUT=$PROJECT_TOP/$2/ @@ -25,8 +27,8 @@ LIBCXX_X64_OUT=$PROJECT_TOP/$1/ndk/libcxx/linux_x86_64 SUBSYS_X64_OUT=$PROJECT_TOP/$2/$TAIL_DIR PROTOC=$PROJECT_TOP/$2/$TAIL_DIR/protoc -OPT_PLUGIN_PROTOREADER_PATH=$PROJECT_TOP/$2/$TAIL_DIR/protoreader_plugin -OPT_PLUGIN_PROTOREADER="--plugin=protoc-gen-plugin=$PROJECT_TOP/$2/$TAIL_DIR/protoreader_plugin --plugin_out=wrapper_namespace=ProtoReader" +OPT_PLUGIN_PROTOREADER_PATH=$PROJECT_TOP/$2/$SUBSYS_DIR/protoreader_plugin +OPT_PLUGIN_PROTOREADER="--plugin=protoc-gen-plugin=$PROJECT_TOP/$2/$SUBSYS_DIR/protoreader_plugin --plugin_out=wrapper_namespace=ProtoReader" OPT_OUT=--opt_out OPT_PROTOREADER_OUT=--cpp_out PYTHON_SHELL=$THIS_DIR/make_standard_proto.py # shell path diff --git a/trace_streamer/build/protoc_w.sh b/trace_streamer/build/protoc_w.sh index 0e3217522..da97a2a1c 100644 --- a/trace_streamer/build/protoc_w.sh +++ b/trace_streamer/build/protoc_w.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright (C) 2021 Huawei Device Co., Ltd. +# Copyright (C) 2023 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/trace_streamer/build/ts.gni b/trace_streamer/build/ts.gni index e7b7efb15..0ccc449b2 100755 --- a/trace_streamer/build/ts.gni +++ b/trace_streamer/build/ts.gni @@ -10,48 +10,23 @@ # WITHOUT 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("config.gni") -if (target_os == "linux" || target_os == "macx" || target_os == "windows") { - clang_x64_folder = "." - THIRD_PARTY = "//third_party" - SRC = "//src" - PREBUILTS = "//prebuilts" - - # kernel_version = "5.10.79_aarch64" - kernel_version = "." - if (target == "test") { - enable_ts_utest = true - } else { - enable_ts_utest = false - } - device_kernel_version = "default" - is_ohos = false - PERF_DIR = "//third_party" - OHOS_TRACE_STREAMER_PROTOS_DIR = get_path_info("../src", "abspath") - OHOS_TRACE_STREAMER_DIR = get_path_info("../", "abspath") - OHOS_TRACE_STREAMER_DIR_PROTOC = get_path_info("./protoc.sh", "abspath") +declare_args() { + profiler_SmartPerf = true + is_independent_compile = false +} - if (target_os == "windows") { - OHOS_TRACE_STREAMER_DIR_PROTOC = get_path_info("./protoc_w.sh", "abspath") - } else { - script_executable = "/usr/bin/env" - } - OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR = - get_path_info("../third_party/protobuf", "abspath") +if (is_independent_compile) { + asdk_libs_dir="." + host_toolchain = "" + PERF_DIR = "//third_party" + clang_x64_folder = "." + enable_ts_utest = (target == "test") } else { - script_executable = "/usr/bin/env" - clang_x64_folder = "clang_x64" + PERF_DIR = "//developtools" with_ebpf_help_table = false - OHOS_TRACE_STREAMER_DIR = get_path_info("..", "abspath") - OHOS_TRACE_STREAMER_DIR_PROTOC = get_path_info("/protoc.sh", "abspath") - THIRD_PARTY = get_path_info("../../../../../../third_party/", "abspath") - PERF_DIR = get_path_info("../../../../../", "abspath") - SRC = "${OHOS_TRACE_STREAMER_DIR}/src" - PREBUILTS = "${OHOS_TRACE_STREAMER_DIR}/prebuilts" - target = "trace_steamer" + clang_x64_folder = "clang_x64" is_macx = false - with_perf = true is_test = false is_protoc = false is_spb = false @@ -59,12 +34,34 @@ if (target_os == "linux" || target_os == "macx" || target_os == "windows") { is_dubai_sdk = false is_sdkdemo_test = false use_wasm = false - enable_ts_utest = true - kernel_version = "." + enable_ts_utest = false is_fuzz = false - target = "trace_streamer" - is_ohos = true } -if (is_ohos) { - import("../../../../build/config.gni") + +script_executable = "/usr/bin/env" +device_kernel_version = "default" +OHOS_TRACE_STREAMER_PROTOS_DIR = get_path_info("../src", "abspath") + +OHOS_TRACE_STREAMER_DIR = get_path_info("../", "abspath") +SRC = "${OHOS_TRACE_STREAMER_DIR}/src" +PREBUILTS = "//prebuilts" +THIRD_PARTY = "//third_party" +kernel_version = "." + +OHOS_TRACE_STREAMER_DIR_PROTOC= get_path_info("./protoc.sh", "abspath") + +if (target_os == "windows") { + OHOS_TRACE_STREAMER_DIR_PROTOC= get_path_info("./protoc_w.sh", "abspath") +} + +OHOS_PROFILER_3RDPARTY_GRPC_DIR = "${THIRD_PARTY}/grpc" +OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR = "${THIRD_PARTY}/protobuf" +OHOS_PROFILER_3RDPARTY_GOOGLETEST_DIR = "${THIRD_PARTY}/googletest" +OHOS_PROFILER_SUBSYS_NAME = "developtools" +OHOS_PROFILER_PART_NAME = "smartperf_host" +OHOS_PROFILER_TEST_MODULE_OUTPUT_PATH = "smartperf_host" + +build_l2 = false +if (getenv("BUILD_L2") == "true") { + build_l2 = true } diff --git a/trace_streamer/build_operator.sh b/trace_streamer/build_operator.sh index 3d46b718c..61a819efb 100755 --- a/trace_streamer/build_operator.sh +++ b/trace_streamer/build_operator.sh @@ -12,10 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. set -e -ext="/clang_x64" +ext="" +clang_dir="clang_x64" target_dir="linux" subsys_name="developtools" -part_name="profiler" +part_name="smartperf_host" is_debug="$1" target="$2" target_os="$3" @@ -60,7 +61,10 @@ else exit fi if [ "$is_debug" != "false" ];then - ext="_debug" + ext="_debug" +fi +if [ ! -d "third_party/protogen" ] && [ "$target" != "spb" ] && [ "$target" != "protoc" ];then + ./src/protos/protogen.sh fi if [ "$target" == "test" ] || [ "$target" == "fuzz" ] || [ "$target"="wasm" ] || [ "$target"="sdkdemo" ] || [ "$target"="sdkdemotest" ];then @@ -75,14 +79,14 @@ echo "target_dir:" $target_dir echo "target:" $target # exit if [ "$is_clean" == "true" ];then - prebuilts/$gn_path/$gn gen out/"$target_dir""$ext"/$subsys_name/$part_name --clean - prebuilts/$gn_path/$ninja -C out/"$target_dir""$ext"/$subsys_name/$part_name -t clean + prebuilts/$gn_path/$gn gen out/"$target_dir""$ext"/$clang_dir/$subsys_name/$part_name --clean + prebuilts/$gn_path/$ninja -C out/"$target_dir""$ext"/$clang_dir/$subsys_name/$part_name -t clean else - prebuilts/$gn_path/$gn gen out/"$target_dir""$ext"/$subsys_name/$part_name --args='is_debug='"$is_debug"' target="'"$target"'" target_os="'"$target_os"'"' + prebuilts/$gn_path/$gn gen out/"$target_dir""$ext"/$clang_dir/$subsys_name/$part_name --args='is_debug='"$is_debug"' target="'"$target"'" target_os="'"$target_os"'" is_independent_compile=true' echo "begin to build ..." - prebuilts/$gn_path/$ninja -C out/"$target_dir""$ext"/$subsys_name/$part_name - if [ $target_dir == "linux" ] && [ -f "out/$target_dir$ext/$subsys_name/$part_name/trace_streamer" ];then - mkdir -p out/linux - cp out/"$target_dir""$ext"/$subsys_name/$part_name/trace_streamer out/linux/ + prebuilts/$gn_path/$ninja -C out/"$target_dir""$ext"/$clang_dir/$subsys_name/$part_name + if [ "$target" != "protoc" ] && [ "$target" != "spb" ];then + cp -r out/"$target_dir""$ext"/$clang_dir/$subsys_name/$part_name/* out/"$target_dir""$ext"/ + rm -rf out/"$target_dir""$ext"/$clang_dir fi fi diff --git a/trace_streamer/doc/app_startup.md b/trace_streamer/doc/app_startup.md new file mode 100644 index 000000000..e7031ab2c --- /dev/null +++ b/trace_streamer/doc/app_startup.md @@ -0,0 +1,23 @@ +# 应用启动数据说明 + +TraceStreamer支持解析应用启动数据,数据包含应用拉起的6个阶段及相关的调用栈信息,分别为Proess Creating(创建应用进程),Application +Launching(加载应用),UI Ability Launching(加载UI Ability), UI Ability OnForeground(应用进入前台),First Frame-App Phase(首帧渲染提交-应用),First Frame-Render Phase(首帧渲染提交-Render Service)。 + +应用启动每个阶段的开始和结束时间如图: + +![1689415472707](image/app_startup/1689415472707.png) + +前四个阶段对应的标志事件字符串: +Proess Creating:在callstack表中查找包含"H:int OHOS::AAFwk::MissionListManager::StartAbilityLocked("的字符,并且向上的调用栈包含"H:virtual int OHOS::AAFwk::AbilityManagerService::StartAbility("字符的数据,即为启动第一阶段。该数据中第一个'##'之后的字符串即为该应用的名称。 + +Application Launching:在callstack表中查找包含"H:virtual void OHOS::AppExecFwk::AppMgrServiceInner::AttachApplication(const pid_t, const sptrOHOS::AppExecFwk::IAppScheduler &)##"字符的数据,即为启动第二阶段。该数据中第一个'##'之后的字符串即为该应用的名称。 + +UI Ability Launching:在callstack表中查找包含"H:void OHOS::AppExecFwk::MainThread::HandleLaunchAbility(const std::shared_ptr `` &)##"字符的数据,即为启动的第三阶段,在这个阶段会上报包名和拉起该应用的ipid。如数据中缺少此阶段,可视为应用未启动。 + +UI Ability OnForeground:在callstack表中查找包含"H:void OHOS::AppExecFwk::AbilityThread::HandleAbilityTransaction(const OHOS::AppExecFwk::Want &, const OHOS::AppExecFwk::LifeCycleStateInfo &, sptrOHOS::AAFwk::SessionInfo)##"字符的数据,即为启动的第四阶段,该阶段会上报ipid,同一个应用第三和第四阶段上报的ipid相同。 + +后两个阶段的计算方式如下: + +First Frame-App Phase:使用第三阶段得到的ipid关联到frame_slice表中,取到该ipid对应的应用帧的首帧数据,即为该应用第五阶段的数据。 + +First Frame-Render Phase:通过应用帧首帧数据,可以在frame_slice表中通过dst字段关联到渲染帧首帧数据,即为该应用的第六阶段的数据。 diff --git a/trace_streamer/doc/des_tables.md b/trace_streamer/doc/des_tables.md index 8d8a2ec15..652364934 100755 --- a/trace_streamer/doc/des_tables.md +++ b/trace_streamer/doc/des_tables.md @@ -39,6 +39,8 @@ TraceStreamer可以将trace数据源转化为易于理解和使用的数据库 | js_heap_string | 记录了js内存数据中的字符串| | js_heap_trace_function_info | 记录了timeline模式下的调用栈的每个函数信息| | js_heap_trace_node | 记录了timeline模式下的调用栈信息| +| app_startup | 记录了应用启动相关数据| +| static_initalize | 记录了so初始化相关数据| | live_process | 记录了一些实时的进程中执行的一些数据| | log | 记录hilog打印日志数据| | measure_filter | 记录一个递增的filterid队列,所有其他的filter类型在获取过程中,均从此数据列表中获取下一个可用的filter_id并做记录| @@ -71,9 +73,11 @@ TraceStreamer可以将trace数据源转化为易于理解和使用的数据库 | trace_range | 记录ftrace数据与其他类型数据的时间交集,供前端展示数据时使用| | clock_snapshot | 时钟号和时间,时钟名的映射表| | datasource_clockid | 数据源和时钟号的映射表| +| task_pool | 记录任务池相关数据,与callstack表相关联| ## 表与事件来源 | 表名称 | 事件源 | 插件名 | 备注 | | ---- | ---- | ---- | ---- | +|animation | - |ftrace-plugin |记录动效的响应时延和完成时延 | |app_name | - |hisysevent-plugin |JSON数据源 | |args | - |ftrace-plugin |配合callstack使用 | |callstack | - |ftrace-plugin |异步或非异步的调用 | @@ -81,6 +85,8 @@ TraceStreamer可以将trace数据源转化为易于理解和使用的数据库 |cpu_usage | - |cpu-plugin |cpu使用率 | |data_dict | 通用的 | - |所有字符串的记录 | |data_type | 通用的 | - |辅助表 | +|device_info | - |ftrace-plugin |记录设备分辨率和帧率 | +|dynamic_frame | - |ftrace-plugin |记录动效帧的分辨率和结束时间等 | |file_system_callstack | - | - |ebpf文件系统 | |file_system_sample | - | - |ebpf文件系统 | |frame_maps | - |ftrace-plugin |帧渲染数据,app到RS的映射 | @@ -99,6 +105,8 @@ TraceStreamer可以将trace数据源转化为易于理解和使用的数据库 | js_heap_string | - |arkts-plugin | js内存数据 | | js_heap_trace_function_info | - |arkts-plugin | js内存数据 | | js_heap_trace_node | - |arkts-plugin | js内存数据 | +| app_startup | - |ftrace-plugin | 应用启动数据 | +| static_initalize | - |ftrace-plugin | so初始化数据 | |live_process | - |process-plugin |Monitor数据 | |network | - |network-plugin |Monitor数据 | |diskio | - |diskio-plugin |Monitor数据 | @@ -132,6 +140,7 @@ TraceStreamer可以将trace数据源转化为易于理解和使用的数据库 |thread_filter | 通用的 |ftrace-plugin |线程计量跟踪表(比较少用)| |clock_snapshot | 通用的 |通用的 |时钟号和时间,时钟名的映射表| |datasource_clockid | 通用的 |通用的 |数据源和时钟号的映射表| +|task_pool | - | - |任务池数据 | ## ___表格关系图___ --- @@ -752,6 +761,50 @@ js_heap_sample:记录timeline的时间轴信息 - size:调用栈大小 - parent_id:调用栈父节点 +### app_startup表 +#### 表结构 +| Columns Name | SQL TYPE | +| ------------------- | -------- | +| call_id | INT | +| ipid | INT | +| tid | INT | +| start_time | INT | +| end_time | INT | +| start_name | INT | +| packed_name | INT | +#### 表描述 +记录了应用启动的相关信息。 +#### 相关字段描述 +- call_id:调用者的ID,比如针对线程表里面的id +- ipid:内部进程号 +- tid:内部线程号 +- start_time:阶段开始时间 +- end_time:阶段结束时间 +- start_name:阶段名称 +- packed_name:应用名称 + +### static_intialize表 +#### 表结构 +| Columns Name | SQL TYPE | +| ------------------- | -------- | +| call_id | INT | +| ipid | INT | +| tid | INT | +| start_time | INT | +| end_time | INT | +| so_name | INT | +| depth | INT | +#### 表描述 +记录了so初始化的相关信息。 +#### 相关字段描述 +- call_id:调用者的ID,比如针对线程表里面的id +- ipid:内部进程号 +- tid:内部线程号 +- start_time:阶段开始时间 +- end_time:阶段结束时间 +- so_name:so文件名称 +- depth:泳道图的深度 + ### live_process表 #### 表结构 | Columns Name | SQL TYPE | @@ -1471,4 +1524,82 @@ js_heap_sample:记录timeline的时间轴信息 该表记录了解析开始时间以及结束时间。 #### 关键字段描述 - start_ts:trace的开始时间,纳秒为单位 -- end_ts:trace的结束时间,纳秒为单位 \ No newline at end of file +- end_ts:trace的结束时间,纳秒为单位 +### task_pool表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|allocation_task_row |INT | +|execute_task_row |INT | +|return_task_row |INT | +|allocation_task_id |INT | +|execute_task_id |INT | +|return_task_id |INT | +|execute_id |INT | +|priority |INT | +|execute_state |INT | +|return_state |INT | +#### 表描述 +该表记录了任务池相关数据,与callstack表关联。 +#### 关键字段描述 +- allocation_task_row:与callstack表id号相关联 +- execute_task_row:与callstack表id号相关联 +- return_task_row:与callstack表id号相关联 +- allocation_task_id:任务分发的id号 +- execute_task_id:任务执行的id号 +- return_task_id:任务返回的id号 +- execute_id:任务执行id +- priority:任务分发独有的,优先级{HIGH : 0,MEDIUM : 1,LOW : 2} +- execute_state:任务执行独有的执行状态{NOT_FOUND : 0,WAITING : 1,RUNNING : 2,CANCELED : 3} +- return_state:任务返回独有的任务返回状态[IsCanceled DeserializeFailed Successful Unsuccessful] +### animation表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|input_time |INT | +|start_point |INT | +|end_point |INT | +#### 表描述 +该表记录动效的响应时延和完成时延。 +#### 关键字段描述 +- input_time:输入时间点 +- start_point:开始时间点 +- end_point:结束时间点 +### dynamic_frame表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|x |INT | +|y |INT | +|width |INT | +|height |INT | +|alpha |TEXT | +|name |INT | +|end_time |INT | +#### 表描述 +该表记录动效帧的坐标、分辨率、结束时间等。 +#### 关键字段描述 +- x:坐标x +- y:坐标y +- width:宽 +- height:高 +- alpha:透明度 +- name:当前动效帧名字 +- end_time:结束时间 +### dynamic_frame表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|physical_width |INT | +|physical_height |INT | +|physical_frame_rate |INT | +#### 表描述 +该表记录设备分辨率和帧率。 +#### 关键字段描述 +- physical_width:设备宽 +- physical_height:设备高 +- physical_frame_rate:设备帧率 \ No newline at end of file diff --git a/trace_streamer/doc/image/app_startup/1689415472707.png b/trace_streamer/doc/image/app_startup/1689415472707.png new file mode 100644 index 0000000000000000000000000000000000000000..91c4453e38cfb444363287b6447f5d94ee230aa5 GIT binary patch literal 144045 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 literal 0 HcmV?d00001 diff --git a/trace_streamer/gn/BUILD.gn b/trace_streamer/gn/BUILD.gn index 65adceadc..64ef1b31a 100755 --- a/trace_streamer/gn/BUILD.gn +++ b/trace_streamer/gn/BUILD.gn @@ -138,9 +138,6 @@ config("default") { "-D __KERNEL__", ] } - if (with_perf) { - cflags += [ "-D WITH_PERF" ] - } if (with_ebpf_help_table) { cflags += [ "-D WITH_EBPF_HELP" ] } diff --git a/trace_streamer/gn/CONFIG.gn b/trace_streamer/gn/CONFIG.gn index cf03004e2..6d5e5ad94 100755 --- a/trace_streamer/gn/CONFIG.gn +++ b/trace_streamer/gn/CONFIG.gn @@ -14,7 +14,6 @@ is_win = false is_linux = false is_macx = false is_protoc = false -with_perf = true with_ebpf_help_table = false is_mingw = false with_libunwind = false diff --git a/trace_streamer/gn/toolchain/BUILD.gn b/trace_streamer/gn/toolchain/BUILD.gn index 3b3150946..37f5bc3d0 100755 --- a/trace_streamer/gn/toolchain/BUILD.gn +++ b/trace_streamer/gn/toolchain/BUILD.gn @@ -14,12 +14,12 @@ import("//gn/wasm.gni") declare_args() { if (target_os == "linux" || target_os == "macx") { - cc = "/usr/bin/clang" - cxx = "/usr/bin/clang++" + cc = "clang" + cxx = "clang++" pic = "-fPIC" rebuild_string = "" extra_asmflags = "" - asm = "/usr/bin/clang" + asm = "clang" } else if (target_os == "windows") { cc = "gcc.exe" cxx = "g++.exe" diff --git a/trace_streamer/pare_third_party.sh b/trace_streamer/pare_third_party.sh index 3d8852ad2..2abcfd08f 100755 --- a/trace_streamer/pare_third_party.sh +++ b/trace_streamer/pare_third_party.sh @@ -54,11 +54,11 @@ if [ ! -f "googletest/BUILD.gn" ];then fi fi -if [ ! -f "json-master/BUILD.gn" ];then - rm -rf json-master +if [ ! -f "json/BUILD.gn" ];then + rm -rf json git clone git@gitee.com:openharmony/third_party_json.git if [ -d "third_party_json" ];then - mv third_party_json json-master + mv third_party_json json fi fi diff --git a/trace_streamer/prebuilts/patch_hiperf/BUILD.gn b/trace_streamer/prebuilts/patch_hiperf/BUILD.gn index 4767b9b63..2a2a8eb3a 100644 --- a/trace_streamer/prebuilts/patch_hiperf/BUILD.gn +++ b/trace_streamer/prebuilts/patch_hiperf/BUILD.gn @@ -82,7 +82,7 @@ ohos_source_set("hiperf_src") { ] } -group("hiperf") { +group("hiperf_platform_common") { deps = [ ":elf", ":hiperf_src", diff --git a/trace_streamer/sdk/demo_sdk/BUILD.gn b/trace_streamer/sdk/demo_sdk/BUILD.gn index 498c279f9..979c964f8 100755 --- a/trace_streamer/sdk/demo_sdk/BUILD.gn +++ b/trace_streamer/sdk/demo_sdk/BUILD.gn @@ -52,9 +52,6 @@ ohos_source_set("lib") { "${THIRD_PARTY}/protobuf/src", ] public_deps = [ "protos/types/plugins/mock_data:mock_data_cpp" ] - if (with_perf) { - include_dirs += [] - } } ohos_source_set("trace_streamer_sdk") { subsystem_name = "trace_streamer" @@ -108,7 +105,7 @@ ohos_source_set("trace_streamer_sdk") { "cfg", "${THIRD_PARTY}/sqlite/include", "${THIRD_PARTY}/protobuf/src", - "${THIRD_PARTY}/json-master/single_include/nlohmann", + "${THIRD_PARTY}/json/single_include/nlohmann", ] if (!use_wasm) { include_dirs += [ @@ -116,18 +113,12 @@ ohos_source_set("trace_streamer_sdk") { "${THIRD_PARTY}/libunwind/src", ] } - if (with_perf) { - sources += [] - include_dirs += [] - } deps = [ "${SRC}/base:base", "${THIRD_PARTY}/sqlite:sqlite", "plugin:sdk_plugin", ] public_deps = [ "protos/types/plugins/mock_data:mock_data_cpp" ] - if (with_perf) { - } if (use_wasm || enable_ts_utest) { sources += [ diff --git a/trace_streamer/sdk/demo_sdk/test/BUILD.gn b/trace_streamer/sdk/demo_sdk/test/BUILD.gn index f4582c603..af7b065d5 100755 --- a/trace_streamer/sdk/demo_sdk/test/BUILD.gn +++ b/trace_streamer/sdk/demo_sdk/test/BUILD.gn @@ -46,7 +46,7 @@ if (target == "sdkdemotest") { "${OHOS_PROTO_GEN}/types/plugins/mock_data", "${THIRD_PARTY}/googletest/googletest/include/gtest", "${THIRD_PARTY}/protobuf/src", - "${THIRD_PARTY}/json-master/single_include/nlohmann", + "${THIRD_PARTY}/json/single_include/nlohmann", ] cflags = [ "-Wno-inconsistent-missing-override", diff --git a/trace_streamer/sdk/dubai_sdk/BUILD.gn b/trace_streamer/sdk/dubai_sdk/BUILD.gn index 3f1f91248..5485ea225 100755 --- a/trace_streamer/sdk/dubai_sdk/BUILD.gn +++ b/trace_streamer/sdk/dubai_sdk/BUILD.gn @@ -52,9 +52,6 @@ ohos_source_set("lib") { "${THIRD_PARTY}/sqlite/include", "${THIRD_PARTY}/protobuf/src", ] - if (with_perf) { - include_dirs += [] - } public_deps = [ "protos/types/plugins/mock_data:mock_data_cpp" ] } source_set("trace_streamer_sdk") { @@ -107,7 +104,7 @@ source_set("trace_streamer_sdk") { "cfg", "${THIRD_PARTY}/sqlite/include", "${THIRD_PARTY}/protobuf/src", - "${THIRD_PARTY}/json-master/single_include/nlohmann", + "${THIRD_PARTY}/json/single_include/nlohmann", ] if (!use_wasm) { include_dirs += [ @@ -115,17 +112,11 @@ source_set("trace_streamer_sdk") { "${THIRD_PARTY}/libunwind/src", ] } - if (with_perf) { - sources += [] - include_dirs += [] - } deps = [ "${SRC}/base:base", "${THIRD_PARTY}/sqlite:sqlite", "plugin:sdk_plugin", ] - if (with_perf) { - } if (use_wasm || enable_ts_utest) { sources += [ diff --git a/trace_streamer/sdk/dubai_sdk/test/BUILD.gn b/trace_streamer/sdk/dubai_sdk/test/BUILD.gn index 573eea5b6..efcb6e454 100755 --- a/trace_streamer/sdk/dubai_sdk/test/BUILD.gn +++ b/trace_streamer/sdk/dubai_sdk/test/BUILD.gn @@ -47,7 +47,7 @@ if (target == "sdkdemotest") { "${OHOS_PROTO_GEN}/types/plugins/mock_data", "${THIRD_PARTY}/googletest/googletest/include/gtest", "${THIRD_PARTY}/protobuf/src", - "${THIRD_PARTY}/json-master/single_include/nlohmann", + "${THIRD_PARTY}/json/single_include/nlohmann", ] cflags = [ "-Wno-inconsistent-missing-override", diff --git a/trace_streamer/src/BUILD.gn b/trace_streamer/src/BUILD.gn index a59336582..6f1e0aea7 100644 --- a/trace_streamer/src/BUILD.gn +++ b/trace_streamer/src/BUILD.gn @@ -11,74 +11,82 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("../build/ohos.gni") +import("//build/ohos.gni") import("../build/ts.gni") if (use_wasm) { import("//gn/wasm.gni") } -if (use_wasm) { - ohos_source_set("trace_streamer_builtin") { - subsystem_name = "developtools" - part_name = "smartperf_host" - sources = [] - include_dirs = [] - deps = [] - public_deps = [] - } -} -ohos_source_set("lib") { - subsystem_name = "developtools" - part_name = "smartperf_host" - sources = [ "main.cpp" ] - deps = [ - ":trace_streamer_source", - "proto_reader:proto_reader", - ] - include_dirs = [ - "base", - "..", - "trace_streamer", - "filter", - "table", - "trace_data", - "include", - "rpc", - "./", - "parser", - "cfg", - "proto_reader/include", - "${THIRD_PARTY}/sqlite/include", - "${THIRD_PARTY}/json-master/single_include/nlohmann", - "${THIRD_PARTY}/protobuf/src", - "${THIRD_PARTY}/hiperf/include", - ] - include_dirs += [ - "parser/htrace_pbreader_parser", - "parser/htrace_pbreader_parser/htrace_event_parser", - "parser/htrace_pbreader_parser/htrace_cpu_parser", +ohos_source_set("ts_sqlite") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + sources = [ "//third_party/sqlite/src/sqlite3.c" ] + include_dirs = [ "//third_party/sqlite/include" ] + cflags = [ + "-Wno-shorten-64-to-32", + "-Wno-double-promotion", + "-Wno-disabled-macro-expansion", + "-Wno-float-equal", + "-Wno-cast-qual", + "-Wno-conversion", + "-Wno-cast-align", + "-Wno-unused-macros", + "-Wno-comma", + "-Wno-unreachable-code-break", + "-Wno-unreachable-code", + "-Wno-unreachable-code-return", + "-DSQLITE_THREADSAFE=1", + "-DQLITE_DEFAULT_MEMSTATUS=0", + "-DSQLITE_LIKE_DOESNT_MATCH_BLOBS", + "-DSQLITE_OMIT_DEPRECATED", + "-DSQLITE_OMIT_SHARED_CACHE", + "-DHAVE_USLEEP", + "-DHAVE_UTIME", + "-DSQLITE_BYTEORDER=1234", + "-DSQLITE_DEFAULT_AUTOVACUUM=0", + "-DSQLITE_DEFAULT_MMAP_SIZE=0", + "-DSQLITE_CORE", + "-DSQLITE_TEMP_STORE=3", + "-DSQLITE_OMIT_LOAD_EXTENSION", ] - - if (with_perf) { - include_dirs += [ - "parser/hiperf_parser", - "${THIRD_PARTY}/hiperf/include", - "${THIRD_PARTY}/hiperf/include/nonlinux", - "${THIRD_PARTY}/hiperf/include/nonlinux/linux", - "${THIRD_PARTY}/perf_include/musl", - ] - } - public_deps = [] - if (!use_wasm && !is_test && !is_fuzz) { - public_deps += [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "proto_reader/protoc_plugin:protoreader_plugin", - ] - } } + +trace_streamer_include = [ + "base", + "..", + "trace_streamer", + "filter", + "table", + "trace_data", + "include", + "rpc", + "./", + "parser", + "cfg", + "proto_reader/include", + "parser/ebpf_parser", + "parser/htrace_pbreader_parser", + "parser/htrace_pbreader_parser/htrace_event_parser", + "parser/htrace_pbreader_parser/htrace_cpu_parser", + "parser/hiperf_parser", + "//developtools/hiperf/include", + "${THIRD_PARTY}/sqlite/include", + "${THIRD_PARTY}/json/single_include/nlohmann", + "${THIRD_PARTY}/protobuf/src", + "${THIRD_PARTY}/hiperf/include", + "${THIRD_PARTY}/hiperf/include/nonlinux", + "${THIRD_PARTY}/hiperf/include/nonlinux/linux", + "${THIRD_PARTY}/perf_include/musl", + "${THIRD_PARTY}/musl", + "${THIRD_PARTY}/libunwind/include", + "${THIRD_PARTY}/libunwind/src", + "${THIRD_PARTY}/perf_include/libbpf", + "${THIRD_PARTY}/googletest/googletest/include", +] + ohos_source_set("trace_streamer_source") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "cfg/trace_streamer_config.cpp", "cfg/trace_streamer_config.h", @@ -91,87 +99,31 @@ ohos_source_set("trace_streamer_source") { "trace_streamer/trace_streamer_selector.h", "version.cpp", ] - include_dirs = [ - "base", - "..", - "trace_streamer", - "filter", - "table", - "trace_data", - "include", - "rpc", - "./", - "parser", - "cfg", - "proto_reader/include", - "parser/ebpf_parser", - "${THIRD_PARTY}/sqlite/include", - "${THIRD_PARTY}/protobuf/src", - ] + if (!is_test && !is_fuzz) { + sources += [ "main.cpp" ] + } + if (use_wasm) { + sources += [ + "rpc/wasm_func.cpp", + "rpc/wasm_func.h", + ] + } + + include_dirs = trace_streamer_include if (use_wasm) { include_dirs += [ "../prebuilts/emsdk/emsdk/emscripten/cache/sysroot/include" ] } - if (is_macx && !is_test) { - cflags = [ "-D_XOPEN_SOURCE=600" ] - } if (is_test) { include_dirs += [ "../prebuilts/emsdk/emsdk/emscripten/system/include" ] } - include_dirs += [ - "parser/htrace_pbreader_parser", - "parser/htrace_pbreader_parser/htrace_event_parser", - "parser/htrace_pbreader_parser/htrace_cpu_parser", - ] - - include_dirs += [ - "${THIRD_PARTY}/libunwind/include", - "${THIRD_PARTY}/libunwind/src", - "${THIRD_PARTY}/json-master/single_include/nlohmann", - "${THIRD_PARTY}/hiperf/include", - "${THIRD_PARTY}/hiperf/include/nonlinux/linux", - "${THIRD_PARTY}/hiperf/include/nonlinux", - ] - - if (with_perf) { - include_dirs += [ - "parser/hiperf_parser", - "${THIRD_PARTY}/perf_include/libbpf", - "${THIRD_PARTY}/perf_include/musl", - ] - } - public_deps = [ - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/services:all_type_cpp_standard", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:cpu_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/ftrace_data/${device_kernel_version}:ftrace_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:hilog_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:hisysevent_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_encoder", - ] - - deps = [ - "${THIRD_PARTY}/sqlite:sqlite", - "base:base", - "filter:filter", - "parser:parser", - "table:table", - "trace_data:trace_data", - ] - if (with_perf) { - deps += [ "parser/hiperf_parser:hiperf_parser" ] - } else { - deps += [ "${THIRD_PARTY}/hiperf:elf" ] - } - - if (use_wasm) { - sources += [ - "rpc/wasm_func.cpp", - "rpc/wasm_func.h", - ] + cflags = [ "-D target_cpu_${target_cpu}" ] + if (!use_wasm && !is_win && !is_macx && !is_test) { + cflags += [ "-D HAVE_LIBUNWIND" ] } if (enable_ts_utest && !use_wasm) { - cflags = [ + cflags += [ "-fprofile-arcs", "-ftest-coverage", ] @@ -184,16 +136,55 @@ ohos_source_set("trace_streamer_source") { cflags += [ "-D IS_UT" ] } } + + public_deps = [ + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/services:ts_all_type_cpp_standard", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:cpu_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/ftrace_data/${device_kernel_version}:ftrace_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:hilog_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:hisysevent_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_reader", + ] + if (!use_wasm && !is_test && !is_fuzz) { + public_deps += [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", + ] + } + + deps = [ + ":ts_sqlite", + "base:base", + "filter:filter", + "parser:parser", + "parser/hiperf_parser:hiperf_parser", + "proto_reader:proto_reader", + "table:table", + "trace_data:trace_data", + ] } + if (use_wasm) { + ohos_source_set("trace_streamer_builtin") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + sources = [] + include_dirs = [] + deps = [] + public_deps = [] + } wasm_lib("trace_streamer_builtin_wasm") { name = "trace_streamer_builtin" - deps = [ ":lib" ] + deps = [ ":trace_streamer_source" ] } } else { if (!is_test && !is_fuzz) { - executable("trace_streamer") { - deps = [ ":lib" ] + ohos_executable("trace_streamer") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + sources = [] + include_dirs = trace_streamer_include + deps = [ ":trace_streamer_source" ] } } } diff --git a/trace_streamer/src/base/BUILD.gn b/trace_streamer/src/base/BUILD.gn index f4486b375..643a88e32 100644 --- a/trace_streamer/src/base/BUILD.gn +++ b/trace_streamer/src/base/BUILD.gn @@ -14,8 +14,8 @@ import("//build/ohos.gni") import("../../build/ts.gni") ohos_source_set("base") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":base_parser", ":base_table", @@ -44,13 +44,13 @@ ohos_source_set("base") { } } ohos_source_set("string_help") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "string_help.cpp" ] } ohos_source_set("ibase") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "codec_cov.h", "file.h", @@ -65,8 +65,8 @@ ohos_source_set("ibase") { sources += [ "/usr/x86_64-w64-mingw32/include/windows.h" ] } ohos_source_set("base_parser") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "htrace_plugin_time_parser.cpp", "htrace_plugin_time_parser.h", @@ -76,8 +76,8 @@ ohos_source_set("base_parser") { deps = [] } ohos_source_set("base_table") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "filter_constraints.cpp", "index_map.cpp", diff --git a/trace_streamer/src/base/clock_filter.cpp b/trace_streamer/src/base/clock_filter.cpp index eb4d2ffb5..13e33c8fc 100644 --- a/trace_streamer/src/base/clock_filter.cpp +++ b/trace_streamer/src/base/clock_filter.cpp @@ -16,6 +16,7 @@ #include "clock_filter.h" #include #include +#include #include "log.h" #include "string_help.h" #include "ts_common.h" @@ -36,10 +37,10 @@ std::string ClockFilter::GenClockKey(ClockId srcClockId, ClockId desClockId) uint64_t ClockFilter::ToPrimaryTraceTime(ClockId srcClockId, uint64_t srcTs) const { - if (srcClockId == PRIMARY_CLOCK_ID) { + if (srcClockId == g_primaryClockId) { return srcTs; } - return Convert(srcClockId, srcTs, PRIMARY_CLOCK_ID); + return Convert(srcClockId, srcTs, g_primaryClockId); } uint64_t ClockFilter::Convert(ClockId srcClockId, uint64_t srcTs, ClockId desClockId) const @@ -105,37 +106,37 @@ int32_t ClockFilter::InitSnapShotTimeRange(const uint8_t* data, int32_t len) std::vector snapShot; - TS_LOGI("SDK clockid: TS_CLOCK_BOOTTIME, ts:%lu", profilerSDKTraceFileHeader_->data.boottime); - if (profilerSDKTraceFileHeader_->data.boottime) { + TS_LOGI("SDK clockid: TS_CLOCK_BOOTTIME, ts:%" PRIu64 " ", profilerSDKTraceFileHeader_->data.boottime); + if (profilerSDKTraceFileHeader_->data.boottime != 0) { snapShot.push_back(SnapShot{TS_CLOCK_BOOTTIME, profilerSDKTraceFileHeader_->data.boottime}); } - TS_LOGI("SDK clockid: TS_CLOCK_REALTIME, ts:%lu", profilerSDKTraceFileHeader_->data.realtime); - if (profilerSDKTraceFileHeader_->data.realtime) { + TS_LOGI("SDK clockid: TS_CLOCK_REALTIME, ts:%" PRIu64 "", profilerSDKTraceFileHeader_->data.realtime); + if (profilerSDKTraceFileHeader_->data.realtime != 0) { snapShot.push_back(SnapShot{TS_CLOCK_REALTIME, profilerSDKTraceFileHeader_->data.realtime}); } - TS_LOGI("SDK clockid: TS_CLOCK_REALTIME_COARSE, ts:%lu", profilerSDKTraceFileHeader_->data.realtimeCoarse); - if (profilerSDKTraceFileHeader_->data.realtimeCoarse) { + TS_LOGI("SDK clockid: TS_CLOCK_REALTIME_COARSE, ts:%" PRIu64 "", profilerSDKTraceFileHeader_->data.realtimeCoarse); + if (profilerSDKTraceFileHeader_->data.realtimeCoarse != 0) { snapShot.push_back(SnapShot{TS_CLOCK_REALTIME_COARSE, profilerSDKTraceFileHeader_->data.realtimeCoarse}); } - TS_LOGI("SDK clockid: TS_MONOTONIC, ts:%lu", profilerSDKTraceFileHeader_->data.monotonic); - if (profilerSDKTraceFileHeader_->data.monotonic) { + TS_LOGI("SDK clockid: TS_MONOTONIC, ts:%" PRIu64 "", profilerSDKTraceFileHeader_->data.monotonic); + if (profilerSDKTraceFileHeader_->data.monotonic != 0) { snapShot.push_back(SnapShot{TS_MONOTONIC, profilerSDKTraceFileHeader_->data.monotonic}); } - TS_LOGI("SDK clockid: TS_MONOTONIC_COARSE, ts:%lu", profilerSDKTraceFileHeader_->data.monotonicCoarse); - if (profilerSDKTraceFileHeader_->data.monotonicCoarse) { + TS_LOGI("SDK clockid: TS_MONOTONIC_COARSE, ts:%" PRIu64 "", profilerSDKTraceFileHeader_->data.monotonicCoarse); + if (profilerSDKTraceFileHeader_->data.monotonicCoarse != 0) { snapShot.push_back(SnapShot{TS_MONOTONIC_COARSE, profilerSDKTraceFileHeader_->data.monotonicCoarse}); } - TS_LOGI("SDK clockid: TS_MONOTONIC_RAW, ts:%lu", profilerSDKTraceFileHeader_->data.monotonicRaw); - if (profilerSDKTraceFileHeader_->data.monotonicRaw) { + TS_LOGI("SDK clockid: TS_MONOTONIC_RAW, ts:%" PRIu64 "", profilerSDKTraceFileHeader_->data.monotonicRaw); + if (profilerSDKTraceFileHeader_->data.monotonicRaw != 0) { snapShot.push_back(SnapShot{TS_MONOTONIC_RAW, profilerSDKTraceFileHeader_->data.monotonicRaw}); } - if (snapShot.size()) { + if (!snapShot.empty()) { AddClockSnapshot(snapShot); } return 0; diff --git a/trace_streamer/src/base/clock_filter.h b/trace_streamer/src/base/clock_filter.h index bc0996e52..1322024dc 100644 --- a/trace_streamer/src/base/clock_filter.h +++ b/trace_streamer/src/base/clock_filter.h @@ -52,13 +52,13 @@ public: ClockFilter(); ~ClockFilter(); - void SetPrimaryClock(ClockId primary) + static void SetPrimaryClock(ClockId primary) { - PRIMARY_CLOCK_ID = static_cast(primary); + g_primaryClockId = static_cast(primary); } - ClockId GetPrimaryClock() const + static ClockId GetPrimaryClock() { - return PRIMARY_CLOCK_ID; + return g_primaryClockId; } uint64_t ToPrimaryTraceTime(ClockId srcClockId, uint64_t srcTs) const; uint64_t Convert(ClockId srcClockId, uint64_t srcTs, ClockId desClockId) const; diff --git a/trace_streamer/src/base/file.cpp b/trace_streamer/src/base/file.cpp index 13e1e967b..582f04d9d 100644 --- a/trace_streamer/src/base/file.cpp +++ b/trace_streamer/src/base/file.cpp @@ -54,7 +54,7 @@ ssize_t Read(int32_t fd, uint8_t* dst, size_t dstSize) } int32_t OpenFile(const std::string& path, int32_t flags, uint32_t mode) { - TS_ASSERT((flags & O_CREAT) == 0 || mode != kFileModeInvalid); + TS_ASSERT((flags & O_CREAT) == 0 || mode != K_FILE_MODE_INVALID); #if defined(_WIN32) int32_t fd(_open(path.c_str(), flags | O_BINARY, mode)); #else diff --git a/trace_streamer/src/base/file.h b/trace_streamer/src/base/file.h index a1516952c..a7e2d1496 100644 --- a/trace_streamer/src/base/file.h +++ b/trace_streamer/src/base/file.h @@ -22,7 +22,7 @@ namespace SysTuning { namespace base { #define TS_PERMISSION_RW 0600 #define TS_PERMISSION_RWX 777 -constexpr uint32_t kFileModeInvalid = 0xFFFFFFFF; +constexpr uint32_t K_FILE_MODE_INVALID = 0xFFFFFFFF; enum TraceParserStatus { TRACE_PARSER_NORMAL = 0, TRACE_PARSER_FILE_TYPE_ERROR = 1, @@ -36,7 +36,7 @@ TraceParserStatus GetAnalysisResult(); ssize_t Read(int32_t fd, uint8_t* dst, size_t dstSize); -int32_t OpenFile(const std::string& path, int32_t flags, uint32_t mode = kFileModeInvalid); +int32_t OpenFile(const std::string& path, int32_t flags, uint32_t mode = K_FILE_MODE_INVALID); std::string GetExecutionDirectoryPath(); } // namespace base diff --git a/trace_streamer/src/base/htrace_plugin_time_parser.cpp b/trace_streamer/src/base/htrace_plugin_time_parser.cpp index 7e319fa29..a77b9ab6d 100644 --- a/trace_streamer/src/base/htrace_plugin_time_parser.cpp +++ b/trace_streamer/src/base/htrace_plugin_time_parser.cpp @@ -21,7 +21,7 @@ void HtracePluginTimeParser::UpdatePluginTimeRange(ClockId clockId, uint64_t asy { minTs_ = std::min(minTs_, asyncTimestamp); maxTs_ = std::max(maxTs_, asyncTimestamp); - if (clockId == PRIMARY_CLOCK_ID) { + if (clockId == g_primaryClockId) { syncHtracePluginStartTime_ = std::min(syncHtracePluginStartTime_, syncTimestamp); syncHtracePluginEndTime_ = std::max(syncHtracePluginEndTime_, syncTimestamp); return; @@ -34,7 +34,7 @@ void HtracePluginTimeParser::UpdatePluginTimeRange(ClockId clockId, uint64_t asy asyncHtracePluginEndTime_ = std::max(asyncHtracePluginEndTime_, syncTimestamp); } } -uint64_t HtracePluginTimeParser::GetPluginStartTime() +uint64_t HtracePluginTimeParser::GetPluginStartTime() const { if (syncHtracePluginStartTime_ != std::numeric_limits::max()) { return syncHtracePluginStartTime_; @@ -44,7 +44,7 @@ uint64_t HtracePluginTimeParser::GetPluginStartTime() return std::numeric_limits::max(); } -uint64_t HtracePluginTimeParser::GetPluginEndTime() +uint64_t HtracePluginTimeParser::GetPluginEndTime() const { if (syncHtracePluginEndTime_ != 0) { return syncHtracePluginEndTime_; diff --git a/trace_streamer/src/base/htrace_plugin_time_parser.h b/trace_streamer/src/base/htrace_plugin_time_parser.h index 924bd0f28..3899b2d18 100644 --- a/trace_streamer/src/base/htrace_plugin_time_parser.h +++ b/trace_streamer/src/base/htrace_plugin_time_parser.h @@ -24,8 +24,8 @@ public: HtracePluginTimeParser& operator=(const HtracePluginTimeParser&) = delete; ~HtracePluginTimeParser() = default; void UpdatePluginTimeRange(ClockId clockId, uint64_t asyncTimestamp, uint64_t syncTimestamp); - uint64_t GetPluginStartTime(); - uint64_t GetPluginEndTime(); + uint64_t GetPluginStartTime() const; + uint64_t GetPluginEndTime() const; uint64_t MinTs() const { return minTs_; diff --git a/trace_streamer/src/base/index_map.cpp b/trace_streamer/src/base/index_map.cpp index ac3196882..eabc4ed29 100644 --- a/trace_streamer/src/base/index_map.cpp +++ b/trace_streamer/src/base/index_map.cpp @@ -21,7 +21,7 @@ namespace SysTuning { namespace TraceStreamer { -IndexMap::IndexMap(TableRowId start, TableRowId end) : end_(end), current_(start), start_(start), type_(COMPACT) {} +IndexMap::IndexMap(TableRowId start, TableRowId end) : end_(end), current_(start), start_(start) {} void IndexMap::CovertToIndexMap() { @@ -146,12 +146,14 @@ void IndexMap::FilterTS(unsigned char op, sqlite3_value* argv, const std::deque< break; case SQLITE_INDEX_CONSTRAINT_GT: v++; + [[fallthrough]]; case SQLITE_INDEX_CONSTRAINT_GE: { IntersectGreaterEqual(times, v, getValue); break; } case SQLITE_INDEX_CONSTRAINT_LE: v++; + [[fallthrough]]; case SQLITE_INDEX_CONSTRAINT_LT: IntersectLessEqual(times, v, getValue); break; diff --git a/trace_streamer/src/base/index_map.h b/trace_streamer/src/base/index_map.h index 28169a851..dfe32dcdd 100644 --- a/trace_streamer/src/base/index_map.h +++ b/trace_streamer/src/base/index_map.h @@ -331,7 +331,7 @@ public: } } else { auto size = rows.size(); - for (auto i = 0; i < size; i++) { + for (size_t i = 0; i < size; i++) { if (rows[i] != invalidValue) { rowIndex_.push_back(i); } @@ -354,11 +354,8 @@ private: INDEX_TYPE_OUTER_INDEX, }; FindIndexType indexType_ = INDEX_TYPE_ID; - uint32_t indexSize_ = 0; - uint32_t index_ = 0; enum IndexType { COMPACT, SPARSE }; - uint8_t type_ = COMPACT; bool empty_ = true; bool desc_ = false; bool converted_ = false; diff --git a/trace_streamer/src/base/log.h b/trace_streamer/src/base/log.h index 6d9dbb6bf..90f8c9f93 100644 --- a/trace_streamer/src/base/log.h +++ b/trace_streamer/src/base/log.h @@ -27,11 +27,11 @@ __builtin_unreachable(); \ } while (0) enum LogLevel { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL }; -const enum LogLevel g_currentLogLevel = LOG_DEBUG; +const enum LogLevel CURRENT_LOG_LEVEL = LOG_DEBUG; extern bool g_cleanMode; #define LOGWITHLEVEL(level, motify, fmt, ...) \ do { \ - if (level >= g_currentLogLevel) { \ + if (level >= CURRENT_LOG_LEVEL) { \ if (!g_cleanMode) { \ fprintf(stdout, "[-%c][%s][%d]: " fmt "\n", motify, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ } \ diff --git a/trace_streamer/src/base/parting_string.cpp b/trace_streamer/src/base/parting_string.cpp index adff0f934..a5c9ec69d 100644 --- a/trace_streamer/src/base/parting_string.cpp +++ b/trace_streamer/src/base/parting_string.cpp @@ -27,7 +27,7 @@ bool PartingString::Next() { while (begin_ != end_) { if (*begin_ == delimiter_) { - begin_++; + ++begin_; continue; } @@ -43,11 +43,11 @@ bool PartingString::Next() } } while (begin_++ != end_); - if (*cur_) { + if (*cur_ != '\0') { return true; } - begin_++; + ++begin_; } cur_ = nullptr; diff --git a/trace_streamer/src/base/parting_string.h b/trace_streamer/src/base/parting_string.h index 91a56bfc5..9cb1767f1 100644 --- a/trace_streamer/src/base/parting_string.h +++ b/trace_streamer/src/base/parting_string.h @@ -22,7 +22,7 @@ namespace SysTuning { namespace base { class PartingString { public: - PartingString(std::string, char delimiter); + PartingString(std::string str, char delimiter); bool Next(); diff --git a/trace_streamer/src/base/sqlite_ext/sqlite_ext_funcs.cpp b/trace_streamer/src/base/sqlite_ext/sqlite_ext_funcs.cpp index 58da2731b..2f125f137 100644 --- a/trace_streamer/src/base/sqlite_ext/sqlite_ext_funcs.cpp +++ b/trace_streamer/src/base/sqlite_ext/sqlite_ext_funcs.cpp @@ -153,51 +153,51 @@ struct JsonBuild { JsonBuild() = default; void AppendHead() { - body_ += "{"; + body += "{"; } void AppendTail() { - body_ += "}"; + body += "}"; } void AppendCommon() { - body_ += ","; + body += ","; } bool AppendSqlValue(const std::string& field_name, const TSSqlValue& value) { - body_ += "\"" + field_name + "\":"; + body += "\"" + field_name + "\":"; return AppendSqlValue(value); } bool AppendSqlValue(const TSSqlValue& value) { switch (value.type) { case TS_LONG: - body_ += std::to_string(value.longValue) + ","; + body += std::to_string(value.longValue) + ","; break; case TS_DOUBLE: - body_ += std::to_string(value.doubleValue) + ","; + body += std::to_string(value.doubleValue) + ","; break; case TS_STRING: - body_ += "\"" + std::string(value.stringValue) + "\"" + ","; + body += "\"" + std::string(value.stringValue) + "\"" + ","; break; case TS_BYTES: - body_ += "\"" + std::string(static_cast(value.bytesValue), value.bytesCount) + "\"" + ","; + body += "\"" + std::string(static_cast(value.bytesValue), value.bytesCount) + "\"" + ","; break; case TS_NULL: - body_ += std::to_string(0) + ","; + body += std::to_string(0) + ","; break; } return true; } - std::string body_; - bool poped_ = false; + std::string body; + bool poped = false; void PopLast() { - body_.pop_back(); + body.pop_back(); } const std::string& Body() const { - return body_; + return body; } }; diff --git a/trace_streamer/src/base/string_to_numerical.h b/trace_streamer/src/base/string_to_numerical.h index 020f72c7b..4188385b7 100644 --- a/trace_streamer/src/base/string_to_numerical.h +++ b/trace_streamer/src/base/string_to_numerical.h @@ -48,7 +48,7 @@ inline std::string number(uint64_t value, int32_t base = INTEGER_RADIX_TYPE_DEC) } template -inline std::optional StrToInt(const std::string& str, int32_t base = INTEGER_RADIX_TYPE_DEC) +std::optional StrToInt(const std::string& str, int32_t base = INTEGER_RADIX_TYPE_DEC) { if (!str.empty()) { char* endPtr = nullptr; diff --git a/trace_streamer/src/base/ts_common.cpp b/trace_streamer/src/base/ts_common.cpp index 72c0e27be..5c0c967fe 100644 --- a/trace_streamer/src/base/ts_common.cpp +++ b/trace_streamer/src/base/ts_common.cpp @@ -12,5 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "ts_common.h" -BuiltinClocks PRIMARY_CLOCK_ID = TS_CLOCK_BOOTTIME; \ No newline at end of file +BuiltinClocks g_primaryClockId = TS_CLOCK_BOOTTIME; \ No newline at end of file diff --git a/trace_streamer/src/base/ts_common.h b/trace_streamer/src/base/ts_common.h index 3c6705b02..848f4438f 100644 --- a/trace_streamer/src/base/ts_common.h +++ b/trace_streamer/src/base/ts_common.h @@ -47,7 +47,7 @@ enum BuiltinClocks { TS_MONOTONIC_COARSE = 5, TS_MONOTONIC_RAW = 6, }; -extern BuiltinClocks PRIMARY_CLOCK_ID; +extern BuiltinClocks g_primaryClockId; enum RefType { K_REF_NO_REF = 0, K_REF_ITID = 1, diff --git a/trace_streamer/src/filter/BUILD.gn b/trace_streamer/src/filter/BUILD.gn index 5073653b1..92facc8e0 100644 --- a/trace_streamer/src/filter/BUILD.gn +++ b/trace_streamer/src/filter/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../build/ts.gni") ohos_source_set("filter") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "animation_filter.cpp", "animation_filter.h", @@ -44,6 +44,8 @@ ohos_source_set("filter") { "native_hook_filter.h", "offline_symbolization_filter.cpp", "offline_symbolization_filter.h", + "perf_data_filter.cpp", + "perf_data_filter.h", "process_filter.cpp", "process_filter.h", "slice_filter.cpp", @@ -72,7 +74,7 @@ ohos_source_set("filter") { cflags += [ "-D IS_UT" ] } } - public_deps = [ "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_data_encoder" ] + public_deps = [ "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_data_reader" ] deps = [] include_dirs = [ "${SRC}/base", @@ -89,11 +91,4 @@ ohos_source_set("filter") { "../proto_reader/include", ".", ] - - if (with_perf) { - sources += [ - "perf_data_filter.cpp", - "perf_data_filter.h", - ] - } } diff --git a/trace_streamer/src/filter/animation_filter.cpp b/trace_streamer/src/filter/animation_filter.cpp index 6b0c042d0..941d73069 100644 --- a/trace_streamer/src/filter/animation_filter.cpp +++ b/trace_streamer/src/filter/animation_filter.cpp @@ -67,7 +67,7 @@ bool AnimationFilter::UpdateDeviceInfoEvent(const TracePoint& point, const Bytra uint8_t index = 0; uint32_t width = base::StrToInt(matcheLine[++index].str()).value(); uint32_t height = base::StrToInt(matcheLine[++index].str()).value(); - traceDataCache_->GetDeviceInfo()->UpdateWidthAndHeight(width, height); + traceDataCache_->GetDeviceInfo()->UpdateWidthAndHeight(matcheLine); TS_LOGI("physical width is %u, height is %u", width, height); } else { TS_LOGE("Not support this event: %s\n", point.name_.data()); @@ -147,12 +147,9 @@ void AnimationFilter::UpdateDynamicFrameInfo() const std::string& curStackName = traceDataCache_->GetDataFromDict(nameDataIndex); const std::string& funcArgs = curStackName.substr(leashWindowCmd_.size()); if (std::regex_search(funcArgs, matcheLine, leashWindowPattern)) { - uint8_t index = 0; - dynamicFrame->UpdatePosition(curFrameRow, base::StrToInt(matcheLine[++index].str()).value(), // x - base::StrToInt(matcheLine[++index].str()).value(), // y - base::StrToInt(matcheLine[++index].str()).value(), // width - base::StrToInt(matcheLine[++index].str()).value(), // height - traceDataCache_->GetDataIndex((matcheLine[++index].str()))); // alpha + dynamicFrame->UpdatePosition( + curFrameRow, matcheLine, + traceDataCache_->GetDataIndex((matcheLine[DYNAMICFRAME_MATCH_LAST].str()))); // alpha } else { TS_LOGE("Not support this event: %s\n", funcArgs.data()); break; diff --git a/trace_streamer/src/filter/app_start_filter.cpp b/trace_streamer/src/filter/app_start_filter.cpp index e86f79313..39828c59d 100644 --- a/trace_streamer/src/filter/app_start_filter.cpp +++ b/trace_streamer/src/filter/app_start_filter.cpp @@ -46,6 +46,9 @@ bool APPStartupFilter::GetProcessCreate(uint32_t row, uint64_t& startTime, std:: return true; } parentId = sliceData.ParentIdData()[parentId].value(); + if (parentId == INVALID_UINT32) { + continue; + } name = traceDataCache_->GetDataFromDict(sliceData.NamesData()[parentId]); } return false; @@ -55,7 +58,6 @@ bool APPStartupFilter::CaclRsDataByPid(appMap& mAPPStartupData) { auto frameSliceData = traceDataCache_->GetFrameSliceData(); auto sliceData = traceDataCache_->GetConstInternalSlicesData(); - auto itor = mAPPStartupData.begin(); for (const auto& item : mAPPStartupData) { if (item.second.empty()) { continue; @@ -74,8 +76,8 @@ bool APPStartupFilter::CaclRsDataByPid(appMap& mAPPStartupData) } mAPPStartupData[dataIndex].emplace( FIRST_FRAME_APP_PHASE, - std::move(std::make_unique(callId, itorSecond->second->ipid_, - itorSecond->second->tid_, startTime, endTime))); + std::make_unique(callId, itorSecond->second->ipid_, itorSecond->second->tid_, + startTime, endTime)); auto dstId = frameSliceData->Dsts()[m]; if (dstId == INVALID_UINT64) { continue; @@ -85,8 +87,8 @@ bool APPStartupFilter::CaclRsDataByPid(appMap& mAPPStartupData) endTime = startTime + frameSliceData->Durs()[dstId]; mAPPStartupData[dataIndex].emplace( FIRST_FRAME_RENDER_PHASE, - std::move(std::make_unique(callId, itorSecond->second->ipid_, - itorSecond->second->tid_, startTime, endTime))); + std::make_unique(callId, itorSecond->second->ipid_, itorSecond->second->tid_, + startTime, endTime)); break; } } @@ -154,8 +156,8 @@ void APPStartupFilter::UpdateAPPStartupData(uint32_t row, const std::string& nam auto callId = sliceData.CallIds()[row]; auto startTime = sliceData.TimeStampData()[row]; mAPPStartupData_[dataIndex].insert( - std::make_pair(startIndex, std::move(std::make_unique(callId, INVALID_UINT32, INVALID_UINT32, - startTime, INVALID_UINT64)))); + std::make_pair(startIndex, std::make_unique(callId, INVALID_UINT32, INVALID_UINT32, startTime, + INVALID_UINT64))); } void APPStartupFilter::ParserAppStartup() @@ -182,8 +184,8 @@ void APPStartupFilter::ParserAppStartup() callId = sliceData.CallIds()[i]; auto dataIndex = traceDataCache_->GetDataIndex(mainThreadName.c_str()); mAPPStartupData_[dataIndex].insert(std::make_pair( - PROCESS_CREATING, std::move(std::make_unique(callId, INVALID_UINT32, INVALID_UINT32, - startTime, INVALID_UINT64)))); + PROCESS_CREATING, + std::make_unique(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64))); } else if (StartWith(nameString, APP_LAUNCH)) { UpdateAPPStartupData(i, nameString, APPLICATION_LAUNCHING); } else if (StartWith(nameString, LAUNCH)) { @@ -201,8 +203,8 @@ void APPStartupFilter::ParserAppStartup() auto thread = traceDataCache_->GetThreadData(sliceData.CallIds()[i]); thread->nameIndex_ = dataIndex; mAPPStartupData_[dataIndex].insert(std::make_pair( - UI_ABILITY_LAUNCHING, std::move(std::make_unique( - callId, thread->internalPid_, thread->tid_, startTime, INVALID_UINT64)))); + UI_ABILITY_LAUNCHING, std::make_unique(callId, thread->internalPid_, thread->tid_, + startTime, INVALID_UINT64))); mAPPStartupDataWithPid_.insert(std::make_pair(thread->internalPid_, std::move(mAPPStartupData_))); } else if (StartWith(nameString, ONFOREGROUND)) { // callid is thread table->itid @@ -214,9 +216,9 @@ void APPStartupFilter::ParserAppStartup() auto tid = threadData[callId].tid_; if (mAPPStartupDataWithPid_.count(ipid) && mAPPStartupDataWithPid_[ipid].count(nameindex) && !mAPPStartupDataWithPid_[ipid][nameindex].count(UI_ABILITY_ONFOREGROUND)) { - mAPPStartupDataWithPid_[ipid][nameindex].insert(std::make_pair( - UI_ABILITY_ONFOREGROUND, - std::move(std::make_unique(callId, ipid, tid, startTime, INVALID_UINT64)))); + mAPPStartupDataWithPid_[ipid][nameindex].insert( + std::make_pair(UI_ABILITY_ONFOREGROUND, + std::make_unique(callId, ipid, tid, startTime, INVALID_UINT64))); } } } diff --git a/trace_streamer/src/filter/clock_filter_ex.h b/trace_streamer/src/filter/clock_filter_ex.h index a8d5bdb6d..7a5802d6e 100644 --- a/trace_streamer/src/filter/clock_filter_ex.h +++ b/trace_streamer/src/filter/clock_filter_ex.h @@ -23,6 +23,14 @@ #include #include "htrace_file_header.h" #include "ts_common.h" +#include +#include "clock_filter.h" +#include "filter_base.h" +#include +namespace SysTuning { +namespace TraceStreamer { +class TraceDataCache; +class TraceStreamerFilters; /* * TS_REALTIME: A settable system-wide clock that measures real time. Its time represents seconds and nanoseconds * since the Epoch. @@ -37,18 +45,10 @@ * 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. */ -#include -#include "clock_filter.h" -#include "filter_base.h" -#include -namespace SysTuning { -namespace TraceStreamer { -class TraceDataCache; -class TraceStreamerFilters; class ClockFilterEx : public FilterBase, public ClockFilter { public: ClockFilterEx(TraceDataCache* dataCache, const TraceStreamerFilters* filter); - ~ClockFilterEx(); + ~ClockFilterEx() override; void AddClockSnapshot(const std::vector& snapShot); private: diff --git a/trace_streamer/src/filter/frame_filter.cpp b/trace_streamer/src/filter/frame_filter.cpp index 4a0f6f7ba..b15ff0a38 100644 --- a/trace_streamer/src/filter/frame_filter.cpp +++ b/trace_streamer/src/filter/frame_filter.cpp @@ -14,6 +14,7 @@ */ #include "frame_filter.h" #include +#include #include "log.h" #define ISINVALIDU32(value) (value == INVALID_UINT32) namespace SysTuning { @@ -55,7 +56,7 @@ bool FrameFilter::MarkRSOnvsyncEvent(uint64_t ts, uint32_t itid) { auto frame = vsyncRenderSlice_.find(itid); if (frame == vsyncRenderSlice_.end()) { - TS_LOGW("BeginOnvsyncEvent find for itid:%u failed, ts:%llu", itid, ts); + TS_LOGW("BeginOnvsyncEvent find for itid:%u failed, ts:%" PRIu64 "", itid, ts); return false; } if (!frame->second.size()) { @@ -173,11 +174,11 @@ bool FrameFilter::EndVsyncEvent(uint64_t ts, uint32_t itid) { auto frame = vsyncRenderSlice_.find(itid); if (frame == vsyncRenderSlice_.end()) { - TS_LOGW("EndVsyncEvent find for itid:%u ts:%llu failed", itid, ts); + TS_LOGW("EndVsyncEvent find for itid:%u ts:%" PRIu64 " failed", itid, ts); return false; } if (!frame->second.size()) { - TS_LOGW("EndVsyncEvent find for itid:%u ts:%llu failed", itid, ts); + TS_LOGW("EndVsyncEvent find for itid:%u ts:%" PRIu64 " failed", itid, ts); return false; } auto lastFrameSlice = frame->second.back(); @@ -226,11 +227,11 @@ bool FrameFilter::EndFrameQueue(uint64_t ts, uint32_t itid) { auto frame = vsyncRenderSlice_.find(itid); if (frame == vsyncRenderSlice_.end()) { - TS_LOGW("EndFrameQueue find for itid:%u ts:%llu failed", itid, ts); + TS_LOGW("EndFrameQueue find for itid:%u ts:%" PRIu64 " failed", itid, ts); return false; } if (!frame->second.size()) { - TS_LOGW("EndFrameQueue find for itid:%u ts:%llu failed", itid, ts); + TS_LOGW("EndFrameQueue find for itid:%u ts:%" PRIu64 " failed", itid, ts); return false; } auto firstFrameSlicePos = frame->second.begin(); diff --git a/trace_streamer/src/filter/frame_filter.h b/trace_streamer/src/filter/frame_filter.h index 71c5b2d47..73152c9b8 100644 --- a/trace_streamer/src/filter/frame_filter.h +++ b/trace_streamer/src/filter/frame_filter.h @@ -77,7 +77,6 @@ private: std::unordered_map>> vsyncRenderSlice_ = {}; std::unordered_map>> dstRenderSlice_ = {}; - bool checkFrameAlwasy_ = false; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/filter/native_hook_filter.cpp b/trace_streamer/src/filter/native_hook_filter.cpp index 1b6504689..f19d0f39a 100644 --- a/trace_streamer/src/filter/native_hook_filter.cpp +++ b/trace_streamer/src/filter/native_hook_filter.cpp @@ -15,6 +15,7 @@ #include "native_hook_filter.h" #include "native_hook_config.pbreader.h" +#include namespace SysTuning { namespace TraceStreamer { NativeHookFilter::NativeHookFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) @@ -112,13 +113,12 @@ std::unique_ptr NativeHookFilter::ParseFrame(const ProtoRea } auto frameInfo = std::make_unique(reader.ip(), reader.sp(), symbolIndex, filePathIndex, reader.offset(), reader.symbol_offset()); - return std::move(frameInfo); + return frameInfo; } void NativeHookFilter::CompressStackAndFrames(ProtoReader::RepeatedDataAreaIterator frames) { std::vector framesHash; - uint64_t frameHash = INVALID_UINT64; std::string framesHashStr = ""; for (auto itor = frames; itor; itor++) { std::string_view frameStr(reinterpret_cast(itor->Data()), itor->Size()); @@ -496,10 +496,10 @@ std::tuple NativeHookFilter::GetNeedUpdateProcessMapsAddrRan } inline void NativeHookFilter::FillOfflineSymbolizationFrames( - std::map>>::iterator itor) + std::map>>::iterator mapItor) { - stackIdToCallChainIdMap_.insert(std::make_pair(itor->first, ++callChainId_)); - auto framesInfo = OfflineSymbolization(itor->second); + stackIdToCallChainIdMap_.insert(std::make_pair(mapItor->first, ++callChainId_)); + auto framesInfo = OfflineSymbolization(mapItor->second); uint64_t depth = 0; uint64_t filePathIndex; for (auto itor = framesInfo->rbegin(); itor != framesInfo->rend(); itor++) { @@ -671,7 +671,7 @@ void NativeHookFilter::MaybeUpdateCurrentSizeDur(uint64_t row, uint64_t timeStam void NativeHookFilter::UpdateSymbolIdsForSymbolizationFailed() { auto size = traceDataCache_->GetNativeHookFrameData()->Size(); - for (auto i = 0; i < size; ++i) { + for (size_t i = 0; i < size; ++i) { if (traceDataCache_->GetNativeHookFrameData()->SymbolNames()[i] == INVALID_UINT64) { auto filePathIndex = traceDataCache_->GetNativeHookFrameData()->FilePaths()[i]; auto filePathStr = traceDataCache_->dataDict_.GetDataFromDict(filePathIndex); @@ -873,7 +873,7 @@ bool NativeHookFilter::GetIpsWitchNeedResymbolization(DataIndex filePathId, std: bool value = false; for (auto itor = ipToFrameInfo_.begin(); itor != ipToFrameInfo_.end(); itor++) { if (!itor->second) { - TS_LOGI("ip :%lu can not symbolization! FrameInfo is nullptr", itor->first); + TS_LOGI("ip :%llu can not symbolization! FrameInfo is nullptr", itor->first); continue; } if (itor->second->filePathId_ == filePathId) { diff --git a/trace_streamer/src/filter/offline_symbolization_filter.cpp b/trace_streamer/src/filter/offline_symbolization_filter.cpp index 34c488058..255064de1 100644 --- a/trace_streamer/src/filter/offline_symbolization_filter.cpp +++ b/trace_streamer/src/filter/offline_symbolization_filter.cpp @@ -18,8 +18,8 @@ namespace SysTuning { namespace TraceStreamer { OfflineSymbolizationFilter::OfflineSymbolizationFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) : FilterBase(dataCache, filter), - symbolTablePtrAndStValueToSymAddr_(nullptr), - filePathIdAndStValueToSymAddr_(nullptr) + filePathIdAndStValueToSymAddr_(nullptr), + symbolTablePtrAndStValueToSymAddr_(nullptr) { } std::shared_ptr>> OfflineSymbolizationFilter::OfflineSymbolization( @@ -52,7 +52,7 @@ void OfflineSymbolizationFilter::GetSymbolStartMaybeUpdateFrameInfo(T* elfSym, } } -bool OfflineSymbolizationFilter::FillFrameInfo(std::shared_ptr& frameInfo, +bool OfflineSymbolizationFilter::FillFrameInfo(const std::shared_ptr& frameInfo, uint64_t ip, uint64_t& vmStart, uint64_t& vmOffset) diff --git a/trace_streamer/src/filter/offline_symbolization_filter.h b/trace_streamer/src/filter/offline_symbolization_filter.h index 12a1857ef..16eca11d0 100644 --- a/trace_streamer/src/filter/offline_symbolization_filter.h +++ b/trace_streamer/src/filter/offline_symbolization_filter.h @@ -73,12 +73,12 @@ protected: private: template - void GetSymbolStartMaybeUpdateFrameInfo(T* elfSym, - uint32_t& symbolStart, - uint64_t symVaddr, - uint64_t ip, - FrameInfo* frameInfo); - bool FillFrameInfo(std::shared_ptr& frameInfo, uint64_t ip, uint64_t& vmStart, uint64_t& vmOffset); + static void GetSymbolStartMaybeUpdateFrameInfo(T* elfSym, + uint32_t& symbolStart, + uint64_t symVaddr, + uint64_t ip, + FrameInfo* frameInfo); + bool FillFrameInfo(const std::shared_ptr& frameInfo, uint64_t ip, uint64_t& vmStart, uint64_t& vmOffset); }; } // namespace TraceStreamer diff --git a/trace_streamer/src/filter/process_filter.cpp b/trace_streamer/src/filter/process_filter.cpp index b7b018444..d59796ef6 100644 --- a/trace_streamer/src/filter/process_filter.cpp +++ b/trace_streamer/src/filter/process_filter.cpp @@ -127,7 +127,7 @@ uint32_t ProcessFilter::UpdateOrCreateThreadWithNameIndex(uint64_t timeStamp, ui } for (auto i : internalTids) { thread = traceDataCache_->GetThreadData(i); - if (threadNameIndex != thread->nameIndex_) { + if (thread && threadNameIndex != thread->nameIndex_) { thread->nameIndex_ = threadNameIndex; } } diff --git a/trace_streamer/src/include/BUILD.gn b/trace_streamer/src/include/BUILD.gn index 700014459..406b80d34 100755 --- a/trace_streamer/src/include/BUILD.gn +++ b/trace_streamer/src/include/BUILD.gn @@ -12,8 +12,8 @@ # limitations under the License. import("//build/ohos.gni") ohos_source_set("ibase") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "codec_cov.h", "file.h", diff --git a/trace_streamer/src/main.cpp b/trace_streamer/src/main.cpp index 74d020163..1f78dedff 100644 --- a/trace_streamer/src/main.cpp +++ b/trace_streamer/src/main.cpp @@ -235,7 +235,16 @@ struct HttpOption { bool enable = false; int port = 9001; }; - +int CheckFinal(char** argv, TraceExportOption& traceExportOption, HttpOption& httpOption) +{ + if ((traceExportOption.traceFilePath.empty() || + (!traceExportOption.interactiveState && traceExportOption.sqliteFilePath.empty())) && + !httpOption.enable && !traceExportOption.separateFile && traceExportOption.sqlOperatorFilePath.empty()) { + ShowHelpInfo(argv[0]); + return 1; + } + return 0; +} int CheckArgs(int argc, char** argv, TraceExportOption& traceExportOption, HttpOption& httpOption) { for (int i = 1; i < argc; i++) { @@ -283,13 +292,7 @@ int CheckArgs(int argc, char** argv, TraceExportOption& traceExportOption, HttpO } traceExportOption.traceFilePath = std::string(argv[i]); } - if ((traceExportOption.traceFilePath.empty() || - (!traceExportOption.interactiveState && traceExportOption.sqliteFilePath.empty())) && - !httpOption.enable && !traceExportOption.separateFile && traceExportOption.sqlOperatorFilePath.empty()) { - ShowHelpInfo(argv[0]); - return 1; - } - return 0; + return CheckFinal(argv, traceExportOption, httpOption); } } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/parser/BUILD.gn b/trace_streamer/src/parser/BUILD.gn index 2a5e21d6a..c940b3cfe 100644 --- a/trace_streamer/src/parser/BUILD.gn +++ b/trace_streamer/src/parser/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../build/ts.gni") ohos_source_set("parser") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "bytrace_parser/bytrace_event_parser.cpp", "bytrace_parser/bytrace_event_parser.h", @@ -31,16 +31,16 @@ ohos_source_set("parser") { "thread_state_flag.h", ] deps = [ - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:cpu_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/diskio_data:diskio_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hidump_data:hidump_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:hilog_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:hisysevent_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/js_memory:js_memory_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/network_data:network_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/process_data:process_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:cpu_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/diskio_data:diskio_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hidump_data:hidump_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:hilog_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:hisysevent_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/js_memory:js_memory_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/network_data:network_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/process_data:process_data_reader", "ebpf_parser:ebpf_parser", ] deps += [ "htrace_pbreader_parser:htrace_pbreader_parser" ] @@ -56,7 +56,7 @@ ohos_source_set("parser") { "${SRC}/filter", "${SRC}", ".", - "${THIRD_PARTY}/json-master/single_include/nlohmann", + "${THIRD_PARTY}/json/single_include/nlohmann", ] include_dirs += [ "htrace_pbreader_parser" ] diff --git a/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp b/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp index 7fbc40684..810599a19 100644 --- a/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp +++ b/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp @@ -642,7 +642,7 @@ bool BytraceEventParser::BinderTransactionAllocBufEvent(const ArgsMap& args, con } void BytraceEventParser::ParseDataItem(const BytraceLine& line) { - eventList_.push_back(std::move(std::make_unique(line.ts, std::move(line)))); + eventList_.push_back(std::make_unique(line.ts, std::move(line))); return; } void BytraceEventParser::GetDataSegArgs(BytraceLine& bufLine, ArgsMap& args, uint32_t& tgid) const diff --git a/trace_streamer/src/parser/ebpf_parser/BUILD.gn b/trace_streamer/src/parser/ebpf_parser/BUILD.gn index df0b8c003..4a1a98947 100644 --- a/trace_streamer/src/parser/ebpf_parser/BUILD.gn +++ b/trace_streamer/src/parser/ebpf_parser/BUILD.gn @@ -14,8 +14,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("ebpf_parser_src") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "bio_latency_data_parser.cpp", "bio_latency_data_parser.h", @@ -44,7 +44,7 @@ ohos_source_set("ebpf_parser_src") { "${THIRD_PARTY}/protobuf/src", "${THIRD_PARTY}/sqlite/include", ] - public_deps = [ "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_encoder" ] + public_deps = [ "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_reader" ] if (is_win || is_macx) { include_dirs += [ "${THIRD_PARTY}/perf_include/linux", diff --git a/trace_streamer/src/parser/ebpf_parser/bio_latency_data_parser.cpp b/trace_streamer/src/parser/ebpf_parser/bio_latency_data_parser.cpp index 7f3e9c478..41530723e 100644 --- a/trace_streamer/src/parser/ebpf_parser/bio_latency_data_parser.cpp +++ b/trace_streamer/src/parser/ebpf_parser/bio_latency_data_parser.cpp @@ -68,8 +68,8 @@ void BioLatencyDataParser::ParseBioLatencyEvent() auto newEndTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, endTs); timeParser_->UpdatePluginTimeRange(clockId_, endTs, newEndTs); if (newStartTs > newEndTs) { - TS_LOGE("File system event origin startTs = %lu, endTs = %lu, newStartTs = %lu, newEndTs = %lu", startTs, - endTs, newStartTs, newEndTs); + TS_LOGE("File system event origin startTs = %llu, endTs = %llu, newStartTs = %llu, newEndTs = %llu", + startTs, endTs, newStartTs, newEndTs); streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_PAGED_MEMORY, STAT_EVENT_DATA_INVALID); return; } diff --git a/trace_streamer/src/parser/ebpf_parser/ebpf_data_reader.cpp b/trace_streamer/src/parser/ebpf_parser/ebpf_data_reader.cpp index cc191bdfb..88392d1fa 100644 --- a/trace_streamer/src/parser/ebpf_parser/ebpf_data_reader.cpp +++ b/trace_streamer/src/parser/ebpf_parser/ebpf_data_reader.cpp @@ -16,6 +16,7 @@ #include "ebpf_data_reader.h" #include "file_system_data_parser.h" #include "string_help.h" +#include namespace SysTuning { namespace TraceStreamer { @@ -23,7 +24,7 @@ using namespace SysTuning::base; using namespace SysTuning::EbpfStdtype; EbpfDataReader::EbpfDataReader(TraceDataCache* dataCache, const TraceStreamerFilters* filter) : EventParserBase(dataCache, filter), - ebpfDataHeader_(reinterpret_cast(startAddr_)), + ebpfDataHeader_(nullptr), pidAndStartAddrToMapsAddr_(nullptr), elfAddrAndStValueToSymAddr_(nullptr), tracerEventToStrIndex_(INVALID_UINT64), @@ -47,20 +48,20 @@ bool EbpfDataReader::InitEbpfData(const std::deque& dequeBuffer, uint64 bool EbpfDataReader::InitEbpfHeader() { if (bufferSize_ < EbpfDataHeader::EBPF_DATA_HEADER_SIZE) { - TS_LOGE("buffer size less than ebpf data header!!!, bufferSize_ = %lu ", bufferSize_); + TS_LOGE("buffer size less than ebpf data header!!!, bufferSize_ = %llu ", bufferSize_); return false; } ebpfDataHeader_ = reinterpret_cast(startAddr_); if (ebpfDataHeader_->header.magic != EbpfDataHeader::HEADER_MAGIC) { - TS_LOGE("Get EBPF file header failed! magic = %lx", ebpfDataHeader_->header.magic); + TS_LOGE("Get EBPF file header failed! magic = %llx", ebpfDataHeader_->header.magic); return false; } if (ebpfDataHeader_->header.headSize != EbpfDataHeader::EBPF_DATA_HEADER_SIZE) { TS_LOGE("Get ebpf file header failed! headSize = %u", ebpfDataHeader_->header.headSize); return false; } - TS_LOGI("EBPF data header : magic = %llx, headSize = %llu, clock = %llu, cmdline = %s", + TS_LOGI("EBPF data header : magic = %" PRIu64 ", headSize = %u, clock = %u, cmdline = %s", ebpfDataHeader_->header.magic, ebpfDataHeader_->header.headSize, ebpfDataHeader_->header.clock, ebpfDataHeader_->cmdline); startAddr_ += EbpfDataHeader::EBPF_DATA_HEADER_SIZE; @@ -76,7 +77,7 @@ bool EbpfDataReader::ReadEbpfData() unresolvedLen_ -= EBPF_TITLE_SIZE; if (dataTitle->length > unresolvedLen_) { TS_LOGE("Get EBPF data Title failed!"); - TS_LOGE("type = %lx, length = %lx", dataTitle->type, dataTitle->length); + TS_LOGE("type = %x, length = %x", dataTitle->type, dataTitle->length); return false; } if (dataTitle->length == 0) { @@ -186,7 +187,7 @@ void EbpfDataReader::ReadKernelSymAddrMap(const KernelSymbolInfoHeader* elfAddr, maxKernelAddr_ = elfAddr->vaddrEnd; minKernelAddr_ = elfAddr->vaddrStart; for (auto i = 0; i < sysItemSize; i++) { - (void*)memset_s(strSymbolName_, MAX_SYMBOL_LENGTH, 0, MAX_SYMBOL_LENGTH); + (void)memset_s(strSymbolName_, MAX_SYMBOL_LENGTH, 0, MAX_SYMBOL_LENGTH); auto item = start + i; if (strncpy_s(strSymbolName_, MAX_SYMBOL_LENGTH, strTab + item->nameOffset, MAX_SYMBOL_LENGTH) < 0) { TS_LOGE("get kernel symbol name error"); @@ -321,7 +322,7 @@ bool EbpfDataReader::ReadItemEventStr(const uint8_t* buffer, uint32_t size) streamFilters_->processFilter_->GetOrCreateThreadWithPid(strFixedHeaderAddr->tid, strFixedHeaderAddr->pid); auto strAddr = const_cast(reinterpret_cast(strFixedHeaderAddr + 1)); if ((strFixedHeaderAddr->strLen > size - sizeof(StrEventFixedHeader)) || !strFixedHeaderAddr->strLen) { - TS_LOGE("invalid str event, strEventFixedHeader = %u, strlen = %d, size = %d", sizeof(StrEventFixedHeader), + TS_LOGE("invalid str event, strEventFixedHeader = %lu, strlen = %d, size = %d", sizeof(StrEventFixedHeader), strFixedHeaderAddr->strLen, size); return true; } diff --git a/trace_streamer/src/parser/ebpf_parser/file_system_data_parser.cpp b/trace_streamer/src/parser/ebpf_parser/file_system_data_parser.cpp index 7293d55af..0bb185e64 100644 --- a/trace_streamer/src/parser/ebpf_parser/file_system_data_parser.cpp +++ b/trace_streamer/src/parser/ebpf_parser/file_system_data_parser.cpp @@ -77,7 +77,7 @@ void FileSystemDataParser::ParseFileSystemEvent() auto newEndTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, fsFixedHeadrAddr->endTime); timeParser_->UpdatePluginTimeRange(clockId_, fsFixedHeadrAddr->endTime, newEndTs); if (newStartTs > newEndTs) { - TS_LOGE("File system event origin startTs = %lu, endTs = %lu, newStartTs = %lu, newEndTs = %lu", + TS_LOGE("File system event origin startTs = %llu, endTs = %llu, newStartTs = %llu, newEndTs = %llu", fsFixedHeadrAddr->startTime, fsFixedHeadrAddr->endTime, newStartTs, newEndTs); streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_FILE_SYSTEM, STAT_EVENT_DATA_INVALID); return; diff --git a/trace_streamer/src/parser/ebpf_parser/paged_memory_data_parser.cpp b/trace_streamer/src/parser/ebpf_parser/paged_memory_data_parser.cpp index b159da1d4..70a5a3478 100644 --- a/trace_streamer/src/parser/ebpf_parser/paged_memory_data_parser.cpp +++ b/trace_streamer/src/parser/ebpf_parser/paged_memory_data_parser.cpp @@ -54,7 +54,7 @@ void PagedMemoryDataParser::ParsePagedMemoryEvent() currentCallId_ = callChainId_++; } } else { - currentCallId_ = INVALID_UINT64; + currentCallId_ = INVALID_UINT32; } auto type = pagedMemoryFixedHeadrAddr->type; @@ -71,7 +71,7 @@ void PagedMemoryDataParser::ParsePagedMemoryEvent() auto newEndTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, endTs); timeParser_->UpdatePluginTimeRange(clockId_, endTs, newEndTs); if (newStartTs > newEndTs) { - TS_LOGE("paged memory startTs = %lu, endTs = %lu, newStartTs = %lu, newEndTs = %lu", startTs, endTs, + TS_LOGE("paged memory startTs = %llu, endTs = %llu, newStartTs = %llu, newEndTs = %llu", startTs, endTs, newStartTs, newEndTs); streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_PAGED_MEMORY, STAT_EVENT_DATA_INVALID); return; diff --git a/trace_streamer/src/parser/hiperf_parser/BUILD.gn b/trace_streamer/src/parser/hiperf_parser/BUILD.gn index 9a9e90161..445869e40 100644 --- a/trace_streamer/src/parser/hiperf_parser/BUILD.gn +++ b/trace_streamer/src/parser/hiperf_parser/BUILD.gn @@ -14,8 +14,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("hiperf_parser_src") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "perf_data_parser.cpp" ] include_dirs = [ "${THIRD_PARTY}/hiperf/include/nonlinux/linux", @@ -34,11 +34,18 @@ ohos_source_set("hiperf_parser_src") { "${THIRD_PARTY}/protobuf/src", "${THIRD_PARTY}/perf_include", "${THIRD_PARTY}/perf_include/libbpf", + "//developtools/hiperf/include", + "//commonlibrary/c_utils/base/include", + "${THIRD_PARTY}/googletest/googletest/include", ] include_dirs += [ "${THIRD_PARTY}/libunwind/include" ] + cflags = [ "-D target_cpu_${target_cpu}" ] + if (!use_wasm && !is_win && !is_macx && !is_test) { + cflags += [ "-D HAVE_LIBUNWIND" ] + } if (enable_ts_utest && !use_wasm) { - cflags = [ + cflags += [ "-fprofile-arcs", "-ftest-coverage", ] @@ -56,7 +63,7 @@ ohos_source_set("hiperf_parser_src") { group("hiperf_parser") { deps = [ ":hiperf_parser_src", - "${PERF_DIR}/hiperf:hiperf", + "${PERF_DIR}/hiperf:hiperf_platform_common", "${THIRD_PARTY}/protobuf:protobuf", "${THIRD_PARTY}/protobuf:protobuf_lite", ] diff --git a/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp b/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp index c268c099b..1711e5e72 100644 --- a/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp +++ b/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp @@ -73,8 +73,8 @@ bool PerfDataParser::LoadPerfData() fprintf(stdout, "Failed to create file: %s", tmpPerfData_.c_str()); return false; } - auto ret = ftruncate(fd, 0); - if (bufferSize_ != write(fd, buffer_.get(), bufferSize_)) { + (void)ftruncate(fd, 0); + if (bufferSize_ != (size_t)write(fd, buffer_.get(), bufferSize_)) { close(fd); return false; } @@ -262,8 +262,7 @@ uint32_t PerfDataParser::UpdatePerfCallChainData(const std::unique_ptrsecond; - callStackTemp.emplace_back( - std::move(std::make_unique(depth, frame->vaddrInFile_, fileId, symbolId))); + callStackTemp.emplace_back(std::make_unique(depth, frame->vaddrInFile_, fileId, symbolId)); depth++; } // Determine whether to write callstack data to cache diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/BUILD.gn b/trace_streamer/src/parser/htrace_pbreader_parser/BUILD.gn index 4cf1aa16c..0aef8955a 100755 --- a/trace_streamer/src/parser/htrace_pbreader_parser/BUILD.gn +++ b/trace_streamer/src/parser/htrace_pbreader_parser/BUILD.gn @@ -13,8 +13,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("htrace_pbreader_parser_src") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "../parser_base.cpp", "htrace_clock_detail_parser.cpp", @@ -34,6 +34,8 @@ ohos_source_set("htrace_pbreader_parser_src") { "htrace_hilog_parser.h", "htrace_hisysevent_parser.cpp", "htrace_hisysevent_parser.h", + "htrace_js_cpu_profiler_parser.cpp", + "htrace_js_cpu_profiler_parser.h", "htrace_js_memory_parser.cpp", "htrace_js_memory_parser.h", "htrace_mem_parser.cpp", @@ -61,7 +63,7 @@ ohos_source_set("htrace_pbreader_parser_src") { "../../trace_streamer", "${THIRD_PARTY}/protobuf/src", "${THIRD_PARTY}/sqlite/include", - "${THIRD_PARTY}/json-master/single_include/nlohmann", + "${THIRD_PARTY}/json/single_include/nlohmann", "../../filter", "../../base", "../ebpf_parser", @@ -72,20 +74,24 @@ ohos_source_set("htrace_pbreader_parser_src") { "${THIRD_PARTY}/hiperf/include", "${THIRD_PARTY}/hiperf/include/nonlinux/linux", "${THIRD_PARTY}/hiperf/include/nonlinux", + "//developtools/hiperf/include", + "${THIRD_PARTY}/musl", + "${THIRD_PARTY}/googletest/googletest/include", + "${THIRD_PARTY}/perf_include/musl", + "${THIRD_PARTY}/perf_include/libbpf", + "${THIRD_PARTY}/perf_include/include", + "${THIRD_PARTY}/perf_include", + "${THIRD_PARTY}/perf_include/linux", + "../hiperf_parser", + "../hiperf_parser/include", ] - if (with_perf) { - include_dirs += [ - "${THIRD_PARTY}/perf_include/musl", - "${THIRD_PARTY}/perf_include/libbpf", - "${THIRD_PARTY}/perf_include/include", - "${THIRD_PARTY}/perf_include", - "${THIRD_PARTY}/perf_include/linux", - "../hiperf_parser", - "../hiperf_parser/include", - ] + + cflags = [ "-D target_cpu_${target_cpu}" ] + if (!use_wasm && !is_win && !is_macx && !is_test) { + cflags += [ "-D HAVE_LIBUNWIND" ] } if (enable_ts_utest && !use_wasm) { - cflags = [ + cflags += [ "-fprofile-arcs", "-ftest-coverage", ] @@ -97,18 +103,18 @@ ohos_source_set("htrace_pbreader_parser_src") { } public_deps = [] deps = [ - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/services:all_type_cpp_standard", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:cpu_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/diskio_data:diskio_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/ftrace_data/${device_kernel_version}:ftrace_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hidump_data:hidump_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:hilog_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:hisysevent_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/js_memory:js_memory_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/network_data:network_data_encoder", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/process_data:process_data_encoder", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/services:ts_all_type_cpp_standard", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:cpu_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/diskio_data:diskio_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/ftrace_data/${device_kernel_version}:ftrace_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hidump_data:hidump_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:hilog_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:hisysevent_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/js_memory:js_memory_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/network_data:network_data_reader", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/process_data:process_data_reader", ] } group("htrace_pbreader_parser") { diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_clock_detail_parser.cpp b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_clock_detail_parser.cpp index 102e7e8e7..029be3c25 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_clock_detail_parser.cpp +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_clock_detail_parser.cpp @@ -19,6 +19,8 @@ #include "process_filter.h" #include "stat_filter.h" #include "symbols_filter.h" +#include + namespace SysTuning { namespace TraceStreamer { HtraceClockDetailParser::HtraceClockDetailParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters) @@ -52,7 +54,7 @@ void HtraceClockDetailParser::Parse(const ProtoReader::BytesView& tracePacket) c TS_LOGI("clockid:%d, ts:%llu", id, static_cast(time.tv_nsec() + time.tv_sec() * SEC_TO_NS)); snapShot.push_back(SnapShot{static_cast(id), time.tv_nsec() + time.tv_sec() * SEC_TO_NS}); } - if (snapShot.size()) { + if (!snapShot.empty()) { streamFilters_->clockFilter_->AddClockSnapshot(snapShot); } streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLOCK_SYNC, STAT_EVENT_RECEIVED); @@ -72,37 +74,37 @@ void HtraceClockDetailParser::Parse(const ProfilerTraceFileHeader* profilerTrace std::vector snapShot; TS_LOGI("got clock snapshot"); - TS_LOGI("clockid: TS_CLOCK_BOOTTIME, ts:%llu", profilerTraceFileHeader->data.boottime); + TS_LOGI("clockid: TS_CLOCK_BOOTTIME, ts:%" PRIu64 "", profilerTraceFileHeader->data.boottime); if (profilerTraceFileHeader->data.boottime) { snapShot.push_back(SnapShot{TS_CLOCK_BOOTTIME, profilerTraceFileHeader->data.boottime}); } - TS_LOGI("clockid: TS_CLOCK_REALTIME, ts:%llu", profilerTraceFileHeader->data.realtime); + TS_LOGI("clockid: TS_CLOCK_REALTIME, ts:%" PRIu64 "", profilerTraceFileHeader->data.realtime); if (profilerTraceFileHeader->data.realtime) { snapShot.push_back(SnapShot{TS_CLOCK_REALTIME, profilerTraceFileHeader->data.realtime}); } - TS_LOGI("clockid: TS_CLOCK_REALTIME_COARSE, ts:%llu", profilerTraceFileHeader->data.realtimeCoarse); + TS_LOGI("clockid: TS_CLOCK_REALTIME_COARSE, ts:%" PRIu64 "", profilerTraceFileHeader->data.realtimeCoarse); if (profilerTraceFileHeader->data.realtimeCoarse) { snapShot.push_back(SnapShot{TS_CLOCK_REALTIME_COARSE, profilerTraceFileHeader->data.realtimeCoarse}); } - TS_LOGI("clockid: TS_MONOTONIC, ts:%llu", profilerTraceFileHeader->data.monotonic); + TS_LOGI("clockid: TS_MONOTONIC, ts:%" PRIu64 "", profilerTraceFileHeader->data.monotonic); if (profilerTraceFileHeader->data.monotonic) { snapShot.push_back(SnapShot{TS_MONOTONIC, profilerTraceFileHeader->data.monotonic}); } - TS_LOGI("clockid: TS_MONOTONIC_COARSE, ts:%llu", profilerTraceFileHeader->data.monotonicCoarse); + TS_LOGI("clockid: TS_MONOTONIC_COARSE, ts:%" PRIu64 "", profilerTraceFileHeader->data.monotonicCoarse); if (profilerTraceFileHeader->data.monotonicCoarse) { snapShot.push_back(SnapShot{TS_MONOTONIC_COARSE, profilerTraceFileHeader->data.monotonicCoarse}); } - TS_LOGI("clockid: TS_MONOTONIC_RAW, ts:%llu", profilerTraceFileHeader->data.monotonicRaw); + TS_LOGI("clockid: TS_MONOTONIC_RAW, ts:%" PRIu64 "", profilerTraceFileHeader->data.monotonicRaw); if (profilerTraceFileHeader->data.monotonicRaw) { snapShot.push_back(SnapShot{TS_MONOTONIC_RAW, profilerTraceFileHeader->data.monotonicRaw}); } - if (snapShot.size()) { + if (!snapShot.empty()) { streamFilters_->clockFilter_->AddClockSnapshot(snapShot); streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLOCK_SYNC, STAT_EVENT_RECEIVED); } diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.cpp b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.cpp index 491537236..8869ef6b7 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.cpp +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.cpp @@ -36,7 +36,6 @@ void HtraceCpuDataParser::Parse(ProtoReader::BytesView tracePacket, uint64_t ts) return; } if (cpuData.has_cpu_usage_info()) { - auto cpuInfo = cpuData.cpu_usage_info(); auto userLoad = cpuData.user_load(); auto sysLoad = cpuData.sys_load(); auto process_num = cpuData.process_num(); diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.h b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.h index abb3282cc..5954b8ebc 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.h +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_cpu_data_parser.h @@ -71,7 +71,6 @@ public: private: std::string threadStateDesc_[ProtoReader::THREAD_WAITING + 1] = {"undefined", "Running", "Sleep", "Sloped", "Watting"}; - uint64_t lastLineSeq_ = 0; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_event_parser/htrace_event_parser.cpp b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_event_parser/htrace_event_parser.cpp index 0b3afb071..b228be926 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_event_parser/htrace_event_parser.cpp +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_event_parser/htrace_event_parser.cpp @@ -164,7 +164,7 @@ void HtraceEventParser::ParseDataItem(HtraceDataSegment& tracePacket, BuiltinClo lastOverwrite_ = msg.overwrite(); } if (lastOverwrite_ != msg.overwrite()) { - TS_LOGW("lost events:%lu", msg.overwrite() - lastOverwrite_); + TS_LOGW("lost events:%llu", msg.overwrite() - lastOverwrite_); lastOverwrite_ = msg.overwrite(); } streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_LOST); @@ -176,8 +176,7 @@ void HtraceEventParser::ParseDataItem(HtraceDataSegment& tracePacket, BuiltinClo ProtoReader::BytesView event(i->ToBytes()); uint64_t timeStamp = 0; if (event.size_ > MIN_DATA_AREA && event.data_[0] == tsTag) { - const uint8_t* nextData = - ProtoReader::VarIntDecode(event.data_ + DATA_AREA_START, event.data_ + DATA_AREA_END, &timeStamp); + (void)ProtoReader::VarIntDecode(event.data_ + DATA_AREA_START, event.data_ + DATA_AREA_END, &timeStamp); } eventTimeStamp_ = timeStamp; ftraceOriginStartTime_ = std::min(ftraceOriginStartTime_, eventTimeStamp_); @@ -188,7 +187,7 @@ void HtraceEventParser::ParseDataItem(HtraceDataSegment& tracePacket, BuiltinClo traceDataCache_->UpdateTraceTime(eventTimeStamp_); ProtoReader::BytesView commonField; eventList_.push_back( - std::move(std::make_unique(eventTimeStamp_, eventCpu_, tracePacket.seg, i->ToBytes()))); + std::make_unique(eventTimeStamp_, eventCpu_, tracePacket.seg, i->ToBytes())); FilterAllEventsReader(); } } diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_cpu_profiler_parser.cpp b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_cpu_profiler_parser.cpp new file mode 100644 index 000000000..37fc4cc69 --- /dev/null +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_cpu_profiler_parser.cpp @@ -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. + */ +#include "htrace_js_cpu_profiler_parser.h" +#include +#include +#include + +namespace SysTuning { +namespace TraceStreamer { +const uint32_t TIME_SECOND_COVER = 1000; +namespace jsonns { + +struct CallFrame { + std::string functionName; + std::string scriptId; + std::string url; + int32_t lineNumber; + int32_t columnNumber; +}; +struct Node { + uint32_t id; + CallFrame callFrame; + uint32_t hitCount; + std::string children; +}; +void from_json(const json& j, CallFrame& callFrame) +{ + j.at("functionName").get_to(callFrame.functionName); + j.at("scriptId").get_to(callFrame.scriptId); + j.at("url").get_to(callFrame.url); + j.at("lineNumber").get_to(callFrame.lineNumber); + j.at("columnNumber").get_to(callFrame.columnNumber); + return; +} +std::map nodes_; +void from_json(const json& j, Node& node) +{ + j.at("id").get_to(node.id); + j.at("callFrame").get_to(node.callFrame); + j.at("hitCount").get_to(node.hitCount); + for (int32_t i = 0; i < j["children"].size(); i++) { + int child = j["children"][i]; + nodes_.emplace(child, node.id); + auto children = std::to_string(child); + node.children += children + ","; + } + return; +} +} // namespace jsonns + +HtraceJsCpuProfilerParser::HtraceJsCpuProfilerParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : EventParserBase(dataCache, ctx) +{ +} + +void HtraceJsCpuProfilerParser::ParseJsCpuProfiler(std::string result) +{ + json jMessage = json::parse(result); + int nodeCount = jMessage.at("nodes").size(); + for (int i = nodeCount - 1; i > 0; i--) { + jsonns::Node node = jMessage.at("nodes")[i]; + } + for (int i = 0; i < nodeCount; i++) { + jsonns::Node node = jMessage.at("nodes")[i]; + auto id = node.id; + auto functionName = node.callFrame.functionName; + DataIndex functionNameKey = traceDataCache_->GetDataIndex(functionName); + auto scriptId = node.callFrame.scriptId; + auto url = node.callFrame.url; + DataIndex urlKey = traceDataCache_->GetDataIndex(url); + auto lineNumber = node.callFrame.lineNumber; + auto columnNumber = node.callFrame.columnNumber; + auto hitCount = node.hitCount; + auto children = node.children; + children = children.substr(0, children.size() - 1); + uint32_t parentId = 0; + if (jsonns::nodes_.find(id) != jsonns::nodes_.end()) { + parentId = jsonns::nodes_.find(id)->second; + } + (void)traceDataCache_->GetJsCpuProfilerNodeData()->AppendNewData( + id, functionNameKey, scriptId, urlKey, lineNumber, columnNumber, hitCount, children, parentId); + } + uint64_t startTime = jMessage.at("startTime"); + uint64_t endTime = jMessage.at("endTime"); + uint32_t sample = std::numeric_limits::max(); + uint64_t sampleEndTime = startTime; + uint64_t dur = 0; + for (auto i = 0; i < jMessage.at("samples").size(); i++) { + if (sample != std::numeric_limits::max() && sample != jMessage.at("samples")[i]) { + dur = (sampleEndTime * TIME_SECOND_COVER) - (startTime * TIME_SECOND_COVER); + (void)traceDataCache_->GetJsCpuProfilerSampleData()->AppendNewData(sample, startTime * TIME_SECOND_COVER, + sampleEndTime * TIME_SECOND_COVER, dur); + sample = jMessage.at("samples")[i]; + startTime = sampleEndTime; + } else if (sample == std::numeric_limits::max()) { + sample = jMessage.at("samples")[0]; + } + uint32_t timeDeltas = jMessage.at("timeDeltas")[i]; + sampleEndTime += timeDeltas; + } + dur = (sampleEndTime * TIME_SECOND_COVER) - (startTime * TIME_SECOND_COVER); + (void)traceDataCache_->GetJsCpuProfilerSampleData()->AppendNewData(sample, startTime * TIME_SECOND_COVER, + sampleEndTime * TIME_SECOND_COVER, dur); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_cpu_profiler_parser.h b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_cpu_profiler_parser.h new file mode 100644 index 000000000..87976b8cb --- /dev/null +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_cpu_profiler_parser.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 HTRACE_JS_CPU_PERFILER_PARSER_H +#define HTRACE_JS_CPU_PERFILER_PARSER_H +#include +#include +#include +#include "common_types.h" +#include "event_parser_base.h" +#include "htrace_plugin_time_parser.h" +#include "json.hpp" +#include "trace_streamer_config.h" +#include "trace_streamer_filters.h" +using json = nlohmann::json; + +namespace SysTuning { +namespace TraceStreamer { +class HtraceJsCpuProfilerParser : public EventParserBase, public HtracePluginTimeParser { +public: + HtraceJsCpuProfilerParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~HtraceJsCpuProfilerParser(){}; + void ParseJsCpuProfiler(std::string result); +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_JS_CPU_PERFILER_PARSER_H diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_memory_parser.cpp b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_memory_parser.cpp index 9be2bb85d..3976221f1 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_memory_parser.cpp +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_memory_parser.cpp @@ -286,9 +286,11 @@ void from_json(const json& j, TraceTree& v) const int32_t END_POS = 3; const int32_t CHUNK_POS = 8; +const int32_t PROFILE_POS = 9; +const int32_t END_PROFILE_POS = 2; HtraceJSMemoryParser::HtraceJSMemoryParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) - : EventParserBase(dataCache, ctx) + : EventParserBase(dataCache, ctx), jsCpuProfilerParser_(std::make_unique(dataCache, ctx)) { DIR* dir = opendir("."); if (dir != nullptr) { @@ -312,8 +314,15 @@ HtraceJSMemoryParser::~HtraceJSMemoryParser() void HtraceJSMemoryParser::ParseJSMemoryConfig(ProtoReader::BytesView tracePacket) { ProtoReader::ArkTSConfig_Reader jsHeapConfig(tracePacket.data_, tracePacket.size_); + auto pid = jsHeapConfig.pid(); type_ = jsHeapConfig.type(); - pid_ = jsHeapConfig.pid(); + auto interval = jsHeapConfig.interval(); + auto captureNumericValue = jsHeapConfig.capture_numeric_value() ? 1 : 0; + auto trackAllocation = jsHeapConfig.track_allocations() ? 1 : 0; + auto cpuProfiler = jsHeapConfig.enable_cpu_profiler() ? 1 : 0; + auto cpuProfilerInterval = jsHeapConfig.cpu_profiler_interval(); + (void)traceDataCache_->GetJsConfigData()->AppendNewData(pid, type_, interval, captureNumericValue, trackAllocation, + cpuProfiler, cpuProfilerInterval); } void HtraceJSMemoryParser::Parse(ProtoReader::BytesView tracePacket, uint64_t ts) @@ -343,12 +352,16 @@ void HtraceJSMemoryParser::Parse(ProtoReader::BytesView tracePacket, uint64_t ts } ts = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, ts); UpdatePluginTimeRange(TS_CLOCK_REALTIME, ts, ts); - (void)traceDataCache_->GetJsHeapFilesData()->AppendNewData(fileId_, fileName, startTime_, ts, pid_, - selfSizeCount_); + (void)traceDataCache_->GetJsHeapFilesData()->AppendNewData(fileId_, fileName, startTime_, ts, selfSizeCount_); selfSizeCount_ = 0; fileId_++; isFirst_ = true; return; + } else if (cpuTimeFirst_ && result == jsCpuProfilerStart_) { + ts = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, ts); + UpdatePluginTimeRange(TS_CLOCK_REALTIME, ts, ts); + startTime_ = ts; + cpuTimeFirst_ = false; } auto pos = result.find("chunk"); if (pos != string::npos) { @@ -360,6 +373,30 @@ void HtraceJSMemoryParser::Parse(ProtoReader::BytesView tracePacket, uint64_t ts } auto resultJson = result.substr(pos + CHUNK_POS, result.size() - pos - CHUNK_POS - END_POS); jsMemoryString_ += resultJson; + } else { + auto jsCpuProfilerPos = result.find("profile"); + if (jsCpuProfilerPos != string::npos) { + auto jsCpuProfilerString = result.substr(jsCpuProfilerPos + PROFILE_POS, + result.size() - jsCpuProfilerPos - PROFILE_POS - END_PROFILE_POS); + std::regex strEscapeInvalid("\\\\n"); + std::regex strInvalid("\\\\\""); + auto strEscape = std::regex_replace(jsCpuProfilerString, strEscapeInvalid, ""); + auto str = std::regex_replace(strEscape, strInvalid, "\""); + ts = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, ts); + UpdatePluginTimeRange(TS_CLOCK_REALTIME, ts, ts); + if (enableFileSave_) { + auto fd = base::OpenFile(tmpJsCpuProfilerData_ + jsCpuProFiler, O_CREAT | O_RDWR, TS_PERMISSION_RW); + if (!fd) { + fprintf(stdout, "Failed to create file: %s", jsCpuProFiler.c_str()); + exit(-1); + } + (void)ftruncate(fd, 0); + (void)write(fd, str.data(), str.size()); + close(fd); + fd = 0; + } + jsCpuProfilerParser_->ParseJsCpuProfiler(str); + } } } diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_memory_parser.h b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_memory_parser.h index 72ed719f8..a3420300d 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_memory_parser.h +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_memory_parser.h @@ -19,6 +19,7 @@ #include #include "common_types.h" #include "event_parser_base.h" +#include "htrace_js_cpu_profiler_parser.h" #include "htrace_plugin_time_parser.h" #include "json.hpp" #include "trace_streamer_config.h" @@ -52,8 +53,10 @@ private: int32_t pid_ = 0; const std::string snapshotEnd_ = "{\"id\":1,\"result\":{}}"; const std::string timeLineEnd_ = "{\"id\":2,\"result\":{}}"; + const std::string jsCpuProfilerStart_ = "{\"id\":3,\"result\":{}}"; uint64_t startTime_ = std::numeric_limits::max(); bool isFirst_ = true; + bool cpuTimeFirst_ = true; std::string jsMemoryString_ = ""; int32_t fileId_ = 0; int32_t jsFileId_ = 0; @@ -63,6 +66,9 @@ private: const std::string tmpJsMemoryTimelineData_ = "ts_tmp.jsmemory_timeline.heapsnapshot"; const std::string tmpJsMemorySnapshotData_ = "ts_tmp.jsmemory_snapshot"; const std::string jsSnapshotFileTail = ".heapsnapshot"; + const std::string tmpJsCpuProfilerData_ = "Profile"; + const std::string jsCpuProFiler = ".cpuprofile"; + std::unique_ptr jsCpuProfilerParser_; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_network_parser.cpp b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_network_parser.cpp index 49597383f..79f804934 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_network_parser.cpp +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_network_parser.cpp @@ -44,7 +44,7 @@ void HtraceNetworkParser::Parse(ProtoReader::BytesView tracePacket, uint64_t ts) ts = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, ts); streamFilters_->statFilter_->IncreaseStat(TRACE_NETWORK, STAT_EVENT_RECEIVED); - networkData_.push_back(std::move(TsNetworkData{ts, tv_sec, tv_nsec, rx_bytes, rx_packets, tx_bytes, tx_packets})); + networkData_.push_back(TsNetworkData{ts, tv_sec, tv_nsec, rx_bytes, rx_packets, tx_bytes, tx_packets}); } void HtraceNetworkParser::Finish() { diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.cpp b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.cpp index 5e079c368..5b5031269 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.cpp +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.cpp @@ -46,9 +46,7 @@ HtraceParser::HtraceParser(TraceDataCache* dataCache, const TraceStreamerFilters processParser_(std::make_unique(dataCache, filters)), hisyseventParser_(std::make_unique(dataCache, filters)), jsMemoryParser_(std::make_unique(dataCache, filters)), -#if WITH_PERF perfDataParser_(std::make_unique(dataCache, filters)), -#endif #ifdef SUPPORTTHREAD supportThread_(true), dataSegArray_(std::make_unique(MAX_SEG_ARRAY_SIZE)) @@ -62,7 +60,6 @@ void HtraceParser::GetSymbols(std::unique_ptr elfPtr, std::shared_ptr symbols, const std::string& filename) { - symbols->filePathIndex = traceDataCache_->dataDict_.GetStringIndex(filename.c_str()); symbols->textVaddr = (std::numeric_limits::max)(); for (auto& item : elfPtr->phdrs_) { @@ -145,11 +142,9 @@ bool HtraceParser::ReparseSymbolFilesAndResymbolization(std::string& symbolsPath std::vector& symbolsPaths) { auto parsePerfStatus = false; -#if WITH_PERF std::vector dir; dir.emplace_back(symbolsPath); parsePerfStatus = perfDataParser_->PerfReloadSymbolFiles(dir); -#endif auto parseFileSOStatus = ParserFileSO(symbolsPath, symbolsPaths); if (!parseFileSOStatus) { elfSymbolTables_.reset(); @@ -184,9 +179,7 @@ void HtraceParser::WaitForParserEnd() jsMemoryParser_->Finish(); // keep final upate perf and ebpf data time range ebpfDataParser_->Finish(); -#if WITH_PERF perfDataParser_->Finish(); -#endif htraceNativeHookParser_->Finish(); htraceMemParser_->Finish(); traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_TRACE, @@ -391,7 +384,7 @@ void HtraceParser::ParserData(HtraceDataSegment& dataSeg) return; } if (!supportThread_) { // do it only in wasm mode, wasm noThead_ will be true - if (dataSeg.status == STAT_EVENT_DATA_INVALID) { + if (dataSeg.status == TS_PARSE_STATUS_INVALID) { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID); return; } @@ -586,7 +579,6 @@ bool HtraceParser::ParseDataRecursively(std::deque::iterator& packagesB } if (profilerTraceFileHeader_.data.dataType == ProfilerTraceFileHeader::HIPERF_DATA) { if (packagesBuffer_.size() >= profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH) { -#if WITH_PERF auto size = profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH; perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, size); currentLength -= size; @@ -594,7 +586,6 @@ bool HtraceParser::ParseDataRecursively(std::deque::iterator& packagesB profilerTraceFileHeader_.data.dataType = ProfilerTraceFileHeader::UNKNOW_TYPE; hasGotHeader_ = false; return true; -#endif } return false; } @@ -644,7 +635,7 @@ bool HtraceParser::ParseDataRecursively(std::deque::iterator& packagesB packagesBegin += nextLength_; currentLength -= nextLength_; if (nextLength_ > htraceCurentLength_) { - TS_LOGE("fatal error, data length not match nextLength_:%u, htraceCurentLength_:%llu", nextLength_, + TS_LOGE("fatal error, data length not match nextLength_:%u, htraceCurentLength_:%" PRIu64 "", nextLength_, htraceCurentLength_); } htraceCurentLength_ -= nextLength_; @@ -694,7 +685,7 @@ bool HtraceParser::InitProfilerTraceFileHeader() } auto ret = memcpy_s(&profilerTraceFileHeader_, sizeof(profilerTraceFileHeader_), buffer, PACKET_HEADER_LENGTH); if (ret == -1 || profilerTraceFileHeader_.data.magic != ProfilerTraceFileHeader::HEADER_MAGIC) { - TS_LOGE("Get profiler trace file header failed! ret = %d, magic = %lx", ret, + TS_LOGE("Get profiler trace file header failed! ret = %d, magic = %llx", ret, profilerTraceFileHeader_.data.magic); return false; } @@ -702,9 +693,9 @@ bool HtraceParser::InitProfilerTraceFileHeader() TS_LOGE("Profiler Trace data is truncated!!!"); return false; } - TS_LOGI("magic = %lx, length = %llx, dataType = %llx, boottime = %llx", profilerTraceFileHeader_.data.magic, - profilerTraceFileHeader_.data.length, profilerTraceFileHeader_.data.dataType, - profilerTraceFileHeader_.data.boottime); + TS_LOGI("magic = %llx, length = %" PRIu64 ", dataType = %x, boottime = %" PRIu64 "", + profilerTraceFileHeader_.data.magic, profilerTraceFileHeader_.data.length, + profilerTraceFileHeader_.data.dataType, profilerTraceFileHeader_.data.boottime); #if IS_WASM const int32_t DATA_TYPE_CLOCK = 100; TraceStreamer_Plugin_Out_SendData(reinterpret_cast(&profilerTraceFileHeader_), diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.h b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.h index 44d4a0319..cc7041821 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.h +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_parser.h @@ -42,9 +42,7 @@ #include "htrace_symbols_detail_parser.h" #include "log.h" #include "parser_base.h" -#if WITH_PERF #include "perf_data_parser.h" -#endif #include "proto_reader_help.h" #include "string_help.h" #include "trace_data/trace_data_cache.h" @@ -55,9 +53,7 @@ namespace SysTuning { namespace TraceStreamer { using namespace SysTuning::base; using namespace OHOS::Developtools::HiPerf::ELF; -#if WITH_PERF using namespace OHOS::Developtools::HiPerf; -#endif class HtraceParser : public ParserBase { public: HtraceParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters); @@ -119,9 +115,7 @@ private: std::unique_ptr processParser_; std::unique_ptr hisyseventParser_; std::unique_ptr jsMemoryParser_; -#if WITH_PERF std::unique_ptr perfDataParser_; -#endif std::unique_ptr ebpfDataParser_; std::atomic filterThreadStarted_{false}; const int32_t MAX_SEG_ARRAY_SIZE = 10000; @@ -131,7 +125,6 @@ private: bool exited_ = false; int32_t filterHead_ = 0; int32_t parseHead_ = 0; - size_t sizeAll_ = 0; size_t htraceLength_ = 1024; const int32_t sleepDur_ = 100; bool parseThreadStarted_ = false; diff --git a/trace_streamer/src/parser/print_event_parser.cpp b/trace_streamer/src/parser/print_event_parser.cpp index e06f885e3..85ce980df 100644 --- a/trace_streamer/src/parser/print_event_parser.cpp +++ b/trace_streamer/src/parser/print_event_parser.cpp @@ -18,6 +18,7 @@ #include "frame_filter.h" #include "stat_filter.h" #include "string_to_numerical.h" +#include namespace SysTuning { namespace TraceStreamer { PrintEventParser::PrintEventParser(TraceDataCache* dataCache, const TraceStreamerFilters* filter) @@ -346,10 +347,10 @@ void PrintEventParser::HandleFrameSliceEndEvent(uint64_t ts, uint64_t pid, uint6 auto iTid = streamFilters_->processFilter_->GetInternalTid(tid); auto pos = std::find(vsyncSliceIds_.begin(), vsyncSliceIds_.end(), callStackRow); if (pos != vsyncSliceIds_.end()) { - TS_LOGD("ts:%llu, RenderSliceEnd:%llu, callStackRow:%zu", ts, tid, callStackRow); + TS_LOGD("ts:%" PRIu64 ", RenderSliceEnd:%" PRIu64 ", callStackRow:%zu", ts, tid, callStackRow); if (!streamFilters_->frameFilter_->EndVsyncEvent(ts, iTid)) { streamFilters_->statFilter_->IncreaseStat(TRACE_VSYNC, STAT_EVENT_NOTMATCH); - TS_LOGW("ts:%llu, RenderSliceEnd:%llu, callStackRow:%zu failed", ts, tid, callStackRow); + TS_LOGW("ts:%" PRIu64 ", RenderSliceEnd:%" PRIu64 ", callStackRow:%zu failed", ts, tid, callStackRow); } vsyncSliceIds_.erase(pos); } @@ -362,10 +363,10 @@ void PrintEventParser::HandleFrameQueueEndEvent(uint64_t ts, uint64_t pid, uint6 auto iTid = streamFilters_->processFilter_->GetInternalTid(tid); auto pos = std::find(frameCallIds_.begin(), frameCallIds_.end(), callStackRow); if (pos != frameCallIds_.end()) { - TS_LOGD("ts:%llu, frameSliceEnd:%u", ts, tid); + TS_LOGD("ts:%" PRIu64 ", frameSliceEnd:%" PRIu64 "", ts, tid); if (!streamFilters_->frameFilter_->EndFrameQueue(ts, iTid)) { streamFilters_->statFilter_->IncreaseStat(TRACE_FRAMEQUEUE, STAT_EVENT_NOTMATCH); - TS_LOGW("ts:%llu, frameSliceEnd:%lu failed", ts, tid); + TS_LOGW("ts:%" PRIu64 ", frameSliceEnd:%" PRIu64 " failed", ts, tid); } frameCallIds_.erase(pos); } diff --git a/trace_streamer/src/proto_reader/BUILD.gn b/trace_streamer/src/proto_reader/BUILD.gn index d97d7de56..6306c9472 100755 --- a/trace_streamer/src/proto_reader/BUILD.gn +++ b/trace_streamer/src/proto_reader/BUILD.gn @@ -14,12 +14,11 @@ import("//build/ohos.gni") import("../../build/ts.gni") ohos_source_set("proto_reader") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" public_configs = [ "../../gn:default_config" ] public_deps = [] include_dirs = [ "include" ] - deps = [ "../../gn:default_deps" ] sources = [ "proto_reader.cpp" ] include_dirs += [ "../include", diff --git a/trace_streamer/src/proto_reader/include/data_area.h b/trace_streamer/src/proto_reader/include/data_area.h index 1a3ac3fec..f5b8a1913 100644 --- a/trace_streamer/src/proto_reader/include/data_area.h +++ b/trace_streamer/src/proto_reader/include/data_area.h @@ -83,14 +83,14 @@ public: { float res; uint32_t value32 = static_cast(intValue_); - (void*)memcpy_s(&res, sizeof(res), &value32, sizeof(value32)); + (void)memcpy_s(&res, sizeof(res), &value32, sizeof(value32)); return res; } double ToDouble() const { double res; - (void*)memcpy_s(&res, sizeof(res), &intValue_, sizeof(intValue_)); + (void)memcpy_s(&res, sizeof(res), &intValue_, sizeof(intValue_)); return res; } diff --git a/trace_streamer/src/proto_reader/proto_reader.cpp b/trace_streamer/src/proto_reader/proto_reader.cpp index 7c0db3284..53c993b64 100644 --- a/trace_streamer/src/proto_reader/proto_reader.cpp +++ b/trace_streamer/src/proto_reader/proto_reader.cpp @@ -109,7 +109,7 @@ bool ProtoReaderBase::ParseFixed64Value(ParseDataAreaResult& result, return false; } - (void*)memcpy_s(&intValue, sizeof(uint64_t), startAddr, sizeof(uint64_t)); + (void)memcpy_s(&intValue, sizeof(uint64_t), startAddr, sizeof(uint64_t)); result.dataArea.SetDataAreaIntValue(intValue); result.next = cursor; result.status = OK; @@ -125,7 +125,7 @@ bool ProtoReaderBase::ParseFixed32Value(ParseDataAreaResult& result, if (cursor > endAddr) { return false; } - (void*)memcpy_s(&intValue, sizeof(uint64_t), startAddr, sizeof(uint32_t)); + (void)memcpy_s(&intValue, sizeof(uint64_t), startAddr, sizeof(uint32_t)); result.dataArea.SetDataAreaIntValue(intValue); result.next = cursor; result.status = OK; @@ -227,7 +227,7 @@ void ProtoReaderBase::MoveToLargerHeapStorage() { uint32_t largerVolume = volume_ << 1; std::unique_ptr largerVolumeStorage(new DataArea[largerVolume]); - (void*)memcpy_s(&largerVolumeStorage[0], sizeof(DataArea) * largerVolume, dataAreas_, sizeof(DataArea) * size_); + (void)memcpy_s(&largerVolumeStorage[0], sizeof(DataArea) * largerVolume, dataAreas_, sizeof(DataArea) * size_); lagerHeapStorage_ = std::move(largerVolumeStorage); dataAreas_ = &lagerHeapStorage_[0]; volume_ = largerVolume; diff --git a/trace_streamer/src/proto_reader/protoc_plugin/BUILD.gn b/trace_streamer/src/proto_reader/protoc_plugin/BUILD.gn index 051400fd6..b88c8db0a 100755 --- a/trace_streamer/src/proto_reader/protoc_plugin/BUILD.gn +++ b/trace_streamer/src/proto_reader/protoc_plugin/BUILD.gn @@ -13,12 +13,13 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_executable("protoreader_plugin") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "proto_reader_plugin.cpp" ] deps = [ "${SRC}/base:string_help", - "${THIRD_PARTY}/protobuf:protoc_lib", + "${THIRD_PARTY}/protobuf:protobuf(${host_toolchain})", + "${THIRD_PARTY}/protobuf:protoc_lib(${host_toolchain})", ] include_dirs = [ "${SRC}/base", diff --git a/trace_streamer/src/proto_reader/protoc_plugin/proto_reader_plugin.cpp b/trace_streamer/src/proto_reader/protoc_plugin/proto_reader_plugin.cpp index d95bf7a43..63dfbdea1 100644 --- a/trace_streamer/src/proto_reader/protoc_plugin/proto_reader_plugin.cpp +++ b/trace_streamer/src/proto_reader/protoc_plugin/proto_reader_plugin.cpp @@ -18,7 +18,6 @@ namespace SysTuning { namespace ProtoReader { const std::string SYS_NAMESPACE = "SysTuning"; -const int32_t MAX_DECODER_FIELDID = 999; const int32_t MIN_OPTIONS_SIZE = 2; bool ProtoReaderPlugin::Generate(const FileDescriptor* file, diff --git a/trace_streamer/src/protos/protogen.sh b/trace_streamer/src/protos/protogen.sh index 2990fdc00..c00275eac 100755 --- a/trace_streamer/src/protos/protogen.sh +++ b/trace_streamer/src/protos/protogen.sh @@ -15,16 +15,10 @@ set -e protoc='protoc' proto_dir='.' protoreader_plugin='protoreader_plugin' -# case "$OSTYPE" in -# msys*) out='../../out/windows' protoreader_plugin='protoreader_plugin.exe' protoc='protoc.exe' proto_dir=$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ;; -# darwin*) out='../../out/macx' proto_dir=$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ;; -# linux*) out='../../out/linux' proto_dir=$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ;; -# *) echo "other: $OSTYPE" ;; -# esac case "$OSTYPE" in - msys*) out='../out/windows' protoreader_plugin='protoreader_plugin.exe' protoc='protoc.exe' proto_dir=$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ;; - darwin*) out='../out/macx' proto_dir=$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ;; - linux*) out='../out/linux' proto_dir=$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ;; + msys*) out='../../out/windows' protoreader_plugin='protoreader_plugin.exe' protoc='protoc.exe' proto_dir=$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ;; + darwin*) out='../../out/macx' proto_dir=$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ;; + linux*) out='../../out/linux' proto_dir=$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ;; *) echo "other: $OSTYPE" ;; esac echo $proto_dir diff --git a/trace_streamer/src/protos/protos.gni b/trace_streamer/src/protos/protos.gni index b4c7ee794..142b06ffc 100755 --- a/trace_streamer/src/protos/protos.gni +++ b/trace_streamer/src/protos/protos.gni @@ -11,7 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("../../build/config.gni") +import("../../build/ts.gni") subsys_name = OHOS_PROFILER_SUBSYS_NAME part_name = OHOS_PROFILER_PART_NAME diff --git a/trace_streamer/src/protos/services/BUILD.gn b/trace_streamer/src/protos/services/BUILD.gn index a377364b5..35875921a 100755 --- a/trace_streamer/src/protos/services/BUILD.gn +++ b/trace_streamer/src/protos/services/BUILD.gn @@ -44,7 +44,7 @@ all_type_codegen_all += all_type_codegen all_type_codegen_all += all_type_codegen_standard all_type_codegen_all += all_type_codegen_reader -action("all_type_gen") { +action("ts_all_type_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = all_type_proto outputs = all_type_codegen_all @@ -60,14 +60,14 @@ action("all_type_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", ] } } -ohos_source_set("all_type_cpp_standard") { - deps = [ ":all_type_gen" ] +ohos_source_set("ts_all_type_cpp_standard") { + deps = [ ":ts_all_type_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", diff --git a/trace_streamer/src/protos/types/plugins/agent_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/agent_data/BUILD.gn index 855f2e164..bcdc5d195 100755 --- a/trace_streamer/src/protos/types/plugins/agent_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/agent_data/BUILD.gn @@ -49,7 +49,7 @@ config("agent_include_config") { } ####################################################### -action("agent_data_cpp_gen") { +action("ts_agent_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = agent_sources outputs = agent_data_codegen_all @@ -65,14 +65,16 @@ action("agent_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", ] } } -ohos_source_set("agent_data_cpp") { - deps = [ ":agent_data_cpp_gen" ] +ohos_source_set("ts_agent_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_agent_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", diff --git a/trace_streamer/src/protos/types/plugins/bytrace_plugin/BUILD.gn b/trace_streamer/src/protos/types/plugins/bytrace_plugin/BUILD.gn index d40d7c647..ba8a69169 100755 --- a/trace_streamer/src/protos/types/plugins/bytrace_plugin/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/bytrace_plugin/BUILD.gn @@ -38,7 +38,7 @@ foreach(proto, bytrace_plugin_protos_defines) { bytrace_plugin_protos_codegen_all += bytrace_plugin_protos_codegen bytrace_plugin_protos_codegen_all += bytrace_plugin_protos_codegen_standard -action("bytrace_plugin_protos_protoc") { +action("ts_bytrace_plugin_protos_protoc") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = bytrace_plugin_protos_defines outputs = bytrace_plugin_protos_codegen_all @@ -58,8 +58,10 @@ config("bytrace_plugin_protos_config") { include_dirs = [ "$proto_out_dir" ] } -ohos_source_set("bytrace_plugin_protos_cpp") { - deps = [ ":bytrace_plugin_protos_protoc" ] +ohos_source_set("ts_bytrace_plugin_protos_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_bytrace_plugin_protos_protoc" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -67,12 +69,12 @@ ohos_source_set("bytrace_plugin_protos_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":bytrace_plugin_protos_config" ] sources = bytrace_plugin_protos_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } -ohos_source_set("bytrace_plugin_protos_cpp_standard") { - deps = [ ":bytrace_plugin_protos_protoc" ] +ohos_source_set("ts_bytrace_plugin_protos_cpp_standard") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_bytrace_plugin_protos_protoc" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", diff --git a/trace_streamer/src/protos/types/plugins/cpu_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/cpu_data/BUILD.gn index 14cab6be2..b25017e4c 100755 --- a/trace_streamer/src/protos/types/plugins/cpu_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/cpu_data/BUILD.gn @@ -42,7 +42,7 @@ config("cpu_include_config") { } ####################################################### -action("cpu_data_cpp_gen") { +action("ts_cpu_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = cpu_data_sources outputs = cpu_data_codegen_all @@ -58,14 +58,16 @@ action("cpu_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", ] } } -ohos_source_set("cpu_data_cpp") { - deps = [ ":cpu_data_cpp_gen" ] +ohos_source_set("ts_cpu_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_cpu_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -73,15 +75,13 @@ ohos_source_set("cpu_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":cpu_include_config" ] sources = cpu_data_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } -ohos_source_set("cpu_data_encoder") { - deps = [ ":cpu_data_cpp_gen" ] +ohos_source_set("cpu_data_reader") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_cpu_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":cpu_include_config" ] sources = cpu_data_codegen_reader - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/diskio_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/diskio_data/BUILD.gn index f2941ec73..3e10a2ded 100755 --- a/trace_streamer/src/protos/types/plugins/diskio_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/diskio_data/BUILD.gn @@ -42,7 +42,7 @@ config("diskio_include_config") { } ####################################################### -action("diskio_data_cpp_gen") { +action("ts_diskio_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = diskio_data_sources outputs = diskio_data_codegen_all @@ -58,14 +58,16 @@ action("diskio_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", ] } } -ohos_source_set("diskio_data_cpp") { - deps = [ ":diskio_data_cpp_gen" ] +ohos_source_set("ts_diskio_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_diskio_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -73,15 +75,13 @@ ohos_source_set("diskio_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":diskio_include_config" ] sources = diskio_data_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } -ohos_source_set("diskio_data_encoder") { - deps = [ ":diskio_data_cpp_gen" ] +ohos_source_set("diskio_data_reader") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_diskio_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":diskio_include_config" ] sources = diskio_data_codegen_reader - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/ftrace_data/default/BUILD.gn b/trace_streamer/src/protos/types/plugins/ftrace_data/default/BUILD.gn index b22b0394a..8979ba664 100755 --- a/trace_streamer/src/protos/types/plugins/ftrace_data/default/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/ftrace_data/default/BUILD.gn @@ -40,7 +40,7 @@ foreach(proto, ftrace_data_proto) { all_proto_codegen = ftrace_data_codegen all_proto_codegen += ftrace_data_codegen_reader -action("all_proto_gen") { +action("ts_all_proto_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = all_proto outputs = all_proto_codegen @@ -56,8 +56,8 @@ action("all_proto_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", ] } } @@ -66,8 +66,10 @@ config("public_configs") { include_dirs = [ "$proto_out_dir" ] } -ohos_source_set("ftrace_data_cpp") { - deps = [ ":all_proto_gen" ] +ohos_source_set("ts_ftrace_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_all_proto_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -77,8 +79,10 @@ ohos_source_set("ftrace_data_cpp") { sources = ftrace_data_codegen } -ohos_source_set("ftrace_data_encoder") { - deps = [ ":all_proto_gen" ] +ohos_source_set("ftrace_data_reader") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_all_proto_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":public_configs" ] sources = ftrace_data_codegen_reader diff --git a/trace_streamer/src/protos/types/plugins/hidump_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/hidump_data/BUILD.gn index 7eea96a9b..36bb4f6c6 100755 --- a/trace_streamer/src/protos/types/plugins/hidump_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/hidump_data/BUILD.gn @@ -42,7 +42,7 @@ config("hidump_include_config") { } ####################################################### -action("hidump_data_cpp_gen") { +action("ts_hidump_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = hidump_data_sources outputs = hidump_data_codegen_all @@ -58,14 +58,16 @@ action("hidump_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", ] } } -ohos_source_set("hidump_data_cpp") { - deps = [ ":hidump_data_cpp_gen" ] +ohos_source_set("ts_hidump_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_hidump_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -73,15 +75,13 @@ ohos_source_set("hidump_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hidump_include_config" ] sources = hidump_data_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } -ohos_source_set("hidump_data_encoder") { - deps = [ ":hidump_data_cpp_gen" ] +ohos_source_set("hidump_data_reader") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_hidump_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hidump_include_config" ] sources = hidump_data_codegen_reader - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/hiebpf_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/hiebpf_data/BUILD.gn index 7dcc52c5c..d6e71f41e 100755 --- a/trace_streamer/src/protos/types/plugins/hiebpf_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/hiebpf_data/BUILD.gn @@ -61,6 +61,8 @@ action("hiebpf_data_cpp_gen") { } ohos_source_set("hiebpf_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":hiebpf_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", @@ -69,11 +71,11 @@ ohos_source_set("hiebpf_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hiebpf_include_config" ] sources = hiebpf_data_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } ohos_source_set("hiebpf_data_cpp_standard") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":hiebpf_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", @@ -82,6 +84,4 @@ ohos_source_set("hiebpf_data_cpp_standard") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hiebpf_include_config" ] sources = hiebpf_data_codegen_standard - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/hilog_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/hilog_data/BUILD.gn index 2ec5dab79..7b6f2a8df 100755 --- a/trace_streamer/src/protos/types/plugins/hilog_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/hilog_data/BUILD.gn @@ -42,7 +42,7 @@ config("hilog_include_config") { } ####################################################### -action("hilog_data_cpp_gen") { +action("ts_hilog_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = hilog_data_sources outputs = hilog_data_codegen_all @@ -58,14 +58,16 @@ action("hilog_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", ] } } -ohos_source_set("hilog_data_cpp") { - deps = [ ":hilog_data_cpp_gen" ] +ohos_source_set("ts_hilog_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_hilog_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -73,15 +75,13 @@ ohos_source_set("hilog_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hilog_include_config" ] sources = hilog_data_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } -ohos_source_set("hilog_data_encoder") { - deps = [ ":hilog_data_cpp_gen" ] +ohos_source_set("hilog_data_reader") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_hilog_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hilog_include_config" ] sources = hilog_data_codegen_reader - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/BUILD.gn b/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/BUILD.gn index 7ddfa159e..d597fe409 100755 --- a/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/BUILD.gn @@ -31,7 +31,7 @@ foreach(proto, hiperf_call_plugin_protos_defines) { ] } -action("hiperf_call_plugin_protos_protoc") { +action("ts_hiperf_call_plugin_protos_protoc") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = hiperf_call_plugin_protos_defines outputs = hiperf_call_plugin_protos_codegen @@ -50,8 +50,10 @@ config("hiperf_call_plugin_protos_config") { include_dirs = [ "$proto_out_dir" ] } -source_set("hiperf_call_plugin_protos_cpp") { - deps = [ ":hiperf_call_plugin_protos_protoc" ] +source_set("ts_hiperf_call_plugin_protos_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_hiperf_call_plugin_protos_protoc" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -59,6 +61,4 @@ source_set("hiperf_call_plugin_protos_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hiperf_call_plugin_protos_config" ] sources = hiperf_call_plugin_protos_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/hiperf_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/hiperf_data/BUILD.gn index eacc01021..175cd2dba 100755 --- a/trace_streamer/src/protos/types/plugins/hiperf_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/hiperf_data/BUILD.gn @@ -38,7 +38,7 @@ foreach(proto, hiperf_data_protos_defines) { hiperf_data_protos_codegen_all += hiperf_data_protos_codegen hiperf_data_protos_codegen_all += hiperf_data_protos_codegen_standard -action("hiperf_data_protos_protoc") { +action("ts_hiperf_data_protos_protoc") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = hiperf_data_protos_defines outputs = hiperf_data_protos_codegen_all @@ -58,8 +58,10 @@ config("hiperf_data_protos_config") { include_dirs = [ "$proto_out_dir" ] } -ohos_source_set("hiperf_data_cpp") { - deps = [ ":hiperf_data_protos_protoc" ] +ohos_source_set("ts_hiperf_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_hiperf_data_protos_protoc" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -67,12 +69,12 @@ ohos_source_set("hiperf_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hiperf_data_protos_config" ] sources = hiperf_data_protos_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } -ohos_source_set("hiperf_data_cpp_standard") { - deps = [ ":hiperf_data_protos_protoc" ] +ohos_source_set("ts_hiperf_data_cpp_standard") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_hiperf_data_protos_protoc" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -80,6 +82,4 @@ ohos_source_set("hiperf_data_cpp_standard") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hiperf_data_protos_config" ] sources = hiperf_data_protos_codegen_standard - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/hisysevent_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/hisysevent_data/BUILD.gn index 679d3aeef..933ef5c5e 100644 --- a/trace_streamer/src/protos/types/plugins/hisysevent_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/hisysevent_data/BUILD.gn @@ -44,7 +44,7 @@ config("hisysevent_include_config") { } ####################################################### -action("hisysevent_data_cpp_gen") { +action("ts_hisysevent_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = hisysevent_data_sources outputs = hisysevent_data_codegen_all @@ -60,14 +60,16 @@ action("hisysevent_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", ] } } -ohos_source_set("hisysevent_data_cpp") { - deps = [ ":hisysevent_data_cpp_gen" ] +ohos_source_set("ts_hisysevent_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_hisysevent_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -75,15 +77,13 @@ ohos_source_set("hisysevent_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hisysevent_include_config" ] sources = hisysevent_data_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } -ohos_source_set("hisysevent_data_encoder") { - deps = [ ":hisysevent_data_cpp_gen" ] +ohos_source_set("hisysevent_data_reader") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_hisysevent_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":hisysevent_include_config" ] sources = hisysevent_data_codegen_reader - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/js_memory/BUILD.gn b/trace_streamer/src/protos/types/plugins/js_memory/BUILD.gn index c55f7b468..959ac455f 100755 --- a/trace_streamer/src/protos/types/plugins/js_memory/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/js_memory/BUILD.gn @@ -42,7 +42,7 @@ config("js_memory_include_config") { } ####################################################### -action("js_memory_data_cpp_gen") { +action("ts_js_memory_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = js_memory_data_sources outputs = js_memory_data_codegen_all @@ -58,14 +58,16 @@ action("js_memory_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", ] } } -ohos_source_set("js_memory_data_cpp") { - deps = [ ":js_memory_data_cpp_gen" ] +ohos_source_set("ts_js_memory_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_js_memory_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -73,15 +75,13 @@ ohos_source_set("js_memory_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":js_memory_include_config" ] sources = js_memory_data_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } -ohos_source_set("js_memory_data_encoder") { - deps = [ ":js_memory_data_cpp_gen" ] +ohos_source_set("js_memory_data_reader") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_js_memory_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":js_memory_include_config" ] sources = js_memory_data_codegen_reader - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/js_memory/js_heap_config.proto b/trace_streamer/src/protos/types/plugins/js_memory/js_heap_config.proto index 1124d5023..71ebdba1a 100755 --- a/trace_streamer/src/protos/types/plugins/js_memory/js_heap_config.proto +++ b/trace_streamer/src/protos/types/plugins/js_memory/js_heap_config.proto @@ -19,10 +19,13 @@ message ArkTSConfig { enum HeapType { SNAPSHOT = 0; TIMELINE = 1; + INVALID = -1; } int32 pid = 1; HeapType type = 2; uint32 interval = 3; bool capture_numeric_value = 4; bool track_allocations = 5; -} \ No newline at end of file + bool enable_cpu_profiler = 6; + uint32 cpu_profiler_interval = 7; +} diff --git a/trace_streamer/src/protos/types/plugins/memory_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/memory_data/BUILD.gn index 64b042c45..df62e2add 100755 --- a/trace_streamer/src/protos/types/plugins/memory_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/memory_data/BUILD.gn @@ -44,7 +44,7 @@ config("memory_include_config") { } ####################################################### -action("memory_data_cpp_gen") { +action("ts_memory_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = memory_data_sources outputs = memory_data_codegen_all @@ -60,14 +60,16 @@ action("memory_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", ] } } -ohos_source_set("memory_data_cpp") { - deps = [ ":memory_data_cpp_gen" ] +ohos_source_set("ts_memory_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_memory_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -75,15 +77,13 @@ ohos_source_set("memory_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":memory_include_config" ] sources = memory_data_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } -ohos_source_set("memory_data_encoder") { - deps = [ ":memory_data_cpp_gen" ] +ohos_source_set("memory_data_reader") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_memory_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":memory_include_config" ] sources = memory_data_codegen_reader - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/native_hook/BUILD.gn b/trace_streamer/src/protos/types/plugins/native_hook/BUILD.gn index be9f73882..4007a7b1d 100755 --- a/trace_streamer/src/protos/types/plugins/native_hook/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/native_hook/BUILD.gn @@ -42,7 +42,7 @@ config("native_hook_include_config") { } ####################################################### -action("native_hook_cpp_gen") { +action("ts_native_hook_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = native_hook_sources outputs = native_hook_codegen_all @@ -58,14 +58,16 @@ action("native_hook_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", ] } } -ohos_source_set("native_hook_cpp") { - deps = [ ":native_hook_cpp_gen" ] +ohos_source_set("ts_native_hook_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_native_hook_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -73,11 +75,11 @@ ohos_source_set("native_hook_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":native_hook_include_config" ] sources = native_hook_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } -ohos_source_set("native_hook_data_encoder") { - deps = [ ":native_hook_cpp_gen" ] +ohos_source_set("native_hook_data_reader") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_native_hook_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -85,6 +87,4 @@ ohos_source_set("native_hook_data_encoder") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":native_hook_include_config" ] sources = native_hook_codegen_reader - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/network_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/network_data/BUILD.gn index 08f5f5e2b..5cff948a7 100755 --- a/trace_streamer/src/protos/types/plugins/network_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/network_data/BUILD.gn @@ -42,7 +42,7 @@ config("network_include_config") { } ####################################################### -action("network_data_cpp_gen") { +action("ts_network_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = network_data_sources outputs = network_data_codegen_all @@ -58,14 +58,16 @@ action("network_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", ] } } -ohos_source_set("network_data_cpp") { - deps = [ ":network_data_cpp_gen" ] +ohos_source_set("ts_network_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_network_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -73,15 +75,13 @@ ohos_source_set("network_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":network_include_config" ] sources = network_data_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } -ohos_source_set("network_data_encoder") { - deps = [ ":network_data_cpp_gen" ] +ohos_source_set("network_data_reader") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_network_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":network_include_config" ] sources = network_data_codegen_reader - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/process_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/process_data/BUILD.gn index 12ec2bf95..4a6c27aed 100755 --- a/trace_streamer/src/protos/types/plugins/process_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/process_data/BUILD.gn @@ -42,7 +42,7 @@ config("process_include_config") { } ####################################################### -action("process_data_cpp_gen") { +action("ts_process_data_cpp_gen") { script = "${OHOS_TRACE_STREAMER_DIR_PROTOC}" sources = process_data_sources outputs = process_data_codegen_all @@ -58,14 +58,16 @@ action("process_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", ] } } -ohos_source_set("process_data_cpp") { - deps = [ ":process_data_cpp_gen" ] +ohos_source_set("ts_process_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_process_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", @@ -73,15 +75,13 @@ ohos_source_set("process_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":process_include_config" ] sources = process_data_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } -ohos_source_set("process_data_encoder") { - deps = [ ":process_data_cpp_gen" ] +ohos_source_set("process_data_reader") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + deps = [ ":ts_process_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":process_include_config" ] sources = process_data_codegen_reader - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/sample_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/sample_data/BUILD.gn index 39bb0e7ad..21a6aa648 100755 --- a/trace_streamer/src/protos/types/plugins/sample_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/sample_data/BUILD.gn @@ -66,6 +66,8 @@ action("sample_data_cpp_gen") { } ohos_source_set("sample_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":sample_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", @@ -74,15 +76,13 @@ ohos_source_set("sample_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":sample_include_config" ] sources = sample_data_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } ohos_source_set("sample_data_encoder") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":sample_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":sample_include_config" ] sources = sample_data_codegen_reader - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/stream_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/stream_data/BUILD.gn index b5ca47f39..f385b92e7 100755 --- a/trace_streamer/src/protos/types/plugins/stream_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/stream_data/BUILD.gn @@ -66,6 +66,8 @@ action("stream_data_cpp_gen") { } ohos_source_set("stream_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":stream_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", @@ -74,15 +76,13 @@ ohos_source_set("stream_data_cpp") { include_dirs = [ "$proto_out_dir" ] public_configs = [ ":stream_include_config" ] sources = stream_data_codegen - subsystem_name = "developtools" - part_name = "smartperf_host" } ohos_source_set("stream_data_encoder") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":stream_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":stream_include_config" ] sources = stream_data_codegen_reader - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/protos/types/plugins/test_data/BUILD.gn b/trace_streamer/src/protos/types/plugins/test_data/BUILD.gn index 64c82e949..dcd505f97 100644 --- a/trace_streamer/src/protos/types/plugins/test_data/BUILD.gn +++ b/trace_streamer/src/protos/types/plugins/test_data/BUILD.gn @@ -55,13 +55,15 @@ action("test_data_cpp_gen") { args += rebase_path(sources, root_build_dir) if (!use_wasm && !is_test && !is_fuzz) { deps = [ - "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc", - "${SRC}/proto_reader/protoc_plugin:protoreader_plugin", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", + "${SRC}/proto_reader/protoc_plugin:protoreader_plugin(${host_toolchain})", ] } } ohos_source_set("test_data_cpp") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":test_data_cpp_gen" ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", @@ -73,10 +75,10 @@ ohos_source_set("test_data_cpp") { } ohos_source_set("test_data_encoder") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" deps = [ ":test_data_cpp_gen" ] include_dirs = [ "$proto_out_dir" ] public_configs = [ ":test_include_config" ] sources = test_data_codegen_reader - subsystem_name = "developtools" - part_name = "smartperf_host" } diff --git a/trace_streamer/src/rpc/rpc_server.cpp b/trace_streamer/src/rpc/rpc_server.cpp index d6d6c7372..7b66cfd84 100644 --- a/trace_streamer/src/rpc/rpc_server.cpp +++ b/trace_streamer/src/rpc/rpc_server.cpp @@ -31,7 +31,6 @@ } while (0) namespace SysTuning { namespace TraceStreamer { -const int32_t MAX_LEN_STR = 100; uint32_t g_fileLen = 0; FILE* g_importFileFd = nullptr; bool RpcServer::ParseData(const uint8_t* data, size_t len, ResultCallBack resultCallBack) diff --git a/trace_streamer/src/rpc/rpc_server.h b/trace_streamer/src/rpc/rpc_server.h index 65d8104c5..b6ef0c472 100644 --- a/trace_streamer/src/rpc/rpc_server.h +++ b/trace_streamer/src/rpc/rpc_server.h @@ -40,7 +40,7 @@ public: int32_t UpdateTraceTime(const uint8_t* data, int32_t len); int32_t TraceStreamer_Init_ThirdParty_Config(const uint8_t* data, int32_t len); int32_t WasmExportDatabase(ResultCallBack resultCallBack); -#if IS_WASM +#ifdef IS_WASM int32_t DownloadELFCallback(const std::string& fileName, size_t totalLen, const uint8_t* data, diff --git a/trace_streamer/src/table/BUILD.gn b/trace_streamer/src/table/BUILD.gn index ed2a3ffd2..29a0ffae1 100644 --- a/trace_streamer/src/table/BUILD.gn +++ b/trace_streamer/src/table/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../build/ts.gni") ohos_source_set("table") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" include_dirs = [ "${THIRD_PARTY}/sqlite/include", "${SRC}/base", @@ -47,11 +47,9 @@ ohos_source_set("table") { "ebpf:ebpf_tables", "ftrace:ftrace_tables", "hi_sysevent:hi_sysevent_tables", + "hiperf:hiperf_tables", "js_memory:js_memory_tables", "monitor:monitor_tables", "native_hook:native_hook_tables", ] - if (with_perf) { - deps += [ "hiperf:hiperf_tables" ] - } } diff --git a/trace_streamer/src/table/base/BUILD.gn b/trace_streamer/src/table/base/BUILD.gn index 30a15a4de..73e32cd53 100644 --- a/trace_streamer/src/table/base/BUILD.gn +++ b/trace_streamer/src/table/base/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("base_tables") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "args_table.cpp", "args_table.h", diff --git a/trace_streamer/src/table/base/span_join.h b/trace_streamer/src/table/base/span_join.h index b7df9f326..2cff0502e 100644 --- a/trace_streamer/src/table/base/span_join.h +++ b/trace_streamer/src/table/base/span_join.h @@ -85,7 +85,7 @@ public: int32_t missPartitionStart_ = 0; int32_t missPartitionEnd_ = 0; std::string sqlQuery_; - sqlite3_stmt* stmt_; + sqlite3_stmt* stmt_ = nullptr; const TableDesc* desc_ = nullptr; sqlite3* db_ = nullptr; SpanJoin* table_ = nullptr; diff --git a/trace_streamer/src/table/ftrace/BUILD.gn b/trace_streamer/src/table/ftrace/BUILD.gn index 2c2a0008e..fed4d03e0 100644 --- a/trace_streamer/src/table/ftrace/BUILD.gn +++ b/trace_streamer/src/table/ftrace/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("ftrace_tables") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "animation_table.cpp", "animation_table.h", diff --git a/trace_streamer/src/table/ftrace/process_table.cpp b/trace_streamer/src/table/ftrace/process_table.cpp index e626528f7..9be2d5b02 100644 --- a/trace_streamer/src/table/ftrace/process_table.cpp +++ b/trace_streamer/src/table/ftrace/process_table.cpp @@ -294,7 +294,6 @@ void ProcessTable::Cursor::FilterPid(unsigned char op, uint64_t value) } void ProcessTable::Cursor::FilterIndex(int32_t col, unsigned char op, sqlite3_value* argv) { - auto type = sqlite3_value_type(argv); switch (col) { case PID: /* code */ @@ -307,7 +306,6 @@ void ProcessTable::Cursor::FilterIndex(int32_t col, unsigned char op, sqlite3_va } void ProcessTable::Cursor::FilterId(unsigned char op, sqlite3_value* argv) { - auto type = sqlite3_value_type(argv); auto v = static_cast(sqlite3_value_int64(argv)); switch (op) { case SQLITE_INDEX_CONSTRAINT_EQ: diff --git a/trace_streamer/src/table/hi_sysevent/BUILD.gn b/trace_streamer/src/table/hi_sysevent/BUILD.gn index 5376f8207..fcf1a758f 100644 --- a/trace_streamer/src/table/hi_sysevent/BUILD.gn +++ b/trace_streamer/src/table/hi_sysevent/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("hi_sysevent_tables") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "device_state_table.cpp", "device_state_table.h", diff --git a/trace_streamer/src/table/js_memory/BUILD.gn b/trace_streamer/src/table/js_memory/BUILD.gn index 2138c540a..8352e1ba5 100644 --- a/trace_streamer/src/table/js_memory/BUILD.gn +++ b/trace_streamer/src/table/js_memory/BUILD.gn @@ -20,6 +20,12 @@ ohos_source_set("js_memory_tables") { sources = [ "appname_table.cpp", "appname_table.h", + "js_config_table.cpp", + "js_config_table.h", + "js_cpu_profiler_node_table.cpp", + "js_cpu_profiler_node_table.h", + "js_cpu_profiler_sample_table.cpp", + "js_cpu_profiler_sample_table.h", "js_heap_edges_table.cpp", "js_heap_edges_table.h", "js_heap_files_table.cpp", diff --git a/trace_streamer/src/table/js_memory/js_config_table.cpp b/trace_streamer/src/table/js_memory/js_config_table.cpp new file mode 100644 index 000000000..59b237709 --- /dev/null +++ b/trace_streamer/src/table/js_memory/js_config_table.cpp @@ -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. + */ + +#include "js_config_table.h" + +namespace SysTuning { +namespace TraceStreamer { +enum Index { PID = 0, TYPE, INTERVAL, CAPTURE_NUMERIC_VALUE, TRACK_ALLOCATION, CPU_PROFILER, CPU_PROFILER_INTERVAL }; +JsConfigTable::JsConfigTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("pid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("interval", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("capture_numeric_value", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("trace_allocation", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("enable_cpu_profiler ", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu_profiler_interval ", "INTEGER")); + tablePriKey_.push_back("pid"); +} + +JsConfigTable::~JsConfigTable() {} + +std::unique_ptr JsConfigTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +JsConfigTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstJsConfigData().Size())), + jsConfig_(dataCache->GetConstJsConfigData()) +{ +} + +JsConfigTable::Cursor::~Cursor() {} + +int32_t JsConfigTable::Cursor::Column(int32_t col) const +{ + switch (col) { + case PID: + sqlite3_result_int64(context_, static_cast(jsConfig_.Pids()[CurrentRow()])); + break; + case TYPE: + sqlite3_result_int64(context_, static_cast(jsConfig_.Types()[CurrentRow()])); + break; + case INTERVAL: + sqlite3_result_int64(context_, static_cast(jsConfig_.Intervals()[CurrentRow()])); + break; + case CAPTURE_NUMERIC_VALUE: + sqlite3_result_int64(context_, static_cast(jsConfig_.CaptureNumericValue()[CurrentRow()])); + break; + case TRACK_ALLOCATION: + sqlite3_result_int64(context_, static_cast(jsConfig_.TrackAllocations()[CurrentRow()])); + break; + case CPU_PROFILER: + sqlite3_result_int64(context_, static_cast(jsConfig_.CpuProfiler()[CurrentRow()])); + break; + case CPU_PROFILER_INTERVAL: + sqlite3_result_int64(context_, static_cast(jsConfig_.CpuProfilerInterval()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", col); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/src/table/js_memory/js_config_table.h b/trace_streamer/src/table/js_memory/js_config_table.h new file mode 100644 index 000000000..884ccfab7 --- /dev/null +++ b/trace_streamer/src/table/js_memory/js_config_table.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 JS_CONFIG_TABLE_H +#define JS_CONFIG_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class JsConfigTable : public TableBase { +public: + explicit JsConfigTable(const TraceDataCache* dataCache); + ~JsConfigTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override + { + UNUSED(fc); + UNUSED(ei); + } + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int32_t Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int32_t Column(int32_t col) const override; + + private: + const JsConfig& jsConfig_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // JS_CONFIG_TABLE_H diff --git a/trace_streamer/src/table/js_memory/js_cpu_profiler_node_table.cpp b/trace_streamer/src/table/js_memory/js_cpu_profiler_node_table.cpp new file mode 100644 index 000000000..e92c03b92 --- /dev/null +++ b/trace_streamer/src/table/js_memory/js_cpu_profiler_node_table.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "js_cpu_profiler_node_table.h" + +namespace SysTuning { +namespace TraceStreamer { +enum Index { + FUNCTION_ID = 0, + FUNCTION_NAME, + SCRIPT_ID, + URL, + LINE_NUMBER, + COLUMN_NUMBER, + HIT_COUNT, + CHILDREN, + PARENT_ID +}; +JsCpuProfilerNodeTable::JsCpuProfilerNodeTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("function_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("function_index", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("script_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("url_index", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("line_number", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("column_number", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("hit_count", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("children", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("parent_id", "INTEGER")); + tablePriKey_.push_back("function_id"); +} + +JsCpuProfilerNodeTable::~JsCpuProfilerNodeTable() {} + +std::unique_ptr JsCpuProfilerNodeTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +JsCpuProfilerNodeTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstJsCpuProfilerNodeData().Size())), + jsCpuProfilerNodes_(dataCache->GetConstJsCpuProfilerNodeData()) +{ +} + +JsCpuProfilerNodeTable::Cursor::~Cursor() {} + +int32_t JsCpuProfilerNodeTable::Cursor::Column(int32_t col) const +{ + switch (col) { + case FUNCTION_ID: + sqlite3_result_int64(context_, static_cast(jsCpuProfilerNodes_.FunctionIds()[CurrentRow()])); + break; + case FUNCTION_NAME: + sqlite3_result_int64(context_, static_cast(jsCpuProfilerNodes_.FunctionNames()[CurrentRow()])); + break; + case SCRIPT_ID: + sqlite3_result_text(context_, jsCpuProfilerNodes_.ScriptIds()[CurrentRow()].c_str(), STR_DEFAULT_LEN, + nullptr); + break; + case URL: + sqlite3_result_int64(context_, static_cast(jsCpuProfilerNodes_.Urls()[CurrentRow()])); + break; + case LINE_NUMBER: + sqlite3_result_int64(context_, static_cast(jsCpuProfilerNodes_.LineNumbers()[CurrentRow()])); + break; + case COLUMN_NUMBER: + sqlite3_result_int64(context_, static_cast(jsCpuProfilerNodes_.ColumnNumbers()[CurrentRow()])); + break; + case HIT_COUNT: + sqlite3_result_int64(context_, static_cast(jsCpuProfilerNodes_.HitCounts()[CurrentRow()])); + break; + case CHILDREN: + sqlite3_result_text(context_, jsCpuProfilerNodes_.Children()[CurrentRow()].c_str(), STR_DEFAULT_LEN, + nullptr); + break; + case PARENT_ID: + sqlite3_result_int64(context_, static_cast(jsCpuProfilerNodes_.Parents()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", col); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/src/table/js_memory/js_cpu_profiler_node_table.h b/trace_streamer/src/table/js_memory/js_cpu_profiler_node_table.h new file mode 100644 index 000000000..e30901620 --- /dev/null +++ b/trace_streamer/src/table/js_memory/js_cpu_profiler_node_table.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 JS_CPU_PROFILER_NODE_TABLE_H +#define JS_CPU_PROFILER_NODE_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class JsCpuProfilerNodeTable : public TableBase { +public: + explicit JsCpuProfilerNodeTable(const TraceDataCache* dataCache); + ~JsCpuProfilerNodeTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override + { + UNUSED(fc); + UNUSED(ei); + } + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int32_t Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int32_t Column(int32_t col) const override; + + private: + const JsCpuProfilerNode& jsCpuProfilerNodes_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // JS_CPU_PROFILER_NODE_TABLE_H diff --git a/trace_streamer/src/table/js_memory/js_cpu_profiler_sample_table.cpp b/trace_streamer/src/table/js_memory/js_cpu_profiler_sample_table.cpp new file mode 100644 index 000000000..abc928363 --- /dev/null +++ b/trace_streamer/src/table/js_memory/js_cpu_profiler_sample_table.cpp @@ -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. + */ + +#include "js_cpu_profiler_sample_table.h" + +namespace SysTuning { +namespace TraceStreamer { +enum Index { ID = 0, FUNCTION_ID, START_TIME, END_TIME, DUR }; +JsCpuProfilerSampleTable::JsCpuProfilerSampleTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("function_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("start_time", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("end_time", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER")); + tablePriKey_.push_back("id"); +} + +JsCpuProfilerSampleTable::~JsCpuProfilerSampleTable() {} + +std::unique_ptr JsCpuProfilerSampleTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +JsCpuProfilerSampleTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstJsCpuProfilerSampleData().Size())), + jsCpuProfilerSample_(dataCache->GetConstJsCpuProfilerSampleData()) +{ +} + +JsCpuProfilerSampleTable::Cursor::~Cursor() {} + +int32_t JsCpuProfilerSampleTable::Cursor::Column(int32_t col) const +{ + switch (col) { + case ID: + sqlite3_result_int64(context_, static_cast(jsCpuProfilerSample_.IdsData()[CurrentRow()])); + break; + case FUNCTION_ID: + sqlite3_result_int64(context_, static_cast(jsCpuProfilerSample_.FunctionIds()[CurrentRow()])); + break; + case START_TIME: + sqlite3_result_int64(context_, static_cast(jsCpuProfilerSample_.StartTimes()[CurrentRow()])); + break; + case END_TIME: + sqlite3_result_int64(context_, static_cast(jsCpuProfilerSample_.EndTimes()[CurrentRow()])); + break; + case DUR: + sqlite3_result_int64(context_, static_cast(jsCpuProfilerSample_.Durs()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", col); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/src/table/js_memory/js_cpu_profiler_sample_table.h b/trace_streamer/src/table/js_memory/js_cpu_profiler_sample_table.h new file mode 100644 index 000000000..cf40cca1d --- /dev/null +++ b/trace_streamer/src/table/js_memory/js_cpu_profiler_sample_table.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 JS_CPU_PROFILER_SAMPLE_TABLE_H +#define JS_CPU_PROFILER_SAMPLE_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class JsCpuProfilerSampleTable : public TableBase { +public: + explicit JsCpuProfilerSampleTable(const TraceDataCache* dataCache); + ~JsCpuProfilerSampleTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override + { + UNUSED(fc); + UNUSED(ei); + } + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int32_t Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int32_t Column(int32_t col) const override; + + private: + const JsCpuProfilerSample& jsCpuProfilerSample_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // JS_CPU_PROFILER_SAMPLE_TABLE_H diff --git a/trace_streamer/src/table/js_memory/js_heap_files_table.cpp b/trace_streamer/src/table/js_memory/js_heap_files_table.cpp index 84e37ca1c..369ddce66 100644 --- a/trace_streamer/src/table/js_memory/js_heap_files_table.cpp +++ b/trace_streamer/src/table/js_memory/js_heap_files_table.cpp @@ -17,14 +17,13 @@ namespace SysTuning { namespace TraceStreamer { -enum Index { ID = 0, FILE_NAME, START_TIME, END_TIME, IPID, SELF_SIZE_COUNT }; +enum Index { ID = 0, FILE_NAME, START_TIME, END_TIME, SELF_SIZE_COUNT }; JsHeapFilesTable::JsHeapFilesTable(const TraceDataCache* dataCache) : TableBase(dataCache) { tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("file_name", "TEXT")); tableColumn_.push_back(TableBase::ColumnInfo("start_time", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("end_time", "INTEGER")); - tableColumn_.push_back(TableBase::ColumnInfo("pid", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("self_size", "INTEGER")); tablePriKey_.push_back("id"); } @@ -59,9 +58,6 @@ int32_t JsHeapFilesTable::Cursor::Column(int32_t col) const case END_TIME: sqlite3_result_int64(context_, static_cast(jsHeapFiles_.EndTimes()[CurrentRow()])); break; - case IPID: - sqlite3_result_int64(context_, static_cast(jsHeapFiles_.Pids()[CurrentRow()])); - break; case SELF_SIZE_COUNT: sqlite3_result_int64(context_, static_cast(jsHeapFiles_.SelfSizeCount()[CurrentRow()])); break; diff --git a/trace_streamer/src/table/monitor/BUILD.gn b/trace_streamer/src/table/monitor/BUILD.gn index e659fc2b8..db680eb24 100644 --- a/trace_streamer/src/table/monitor/BUILD.gn +++ b/trace_streamer/src/table/monitor/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("monitor_tables") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "cpu_usage_info_table.cpp", "cpu_usage_info_table.h", diff --git a/trace_streamer/src/table/native_hook/BUILD.gn b/trace_streamer/src/table/native_hook/BUILD.gn index 4349bed8e..10a75c6c0 100644 --- a/trace_streamer/src/table/native_hook/BUILD.gn +++ b/trace_streamer/src/table/native_hook/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../../build/ts.gni") ohos_source_set("native_hook_tables") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "native_hook_frame_table.cpp", "native_hook_frame_table.h", diff --git a/trace_streamer/src/trace_data/BUILD.gn b/trace_streamer/src/trace_data/BUILD.gn index 3cd8a2395..a21f04aae 100644 --- a/trace_streamer/src/trace_data/BUILD.gn +++ b/trace_streamer/src/trace_data/BUILD.gn @@ -15,8 +15,8 @@ import("//build/ohos.gni") import("../../build/ts.gni") ohos_source_set("trace_data") { - subsystem_name = "developtools" - part_name = "smartperf_host" + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" sources = [ "trace_data_cache.cpp", "trace_data_cache.h", diff --git a/trace_streamer/src/trace_data/trace_data_cache.cpp b/trace_streamer/src/trace_data/trace_data_cache.cpp index 903876c95..23023fba6 100644 --- a/trace_streamer/src/trace_data/trace_data_cache.cpp +++ b/trace_streamer/src/trace_data/trace_data_cache.cpp @@ -43,6 +43,9 @@ #include "frame_maps_table.h" #include "frame_slice_table.h" #include "gpu_slice_table.h" +#include "js_config_table.h" +#include "js_cpu_profiler_node_table.h" +#include "js_cpu_profiler_sample_table.h" #include "js_heap_edges_table.h" #include "js_heap_files_table.h" #include "js_heap_info_table.h" @@ -66,13 +69,11 @@ #include "native_hook_statistic_table.h" #include "network_table.h" #include "paged_memory_sample_table.h" -#if WITH_PERF #include "perf_call_chain_table.h" #include "perf_files_table.h" #include "perf_report_table.h" #include "perf_sample_table.h" #include "perf_thread_table.h" -#endif #include "process_filter_table.h" #include "process_measure_filter_table.h" #include "process_table.h" @@ -160,6 +161,9 @@ void TraceDataCache::InitDB() TableBase::TableDeclare(*db_, this, "js_heap_string"); TableBase::TableDeclare(*db_, this, "js_heap_trace_function_info"); TableBase::TableDeclare(*db_, this, "js_heap_trace_node"); + TableBase::TableDeclare(*db_, this, "js_cpu_profiler_node"); + TableBase::TableDeclare(*db_, this, "js_cpu_profiler_sample"); + TableBase::TableDeclare(*db_, this, "js_config"); TableBase::TableDeclare(*db_, this, "args"); TableBase::TableDeclare(*db_, this, "sys_event_filter"); @@ -188,13 +192,11 @@ void TraceDataCache::InitDB() TableBase::TableDeclare(*db_, this, "app_startup"); TableBase::TableDeclare(*db_, this, "static_initalize"); -#if WITH_PERF TableBase::TableDeclare(*db_, this, "perf_report"); TableBase::TableDeclare(*db_, this, "perf_sample"); TableBase::TableDeclare(*db_, this, "perf_callchain"); TableBase::TableDeclare(*db_, this, "perf_thread"); TableBase::TableDeclare(*db_, this, "perf_files"); -#endif #else TableBase::TableDeclare(*db_, this, "_animation"); TableBase::TableDeclare(*db_, this, "_dynamic_frame"); @@ -246,6 +248,9 @@ void TraceDataCache::InitDB() TableBase::TableDeclare(*db_, this, "_js_heap_string"); TableBase::TableDeclare(*db_, this, "_js_heap_trace_function_info"); TableBase::TableDeclare(*db_, this, "_js_heap_trace_node"); + TableBase::TableDeclare(*db_, this, "_js_cpu_Perfiler_Node"); + TableBase::TableDeclare(*db_, this, "_js_cpu_Perfiler_Sample"); + TableBase::TableDeclare(*db_, this, "_js_config"); TableBase::TableDeclare(*db_, this, "_args"); TableBase::TableDeclare(*db_, this, "_sys_event_filter"); TableBase::TableDeclare(*db_, this, "_diskio"); @@ -272,13 +277,11 @@ void TraceDataCache::InitDB() TableBase::TableDeclare(*db_, this, "_hisys_event_measure"); TableBase::TableDeclare(*db_, this, "_device_state"); TableBase::TableDeclare(*db_, this, "_trace_config"); -#if WITH_PERF TableBase::TableDeclare(*db_, this, "_perf_report"); TableBase::TableDeclare(*db_, this, "_perf_sample"); TableBase::TableDeclare(*db_, this, "_perf_callchain"); TableBase::TableDeclare(*db_, this, "_perf_thread"); TableBase::TableDeclare(*db_, this, "_perf_files"); -#endif #endif dbInited_ = true; } diff --git a/trace_streamer/src/trace_data/trace_data_cache_base.h b/trace_streamer/src/trace_data/trace_data_cache_base.h index 7e9e573f8..03b5f50a3 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_base.h +++ b/trace_streamer/src/trace_data/trace_data_cache_base.h @@ -162,6 +162,9 @@ public: JsHeapString jsHeapStringData_; JsHeapTraceFuncInfo jsHeapTraceFuncInfoData_; JsHeapTraceNode jsHeapTraceNodeData_; + JsCpuProfilerNode jsCpuProfilerNodeData_; + JsCpuProfilerSample jsCpuProfilerSampleData_; + JsConfig jsConfigData_; AppStartup appStartupData_; SoStaticInitalization staticInitalizationData_; Animation animation_; diff --git a/trace_streamer/src/trace_data/trace_data_cache_reader.cpp b/trace_streamer/src/trace_data/trace_data_cache_reader.cpp index 1491e2fc1..59e7860cb 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_reader.cpp +++ b/trace_streamer/src/trace_data/trace_data_cache_reader.cpp @@ -232,6 +232,19 @@ const JsHeapTraceNode& TraceDataCacheReader::GetConstJsHeapTraceNodeData() const { return jsHeapTraceNodeData_; } +const JsCpuProfilerNode& TraceDataCacheReader::GetConstJsCpuProfilerNodeData() const +{ + return jsCpuProfilerNodeData_; +} +const JsCpuProfilerSample& TraceDataCacheReader::GetConstJsCpuProfilerSampleData() const +{ + return jsCpuProfilerSampleData_; +} + +const JsConfig& TraceDataCacheReader::GetConstJsConfigData() const +{ + return jsConfigData_; +} const DataType& TraceDataCacheReader::GetConstDataTypeData() const { diff --git a/trace_streamer/src/trace_data/trace_data_cache_reader.h b/trace_streamer/src/trace_data/trace_data_cache_reader.h index d1d1b14d9..53559550e 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_reader.h +++ b/trace_streamer/src/trace_data/trace_data_cache_reader.h @@ -81,7 +81,7 @@ public: const DeviceStateData& GetConstDeviceStateData() const; const EbpfCallStackData& GetConstEbpfCallStackData() const; const PagedMemorySampleData& GetConstPagedMemorySampleData() const; -#if WITH_EBPF_HELP +#ifdef WITH_EBPF_HELP const EbpfProcessMaps& GetConstEbpfProcessMaps() const; const EbpfElf& GetConstEbpfElf() const; const EbpfElfSymbol& GetConstEbpfElfSymbol() const; @@ -106,6 +106,9 @@ public: const JsHeapString& GetConstJsHeapStringData() const; const JsHeapTraceFuncInfo& GetConstJsHeapTraceFuncInfoData() const; const JsHeapTraceNode& GetConstJsHeapTraceNodeData() const; + const JsCpuProfilerNode& GetConstJsCpuProfilerNodeData() const; + const JsCpuProfilerSample& GetConstJsCpuProfilerSampleData() const; + const JsConfig& GetConstJsConfigData() const; const AppStartup& GetConstAppStartupData() const; const SoStaticInitalization& GetConstStaticInitalizationData() const; const Animation& GetConstAnimation() const; diff --git a/trace_streamer/src/trace_data/trace_data_cache_writer.cpp b/trace_streamer/src/trace_data/trace_data_cache_writer.cpp index 41844cc4c..dfd67a133 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_writer.cpp +++ b/trace_streamer/src/trace_data/trace_data_cache_writer.cpp @@ -374,6 +374,18 @@ JsHeapTraceNode* TraceDataCacheWriter::GetJsHeapTraceNodeData() { return &jsHeapTraceNodeData_; } +JsCpuProfilerNode* TraceDataCacheWriter::GetJsCpuProfilerNodeData() +{ + return &jsCpuProfilerNodeData_; +} +JsCpuProfilerSample* TraceDataCacheWriter::GetJsCpuProfilerSampleData() +{ + return &jsCpuProfilerSampleData_; +} +JsConfig* TraceDataCacheWriter::GetJsConfigData() +{ + return &jsConfigData_; +} AppStartup* TraceDataCacheWriter::GetAppStartupData() { return &appStartupData_; @@ -451,6 +463,9 @@ void TraceDataCacheWriter::Clear() jsHeapStringData_.Clear(); jsHeapTraceFuncInfoData_.Clear(); jsHeapTraceNodeData_.Clear(); + jsCpuProfilerNodeData_.Clear(); + jsCpuProfilerSampleData_.Clear(); + jsConfigData_.Clear(); appStartupData_.Clear(); staticInitalizationData_.Clear(); animation_.Clear(); diff --git a/trace_streamer/src/trace_data/trace_data_cache_writer.h b/trace_streamer/src/trace_data/trace_data_cache_writer.h index a98a92c9b..994aaa23d 100644 --- a/trace_streamer/src/trace_data/trace_data_cache_writer.h +++ b/trace_streamer/src/trace_data/trace_data_cache_writer.h @@ -79,7 +79,7 @@ public: FileSystemSample* GetFileSystemSample(); EbpfCallStackData* GetEbpfCallStack(); PagedMemorySampleData* GetPagedMemorySampleData(); -#if WITH_EBPF_HELP +#ifdef WITH_EBPF_HELP EbpfProcessMaps* GetEbpfProcessMaps(); EbpfElf* GetEbpfElf(); EbpfElfSymbol* GetEbpfElfSymbol(); @@ -105,6 +105,9 @@ public: JsHeapString* GetJsHeapStringData(); JsHeapTraceFuncInfo* GetJsHeapTraceFuncInfoData(); JsHeapTraceNode* GetJsHeapTraceNodeData(); + JsCpuProfilerNode* GetJsCpuProfilerNodeData(); + JsCpuProfilerSample* GetJsCpuProfilerSampleData(); + JsConfig* GetJsConfigData(); AppStartup* GetAppStartupData(); SoStaticInitalization* GetStaticInitalizationData(); Animation* GetAnimation(); diff --git a/trace_streamer/src/trace_data/trace_stdtype.cpp b/trace_streamer/src/trace_data/trace_stdtype.cpp index ac133b484..284315d19 100644 --- a/trace_streamer/src/trace_data/trace_stdtype.cpp +++ b/trace_streamer/src/trace_data/trace_stdtype.cpp @@ -17,9 +17,11 @@ #include #include #include +#include "string_to_numerical.h" namespace SysTuning { namespace TraceStdtype { -const int32_t MAX_SIZE_LEN = 80; +constexpr int32_t MAX_SIZE_LEN = 80; +constexpr uint8_t DEVICEINFO_MATCH_LAST = 2; #define UNUSED(expr) \ do { \ static_cast(expr); \ @@ -2304,7 +2306,7 @@ const std::deque& GPUSlice::Durs() const { return durs_; } -const size_t GPUSlice::Size() const +size_t GPUSlice::Size() const { return durs_.size(); } @@ -2407,14 +2409,12 @@ size_t JsHeapFiles::AppendNewData(uint32_t id, std::string filePath, uint64_t startTime, uint64_t endTime, - uint32_t ipid, uint64_t selfSizeCount) { fileIds_.emplace_back(id); filePaths_.emplace_back(filePath); startTimes_.emplace_back(startTime); endTimes_.emplace_back(endTime); - ipids_.emplace_back(ipid); selfSizeCount_.emplace_back(selfSizeCount); ids_.emplace_back(Size()); return Size() - 1; @@ -2435,10 +2435,6 @@ const std::deque& JsHeapFiles::EndTimes() const { return endTimes_; } -const std::deque& JsHeapFiles::Pids() const -{ - return ipids_; -} const std::deque& JsHeapFiles::SelfSizeCount() const { @@ -2754,6 +2750,139 @@ const std::deque& JsHeapTraceNode::ParentIds() const return parentIds_; } +size_t JsCpuProfilerNode::AppendNewData(uint32_t functionId, + uint32_t functionName, + std::string scriptId, + uint32_t url, + uint32_t lineNumber, + uint32_t columnNumber, + uint32_t hitCount, + std::string children, + uint32_t parentId) +{ + functionIds_.emplace_back(functionId); + functionNames_.emplace_back(functionName); + scriptIds_.emplace_back(scriptId); + urls_.emplace_back(url); + lineNumbers_.emplace_back(lineNumber); + columnNumbers_.emplace_back(columnNumber); + hitCounts_.emplace_back(hitCount); + children_.emplace_back(children); + parents_.emplace_back(parentId); + ids_.emplace_back(Size()); + return Size() - 1; +} + +const std::deque& JsCpuProfilerNode::FunctionIds() const +{ + return functionIds_; +} +const std::deque& JsCpuProfilerNode::FunctionNames() const +{ + return functionNames_; +} +const std::deque& JsCpuProfilerNode::ScriptIds() const +{ + return scriptIds_; +} +const std::deque& JsCpuProfilerNode::Urls() const +{ + return urls_; +} +const std::deque& JsCpuProfilerNode::LineNumbers() const +{ + return lineNumbers_; +} +const std::deque& JsCpuProfilerNode::ColumnNumbers() const +{ + return columnNumbers_; +} +const std::deque& JsCpuProfilerNode::HitCounts() const +{ + return hitCounts_; +} +const std::deque& JsCpuProfilerNode::Children() const +{ + return children_; +} +const std::deque& JsCpuProfilerNode::Parents() const +{ + return parents_; +} + +size_t JsCpuProfilerSample::AppendNewData(uint32_t functionId, uint64_t startTime, uint64_t endTime, uint64_t dur) +{ + functionIds_.emplace_back(functionId); + startTimes_.emplace_back(startTime); + endTimes_.emplace_back(endTime); + durs_.emplace_back(dur); + ids_.emplace_back(Size()); + return Size() - 1; +} +const std::deque& JsCpuProfilerSample::FunctionIds() const +{ + return functionIds_; +} +const std::deque& JsCpuProfilerSample::StartTimes() const +{ + return startTimes_; +} +const std::deque& JsCpuProfilerSample::EndTimes() const +{ + return endTimes_; +} +const std::deque& JsCpuProfilerSample::Durs() const +{ + return durs_; +} + +size_t JsConfig::AppendNewData(uint32_t pid, + uint64_t type, + uint32_t interval, + uint32_t captureNumericValue, + uint32_t trackAllocation, + uint32_t cpuProfiler, + uint32_t cpuProfilerInterval) +{ + pids_.emplace_back(pid); + types_.emplace_back(type); + intervals_.emplace_back(interval); + captureNumericValues_.emplace_back(captureNumericValue); + trackAllocations_.emplace_back(trackAllocation); + cpuProfilers_.emplace_back(cpuProfiler); + cpuProfilerIntervals_.emplace_back(cpuProfilerInterval); + ids_.emplace_back(Size()); + return Size() - 1; +} +const std::deque& JsConfig::Pids() const +{ + return pids_; +} +const std::deque& JsConfig::Types() const +{ + return types_; +} +const std::deque& JsConfig::Intervals() const +{ + return intervals_; +} +const std::deque& JsConfig::CaptureNumericValue() const +{ + return captureNumericValues_; +} +const std::deque& JsConfig::TrackAllocations() const +{ + return trackAllocations_; +} +const std::deque& JsConfig::CpuProfiler() const +{ + return cpuProfilers_; +} +const std::deque& JsConfig::CpuProfilerInterval() const +{ + return cpuProfilerIntervals_; +} + size_t TaskPoolInfo::AppendAllocationTaskData(uint32_t allocationTaskRow, uint32_t allocationTaskId, uint32_t executeId, @@ -2936,10 +3065,13 @@ const uint32_t DeviceInfo::PhysicalFrameRate() const { return physicalFrameRate_; } -void DeviceInfo::UpdateWidthAndHeight(uint32_t width, uint32_t height) +void DeviceInfo::UpdateWidthAndHeight(const std::smatch& matcheLine) { - physicalWidth_ = width; - physicalHeight_ = height; + if (matcheLine.size() > DEVICEINFO_MATCH_LAST) { + uint8_t matcheIndex = 0; + physicalWidth_ = base::StrToInt(matcheLine[++matcheIndex].str()).value(); + physicalHeight_ = base::StrToInt(matcheLine[++matcheIndex].str()).value(); + } } void DeviceInfo::UpdateFrameRate(uint32_t frameRate) { @@ -2969,18 +3101,14 @@ void DynamicFrame::UpdateNameIndex(TableRowId index, DataIndex nameId) names_[index] = nameId; } } -void DynamicFrame::UpdatePosition(TableRowId index, - uint32_t x, - uint32_t y, - uint32_t width, - uint32_t height, - DataIndex alpha) +void DynamicFrame::UpdatePosition(TableRowId index, const std::smatch& matcheLine, DataIndex alpha) { - if (index <= Size()) { - xs_[index] = x; - ys_[index] = y; - widths_[index] = width; - heights_[index] = height; + if (index <= Size() && matcheLine.size() > DYNAMICFRAME_MATCH_LAST) { + uint8_t matcheIndex = 0; + xs_[index] = base::StrToInt(matcheLine[++matcheIndex].str()).value(); + ys_[index] = base::StrToInt(matcheLine[++matcheIndex].str()).value(); + widths_[index] = base::StrToInt(matcheLine[++matcheIndex].str()).value(); + heights_[index] = base::StrToInt(matcheLine[++matcheIndex].str()).value(); alphas_[index] = alpha; } } diff --git a/trace_streamer/src/trace_data/trace_stdtype.h b/trace_streamer/src/trace_data/trace_stdtype.h index 93ebdece5..ce6b8f80c 100644 --- a/trace_streamer/src/trace_data/trace_stdtype.h +++ b/trace_streamer/src/trace_data/trace_stdtype.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ using namespace SysTuning::TraceCfg; using namespace SysTuning::TraceStreamer; constexpr uint32_t ONE_MILLION_NANOSECONDS = 1000000; constexpr uint32_t BILLION_NANOSECONDS = 1000000000; +constexpr uint8_t DYNAMICFRAME_MATCH_LAST = 5; class CacheBase { public: size_t Size() const @@ -141,7 +143,7 @@ public: states_.clear(); cpus_.clear(); } - const uint32_t Size() const + uint32_t Size() const { return itids_.size(); } @@ -871,8 +873,6 @@ private: std::deque symbolOffsets_ = {}; std::deque vaddrs_ = {}; std::map symbolIdToSymbolName_ = {}; - DataIndex libcFilePathIndex_ = INVALID_UINT64; - DataIndex muslFilePathIndex_ = INVALID_UINT64; }; class NativeHookStatistic : public CacheBase { @@ -1552,7 +1552,6 @@ private: std::deque flags_ = {}; std::deque appNames_ = {}; std::deque keyNames_ = {}; - uint32_t rowCount_ = 0; }; class SysEventMeasureData : public CacheBase { public: @@ -1824,7 +1823,7 @@ public: names_.emplace_back(name); return ts_.size(); } - const size_t Size() const + size_t Size() const { return ts_.size(); } @@ -1855,7 +1854,7 @@ public: clockIds_.emplace_back(clockId); return dataSourceNames_.size(); } - const size_t Size() const + size_t Size() const { return dataSourceNames_.size(); } @@ -2016,17 +2015,12 @@ private: class JsHeapFiles : public CacheBase { public: - size_t AppendNewData(uint32_t id, - std::string filePath, - uint64_t startTime, - uint64_t endTime, - uint32_t ipid, - uint64_t selfSizeCount); + size_t + AppendNewData(uint32_t id, std::string filePath, uint64_t startTime, uint64_t endTime, uint64_t selfSizeCount); const std::deque& IDs() const; const std::deque& FilePaths() const; const std::deque& StartTimes() const; const std::deque& EndTimes() const; - const std::deque& Pids() const; const std::deque& SelfSizeCount() const; void Clear() override { @@ -2035,7 +2029,6 @@ public: filePaths_.clear(); startTimes_.clear(); endTimes_.clear(); - ipids_.clear(); selfSizeCount_.clear(); } @@ -2044,7 +2037,6 @@ private: std::deque filePaths_ = {}; std::deque startTimes_ = {}; std::deque endTimes_ = {}; - std::deque ipids_ = {}; std::deque selfSizeCount_ = {}; }; @@ -2300,12 +2292,119 @@ private: std::deque parentIds_ = {}; }; +class JsConfig : public CacheBase { +public: + size_t AppendNewData(uint32_t pid, + uint64_t type, + uint32_t interval, + uint32_t captureNumericValue, + uint32_t trackAllocation, + uint32_t cpuProfiler, + uint32_t cpuProfilerInterval); + const std::deque& Pids() const; + const std::deque& Types() const; + const std::deque& Intervals() const; + const std::deque& CaptureNumericValue() const; + const std::deque& TrackAllocations() const; + const std::deque& CpuProfiler() const; + const std::deque& CpuProfilerInterval() const; + void Clear() override + { + CacheBase::Clear(); + pids_.clear(); + types_.clear(); + intervals_.clear(); + captureNumericValues_.clear(); + trackAllocations_.clear(); + cpuProfilers_.clear(); + cpuProfilerIntervals_.clear(); + } + +private: + std::deque pids_ = {}; + std::deque types_ = {}; + std::deque intervals_ = {}; + std::deque captureNumericValues_ = {}; + std::deque trackAllocations_ = {}; + std::deque cpuProfilers_ = {}; + std::deque cpuProfilerIntervals_ = {}; +}; + +class JsCpuProfilerNode : public CacheBase { +public: + size_t AppendNewData(uint32_t functionId, + uint32_t functionName, + std::string scriptId, + uint32_t url, + uint32_t lineNumber, + uint32_t columnNumber, + uint32_t hitCount, + std::string children, + uint32_t parent); + const std::deque& FunctionIds() const; + const std::deque& FunctionNames() const; + const std::deque& ScriptIds() const; + const std::deque& Urls() const; + const std::deque& LineNumbers() const; + const std::deque& ColumnNumbers() const; + const std::deque& HitCounts() const; + const std::deque& Children() const; + const std::deque& Parents() const; + void Clear() override + { + CacheBase::Clear(); + functionIds_.clear(); + functionNames_.clear(); + scriptIds_.clear(); + urls_.clear(); + lineNumbers_.clear(); + columnNumbers_.clear(); + hitCounts_.clear(); + children_.clear(); + parents_.clear(); + } + +private: + std::deque functionIds_ = {}; + std::deque functionNames_ = {}; + std::deque scriptIds_ = {}; + std::deque urls_ = {}; + std::deque lineNumbers_ = {}; + std::deque columnNumbers_ = {}; + std::deque hitCounts_ = {}; + std::deque children_ = {}; + std::deque parents_ = {}; +}; + +class JsCpuProfilerSample : public CacheBase { +public: + size_t AppendNewData(uint32_t functionId, uint64_t startTimes, uint64_t endTimes, uint64_t durs); + const std::deque& FunctionIds() const; + const std::deque& StartTimes() const; + const std::deque& EndTimes() const; + const std::deque& Durs() const; + void Clear() override + { + CacheBase::Clear(); + functionIds_.clear(); + startTimes_.clear(); + endTimes_.clear(); + durs_.clear(); + } + +private: + std::deque functionIds_ = {}; + std::deque startTimes_ = {}; + std::deque endTimes_ = {}; + std::deque durs_ = {}; +}; + class GPUSlice { public: size_t AppendNew(uint32_t frameRow, uint64_t dur); const std::deque& FrameRows() const; const std::deque& Durs() const; - const size_t Size() const; + size_t Size() const; private: std::deque frameRows_ = {}; @@ -2392,7 +2491,7 @@ public: const uint32_t PhysicalWidth() const; const uint32_t PhysicalHeight() const; const uint32_t PhysicalFrameRate() const; - void UpdateWidthAndHeight(uint32_t width, uint32_t height); + void UpdateWidthAndHeight(const std::smatch& matcheLine); void UpdateFrameRate(uint32_t frameRate); void Clear(); @@ -2406,7 +2505,7 @@ class DynamicFrame { public: TableRowId AppendDynamicFrame(DataIndex nameId); void UpdateNameIndex(TableRowId index, DataIndex nameId); - void UpdatePosition(TableRowId index, uint32_t x, uint32_t y, uint32_t width, uint32_t height, DataIndex alpha); + void UpdatePosition(TableRowId index, const std::smatch& matcheLine, DataIndex alpha); void UpdateEndTime(TableRowId index, InternalTime endTime); size_t Size() const; diff --git a/trace_streamer/src/trace_streamer/trace_streamer_filters.h b/trace_streamer/src/trace_streamer/trace_streamer_filters.h index e711f8751..d9cd4c4ec 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_filters.h +++ b/trace_streamer/src/trace_streamer/trace_streamer_filters.h @@ -36,9 +36,7 @@ class HiSysEventMeasureFilter; class FrameFilter; class APPStartupFilter; class TaskPoolFilter; -#if WITH_PERF class PerfDataFilter; -#endif class TraceStreamerFilters { public: TraceStreamerFilters(); @@ -72,9 +70,7 @@ public: std::unique_ptr frameFilter_; std::unique_ptr appStartupFilter_; std::unique_ptr taskPoolFilter_; -#if WITH_PERF std::unique_ptr perfDataFilter_; -#endif }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp index cd90b1b43..47e754bee 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp +++ b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp @@ -33,9 +33,7 @@ #include "task_pool_filter.h" #include "parser/bytrace_parser/bytrace_parser.h" #include "parser/htrace_pbreader_parser/htrace_parser.h" -#if WITH_PERF #include "perf_data_filter.h" -#endif #include "process_filter.h" #include "slice_filter.h" #include "stat_filter.h" @@ -146,9 +144,7 @@ void TraceStreamerSelector::InitFilter() streamFilters_->sysEventVMemMeasureFilter_ = std::make_unique( traceDataCache_.get(), streamFilters_.get(), E_SYS_VIRTUAL_MEMORY_FILTER); streamFilters_->appStartupFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); -#if WITH_PERF streamFilters_->perfDataFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); -#endif streamFilters_->sysEventSourceFilter_ = std::make_unique( traceDataCache_.get(), streamFilters_.get(), E_SYS_EVENT_SOURCE_FILTER); streamFilters_->hiSysEventMeasureFilter_ = diff --git a/trace_streamer/src/version.cpp b/trace_streamer/src/version.cpp index 2d8fa8666..2f3abf5d5 100644 --- a/trace_streamer/src/version.cpp +++ b/trace_streamer/src/version.cpp @@ -14,5 +14,5 @@ */ #include "version.h" size_t g_loadSize = 0; -std::string TRACE_STREAM_VERSION = "3.4.3"; // version -std::string TRACE_STREAM_PUBLISHVERSION = "2023/7/14"; // publish datetime +const std::string TRACE_STREAM_VERSION = "3.4.3"; // version +const std::string TRACE_STREAM_PUBLISHVERSION = "2023/7/14"; // publish datetime diff --git a/trace_streamer/src/version.h b/trace_streamer/src/version.h index 854e7cff4..71bb6b895 100644 --- a/trace_streamer/src/version.h +++ b/trace_streamer/src/version.h @@ -18,6 +18,6 @@ #include #include extern size_t g_loadSize; -extern std::string TRACE_STREAM_VERSION; // version -extern std::string TRACE_STREAM_PUBLISHVERSION; // publish datetime +extern const std::string TRACE_STREAM_VERSION; // version +extern const std::string TRACE_STREAM_PUBLISHVERSION; // publish datetime #endif diff --git a/trace_streamer/test/BUILD.gn b/trace_streamer/test/BUILD.gn index 26d80dea0..2f135f030 100755 --- a/trace_streamer/test/BUILD.gn +++ b/trace_streamer/test/BUILD.gn @@ -20,6 +20,7 @@ if (is_test) { ohos_unittest("trace_streamer_ut") { sources = [ "unittest/animation_filter_test.cpp", + "unittest/app_start_filter_test.cpp", "unittest/binder_filter_test.cpp", "unittest/bio_parser_test.cpp", "unittest/bytrace_parser_test.cpp", @@ -60,27 +61,25 @@ if (is_test) { "unittest/table_test.cpp", "unittest/task_pool_filter_test.cpp", "unittest/wasm_func_test.cpp", - "unittest/app_start_filter_test.cpp", ] deps = [ - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:cpu_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/diskio_data:diskio_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/ftrace_data/${device_kernel_version}:ftrace_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hidump_data:hidump_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:hilog_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:hisysevent_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/js_memory:js_memory_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/network_data:network_data_cpp", - "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/process_data:process_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/cpu_data:ts_cpu_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/diskio_data:ts_diskio_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/ftrace_data/${device_kernel_version}:ts_ftrace_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hidump_data:ts_hidump_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hilog_data:ts_hilog_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/hisysevent_data:ts_hisysevent_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/js_memory:ts_js_memory_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:ts_memory_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:ts_native_hook_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/network_data:ts_network_data_cpp", + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/process_data:ts_process_data_cpp", "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/test_data:test_data_cpp", "${THIRD_PARTY}/googletest:gtest", "${THIRD_PARTY}/googletest:gtest_main", "${THIRD_PARTY}/protobuf:protobuf", "${THIRD_PARTY}/protobuf:protobuf_lite", - "${THIRD_PARTY}/sqlite:sqlite", "../src:trace_streamer_source", "../src/parser/htrace_pbreader_parser:htrace_pbreader_parser", "../src/proto_reader:proto_reader", @@ -108,8 +107,9 @@ if (is_test) { "${THIRD_PARTY}/hiperf/include", "${THIRD_PARTY}/hiperf/include/nonlinux/linux", "${THIRD_PARTY}/protobuf/src/google/protobuf", - "${THIRD_PARTY}/json-master/single_include/nlohmann", + "${THIRD_PARTY}/json/single_include/nlohmann", "${THIRD_PARTY}/perf_include/musl", + "${THIRD_PARTY}/sqlite/include", "../src/parser/htrace_pbreader_parser", "../src/parser/htrace_pbreader_parser/htrace_event_parser", "../src/parser/htrace_pbreader_parser/htrace_cpu_parser", diff --git a/trace_streamer/test/test_fuzzer/bytrace_fuzzer/BUILD.gn b/trace_streamer/test/test_fuzzer/bytrace_fuzzer/BUILD.gn index 97ed18a9a..a86a54848 100644 --- a/trace_streamer/test/test_fuzzer/bytrace_fuzzer/BUILD.gn +++ b/trace_streamer/test/test_fuzzer/bytrace_fuzzer/BUILD.gn @@ -48,7 +48,6 @@ ohos_fuzztest("ts_bytrace_fuzz_test") { deps = [ "${THIRD_PARTY}/protobuf:protobuf", "${THIRD_PARTY}/protobuf:protobuf_lite", - "${THIRD_PARTY}/sqlite:sqlite", "../../../src:trace_streamer_source", "../../../src/proto_reader:proto_reader", ] diff --git a/trace_streamer/test/test_fuzzer/htrace_fuzzer/BUILD.gn b/trace_streamer/test/test_fuzzer/htrace_fuzzer/BUILD.gn index 1bdfaf6d1..bc8debc51 100644 --- a/trace_streamer/test/test_fuzzer/htrace_fuzzer/BUILD.gn +++ b/trace_streamer/test/test_fuzzer/htrace_fuzzer/BUILD.gn @@ -48,7 +48,6 @@ ohos_fuzztest("ts_htrace_fuzz_test") { deps = [ "${THIRD_PARTY}/protobuf:protobuf", "${THIRD_PARTY}/protobuf:protobuf_lite", - "${THIRD_PARTY}/sqlite:sqlite", "../../../src:trace_streamer_source", "../../../src/proto_reader:proto_reader", ] diff --git a/trace_streamer/test/test_fuzzer/selector_fuzzer/BUILD.gn b/trace_streamer/test/test_fuzzer/selector_fuzzer/BUILD.gn index 146e2c734..fa0479cac 100644 --- a/trace_streamer/test/test_fuzzer/selector_fuzzer/BUILD.gn +++ b/trace_streamer/test/test_fuzzer/selector_fuzzer/BUILD.gn @@ -48,7 +48,6 @@ ohos_fuzztest("ts_selector_fuzz_test") { deps = [ "${THIRD_PARTY}/protobuf:protobuf", "${THIRD_PARTY}/protobuf:protobuf_lite", - "${THIRD_PARTY}/sqlite:sqlite", "../../../src:trace_streamer_source", "../../../src/proto_reader:proto_reader", ] diff --git a/trace_streamer/test/test_ts.gni b/trace_streamer/test/test_ts.gni index e67c6457f..4a051f46f 100755 --- a/trace_streamer/test/test_ts.gni +++ b/trace_streamer/test/test_ts.gni @@ -13,7 +13,6 @@ OHOS_PROTO_DIR = "" kernel_version = "." THIRD_PARTY = "//third_party" -SRC = "//src" PREBUILTS = "//prebuilts" if (target_os == "linux" || target_os == "windows" || target_os == "macx") { if (is_test) { diff --git a/trace_streamer/test/unittest/app_start_filter_test.cpp b/trace_streamer/test/unittest/app_start_filter_test.cpp old mode 100755 new mode 100644 index c7d7679e4..698234984 --- a/trace_streamer/test/unittest/app_start_filter_test.cpp +++ b/trace_streamer/test/unittest/app_start_filter_test.cpp @@ -45,9 +45,11 @@ HWTEST_F(AppStartFilterTest, ProcessCreateTest, TestSize.Level1) { TS_LOGI("test40-1"); - const std::string parent_str = "H:virtual int OHOS::AAFwk::AbilityManagerService::StartAbility(" + const std::string parent_str = + "H:virtual int OHOS::AAFwk::AbilityManagerService::StartAbility(" "const OHOS::AAFwk::Want &, const sptr &, int32_t, int)"; - const std::string process_create_str = "H:int OHOS::AAFwk::MissionListManager::StartAbilityLocked(" + const std::string process_create_str = + "H:int OHOS::AAFwk::MissionListManager::StartAbilityLocked(" "const std::shared_ptr &, const std::shared_ptr &, " "const OHOS::AAFwk::AbilityRequest &)##com.ohos.smartperf##MainAbility"; uint64_t ts1 = 168758662957000; @@ -69,7 +71,8 @@ HWTEST_F(AppStartFilterTest, ProcessCreateTest, TestSize.Level1) auto dataIndex = stream_.traceDataCache_->GetDataIndex("com.ohos.smartperf"); EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.size() == 1); - EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.find(dataIndex) != nullptr); + EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.find(dataIndex) != + stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.end()); } /** @@ -81,7 +84,8 @@ HWTEST_F(AppStartFilterTest, AppLunchTest, TestSize.Level1) { TS_LOGI("test40-2"); - const std::string process_create_str = "H:virtual void OHOS::AppExecFwk::AppMgrServiceInner::AttachApplication(" + const std::string process_create_str = + "H:virtual void OHOS::AppExecFwk::AppMgrServiceInner::AttachApplication(" "const pid_t, const sptr &)##com.ohos.smartperf"; uint64_t ts1 = 168758662957000; uint64_t ts2 = 168758663011000; @@ -97,7 +101,8 @@ HWTEST_F(AppStartFilterTest, AppLunchTest, TestSize.Level1) auto dataIndex = stream_.traceDataCache_->GetDataIndex("com.ohos.smartperf"); EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.size() == 1); - EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.find(dataIndex) != nullptr); + EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.find(dataIndex) != + stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.end()); } /** @@ -109,7 +114,8 @@ HWTEST_F(AppStartFilterTest, LunchTest, TestSize.Level1) { TS_LOGI("test40-3"); - const std::string process_create_str = "H:void OHOS::AppExecFwk::MainThread::HandleLaunchAbility(" + const std::string process_create_str = + "H:void OHOS::AppExecFwk::MainThread::HandleLaunchAbility(" "const std::shared_ptr &)##com.ohos.smartperf"; uint64_t ts1 = 168758662957000; uint64_t ts2 = 168758663011000; @@ -124,8 +130,9 @@ HWTEST_F(AppStartFilterTest, LunchTest, TestSize.Level1) stream_.streamFilters_->appStartupFilter_->FilterAllAPPStartupData(); auto dataIndex = stream_.traceDataCache_->GetDataIndex("com.ohos.smartperf"); - EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.size() == 1); - EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.find(dataIndex) != nullptr); + EXPECT_EQ(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.size(), 0); + EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.find(dataIndex) == + stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.end()); } /** @@ -137,8 +144,10 @@ HWTEST_F(AppStartFilterTest, OnforegroundTest, TestSize.Level1) { TS_LOGI("test40-4"); - const std::string process_create_str = "H:void OHOS::AppExecFwk::AbilityThread::HandleAbilityTransaction(" - "const OHOS::AppExecFwk::Want &, const OHOS::AppExecFwk::LifeCycleStateInfo &, sptr)##"; + const std::string process_create_str = + "H:void OHOS::AppExecFwk::AbilityThread::HandleAbilityTransaction(" + "const OHOS::AppExecFwk::Want &, const OHOS::AppExecFwk::LifeCycleStateInfo &, " + "sptr)##"; uint64_t ts1 = 168758662957000; uint64_t ts2 = 168758663011000; uint32_t pid1 = 1655; @@ -152,8 +161,9 @@ HWTEST_F(AppStartFilterTest, OnforegroundTest, TestSize.Level1) stream_.streamFilters_->appStartupFilter_->FilterAllAPPStartupData(); auto dataIndex = stream_.traceDataCache_->GetDataIndex(".ohos.smartperf"); - EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.size() == 1); - EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.find(dataIndex) != nullptr); + EXPECT_EQ(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.size(), 0); + EXPECT_TRUE(stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.find(dataIndex) == + stream_.streamFilters_->appStartupFilter_->mAPPStartupData_.end()); } /** diff --git a/trace_streamer/test/unittest/bytrace_parser_test.cpp b/trace_streamer/test/unittest/bytrace_parser_test.cpp index 70bcfa68e..dad18a507 100644 --- a/trace_streamer/test/unittest/bytrace_parser_test.cpp +++ b/trace_streamer/test/unittest/bytrace_parser_test.cpp @@ -41,7 +41,7 @@ public: public: SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; - const std::string dbPath_ = "data/resource/out.db"; + const std::string dbPath_ = "../../../data/resource/out.db"; }; /** diff --git a/trace_streamer/test/unittest/event_parser_test.cpp b/trace_streamer/test/unittest/event_parser_test.cpp index 0051afb1e..0d1f4050a 100644 --- a/trace_streamer/test/unittest/event_parser_test.cpp +++ b/trace_streamer/test/unittest/event_parser_test.cpp @@ -50,7 +50,7 @@ public: public: TraceStreamerSelector stream_ = {}; - const std::string dbPath_ = "data/resource/out.db"; + const std::string dbPath_ = "../../../data/resource/out.db"; }; /** diff --git a/trace_streamer/test/unittest/hidump_parser_test.cpp b/trace_streamer/test/unittest/hidump_parser_test.cpp index 77d370a82..e3c313ac8 100644 --- a/trace_streamer/test/unittest/hidump_parser_test.cpp +++ b/trace_streamer/test/unittest/hidump_parser_test.cpp @@ -46,7 +46,7 @@ public: public: SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; - const std::string dbPath_ = "data/resource/out.db"; + const std::string dbPath_ = "../../../data/resource/out.db"; }; /** diff --git a/trace_streamer/test/unittest/htrace_event_parser_test.cpp b/trace_streamer/test/unittest/htrace_event_parser_test.cpp index e447d6e77..18b334a00 100644 --- a/trace_streamer/test/unittest/htrace_event_parser_test.cpp +++ b/trace_streamer/test/unittest/htrace_event_parser_test.cpp @@ -752,7 +752,6 @@ HWTEST_F(HtraceEventParserTest, ParseSysEnterEvent, TestSize.Level1) TS_LOGI("test14-18"); SysEnterFormat* sysEnterEvent = new SysEnterFormat(); sysEnterEvent->set_id(1); - sysEnterEvent->set_args(0, 1); TracePluginResult tracePacket; FtraceCpuDetailMsg* ftraceCpuDetail = tracePacket.add_ftrace_cpu_detail(); diff --git a/trace_streamer/test/unittest/htrace_mem_parser_test.cpp b/trace_streamer/test/unittest/htrace_mem_parser_test.cpp index 65ecec9d5..4b568f410 100644 --- a/trace_streamer/test/unittest/htrace_mem_parser_test.cpp +++ b/trace_streamer/test/unittest/htrace_mem_parser_test.cpp @@ -46,7 +46,7 @@ public: public: SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; - const std::string dbPath_ = "data/resource/out.db"; + const std::string dbPath_ = "../../../data/resource/out.db"; }; /** diff --git a/trace_streamer/test/unittest/htrace_sys_mem_parser_test.cpp b/trace_streamer/test/unittest/htrace_sys_mem_parser_test.cpp index 850bb981a..e16884c3a 100644 --- a/trace_streamer/test/unittest/htrace_sys_mem_parser_test.cpp +++ b/trace_streamer/test/unittest/htrace_sys_mem_parser_test.cpp @@ -46,7 +46,7 @@ public: public: SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; - const std::string dbPath_ = "data/resource/out.db"; + const std::string dbPath_ = "../../../data/resource/out.db"; }; /** diff --git a/trace_streamer/test/unittest/htrace_sys_vmem_parser_test.cpp b/trace_streamer/test/unittest/htrace_sys_vmem_parser_test.cpp index 954bf84a2..79cecc638 100644 --- a/trace_streamer/test/unittest/htrace_sys_vmem_parser_test.cpp +++ b/trace_streamer/test/unittest/htrace_sys_vmem_parser_test.cpp @@ -46,7 +46,7 @@ public: public: SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; - const std::string dbPath_ = "data/resource/out.db"; + const std::string dbPath_ = "../../../data/resource/out.db"; }; /** diff --git a/trace_streamer/test/unittest/parser_pbreader_test.cpp b/trace_streamer/test/unittest/parser_pbreader_test.cpp index 787543f2b..74d4af3b3 100644 --- a/trace_streamer/test/unittest/parser_pbreader_test.cpp +++ b/trace_streamer/test/unittest/parser_pbreader_test.cpp @@ -43,8 +43,8 @@ protected: HWTEST_F(ParserPbreaderTest, HtracePbreaderParserTest, TestSize.Level1) { TS_LOGI("test34-1"); - const std::string tracePath = "data/resource/pbreader.htrace"; - const std::string dbPath = "data/resource/test34-1_out.db"; + const std::string tracePath = "../../../data/resource/pbreader.htrace"; + const std::string dbPath = "../../../data/resource/test34-1_out.db"; constexpr size_t readSize = 1024; constexpr uint32_t lineLength = 256; @@ -52,7 +52,6 @@ HWTEST_F(ParserPbreaderTest, HtracePbreaderParserTest, TestSize.Level1) std::unique_ptr ta = std::make_unique(); ta->EnableMetaTable(false); - ta->SetCleanMode(false); int32_t fd(base::OpenFile(tracePath, O_RDONLY, G_FILE_PERMISSION)); while (true) { std::unique_ptr buf = std::make_unique(readSize); @@ -72,7 +71,6 @@ HWTEST_F(ParserPbreaderTest, HtracePbreaderParserTest, TestSize.Level1) ta->WaitForParserEnd(); close(fd); ta->ExportDatabase(dbPath); - ta->Clear(); EXPECT_TRUE(access(dbPath.c_str(), F_OK) == 0); remove(dbPath.c_str()); } else { @@ -88,8 +86,8 @@ HWTEST_F(ParserPbreaderTest, HtracePbreaderParserTest, TestSize.Level1) HWTEST_F(ParserPbreaderTest, BytraceParserTest, TestSize.Level1) { TS_LOGI("test34-2"); - const std::string tracePath = "data/resource/ut_bytrace_input_full.txt"; - const std::string dbPath = "data/resource/test34-2_out.db"; + const std::string tracePath = "../../../data/resource/ut_bytrace_input_full.txt"; + const std::string dbPath = "../../../data/resource/test34-2_out.db"; constexpr size_t readSize = 1024 * 1024; constexpr uint32_t lineLength = 256; @@ -97,7 +95,6 @@ HWTEST_F(ParserPbreaderTest, BytraceParserTest, TestSize.Level1) std::unique_ptr ta = std::make_unique(); ta->EnableMetaTable(false); - ta->SetCleanMode(false); int32_t fd(base::OpenFile(tracePath, O_RDONLY, G_FILE_PERMISSION)); while (true) { std::unique_ptr buf = std::make_unique(readSize); @@ -116,7 +113,6 @@ HWTEST_F(ParserPbreaderTest, BytraceParserTest, TestSize.Level1) ta->WaitForParserEnd(); close(fd); ta->ExportDatabase(dbPath); - ta->Clear(); EXPECT_TRUE(access(dbPath.c_str(), F_OK) == 0); remove(dbPath.c_str()); } else { @@ -132,8 +128,8 @@ HWTEST_F(ParserPbreaderTest, BytraceParserTest, TestSize.Level1) HWTEST_F(ParserPbreaderTest, HtraceAndPerfParserTest, TestSize.Level1) { TS_LOGI("test34-3"); - const std::string tracePath = "data/resource/htrace_perf.bin"; - const std::string dbPath = "data/resource/test34-3_out.db"; + const std::string tracePath = "../../../data/resource/htrace_perf.bin"; + const std::string dbPath = "../../../data/resource/test34-3_out.db"; constexpr size_t readSize = 1024; constexpr uint32_t lineLength = 256; @@ -141,7 +137,6 @@ HWTEST_F(ParserPbreaderTest, HtraceAndPerfParserTest, TestSize.Level1) std::unique_ptr ta = std::make_unique(); ta->EnableMetaTable(false); - ta->SetCleanMode(false); int32_t fd(base::OpenFile(tracePath, O_RDONLY, G_FILE_PERMISSION)); while (true) { std::unique_ptr buf = std::make_unique(readSize); @@ -161,7 +156,6 @@ HWTEST_F(ParserPbreaderTest, HtraceAndPerfParserTest, TestSize.Level1) ta->WaitForParserEnd(); close(fd); ta->ExportDatabase(dbPath); - ta->Clear(); EXPECT_TRUE(access(dbPath.c_str(), F_OK) == 0); remove(dbPath.c_str()); } else { @@ -177,8 +171,8 @@ HWTEST_F(ParserPbreaderTest, HtraceAndPerfParserTest, TestSize.Level1) HWTEST_F(ParserPbreaderTest, HtraceAndEbpfParserTest, TestSize.Level1) { TS_LOGI("test34-4"); - const std::string tracePath = "data/resource/htrace_ebpf.bin"; - const std::string dbPath = "data/resource/test34-4_out.db"; + const std::string tracePath = "../../../data/resource/htrace_ebpf.bin"; + const std::string dbPath = "../../../data/resource/test34-4_out.db"; constexpr size_t readSize = 1024; constexpr uint32_t lineLength = 256; @@ -186,7 +180,6 @@ HWTEST_F(ParserPbreaderTest, HtraceAndEbpfParserTest, TestSize.Level1) std::unique_ptr ta = std::make_unique(); ta->EnableMetaTable(false); - ta->SetCleanMode(false); int32_t fd(base::OpenFile(tracePath, O_RDONLY, G_FILE_PERMISSION)); while (true) { std::unique_ptr buf = std::make_unique(readSize); @@ -206,7 +199,6 @@ HWTEST_F(ParserPbreaderTest, HtraceAndEbpfParserTest, TestSize.Level1) ta->WaitForParserEnd(); close(fd); ta->ExportDatabase(dbPath); - ta->Clear(); EXPECT_TRUE(access(dbPath.c_str(), F_OK) == 0); remove(dbPath.c_str()); } else { diff --git a/trace_streamer/test/unittest/smaps_parser_test.cpp b/trace_streamer/test/unittest/smaps_parser_test.cpp index f775dfbe4..e0594a8ea 100644 --- a/trace_streamer/test/unittest/smaps_parser_test.cpp +++ b/trace_streamer/test/unittest/smaps_parser_test.cpp @@ -41,7 +41,7 @@ public: public: SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; - const std::string dbPath_ = "data/resource/out.db"; + const std::string dbPath_ = "../../../data/resource/out.db"; }; /** * @tc.name: ParseSmapsParse diff --git a/trace_streamer/test/unittest/table_test.cpp b/trace_streamer/test/unittest/table_test.cpp index 5b31eaf13..ad4d00a11 100644 --- a/trace_streamer/test/unittest/table_test.cpp +++ b/trace_streamer/test/unittest/table_test.cpp @@ -303,15 +303,15 @@ HWTEST_F(TableTest, DataDictTableTest, TestSize.Level1) std::string sqlSelect5 = "select * from data_dict where data <= 1"; stream_.traceDataCache_->GetDataFromDict(1); auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); - EXPECT_EQ(row, 59); + EXPECT_EQ(row, 61); row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); EXPECT_EQ(row, 1); row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); - EXPECT_EQ(row, 57); + EXPECT_EQ(row, 59); row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); EXPECT_EQ(row, 1); row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); - EXPECT_EQ(row, 58); + EXPECT_EQ(row, 60); row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); EXPECT_EQ(row, 1); } diff --git a/trace_streamer/test/unittest/task_pool_filter_test.cpp b/trace_streamer/test/unittest/task_pool_filter_test.cpp index f9da3ffe0..fc83cf9d6 100644 --- a/trace_streamer/test/unittest/task_pool_filter_test.cpp +++ b/trace_streamer/test/unittest/task_pool_filter_test.cpp @@ -49,7 +49,6 @@ HWTEST_F(TaskPoolFilterTest, CheckTheSameTaskTest, TestSize.Level1) int32_t executeId = 0; uint32_t res = stream_.streamFilters_->taskPoolFilter_->CheckTheSameTask(executeId); EXPECT_EQ(res, INVALID_INT32); - } /** -- Gitee From c37bb84bbbc4d02ba3b23c965ee6cf60df324756 Mon Sep 17 00:00:00 2001 From: jichuan Date: Thu, 27 Jul 2023 15:07:15 +0800 Subject: [PATCH 09/14] =?UTF-8?q?Feat:Server=E6=94=AF=E6=8C=81Python?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: jichuan --- ide/server/smarperfServer.py | 282 +++++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 ide/server/smarperfServer.py diff --git a/ide/server/smarperfServer.py b/ide/server/smarperfServer.py new file mode 100644 index 000000000..2f30cb886 --- /dev/null +++ b/ide/server/smarperfServer.py @@ -0,0 +1,282 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 http +import json +from datetime import datetime +from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer +import ssl +import os +from urllib.parse import urlparse +import urllib.request +import subprocess +import re +import platform +import webbrowser + +PORT = 9000 +CERT_FILE = './cert/certFile.pem' +KEY_FILE = './cert/keyFile.key' +version = 'v1.0.0' +serveInfo = '' + + +def is_windows(): + return platform.system() == 'Windows' + + +def is_darwin(): + return platform.system() == 'Darwin' + + +def is_linux(): + return platform.system() == 'Linux' + + +def openWeb(url): + webbrowser.open(url) + + +def get_pid_by_port(port_number): + res_pid = -1 + cmd_res = subprocess.run(f"netstat -ano -p tcp | findstr {port_number}", capture_output=True, text=True, + shell=True) + cmd_res_str = cmd_res.stdout + find_str = re.findall(r'\s(\d+)\s', cmd_res_str) + if len(find_str) > 0: + try: + res_pid = int(find_str[0]) + except ValueError: + res_pid = -1 + return res_pid + + +def check_port(port): + if is_windows(): + pid = get_pid_by_port(port) + if pid != -1: + subprocess.run(f"taskkill /F /PID {pid} /T", shell=True) + + +class SpRequestHandler(http.server.BaseHTTPRequestHandler): + global version + global serveInfo + + def log_message(self, format, *args): + return + + def do_GET(self): + parse_result = urlparse(self.path) + if parse_result.path == '/application/serverInfo': + self.serverInfo_handler() + elif parse_result.path.startswith('/application'): + self.application_handler(parse_result) + else: + self.send_error(404, 'Not found') + + def do_POST(self): + parse_result = urlparse(self.path) + if parse_result.path.startswith('/logger'): + self.console_handler() + elif parse_result.path.startswith('/upload'): + print(f'upload') + + elif parse_result.path.startswith('/download-file'): + print(f'download-file') + self.download_handler() + + def download_handler(self): + self.clear_overdue_file() + content_type = self.headers.get("Content-Type") + if content_type and content_type.startswith("application/x-www-form-urlencoded"): + url = self.post_form_value("url") + try: + req = urllib.request.Request(url) + response = urllib.request.urlopen(req) + content = response.read().decode("utf-8") + except Exception as e: + self.send_response(200) + response = {"success": False, "code": -1, "message": str(e), "data": None} + self.wfile.write(bytes(json.dumps(response), "utf-8")) + return + suffixStr = os.path.splitext(url.split("/")[-1])[1] + file_name = f"upload/{datetime.now().strftime('%Y%m%d%H%M%S%f')}{suffixStr}" + os.makedirs(os.path.dirname(file_name), exist_ok=True) + try: + with open(file_name, "wb") as f: + f.write(content) + written = f.tell() + except Exception as e: + self.send_response(200) + response = {"success": False, "code": -1, "message": str(e), "data": None} + self.wfile.write(bytes(json.dumps(response), "utf-8")) + return + self.send_response(200) + response = {"success": True, "code": 0, "message": "success", "data": {"url": file_name, "size": written}} + self.wfile.write(bytes(json.dumps(response), "utf-8")) + return + + def post_form_value(self, key): + content_length = int(self.headers.get("Content-Length", 0)) + post_data = self.rfile.read(content_length).decode("utf-8") + for param in post_data.split("&"): + param_key, param_value = param.split("=") + if param_key == key: + return param_value + return "" + + def clear_overdue_file(self): + path = "./upload/" + upload_dir = os.path.dirname(os.path.normpath(path)) + if not os.path.exists(upload_dir): + os.makedirs(upload_dir) + now = datetime.now() + for root, dirs, files in os.walk(path): + for file_name in files: + file_path = os.path.join(root, file_name) + if self.check_due(file_name): + print(f"{now} delete -> {file_path}") + os.remove(file_path) + + def check_due(self, file_name): + now = datetime.now() + datetime_str = os.path.splitext(os.path.basename(file_name))[0] + fileDate = datetime.strptime(datetime_str, "%Y%m%d%H%M%S%f") + return (now - fileDate).total_seconds() > 3600 + + def console_handler(self): + self.check_dir('./logger') + nowDate = datetime.now() + now = nowDate.strftime("%Y-%m-%d") + fileName = f"{now}.txt" + dst = open("./logger/" + fileName, "a") + content_type = self.headers.get("Content-Type") + if content_type and content_type.startswith("application/json"): + content_length = int(self.headers.get("Content-Length", 0)) + req_data = self.rfile.read(content_length) + req = json.loads(req_data) + now = datetime.now() + formatted_date = now.strftime("%Y-%m-%d %H:%M:%S") + dst.write(f"{formatted_date} {req['fileName']} ({req['fileSize']} M)\n") + self.send_response(200) + self.send_header("Content-type", "text/html") + self.end_headers() + self.wfile.write(bytes(f"日志写入成功", "utf-8")) + + def check_dir(self, dir_path): + if not os.path.exists(dir_path): + os.makedirs(dir_path) + + def application_handler(self, parse_result): + file_path = parse_result.path[12:] + file_extension = os.path.splitext(file_path)[1] + if file_path == '/' or file_path == '': + file_path = './index.html' + file_extension = '.html' + else: + file_path = '.' + file_path + try: + with open(file_path, 'rb') as file: + content = file.read() + self.send_response(200) + self.send_header('Content-type', get_content_type(file_extension)) + self.send_header("Cross-Origin-Opener-Policy", "same-origin") + self.send_header("Cross-Origin-Embedder-Policy", "require-corp") + self.send_header("Access-Control-Allow-Origin", "*") + self.send_header("Access-Control-Allow-Credentials", "true") + self.send_header("Access-Control-Allow-Headers", "x-requested-with, authorization, blade-auth") + self.send_header("Access-Control-Allow-Methods", "*") + self.send_header("Access-Control-Max-Age", "3600") + self.send_header("data-version", version) + self.end_headers() + self.wfile.write(content) + except FileNotFoundError: + self.send_error(404, 'File not found') + + def serverInfo_handler(self): + self.send_response(200) + self.send_header("Access-Control-Allow-Origin", "*") + self.send_header("request_info", serveInfo) + self.end_headers() + + +def read_text(read_file_path): + try: + with open(read_file_path, 'r') as file: + content = file.read() + return content + except IOError: + return None + + +def get_content_type(file_extension): + if file_extension == '.js': + return 'application/javascript' + if file_extension == '.wasm': + return 'application/wasm' + if file_extension == '.json': + return 'application/json' + if file_extension == '.html': + return 'text/html' + if file_extension == '.svg': + return 'image/svg+xml' + return 'text/plain' + +def gen_ssl(cert_file, key_file): + serial_number = 123456789 + organization = "www.smartperf.com" + organizational_unit = "ITs" + common_name = "www.smartperf.com" + validity_days = 3650 + subprocess.run(["openssl", "genpkey", "-algorithm", "RSA", "-out", key_file]) + csr_file = "cert/cert.csr" + subprocess.run(["openssl", "req", "-new", "-key", key_file, "-out", csr_file, "-subj", + "/O={}/OU={}/CN={}".format(organization, organizational_unit, common_name)]) + subprocess.run(["openssl", "x509", "-req", "-days", str(validity_days), "-in", csr_file, "-signkey", + key_file, "-out", cert_file, "-set_serial", str(serial_number)]) + +class SpServer: + def __init__(self, server_address, cert_file_path, keyfile_path): + global version + global serveInfo + version = read_text('version.txt') + serveInfo = read_text('server-config.txt') + self.server_address = server_address + self.context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) + self.context.load_cert_chain(cert_file_path, keyfile_path) + self.httpd = ThreadingHTTPServer(server_address, SpRequestHandler) + self.httpd.socket = self.context.wrap_socket(self.httpd.socket, True) + + def start(self): + print(f'HTTPS[{PORT}] SmartPerf Server Start') + if is_windows(): + openWeb("https://127.0.0.1:9000/application/") + self.httpd.serve_forever() + + +def main(): + check_port(PORT) + if not os.path.exists(CERT_FILE) or not os.path.exists(KEY_FILE): + if is_linux(): + if not os.path.exists('./cert'): + os.makedirs('./cert') + gen_ssl(CERT_FILE, KEY_FILE) + server_address = ('', PORT) + server = SpServer(server_address, CERT_FILE, KEY_FILE) + server.start() + + +if __name__ == '__main__': + main() -- Gitee From 94b998d0bf196af2fdd851b885d29b92a0bdef92 Mon Sep 17 00:00:00 2001 From: jichuan Date: Thu, 27 Jul 2023 15:07:53 +0800 Subject: [PATCH 10/14] add arkTs func Signed-off-by: jichuan --- trace_streamer/build/make_standard_proto.py | 2 - trace_streamer/build_operator.sh | 5 +- trace_streamer/sdk/demo_sdk/sdk/ts.gni | 11 --- trace_streamer/sdk/demo_sdk/ts.gni | 11 --- trace_streamer/sdk/dubai_sdk/sdk/ts.gni | 13 --- trace_streamer/sdk/dubai_sdk/ts.gni | 13 --- trace_streamer/src/base/file.cpp | 2 +- .../src/filter/app_start_filter.cpp | 60 ++++++------- trace_streamer/src/filter/app_start_filter.h | 2 +- .../src/filter/native_hook_filter.cpp | 8 +- .../src/filter/task_pool_filter.cpp | 84 +++++++++++-------- trace_streamer/src/filter/task_pool_filter.h | 11 +-- trace_streamer/src/main.cpp | 10 +-- .../htrace_event_parser.cpp | 2 +- .../htrace_js_cpu_profiler_parser.cpp | 6 +- .../native_hook/native_hook_result.proto | 1 + trace_streamer/src/rpc/rpc_server.cpp | 4 +- .../src/table/ftrace/dynamic_frame_table.cpp | 1 - .../src/table/ftrace/task_pool_table.cpp | 30 +++---- .../native_hook_statistic_table.cpp | 20 ++++- .../src/trace_data/trace_stdtype.cpp | 58 +++++++------ trace_streamer/src/trace_data/trace_stdtype.h | 39 +++++---- trace_streamer/src/version.cpp | 4 +- trace_streamer/src/version.h | 4 +- 24 files changed, 200 insertions(+), 201 deletions(-) diff --git a/trace_streamer/build/make_standard_proto.py b/trace_streamer/build/make_standard_proto.py index ba5e57398..c4d0b60f5 100755 --- a/trace_streamer/build/make_standard_proto.py +++ b/trace_streamer/build/make_standard_proto.py @@ -19,9 +19,7 @@ import shutil def replace_lite_option(target_path, protofilepath): target_file_path = os.path.basename(protofilepath) target_file_path = target_path + '/' + target_file_path.replace(".proto", "_standard.proto") - # print("-------",target_path, target_file_path, protofilepath) os.makedirs(target_path, exist_ok=True) - # os.makedirs(target_path) shutil.copyfile(protofilepath, target_file_path) # replease lite flag, import file name, add package name with open(target_file_path, 'r+') as content: diff --git a/trace_streamer/build_operator.sh b/trace_streamer/build_operator.sh index 61a819efb..d2c74135f 100755 --- a/trace_streamer/build_operator.sh +++ b/trace_streamer/build_operator.sh @@ -63,9 +63,6 @@ fi if [ "$is_debug" != "false" ];then ext="_debug" fi -if [ ! -d "third_party/protogen" ] && [ "$target" != "spb" ] && [ "$target" != "protoc" ];then - ./src/protos/protogen.sh -fi if [ "$target" == "test" ] || [ "$target" == "fuzz" ] || [ "$target"="wasm" ] || [ "$target"="sdkdemo" ] || [ "$target"="sdkdemotest" ];then target_dir=$target @@ -77,7 +74,7 @@ if [ "$target" == "trace_streamer" ] || [ "$target" == "trace" ] || [ "$target" fi echo "target_dir:" $target_dir echo "target:" $target -# exit + if [ "$is_clean" == "true" ];then prebuilts/$gn_path/$gn gen out/"$target_dir""$ext"/$clang_dir/$subsys_name/$part_name --clean prebuilts/$gn_path/$ninja -C out/"$target_dir""$ext"/$clang_dir/$subsys_name/$part_name -t clean diff --git a/trace_streamer/sdk/demo_sdk/sdk/ts.gni b/trace_streamer/sdk/demo_sdk/sdk/ts.gni index 162797728..ca2553f28 100755 --- a/trace_streamer/sdk/demo_sdk/sdk/ts.gni +++ b/trace_streamer/sdk/demo_sdk/sdk/ts.gni @@ -13,22 +13,11 @@ OHOS_PROTO_DIR = "" if (target_os == "linux" || target_os == "macx" || target_os == "windows") { - # 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" diff --git a/trace_streamer/sdk/demo_sdk/ts.gni b/trace_streamer/sdk/demo_sdk/ts.gni index 162797728..ca2553f28 100755 --- a/trace_streamer/sdk/demo_sdk/ts.gni +++ b/trace_streamer/sdk/demo_sdk/ts.gni @@ -13,22 +13,11 @@ OHOS_PROTO_DIR = "" if (target_os == "linux" || target_os == "macx" || target_os == "windows") { - # 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" diff --git a/trace_streamer/sdk/dubai_sdk/sdk/ts.gni b/trace_streamer/sdk/dubai_sdk/sdk/ts.gni index 162797728..e4556dcb4 100755 --- a/trace_streamer/sdk/dubai_sdk/sdk/ts.gni +++ b/trace_streamer/sdk/dubai_sdk/sdk/ts.gni @@ -13,26 +13,13 @@ OHOS_PROTO_DIR = "" if (target_os == "linux" || target_os == "macx" || target_os == "windows") { - # 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" - - # kernel_version = "5.10.79_aarch64" kernel_version = "." if (target == "test") { enable_ts_utest = true diff --git a/trace_streamer/sdk/dubai_sdk/ts.gni b/trace_streamer/sdk/dubai_sdk/ts.gni index 162797728..e4556dcb4 100755 --- a/trace_streamer/sdk/dubai_sdk/ts.gni +++ b/trace_streamer/sdk/dubai_sdk/ts.gni @@ -13,26 +13,13 @@ OHOS_PROTO_DIR = "" if (target_os == "linux" || target_os == "macx" || target_os == "windows") { - # 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" - - # kernel_version = "5.10.79_aarch64" kernel_version = "." if (target == "test") { enable_ts_utest = true diff --git a/trace_streamer/src/base/file.cpp b/trace_streamer/src/base/file.cpp index 582f04d9d..b4d9feca8 100644 --- a/trace_streamer/src/base/file.cpp +++ b/trace_streamer/src/base/file.cpp @@ -70,7 +70,7 @@ std::string GetExecutionDirectoryPath() ::GetModuleFileNameA(NULL, currPath, MAX_PATH); (strrchr(currPath, '\\'))[1] = 0; #else - readlink("/proc/self/exe", currPath, sizeof(currPath) - 1); + (void)readlink("/proc/self/exe", currPath, sizeof(currPath) - 1); #endif std::string str(currPath); return str.substr(0, str.find_last_of('/')); diff --git a/trace_streamer/src/filter/app_start_filter.cpp b/trace_streamer/src/filter/app_start_filter.cpp index 39828c59d..9c3d1d404 100644 --- a/trace_streamer/src/filter/app_start_filter.cpp +++ b/trace_streamer/src/filter/app_start_filter.cpp @@ -63,34 +63,34 @@ bool APPStartupFilter::CaclRsDataByPid(appMap& mAPPStartupData) continue; } auto itorSecond = item.second.begin(); - auto dataIndex = item.first; - if (itorSecond->second->ipid_ != INVALID_UINT32) { - for (int m = 0; m < frameSliceData->Ipids().size(); m++) { - if (itorSecond->second->ipid_ == frameSliceData->Ipids()[m] && !frameSliceData->Types()[m] && - frameSliceData->Flags()[m] != INVAILD_DATA) { - auto startTime = sliceData.TimeStampData()[frameSliceData->CallStackIds()[m]]; - auto callId = sliceData.CallIds()[frameSliceData->CallStackIds()[m]]; - auto endTime = startTime + frameSliceData->Durs()[m]; - if (frameSliceData->Durs()[m] == INVALID_UINT64) { - endTime = INVALID_UINT64; - } - mAPPStartupData[dataIndex].emplace( - FIRST_FRAME_APP_PHASE, - std::make_unique(callId, itorSecond->second->ipid_, itorSecond->second->tid_, - startTime, endTime)); - auto dstId = frameSliceData->Dsts()[m]; - if (dstId == INVALID_UINT64) { - continue; - } - callId = sliceData.CallIds()[frameSliceData->CallStackIds()[dstId]]; - startTime = frameSliceData->TimeStampData()[dstId]; - endTime = startTime + frameSliceData->Durs()[dstId]; - mAPPStartupData[dataIndex].emplace( - FIRST_FRAME_RENDER_PHASE, - std::make_unique(callId, itorSecond->second->ipid_, itorSecond->second->tid_, - startTime, endTime)); - break; + if (itorSecond->second->ipid_ == INVALID_UINT32) { + continue; + } + for (int m = 0; m < frameSliceData->Ipids().size(); m++) { + if (itorSecond->second->ipid_ == frameSliceData->Ipids()[m] && !frameSliceData->Types()[m] && + frameSliceData->Flags()[m] != INVAILD_DATA) { + auto startTime = sliceData.TimeStampData()[frameSliceData->CallStackIds()[m]]; + auto callId = sliceData.CallIds()[frameSliceData->CallStackIds()[m]]; + auto endTime = startTime + frameSliceData->Durs()[m]; + if (frameSliceData->Durs()[m] == INVALID_UINT64) { + endTime = INVALID_UINT64; + } + mAPPStartupData[item.first].emplace(FIRST_FRAME_APP_PHASE, + std::make_unique(callId, itorSecond->second->ipid_, + itorSecond->second->tid_, + startTime, endTime)); + auto dstId = frameSliceData->Dsts()[m]; + if (dstId == INVALID_UINT64) { + continue; } + callId = sliceData.CallIds()[frameSliceData->CallStackIds()[dstId]]; + startTime = frameSliceData->TimeStampData()[dstId]; + endTime = startTime + frameSliceData->Durs()[dstId]; + mAPPStartupData[item.first].emplace(FIRST_FRAME_RENDER_PHASE, + std::make_unique(callId, itorSecond->second->ipid_, + itorSecond->second->tid_, + startTime, endTime)); + break; } } } @@ -149,7 +149,7 @@ void APPStartupFilter::UpdateAPPStartupData(uint32_t row, const std::string& nam { auto sliceData = traceDataCache_->GetConstInternalSlicesData(); auto vNameString = SplitStringToVec(nameString, "##"); - if (vNameString.size() < MIN_VECTOR_SIZE_) { + if (vNameString.size() < MIN_VECTOR_SIZE) { return; } auto dataIndex = traceDataCache_->GetDataIndex(vNameString[1].c_str()); @@ -171,7 +171,7 @@ void APPStartupFilter::ParserAppStartup() auto& nameString = traceDataCache_->GetDataFromDict(sliceData.NamesData()[i]); if (StartWith(nameString, PROCESS_CREATE)) { auto vNameString = SplitStringToVec(nameString, "##"); - if (vNameString.size() >= MIN_VECTOR_SIZE_) { + if (vNameString.size() >= MIN_VECTOR_SIZE) { mainThreadName = vNameString[1]; } if (!sliceData.ParentIdData()[i].has_value()) { @@ -191,7 +191,7 @@ void APPStartupFilter::ParserAppStartup() } else if (StartWith(nameString, LAUNCH)) { auto sliceData = traceDataCache_->GetConstInternalSlicesData(); auto vNameString = SplitStringToVec(nameString, "##"); - if (vNameString.size() < MIN_VECTOR_SIZE_) { + if (vNameString.size() < MIN_VECTOR_SIZE) { continue; } auto dataIndex = traceDataCache_->GetDataIndex(vNameString[1].c_str()); diff --git a/trace_streamer/src/filter/app_start_filter.h b/trace_streamer/src/filter/app_start_filter.h index cc5d4d8a4..ac962f494 100644 --- a/trace_streamer/src/filter/app_start_filter.h +++ b/trace_streamer/src/filter/app_start_filter.h @@ -26,7 +26,7 @@ namespace SysTuning { namespace TraceStreamer { constexpr uint32_t INVAILD_DATA = 2; -constexpr uint32_t MIN_VECTOR_SIZE_ = 2; +constexpr uint32_t MIN_VECTOR_SIZE = 2; constexpr uint32_t VAILD_DATA_COUNT = 4; const std::string PROCESS_CREATE = "H:int OHOS::AAFwk::MissionListManager::StartAbilityLocked("; const std::string START_ABILITY = "H:virtual int OHOS::AAFwk::AbilityManagerService::StartAbility("; diff --git a/trace_streamer/src/filter/native_hook_filter.cpp b/trace_streamer/src/filter/native_hook_filter.cpp index f19d0f39a..03c32eabc 100644 --- a/trace_streamer/src/filter/native_hook_filter.cpp +++ b/trace_streamer/src/filter/native_hook_filter.cpp @@ -167,9 +167,13 @@ void NativeHookFilter::ParseStatisticEvent(uint64_t timeStamp, const ProtoReader callChainId = reader.callstack_id(); } + DataIndex memSubType = INVALID_UINT64; + if (reader.has_tag_name()) { + memSubType = traceDataCache_->GetDataIndex(reader.tag_name().ToStdString()); + } traceDataCache_->GetNativeHookStatisticsData()->AppendNewNativeHookStatistic( - ipid_, timeStamp, callChainId, reader.type(), reader.apply_count(), reader.release_count(), reader.apply_size(), - reader.release_size()); + ipid_, timeStamp, callChainId, reader.type(), memSubType, reader.apply_count(), reader.release_count(), + reader.apply_size(), reader.release_size()); } void NativeHookFilter::ParseAllocEvent(uint64_t timeStamp, const ProtoReader::BytesView& bytesView) { diff --git a/trace_streamer/src/filter/task_pool_filter.cpp b/trace_streamer/src/filter/task_pool_filter.cpp index da4f75289..95cdcbfd3 100644 --- a/trace_streamer/src/filter/task_pool_filter.cpp +++ b/trace_streamer/src/filter/task_pool_filter.cpp @@ -22,17 +22,27 @@ namespace TraceStreamer { const uint32_t EXECUTE_DATA_FLAG = 2; TaskPoolFilter::TaskPoolFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) - : FilterBase(dataCache, filter) + : FilterBase(dataCache, filter), IpidExecuteMap_(INVALID_INT32) { } TaskPoolFilter::~TaskPoolFilter() = default; -uint32_t TaskPoolFilter::CheckTheSameTask(int32_t executeId) +uint32_t TaskPoolFilter::GetIpId(uint32_t index) { - if (executeMap_.count(executeId)) { - return executeMap_[executeId]; + if (index >= traceDataCache_->GetConstInternalSlicesData().CallIds().size()) { + return INVALID_UINT32; } - return INVALID_INT32; + auto itid = traceDataCache_->GetConstInternalSlicesData().CallIds()[index]; + auto thread = traceDataCache_->GetThreadData(itid); + if (!thread) { + return INVALID_UINT32; + } + return thread->internalPid_; +} + +uint32_t TaskPoolFilter::CheckTheSameTask(int32_t executeId, uint32_t index) +{ + return IpidExecuteMap_.Find(GetIpId(index), executeId); } void TaskPoolFilter::TaskPoolFieldSegmentation(const std::string& taskPoolStr, @@ -61,80 +71,84 @@ bool TaskPoolFilter::TaskPoolEvent(const std::string& taskPoolStr, int32_t index if (StartWith(taskPoolStr, allocationStr)) { allocationStr = taskPoolStr.substr(allocationStr.length(), taskPoolStr.length()); TaskPoolFieldSegmentation(allocationStr, args); - UpdateAssignData(args, index); - return true; + return UpdateAssignData(args, index); } std::string executeStr = "H:Task Perform: "; if (StartWith(taskPoolStr, executeStr)) { executeStr = taskPoolStr.substr(executeStr.length(), taskPoolStr.length()); TaskPoolFieldSegmentation(executeStr, args); - UpdateExecuteData(args, index); - return true; + return UpdateExecuteData(args, index); } std::string returnStr = "H:Task PerformTask End: "; if (StartWith(taskPoolStr, returnStr)) { returnStr = taskPoolStr.substr(returnStr.length(), taskPoolStr.length()); TaskPoolFieldSegmentation(returnStr, args); - UpdateReturnData(args, index); - return true; + return UpdateReturnData(args, index); } } return false; } -void TaskPoolFilter::UpdateAssignData(const std::unordered_map& args, int32_t index) +bool TaskPoolFilter::UpdateAssignData(const std::unordered_map& args, int32_t index) { - auto assignTaskId = base::StrToInt(args.at("taskId ")); + if (index >= traceDataCache_->GetConstInternalSlicesData().CallIds().size()) { + return false; + } + auto allocItid = traceDataCache_->GetConstInternalSlicesData().CallIds()[index]; auto executeId = base::StrToInt(args.at(" executeId ")); auto priority = base::StrToInt(args.at(" priority ")); auto executeState = base::StrToInt(args.at(" executeState ")); - int32_t returnValue = CheckTheSameTask(executeId.value()); + int32_t returnValue = CheckTheSameTask(executeId.value(), index); if (returnValue == INVALID_INT32) { int32_t taskIndex = traceDataCache_->GetTaskPoolData()->AppendAllocationTaskData( - index, assignTaskId.value(), executeId.value(), priority.value(), executeState.value()); - executeMap_.emplace(executeId.value(), taskIndex); + index, allocItid, executeId.value(), priority.value(), executeState.value()); + IpidExecuteMap_.Insert(GetIpId(index), executeId.value(), taskIndex); } else { - traceDataCache_->GetTaskPoolData()->UpdateAllocationTaskData(returnValue, index, assignTaskId.value(), + traceDataCache_->GetTaskPoolData()->UpdateAllocationTaskData(returnValue, index, allocItid, priority.value(), executeState.value()); } + return true; } -void TaskPoolFilter::UpdateExecuteData(const std::unordered_map& args, int32_t index) +bool TaskPoolFilter::UpdateExecuteData(const std::unordered_map& args, int32_t index) { - auto executeTaskId = base::StrToInt(args.at("taskId ")); + if (index >= traceDataCache_->GetConstInternalSlicesData().CallIds().size()) { + return false; + } + auto executeItid = traceDataCache_->GetConstInternalSlicesData().CallIds()[index]; auto executeId = base::StrToInt(args.at(" executeId ")); - int32_t returnValue = CheckTheSameTask(executeId.value()); + int32_t returnValue = CheckTheSameTask(executeId.value(), index); if (returnValue == INVALID_INT32) { int32_t taskIndex = - traceDataCache_->GetTaskPoolData()->AppendExecuteTaskData(index, executeTaskId.value(), executeId.value()); - executeMap_.emplace(executeId.value(), taskIndex); + traceDataCache_->GetTaskPoolData()->AppendExecuteTaskData(index, executeItid, executeId.value()); + IpidExecuteMap_.Insert(GetIpId(index), executeId.value(), taskIndex); } else { - traceDataCache_->GetTaskPoolData()->UpdateExecuteTaskData(returnValue, index, executeTaskId.value()); + traceDataCache_->GetTaskPoolData()->UpdateExecuteTaskData(returnValue, index, executeItid); } + return true; } -void TaskPoolFilter::UpdateReturnData(const std::unordered_map& args, int32_t index) +bool TaskPoolFilter::UpdateReturnData(const std::unordered_map& args, int32_t index) { - int32_t returnState; - auto returnTaskId = base::StrToInt(args.at("taskId ")); + if (index >= traceDataCache_->GetConstInternalSlicesData().CallIds().size()) { + return false; + } + auto returnItid = traceDataCache_->GetConstInternalSlicesData().CallIds()[index]; auto executeId = base::StrToInt(args.at(" executeId ")); auto returnStr = std::string_view(args.at(" performResult ")); - if (!returnStr.compare(" Successful")) { - returnState = 1; - } else { - returnState = 0; - } + int32_t returnState = returnStr.compare(" Successful") ? 0 : 1; - int32_t returnValue = CheckTheSameTask(executeId.value()); + int32_t returnValue = CheckTheSameTask(executeId.value(), index); if (returnValue == INVALID_INT32) { - int32_t taskIndex = traceDataCache_->GetTaskPoolData()->AppendReturnTaskData(index, returnTaskId.value(), + int32_t taskIndex = traceDataCache_->GetTaskPoolData()->AppendReturnTaskData(index, returnItid, executeId.value(), returnState); - executeMap_.emplace(executeId.value(), taskIndex); + IpidExecuteMap_.Insert(GetIpId(index), executeId.value(), taskIndex); } else { - traceDataCache_->GetTaskPoolData()->UpdateReturnTaskData(returnValue, index, returnTaskId.value(), returnState); + traceDataCache_->GetTaskPoolData()->UpdateReturnTaskData(returnValue, index, returnItid, returnState); } + return true; } } // namespace TraceStreamer diff --git a/trace_streamer/src/filter/task_pool_filter.h b/trace_streamer/src/filter/task_pool_filter.h index 2b0a8b323..1af5cf585 100644 --- a/trace_streamer/src/filter/task_pool_filter.h +++ b/trace_streamer/src/filter/task_pool_filter.h @@ -32,15 +32,16 @@ public: TaskPoolFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter); TaskPoolFilter(const TaskPoolFilter&) = delete; ~TaskPoolFilter() override; - uint32_t CheckTheSameTask(int32_t executeId); + uint32_t GetIpId(uint32_t index); + uint32_t CheckTheSameTask(int32_t executeId, uint32_t index); bool TaskPoolEvent(const std::string& taskPoolStr, int32_t index); void TaskPoolFieldSegmentation(const std::string& taskPoolStr, std::unordered_map& args); - void UpdateAssignData(const std::unordered_map& args, int32_t index); - void UpdateExecuteData(const std::unordered_map& args, int32_t index); - void UpdateReturnData(const std::unordered_map& args, int32_t index); + bool UpdateAssignData(const std::unordered_map& args, int32_t index); + bool UpdateExecuteData(const std::unordered_map& args, int32_t index); + bool UpdateReturnData(const std::unordered_map& args, int32_t index); private: - std::unordered_map executeMap_ = {}; + DoubleMap IpidExecuteMap_; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/main.cpp b/trace_streamer/src/main.cpp index 1f78dedff..425a30415 100644 --- a/trace_streamer/src/main.cpp +++ b/trace_streamer/src/main.cpp @@ -88,7 +88,7 @@ void PrintInformation() } void PrintVersion() { - fprintf(stderr, "version %s\n", TRACE_STREAM_VERSION.c_str()); + fprintf(stderr, "version %s\n", g_traceStreamerVersion.c_str()); } void LoadQueryFile(const std::string& sqlOperator, std::vector& sqlStrings) @@ -203,8 +203,8 @@ int ExportDatabase(TraceStreamerSelector& ts, const std::string& sqliteFilePath) } #endif metaData->SetOutputFileName(fileNameTmp); - metaData->SetParserToolVersion(TRACE_STREAM_VERSION); - metaData->SetParserToolPublishDateTime(TRACE_STREAM_PUBLISHVERSION); + metaData->SetParserToolVersion(g_traceStreamerVersion); + metaData->SetParserToolPublishDateTime(g_traceStreamerPublishVersion); metaData->SetTraceDataSize(g_loadSize); fprintf(stdout, "ExportDatabase begin...\n"); if (ts.ExportDatabase(sqliteFilePath)) { @@ -330,8 +330,8 @@ int main(int argc, char** argv) if (tsOption.interactiveState) { MetaData* metaData = ts.GetMetaData(); metaData->SetOutputFileName("command line mode"); - metaData->SetParserToolVersion(TRACE_STREAM_VERSION.c_str()); - metaData->SetParserToolPublishDateTime(TRACE_STREAM_PUBLISHVERSION.c_str()); + metaData->SetParserToolVersion(g_traceStreamerVersion.c_str()); + metaData->SetParserToolPublishDateTime(g_traceStreamerPublishVersion.c_str()); metaData->SetTraceDataSize(g_loadSize); while (1) { auto values = ts.SearchData(); diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_event_parser/htrace_event_parser.cpp b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_event_parser/htrace_event_parser.cpp index b228be926..098aa5366 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_event_parser/htrace_event_parser.cpp +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_event_parser/htrace_event_parser.cpp @@ -164,7 +164,7 @@ void HtraceEventParser::ParseDataItem(HtraceDataSegment& tracePacket, BuiltinClo lastOverwrite_ = msg.overwrite(); } if (lastOverwrite_ != msg.overwrite()) { - TS_LOGW("lost events:%llu", msg.overwrite() - lastOverwrite_); + TS_LOGW("lost events:%lu", msg.overwrite() - lastOverwrite_); lastOverwrite_ = msg.overwrite(); } streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_LOST); diff --git a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_cpu_profiler_parser.cpp b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_cpu_profiler_parser.cpp index 37fc4cc69..cd35c6f66 100644 --- a/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_cpu_profiler_parser.cpp +++ b/trace_streamer/src/parser/htrace_pbreader_parser/htrace_js_cpu_profiler_parser.cpp @@ -107,8 +107,10 @@ void HtraceJsCpuProfilerParser::ParseJsCpuProfiler(std::string result) } else if (sample == std::numeric_limits::max()) { sample = jMessage.at("samples")[0]; } - uint32_t timeDeltas = jMessage.at("timeDeltas")[i]; - sampleEndTime += timeDeltas; + if (i + 1 < jMessage.at("timeDeltas").size()) { + uint32_t timeDeltas = jMessage.at("timeDeltas")[i + 1]; + sampleEndTime += timeDeltas; + } } dur = (sampleEndTime * TIME_SECOND_COVER) - (startTime * TIME_SECOND_COVER); (void)traceDataCache_->GetJsCpuProfilerSampleData()->AppendNewData(sample, startTime * TIME_SECOND_COVER, diff --git a/trace_streamer/src/protos/types/plugins/native_hook/native_hook_result.proto b/trace_streamer/src/protos/types/plugins/native_hook/native_hook_result.proto index 578e5ad21..bff0ad0a3 100755 --- a/trace_streamer/src/protos/types/plugins/native_hook/native_hook_result.proto +++ b/trace_streamer/src/protos/types/plugins/native_hook/native_hook_result.proto @@ -131,6 +131,7 @@ message RecordStatisticsEvent { uint64 release_count = 5; uint64 apply_size = 6; uint64 release_size = 7; + string tag_name = 8; } message NativeHookData { diff --git a/trace_streamer/src/rpc/rpc_server.cpp b/trace_streamer/src/rpc/rpc_server.cpp index 7b66cfd84..85dfb2a7b 100644 --- a/trace_streamer/src/rpc/rpc_server.cpp +++ b/trace_streamer/src/rpc/rpc_server.cpp @@ -92,8 +92,8 @@ bool RpcServer::ParseDataOver(const uint8_t* data, size_t len, ResultCallBack re MetaData* metaData = ts_->GetMetaData(); metaData->SetSourceFileName("input stream mode"); metaData->SetOutputFileName("wasm mode"); - metaData->SetParserToolVersion(TRACE_STREAM_VERSION); - metaData->SetParserToolPublishDateTime(TRACE_STREAM_PUBLISHVERSION); + metaData->SetParserToolVersion(g_traceStreamerVersion); + metaData->SetParserToolPublishDateTime(g_traceStreamerPublishVersion); metaData->SetTraceDataSize(g_loadSize); metaData->SetTraceType((ts_->DataType() == TRACE_FILETYPE_H_TRACE) ? "proto-based-trace" : "txt-based-trace"); TS_LOGI("RPC ParseDataOver, has parsed len %zu", lenParseData_); diff --git a/trace_streamer/src/table/ftrace/dynamic_frame_table.cpp b/trace_streamer/src/table/ftrace/dynamic_frame_table.cpp index 9fa134a37..16c439e50 100644 --- a/trace_streamer/src/table/ftrace/dynamic_frame_table.cpp +++ b/trace_streamer/src/table/ftrace/dynamic_frame_table.cpp @@ -195,7 +195,6 @@ int32_t DynamicFrameTable::Cursor::Column(int32_t col) const dataCache_->GetDataFromDict(static_cast(dynamicFrameObj_.Alphas()[CurrentRow()])); sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr); } - break; } case NAME: { diff --git a/trace_streamer/src/table/ftrace/task_pool_table.cpp b/trace_streamer/src/table/ftrace/task_pool_table.cpp index 0e8c287a5..2990bbf38 100644 --- a/trace_streamer/src/table/ftrace/task_pool_table.cpp +++ b/trace_streamer/src/table/ftrace/task_pool_table.cpp @@ -22,9 +22,9 @@ enum Index { ALLOCATION_TASK_ROW, EXECUTE_TASK_ROW, RETURN_TASK_ROW, - ALLOCATION_TASK_ID, - EXECUTE_TASK_ID, - RETURN_TASK_ID, + ALLOCATION_ITID, + EXECUTE_ITID, + RETURN_ITID, EXECUTE_ID, PRIORITY, EXECUTE_STATE, @@ -36,9 +36,9 @@ TaskPoolTable::TaskPoolTable(const TraceDataCache* dataCache) : TableBase(dataCa tableColumn_.push_back(TableBase::ColumnInfo("allocation_task_row", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("execute_task_row", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("return_task_row", "INTEGER")); - tableColumn_.push_back(TableBase::ColumnInfo("allocation_task_id", "INTEGER")); - tableColumn_.push_back(TableBase::ColumnInfo("execute_task_id", "INTEGER")); - tableColumn_.push_back(TableBase::ColumnInfo("return_task_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("allocation_itid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("execute_itid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("return_itid", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("execute_id", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("priority", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("execute_state", "INTEGER")); @@ -86,23 +86,23 @@ int32_t TaskPoolTable::Cursor::Column(int32_t column) const dataCache_->GetConstTaskPoolData().ReturnTaskRows()[CurrentRow()])); } break; - case ALLOCATION_TASK_ID: - if (taskPoolObj_.AllocationTaskIds()[CurrentRow()] != INVALID_INT32) { + case ALLOCATION_ITID: + if (taskPoolObj_.AllocationItids()[CurrentRow()] != INVALID_INT32) { sqlite3_result_int64( context_, - static_cast(dataCache_->GetConstTaskPoolData().AllocationTaskIds()[CurrentRow()])); + static_cast(dataCache_->GetConstTaskPoolData().AllocationItids()[CurrentRow()])); } break; - case EXECUTE_TASK_ID: - if (taskPoolObj_.ExecuteTaskIds()[CurrentRow()] != INVALID_INT32) { + case EXECUTE_ITID: + if (taskPoolObj_.ExecuteItids()[CurrentRow()] != INVALID_INT32) { sqlite3_result_int64(context_, static_cast( - dataCache_->GetConstTaskPoolData().ExecuteTaskIds()[CurrentRow()])); + dataCache_->GetConstTaskPoolData().ExecuteItids()[CurrentRow()])); } break; - case RETURN_TASK_ID: - if (taskPoolObj_.ReturnTaskIds()[CurrentRow()] != INVALID_INT32) { + case RETURN_ITID: + if (taskPoolObj_.ReturnItids()[CurrentRow()] != INVALID_INT32) { sqlite3_result_int64(context_, static_cast( - dataCache_->GetConstTaskPoolData().ReturnTaskIds()[CurrentRow()])); + dataCache_->GetConstTaskPoolData().ReturnItids()[CurrentRow()])); } break; case EXECUTE_ID: diff --git a/trace_streamer/src/table/native_hook/native_hook_statistic_table.cpp b/trace_streamer/src/table/native_hook/native_hook_statistic_table.cpp index 1fc653768..d70c5669d 100644 --- a/trace_streamer/src/table/native_hook/native_hook_statistic_table.cpp +++ b/trace_streamer/src/table/native_hook/native_hook_statistic_table.cpp @@ -17,7 +17,18 @@ namespace SysTuning { namespace TraceStreamer { -enum Index { ID = 0, CALLCHAIN_ID, IPID, TS, MEMORY_TYPE, APPLY_COUNT, RELEASE_COUNT, APPLY_SIZE, RELEASE_SIZE }; +enum Index { + ID = 0, + CALLCHAIN_ID, + IPID, + TS, + MEMORY_TYPE, + MEMORY_SUB_TYPE, + APPLY_COUNT, + RELEASE_COUNT, + APPLY_SIZE, + RELEASE_SIZE +}; NativeHookStatisticTable::NativeHookStatisticTable(const TraceDataCache* dataCache) : TableBase(dataCache) { tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); @@ -25,6 +36,7 @@ NativeHookStatisticTable::NativeHookStatisticTable(const TraceDataCache* dataCac tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("type", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("sub_type_id", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("apply_count", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("release_count", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("apply_size", "INTEGER")); @@ -180,6 +192,12 @@ int32_t NativeHookStatisticTable::Cursor::Column(int32_t column) const sqlite3_result_int64(context_, static_cast(nativeHookStatisticInfoObj_.MemoryTypes()[CurrentRow()])); break; + case MEMORY_SUB_TYPE: + if (nativeHookStatisticInfoObj_.MemorySubTypes()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, + static_cast(nativeHookStatisticInfoObj_.MemorySubTypes()[CurrentRow()])); + } + break; case APPLY_COUNT: sqlite3_result_int64(context_, static_cast(nativeHookStatisticInfoObj_.ApplyCounts()[CurrentRow()])); diff --git a/trace_streamer/src/trace_data/trace_stdtype.cpp b/trace_streamer/src/trace_data/trace_stdtype.cpp index 284315d19..7e352860a 100644 --- a/trace_streamer/src/trace_data/trace_stdtype.cpp +++ b/trace_streamer/src/trace_data/trace_stdtype.cpp @@ -738,6 +738,7 @@ size_t NativeHookStatistic::AppendNewNativeHookStatistic(uint32_t ipid, uint64_t timeStamp, uint32_t callChainId, uint32_t memoryType, + DataIndex subMemType, uint64_t applyCount, uint64_t releaseCount, uint64_t applySize, @@ -749,6 +750,7 @@ size_t NativeHookStatistic::AppendNewNativeHookStatistic(uint32_t ipid, callChainIds_.emplace_back(callChainId); memoryTypes_.emplace_back(memoryType); applyCounts_.emplace_back(applyCount); + memSubTypes_.emplace_back(subMemType); releaseCounts_.emplace_back(releaseCount); applySizes_.emplace_back(applySize); releaseSizes_.emplace_back(releaseSize); @@ -766,6 +768,10 @@ const std::deque& NativeHookStatistic::MemoryTypes() const { return memoryTypes_; } +const std::deque& NativeHookStatistic::MemorySubTypes() const +{ + return memSubTypes_; +} const std::deque& NativeHookStatistic::ApplyCounts() const { return applyCounts_; @@ -2258,7 +2264,7 @@ void FrameSlice::SetEndTimeAndFlag(uint64_t row, uint64_t ts, uint64_t expectDur { UNUSED(expectDur); durs_[row] = ts - timeStamps_[row]; - if (flags_[row] != ABNORMAL_START_END_TIME) { + if (flags_[row] != abnormalStartEndTimeState_) { flags_[row] = expectEnd >= ts ? 0 : 1; } } @@ -2277,7 +2283,7 @@ size_t FrameMaps::AppendNew(FrameSlice* frameSlice, uint64_t src, uint64_t dst) uint64_t expUiEndTime = frameSlice->TimeStampData().at(src) + frameSlice->Durs().at(src); if (std::abs(static_cast(expRsStartTime - expUiEndTime)) >= ONE_MILLION_NANOSECONDS) { auto acturalRow = dst - 1; - frameSlice->SetFlags(acturalRow, FrameSlice::ABNORMAL_START_END_TIME); + frameSlice->SetFlags(acturalRow, FrameSlice::GetAbnormalStartEndTimeState()); } } @@ -2884,7 +2890,7 @@ const std::deque& JsConfig::CpuProfilerInterval() const } size_t TaskPoolInfo::AppendAllocationTaskData(uint32_t allocationTaskRow, - uint32_t allocationTaskId, + uint32_t allocationItid, uint32_t executeId, uint32_t priority, uint32_t executeState) @@ -2892,9 +2898,9 @@ size_t TaskPoolInfo::AppendAllocationTaskData(uint32_t allocationTaskRow, allocationTaskRows_.emplace_back(allocationTaskRow); executeTaskRows_.emplace_back(INVALID_INT32); returnTaskRows_.emplace_back(INVALID_INT32); - allocationTaskIds_.emplace_back(allocationTaskId); - executeTaskIds_.emplace_back(INVALID_INT32); - returnTaskIds_.emplace_back(INVALID_INT32); + allocationItids_.emplace_back(allocationItid); + executeItids_.emplace_back(INVALID_INT32); + returnItids_.emplace_back(INVALID_INT32); executeIds_.emplace_back(executeId); prioritys_.emplace_back(priority); executeStates_.emplace_back(executeState); @@ -2902,14 +2908,14 @@ size_t TaskPoolInfo::AppendAllocationTaskData(uint32_t allocationTaskRow, ids_.emplace_back(Size()); return Size() - 1; } -size_t TaskPoolInfo::AppendExecuteTaskData(uint32_t executeTaskRow, uint32_t executeTaskId, uint32_t executeId) +size_t TaskPoolInfo::AppendExecuteTaskData(uint32_t executeTaskRow, uint32_t executeItid, uint32_t executeId) { allocationTaskRows_.emplace_back(INVALID_INT32); executeTaskRows_.emplace_back(executeTaskRow); returnTaskRows_.emplace_back(INVALID_INT32); - allocationTaskIds_.emplace_back(INVALID_INT32); - executeTaskIds_.emplace_back(executeTaskId); - returnTaskIds_.emplace_back(INVALID_INT32); + allocationItids_.emplace_back(INVALID_INT32); + executeItids_.emplace_back(executeItid); + returnItids_.emplace_back(INVALID_INT32); executeIds_.emplace_back(executeId); prioritys_.emplace_back(INVALID_INT32); executeStates_.emplace_back(INVALID_INT32); @@ -2918,16 +2924,16 @@ size_t TaskPoolInfo::AppendExecuteTaskData(uint32_t executeTaskRow, uint32_t exe return Size() - 1; } size_t TaskPoolInfo::AppendReturnTaskData(uint32_t returnTaskRow, - uint32_t returnTaskId, + uint32_t returnItid, uint32_t executeId, uint32_t returnState) { allocationTaskRows_.emplace_back(INVALID_INT32); executeTaskRows_.emplace_back(INVALID_INT32); returnTaskRows_.emplace_back(returnTaskRow); - allocationTaskIds_.emplace_back(INVALID_INT32); - executeTaskIds_.emplace_back(INVALID_INT32); - returnTaskIds_.emplace_back(returnTaskId); + allocationItids_.emplace_back(INVALID_INT32); + executeItids_.emplace_back(INVALID_INT32); + returnItids_.emplace_back(returnItid); executeIds_.emplace_back(executeId); prioritys_.emplace_back(INVALID_INT32); executeStates_.emplace_back(INVALID_INT32); @@ -2947,17 +2953,17 @@ const std::deque& TaskPoolInfo::ReturnTaskRows() const { return returnTaskRows_; } -const std::deque& TaskPoolInfo::AllocationTaskIds() const +const std::deque& TaskPoolInfo::AllocationItids() const { - return allocationTaskIds_; + return allocationItids_; } -const std::deque& TaskPoolInfo::ExecuteTaskIds() const +const std::deque& TaskPoolInfo::ExecuteItids() const { - return executeTaskIds_; + return executeItids_; } -const std::deque& TaskPoolInfo::ReturnTaskIds() const +const std::deque& TaskPoolInfo::ReturnItids() const { - return returnTaskIds_; + return returnItids_; } const std::deque& TaskPoolInfo::ExecuteIds() const { @@ -2977,32 +2983,32 @@ const std::deque& TaskPoolInfo::ReturnStates() const } void TaskPoolInfo::UpdateAllocationTaskData(uint32_t index, uint32_t allocationTaskRow, - uint32_t allocationTaskId, + uint32_t allocationItid, uint32_t priority, uint32_t executeState) { if (index < Size()) { allocationTaskRows_[index] = allocationTaskRow; - allocationTaskIds_[index] = allocationTaskId; + allocationItids_[index] = allocationItid; prioritys_[index] = priority; executeStates_[index] = executeState; } } -void TaskPoolInfo::UpdateExecuteTaskData(uint32_t index, uint32_t executeTaskRow, uint32_t executeTaskId) +void TaskPoolInfo::UpdateExecuteTaskData(uint32_t index, uint32_t executeTaskRow, uint32_t executeItid) { if (index < Size()) { executeTaskRows_[index] = executeTaskRow; - executeTaskIds_[index] = executeTaskId; + executeItids_[index] = executeItid; } } void TaskPoolInfo::UpdateReturnTaskData(uint32_t index, uint32_t returnTaskRow, - uint32_t returnTaskId, + uint32_t returnItid, uint32_t returnState) { if (index < Size()) { returnTaskRows_[index] = returnTaskRow; - returnTaskIds_[index] = returnTaskId; + returnItids_[index] = returnItid; returnStates_[index] = returnState; } } diff --git a/trace_streamer/src/trace_data/trace_stdtype.h b/trace_streamer/src/trace_data/trace_stdtype.h index ce6b8f80c..1246eb446 100644 --- a/trace_streamer/src/trace_data/trace_stdtype.h +++ b/trace_streamer/src/trace_data/trace_stdtype.h @@ -881,6 +881,7 @@ public: uint64_t timeStamp, uint32_t callChainId, uint32_t memoryType, + DataIndex subMemType, uint64_t applyCount, uint64_t releaseCount, uint64_t applySize, @@ -889,6 +890,7 @@ public: const std::deque& Ipids() const; const std::deque& CallChainIds() const; const std::deque& MemoryTypes() const; + const std::deque& MemorySubTypes() const; const std::deque& ApplyCounts() const; const std::deque& ReleaseCounts() const; const std::deque& ApplySizes() const; @@ -911,6 +913,7 @@ private: std::deque ipids_ = {}; std::deque callChainIds_ = {}; std::deque memoryTypes_ = {}; + std::deque memSubTypes_ = {}; std::deque applyCounts_ = {}; std::deque releaseCounts_ = {}; std::deque applySizes_ = {}; @@ -1905,9 +1908,12 @@ public: void UpdateCallStackSliceId(uint64_t row, uint64_t callStackSliceId); void SetEndTimeAndFlag(uint64_t row, uint64_t ts, uint64_t expectDur, uint64_t expectEnd); void Erase(uint64_t row); + static const uint32_t GetAbnormalStartEndTimeState() + { + return abnormalStartEndTimeState_; + } public: - static const uint32_t ABNORMAL_START_END_TIME = 3; typedef enum FrameSliceType { ACTURAL_SLICE, EXPECT_SLICE } FrameSliceType; private: @@ -1923,6 +1929,7 @@ private: std::deque depths_ = {}; std::deque frameNos_ = {}; const uint32_t INVALID_ROW = 2; + static const uint32_t abnormalStartEndTimeState_ = 3; }; class FrameMaps : public CacheBase { public: @@ -2414,29 +2421,29 @@ private: class TaskPoolInfo : public CacheBase { public: size_t AppendAllocationTaskData(uint32_t allocationTaskRow, - uint32_t allocationTaskId, + uint32_t allocationItid, uint32_t executeId, uint32_t priority, uint32_t executeState); - size_t AppendExecuteTaskData(uint32_t executeTaskRow, uint32_t executeTaskId, uint32_t executeId); + size_t AppendExecuteTaskData(uint32_t executeTaskRow, uint32_t executeItid, uint32_t executeId); size_t AppendReturnTaskData(uint32_t returnTaskRow, - uint32_t returnTaskId, + uint32_t returnItid, uint32_t executeId, uint32_t returnState); void UpdateAllocationTaskData(uint32_t index, uint32_t allocationTaskRow, - uint32_t allocationTaskId, + uint32_t allocationItid, uint32_t priority, uint32_t executeState); - void UpdateExecuteTaskData(uint32_t index, uint32_t executeTaskRow, uint32_t executeTaskId); - void UpdateReturnTaskData(uint32_t index, uint32_t returnTaskRow, uint32_t returnTaskId, uint32_t returnState); + void UpdateExecuteTaskData(uint32_t index, uint32_t executeTaskRow, uint32_t executeItid); + void UpdateReturnTaskData(uint32_t index, uint32_t returnTaskRow, uint32_t returnItid, uint32_t returnState); const std::deque& AllocationTaskRows() const; const std::deque& ExecuteTaskRows() const; const std::deque& ReturnTaskRows() const; - const std::deque& AllocationTaskIds() const; - const std::deque& ExecuteTaskIds() const; - const std::deque& ReturnTaskIds() const; + const std::deque& AllocationItids() const; + const std::deque& ExecuteItids() const; + const std::deque& ReturnItids() const; const std::deque& ExecuteIds() const; const std::deque& Prioritys() const; const std::deque& ExecuteStates() const; @@ -2447,9 +2454,9 @@ public: allocationTaskRows_.clear(); executeTaskRows_.clear(); returnTaskRows_.clear(); - allocationTaskIds_.clear(); - executeTaskIds_.clear(); - returnTaskIds_.clear(); + allocationItids_.clear(); + executeItids_.clear(); + returnItids_.clear(); executeIds_.clear(); prioritys_.clear(); executeStates_.clear(); @@ -2460,9 +2467,9 @@ private: std::deque allocationTaskRows_ = {}; std::deque executeTaskRows_ = {}; std::deque returnTaskRows_ = {}; - std::deque allocationTaskIds_ = {}; - std::deque executeTaskIds_ = {}; - std::deque returnTaskIds_ = {}; + std::deque allocationItids_ = {}; + std::deque executeItids_ = {}; + std::deque returnItids_ = {}; std::deque executeIds_ = {}; std::deque prioritys_ = {}; std::deque executeStates_ = {}; diff --git a/trace_streamer/src/version.cpp b/trace_streamer/src/version.cpp index 2f3abf5d5..e788515b1 100644 --- a/trace_streamer/src/version.cpp +++ b/trace_streamer/src/version.cpp @@ -14,5 +14,5 @@ */ #include "version.h" size_t g_loadSize = 0; -const std::string TRACE_STREAM_VERSION = "3.4.3"; // version -const std::string TRACE_STREAM_PUBLISHVERSION = "2023/7/14"; // publish datetime +const std::string g_traceStreamerVersion = "3.4.4"; // version +const std::string g_traceStreamerPublishVersion = "2023/7/19"; // publish datetime diff --git a/trace_streamer/src/version.h b/trace_streamer/src/version.h index 71bb6b895..621f4dcc5 100644 --- a/trace_streamer/src/version.h +++ b/trace_streamer/src/version.h @@ -18,6 +18,6 @@ #include #include extern size_t g_loadSize; -extern const std::string TRACE_STREAM_VERSION; // version -extern const std::string TRACE_STREAM_PUBLISHVERSION; // publish datetime +extern const std::string g_traceStreamerVersion; // version +extern const std::string g_traceStreamerPublishVersion; // publish datetime #endif -- Gitee From ced4f1b34192f43b6e321c1cbf30572b83eb1e41 Mon Sep 17 00:00:00 2001 From: jichuan Date: Thu, 27 Jul 2023 15:08:32 +0800 Subject: [PATCH 11/14] =?UTF-8?q?Feat:ArtTS=E5=88=86=E6=9E=90=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: jichuan --- ide/src/base-ui/radiobox/LitRadioBox.ts | 17 +- ide/src/base-ui/table/lit-table.ts | 3 +- ide/src/command/Cmd.ts | 8 +- ide/src/js-heap/HeapDataInterface.ts | 3 - ide/src/js-heap/LoadDatabase.ts | 4 - ide/src/trace/SpApplication.ts | 13 +- ide/src/trace/bean/BoxSelection.ts | 4 +- ide/src/trace/bean/FuncStruct.ts | 2 + ide/src/trace/bean/JsStruct.ts | 124 ++++ ide/src/trace/component/SpFlags.ts | 145 +++-- ide/src/trace/component/SpMetrics.ts | 22 +- ide/src/trace/component/SpQuerySQL.ts | 48 +- ide/src/trace/component/SpRecordTrace.ts | 142 ++--- ide/src/trace/component/SpSystemTrace.ts | 241 ++++++-- ide/src/trace/component/Utils.ts | 51 ++ ide/src/trace/component/chart/SpArkTsChart.ts | 275 +++++++++ .../trace/component/chart/SpChartManager.ts | 19 +- .../trace/component/chart/SpFrameTimeChart.ts | 11 +- .../trace/component/chart/SpJsMemoryChart.ts | 148 ----- .../trace/component/chart/SpProcessChart.ts | 207 +++---- .../trace/component/metrics/CpuStrategy.ts | 4 +- .../metrics/DistributeTermStrategy.ts | 6 +- .../setting/{SpJsHeap.ts => SpArkTs.ts} | 251 +++++++- .../trace/component/setting/SpCheckDesBox.ts | 19 +- .../trace/component/setting/SpProbesConfig.ts | 8 +- .../trace/component/setting/SpTraceCommand.ts | 8 +- .../setting/bean/ProfilerServiceTypes.ts | 2 + .../trace/component/trace/base/Extension.ts | 2 + .../trace/component/trace/base/TraceRow.ts | 6 +- .../component/trace/base/TraceRowConfig.ts | 147 ++--- .../trace/component/trace/base/TraceSheet.ts | 123 ++-- .../component/trace/base/TraceSheetConfig.ts | 23 +- .../trace/sheet/TabPaneCurrentSelection.ts | 191 +++--- .../{snapshot => ark-ts}/TabPaneComparison.ts | 0 .../trace/sheet/ark-ts/TabPaneJsCpu.ts | 312 ++++++++++ .../sheet/ark-ts/TabPaneJsCpuBottomUp.ts | 27 + .../sheet/ark-ts/TabPaneJsCpuCallTree.ts | 27 + .../sheet/ark-ts/TabPaneJsCpuStatistics.ts | 281 +++++++++ .../{snapshot => ark-ts}/TabPaneSummary.ts | 35 +- .../sheet/energy/TabPaneSystemDetails.ts | 7 +- .../TabPaneFilesystemStatisticsAnalysis.ts | 108 ++-- .../TabPaneIOTierStatisticsAnalysis.ts | 111 ++-- .../TabPaneVirtualMemoryStatisticsAnalysis.ts | 108 ++-- .../trace/sheet/hiperf/TabPanePerfAnalysis.ts | 84 +-- .../trace/sheet/jank/TabPaneFrames.ts | 50 +- .../TabPaneNMStatisticAnalysis.ts | 135 ++--- .../trace/sheet/process/TabPaneStartup.ts | 10 +- .../trace/sheet/process/TabPaneStaticInit.ts | 10 +- .../trace/sheet/task/TabPaneTaskFrames.ts | 291 ++++----- ide/src/trace/database/DBUtils.ts | 22 +- ide/src/trace/database/SqlLite.ts | 160 +++-- ide/src/trace/database/TraceWorker.ts | 20 +- .../logic-worker/ProcedureLogicWorker.ts | 2 + .../ProcedureLogicWorkerCommon.ts | 110 ++-- .../ProcedureLogicWorkerJsCpuProfiler.ts | 554 ++++++++++++++++++ .../ProcedureLogicWorkerNativeNemory.ts | 4 +- .../logic-worker/ProcedureLogicWorkerPerf.ts | 2 +- .../database/ui-worker/ProcedureWorker.ts | 6 +- .../ui-worker/ProcedureWorkerAppStartup.ts | 14 +- .../ui-worker/ProcedureWorkerCommon.ts | 7 + .../ui-worker/ProcedureWorkerCpuProfiler.ts | 196 +++++++ .../ProcedureWorkerFrameAnimation.ts | 84 +-- .../ui-worker/ProcedureWorkerFrameDynamic.ts | 133 +++-- .../ui-worker/ProcedureWorkerFrameSpacing.ts | 54 +- .../ui-worker/ProcedureWorkerHeapSnapshot.ts | 7 - .../ui-worker/ProcedureWorkerHeapTimeline.ts | 25 +- .../database/ui-worker/ProcedureWorkerJank.ts | 21 +- .../ui-worker/ProcedureWorkerSoInit.ts | 27 +- 68 files changed, 3798 insertions(+), 1523 deletions(-) create mode 100644 ide/src/trace/bean/JsStruct.ts create mode 100644 ide/src/trace/component/Utils.ts create mode 100644 ide/src/trace/component/chart/SpArkTsChart.ts delete mode 100644 ide/src/trace/component/chart/SpJsMemoryChart.ts rename ide/src/trace/component/setting/{SpJsHeap.ts => SpArkTs.ts} (41%) rename ide/src/trace/component/trace/sheet/{snapshot => ark-ts}/TabPaneComparison.ts (100%) create mode 100644 ide/src/trace/component/trace/sheet/ark-ts/TabPaneJsCpu.ts create mode 100644 ide/src/trace/component/trace/sheet/ark-ts/TabPaneJsCpuBottomUp.ts create mode 100644 ide/src/trace/component/trace/sheet/ark-ts/TabPaneJsCpuCallTree.ts create mode 100644 ide/src/trace/component/trace/sheet/ark-ts/TabPaneJsCpuStatistics.ts rename ide/src/trace/component/trace/sheet/{snapshot => ark-ts}/TabPaneSummary.ts (97%) create mode 100644 ide/src/trace/database/logic-worker/ProcedureLogicWorkerJsCpuProfiler.ts create mode 100644 ide/src/trace/database/ui-worker/ProcedureWorkerCpuProfiler.ts diff --git a/ide/src/base-ui/radiobox/LitRadioBox.ts b/ide/src/base-ui/radiobox/LitRadioBox.ts index 102573843..072669120 100644 --- a/ide/src/base-ui/radiobox/LitRadioBox.ts +++ b/ide/src/base-ui/radiobox/LitRadioBox.ts @@ -23,7 +23,19 @@ export class LitRadioBox extends BaseElement { private radio: HTMLInputElement | undefined | null; static get observedAttributes() { - return ['checked', 'value']; + return ['checked', 'value', 'disabled']; + } + + get disabled() { + return this.getAttribute('disabled') !== null; + } + + set disabled(value) { + if (value === null || value === false) { + this.removeAttribute('disabled'); + } else { + this.setAttribute('disabled', ''); + } } get checked() { @@ -181,6 +193,9 @@ export class LitRadioBox extends BaseElement { background-color: #1A83FF; color:#ffffff } + :host([disabled]){ + pointer-events: none; + }