Merge "ui: Make thread and process name columns Optional"
diff --git a/Android.bp b/Android.bp
index 6a66249..5bf2da2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1586,6 +1586,11 @@
name: "perfetto_include_perfetto_ext_ipc_ipc",
}
+// GN: //include/perfetto/ext/trace_processor:demangle
+filegroup {
+ name: "perfetto_include_perfetto_ext_trace_processor_demangle",
+}
+
// GN: //include/perfetto/ext/trace_processor:export_json
filegroup {
name: "perfetto_include_perfetto_ext_trace_processor_export_json",
@@ -1855,6 +1860,7 @@
"libgmock",
"libgtest",
"libperfetto_client_experimental",
+ "perfetto_src_trace_processor_demangle",
],
whole_static_libs: [
"perfetto_gtest_logcat_printer",
@@ -3730,12 +3736,14 @@
"protos/perfetto/metrics/chrome/blink_gc_metric.proto",
"protos/perfetto/metrics/chrome/dropped_frames.proto",
"protos/perfetto/metrics/chrome/frame_times.proto",
+ "protos/perfetto/metrics/chrome/histogram_hashes.proto",
"protos/perfetto/metrics/chrome/long_latency.proto",
"protos/perfetto/metrics/chrome/media_metric.proto",
"protos/perfetto/metrics/chrome/reported_by_page.proto",
"protos/perfetto/metrics/chrome/scroll_jank.proto",
"protos/perfetto/metrics/chrome/test_chrome_metric.proto",
"protos/perfetto/metrics/chrome/touch_jank.proto",
+ "protos/perfetto/metrics/chrome/user_event_hashes.proto",
"protos/perfetto/metrics/custom_options.proto",
"protos/perfetto/metrics/metrics.proto",
],
@@ -8110,6 +8118,21 @@
],
}
+// GN: //src/trace_processor:demangle
+cc_library_static {
+ name: "perfetto_src_trace_processor_demangle",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_include_perfetto_ext_trace_processor_demangle",
+ "src/trace_processor/demangle.cc",
+ ],
+ host_supported: true,
+ defaults: [
+ "perfetto_defaults",
+ ],
+}
+
// GN: //src/trace_processor:export_json
filegroup {
name: "perfetto_src_trace_processor_export_json",
@@ -8367,8 +8390,10 @@
"src/trace_processor/metrics/sql/chrome/actual_power_by_category.sql",
"src/trace_processor/metrics/sql/chrome/actual_power_by_rail_mode.sql",
"src/trace_processor/metrics/sql/chrome/chrome_event_metadata.sql",
+ "src/trace_processor/metrics/sql/chrome/chrome_histogram_hashes.sql",
"src/trace_processor/metrics/sql/chrome/chrome_processes.sql",
"src/trace_processor/metrics/sql/chrome/chrome_thread_slice.sql",
+ "src/trace_processor/metrics/sql/chrome/chrome_user_event_hashes.sql",
"src/trace_processor/metrics/sql/chrome/cpu_time_by_category.sql",
"src/trace_processor/metrics/sql/chrome/cpu_time_by_rail_mode.sql",
"src/trace_processor/metrics/sql/chrome/estimated_power_by_category.sql",
@@ -9776,6 +9801,7 @@
static_libs: [
"libgmock",
"libgtest",
+ "perfetto_src_trace_processor_demangle",
],
whole_static_libs: [
"perfetto_gtest_logcat_printer",
@@ -10013,6 +10039,9 @@
"src/trace_processor/trace_processor_shell.cc",
"src/trace_processor/util/proto_to_json.cc",
],
+ static_libs: [
+ "perfetto_src_trace_processor_demangle",
+ ],
host_supported: true,
generated_headers: [
"perfetto_protos_perfetto_common_zero_gen_headers",
@@ -10172,6 +10201,7 @@
static_libs: [
"libsqlite",
"libz",
+ "perfetto_src_trace_processor_demangle",
],
generated_headers: [
"perfetto_protos_perfetto_common_zero_gen_headers",
diff --git a/BUILD b/BUILD
index 3260a6e..8870bbd 100644
--- a/BUILD
+++ b/BUILD
@@ -423,6 +423,14 @@
],
)
+# GN target: //include/perfetto/ext/trace_processor:demangle
+perfetto_filegroup(
+ name = "include_perfetto_ext_trace_processor_demangle",
+ srcs = [
+ "include/perfetto/ext/trace_processor/demangle.h",
+ ],
+)
+
# GN target: //include/perfetto/ext/trace_processor:export_json
perfetto_filegroup(
name = "include_perfetto_ext_trace_processor_export_json",
@@ -1106,8 +1114,10 @@
"src/trace_processor/metrics/sql/chrome/actual_power_by_category.sql",
"src/trace_processor/metrics/sql/chrome/actual_power_by_rail_mode.sql",
"src/trace_processor/metrics/sql/chrome/chrome_event_metadata.sql",
+ "src/trace_processor/metrics/sql/chrome/chrome_histogram_hashes.sql",
"src/trace_processor/metrics/sql/chrome/chrome_processes.sql",
"src/trace_processor/metrics/sql/chrome/chrome_thread_slice.sql",
+ "src/trace_processor/metrics/sql/chrome/chrome_user_event_hashes.sql",
"src/trace_processor/metrics/sql/chrome/cpu_time_by_category.sql",
"src/trace_processor/metrics/sql/chrome/cpu_time_by_rail_mode.sql",
"src/trace_processor/metrics/sql/chrome/estimated_power_by_category.sql",
@@ -1332,6 +1342,20 @@
],
)
+# GN target: //src/trace_processor:demangle
+perfetto_cc_library(
+ name = "src_trace_processor_demangle",
+ srcs = [
+ "src/trace_processor/demangle.cc",
+ ],
+ hdrs = [
+ ":include_perfetto_base_base",
+ ":include_perfetto_ext_base_base",
+ ":include_perfetto_ext_trace_processor_demangle",
+ ],
+ linkstatic = True,
+)
+
# GN target: //src/trace_processor:export_json
perfetto_filegroup(
name = "src_trace_processor_export_json",
@@ -2721,12 +2745,14 @@
"protos/perfetto/metrics/chrome/blink_gc_metric.proto",
"protos/perfetto/metrics/chrome/dropped_frames.proto",
"protos/perfetto/metrics/chrome/frame_times.proto",
+ "protos/perfetto/metrics/chrome/histogram_hashes.proto",
"protos/perfetto/metrics/chrome/long_latency.proto",
"protos/perfetto/metrics/chrome/media_metric.proto",
"protos/perfetto/metrics/chrome/reported_by_page.proto",
"protos/perfetto/metrics/chrome/scroll_jank.proto",
"protos/perfetto/metrics/chrome/test_chrome_metric.proto",
"protos/perfetto/metrics/chrome/touch_jank.proto",
+ "protos/perfetto/metrics/chrome/user_event_hashes.proto",
],
visibility = [
PERFETTO_CONFIG.proto_library_visibility,
@@ -3692,7 +3718,8 @@
PERFETTO_CONFIG.deps.sqlite_ext_percentile +
PERFETTO_CONFIG.deps.zlib + [
":cc_amalgamated_sql_metrics",
- ],
+ ] +
+ PERFETTO_CONFIG.deps.demangle_wrapper,
linkstatic = True,
)
@@ -3790,7 +3817,8 @@
PERFETTO_CONFIG.deps.sqlite_ext_percentile +
PERFETTO_CONFIG.deps.zlib + [
":cc_amalgamated_sql_metrics",
- ],
+ ] +
+ PERFETTO_CONFIG.deps.demangle_wrapper,
)
# GN target: //src/traced/probes:traced_probes
@@ -3974,7 +4002,8 @@
PERFETTO_CONFIG.deps.sqlite_ext_percentile +
PERFETTO_CONFIG.deps.zlib + [
":cc_amalgamated_sql_metrics",
- ],
+ ] +
+ PERFETTO_CONFIG.deps.demangle_wrapper,
)
# Content from BUILD.extras
diff --git a/CHANGELOG b/CHANGELOG
index 8f2d129..955527a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -8,7 +8,11 @@
message.
Trace Processor:
* Added prebuilts for mac-arm64.
- *
+ * Added an optional dependency from trace processor onto a subset of
+ sources from llvm-project for function name demangling. Bazel embedders
+ might need to update their PERFETTO_CONFIG in perfetto_cfg.bzl to opt in
+ or out of the new dependency. See
+ perfetto/bazel/standalone/perfetto_cfg.bzl for details.
UI:
* Added flow arrows between binder transaction pairs (request/reply
and async send/async recv).
diff --git a/bazel/deps.bzl b/bazel/deps.bzl
index 9d01d11..23fb787 100644
--- a/bazel/deps.bzl
+++ b/bazel/deps.bzl
@@ -74,6 +74,15 @@
shallow_since = "1557160162 -0700",
)
+ _add_repo_if_not_existing(
+ http_archive,
+ name = "perfetto_dep_llvm_demangle",
+ url = "https://storage.googleapis.com/perfetto/llvm-project-3b4c59c156919902c785ce3cbae0eee2ee53064d.tgz",
+ sha256 = "f4a52e7f36edd7cacc844d5ae0e5f60b6f57c5afc40683e99f295886c9ce8ff4",
+ strip_prefix = "llvm-project",
+ build_file = "//bazel:llvm_demangle.BUILD",
+ )
+
# Without this protobuf.bzl fails. This seems a bug in protobuf_deps().
_add_repo_if_not_existing(
http_archive,
diff --git a/bazel/llvm_demangle.BUILD b/bazel/llvm_demangle.BUILD
new file mode 100644
index 0000000..fe406fa
--- /dev/null
+++ b/bazel/llvm_demangle.BUILD
@@ -0,0 +1,39 @@
+# Copyright (C) 2022 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
+
+cc_library(
+ name = "llvm_demangle",
+ srcs = [
+ "llvm/lib/Demangle/DLangDemangle.cpp",
+ "llvm/lib/Demangle/Demangle.cpp",
+ "llvm/lib/Demangle/ItaniumDemangle.cpp",
+ "llvm/lib/Demangle/MicrosoftDemangle.cpp",
+ "llvm/lib/Demangle/MicrosoftDemangleNodes.cpp",
+ "llvm/lib/Demangle/RustDemangle.cpp",
+ ],
+ hdrs = [
+ "llvm/include/llvm/Demangle/Demangle.h",
+ "llvm/include/llvm/Demangle/DemangleConfig.h",
+ "llvm/include/llvm/Demangle/ItaniumDemangle.h",
+ "llvm/include/llvm/Demangle/MicrosoftDemangle.h",
+ "llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h",
+ "llvm/include/llvm/Demangle/StringView.h",
+ "llvm/include/llvm/Demangle/Utility.h",
+ ],
+ copts = ["-std=c++14"] + PERFETTO_CONFIG.deps_copts.llvm_demangle,
+ includes = ["llvm/include"],
+ visibility = ["//visibility:public"],
+)
diff --git a/bazel/standalone/perfetto_cfg.bzl b/bazel/standalone/perfetto_cfg.bzl
index c9c89f1..a68bd34 100644
--- a/bazel/standalone/perfetto_cfg.bzl
+++ b/bazel/standalone/perfetto_cfg.bzl
@@ -56,6 +56,21 @@
protobuf_py = [],
pandas_py = [],
tp_vendor_py = [],
+
+ # There are multiple configurations for the function name demangling
+ # logic in trace processor:
+ # (1) The following defaults include a subset of demangling sources
+ # from llvm-project. This is the most complete implementation.
+ # (2) You can avoid the llvm dependency by setting "llvm_demangle = []"
+ # here and PERFETTO_LLVM_DEMANGLE to false in your
+ # perfetto_build_flags.h. Then the implementation will use a
+ # demangler from the c++ runtime, which will most likely handle
+ # only itanium mangling, and is unavailable on some platforms (e.g.
+ # Windows, where it becomes a nop).
+ # (3) You can override the whole demangle_wrapper below, and provide
+ # your own demangling implementation.
+ demangle_wrapper = [ "//:src_trace_processor_demangle" ],
+ llvm_demangle = ["@perfetto_dep_llvm_demangle//:llvm_demangle"],
),
# This struct allows embedders to customize the cc_opts for Perfetto
@@ -66,6 +81,7 @@
jsoncpp = [],
linenoise = [],
sqlite = [],
+ llvm_demangle = [],
),
# Allow Bazel embedders to change the visibility of "public" targets.
diff --git a/buildtools/.gitignore b/buildtools/.gitignore
index e29be60..869315f 100644
--- a/buildtools/.gitignore
+++ b/buildtools/.gitignore
@@ -27,6 +27,7 @@
linenoise/
linux/
linux64/
+llvm-project/
lzma/
mac/
ndk/
diff --git a/buildtools/BUILD.gn b/buildtools/BUILD.gn
index ee84087..a508a74 100644
--- a/buildtools/BUILD.gn
+++ b/buildtools/BUILD.gn
@@ -974,6 +974,12 @@
]
}
+# Here be dragons. Used only by standalone profiler builds, which are
+# considered best effort. Since the headers use c++17 features, this source_set
+# pushes -std=c++17 flags up the dependency tree, whereas the rest of the
+# project continues to build under c++11. So the profilers end up linking
+# together code built under different standards, and rely on that to be ABI
+# compatible.
source_set("libunwindstack") {
visibility = _buildtools_visibility
include_dirs = [
@@ -1033,9 +1039,7 @@
"android-unwinding/libunwindstack/MemoryMte.cpp",
]
} else {
- sources += [
- "android-unwinding/libunwindstack/LogAndroid.cpp",
- ]
+ sources += [ "android-unwinding/libunwindstack/LogAndroid.cpp" ]
}
if (current_cpu == "x86") {
sources += [ "android-unwinding/libunwindstack/AsmGetRegsX86.S" ]
@@ -1147,3 +1151,39 @@
deps = [ "//gn:default_deps" ]
}
}
+
+config("llvm_demangle_config") {
+ visibility = _buildtools_visibility
+ include_dirs = [ "llvm-project/llvm/include" ]
+}
+
+# NB: this is built under c++14 and linked into code that is c++11 by default.
+# We rely on the ABIs being compatible for this to be sane. At the time of
+# writing, the only c++14 specific code is behind an #ifndef NDEBUG, so we
+# could keep building as c++11 in non-debug builds, but we always use c++14 for
+# consistency.
+static_library("llvm_demangle") {
+ visibility = _buildtools_visibility
+ configs -= [
+ "//gn/standalone:extra_warnings",
+ "//gn/standalone:c++11",
+ ]
+ configs += [ "//gn/standalone:c++14" ]
+ public_configs = [ ":llvm_demangle_config" ]
+ sources = [
+ "llvm-project/llvm/include/llvm/Demangle/Demangle.h",
+ "llvm-project/llvm/include/llvm/Demangle/DemangleConfig.h",
+ "llvm-project/llvm/include/llvm/Demangle/ItaniumDemangle.h",
+ "llvm-project/llvm/include/llvm/Demangle/MicrosoftDemangle.h",
+ "llvm-project/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h",
+ "llvm-project/llvm/include/llvm/Demangle/StringView.h",
+ "llvm-project/llvm/include/llvm/Demangle/Utility.h",
+ "llvm-project/llvm/lib/Demangle/DLangDemangle.cpp",
+ "llvm-project/llvm/lib/Demangle/Demangle.cpp",
+ "llvm-project/llvm/lib/Demangle/ItaniumDemangle.cpp",
+ "llvm-project/llvm/lib/Demangle/MicrosoftDemangle.cpp",
+ "llvm-project/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp",
+ "llvm-project/llvm/lib/Demangle/RustDemangle.cpp",
+ ]
+ deps = [ "//gn:default_deps" ]
+}
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index f404832..b0e61b1 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -88,6 +88,7 @@
"PERFETTO_HEAPPROFD=$enable_perfetto_heapprofd",
"PERFETTO_STDERR_CRASH_DUMP=$enable_perfetto_stderr_crash_dump",
"PERFETTO_X64_CPU_OPT=$enable_perfetto_x64_cpu_opt",
+ "PERFETTO_LLVM_DEMANGLE=$enable_perfetto_llvm_demangle",
]
rel_out_path = rebase_path(gen_header_path, "$root_build_dir")
@@ -104,7 +105,8 @@
# All targets should depend on this target to inherit the right flags and
# include directories.
group("default_deps") {
- visibility = [ "../*" ] # Prevent chromium targets from depending on this (breaks component).
+ visibility = [ "../*" ] # Prevent chromium targets from depending on this
+ # (breaks component).
public_configs = [ ":default_config" ]
deps = [ ":gen_buildflags" ]
if (perfetto_build_standalone) {
@@ -124,7 +126,8 @@
# embedders that depend on perfetto (e.g. chrome). :public_config (see below) is
# used for that.
config("default_config") {
- visibility = [ "../*" ] # Prevent chromium targets from depending on this (breaks component).
+ visibility = [ "../*" ] # Prevent chromium targets from depending on this
+ # (breaks component).
configs = [ ":public_config" ]
defines = [ "PERFETTO_IMPLEMENTATION" ]
include_dirs = [
@@ -393,6 +396,12 @@
}
}
+if (enable_perfetto_llvm_demangle) {
+ group("llvm_demangle") {
+ public_deps = [ "//buildtools:llvm_demangle" ]
+ }
+}
+
# Used by fuzzers.
if (enable_perfetto_fuzzers && use_libfuzzer) {
group("libfuzzer") {
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index a755b8c..fe1fa11 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -100,7 +100,7 @@
# Only relevant for GN builds. Sets the path where perfetto lives. This is //
# for standalone builds and //third_party/perfetto/ in embedders. The embedder
-# can ovverride it in its GN files.
+# can override it in its GN files.
if (perfetto_build_standalone || is_perfetto_build_generator) {
perfetto_root_path = "//"
import("//gn/standalone/android.gni") # For android_api_level
@@ -291,6 +291,12 @@
enable_perfetto_zlib =
(enable_perfetto_trace_processor && !build_with_chromium) ||
enable_perfetto_platform_services
+
+ # Enables function name demangling using sources from llvm. Otherwise
+ # trace_processor falls back onto using the c++ runtime demangler, which
+ # typically handles only itanium mangling.
+ enable_perfetto_llvm_demangle =
+ enable_perfetto_trace_processor && perfetto_build_standalone
}
declare_args() {
diff --git a/gn/standalone/BUILD.gn b/gn/standalone/BUILD.gn
index bd33114..ab21e58 100644
--- a/gn/standalone/BUILD.gn
+++ b/gn/standalone/BUILD.gn
@@ -116,7 +116,16 @@
}
}
-# This is needed to compile libunwindstack.
+# Used in buildtools dependencies for standalone builds.
+config("c++14") {
+ if (is_win) {
+ cflags_cc = [ "/std:c++14" ]
+ } else {
+ cflags_cc = [ "-std=c++14" ]
+ }
+}
+
+# Used in buildtools dependencies for standalone builds.
config("c++17") {
if (is_win) {
cflags_cc = [ "/std:c++17" ]
diff --git a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
index a02f467..502e9bf 100644
--- a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
@@ -44,6 +44,7 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_HEAPPROFD() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_STDERR_CRASH_DUMP() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_X64_CPU_OPT() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LLVM_DEMANGLE() (0)
// clang-format on
#endif // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
diff --git a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
index 531445c..53c423e 100644
--- a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
@@ -44,6 +44,7 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_HEAPPROFD() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_STDERR_CRASH_DUMP() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_X64_CPU_OPT() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LLVM_DEMANGLE() (0)
// clang-format on
#endif // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
diff --git a/include/perfetto/ext/trace_processor/BUILD.gn b/include/perfetto/ext/trace_processor/BUILD.gn
index a2fd7fa..6df0cca 100644
--- a/include/perfetto/ext/trace_processor/BUILD.gn
+++ b/include/perfetto/ext/trace_processor/BUILD.gn
@@ -21,3 +21,7 @@
sources += [ "export_json.h" ]
}
}
+
+source_set("demangle") {
+ sources = [ "demangle.h" ]
+}
diff --git a/include/perfetto/ext/trace_processor/demangle.h b/include/perfetto/ext/trace_processor/demangle.h
new file mode 100644
index 0000000..f3c337f
--- /dev/null
+++ b/include/perfetto/ext/trace_processor/demangle.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_DEMANGLE_H_
+#define INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_DEMANGLE_H_
+
+#include "perfetto/ext/base/utils.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace demangle {
+
+// Returns a |malloc|-allocated C string with the demangled name.
+// Returns an empty pointer if demangling was unsuccessful.
+std::unique_ptr<char, base::FreeDeleter> Demangle(const char* mangled_name);
+
+} // namespace demangle
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_DEMANGLE_H_
diff --git a/protos/perfetto/metrics/chrome/BUILD.gn b/protos/perfetto/metrics/chrome/BUILD.gn
index 9e88247..ad53980 100644
--- a/protos/perfetto/metrics/chrome/BUILD.gn
+++ b/protos/perfetto/metrics/chrome/BUILD.gn
@@ -25,12 +25,14 @@
"blink_gc_metric.proto",
"dropped_frames.proto",
"frame_times.proto",
+ "histogram_hashes.proto",
"long_latency.proto",
"media_metric.proto",
"reported_by_page.proto",
"scroll_jank.proto",
"test_chrome_metric.proto",
"touch_jank.proto",
+ "user_event_hashes.proto",
]
}
diff --git a/protos/perfetto/metrics/chrome/all_chrome_metrics.proto b/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
index 4a24580..5513b52 100644
--- a/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
+++ b/protos/perfetto/metrics/chrome/all_chrome_metrics.proto
@@ -22,12 +22,14 @@
import "protos/perfetto/metrics/chrome/blink_gc_metric.proto";
import "protos/perfetto/metrics/chrome/dropped_frames.proto";
import "protos/perfetto/metrics/chrome/frame_times.proto";
+import "protos/perfetto/metrics/chrome/histogram_hashes.proto";
import "protos/perfetto/metrics/chrome/long_latency.proto";
import "protos/perfetto/metrics/chrome/media_metric.proto";
import "protos/perfetto/metrics/chrome/reported_by_page.proto";
import "protos/perfetto/metrics/chrome/scroll_jank.proto";
import "protos/perfetto/metrics/chrome/test_chrome_metric.proto";
import "protos/perfetto/metrics/chrome/touch_jank.proto";
+import "protos/perfetto/metrics/chrome/user_event_hashes.proto";
// TODO(lalitm): rename metrics below to include a "chrome_" prefix.
extend TraceMetrics {
@@ -40,4 +42,6 @@
optional TouchJank touch_jank = 1007;
optional ChromeDroppedFrames chrome_dropped_frames = 1008;
optional ChromeLongLatency chrome_long_latency = 1009;
+ optional ChromeHistogramHashes chrome_histogram_hashes = 1010;
+ optional ChromeUserEventHashes chrome_user_event_hashes = 1011;
}
diff --git a/protos/perfetto/metrics/chrome/histogram_hashes.proto b/protos/perfetto/metrics/chrome/histogram_hashes.proto
new file mode 100644
index 0000000..8f7323e
--- /dev/null
+++ b/protos/perfetto/metrics/chrome/histogram_hashes.proto
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package perfetto.protos;
+
+// The list of Chrome Histogram hashes in trace track events.
+// Use cases include translating histogram hashes to histogram
+// names by getting this list, and prepending a translation table to the trace.
+message ChromeHistogramHashes {
+ repeated int64 hash = 1;
+}
diff --git a/protos/perfetto/metrics/chrome/user_event_hashes.proto b/protos/perfetto/metrics/chrome/user_event_hashes.proto
new file mode 100644
index 0000000..e50e6bd
--- /dev/null
+++ b/protos/perfetto/metrics/chrome/user_event_hashes.proto
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package perfetto.protos;
+
+// The list of Chrome user event hashes in trace track events.
+// Use cases include translating user event hashes to action
+// names by getting this list, and prepending a translation table to the trace.
+message ChromeUserEventHashes {
+ repeated int64 action_hash = 1;
+}
diff --git a/protos/third_party/chromium/chrome_track_event.proto b/protos/third_party/chromium/chrome_track_event.proto
index 08f37a7..c30f4cd 100644
--- a/protos/third_party/chromium/chrome_track_event.proto
+++ b/protos/third_party/chromium/chrome_track_event.proto
@@ -5,6 +5,7 @@
syntax = "proto2";
import public "protos/perfetto/trace/track_event/track_event.proto";
+import public "protos/perfetto/trace/track_event/debug_annotation.proto";
package perfetto.protos;
@@ -152,6 +153,11 @@
optional bool has_speculative_render_frame_host = 3;
optional RenderFrameHost current_frame_host = 4;
+ optional RenderFrameHost speculative_frame_host = 5;
+
+ // Additional untyped debug information associated with this
+ // FrameTreeNode, populated via TracedProto::AddDebugAnnotations API.
+ repeated DebugAnnotation debug_annotations = 99;
}
message ChromeHashedPerformanceMark {
@@ -204,6 +210,10 @@
// Details about the associated browser context.
optional ChromeBrowserContext browser_context = 4;
+
+ // Additional untyped debug information associated with this
+ // RenderProcessHost, populated via TracedProto::AddDebugAnnotations API.
+ repeated DebugAnnotation debug_annotations = 99;
}
message RenderProcessHostListener {
@@ -276,6 +286,10 @@
// The SiteInstanceGroup this SiteInstance belongs to.
optional SiteInstanceGroup site_instance_group = 7;
+
+ // Additional untyped debug information associated with this
+ // SiteInstance, populated via TracedProto::AddDebugAnnotations API.
+ repeated DebugAnnotation debug_annotations = 99;
}
message SiteInstanceGroup {
@@ -287,8 +301,13 @@
// The process ID of the SiteInstanceGroup.
optional RenderProcessHost process = 3;
+
+ // Additional untyped debug information associated with this
+ // SiteInstanceGroup, populated via TracedProto::AddDebugAnnotations API.
+ repeated DebugAnnotation debug_annotations = 99;
}
+// Next ID: 7
message RenderViewHost {
// The RenderViewHostMapId for the RenderViewHost.
optional int32 rvh_map_id = 1;
@@ -296,14 +315,21 @@
// The routing ID for the RenderViewHost.
optional int32 routing_id = 2;
- // The process ID of the RenderViewHost.
+ // The process ID of the RenderViewHost. Deprecated in favour of |process|.
optional int32 process_id = 3;
+ // Process this RenderViewHost is associated with.
+ optional RenderProcessHost process = 6;
+
// Whether the RenderViewHost is in back/forward cache or not.
optional bool is_in_back_forward_cache = 4;
// Whether the renderer-side RenderView is created.
optional bool renderer_view_created = 5;
+
+ // Additional untyped debug information associated with this
+ // RenderViewHost, populated via TracedProto::AddDebugAnnotations API.
+ repeated DebugAnnotation debug_annotations = 99;
}
message RenderFrameProxyHost {
@@ -327,6 +353,10 @@
// The SiteInstanceGroupId of the SiteInstanceGroup associated with the
// RenderFrameProxyHost.
optional int32 site_instance_group_id = 6;
+
+ // Additional untyped debug information associated with this
+ // RenderFrameProxyHost, populated via TracedProto::AddDebugAnnotations API.
+ repeated DebugAnnotation debug_annotations = 99;
}
message AndroidView {
@@ -420,6 +450,10 @@
message BrowsingContextState {
// The ID of the BrowsingInstance that the BrowsingContextState belongs to.
optional int32 browsing_instance_id = 1;
+
+ // Additional untyped debug information associated with this
+ // FrameTreeNode, populated via TracedProto::AddDebugAnnotations API.
+ repeated DebugAnnotation debug_annotations = 99;
}
message RenderFrameHost {
@@ -448,6 +482,10 @@
optional RenderFrameHost outer_document = 9;
optional RenderFrameHost embedder = 10;
optional BrowsingContextState browsing_context_state = 11;
+
+ // Additional untyped debug information associated with this
+ // RenderViewHost, populated via TracedProto::AddDebugAnnotations API.
+ repeated DebugAnnotation debug_annotations = 99;
}
message ChromeThreadPoolTask {
@@ -711,6 +749,19 @@
optional RemoteHungProcessTerminateReason remote_process_terminate_reason = 2;
}
+message NavigationHandle {
+ optional int64 navigation_id = 1;
+ optional bool has_committed = 2;
+ optional bool is_error_page = 3;
+ optional FrameTreeNodeInfo frame_tree_node = 4;
+ optional RenderFrameHost render_frame_host = 5;
+
+ // Additional untyped debug information associated with this
+ // NavigationHandle/Request, populated via TracedProto::AddDebugAnnotations
+ // API.
+ repeated DebugAnnotation debug_annotations = 99;
+}
+
enum DeviceThermalState {
DEVICE_THERMAL_STATE_UNKNOWN = 0;
DEVICE_THERMAL_STATE_NOMINAL = 1;
@@ -801,5 +852,7 @@
optional BrowsingContextState browsing_context_state = 1035;
optional DeviceThermalState device_thermal_state = 1036;
+
+ optional NavigationHandle navigation = 1037;
}
}
diff --git a/src/perfetto_cmd/config.cc b/src/perfetto_cmd/config.cc
index f2b40d4..5022203 100644
--- a/src/perfetto_cmd/config.cc
+++ b/src/perfetto_cmd/config.cc
@@ -147,6 +147,7 @@
ftrace_cfg.add_atrace_categories(cat);
for (const auto& app : atrace_apps)
ftrace_cfg.add_atrace_apps(app);
+ ftrace_cfg.set_symbolize_ksyms(true);
ds_config->set_ftrace_config_raw(ftrace_cfg.SerializeAsString());
auto* ps_config = config->add_data_sources()->mutable_config();
diff --git a/src/perfetto_cmd/config_unittest.cc b/src/perfetto_cmd/config_unittest.cc
index cc1db34..5435c8a 100644
--- a/src/perfetto_cmd/config_unittest.cc
+++ b/src/perfetto_cmd/config_unittest.cc
@@ -147,6 +147,7 @@
ASSERT_TRUE(ftrace.ParseFromString(
config.data_sources()[0].config().ftrace_config_raw()));
EXPECT_THAT(ftrace.ftrace_events(), Contains("sched/sched_switch"));
+ EXPECT_TRUE(ftrace.symbolize_ksyms());
EXPECT_THAT(ftrace.atrace_categories(), Contains("sw"));
EXPECT_THAT(ftrace.atrace_apps(), Contains("com.android.chrome"));
}
diff --git a/src/profiling/deobfuscator.cc b/src/profiling/deobfuscator.cc
index ba58dfa..378677e 100644
--- a/src/profiling/deobfuscator.cc
+++ b/src/profiling/deobfuscator.cc
@@ -159,8 +159,10 @@
// See https://www.guardsquare.com/en/products/proguard/manual/retrace for the
// file format we are parsing.
base::Status ProguardParser::AddLine(std::string line) {
- if (line.length() == 0 || line[0] == '#')
+ auto first_ch_pos = line.find_first_not_of(" \t");
+ if (first_ch_pos == std::string::npos || line[first_ch_pos] == '#')
return base::Status();
+
bool is_member = line[0] == ' ';
if (is_member && !current_class_) {
return base::Status(
diff --git a/src/profiling/deobfuscator_unittest.cc b/src/profiling/deobfuscator_unittest.cc
index 02a0e8d..11b267c 100644
--- a/src/profiling/deobfuscator_unittest.cc
+++ b/src/profiling/deobfuscator_unittest.cc
@@ -71,12 +71,11 @@
ASSERT_TRUE(
p.AddLine(" android.arch.core.executor.TaskExecutor mDelegate -> b")
.ok());
- std::map<std::string, std::string> deobfuscated_fields{{"b", "mDelegate"}};
- ASSERT_THAT(
+ EXPECT_THAT(
p.ConsumeMapping(),
ElementsAre(std::pair<std::string, ObfuscatedClass>(
"android.arch.a.a.a", {"android.arch.core.executor.ArchTaskExecutor",
- std::move(deobfuscated_fields),
+ {{"b", "mDelegate"}},
{}})));
}
@@ -224,6 +223,25 @@
.ok());
}
+TEST(ProguardParserTest, EmptyLinesAndComments) {
+ ProguardParser p;
+ const char input[] = R"(
+# comment
+
+Example$$Class -> C:
+
+ int first -> q
+ # indented comment
+ long second -> o
+)";
+
+ ASSERT_TRUE(p.AddLines(std::string(input)));
+ EXPECT_THAT(
+ p.ConsumeMapping(),
+ ElementsAre(std::pair<std::string, ObfuscatedClass>(
+ "C", {"Example$$Class", {{"q", "first"}, {"o", "second"}}, {}})));
+}
+
} // namespace
} // namespace profiling
} // namespace perfetto
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 45e9774..0961c10 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -54,6 +54,19 @@
]
}
+static_library("demangle") {
+ sources = [ "demangle.cc" ]
+ deps = [
+ "../../gn:default_deps",
+ "../../include/perfetto/base",
+ "../../include/perfetto/ext/base",
+ ]
+ public_deps = [ "../../include/perfetto/ext/trace_processor:demangle" ]
+ if (enable_perfetto_llvm_demangle) {
+ deps += [ "../../gn:llvm_demangle" ]
+ }
+}
+
source_set("ftrace_descriptors") {
sources = [
"importers/ftrace/ftrace_descriptors.cc",
@@ -330,6 +343,7 @@
]
deps = [
+ ":demangle",
":export_json",
":metatrace",
":storage_full",
diff --git a/src/trace_processor/demangle.cc b/src/trace_processor/demangle.cc
new file mode 100644
index 0000000..c44f834
--- /dev/null
+++ b/src/trace_processor/demangle.cc
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "perfetto/ext/trace_processor/demangle.h"
+
+#include <string.h>
+#include <string>
+
+#include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_LLVM_DEMANGLE)
+#include "llvm/Demangle/Demangle.h"
+#elif !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <cxxabi.h>
+#endif
+
+namespace perfetto {
+namespace trace_processor {
+namespace demangle {
+
+// Implementation depends on platform and build config. If llvm demangling
+// sources are available, use them. That is the most portable and handles more
+// than just Itanium mangling (e.g. Rust's _R scheme). Otherwise use the c++
+// standard library demangling if it implements the appropriate ABI. This
+// excludes Windows builds, where we therefore never demangle.
+// TODO(rsavitski): consider reimplementing llvm::demangle inline as it's
+// wrapping in std::strings a set of per-scheme demangling functions that
+// operate on C strings. Right now we're introducing yet another layer that
+// undoes that conversion.
+std::unique_ptr<char, base::FreeDeleter> Demangle(const char* mangled_name) {
+#if PERFETTO_BUILDFLAG(PERFETTO_LLVM_DEMANGLE)
+ std::string input(mangled_name);
+ std::string demangled = llvm::demangle(input);
+ if (demangled == input)
+ return nullptr; // demangling unsuccessful
+
+ std::unique_ptr<char, base::FreeDeleter> output(
+ static_cast<char*>(malloc(demangled.size() + 1)));
+ if (!output)
+ return nullptr;
+ memcpy(output.get(), demangled.c_str(), demangled.size() + 1);
+ return output;
+
+#elif !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ int ignored = 0;
+ return std::unique_ptr<char, base::FreeDeleter>(
+ abi::__cxa_demangle(mangled_name, nullptr, nullptr, &ignored));
+
+#else
+ return nullptr;
+#endif
+}
+
+} // namespace demangle
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/common/BUILD.gn b/src/trace_processor/importers/common/BUILD.gn
index 534c2bb..7048b96 100644
--- a/src/trace_processor/importers/common/BUILD.gn
+++ b/src/trace_processor/importers/common/BUILD.gn
@@ -41,6 +41,7 @@
]
public_deps = [
"../:gen_cc_config_descriptor",
+ "../../util:proto_to_args_parser",
"../../util:protozero_to_text",
]
deps = [
diff --git a/src/trace_processor/importers/common/args_translation_table.cc b/src/trace_processor/importers/common/args_translation_table.cc
index ee91b30..216305d 100644
--- a/src/trace_processor/importers/common/args_translation_table.cc
+++ b/src/trace_processor/importers/common/args_translation_table.cc
@@ -19,6 +19,36 @@
namespace perfetto {
namespace trace_processor {
+constexpr char ArgsTranslationTable::kChromeHistogramHashKey[];
+constexpr char ArgsTranslationTable::kChromeHistogramNameKey[];
+
+ArgsTranslationTable::ArgsTranslationTable(TraceStorage* storage)
+ : storage_(storage),
+ interned_chrome_histogram_name_key_(
+ storage->InternString(kChromeHistogramNameKey)) {}
+
+bool ArgsTranslationTable::TranslateUnsignedIntegerArg(
+ const Key& key,
+ uint64_t value,
+ ArgsTracker::BoundInserter& inserter) {
+ if (key.key == kChromeHistogramHashKey) {
+ const base::Optional<base::StringView> translated_value =
+ TranslateChromeHistogramHash(value);
+ if (translated_value) {
+ inserter.AddArg(
+ interned_chrome_histogram_name_key_,
+ Variadic::String(storage_->InternString(*translated_value)));
+ }
+ }
+ return false;
+}
+
+base::Optional<base::StringView>
+ArgsTranslationTable::TranslateChromeHistogramHashForTesting(
+ uint64_t hash) const {
+ return TranslateChromeHistogramHash(hash);
+}
+
base::Optional<base::StringView>
ArgsTranslationTable::TranslateChromeHistogramHash(uint64_t hash) const {
auto* value = chrome_histogram_hash_to_name_.Find(hash);
diff --git a/src/trace_processor/importers/common/args_translation_table.h b/src/trace_processor/importers/common/args_translation_table.h
index 0e34e2c..aac2bb6 100644
--- a/src/trace_processor/importers/common/args_translation_table.h
+++ b/src/trace_processor/importers/common/args_translation_table.h
@@ -22,6 +22,9 @@
#include "perfetto/ext/base/flat_hash_map.h"
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/string_view.h"
+#include "src/trace_processor/importers/common/args_tracker.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/util/proto_to_args_parser.h"
namespace perfetto {
namespace trace_processor {
@@ -30,18 +33,34 @@
// to map for example hashes to their names.
class ArgsTranslationTable {
public:
+ using Key = util::ProtoToArgsParser::Key;
+
+ ArgsTranslationTable(TraceStorage* storage);
+
+ // Returns true if the translation table fully handles the arg, in which case
+ // the original arg doesn't need to be processed. This function has not added
+ // anything if returning false.
+ bool TranslateUnsignedIntegerArg(const Key& key,
+ uint64_t value,
+ ArgsTracker::BoundInserter& inserter);
+
+ void AddChromeHistogramTranslationRule(uint64_t hash, base::StringView name);
+
+ base::Optional<base::StringView> TranslateChromeHistogramHashForTesting(
+ uint64_t hash) const;
+
+ private:
static constexpr char kChromeHistogramHashKey[] =
"chrome_histogram_sample.name_hash";
static constexpr char kChromeHistogramNameKey[] =
"chrome_histogram_sample.name";
+ TraceStorage* storage_;
+ StringId interned_chrome_histogram_name_key_;
+ base::FlatHashMap<uint64_t, std::string> chrome_histogram_hash_to_name_;
+
base::Optional<base::StringView> TranslateChromeHistogramHash(
uint64_t hash) const;
-
- void AddChromeHistogramTranslationRule(uint64_t hash, base::StringView name);
-
- private:
- base::FlatHashMap<uint64_t, std::string> chrome_histogram_hash_to_name_;
};
} // namespace trace_processor
diff --git a/src/trace_processor/importers/common/args_translation_table_unittest.cc b/src/trace_processor/importers/common/args_translation_table_unittest.cc
index 15dddff..08bc458 100644
--- a/src/trace_processor/importers/common/args_translation_table_unittest.cc
+++ b/src/trace_processor/importers/common/args_translation_table_unittest.cc
@@ -22,19 +22,21 @@
namespace {
TEST(ArgsTranslationTable, EmptyTableByDefault) {
- ArgsTranslationTable table;
- EXPECT_EQ(table.TranslateChromeHistogramHash(1), base::nullopt);
+ TraceStorage storage;
+ ArgsTranslationTable table(&storage);
+ EXPECT_EQ(table.TranslateChromeHistogramHashForTesting(1), base::nullopt);
}
TEST(ArgsTranslationTable, TranslatesHashes) {
- ArgsTranslationTable table;
+ TraceStorage storage;
+ ArgsTranslationTable table(&storage);
table.AddChromeHistogramTranslationRule(1, "hash1");
table.AddChromeHistogramTranslationRule(10, "hash2");
- EXPECT_EQ(table.TranslateChromeHistogramHash(1),
+ EXPECT_EQ(table.TranslateChromeHistogramHashForTesting(1),
base::Optional<base::StringView>("hash1"));
- EXPECT_EQ(table.TranslateChromeHistogramHash(10),
+ EXPECT_EQ(table.TranslateChromeHistogramHashForTesting(10),
base::Optional<base::StringView>("hash2"));
- EXPECT_EQ(table.TranslateChromeHistogramHash(2), base::nullopt);
+ EXPECT_EQ(table.TranslateChromeHistogramHashForTesting(2), base::nullopt);
}
} // namespace
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index f90e808..f83aede 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -167,6 +167,7 @@
cros_ec_arg_num_id_(context->storage->InternString("ec_num")),
cros_ec_arg_ec_id_(context->storage->InternString("ec_delta")),
cros_ec_arg_sample_ts_id_(context->storage->InternString("sample_ts")),
+ ufs_clkgating_id_(context->storage->InternString("UFS clkgating (OFF/REQ_OFF/REQ_ON/ON)")),
ufs_command_count_id_(context->storage->InternString("UFS Command Count")) {
// Build the lookup table for the strings inside ftrace events (e.g. the
// name of ftrace event fields and the names of their args).
@@ -735,6 +736,10 @@
ParseWakeSourceDeactivate(ts, data);
break;
}
+ case FtraceEvent::kUfshcdClkGatingFieldNumber: {
+ ParseUfshcdClkGating(ts, data);
+ break;
+ }
default:
break;
}
@@ -1986,6 +1991,31 @@
args_inserter);
}
+void FtraceParser::ParseUfshcdClkGating(int64_t timestamp,
+ protozero::ConstBytes blob) {
+ protos::pbzero::UfshcdClkGatingFtraceEvent::Decoder evt(blob.data, blob.size);
+ int32_t clk_state = 0;
+
+ switch (evt.state()) {
+ case 1:
+ // Change ON state to 3
+ clk_state = 3;
+ break;
+ case 2:
+ // Change REQ_OFF state to 1
+ clk_state = 1;
+ break;
+ case 3:
+ // Change REQ_ON state to 2
+ clk_state = 2;
+ break;
+ }
+ TrackId track = context_->track_tracker->InternGlobalCounterTrack(
+ ufs_clkgating_id_);
+ context_->event_tracker->PushCounter(timestamp, static_cast<double>(clk_state),
+ track);
+}
+
void FtraceParser::ParseUfshcdCommand(int64_t timestamp,
protozero::ConstBytes blob) {
protos::pbzero::UfshcdCommandFtraceEvent::Decoder evt(blob.data, blob.size);
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.h b/src/trace_processor/importers/ftrace/ftrace_parser.h
index 723be1c..8dff094 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.h
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.h
@@ -170,6 +170,7 @@
void ParseCpuFrequencyLimits(int64_t timestamp, protozero::ConstBytes);
void ParseKfreeSkb(int64_t timestamp, protozero::ConstBytes);
void ParseUfshcdCommand(int64_t timestamp, protozero::ConstBytes);
+ void ParseUfshcdClkGating(int64_t timestamp, protozero::ConstBytes);
void ParseCrosEcSensorhubData(int64_t timestamp, protozero::ConstBytes);
void ParseWakeSourceActivate(int64_t timestamp, protozero::ConstBytes);
@@ -225,6 +226,7 @@
const StringId cros_ec_arg_num_id_;
const StringId cros_ec_arg_ec_id_;
const StringId cros_ec_arg_sample_ts_id_;
+ const StringId ufs_clkgating_id_;
const StringId ufs_command_count_id_;
struct FtraceMessageStrings {
diff --git a/src/trace_processor/importers/proto/track_event_parser.cc b/src/trace_processor/importers/proto/track_event_parser.cc
index f264d27..faa8261 100644
--- a/src/trace_processor/importers/proto/track_event_parser.cc
+++ b/src/trace_processor/importers/proto/track_event_parser.cc
@@ -24,6 +24,7 @@
#include "perfetto/ext/base/string_writer.h"
#include "perfetto/trace_processor/status.h"
#include "src/trace_processor/importers/common/args_tracker.h"
+#include "src/trace_processor/importers/common/args_translation_table.h"
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/flow_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
@@ -70,10 +71,13 @@
public:
TrackEventArgsParser(BoundInserter& inserter,
TraceStorage& storage,
- PacketSequenceStateGeneration& sequence_state)
+ PacketSequenceStateGeneration& sequence_state,
+ ArgsTranslationTable& args_translation_table)
: inserter_(inserter),
storage_(storage),
- sequence_state_(sequence_state) {}
+ sequence_state_(sequence_state),
+ args_translation_table_(args_translation_table) {}
+
~TrackEventArgsParser() override;
using Key = util::ProtoToArgsParser::Key;
@@ -84,6 +88,10 @@
Variadic::Integer(value));
}
void AddUnsignedInteger(const Key& key, uint64_t value) final {
+ if (args_translation_table_.TranslateUnsignedIntegerArg(key, value,
+ inserter_)) {
+ return;
+ }
inserter_.AddArg(storage_.InternString(base::StringView(key.flat_key)),
storage_.InternString(base::StringView(key.key)),
Variadic::UnsignedInteger(value));
@@ -141,6 +149,7 @@
BoundInserter& inserter_;
TraceStorage& storage_;
PacketSequenceStateGeneration& sequence_state_;
+ ArgsTranslationTable& args_translation_table_;
};
TrackEventArgsParser::~TrackEventArgsParser() = default;
@@ -1121,7 +1130,8 @@
ParseHistogramName(event_.chrome_histogram_sample(), inserter));
}
- TrackEventArgsParser args_writer(*inserter, *storage_, *sequence_state_);
+ TrackEventArgsParser args_writer(*inserter, *storage_, *sequence_state_,
+ *context_->args_translation_table);
int unknown_extensions = 0;
log_errors(parser_->args_parser_.ParseMessage(
blob_, ".perfetto.protos.TrackEvent", &parser_->reflect_fields_,
diff --git a/src/trace_processor/metrics/sql/BUILD.gn b/src/trace_processor/metrics/sql/BUILD.gn
index fbbb41c..5c07ca1 100644
--- a/src/trace_processor/metrics/sql/BUILD.gn
+++ b/src/trace_processor/metrics/sql/BUILD.gn
@@ -84,8 +84,10 @@
"chrome/actual_power_by_category.sql",
"chrome/actual_power_by_rail_mode.sql",
"chrome/chrome_event_metadata.sql",
+ "chrome/chrome_histogram_hashes.sql",
"chrome/chrome_processes.sql",
"chrome/chrome_thread_slice.sql",
+ "chrome/chrome_user_event_hashes.sql",
"chrome/cpu_time_by_category.sql",
"chrome/cpu_time_by_rail_mode.sql",
"chrome/estimated_power_by_category.sql",
diff --git a/src/trace_processor/metrics/sql/chrome/chrome_histogram_hashes.sql b/src/trace_processor/metrics/sql/chrome/chrome_histogram_hashes.sql
new file mode 100644
index 0000000..ef5d918
--- /dev/null
+++ b/src/trace_processor/metrics/sql/chrome/chrome_histogram_hashes.sql
@@ -0,0 +1,26 @@
+--
+-- Copyright 2022 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+DROP VIEW IF EXISTS chrome_histogram_hashes_output;
+
+CREATE VIEW chrome_histogram_hashes_output AS
+SELECT ChromeHistogramHashes(
+ 'hash', (
+ SELECT RepeatedField(int_value)
+ FROM args
+ WHERE key = 'chrome_histogram_sample.name_hash'
+ ORDER BY int_value
+ )
+);
diff --git a/src/trace_processor/metrics/sql/chrome/chrome_user_event_hashes.sql b/src/trace_processor/metrics/sql/chrome/chrome_user_event_hashes.sql
new file mode 100644
index 0000000..005e2ad
--- /dev/null
+++ b/src/trace_processor/metrics/sql/chrome/chrome_user_event_hashes.sql
@@ -0,0 +1,26 @@
+--
+-- Copyright 2022 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+DROP VIEW IF EXISTS chrome_user_event_hashes_output;
+
+CREATE VIEW chrome_user_event_hashes_output AS
+SELECT ChromeUserEventHashes(
+ 'action_hash', (
+ SELECT RepeatedField(int_value)
+ FROM args
+ WHERE key = 'chrome_user_event.action_hash'
+ ORDER BY int_value
+ )
+);
diff --git a/src/trace_processor/trace_database_integrationtest.cc b/src/trace_processor/trace_database_integrationtest.cc
index 6a59ca6..4df80b9 100644
--- a/src/trace_processor/trace_database_integrationtest.cc
+++ b/src/trace_processor/trace_database_integrationtest.cc
@@ -179,7 +179,8 @@
ASSERT_EQ(it.Get(0).long_value, static_cast<int64_t>(0xa9cb070fdc15f7a4));
}
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#if !PERFETTO_BUILDFLAG(PERFETTO_LLVM_DEMANGLE) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#define MAYBE_Demangle DISABLED_Demangle
#else
#define MAYBE_Demangle Demangle
@@ -187,15 +188,38 @@
TEST_F(TraceProcessorIntegrationTest, MAYBE_Demangle) {
auto it = Query("select DEMANGLE('_Znwm')");
ASSERT_TRUE(it.Next());
- ASSERT_STRCASEEQ(it.Get(0).string_value, "operator new(unsigned long)");
+ EXPECT_STRCASEEQ(it.Get(0).string_value, "operator new(unsigned long)");
it = Query("select DEMANGLE('_ZN3art6Thread14CreateCallbackEPv')");
ASSERT_TRUE(it.Next());
- ASSERT_STRCASEEQ(it.Get(0).string_value,
+ EXPECT_STRCASEEQ(it.Get(0).string_value,
"art::Thread::CreateCallback(void*)");
it = Query("select DEMANGLE('test')");
ASSERT_TRUE(it.Next());
+ EXPECT_TRUE(it.Get(0).is_null());
+}
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_LLVM_DEMANGLE)
+#define MAYBE_DemangleRust DISABLED_DemangleRust
+#else
+#define MAYBE_DemangleRust DemangleRust
+#endif
+TEST_F(TraceProcessorIntegrationTest, MAYBE_DemangleRust) {
+ auto it = Query(
+ "select DEMANGLE("
+ "'_RNvNvMs0_NtNtNtCsg1Z12QU66Yk_3std3sys4unix6threadNtB7_"
+ "6Thread3new12thread_start')");
+ ASSERT_TRUE(it.Next());
+ EXPECT_STRCASEEQ(it.Get(0).string_value,
+ "<std::sys::unix::thread::Thread>::new::thread_start");
+
+ it = Query("select DEMANGLE('_RNvCsdV139EorvfX_14keystore2_main4main')");
+ ASSERT_TRUE(it.Next());
+ ASSERT_STRCASEEQ(it.Get(0).string_value, "keystore2_main::main");
+
+ it = Query("select DEMANGLE('_R')");
+ ASSERT_TRUE(it.Next());
ASSERT_TRUE(it.Get(0).is_null());
}
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 42d1d4e..9ace9ee 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -24,6 +24,7 @@
#include "perfetto/base/time.h"
#include "perfetto/ext/base/string_splitter.h"
#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/ext/trace_processor/demangle.h"
#include "src/trace_processor/dynamic/ancestor_generator.h"
#include "src/trace_processor/dynamic/connected_flow_generator.h"
#include "src/trace_processor/dynamic/descendant_generator.h"
@@ -71,9 +72,6 @@
#include "src/trace_processor/metrics/metrics.h"
#include "src/trace_processor/metrics/sql/amalgamated_sql_metrics.h"
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <cxxabi.h>
-#endif
// In Android and Chromium tree builds, we don't have the percentile module.
// Just don't include it.
@@ -422,20 +420,16 @@
if (sqlite3_value_type(value) != SQLITE_TEXT)
return base::ErrStatus("Unsupported type of arg passed to DEMANGLE");
- const char* ptr = reinterpret_cast<const char*>(sqlite3_value_text(value));
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
- int ignored = 0;
- // This memory was allocated by malloc and will be passed to SQLite to free.
- char* demangled_name = abi::__cxa_demangle(ptr, nullptr, nullptr, &ignored);
- if (!demangled_name)
+ const char* mangled =
+ reinterpret_cast<const char*>(sqlite3_value_text(value));
+
+ std::unique_ptr<char, base::FreeDeleter> demangled =
+ demangle::Demangle(mangled);
+ if (!demangled)
return base::OkStatus();
destructors.string_destructor = free;
- out = SqlValue::String(demangled_name);
-#else
- destructors.string_destructor = sqlite_utils::kSqliteTransient;
- out = SqlValue::String(ptr);
-#endif
+ out = SqlValue::String(demangled.release());
return base::OkStatus();
}
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index 2c1afb7..51c9e18 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -600,8 +600,9 @@
auto dur = query_end - query_start;
PERFETTO_ILOG(
- "Query execution time: %lld ms",
- std::chrono::duration_cast<std::chrono::milliseconds>(dur).count());
+ "Query execution time: %" PRIi64 " ms",
+ static_cast<int64_t>(
+ std::chrono::duration_cast<std::chrono::milliseconds>(dur).count()));
return base::OkStatus();
}
diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc
index cdd671e..47693df 100644
--- a/src/trace_processor/trace_processor_storage_impl.cc
+++ b/src/trace_processor/trace_processor_storage_impl.cc
@@ -50,7 +50,8 @@
context_.track_tracker.reset(new TrackTracker(&context_));
context_.async_track_set_tracker.reset(new AsyncTrackSetTracker(&context_));
context_.args_tracker.reset(new ArgsTracker(&context_));
- context_.args_translation_table.reset(new ArgsTranslationTable());
+ context_.args_translation_table.reset(
+ new ArgsTranslationTable(context_.storage.get()));
context_.slice_tracker.reset(new SliceTracker(&context_));
context_.flow_tracker.reset(new FlowTracker(&context_));
context_.event_tracker.reset(new EventTracker(&context_));
diff --git a/test/trace_processor/chrome/chrome_histogram_hashes.out b/test/trace_processor/chrome/chrome_histogram_hashes.out
new file mode 100644
index 0000000..4cd61a5
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_histogram_hashes.out
@@ -0,0 +1,4 @@
+[perfetto.protos.chrome_histogram_hashes]: {
+ hash: 10
+ hash: 20
+}
diff --git a/test/trace_processor/chrome/chrome_histogram_hashes.textproto b/test/trace_processor/chrome/chrome_histogram_hashes.textproto
new file mode 100644
index 0000000..dfc1260
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_histogram_hashes.textproto
@@ -0,0 +1,27 @@
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ incremental_state_cleared: true
+ track_event {
+ categories: "cat1"
+ type: 3
+ name_iid: 1
+ chrome_histogram_sample {
+ name_hash: 10
+ sample: 100
+ }
+ }
+}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ incremental_state_cleared: true
+ track_event {
+ categories: "cat2"
+ type: 3
+ name_iid: 2
+ chrome_histogram_sample {
+ name_hash: 20
+ }
+ }
+}
diff --git a/test/trace_processor/chrome/chrome_user_event_hashes.out b/test/trace_processor/chrome/chrome_user_event_hashes.out
new file mode 100644
index 0000000..69ca70f
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_user_event_hashes.out
@@ -0,0 +1,5 @@
+[perfetto.protos.chrome_user_event_hashes]: {
+ action_hash: 10
+ action_hash: 20
+}
+
diff --git a/test/trace_processor/chrome/chrome_user_event_hashes.textproto b/test/trace_processor/chrome/chrome_user_event_hashes.textproto
new file mode 100644
index 0000000..41b21b9
--- /dev/null
+++ b/test/trace_processor/chrome/chrome_user_event_hashes.textproto
@@ -0,0 +1,27 @@
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ incremental_state_cleared: true
+ track_event {
+ categories: "cat1"
+ type: 3
+ name_iid: 1
+ chrome_user_event {
+ action_hash: 10
+ }
+ }
+}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ incremental_state_cleared: true
+ track_event {
+ categories: "cat2"
+ type: 3
+ name_iid: 2
+ chrome_user_event {
+ action_hash: 20
+ }
+ }
+}
+
diff --git a/test/trace_processor/chrome/index b/test/trace_processor/chrome/index
index 7e6856c..9bdeb89 100644
--- a/test/trace_processor/chrome/index
+++ b/test/trace_processor/chrome/index
@@ -54,3 +54,9 @@
../../data/chrome_android_systrace.pftrace chrome_processes.sql chrome_processes_android_systrace.out
../../data/chrome_scroll_without_vsync.pftrace chrome_threads.sql chrome_threads.out
../../data/chrome_android_systrace.pftrace chrome_threads.sql chrome_threads_android_systrace.out
+
+# Chrome histogram hashes
+chrome_histogram_hashes.textproto chrome_histogram_hashes chrome_histogram_hashes.out
+
+# Chrome user events
+chrome_user_event_hashes.textproto chrome_user_event_hashes chrome_user_event_hashes.out
diff --git a/test/trace_processor/include_index b/test/trace_processor/include_index
index 4152371..593e338 100644
--- a/test/trace_processor/include_index
+++ b/test/trace_processor/include_index
@@ -1,11 +1,14 @@
camera/index
-cros/index
chrome/index
+cros/index
dynamic/index
fuchsia/index
graphics/index
+io/index
memory/index
+network/index
parsing/index
+performance/index
power/index
process_tracking/index
profiling/index
@@ -14,6 +17,4 @@
startup/index
tables/index
track_event/index
-network/index
-performance/index
-io/index
+translation/index
diff --git a/test/trace_processor/translation/chrome_histogram.out b/test/trace_processor/translation/chrome_histogram.out
new file mode 100644
index 0000000..e0c4dec
--- /dev/null
+++ b/test/trace_processor/translation/chrome_histogram.out
@@ -0,0 +1,10 @@
+"flat_key","key","int_value","string_value"
+"is_root_in_scope","is_root_in_scope",1,"[NULL]"
+"source","source","[NULL]","descriptor"
+"source_id","source_id",0,"[NULL]"
+"chrome_histogram_sample.name","chrome_histogram_sample.name","[NULL]","histogram_name1"
+"chrome_histogram_sample.name_hash","chrome_histogram_sample.name_hash",10,"[NULL]"
+"chrome_histogram_sample.sample","chrome_histogram_sample.sample",100,"[NULL]"
+"chrome_histogram_sample.name","chrome_histogram_sample.name","[NULL]","histogram_name2"
+"chrome_histogram_sample.name_hash","chrome_histogram_sample.name_hash",20,"[NULL]"
+"chrome_histogram_sample.name_hash","chrome_histogram_sample.name_hash",30,"[NULL]"
diff --git a/test/trace_processor/translation/chrome_histogram.sql b/test/trace_processor/translation/chrome_histogram.sql
new file mode 100644
index 0000000..63c2492
--- /dev/null
+++ b/test/trace_processor/translation/chrome_histogram.sql
@@ -0,0 +1,16 @@
+--
+-- Copyright 2022 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+select flat_key, key, int_value, string_value from args order by arg_set_id, key asc;
diff --git a/test/trace_processor/translation/chrome_histogram.textproto b/test/trace_processor/translation/chrome_histogram.textproto
new file mode 100644
index 0000000..fb6a04e
--- /dev/null
+++ b/test/trace_processor/translation/chrome_histogram.textproto
@@ -0,0 +1,53 @@
+# Chrome histogram hashes translation rules
+packet {
+ translation_table {
+ chrome_histogram {
+ hash_to_name { key: 10 value: "histogram_name1" }
+ hash_to_name { key: 20 value: "histogram_name2" }
+ }
+ }
+}
+# Known histogram hash, should be translated to a name
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ incremental_state_cleared: true
+ track_event {
+ categories: "cat1"
+ type: 3
+ name_iid: 1
+ chrome_histogram_sample {
+ name_hash: 10
+ sample: 100
+ }
+ }
+}
+# Another known hash, should be translated to a name
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ incremental_state_cleared: true
+ track_event {
+ categories: "cat2"
+ type: 3
+ name_iid: 2
+ chrome_histogram_sample {
+ name_hash: 20
+ }
+ }
+}
+# Unknown hash, should not be translated to any name
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ incremental_state_cleared: true
+ track_event {
+ categories: "cat3"
+ type: 3
+ name_iid: 3
+ chrome_histogram_sample {
+ name_hash: 30
+ }
+ }
+}
+
diff --git a/test/trace_processor/translation/index b/test/trace_processor/translation/index
new file mode 100644
index 0000000..77fd3d4
--- /dev/null
+++ b/test/trace_processor/translation/index
@@ -0,0 +1 @@
+chrome_histogram.textproto chrome_histogram.sql chrome_histogram.out
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index 0345604..a3e829f 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -96,6 +96,7 @@
'//:libperfetto',
'//:libperfetto_client_experimental',
'//protos/perfetto/trace:perfetto_trace_protos',
+ '//src/trace_processor:demangle',
'//src/trace_processor:trace_processor_shell',
]
diff --git a/tools/gen_bazel b/tools/gen_bazel
index 79bd4e8..c911be4 100755
--- a/tools/gen_bazel
+++ b/tools/gen_bazel
@@ -46,6 +46,7 @@
'enable_perfetto_heapprofd=false',
'enable_perfetto_traced_perf=false',
'perfetto_force_dcheck="off"',
+ 'enable_perfetto_llvm_demangle=false',
])
# Default targets to translate to the blueprint file.
@@ -113,6 +114,10 @@
'PERFETTO_CONFIG.deps.sqlite_ext_percentile'
],
'//gn:zlib': ['PERFETTO_CONFIG.deps.zlib'],
+ '//gn:llvm_demangle': ['PERFETTO_CONFIG.deps.llvm_demangle'],
+ '//src/trace_processor:demangle': [
+ 'PERFETTO_CONFIG.deps.demangle_wrapper'
+ ],
'//src/trace_processor/metrics/sql:gen_amalgamated_sql_metrics': [[
':cc_amalgamated_sql_metrics'
]],
diff --git a/tools/install-build-deps b/tools/install-build-deps
index bd9100c..96a2f65 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -211,6 +211,17 @@
'all',
'all'),
+ # Archive with only the demangling sources from llvm-project.
+ # See tools/repackage_llvm_demangler.sh on how to update this.
+ # File suffix is the git reference to the commit at which we rearchived the
+ # sources, as hosted on https://llvm.googlesource.com/llvm-project.
+ # If updating the version, also update bazel/deps.bzl.
+ Dependency(
+ 'buildtools/llvm-project.tgz',
+ 'https://storage.googleapis.com/perfetto/llvm-project-3b4c59c156919902c785ce3cbae0eee2ee53064d.tgz',
+ 'f4a52e7f36edd7cacc844d5ae0e5f60b6f57c5afc40683e99f295886c9ce8ff4',
+ 'all', 'all'),
+
# These dependencies are for libunwindstack, which is used by src/profiling.
Dependency('buildtools/android-core',
'https://android.googlesource.com/platform/system/core.git',
diff --git a/ui/release/channels.json b/ui/release/channels.json
index 1540749..156f53f 100644
--- a/ui/release/channels.json
+++ b/ui/release/channels.json
@@ -6,7 +6,7 @@
},
{
"name": "canary",
- "rev": "433c9fe808b23a28f3bcfaaf026830d908be4104"
+ "rev": "6c78846fe39842faac064421b1e1c745a14c516a"
},
{
"name": "autopush",
diff --git a/ui/src/assets/details.scss b/ui/src/assets/details.scss
index 58a8e42..a6ff835 100644
--- a/ui/src/assets/details.scss
+++ b/ui/src/assets/details.scss
@@ -396,6 +396,7 @@
display: grid;
grid-template-rows: auto 1fr;
font-family: 'Roboto Condensed', sans-serif;
+ user-select: text;
header {
position: sticky;
diff --git a/ui/src/assets/modal.scss b/ui/src/assets/modal.scss
index f65961e..20a80a8 100644
--- a/ui/src/assets/modal.scss
+++ b/ui/src/assets/modal.scss
@@ -147,7 +147,8 @@
animation: mmfadeIn .3s cubic-bezier(0.0, 0.0, 0.2, 1);
}
-.micromodal-slide[aria-hidden="false"] .modal-container {
+.micromodal-slide[aria-hidden="false"] .modal-container,
+.micromodal-slide[aria-hidden="false"] .partial-modal-container {
animation: mmslideIn .3s cubic-bezier(0, 0, .2, 1);
}
@@ -155,11 +156,13 @@
animation: mmfadeOut .3s cubic-bezier(0.0, 0.0, 0.2, 1);
}
-.micromodal-slide[aria-hidden="true"] .modal-container {
+.micromodal-slide[aria-hidden="true"] .modal-container,
+.micromodal-slide[aria-hidden="true"] .partial-modal-container {
animation: mmslideOut .3s cubic-bezier(0, 0, .2, 1);
}
.micromodal-slide .modal-container,
+.micromodal-slide .partial-modal-container,
.micromodal-slide .modal-overlay {
will-change: transform;
}
@@ -215,3 +218,32 @@
.modal-small {
font-size: 11px;
}
+
+.partial-modal-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0,0,0,0.6);
+ display: flex;
+ justify-content: center;
+ z-index: 999;
+}
+
+.partial-modal-container {
+ background-color: #fff;
+ margin-top: 1vh;
+ padding: 30px 30px 20px 30px;
+ max-width: 90vw;
+ height: fit-content;
+ border-radius: 4px;
+ overflow-y: auto;
+ box-sizing: border-box;
+}
+
+.partial-modal-header {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index bd914e0..8366f65 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -1006,6 +1006,10 @@
setPivotStateReduxState(
state: StateDraft, args: {pivotTableState: PivotTableReduxState}) {
state.pivotTableRedux = args.pivotTableState;
+ },
+
+ dismissFlamegraphModal(state: StateDraft, _: {}) {
+ state.flamegraphModalDismissed = true;
}
};
diff --git a/ui/src/common/empty_state.ts b/ui/src/common/empty_state.ts
index cc57df5..ac287d2 100644
--- a/ui/src/common/empty_state.ts
+++ b/ui/src/common/empty_state.ts
@@ -97,6 +97,7 @@
recordingInProgress: false,
recordingCancelled: false,
extensionInstalled: false,
+ flamegraphModalDismissed: false,
recordingTarget: recordTargetStore.getValidTarget(),
availableAdbDevices: [],
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index da6809b..ef7edcd 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -79,7 +79,8 @@
// typed key/value because a `Map` does not preserve type during
// serialisation+deserialisation.
// 15: Added state for Pivot Table V2
-export const STATE_VERSION = 15;
+// 16: Added boolean tracking if the flamegraph modal was dismissed
+export const STATE_VERSION = 16;
export const SCROLLING_TRACK_GROUP = 'ScrollingTracks';
@@ -466,6 +467,7 @@
recordingInProgress: boolean;
recordingCancelled: boolean;
extensionInstalled: boolean;
+ flamegraphModalDismissed: boolean;
recordingTarget: RecordingTarget;
availableAdbDevices: AdbRecordingTarget[];
lastRecordingError?: string;
diff --git a/ui/src/controller/flamegraph_controller.ts b/ui/src/controller/flamegraph_controller.ts
index cb7ea7e..cb74e41 100644
--- a/ui/src/controller/flamegraph_controller.ts
+++ b/ui/src/controller/flamegraph_controller.ts
@@ -101,7 +101,7 @@
if (hasAreaChanged) {
const upids = [];
if (!area) {
- publishFlamegraphDetails(
+ this.checkCompletionAndPublishFlamegraph(
{...frontendGlobals.flamegraphDetails, isInAreaSelection: false});
return;
}
@@ -114,7 +114,7 @@
upids.push((trackState.config as PerfSampleConfig).upid);
}
if (upids.length === 0) {
- publishFlamegraphDetails(
+ this.checkCompletionAndPublishFlamegraph(
{...frontendGlobals.flamegraphDetails, isInAreaSelection: false});
return;
}
@@ -228,7 +228,17 @@
this.flamegraphDetails.expandedCallsite = expandedCallsite;
this.flamegraphDetails.viewingOption = viewingOption;
this.flamegraphDetails.isInAreaSelection = hasAreaChanged;
- publishFlamegraphDetails(this.flamegraphDetails);
+ this.checkCompletionAndPublishFlamegraph(this.flamegraphDetails);
+ }
+
+ private async checkCompletionAndPublishFlamegraph(flamegraphDetails:
+ FlamegraphDetails) {
+ flamegraphDetails.graphIncomplete =
+ (await this.args.engine.query(`select value from stats
+ where severity = 'error' and name = 'heap_graph_non_finalized_graph'`))
+ .firstRow({value: NUM})
+ .value > 0;
+ publishFlamegraphDetails(flamegraphDetails);
}
async getFlamegraphData(
diff --git a/ui/src/frontend/flamegraph_panel.ts b/ui/src/frontend/flamegraph_panel.ts
index 35a4d9f..368ab32 100644
--- a/ui/src/frontend/flamegraph_panel.ts
+++ b/ui/src/frontend/flamegraph_panel.ts
@@ -29,8 +29,10 @@
import {PerfettoMouseEvent} from './events';
import {Flamegraph, NodeRendering} from './flamegraph';
import {globals} from './globals';
+import {showPartialModal} from './modal';
import {Panel, PanelSize} from './panel';
import {debounce} from './rate_limiters';
+import {Router} from './router';
import {getCurrentTrace} from './sidebar';
import {convertTraceToPprofAndDownload} from './trace_converter';
@@ -119,6 +121,7 @@
}
}
},
+ this.maybeShowModal(flamegraphDetails.graphIncomplete),
m('.details-panel-heading.flamegraph-profile',
{onclick: (e: MouseEvent) => e.stopPropagation()},
[
@@ -165,6 +168,39 @@
}
}
+
+ private maybeShowModal(graphIncomplete?: boolean): m.Vnode|undefined {
+ if (!graphIncomplete || globals.state.flamegraphModalDismissed) {
+ return undefined;
+ }
+ return showPartialModal({
+ title: 'The flamegraph is incomplete',
+ content:
+ m('div',
+ m('div',
+ 'The current trace does not have a fully formed flamegraph.')),
+ buttons: [
+ {
+ text: 'Show the errors',
+ primary: true,
+ id: 'incomplete_graph_show',
+ action: () => {
+ Router.navigate('#!/info');
+ }
+ },
+ {
+ text: 'Skip',
+ primary: false,
+ id: 'incomplete_graph_skip',
+ action: () => {
+ globals.dispatch(Actions.dismissFlamegraphModal({}));
+ globals.rafScheduler.scheduleFullRedraw();
+ }
+ }
+ ],
+ });
+ }
+
private getTitle(): string {
switch (this.profileType!) {
case ProfileType.NATIVE_HEAP_PROFILE:
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index e5fa7ad..473a945 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -124,6 +124,9 @@
// isInAreaSelection is true if a flamegraph is part of the current area
// selection.
isInAreaSelection?: boolean;
+ // When heap_graph_non_finalized_graph has a count >0, we mark the graph
+ // as incomplete.
+ graphIncomplete?: boolean;
}
export interface CpuProfileDetails {
diff --git a/ui/src/frontend/modal.ts b/ui/src/frontend/modal.ts
index 69482e3..40badd9 100644
--- a/ui/src/frontend/modal.ts
+++ b/ui/src/frontend/modal.ts
@@ -84,3 +84,13 @@
});
return buttons;
}
+
+export function showPartialModal(attrs: ModalDefinition): m.Vnode {
+ return m(
+ '.partial-modal-overlay',
+ {tabindex: -1},
+ m('.partial-modal-container',
+ m('header.partial-modal-header', m('h2.modal-title', attrs.title)),
+ m('main.modal-content', attrs.content),
+ m('footer.modal-footer', ...makeButtons(attrs.buttons))));
+}