Merge "tp: partially revert aosp/2977479" into main
diff --git a/Android.bp b/Android.bp
index a0269f3..a991cc1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -2378,7 +2378,6 @@
":perfetto_src_trace_processor_storage_storage",
":perfetto_src_trace_processor_tables_tables",
":perfetto_src_trace_processor_types_types",
- ":perfetto_src_trace_processor_util_build_id",
":perfetto_src_trace_processor_util_bump_allocator",
":perfetto_src_trace_processor_util_descriptors",
":perfetto_src_trace_processor_util_glob",
@@ -2392,6 +2391,7 @@
":perfetto_src_trace_processor_util_protozero_to_text",
":perfetto_src_trace_processor_util_regex",
":perfetto_src_trace_processor_util_sql_argument",
+ ":perfetto_src_trace_processor_util_stack_traces_util",
":perfetto_src_trace_processor_util_stdlib",
":perfetto_src_trace_processor_util_util",
":perfetto_src_trace_processor_util_zip_reader",
@@ -11110,7 +11110,6 @@
"src/trace_processor/importers/common/event_tracker.cc",
"src/trace_processor/importers/common/flow_tracker.cc",
"src/trace_processor/importers/common/global_args_tracker.cc",
- "src/trace_processor/importers/common/mapping_tracker.cc",
"src/trace_processor/importers/common/metadata_tracker.cc",
"src/trace_processor/importers/common/process_tracker.cc",
"src/trace_processor/importers/common/sched_event_tracker.cc",
@@ -11121,7 +11120,6 @@
"src/trace_processor/importers/common/thread_state_tracker.cc",
"src/trace_processor/importers/common/trace_parser.cc",
"src/trace_processor/importers/common/track_tracker.cc",
- "src/trace_processor/importers/common/virtual_memory_mapping.cc",
],
}
@@ -12066,6 +12064,7 @@
"src/trace_processor/perfetto_sql/stdlib/sched/utilization/process.sql",
"src/trace_processor/perfetto_sql/stdlib/sched/utilization/system.sql",
"src/trace_processor/perfetto_sql/stdlib/sched/utilization/thread.sql",
+ "src/trace_processor/perfetto_sql/stdlib/slices/cpu_time.sql",
"src/trace_processor/perfetto_sql/stdlib/slices/flat_slices.sql",
"src/trace_processor/perfetto_sql/stdlib/slices/slices.sql",
"src/trace_processor/perfetto_sql/stdlib/slices/with_context.sql",
@@ -12325,14 +12324,6 @@
name: "perfetto_src_trace_processor_unittests",
}
-// GN: //src/trace_processor/util:build_id
-filegroup {
- name: "perfetto_src_trace_processor_util_build_id",
- srcs: [
- "src/trace_processor/util/build_id.cc",
- ],
-}
-
// GN: //src/trace_processor/util:bump_allocator
filegroup {
name: "perfetto_src_trace_processor_util_bump_allocator",
@@ -12433,6 +12424,14 @@
],
}
+// GN: //src/trace_processor/util:stack_traces_util
+filegroup {
+ name: "perfetto_src_trace_processor_util_stack_traces_util",
+ srcs: [
+ "src/trace_processor/util/stack_traces_util.cc",
+ ],
+}
+
// GN: //src/trace_processor/util:stdlib
filegroup {
name: "perfetto_src_trace_processor_util_stdlib",
@@ -13960,7 +13959,6 @@
":perfetto_src_trace_processor_types_types",
":perfetto_src_trace_processor_types_unittests",
":perfetto_src_trace_processor_unittests",
- ":perfetto_src_trace_processor_util_build_id",
":perfetto_src_trace_processor_util_bump_allocator",
":perfetto_src_trace_processor_util_descriptors",
":perfetto_src_trace_processor_util_glob",
@@ -13974,6 +13972,7 @@
":perfetto_src_trace_processor_util_protozero_to_text",
":perfetto_src_trace_processor_util_regex",
":perfetto_src_trace_processor_util_sql_argument",
+ ":perfetto_src_trace_processor_util_stack_traces_util",
":perfetto_src_trace_processor_util_stdlib",
":perfetto_src_trace_processor_util_unittests",
":perfetto_src_trace_processor_util_util",
@@ -14663,7 +14662,6 @@
":perfetto_src_trace_processor_storage_storage",
":perfetto_src_trace_processor_tables_tables",
":perfetto_src_trace_processor_types_types",
- ":perfetto_src_trace_processor_util_build_id",
":perfetto_src_trace_processor_util_bump_allocator",
":perfetto_src_trace_processor_util_descriptors",
":perfetto_src_trace_processor_util_glob",
@@ -14677,6 +14675,7 @@
":perfetto_src_trace_processor_util_protozero_to_text",
":perfetto_src_trace_processor_util_regex",
":perfetto_src_trace_processor_util_sql_argument",
+ ":perfetto_src_trace_processor_util_stack_traces_util",
":perfetto_src_trace_processor_util_stdlib",
":perfetto_src_trace_processor_util_util",
":perfetto_src_trace_processor_util_zip_reader",
@@ -14897,7 +14896,6 @@
":perfetto_src_trace_processor_storage_storage",
":perfetto_src_trace_processor_tables_tables",
":perfetto_src_trace_processor_types_types",
- ":perfetto_src_trace_processor_util_build_id",
":perfetto_src_trace_processor_util_bump_allocator",
":perfetto_src_trace_processor_util_descriptors",
":perfetto_src_trace_processor_util_glob",
@@ -14911,6 +14909,7 @@
":perfetto_src_trace_processor_util_protozero_to_text",
":perfetto_src_trace_processor_util_regex",
":perfetto_src_trace_processor_util_sql_argument",
+ ":perfetto_src_trace_processor_util_stack_traces_util",
":perfetto_src_trace_processor_util_stdlib",
":perfetto_src_trace_processor_util_util",
":perfetto_src_trace_processor_util_zip_reader",
diff --git a/BUILD b/BUILD
index bd40277..ac30232 100644
--- a/BUILD
+++ b/BUILD
@@ -266,7 +266,6 @@
":src_trace_processor_tables_tables",
":src_trace_processor_tables_tables_python",
":src_trace_processor_types_types",
- ":src_trace_processor_util_build_id",
":src_trace_processor_util_bump_allocator",
":src_trace_processor_util_descriptors",
":src_trace_processor_util_glob",
@@ -280,6 +279,7 @@
":src_trace_processor_util_protozero_to_text",
":src_trace_processor_util_regex",
":src_trace_processor_util_sql_argument",
+ ":src_trace_processor_util_stack_traces_util",
":src_trace_processor_util_stdlib",
":src_trace_processor_util_util",
":src_trace_processor_util_zip_reader",
@@ -1467,7 +1467,6 @@
"src/trace_processor/importers/common/clock_converter.h",
"src/trace_processor/importers/common/clock_tracker.cc",
"src/trace_processor/importers/common/clock_tracker.h",
- "src/trace_processor/importers/common/create_mapping_params.h",
"src/trace_processor/importers/common/deobfuscation_mapping_table.cc",
"src/trace_processor/importers/common/deobfuscation_mapping_table.h",
"src/trace_processor/importers/common/event_tracker.cc",
@@ -1476,8 +1475,6 @@
"src/trace_processor/importers/common/flow_tracker.h",
"src/trace_processor/importers/common/global_args_tracker.cc",
"src/trace_processor/importers/common/global_args_tracker.h",
- "src/trace_processor/importers/common/mapping_tracker.cc",
- "src/trace_processor/importers/common/mapping_tracker.h",
"src/trace_processor/importers/common/metadata_tracker.cc",
"src/trace_processor/importers/common/metadata_tracker.h",
"src/trace_processor/importers/common/process_tracker.cc",
@@ -1498,8 +1495,6 @@
"src/trace_processor/importers/common/trace_parser.cc",
"src/trace_processor/importers/common/track_tracker.cc",
"src/trace_processor/importers/common/track_tracker.h",
- "src/trace_processor/importers/common/virtual_memory_mapping.cc",
- "src/trace_processor/importers/common/virtual_memory_mapping.h",
],
)
@@ -2518,6 +2513,7 @@
perfetto_filegroup(
name = "src_trace_processor_perfetto_sql_stdlib_slices_slices",
srcs = [
+ "src/trace_processor/perfetto_sql/stdlib/slices/cpu_time.sql",
"src/trace_processor/perfetto_sql/stdlib/slices/flat_slices.sql",
"src/trace_processor/perfetto_sql/stdlib/slices/slices.sql",
"src/trace_processor/perfetto_sql/stdlib/slices/with_context.sql",
@@ -2703,15 +2699,6 @@
],
)
-# GN target: //src/trace_processor/util:build_id
-perfetto_filegroup(
- name = "src_trace_processor_util_build_id",
- srcs = [
- "src/trace_processor/util/build_id.cc",
- "src/trace_processor/util/build_id.h",
- ],
-)
-
# GN target: //src/trace_processor/util:bump_allocator
perfetto_filegroup(
name = "src_trace_processor_util_bump_allocator",
@@ -2831,6 +2818,15 @@
],
)
+# GN target: //src/trace_processor/util:stack_traces_util
+perfetto_filegroup(
+ name = "src_trace_processor_util_stack_traces_util",
+ srcs = [
+ "src/trace_processor/util/stack_traces_util.cc",
+ "src/trace_processor/util/stack_traces_util.h",
+ ],
+)
+
# GN target: //src/trace_processor/util:stdlib
perfetto_filegroup(
name = "src_trace_processor_util_stdlib",
@@ -5648,7 +5644,6 @@
":src_trace_processor_tables_tables",
":src_trace_processor_tables_tables_python",
":src_trace_processor_types_types",
- ":src_trace_processor_util_build_id",
":src_trace_processor_util_bump_allocator",
":src_trace_processor_util_descriptors",
":src_trace_processor_util_glob",
@@ -5662,6 +5657,7 @@
":src_trace_processor_util_protozero_to_text",
":src_trace_processor_util_regex",
":src_trace_processor_util_sql_argument",
+ ":src_trace_processor_util_stack_traces_util",
":src_trace_processor_util_stdlib",
":src_trace_processor_util_util",
":src_trace_processor_util_zip_reader",
@@ -5819,7 +5815,6 @@
":src_trace_processor_tables_tables",
":src_trace_processor_tables_tables_python",
":src_trace_processor_types_types",
- ":src_trace_processor_util_build_id",
":src_trace_processor_util_bump_allocator",
":src_trace_processor_util_descriptors",
":src_trace_processor_util_glob",
@@ -5833,6 +5828,7 @@
":src_trace_processor_util_protozero_to_text",
":src_trace_processor_util_regex",
":src_trace_processor_util_sql_argument",
+ ":src_trace_processor_util_stack_traces_util",
":src_trace_processor_util_stdlib",
":src_trace_processor_util_util",
":src_trace_processor_util_zip_reader",
@@ -5910,7 +5906,7 @@
":src_profiling_deobfuscator",
":src_profiling_symbolizer_symbolize_database",
":src_profiling_symbolizer_symbolizer",
- ":src_trace_processor_util_build_id",
+ ":src_trace_processor_util_stack_traces_util",
":src_traceconv_pprofbuilder",
":src_traceconv_utils",
],
@@ -6042,7 +6038,6 @@
":src_trace_processor_tables_tables",
":src_trace_processor_tables_tables_python",
":src_trace_processor_types_types",
- ":src_trace_processor_util_build_id",
":src_trace_processor_util_bump_allocator",
":src_trace_processor_util_descriptors",
":src_trace_processor_util_glob",
@@ -6056,6 +6051,7 @@
":src_trace_processor_util_protozero_to_text",
":src_trace_processor_util_regex",
":src_trace_processor_util_sql_argument",
+ ":src_trace_processor_util_stack_traces_util",
":src_trace_processor_util_stdlib",
":src_trace_processor_util_util",
":src_trace_processor_util_zip_reader",
diff --git a/gn/perfetto_unittests.gni b/gn/perfetto_unittests.gni
index 836ac9a..f1d46ba 100644
--- a/gn/perfetto_unittests.gni
+++ b/gn/perfetto_unittests.gni
@@ -86,6 +86,4 @@
perfetto_unittests_targets += [ "src/traced_relay:unittests" ]
}
-if (!is_win) {
- perfetto_unittests_targets += [ "src/trace_redaction:unittests" ]
-}
+perfetto_unittests_targets += [ "src/trace_redaction:unittests" ]
diff --git a/python/generators/sql_processing/utils.py b/python/generators/sql_processing/utils.py
index ba14110..539115e 100644
--- a/python/generators/sql_processing/utils.py
+++ b/python/generators/sql_processing/utils.py
@@ -116,7 +116,8 @@
# Allows for nonstandard object names.
OBJECT_NAME_ALLOWLIST = {
- 'slices/with_context.sql': ['process_slice', 'thread_slice']
+ 'slices/with_context.sql': ['process_slice', 'thread_slice'],
+ 'slices/cpu_time.sql': ['thread_slice_cpu_time']
}
# Given a regex pattern and a string to match against, returns all the
diff --git a/src/profiling/symbolizer/BUILD.gn b/src/profiling/symbolizer/BUILD.gn
index 2eb2c93..722d1cf 100644
--- a/src/profiling/symbolizer/BUILD.gn
+++ b/src/profiling/symbolizer/BUILD.gn
@@ -49,7 +49,7 @@
"../../../include/perfetto/trace_processor:trace_processor",
"../../../protos/perfetto/trace:zero",
"../../../protos/perfetto/trace/profiling:zero",
- "../../trace_processor/util:build_id",
+ "../../trace_processor/util:stack_traces_util",
]
sources = [
"symbolize_database.cc",
diff --git a/src/profiling/symbolizer/symbolize_database.cc b/src/profiling/symbolizer/symbolize_database.cc
index a008e1a..224874b 100644
--- a/src/profiling/symbolizer/symbolize_database.cc
+++ b/src/profiling/symbolizer/symbolize_database.cc
@@ -28,7 +28,8 @@
#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
#include "protos/perfetto/trace/trace.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "src/trace_processor/util/build_id.h"
+
+#include "src/trace_processor/util/stack_traces_util.h"
namespace perfetto {
namespace profiling {
@@ -55,6 +56,32 @@
}
};
+std::string FromHex(const char* str, size_t size) {
+ if (size % 2) {
+ PERFETTO_DFATAL_OR_ELOG("Failed to parse hex %s", str);
+ return "";
+ }
+ std::string result(size / 2, '\0');
+ for (size_t i = 0; i < size; i += 2) {
+ char hex_byte[3];
+ hex_byte[0] = str[i];
+ hex_byte[1] = str[i + 1];
+ hex_byte[2] = '\0';
+ char* end;
+ long int byte = strtol(hex_byte, &end, 16);
+ if (*end != '\0') {
+ PERFETTO_DFATAL_OR_ELOG("Failed to parse hex %s", str);
+ return "";
+ }
+ result[i / 2] = static_cast<char>(byte);
+ }
+ return result;
+}
+
+std::string FromHex(const std::string& str) {
+ return FromHex(str.c_str(), str.size());
+}
+
std::map<UnsymbolizedMapping, std::vector<uint64_t>> GetUnsymbolizedFrames(
trace_processor::TraceProcessor* tp) {
std::map<UnsymbolizedMapping, std::vector<uint64_t>> res;
@@ -62,10 +89,17 @@
while (it.Next()) {
int64_t load_bias = it.Get(3).AsLong();
PERFETTO_CHECK(load_bias >= 0);
- trace_processor::BuildId build_id =
- trace_processor::BuildId::FromHex(it.Get(1).AsString());
- UnsymbolizedMapping unsymbolized_mapping{
- it.Get(0).AsString(), build_id.raw(), static_cast<uint64_t>(load_bias)};
+ std::string build_id;
+ // TODO(b/148109467): Remove workaround once all active Chrome versions
+ // write raw bytes instead of a string as build_id.
+ std::string raw_build_id = it.Get(1).AsString();
+ if (!trace_processor::util::IsHexModuleId(base::StringView(raw_build_id))) {
+ build_id = FromHex(raw_build_id);
+ } else {
+ build_id = raw_build_id;
+ }
+ UnsymbolizedMapping unsymbolized_mapping{it.Get(0).AsString(), build_id,
+ static_cast<uint64_t>(load_bias)};
int64_t rel_pc = it.Get(2).AsLong();
res[unsymbolized_mapping].emplace_back(rel_pc);
}
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index e37c9c6..e81b184 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -132,6 +132,7 @@
"util:descriptors",
"util:gzip",
"util:proto_to_args_parser",
+ "util:stack_traces_util",
]
public_deps = [ "../../include/perfetto/trace_processor:storage" ]
}
diff --git a/src/trace_processor/importers/common/BUILD.gn b/src/trace_processor/importers/common/BUILD.gn
index 5108dca..466876a 100644
--- a/src/trace_processor/importers/common/BUILD.gn
+++ b/src/trace_processor/importers/common/BUILD.gn
@@ -28,7 +28,6 @@
"clock_converter.h",
"clock_tracker.cc",
"clock_tracker.h",
- "create_mapping_params.h",
"deobfuscation_mapping_table.cc",
"deobfuscation_mapping_table.h",
"event_tracker.cc",
@@ -37,8 +36,6 @@
"flow_tracker.h",
"global_args_tracker.cc",
"global_args_tracker.h",
- "mapping_tracker.cc",
- "mapping_tracker.h",
"metadata_tracker.cc",
"metadata_tracker.h",
"process_tracker.cc",
@@ -59,8 +56,6 @@
"trace_parser.cc",
"track_tracker.cc",
"track_tracker.h",
- "virtual_memory_mapping.cc",
- "virtual_memory_mapping.h",
]
public_deps = [
":trace_parser_hdr",
@@ -80,8 +75,8 @@
"../../storage",
"../../tables:tables",
"../../types",
- "../../util:build_id",
"../../util:profiler_util",
+ "../../util:stack_traces_util",
"../fuchsia:fuchsia_record",
"../systrace:systrace_line",
]
diff --git a/src/trace_processor/importers/common/create_mapping_params.h b/src/trace_processor/importers/common/create_mapping_params.h
deleted file mode 100644
index 7aba456..0000000
--- a/src/trace_processor/importers/common/create_mapping_params.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2024 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 SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_CREATE_MAPPING_PARAMS_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_CREATE_MAPPING_PARAMS_H_
-
-#include <cstddef>
-#include <cstdint>
-#include <optional>
-#include <string>
-#include <tuple>
-
-#include "perfetto/ext/base/hash.h"
-#include "src/trace_processor/importers/common/address_range.h"
-#include "src/trace_processor/util/build_id.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-struct CreateMappingParams {
- AddressRange memory_range;
- // This is the offset into the file that has been mapped at
- // memory_range.start()
- uint64_t exact_offset = 0;
- // This is the offset into the file where the ELF header starts. We assume
- // all file mappings are ELF files an thus this offset is 0.
- uint64_t start_offset = 0;
- // This can only be read out of the actual ELF file.
- uint64_t load_bias = 0;
- std::string name;
- std::optional<BuildId> build_id;
-
- auto ToTuple() const {
- return std::tie(memory_range, exact_offset, start_offset, load_bias, name,
- build_id);
- }
-
- bool operator==(const CreateMappingParams& o) const {
- return ToTuple() == o.ToTuple();
- }
-
- struct Hasher {
- size_t operator()(const CreateMappingParams& p) const {
- base::Hasher h;
- h.UpdateAll(p.memory_range.start(), p.memory_range.end(), p.exact_offset,
- p.start_offset, p.load_bias, p.name);
- if (p.build_id) {
- h.Update(*p.build_id);
- }
- return static_cast<size_t>(h.digest());
- }
- };
-};
-
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_CREATE_MAPPING_PARAMS_H_
diff --git a/src/trace_processor/importers/common/mapping_tracker.cc b/src/trace_processor/importers/common/mapping_tracker.cc
deleted file mode 100644
index 13b8274..0000000
--- a/src/trace_processor/importers/common/mapping_tracker.cc
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2024 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 "src/trace_processor/importers/common/mapping_tracker.h"
-
-#include <cstddef>
-#include <cstdint>
-#include <memory>
-#include <utility>
-
-#include "perfetto/ext/base/string_view.h"
-#include "src/trace_processor/importers/common/address_range.h"
-#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-#include "src/trace_processor/util/build_id.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-bool IsKernelModule(base::StringView name) {
- return !name.StartsWith("[kernel.kallsyms]");
-}
-
-} // namespace
-
-JitDelegate::~JitDelegate() = default;
-
-template <typename MappingImpl>
-MappingImpl& MappingTracker::AddMapping(std::unique_ptr<MappingImpl> mapping) {
- auto ptr = mapping.get();
- PERFETTO_CHECK(
- mappings_by_id_.Insert(ptr->mapping_id(), std::move(mapping)).second);
-
- mappings_by_name_and_build_id_[NameAndBuildId{base::StringView(ptr->name()),
- ptr->build_id()}]
- .push_back(ptr);
-
- return *ptr;
-}
-
-KernelMemoryMapping& MappingTracker::CreateKernelMemoryMapping(
- CreateMappingParams params) {
- // TODO(carlscab): Guess build_id if not provided. Some tools like simpleperf
- // add a mapping file_name ->build_id that we could use here
-
- const bool is_module = IsKernelModule(base::StringView(params.name));
-
- if (!is_module && kernel_ != nullptr) {
- PERFETTO_CHECK(params.memory_range == kernel_->memory_range());
- return *kernel_;
- }
-
- std::unique_ptr<KernelMemoryMapping> mapping(
- new KernelMemoryMapping(context_, std::move(params)));
-
- if (is_module) {
- // TODO(carlscab): Overlaps not supported (for now?). Should be fine for
- // kernel.
- PERFETTO_CHECK(
- kernel_modules_.Emplace(mapping->memory_range(), mapping.get()));
- } else {
- kernel_ = mapping.get();
- }
-
- return AddMapping(std::move(mapping));
-}
-
-UserMemoryMapping& MappingTracker::CreateUserMemoryMapping(
- UniquePid upid,
- CreateMappingParams params) {
- // TODO(carlscab): Guess build_id if not provided. Some tools like simpleperf
- // add a mapping file_name ->build_id that we could use here
-
- const AddressRange mapping_range = params.memory_range;
- std::unique_ptr<UserMemoryMapping> mapping(
- new UserMemoryMapping(context_, upid, std::move(params)));
- // TODO(carlscab): Overlaps not supported (for now?).
- PERFETTO_CHECK(user_memory_[upid].Emplace(mapping_range, mapping.get()));
-
- jit_delegates_[upid].ForOverlaps(
- mapping_range, [&](std::pair<const AddressRange, JitDelegate*>& entry) {
- const auto& jit_range = entry.first;
- JitDelegate* jit_delegate = entry.second;
- PERFETTO_CHECK(jit_range.Contains(mapping_range));
- mapping->SetJitDelegate(jit_delegate);
- });
-
- return AddMapping(std::move(mapping));
-}
-
-KernelMemoryMapping* MappingTracker::FindKernelMappingForAddress(
- uint64_t address) const {
- if (auto it = kernel_modules_.Find(address); it != kernel_modules_.end()) {
- return it->second;
- }
- if (kernel_ && kernel_->memory_range().Contains(address)) {
- return kernel_;
- }
- return nullptr;
-}
-
-UserMemoryMapping* MappingTracker::FindUserMappingForAddress(
- UniquePid upid,
- uint64_t address) const {
- if (auto* vm = user_memory_.Find(upid); vm) {
- if (auto it = vm->Find(address); it != vm->end()) {
- return it->second;
- }
- }
-
- if (auto* delegates = jit_delegates_.Find(upid); delegates) {
- if (auto it = delegates->Find(address); it != delegates->end()) {
- return it->second->CreateMapping();
- }
- }
-
- return nullptr;
-}
-
-std::vector<VirtualMemoryMapping*> MappingTracker::FindMappings(
- base::StringView name,
- const BuildId& build_id) const {
- if (auto res = mappings_by_name_and_build_id_.Find({name, build_id});
- res != nullptr) {
- return *res;
- }
- return {};
-}
-
-VirtualMemoryMapping& MappingTracker::InternMemoryMapping(
- CreateMappingParams params) {
- if (auto* mapping = interned_mappings_.Find(params); mapping) {
- return **mapping;
- }
-
- std::unique_ptr<VirtualMemoryMapping> mapping(
- new VirtualMemoryMapping(context_, params));
- interned_mappings_.Insert(std::move(params), mapping.get());
- return AddMapping(std::move(mapping));
-}
-
-void MappingTracker::AddJitRange(UniquePid upid,
- AddressRange jit_range,
- JitDelegate* delegate) {
- // TODO(carlscab): Deal with overlaps
- jit_delegates_[upid].DeleteOverlapsAndEmplace(jit_range, delegate);
- user_memory_[upid].ForOverlaps(
- jit_range, [&](std::pair<const AddressRange, UserMemoryMapping*>& entry) {
- PERFETTO_CHECK(jit_range.Contains(entry.first));
- entry.second->SetJitDelegate(delegate);
- });
-}
-
-} // namespace trace_processor
-} // namespace perfetto
diff --git a/src/trace_processor/importers/common/mapping_tracker.h b/src/trace_processor/importers/common/mapping_tracker.h
deleted file mode 100644
index 95dc355..0000000
--- a/src/trace_processor/importers/common/mapping_tracker.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2024 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 SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_MAPPING_TRACKER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_MAPPING_TRACKER_H_
-
-#include <cstddef>
-#include <cstdint>
-#include <memory>
-#include <optional>
-#include <vector>
-
-#include "perfetto/ext/base/flat_hash_map.h"
-#include "perfetto/ext/base/hash.h"
-#include "perfetto/ext/base/string_view.h"
-#include "src/trace_processor/importers/common/address_range.h"
-#include "src/trace_processor/importers/common/virtual_memory_mapping.h"
-#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-#include "src/trace_processor/util/build_id.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Api used to forward frame interning requests for frames that fall in a
-// jitted memory region.
-// MappingTracker allows other trackers to register ranges of memory for
-// which they need to control when a new frame is created. Jitted code can
-// move in memory over time, so the same program counter might refer to
-// different functions at different point in time. MappingTracker does
-// not keep track of such moves but instead delegates the creation of jitted
-// frames to a delegate.
-class JitDelegate {
- public:
- virtual ~JitDelegate();
- // Forward frame interning request.
- // Implementations are free to intern the frame as needed.
- // Returns frame_id, and whether a new row as created or not.
- virtual std::pair<FrameId, bool> InternFrame(
- VirtualMemoryMapping* mapping,
- uint64_t rel_pc,
- base::StringView function_name) = 0;
-
- // Simpleperf does not emit mmap events for jitted ranges (actually for non
- // file backed executable mappings). So have a way to generate a mapping on
- // the fly for FindMapping requests in a jitted region with no associated
- // mapping.
- virtual UserMemoryMapping* CreateMapping() = 0;
-};
-
-// Keeps track of all aspects relative to memory mappings.
-// This class keeps track of 3 types of mappings: UserMemoryMapping,
-// KernelMemoryMapping and others. The others are used to represent mapping
-// where we do not have enough information to determine what type of
-// mapping (user, kernel) we are dealing with. This is usually the case with
-// data sources that do not provide enough information about the mappings.
-//
-// TODO(carlscab): Hopefully we can slowly get rid of cases where these other
-// mappings are needed. The biggest blocker right now is determining the upid.
-// we could infer this from the actual samples that use said mapping (those
-// usually have a pid attached). So we would need to have a "fake" mapping that
-// actually materializes when we see a sample with a pid.
-//
-// ATTENTION: No overlaps allowed (for now). Eventually the order in which
-// mappings are create will matter as newer mappings will delete old ones.
-// This is how tools like linux perf behave, mmap event have a timestamp
-// associated and there are no "delete events" just new mmap events that
-// overlap (to be deleted) mappings.
-class MappingTracker {
- public:
- explicit MappingTracker(TraceProcessorContext* context) : context_(context) {}
-
- // Create a new kernel space mapping. Returned reference will be valid for the
- // duration of this instance.
- KernelMemoryMapping& CreateKernelMemoryMapping(CreateMappingParams params);
-
- // Create a new user space mapping. Returned reference will be valid for the
- // duration of this instance.
- UserMemoryMapping& CreateUserMemoryMapping(UniquePid upid,
- CreateMappingParams params);
-
- // Create an "other" mapping. Returned reference will be valid for the
- // duration of this instance.
- VirtualMemoryMapping& InternMemoryMapping(CreateMappingParams params);
-
- // Given an absolute address find the kernel mapping where this address
- // belongs to. Returns `nullptr` if none is found.
- KernelMemoryMapping* FindKernelMappingForAddress(uint64_t address) const;
-
- // Given an absolute address find the user mapping where this address
- // belongs to. Returns `nullptr` if none is found.
- UserMemoryMapping* FindUserMappingForAddress(UniquePid upid,
- uint64_t address) const;
-
- std::vector<VirtualMemoryMapping*> FindMappings(
- base::StringView name,
- const BuildId& build_id) const;
-
- // Marks a range of memory as containing jitted code.
- // If the added region overlaps with other existing ranges the latter are all
- // deleted.
- // Jitted ranges will only be applied to UserMemoryMappings
- void AddJitRange(UniquePid upid, AddressRange range, JitDelegate* delegate);
-
- private:
- template <typename MappingImpl>
- MappingImpl& AddMapping(std::unique_ptr<MappingImpl> mapping);
-
- TraceProcessorContext* const context_;
- base::FlatHashMap<MappingId, std::unique_ptr<VirtualMemoryMapping>>
- mappings_by_id_;
-
- base::FlatHashMap<CreateMappingParams,
- VirtualMemoryMapping*,
- CreateMappingParams::Hasher>
- interned_mappings_;
-
- struct NameAndBuildId {
- base::StringView name;
- std::optional<BuildId> build_id;
-
- bool operator==(const NameAndBuildId& o) const {
- return name == o.name && build_id == o.build_id;
- }
-
- bool operator!=(const NameAndBuildId& o) const { return !(*this == o); }
-
- struct Hasher {
- size_t operator()(const NameAndBuildId& o) const {
- base::Hasher hasher;
- hasher.Update(o.name);
- if (o.build_id) {
- hasher.Update(*o.build_id);
- }
- return static_cast<size_t>(hasher.digest());
- }
- };
- };
- base::FlatHashMap<NameAndBuildId,
- std::vector<VirtualMemoryMapping*>,
- NameAndBuildId::Hasher>
- mappings_by_name_and_build_id_;
-
- base::FlatHashMap<UniquePid, AddressRangeMap<UserMemoryMapping*>>
- user_memory_;
- AddressRangeMap<KernelMemoryMapping*> kernel_modules_;
- KernelMemoryMapping* kernel_ = nullptr;
-
- base::FlatHashMap<UniquePid, AddressRangeMap<JitDelegate*>> jit_delegates_;
-};
-
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_MAPPING_TRACKER_H_
diff --git a/src/trace_processor/importers/common/stack_profile_tracker.cc b/src/trace_processor/importers/common/stack_profile_tracker.cc
index 799dc29..ad57523 100644
--- a/src/trace_processor/importers/common/stack_profile_tracker.cc
+++ b/src/trace_processor/importers/common/stack_profile_tracker.cc
@@ -16,18 +16,35 @@
#include "src/trace_processor/importers/common/stack_profile_tracker.h"
-#include <cstddef>
-#include <cstdint>
-
+#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/string_view.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/tables/profiler_tables_py.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/util/profiler_util.h"
+#include "src/trace_processor/util/stack_traces_util.h"
namespace perfetto {
namespace trace_processor {
+namespace {
+std::string CleanBuildId(base::StringView build_id) {
+ if (build_id.empty()) {
+ return build_id.ToStdString();
+ }
+ // If the build_id is 33 characters long, we assume it's a Breakpad debug
+ // identifier which is already in Hex and doesn't need conversion.
+ // TODO(b/148109467): Remove workaround once all active Chrome versions
+ // write raw bytes instead of a string as build_id.
+ if (util::IsHexModuleId(build_id)) {
+ return build_id.ToStdString();
+ }
+
+ return base::ToHex(build_id.data(), build_id.size());
+}
+
+} // namespace
+
std::vector<FrameId> StackProfileTracker::JavaFramesForName(
NameInPackage name) const {
if (const auto* frames = java_frames_for_name_.Find(name); frames) {
@@ -36,6 +53,50 @@
return {};
}
+std::vector<MappingId> StackProfileTracker::FindMappingRow(
+ StringId name,
+ StringId build_id) const {
+ if (const auto* mappings =
+ mappings_by_name_and_build_id_.Find(std::make_pair(name, build_id));
+ mappings) {
+ return *mappings;
+ }
+ return {};
+}
+
+std::vector<FrameId> StackProfileTracker::FindFrameIds(MappingId mapping_id,
+ uint64_t rel_pc) const {
+ if (const auto* frames =
+ frame_by_mapping_and_rel_pc_.Find(std::make_pair(mapping_id, rel_pc));
+ frames) {
+ return *frames;
+ }
+ return {};
+}
+
+MappingId StackProfileTracker::InternMapping(
+ const CreateMappingParams& params) {
+ tables::StackProfileMappingTable::Row row;
+ row.build_id = InternBuildId(params.build_id);
+ row.exact_offset = static_cast<int64_t>(params.exact_offset);
+ row.start_offset = static_cast<int64_t>(params.start_offset);
+ row.start = static_cast<int64_t>(params.start);
+ row.end = static_cast<int64_t>(params.end);
+ row.load_bias = static_cast<int64_t>(params.load_bias);
+ row.name = context_->storage->InternString(params.name);
+
+ if (MappingId* id = mapping_unique_row_index_.Find(row); id) {
+ return *id;
+ }
+
+ MappingId mapping_id =
+ context_->storage->mutable_stack_profile_mapping_table()->Insert(row).id;
+ mapping_unique_row_index_.Insert(row, mapping_id);
+ mappings_by_name_and_build_id_[{row.name, row.build_id}].push_back(
+ mapping_id);
+ return mapping_id;
+}
+
CallsiteId StackProfileTracker::InternCallsite(
std::optional<CallsiteId> parent_callsite_id,
FrameId frame_id,
@@ -52,12 +113,22 @@
return callsite_id;
}
-void StackProfileTracker::OnFrameCreated(FrameId frame_id) {
- auto frame =
- *context_->storage->stack_profile_frame_table().FindById(frame_id);
- const MappingId mapping_id = frame.mapping();
- const StringId name_id = frame.name();
- const auto function_name = context_->storage->GetString(name_id);
+FrameId StackProfileTracker::InternFrame(MappingId mapping_id,
+ uint64_t rel_pc,
+ base::StringView function_name) {
+ tables::StackProfileFrameTable::Row row;
+ row.mapping = mapping_id;
+ row.rel_pc = static_cast<int64_t>(rel_pc);
+ row.name = context_->storage->InternString(function_name);
+
+ if (FrameId* id = frame_unique_row_index_.Find(row); id) {
+ return *id;
+ }
+
+ FrameId frame_id =
+ context_->storage->mutable_stack_profile_frame_table()->Insert(row).id;
+ frame_unique_row_index_.Insert(row, frame_id);
+ frame_by_mapping_and_rel_pc_[{mapping_id, rel_pc}].push_back(frame_id);
if (function_name.find('.') != base::StringView::npos) {
// Java frames always contain a '.'
@@ -68,14 +139,21 @@
std::optional<std::string> package =
PackageFromLocation(context_->storage.get(), mapping_name);
if (package) {
- NameInPackage nip{
- name_id, context_->storage->InternString(base::StringView(*package))};
+ NameInPackage nip{row.name, context_->storage->InternString(
+ base::StringView(*package))};
java_frames_for_name_[nip].push_back(frame_id);
} else if (mapping_name.find("/memfd:") == 0) {
- NameInPackage nip{name_id, context_->storage->InternString("memfd")};
+ NameInPackage nip{row.name, context_->storage->InternString("memfd")};
java_frames_for_name_[nip].push_back(frame_id);
}
}
+
+ return frame_id;
+}
+
+StringId StackProfileTracker::InternBuildId(base::StringView build_id) {
+ return context_->storage->InternString(
+ base::StringView(CleanBuildId(build_id)));
}
} // namespace trace_processor
diff --git a/src/trace_processor/importers/common/stack_profile_tracker.h b/src/trace_processor/importers/common/stack_profile_tracker.h
index b018f74..a1067b8 100644
--- a/src/trace_processor/importers/common/stack_profile_tracker.h
+++ b/src/trace_processor/importers/common/stack_profile_tracker.h
@@ -20,11 +20,12 @@
#include <cstdint>
#include <optional>
#include <tuple>
+#include <utility>
#include <vector>
#include "perfetto/ext/base/flat_hash_map.h"
#include "perfetto/ext/base/hash.h"
-
+#include "perfetto/ext/base/string_view.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/tables/profiler_tables_py.h"
@@ -51,39 +52,64 @@
class StackProfileTracker {
public:
+ struct CreateMappingParams {
+ base::StringView build_id;
+ uint64_t exact_offset;
+ uint64_t start_offset;
+ uint64_t start;
+ uint64_t end;
+ uint64_t load_bias;
+ base::StringView name;
+ };
+
explicit StackProfileTracker(TraceProcessorContext* context)
: context_(context) {}
std::vector<FrameId> JavaFramesForName(NameInPackage name) const;
+ std::vector<MappingId> FindMappingRow(StringId name, StringId build_id) const;
+ std::vector<FrameId> FindFrameIds(MappingId mapping_id,
+ uint64_t rel_pc) const;
+ MappingId InternMapping(const CreateMappingParams& params);
CallsiteId InternCallsite(std::optional<CallsiteId> parent_callsite_id,
FrameId frame_id,
uint32_t depth);
-
- void OnFrameCreated(FrameId frame_id);
+ FrameId InternFrame(MappingId mapping_id,
+ uint64_t rel_pc,
+ base::StringView function_name);
private:
+ StringId InternBuildId(base::StringView build_id);
+
TraceProcessorContext* const context_;
+ base::FlatHashMap<tables::StackProfileMappingTable::Row, MappingId>
+ mapping_unique_row_index_;
base::FlatHashMap<tables::StackProfileCallsiteTable::Row, CallsiteId>
callsite_unique_row_index_;
+ base::FlatHashMap<tables::StackProfileFrameTable::Row, FrameId>
+ frame_unique_row_index_;
- struct FrameKey {
- MappingId mapping_id;
- uint64_t rel_pc;
-
- bool operator==(const FrameKey& o) const {
- return mapping_id == o.mapping_id && rel_pc == o.rel_pc;
+ struct MappingHasher {
+ size_t operator()(const std::pair<StringId, StringId>& o) const {
+ return static_cast<size_t>(
+ base::Hasher::Combine(o.first.raw_id(), o.second.raw_id()));
}
-
- bool operator!=(const FrameKey& o) const { return !(*this == o); }
-
- struct Hasher {
- size_t operator()(const FrameKey& o) const {
- return static_cast<size_t>(
- base::Hasher::Combine(o.mapping_id.value, o.rel_pc));
- }
- };
};
+ base::FlatHashMap<std::pair<StringId, StringId>,
+ std::vector<MappingId>,
+ MappingHasher>
+ mappings_by_name_and_build_id_;
+
+ struct FrameHasher {
+ size_t operator()(const std::pair<MappingId, uint64_t>& o) const {
+ return static_cast<size_t>(
+ base::Hasher::Combine(o.first.value, o.second));
+ }
+ };
+ base::FlatHashMap<std::pair<MappingId, uint64_t>,
+ std::vector<FrameId>,
+ FrameHasher>
+ frame_by_mapping_and_rel_pc_;
base::FlatHashMap<NameInPackage, std::vector<FrameId>, NameInPackage::Hasher>
java_frames_for_name_;
diff --git a/src/trace_processor/importers/common/virtual_memory_mapping.cc b/src/trace_processor/importers/common/virtual_memory_mapping.cc
deleted file mode 100644
index 60166f59..0000000
--- a/src/trace_processor/importers/common/virtual_memory_mapping.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2024 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 "src/trace_processor/importers/common/virtual_memory_mapping.h"
-
-#include <cstddef>
-#include <cstdint>
-#include <memory>
-#include <optional>
-#include <string>
-#include <utility>
-
-#include "perfetto/ext/base/string_view.h"
-#include "src/trace_processor/importers/common/address_range.h"
-#include "src/trace_processor/importers/common/mapping_tracker.h"
-#include "src/trace_processor/importers/common/stack_profile_tracker.h"
-#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/tables/profiler_tables_py.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-#include "src/trace_processor/util/build_id.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-MappingId CreateMapping(TraceProcessorContext* context,
- const CreateMappingParams& params) {
- StringId build_id = context->storage->InternString(base::StringView(
- params.build_id ? params.build_id->ToHex() : std::string()));
- MappingId mapping_id =
- context->storage->mutable_stack_profile_mapping_table()
- ->Insert(
- {build_id, static_cast<int64_t>(params.exact_offset),
- static_cast<int64_t>(params.start_offset),
- static_cast<int64_t>(params.memory_range.start()),
- static_cast<int64_t>(params.memory_range.end()),
- static_cast<int64_t>(params.load_bias),
- context->storage->InternString(base::StringView(params.name))})
- .id;
-
- return mapping_id;
-}
-
-} // namespace
-
-VirtualMemoryMapping::VirtualMemoryMapping(TraceProcessorContext* context,
- CreateMappingParams params)
- : context_(context),
- mapping_id_(CreateMapping(context, params)),
- memory_range_(params.memory_range),
- offset_(params.exact_offset),
- load_bias_(params.load_bias),
- name_(std::move(params.name)),
- build_id_(std::move(params.build_id)) {}
-
-VirtualMemoryMapping::~VirtualMemoryMapping() = default;
-
-KernelMemoryMapping::KernelMemoryMapping(TraceProcessorContext* context,
- CreateMappingParams params)
- : VirtualMemoryMapping(context, std::move(params)) {}
-
-KernelMemoryMapping::~KernelMemoryMapping() = default;
-
-UserMemoryMapping::UserMemoryMapping(TraceProcessorContext* context,
- UniquePid upid,
- CreateMappingParams params)
- : VirtualMemoryMapping(context, std::move(params)), upid_(upid) {}
-
-UserMemoryMapping::~UserMemoryMapping() = default;
-
-FrameId VirtualMemoryMapping::InternFrame(uint64_t rel_pc,
- base::StringView function_name) {
- auto [frame_id, was_inserted] =
- jit_delegate_ ? jit_delegate_->InternFrame(this, rel_pc, function_name)
- : InternFrameImpl(rel_pc, function_name);
- if (was_inserted) {
- frames_by_rel_pc_[rel_pc].push_back(frame_id);
- context_->stack_profile_tracker->OnFrameCreated(frame_id);
- }
- return frame_id;
-}
-
-std::vector<FrameId> VirtualMemoryMapping::FindFrameIds(uint64_t rel_pc) const {
- if (auto* res = frames_by_rel_pc_.Find(rel_pc); res != nullptr) {
- return *res;
- }
- return {};
-}
-
-std::pair<FrameId, bool> VirtualMemoryMapping::InternFrameImpl(
- uint64_t rel_pc,
- base::StringView function_name) {
- const FrameKey frame_key{rel_pc,
- context_->storage->InternString(function_name)};
- if (FrameId* id = interned_frames_.Find(frame_key); id) {
- return {*id, false};
- }
-
- const FrameId frame_id =
- context_->storage->mutable_stack_profile_frame_table()
- ->Insert(
- {frame_key.name_id, mapping_id_, static_cast<int64_t>(rel_pc)})
- .id;
- interned_frames_.Insert(frame_key, frame_id);
-
- return {frame_id, true};
-}
-
-} // namespace trace_processor
-} // namespace perfetto
diff --git a/src/trace_processor/importers/common/virtual_memory_mapping.h b/src/trace_processor/importers/common/virtual_memory_mapping.h
deleted file mode 100644
index 7b8ef58..0000000
--- a/src/trace_processor/importers/common/virtual_memory_mapping.h
+++ /dev/null
@@ -1,152 +0,0 @@
-
-/*
- * Copyright (C) 2024 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 SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_VIRTUAL_MEMORY_MAPPING_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_VIRTUAL_MEMORY_MAPPING_H_
-
-#include <cstddef>
-#include <cstdint>
-#include <optional>
-#include <string>
-#include <vector>
-
-#include "perfetto/ext/base/flat_hash_map.h"
-#include "perfetto/ext/base/hash.h"
-#include "perfetto/ext/base/string_view.h"
-#include "src/trace_processor/importers/common/address_range.h"
-#include "src/trace_processor/importers/common/create_mapping_params.h"
-#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-#include "src/trace_processor/util/build_id.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// TODO(carlscab): Reconsider whether jit is the best abstraction here. All we
-// really care is about mapping a `rel_pc` to a symbol (aka symbolization) and
-// whether is this is constant.
-class JitDelegate;
-
-// Represents a mapping in virtual memory.
-class VirtualMemoryMapping {
- public:
- virtual ~VirtualMemoryMapping();
- // Range of virtual memory this mapping covers.
- AddressRange memory_range() const { return memory_range_; }
- MappingId mapping_id() const { return mapping_id_; }
- // This name could be the path of the underlying file mapped into memory.
- const std::string& name() const { return name_; }
- // For file mappings, this is the offset into the file for the first byte in
- // the mapping
- uint64_t offset() const { return offset_; }
- // If the mapped file is an executable or shared library this will return the
- // load bias, if known. Returns 0 otherwise.
- uint64_t load_bias() const { return load_bias_; }
- // If the mapped file is an executable or shared library this will return its
- // build id, if known.
- const std::optional<BuildId>& build_id() const { return build_id_; }
-
- // Whether this maps to a region that holds jitted code.
- bool is_jitted() const { return jit_delegate_ != nullptr; }
-
- // Converts an absolute address into a relative one.
- uint64_t ToRelativePc(uint64_t address) const {
- return address - memory_range_.start() + offset_ + load_bias_;
- }
-
- // Creates a frame for the given `rel_pc`. Note that if the mapping
- // `is_jitted()` same `rel_pc` values can return different mappings (as jitted
- // functions can be created and deleted over time.) So for such mappings the
- // returned `FrameId` should not be cached.
- FrameId InternFrame(uint64_t rel_pc, base::StringView function_name);
-
- // Returns all frames ever created in this mapping for the given `rel_pc`.
- std::vector<FrameId> FindFrameIds(uint64_t rel_pc) const;
-
- protected:
- VirtualMemoryMapping(TraceProcessorContext* context,
- CreateMappingParams params);
-
- private:
- friend class MappingTracker;
-
- std::pair<FrameId, bool> InternFrameImpl(uint64_t rel_pc,
- base::StringView function_name);
-
- void SetJitDelegate(JitDelegate* jit_delegate) {
- jit_delegate_ = jit_delegate;
- }
-
- TraceProcessorContext* const context_;
- const MappingId mapping_id_;
- const AddressRange memory_range_;
- const uint64_t offset_;
- const uint64_t load_bias_;
- const std::string name_;
- std::optional<BuildId> const build_id_;
- JitDelegate* jit_delegate_ = nullptr;
-
- struct FrameKey {
- uint64_t rel_pc;
- // It doesn't seem to make too much sense to key on name, as for the same
- // mapping and same rel_pc the name should always be the same. But who knows
- // how producers behave.
- StringId name_id;
-
- bool operator==(const FrameKey& o) const {
- return rel_pc == o.rel_pc && name_id == o.name_id;
- }
-
- struct Hasher {
- size_t operator()(const FrameKey& k) const {
- return static_cast<size_t>(
- base::Hasher::Combine(k.rel_pc, k.name_id.raw_id()));
- }
- };
- };
- base::FlatHashMap<FrameKey, FrameId, FrameKey::Hasher> interned_frames_;
- base::FlatHashMap<uint64_t, std::vector<FrameId>> frames_by_rel_pc_;
-};
-
-class KernelMemoryMapping : public VirtualMemoryMapping {
- public:
- ~KernelMemoryMapping() override;
-
- private:
- friend class MappingTracker;
- KernelMemoryMapping(TraceProcessorContext* context,
- CreateMappingParams params);
-};
-
-class UserMemoryMapping : public VirtualMemoryMapping {
- public:
- ~UserMemoryMapping() override;
- UniquePid upid() const { return upid_; }
-
- private:
- friend class MappingTracker;
- UserMemoryMapping(TraceProcessorContext* context,
- UniquePid upid,
- CreateMappingParams params);
-
- const UniquePid upid_;
-};
-
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_VIRTUAL_MEMORY_MAPPING_H_
diff --git a/src/trace_processor/importers/perf/BUILD.gn b/src/trace_processor/importers/perf/BUILD.gn
index 960cd27..387468f 100644
--- a/src/trace_processor/importers/perf/BUILD.gn
+++ b/src/trace_processor/importers/perf/BUILD.gn
@@ -28,7 +28,6 @@
]
deps = [
"../../../../gn:default_deps",
- "../../../../protos/perfetto/trace/profiling:zero",
"../../importers/common",
"../../importers/common:parser_types",
"../../sorter",
@@ -48,8 +47,6 @@
":perf",
"../../../../gn:default_deps",
"../../../../gn:gtest_and_gmock",
- "../../../../protos/perfetto/trace/profiling:zero",
"../../../base",
- "../../importers/common",
]
}
diff --git a/src/trace_processor/importers/perf/perf_data_parser.cc b/src/trace_processor/importers/perf/perf_data_parser.cc
index bb79209..11a5a13 100644
--- a/src/trace_processor/importers/perf/perf_data_parser.cc
+++ b/src/trace_processor/importers/perf/perf_data_parser.cc
@@ -22,7 +22,6 @@
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/trace_processor/trace_blob_view.h"
-#include "src/trace_processor/importers/common/mapping_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/perf/perf_data_reader.h"
#include "src/trace_processor/importers/perf/perf_data_tracker.h"
@@ -59,8 +58,7 @@
// First instruction pointer in the callchain should be from kernel space, so
// it shouldn't be available in mappings.
- if (context_->mapping_tracker->FindUserMappingForAddress(
- *sample.pid, sample.callchain.front())) {
+ if (tracker_->FindMapping(*sample.pid, sample.callchain.front()).ok()) {
context_->storage->IncrementStats(stats::perf_samples_skipped);
return;
}
@@ -72,22 +70,19 @@
std::vector<FramesTable::Row> frame_rows;
for (uint32_t i = 1; i < sample.callchain.size(); i++) {
- UserMemoryMapping* mapping =
- context_->mapping_tracker->FindUserMappingForAddress(
- *sample.pid, sample.callchain[i]);
- if (!mapping) {
+ auto mapping = tracker_->FindMapping(*sample.pid, sample.callchain[i]);
+ if (!mapping.ok()) {
context_->storage->IncrementStats(stats::perf_samples_skipped);
return;
}
FramesTable::Row new_row;
std::string mock_name =
- base::StackString<1024>(
- "%" PRIu64, sample.callchain[i] - mapping->memory_range().start())
+ base::StackString<1024>("%" PRIu64,
+ sample.callchain[i] - mapping->start)
.ToStdString();
new_row.name = context_->storage->InternString(mock_name.c_str());
- new_row.mapping = mapping->mapping_id();
- new_row.rel_pc =
- static_cast<int64_t>(mapping->ToRelativePc(sample.callchain[i]));
+ new_row.mapping = mapping->id;
+ new_row.rel_pc = static_cast<int64_t>(sample.callchain[i] - mapping->start);
frame_rows.push_back(new_row);
}
diff --git a/src/trace_processor/importers/perf/perf_data_tokenizer.cc b/src/trace_processor/importers/perf/perf_data_tokenizer.cc
index 334148a..be1ec02 100644
--- a/src/trace_processor/importers/perf/perf_data_tokenizer.cc
+++ b/src/trace_processor/importers/perf/perf_data_tokenizer.cc
@@ -15,7 +15,6 @@
*/
#include "src/trace_processor/importers/perf/perf_data_tokenizer.h"
-
#include <cstdint>
#include <cstring>
#include <vector>
@@ -32,29 +31,9 @@
#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/util/status_macros.h"
-#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
-
namespace perfetto {
namespace trace_processor {
namespace perf_importer {
-namespace {
-protos::pbzero::Profiling::CpuMode GetCpuMode(const perf_event_header& header) {
- switch (header.misc & kPerfRecordMiscCpumodeMask) {
- case PERF_RECORD_MISC_KERNEL:
- return protos::pbzero::Profiling::MODE_KERNEL;
- case PERF_RECORD_MISC_USER:
- return protos::pbzero::Profiling::MODE_USER;
- case PERF_RECORD_MISC_HYPERVISOR:
- return protos::pbzero::Profiling::MODE_HYPERVISOR;
- case PERF_RECORD_MISC_GUEST_KERNEL:
- return protos::pbzero::Profiling::MODE_GUEST_KERNEL;
- case PERF_RECORD_MISC_GUEST_USER:
- return protos::pbzero::Profiling::MODE_GUEST_USER;
- default:
- return protos::pbzero::Profiling::MODE_UNKNOWN;
- }
-}
-} // namespace
PerfDataTokenizer::PerfDataTokenizer(TraceProcessorContext* ctx)
: context_(ctx),
@@ -145,7 +124,6 @@
sizeof(PerfDataTracker::Mmap2Record::Numeric));
auto record = ParseMmap2Record(record_size);
RETURN_IF_ERROR(record.status());
- record->cpu_mode = GetCpuMode(ev_header);
tracker_->PushMmap2Record(*record);
break;
}
diff --git a/src/trace_processor/importers/perf/perf_data_tracker.cc b/src/trace_processor/importers/perf/perf_data_tracker.cc
index c670258..0c9b209 100644
--- a/src/trace_processor/importers/perf/perf_data_tracker.cc
+++ b/src/trace_processor/importers/perf/perf_data_tracker.cc
@@ -15,53 +15,12 @@
*/
#include "src/trace_processor/importers/perf/perf_data_tracker.h"
-
-#include <optional>
-
#include "perfetto/base/status.h"
-#include "src/trace_processor/importers/common/address_range.h"
-#include "src/trace_processor/importers/common/mapping_tracker.h"
-#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/storage/stats.h"
-#include "src/trace_processor/storage/trace_storage.h"
-
-#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
namespace perfetto {
namespace trace_processor {
namespace perf_importer {
-namespace {
-
-bool IsInKernel(protos::pbzero::Profiling::CpuMode cpu_mode) {
- switch (cpu_mode) {
- case protos::pbzero::Profiling::MODE_UNKNOWN:
- PERFETTO_CHECK(false);
- case protos::pbzero::Profiling::MODE_GUEST_KERNEL:
- case protos::pbzero::Profiling::MODE_KERNEL:
- return true;
- case protos::pbzero::Profiling::MODE_USER:
- case protos::pbzero::Profiling::MODE_HYPERVISOR:
- case protos::pbzero::Profiling::MODE_GUEST_USER:
- return false;
- }
- PERFETTO_CHECK(false);
-}
-
-CreateMappingParams BuildCreateMappingParams(
- PerfDataTracker::Mmap2Record record) {
- return {AddressRange::FromStartAndSize(record.num.addr, record.num.len),
- record.num.pgoff,
- // start_offset: This is the offset into the file where the ELF header
- // starts. We assume all file mappings are ELF files an thus this
- // offset is 0.
- 0,
- // load_bias: This can only be read out of the actual ELF file, which
- // we do not have here, so we set it to 0. When symbolizing we will
- // hopefully have the real load bias and we can compensate there for a
- // possible mismatch.
- 0, record.filename, std::nullopt};
-}
-} // namespace
PerfDataTracker::~PerfDataTracker() = default;
@@ -89,15 +48,31 @@
}
void PerfDataTracker::PushMmap2Record(Mmap2Record record) {
- if (IsInKernel(record.cpu_mode)) {
- context_->mapping_tracker->CreateKernelMemoryMapping(
- BuildCreateMappingParams(std::move(record)));
- } else {
- UniquePid upid =
- context_->process_tracker->GetOrCreateProcess(record.num.pid);
- context_->mapping_tracker->CreateUserMemoryMapping(
- upid, BuildCreateMappingParams(std::move(record)));
+ const auto mappings =
+ context_->storage->mutable_stack_profile_mapping_table();
+ MappingTable::Row row;
+ row.start = static_cast<int64_t>(record.num.addr);
+ row.end = static_cast<int64_t>(record.num.addr + record.num.len);
+ row.name = context_->storage->InternString(record.filename.c_str());
+ MappingTable::Id id = mappings->Insert(row).id;
+ MmapRange mmap2_range{record.num.addr, record.num.addr + record.num.len, id};
+ mmap2_ranges_[record.num.pid].push_back(mmap2_range);
+}
+
+base::StatusOr<PerfDataTracker::MmapRange> PerfDataTracker::FindMapping(
+ uint32_t pid,
+ uint64_t ips) {
+ auto vec = mmap2_ranges_.Find(pid);
+ if (!vec) {
+ return base::ErrStatus("Sample pid not found in mappings.");
}
+
+ for (const auto& range : *vec) {
+ if (ips >= range.start && ips < range.end) {
+ return range;
+ }
+ }
+ return base::ErrStatus("No mapping for callstack frame instruction pointer");
}
base::StatusOr<PerfDataTracker::PerfSample> PerfDataTracker::ParseSample(
diff --git a/src/trace_processor/importers/perf/perf_data_tracker.h b/src/trace_processor/importers/perf/perf_data_tracker.h
index 11258ed..0ab99aa 100644
--- a/src/trace_processor/importers/perf/perf_data_tracker.h
+++ b/src/trace_processor/importers/perf/perf_data_tracker.h
@@ -25,7 +25,6 @@
#include "perfetto/ext/base/flat_hash_map.h"
#include "perfetto/ext/base/status_or.h"
#include "perfetto/ext/base/string_utils.h"
-#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
#include "src/trace_processor/importers/perf/perf_data_reader.h"
#include "src/trace_processor/importers/perf/perf_event.h"
#include "src/trace_processor/storage/trace_storage.h"
@@ -77,10 +76,14 @@
uint32_t prot;
uint32_t flags;
};
- protos::pbzero::Profiling::CpuMode cpu_mode;
Numeric num;
std::string filename;
};
+ struct MmapRange {
+ uint64_t start;
+ uint64_t end;
+ MappingTable::Id id;
+ };
PerfDataTracker(const PerfDataTracker&) = delete;
PerfDataTracker& operator=(const PerfDataTracker&) = delete;
@@ -100,11 +103,14 @@
base::StatusOr<PerfSample> ParseSample(
perfetto::trace_processor::perf_importer::Reader&);
+ base::StatusOr<MmapRange> FindMapping(uint32_t pid, uint64_t ips);
+
private:
const perf_event_attr* FindAttrWithId(uint64_t id) const;
TraceProcessorContext* context_;
std::vector<AttrAndIds> attrs_;
+ base::FlatHashMap</*pid=*/uint32_t, std::vector<MmapRange>> mmap2_ranges_;
uint64_t common_sample_type_;
};
} // namespace perf_importer
diff --git a/src/trace_processor/importers/perf/perf_data_tracker_unittest.cc b/src/trace_processor/importers/perf/perf_data_tracker_unittest.cc
index 3cbdc80..6c59be6 100644
--- a/src/trace_processor/importers/perf/perf_data_tracker_unittest.cc
+++ b/src/trace_processor/importers/perf/perf_data_tracker_unittest.cc
@@ -22,35 +22,16 @@
#include <vector>
#include "perfetto/base/build_config.h"
-#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
-#include "src/trace_processor/importers/common/address_range.h"
-#include "src/trace_processor/importers/common/mapping_tracker.h"
-#include "src/trace_processor/importers/common/process_tracker.h"
-#include "src/trace_processor/importers/common/stack_profile_tracker.h"
#include "src/trace_processor/importers/perf/perf_event.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
namespace trace_processor {
namespace perf_importer {
-namespace {
-class PerfDataTrackerUnittest : public testing::Test {
- public:
- PerfDataTrackerUnittest() {
- context_.storage = std::make_unique<TraceStorage>();
- context_.process_tracker = std::make_unique<ProcessTracker>(&context_);
- context_.stack_profile_tracker =
- std::make_unique<StackProfileTracker>(&context_);
- context_.mapping_tracker = std::make_unique<MappingTracker>(&context_);
- }
-
- protected:
- TraceProcessorContext context_;
-};
-
-TEST_F(PerfDataTrackerUnittest, ComputeCommonSampleType) {
- PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context_);
+TEST(PerfDataTrackerUnittest, ComputeCommonSampleType) {
+ TraceProcessorContext context;
+ PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context);
PerfDataTracker::AttrAndIds attr_and_ids;
attr_and_ids.attr.sample_type =
@@ -65,15 +46,16 @@
EXPECT_FALSE(tracker->common_sample_type() & PERF_SAMPLE_CALLCHAIN);
}
-TEST_F(PerfDataTrackerUnittest, FindMapping) {
- PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context_);
+TEST(PerfDataTrackerUnittest, FindMapping) {
+ TraceProcessorContext context;
+ context.storage = std::make_unique<TraceStorage>();
+ PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context);
PerfDataTracker::Mmap2Record rec;
rec.filename = "file1";
rec.num.addr = 1000;
rec.num.len = 100;
rec.num.pid = 1;
- rec.cpu_mode = protos::pbzero::Profiling::MODE_USER;
tracker->PushMmap2Record(rec);
rec.num.addr = 2000;
@@ -82,33 +64,32 @@
rec.num.addr = 3000;
tracker->PushMmap2Record(rec);
- UserMemoryMapping* mapping =
- context_.mapping_tracker->FindUserMappingForAddress(
- context_.process_tracker->GetOrCreateProcess(1), 2050);
- ASSERT_NE(mapping, nullptr);
- EXPECT_EQ(mapping->memory_range().start(), 2000u);
- EXPECT_EQ(mapping->memory_range().end(), 2100u);
+ auto res_status = tracker->FindMapping(1, 2050);
+ EXPECT_TRUE(res_status.ok());
+ EXPECT_EQ(res_status->start, 2000u);
+ EXPECT_EQ(res_status->end, 2100u);
}
-TEST_F(PerfDataTrackerUnittest, FindMappingFalse) {
- PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context_);
+TEST(PerfDataTrackerUnittest, FindMappingFalse) {
+ TraceProcessorContext context;
+ context.storage = std::make_unique<TraceStorage>();
+ PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context);
PerfDataTracker::Mmap2Record rec;
rec.filename = "file1";
rec.num.addr = 1000;
rec.num.len = 100;
rec.num.pid = 1;
- rec.cpu_mode = protos::pbzero::Profiling::MODE_USER;
tracker->PushMmap2Record(rec);
- UserMemoryMapping* mapping =
- context_.mapping_tracker->FindUserMappingForAddress(
- context_.process_tracker->GetOrCreateProcess(2), 2050);
- EXPECT_EQ(mapping, nullptr);
+ auto res_status = tracker->FindMapping(2, 2050);
+ EXPECT_FALSE(res_status.ok());
}
-TEST_F(PerfDataTrackerUnittest, ParseSampleTrivial) {
- PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context_);
+TEST(PerfDataTrackerUnittest, ParseSampleTrivial) {
+ TraceProcessorContext context;
+ context.storage = std::make_unique<TraceStorage>();
+ PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context);
PerfDataTracker::AttrAndIds attr_and_ids;
attr_and_ids.attr.sample_type = PERF_SAMPLE_TIME;
@@ -126,8 +107,10 @@
EXPECT_EQ(parsed_sample->ts, 100u);
}
-TEST_F(PerfDataTrackerUnittest, ParseSampleCallchain) {
- PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context_);
+TEST(PerfDataTrackerUnittest, ParseSampleCallchain) {
+ TraceProcessorContext context;
+ context.storage = std::make_unique<TraceStorage>();
+ PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context);
PerfDataTracker::AttrAndIds attr_and_ids;
attr_and_ids.attr.sample_type = PERF_SAMPLE_CALLCHAIN;
@@ -154,8 +137,10 @@
EXPECT_EQ(parsed_sample->callchain.size(), 3u);
}
-TEST_F(PerfDataTrackerUnittest, ParseSampleWithoutId) {
- PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context_);
+TEST(PerfDataTrackerUnittest, ParseSampleWithoutId) {
+ TraceProcessorContext context;
+ context.storage = std::make_unique<TraceStorage>();
+ PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context);
PerfDataTracker::AttrAndIds attr_and_ids;
attr_and_ids.attr.sample_type = PERF_SAMPLE_TID | PERF_SAMPLE_TIME |
@@ -192,8 +177,10 @@
EXPECT_EQ(sample.ts, parsed_sample->ts);
}
-TEST_F(PerfDataTrackerUnittest, ParseSampleWithId) {
- PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context_);
+TEST(PerfDataTrackerUnittest, ParseSampleWithId) {
+ TraceProcessorContext context;
+ context.storage = std::make_unique<TraceStorage>();
+ PerfDataTracker* tracker = PerfDataTracker::GetOrCreate(&context);
PerfDataTracker::AttrAndIds attr_and_ids;
attr_and_ids.attr.sample_type = PERF_SAMPLE_CPU | PERF_SAMPLE_TID |
@@ -235,7 +222,6 @@
EXPECT_EQ(100u, parsed_sample->ts);
}
-} // namespace
} // namespace perf_importer
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/perf/perf_event.h b/src/trace_processor/importers/perf/perf_event.h
index c60709f..53f5f05 100644
--- a/src/trace_processor/importers/perf/perf_event.h
+++ b/src/trace_processor/importers/perf/perf_event.h
@@ -223,15 +223,4 @@
PERF_SAMPLE_MAX = 1U << 25, /* non-ABI */
};
-constexpr auto kPerfRecordMiscCpumodeMask = 0x7;
-
-enum perf_record_misc {
- PERF_RECORD_MISC_CPUMODE_UNKNOWN = 0,
- PERF_RECORD_MISC_KERNEL = 1,
- PERF_RECORD_MISC_USER = 2,
- PERF_RECORD_MISC_HYPERVISOR = 3,
- PERF_RECORD_MISC_GUEST_KERNEL = 4,
- PERF_RECORD_MISC_GUEST_USER = 5,
-};
-
#endif // SRC_TRACE_PROCESSOR_IMPORTERS_PERF_PERF_EVENT_H_
diff --git a/src/trace_processor/importers/proto/BUILD.gn b/src/trace_processor/importers/proto/BUILD.gn
index 2e542d0..2eaa5fe 100644
--- a/src/trace_processor/importers/proto/BUILD.gn
+++ b/src/trace_processor/importers/proto/BUILD.gn
@@ -91,9 +91,9 @@
"../../storage",
"../../tables",
"../../types",
- "../../util:build_id",
"../../util:gzip",
"../../util:profiler_util",
+ "../../util:stack_traces_util",
"../common",
"../common:parser_types",
"../ftrace:minimal",
@@ -181,6 +181,7 @@
"../../util:profiler_util",
"../../util:proto_profiler",
"../../util:proto_to_args_parser",
+ "../../util:stack_traces_util",
"../common",
"../common:parser_types",
"../etw:full",
@@ -275,6 +276,7 @@
"../../types",
"../../util:descriptors",
"../../util:profiler_util",
+ "../../util:stack_traces_util",
"../common",
"../ftrace:full",
]
diff --git a/src/trace_processor/importers/proto/profile_module.cc b/src/trace_processor/importers/proto/profile_module.cc
index b80cae7..61596d3 100644
--- a/src/trace_processor/importers/proto/profile_module.cc
+++ b/src/trace_processor/importers/proto/profile_module.cc
@@ -24,7 +24,6 @@
#include "src/trace_processor/importers/common/clock_tracker.h"
#include "src/trace_processor/importers/common/deobfuscation_mapping_table.h"
#include "src/trace_processor/importers/common/event_tracker.h"
-#include "src/trace_processor/importers/common/mapping_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/stack_profile_tracker.h"
#include "src/trace_processor/importers/proto/packet_sequence_state.h"
@@ -37,8 +36,8 @@
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/tables/profiler_tables_py.h"
#include "src/trace_processor/types/trace_processor_context.h"
-#include "src/trace_processor/util/build_id.h"
#include "src/trace_processor/util/profiler_util.h"
+#include "src/trace_processor/util/stack_traces_util.h"
#include "protos/perfetto/common/builtin_clock.pbzero.h"
#include "protos/perfetto/common/perf_events.pbzero.h"
@@ -429,11 +428,19 @@
void ProfileModule::ParseModuleSymbols(ConstBytes blob) {
protos::pbzero::ModuleSymbols::Decoder module_symbols(blob.data, blob.size);
- BuildId build_id = BuildId::FromRaw(module_symbols.build_id());
+ StringId build_id;
+ // TODO(b/148109467): Remove workaround once all active Chrome versions
+ // write raw bytes instead of a string as build_id.
+ if (util::IsHexModuleId(module_symbols.build_id())) {
+ build_id = context_->storage->InternString(module_symbols.build_id());
+ } else {
+ build_id = context_->storage->InternString(base::StringView(base::ToHex(
+ module_symbols.build_id().data, module_symbols.build_id().size)));
+ }
- auto mappings =
- context_->mapping_tracker->FindMappings(module_symbols.path(), build_id);
- if (mappings.empty()) {
+ auto mapping_ids = context_->stack_profile_tracker->FindMappingRow(
+ context_->storage->InternString(module_symbols.path()), build_id);
+ if (mapping_ids.empty()) {
context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
return;
}
@@ -460,11 +467,12 @@
continue;
}
bool frame_found = false;
- for (VirtualMemoryMapping* mapping : mappings) {
+ for (MappingId mapping_id : mapping_ids) {
context_->args_translation_table->AddNativeSymbolTranslationRule(
- mapping->mapping_id(), address_symbols.address(), last_location);
+ mapping_id, address_symbols.address(), last_location);
std::vector<FrameId> frame_ids =
- mapping->FindFrameIds(address_symbols.address());
+ context_->stack_profile_tracker->FindFrameIds(
+ mapping_id, address_symbols.address());
for (const FrameId frame_id : frame_ids) {
auto* frames = context_->storage->mutable_stack_profile_frame_table();
diff --git a/src/trace_processor/importers/proto/profile_packet_sequence_state.cc b/src/trace_processor/importers/proto/profile_packet_sequence_state.cc
index 31841fc..9d889ef 100644
--- a/src/trace_processor/importers/proto/profile_packet_sequence_state.cc
+++ b/src/trace_processor/importers/proto/profile_packet_sequence_state.cc
@@ -19,8 +19,6 @@
#include "perfetto/base/flat_set.h"
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/string_view.h"
-#include "src/trace_processor/importers/common/address_range.h"
-#include "src/trace_processor/importers/common/mapping_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/stack_profile_tracker.h"
#include "src/trace_processor/importers/proto/packet_sequence_state.h"
@@ -30,7 +28,6 @@
#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"
-#include "src/trace_processor/util/build_id.h"
namespace perfetto {
namespace trace_processor {
@@ -71,16 +68,17 @@
void ProfilePacketSequenceState::AddMapping(SourceMappingId id,
const SourceMapping& mapping) {
- CreateMappingParams params;
+ StackProfileTracker::CreateMappingParams params;
if (std::string* str = strings_.Find(mapping.build_id); str) {
- params.build_id = BuildId::FromRaw(*str);
+ params.build_id = base::StringView(*str);
} else {
context_->storage->IncrementStats(stats::stackprofile_invalid_string_id);
return;
}
params.exact_offset = mapping.exact_offset;
params.start_offset = mapping.start_offset;
- params.memory_range = AddressRange(mapping.start, mapping.end);
+ params.start = mapping.start;
+ params.end = mapping.end;
params.load_bias = mapping.load_bias;
std::vector<base::StringView> path_components;
@@ -95,16 +93,16 @@
break;
}
}
-
- params.name = ProfilePacketUtils::MakeMappingName(path_components);
- mappings_.Insert(
- id, &context_->mapping_tracker->InternMemoryMapping(std::move(params)));
+ std::string path = ProfilePacketUtils::MakeMappingName(path_components);
+ params.name = base::StringView(path);
+ MappingId mapping_id = context_->stack_profile_tracker->InternMapping(params);
+ mappings_.Insert(id, mapping_id);
}
void ProfilePacketSequenceState::AddFrame(SourceFrameId id,
const SourceFrame& frame) {
- VirtualMemoryMapping** mapping = mappings_.Find(frame.mapping_id);
- if (!mapping) {
+ MappingId* mapping_id = mappings_.Find(frame.mapping_id);
+ if (!mapping_id) {
context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
return;
}
@@ -115,8 +113,9 @@
return;
}
- FrameId frame_id =
- (*mapping)->InternFrame(frame.rel_pc, base::StringView(*function_name));
+ FrameId frame_id = context_->stack_profile_tracker->InternFrame(
+ *mapping_id, frame.rel_pc, base::StringView(*function_name));
+
frames_.Insert(id, frame_id);
}
diff --git a/src/trace_processor/importers/proto/profile_packet_sequence_state.h b/src/trace_processor/importers/proto/profile_packet_sequence_state.h
index 99661da..678aab2 100644
--- a/src/trace_processor/importers/proto/profile_packet_sequence_state.h
+++ b/src/trace_processor/importers/proto/profile_packet_sequence_state.h
@@ -23,6 +23,7 @@
#include "perfetto/ext/base/hash.h"
#include "perfetto/ext/base/string_view.h"
+#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
#include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
#include "src/trace_processor/importers/proto/stack_profile_sequence_state.h"
#include "src/trace_processor/storage/trace_storage.h"
@@ -30,8 +31,6 @@
namespace perfetto {
namespace trace_processor {
-class VirtualMemoryMapping;
-
// Keeps sequence specific state for profile packets.
class ProfilePacketSequenceState final
: public PacketSequenceStateGeneration::InternedDataTracker {
@@ -127,7 +126,7 @@
TraceProcessorContext* const context_;
base::FlatHashMap<SourceStringId, std::string> strings_;
- base::FlatHashMap<SourceMappingId, VirtualMemoryMapping*> mappings_;
+ base::FlatHashMap<SourceMappingId, MappingId> mappings_;
base::FlatHashMap<SourceFrameId, FrameId> frames_;
base::FlatHashMap<SourceCallstackId, CallsiteId> callstacks_;
diff --git a/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc b/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc
index c9cd6e3..ab947fa 100644
--- a/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc
+++ b/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc
@@ -18,9 +18,8 @@
#include <memory>
-#include "src/trace_processor/importers/common/mapping_tracker.h"
-#include "src/trace_processor/importers/common/stack_profile_tracker.h"
#include "src/trace_processor/importers/proto/packet_sequence_state.h"
+#include "src/trace_processor/importers/common/stack_profile_tracker.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "test/gtest_and_gmock.h"
@@ -59,7 +58,6 @@
public:
HeapProfileTrackerDupTest() {
context.storage.reset(new TraceStorage());
- context.mapping_tracker.reset(new MappingTracker(&context));
context.stack_profile_tracker.reset(new StackProfileTracker(&context));
packet_sequence_state.reset(new PacketSequenceState(&context));
@@ -198,7 +196,6 @@
TEST(HeapProfileTrackerTest, SourceMappingPath) {
TraceProcessorContext context;
context.storage.reset(new TraceStorage());
- context.mapping_tracker.reset(new MappingTracker(&context));
context.stack_profile_tracker.reset(new StackProfileTracker(&context));
PacketSequenceState pss(&context);
ProfilePacketSequenceState& ppss =
@@ -232,7 +229,6 @@
TEST(HeapProfileTrackerTest, Functional) {
TraceProcessorContext context;
context.storage.reset(new TraceStorage());
- context.mapping_tracker.reset(new MappingTracker(&context));
context.stack_profile_tracker.reset(new StackProfileTracker(&context));
PacketSequenceState pss(&context);
diff --git a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
index e612709..11a45f5 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
@@ -25,7 +25,6 @@
#include "src/trace_processor/importers/common/clock_tracker.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/mapping_tracker.h"
#include "src/trace_processor/importers/common/metadata_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/slice_tracker.h"
@@ -253,7 +252,6 @@
context_.track_tracker.reset(new TrackTracker(&context_));
context_.global_args_tracker.reset(
new GlobalArgsTracker(context_.storage.get()));
- context_.mapping_tracker.reset(new MappingTracker(&context_));
context_.stack_profile_tracker.reset(new StackProfileTracker(&context_));
context_.args_tracker.reset(new ArgsTracker(&context_));
context_.args_translation_table.reset(new ArgsTranslationTable(storage_));
diff --git a/src/trace_processor/importers/proto/stack_profile_sequence_state.cc b/src/trace_processor/importers/proto/stack_profile_sequence_state.cc
index a469f92..e503a09 100644
--- a/src/trace_processor/importers/proto/stack_profile_sequence_state.cc
+++ b/src/trace_processor/importers/proto/stack_profile_sequence_state.cc
@@ -23,8 +23,6 @@
#include "perfetto/ext/base/string_view.h"
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
-#include "src/trace_processor/importers/common/address_range.h"
-#include "src/trace_processor/importers/common/mapping_tracker.h"
#include "src/trace_processor/importers/common/stack_profile_tracker.h"
#include "src/trace_processor/importers/proto/packet_sequence_state.h"
#include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
@@ -32,7 +30,6 @@
#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"
-#include "src/trace_processor/util/build_id.h"
namespace perfetto {
namespace trace_processor {
@@ -51,23 +48,21 @@
std::optional<MappingId> StackProfileSequenceState::FindOrInsertMapping(
uint64_t iid) {
- if (VirtualMemoryMapping* mapping = FindOrInsertMappingImpl(iid); mapping) {
- return mapping->mapping_id();
- }
- return std::nullopt;
-}
-
-VirtualMemoryMapping* StackProfileSequenceState::FindOrInsertMappingImpl(
- uint64_t iid) {
- if (auto ptr = cached_mappings_.Find(iid); ptr) {
- return *ptr;
+ if (MappingId* id = cached_mappings_.Find(iid); id) {
+ return *id;
}
auto* decoder =
LookupInternedMessage<protos::pbzero::InternedData::kMappingsFieldNumber,
protos::pbzero::Mapping>(iid);
if (!decoder) {
context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
- return nullptr;
+ return std::nullopt;
+ }
+
+ std::optional<base::StringView> build_id =
+ LookupInternedBuildId(decoder->build_id());
+ if (!build_id) {
+ return std::nullopt;
}
std::vector<base::StringView> path_components;
@@ -80,26 +75,19 @@
}
path_components.push_back(*str);
}
+ std::string path = ProfilePacketUtils::MakeMappingName(path_components);
- CreateMappingParams params;
- std::optional<base::StringView> build_id =
- LookupInternedBuildId(decoder->build_id());
- if (!build_id) {
- return nullptr;
- }
- params.build_id = BuildId::FromRaw(*build_id);
-
- params.memory_range = AddressRange(decoder->start(), decoder->end());
+ StackProfileTracker::CreateMappingParams params;
+ params.build_id = *build_id;
params.exact_offset = decoder->exact_offset();
params.start_offset = decoder->start_offset();
+ params.start = decoder->start();
+ params.end = decoder->end();
params.load_bias = decoder->load_bias();
- params.name = ProfilePacketUtils::MakeMappingName(path_components);
-
- VirtualMemoryMapping& mapping =
- context_->mapping_tracker->InternMemoryMapping(std::move(params));
-
- cached_mappings_.Insert(iid, &mapping);
- return &mapping;
+ params.name = base::StringView(path);
+ MappingId mapping_id = context_->stack_profile_tracker->InternMapping(params);
+ cached_mappings_.Insert(iid, mapping_id);
+ return mapping_id;
}
std::optional<base::StringView>
@@ -122,6 +110,11 @@
std::optional<base::StringView>
StackProfileSequenceState::LookupInternedMappingPath(uint64_t iid) {
+ // This should really be an error (value not set) or at the very least return
+ // a null string, but for backward compatibility use an empty string instead.
+ if (iid == 0) {
+ return "";
+ }
auto* decoder = LookupInternedMessage<
protos::pbzero::InternedData::kMappingPathsFieldNumber,
protos::pbzero::InternedString>(iid);
@@ -165,7 +158,7 @@
cached_callstacks_.Insert(iid, *parent_callsite_id);
- return parent_callsite_id;
+ return *parent_callsite_id;
}
std::optional<FrameId> StackProfileSequenceState::FindOrInsertFrame(
@@ -181,9 +174,9 @@
return std::nullopt;
}
- VirtualMemoryMapping* mapping =
- FindOrInsertMappingImpl(decoder->mapping_id());
- if (!mapping) {
+ std::optional<MappingId> mapping_id =
+ FindOrInsertMapping(decoder->mapping_id());
+ if (!mapping_id) {
return std::nullopt;
}
@@ -197,7 +190,9 @@
function_name = *func;
}
- FrameId frame_id = mapping->InternFrame(decoder->rel_pc(), function_name);
+ FrameId frame_id = context_->stack_profile_tracker->InternFrame(
+ *mapping_id, decoder->rel_pc(), function_name);
+
cached_frames_.Insert(iid, frame_id);
return frame_id;
diff --git a/src/trace_processor/importers/proto/stack_profile_sequence_state.h b/src/trace_processor/importers/proto/stack_profile_sequence_state.h
index 82de785..7a7879a 100644
--- a/src/trace_processor/importers/proto/stack_profile_sequence_state.h
+++ b/src/trace_processor/importers/proto/stack_profile_sequence_state.h
@@ -30,7 +30,6 @@
namespace trace_processor {
class TraceProcessorContext;
-class VirtualMemoryMapping;
class StackProfileSequenceState final
: public PacketSequenceStateGeneration::InternedDataTracker {
@@ -45,15 +44,13 @@
std::optional<CallsiteId> FindOrInsertCallstack(uint64_t iid);
private:
- // Returns `nullptr`if non could be found.
- VirtualMemoryMapping* FindOrInsertMappingImpl(uint64_t iid);
std::optional<base::StringView> LookupInternedBuildId(uint64_t iid);
std::optional<base::StringView> LookupInternedMappingPath(uint64_t iid);
std::optional<base::StringView> LookupInternedFunctionName(uint64_t iid);
std::optional<FrameId> FindOrInsertFrame(uint64_t iid);
TraceProcessorContext* const context_;
- base::FlatHashMap<uint64_t, VirtualMemoryMapping*> cached_mappings_;
+ base::FlatHashMap<uint64_t, MappingId> cached_mappings_;
base::FlatHashMap<uint64_t, CallsiteId> cached_callstacks_;
base::FlatHashMap<uint64_t, FrameId> cached_frames_;
};
diff --git a/src/trace_processor/perfetto_sql/stdlib/slices/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/slices/BUILD.gn
index 2e5f02f..f69eafd 100644
--- a/src/trace_processor/perfetto_sql/stdlib/slices/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/stdlib/slices/BUILD.gn
@@ -16,6 +16,7 @@
perfetto_sql_source_set("slices") {
sources = [
+ "cpu_time.sql",
"flat_slices.sql",
"slices.sql",
"with_context.sql",
diff --git a/src/trace_processor/perfetto_sql/stdlib/slices/cpu_time.sql b/src/trace_processor/perfetto_sql/stdlib/slices/cpu_time.sql
new file mode 100644
index 0000000..4a36d9c
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/stdlib/slices/cpu_time.sql
@@ -0,0 +1,72 @@
+--
+-- Copyright 2024 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.
+
+-- TODO(mayzner): Replace with good implementation of interval intersect.
+CREATE PERFETTO MACRO _interval_intersect_partition_utid(
+ left_table TableOrSubquery,
+ right_table TableOrSubquery
+)
+RETURNS TableOrSubquery AS
+(
+ WITH on_left AS (
+ SELECT
+ B.ts,
+ IIF(
+ A.ts + A.dur <= B.ts + B.dur,
+ A.ts + A.dur - B.ts, B.dur) AS dur,
+ A.id AS left_id,
+ B.id as right_id
+ FROM $left_table A
+ JOIN $right_table B ON (A.ts <= B.ts AND A.ts + A.dur > B.ts AND A.utid = B.utid)
+ ), on_right AS (
+ SELECT
+ B.ts,
+ IIF(
+ A.ts + A.dur <= B.ts + B.dur,
+ A.ts + A.dur - B.ts, B.dur) AS dur,
+ B.id as left_id,
+ A.id AS right_id
+ FROM $right_table A
+ -- The difference between this table and on_left is the lack of equality on
+ -- A.ts <= B.ts. This is to remove the issue of double accounting
+ -- timestamps that start at the same time.
+ JOIN $left_table B ON (A.ts < B.ts AND A.ts + A.dur > B.ts AND A.utid = B.utid)
+ )
+ SELECT * FROM on_left
+ UNION ALL
+ SELECT * FROM on_right
+);
+
+-- Time each thread slice spent running on CPU.
+-- Requires scheduling data to be available in the trace.
+CREATE PERFETTO TABLE thread_slice_cpu_time(
+ -- Slice id.
+ id INT,
+ -- Duration of the time the slice was running.
+ cpu_time INT) AS
+WITH slice_with_utid AS (
+ SELECT
+ slice.id,
+ slice.ts,
+ slice.dur,
+ utid
+ FROM slice
+ JOIN thread_track ON slice.track_id = thread_track.id
+ JOIN thread USING (utid)
+ WHERE utid != 0)
+SELECT left_id AS id, SUM(dur) AS cpu_time
+FROM _interval_intersect_partition_utid!(slice_with_utid, sched)
+GROUP BY 1
+ORDER BY 1;
\ No newline at end of file
diff --git a/src/trace_processor/trace_processor_context.cc b/src/trace_processor/trace_processor_context.cc
index 2ee7b3d..908fdea 100644
--- a/src/trace_processor/trace_processor_context.cc
+++ b/src/trace_processor/trace_processor_context.cc
@@ -27,7 +27,6 @@
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/flow_tracker.h"
#include "src/trace_processor/importers/common/global_args_tracker.h"
-#include "src/trace_processor/importers/common/mapping_tracker.h"
#include "src/trace_processor/importers/common/metadata_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/sched_event_tracker.h"
diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc
index b0c7a15..1f06a0f 100644
--- a/src/trace_processor/trace_processor_storage_impl.cc
+++ b/src/trace_processor/trace_processor_storage_impl.cc
@@ -26,7 +26,6 @@
#include "src/trace_processor/importers/common/clock_tracker.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/mapping_tracker.h"
#include "src/trace_processor/importers/common/metadata_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/sched_event_tracker.h"
@@ -65,7 +64,6 @@
context_.process_tracker.reset(new ProcessTracker(&context_));
context_.clock_tracker.reset(new ClockTracker(&context_));
context_.clock_converter.reset(new ClockConverter(&context_));
- context_.mapping_tracker.reset(new MappingTracker(&context_));
context_.perf_sample_tracker.reset(new PerfSampleTracker(&context_));
context_.stack_profile_tracker.reset(new StackProfileTracker(&context_));
context_.metadata_tracker.reset(new MetadataTracker(context_.storage.get()));
diff --git a/src/trace_processor/types/trace_processor_context.h b/src/trace_processor/types/trace_processor_context.h
index 26d1ff5..3b3336c 100644
--- a/src/trace_processor/types/trace_processor_context.h
+++ b/src/trace_processor/types/trace_processor_context.h
@@ -55,7 +55,6 @@
class StackProfileTracker;
class HeapGraphTracker;
class PerfSampleTracker;
-class MappingTracker;
class MetadataTracker;
class PacketAnalyzer;
class ProtoImporterModule;
@@ -103,7 +102,6 @@
std::unique_ptr<SchedEventTracker> sched_event_tracker;
std::unique_ptr<ClockTracker> clock_tracker;
std::unique_ptr<ClockConverter> clock_converter;
- std::unique_ptr<MappingTracker> mapping_tracker;
std::unique_ptr<PerfSampleTracker> perf_sample_tracker;
std::unique_ptr<StackProfileTracker> stack_profile_tracker;
std::unique_ptr<MetadataTracker> metadata_tracker;
diff --git a/src/trace_processor/util/BUILD.gn b/src/trace_processor/util/BUILD.gn
index 13aefe5..8420a06 100644
--- a/src/trace_processor/util/BUILD.gn
+++ b/src/trace_processor/util/BUILD.gn
@@ -61,17 +61,6 @@
}
}
-source_set("build_id") {
- sources = [
- "build_id.cc",
- "build_id.h",
- ]
- deps = [
- "../../../gn:default_deps",
- "../../../include/perfetto/ext/base:base",
- ]
-}
-
source_set("profiler_util") {
sources = [
"profiler_util.cc",
@@ -85,6 +74,18 @@
]
}
+source_set("stack_traces_util") {
+ sources = [
+ "stack_traces_util.cc",
+ "stack_traces_util.h",
+ ]
+ deps = [
+ "../../../gn:default_deps",
+ "../../../include/perfetto/ext/base:base",
+ "../../../protos/perfetto/trace/profiling:zero",
+ ]
+}
+
source_set("protozero_to_text") {
sources = [
"protozero_to_text.cc",
diff --git a/src/trace_processor/util/build_id.cc b/src/trace_processor/util/build_id.cc
deleted file mode 100644
index 889291d..0000000
--- a/src/trace_processor/util/build_id.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2023 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 "src/trace_processor/util/build_id.h"
-
-#include <cctype>
-#include <cstddef>
-#include <string>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/string_view.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-uint8_t HexToBinary(char c) {
- switch (c) {
- case '0':
- return 0;
- case '1':
- return 1;
- case '2':
- return 2;
- case '3':
- return 3;
- case '4':
- return 4;
- case '5':
- return 5;
- case '6':
- return 6;
- case '7':
- return 7;
- case '8':
- return 8;
- case '9':
- return 9;
- case 'a':
- case 'A':
- return 10;
- case 'b':
- case 'B':
- return 11;
- case 'c':
- case 'C':
- return 12;
- case 'd':
- case 'D':
- return 13;
- case 'e':
- case 'E':
- return 14;
- case 'f':
- case 'F':
- return 15;
- default:
- PERFETTO_CHECK(false);
- }
-}
-
-std::string HexToBinary(base::StringView hex) {
- std::string res;
- res.reserve((hex.size() + 1) / 2);
- auto it = hex.begin();
-
- if (hex.size() % 2 != 0) {
- res.push_back(static_cast<char>(HexToBinary(*it)));
- ++it;
- }
-
- while (it != hex.end()) {
- int v = (HexToBinary(*it++) << 4);
- v += HexToBinary(*it++);
- res.push_back(static_cast<char>(v));
- }
- return res;
-}
-
-bool IsHex(base::StringView module) {
- for (char c : module) {
- if (!std::isxdigit(c)) {
- return false;
- }
- }
- return true;
-}
-
-// Returns whether this string is of a hex chrome module or not to decide
-// whether to convert the module to/from hex.
-// TODO(b/148109467): Remove workaround once all active Chrome versions
-// write raw bytes instead of a string as build_id.
-bool IsHexModuleId(base::StringView module) {
- return module.size() == 33 && IsHex(module);
-}
-
-} // namespace
-
-// static
-BuildId BuildId::FromHex(base::StringView data) {
- if (IsHexModuleId(data)) {
- return BuildId(data.ToStdString());
- }
- return BuildId(HexToBinary(data));
-}
-
-std::string BuildId::ToHex() const {
- if (IsHexModuleId(base::StringView(raw_))) {
- return raw_;
- }
- return base::ToHex(raw_.data(), raw_.size());
-}
-
-} // namespace trace_processor
-} // namespace perfetto
diff --git a/src/trace_processor/util/build_id.h b/src/trace_processor/util/build_id.h
deleted file mode 100644
index 64ec9ac..0000000
--- a/src/trace_processor/util/build_id.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_UTIL_BUILD_ID_H_
-#define SRC_TRACE_PROCESSOR_UTIL_BUILD_ID_H_
-
-#include <string>
-#include <utility>
-
-#include "perfetto/ext/base/hash.h"
-#include "perfetto/ext/base/string_view.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Represents the unique identifier of an executable, shared library, or module.
-// For example for ELF files this is the id stored in the .note.gnu.build-id
-// section. Sometimes a breakpad module id is used.
-// This class abstracts away the details of where this id comes from and how it
-// is converted to a StringId which is the representation used by tables in
-// trace_processor.
-class BuildId {
- public:
- // Allow hashing with base::Hash.
- static constexpr bool kHashable = true;
- size_t size() const { return raw_.size(); }
- const char* data() const { return raw_.data(); }
-
- static BuildId FromHex(base::StringView data);
-
- static BuildId FromRaw(base::StringView data) {
- return BuildId(data.ToStdString());
- }
- static BuildId FromRaw(std::string data) { return BuildId(std::move(data)); }
- static BuildId FromRaw(const uint8_t* data, size_t size) {
- return BuildId(std::string(reinterpret_cast<const char*>(data), size));
- }
-
- BuildId(const BuildId&) = default;
- BuildId(BuildId&&) = default;
-
- BuildId& operator=(const BuildId&) = default;
- BuildId& operator=(BuildId&&) = default;
-
- bool operator==(const BuildId& o) const { return raw_ == o.raw_; }
-
- bool operator!=(const BuildId& o) const { return !(*this == o); }
-
- bool operator<(const BuildId& o) const { return raw_ < o.raw_; }
-
- std::string ToHex() const;
-
- const std::string& raw() const { return raw_; }
-
- private:
- explicit BuildId(std::string data) : raw_(std::move(data)) {}
- std::string raw_;
-};
-
-} // namespace trace_processor
-} // namespace perfetto
-
-template <>
-struct std::hash<perfetto::trace_processor::BuildId> {
- std::size_t operator()(
- const perfetto::trace_processor::BuildId& o) const noexcept {
- return perfetto::base::Hasher::Combine(o);
- }
-};
-
-#endif // SRC_TRACE_PROCESSOR_UTIL_BUILD_ID_H_
diff --git a/src/trace_processor/util/stack_traces_util.cc b/src/trace_processor/util/stack_traces_util.cc
new file mode 100644
index 0000000..a255560
--- /dev/null
+++ b/src/trace_processor/util/stack_traces_util.cc
@@ -0,0 +1,30 @@
+/*
+ * 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 "src/trace_processor/util/stack_traces_util.h"
+#include "perfetto/ext/base/string_view.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace util {
+
+bool IsHexModuleId(base::StringView module) {
+ return module.size() == 33;
+}
+
+} // namespace util
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/util/stack_traces_util.h b/src/trace_processor/util/stack_traces_util.h
new file mode 100644
index 0000000..1171786
--- /dev/null
+++ b/src/trace_processor/util/stack_traces_util.h
@@ -0,0 +1,36 @@
+/*
+ * 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 SRC_TRACE_PROCESSOR_UTIL_STACK_TRACES_UTIL_H_
+#define SRC_TRACE_PROCESSOR_UTIL_STACK_TRACES_UTIL_H_
+
+#include "perfetto/ext/base/string_view.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace util {
+
+// Returns whether this string is of a hex chrome module or not to decide
+// whether to convert the module to/from hex.
+// TODO(b/148109467): Remove workaround once all active Chrome versions
+// write raw bytes instead of a string as build_id.
+bool IsHexModuleId(base::StringView module);
+
+} // namespace util
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_UTIL_STACK_TRACES_UTIL_H_
diff --git a/src/trace_redaction/trace_redactor_integrationtest.cc b/src/trace_redaction/trace_redactor_integrationtest.cc
index 8f14744..50074b1 100644
--- a/src/trace_redaction/trace_redactor_integrationtest.cc
+++ b/src/trace_redaction/trace_redactor_integrationtest.cc
@@ -23,6 +23,7 @@
#include "perfetto/base/status.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/temp_file.h"
+#include "src/base/test/tmp_dir_tree.h"
#include "src/base/test/utils.h"
#include "src/trace_redaction/find_package_uid.h"
#include "src/trace_redaction/prune_package_list.h"
@@ -54,13 +55,10 @@
protected:
void SetUp() override {
src_trace_ = base::GetTestDataPath(std::string(kTracePath));
- dest_trace_ = std::make_unique<base::TempFile>(base::TempFile::Create());
}
const std::string& src_trace() const { return src_trace_; }
- const std::string& dest_trace() const { return dest_trace_->path(); }
-
std::vector<protozero::ConstBytes> GetPackageInfos(
const Trace::Decoder& trace) const {
std::vector<protozero::ConstBytes> infos;
@@ -79,9 +77,8 @@
return infos;
}
- private:
std::string src_trace_;
- std::unique_ptr<base::TempFile> dest_trace_;
+ base::TmpDirTree tmp_dir_;
};
TEST_F(TraceRedactorIntegrationTest, FindsPackageAndFiltersPackageList) {
@@ -92,12 +89,15 @@
Context context;
context.package_name = "com.Unity.com.unity.multiplayer.samples.coop";
- auto result = redaction.Redact(src_trace(), dest_trace(), &context);
+ auto result = redaction.Redact(
+ src_trace(), tmp_dir_.AbsolutePath("dst.pftrace"), &context);
+ tmp_dir_.TrackFile("dst.pftrace");
ASSERT_TRUE(result.ok()) << result.message();
std::string redacted_buffer;
- ASSERT_TRUE(base::ReadFile(dest_trace(), &redacted_buffer));
+ ASSERT_TRUE(
+ base::ReadFile(tmp_dir_.AbsolutePath("dst.pftrace"), &redacted_buffer));
Trace::Decoder redacted_trace(redacted_buffer);
std::vector<protozero::ConstBytes> infos = GetPackageInfos(redacted_trace);
@@ -139,11 +139,14 @@
Context context;
context.package_name = "com.google.android.networkstack.tethering";
- auto result = redaction.Redact(src_trace(), dest_trace(), &context);
+ auto result = redaction.Redact(
+ src_trace(), tmp_dir_.AbsolutePath("dst.pftrace"), &context);
+ tmp_dir_.TrackFile("dst.pftrace");
ASSERT_TRUE(result.ok()) << result.message();
std::string redacted_buffer;
- ASSERT_TRUE(base::ReadFile(dest_trace(), &redacted_buffer));
+ ASSERT_TRUE(
+ base::ReadFile(tmp_dir_.AbsolutePath("dst.pftrace"), &redacted_buffer));
Trace::Decoder redacted_trace(redacted_buffer);
std::vector<protozero::ConstBytes> infos = GetPackageInfos(redacted_trace);
diff --git a/test/trace_processor/diff_tests/stdlib/slices/tests.py b/test/trace_processor/diff_tests/stdlib/slices/tests.py
index e3db459..053dabf 100644
--- a/test/trace_processor/diff_tests/stdlib/slices/tests.py
+++ b/test/trace_processor/diff_tests/stdlib/slices/tests.py
@@ -91,4 +91,28 @@
"ThreadControllerImpl::RunTask",174796099970797,186000,0
"Looper.dispatch: jy3(null)",174800056530797,1368000,0
"ThreadControllerImpl::RunTask",174800107962797,132000,0
- """))
\ No newline at end of file
+ """))
+
+ def test_thread_slice_cpu_time(self):
+ return DiffTestBlueprint(
+ trace=DataPath('example_android_trace_30s.pb'),
+ query="""
+ INCLUDE PERFETTO MODULE slices.cpu_time;
+
+ SELECT *
+ FROM thread_slice_cpu_time
+ LIMIT 10;
+ """,
+ out=Csv("""
+ "id","cpu_time"
+ 0,178646
+ 1,119740
+ 2,58073
+ 3,98698
+ 4,121979
+ 5,45000
+ 6,35104
+ 7,33333
+ 8,46926
+ 9,17865
+ """))
\ No newline at end of file