Merge "trace_processor: allow selecting rowmaps with smaller rowmaps"
diff --git a/bazel/rules.bzl b/bazel/rules.bzl
index 7fca94d..498f34a 100644
--- a/bazel/rules.bzl
+++ b/bazel/rules.bzl
@@ -22,7 +22,9 @@
def default_cc_args():
return {
"deps": PERFETTO_CONFIG.deps.build_config,
- "copts": [],
+ "copts": [
+ "-Wno-pragma-system-header-outside-header",
+ ],
"includes": ["include"],
"linkopts": select({
"@perfetto//bazel:os_linux": ["-ldl", "-lrt", "-lpthread"],
diff --git a/include/perfetto/tracing/event_context.h b/include/perfetto/tracing/event_context.h
index da1607b..fe9c4bb 100644
--- a/include/perfetto/tracing/event_context.h
+++ b/include/perfetto/tracing/event_context.h
@@ -35,9 +35,15 @@
// dbg->set_int_value(1234);
// });
//
-class EventContext {
+class PERFETTO_EXPORT EventContext {
public:
EventContext(EventContext&&) = default;
+
+ // For Chromium during the transition phase to the client library.
+ // TODO(eseckler): Remove once Chromium has switched to client lib entirely.
+ explicit EventContext(protos::pbzero::TrackEvent* event)
+ : event_(event), incremental_state_(nullptr) {}
+
~EventContext();
protos::pbzero::TrackEvent* event() const { return event_; }
diff --git a/src/trace_processor/containers/bit_vector.h b/src/trace_processor/containers/bit_vector.h
index 58b9e23..5ef0f74 100644
--- a/src/trace_processor/containers/bit_vector.h
+++ b/src/trace_processor/containers/bit_vector.h
@@ -107,8 +107,8 @@
PERFETTO_DCHECK(it != counts_.begin());
// Go back one block to find the block which has the bit we are looking for.
- uint16_t block_idx =
- static_cast<uint16_t>(std::distance(counts_.begin(), it) - 1);
+ uint32_t block_idx =
+ static_cast<uint32_t>(std::distance(counts_.begin(), it) - 1);
// Figure out how many set bits forward we are looking inside the block
// by taking away the number of bits at the start of the block from n.
diff --git a/src/trace_processor/heap_profile_tracker.cc b/src/trace_processor/heap_profile_tracker.cc
index a666dad..4bf0756 100644
--- a/src/trace_processor/heap_profile_tracker.cc
+++ b/src/trace_processor/heap_profile_tracker.cc
@@ -45,23 +45,23 @@
const SourceAllocation& alloc,
const StackProfileTracker::InternLookup* intern_lookup) {
SequenceState& sequence_state = sequence_state_[seq_id];
- auto maybe_callstack_id =
- stack_profile_tracker->FindCallstack(alloc.callstack_id, intern_lookup);
+ auto maybe_callstack_id = stack_profile_tracker->FindOrInsertCallstack(
+ alloc.callstack_id, intern_lookup);
if (!maybe_callstack_id)
return;
- int64_t callstack_id = *maybe_callstack_id;
+ CallsiteId callstack_id = *maybe_callstack_id;
UniquePid upid = context_->process_tracker->GetOrCreateProcess(
static_cast<uint32_t>(alloc.pid));
tables::HeapProfileAllocationTable::Row alloc_row{
- alloc.timestamp, upid, callstack_id,
+ alloc.timestamp, upid, callstack_id.value,
static_cast<int64_t>(alloc.alloc_count),
static_cast<int64_t>(alloc.self_allocated)};
tables::HeapProfileAllocationTable::Row free_row{
- alloc.timestamp, upid, callstack_id,
+ alloc.timestamp, upid, callstack_id.value,
-static_cast<int64_t>(alloc.free_count),
-static_cast<int64_t>(alloc.self_freed)};
diff --git a/src/trace_processor/heap_profile_tracker.h b/src/trace_processor/heap_profile_tracker.h
index 1d121aa..93a2440 100644
--- a/src/trace_processor/heap_profile_tracker.h
+++ b/src/trace_processor/heap_profile_tracker.h
@@ -77,10 +77,10 @@
struct SequenceState {
std::vector<SourceAllocation> pending_allocs;
- std::unordered_map<std::pair<UniquePid, int64_t>,
+ std::unordered_map<std::pair<UniquePid, CallsiteId>,
tables::HeapProfileAllocationTable::Row>
prev_alloc;
- std::unordered_map<std::pair<UniquePid, int64_t>,
+ std::unordered_map<std::pair<UniquePid, CallsiteId>,
tables::HeapProfileAllocationTable::Row>
prev_free;
diff --git a/src/trace_processor/heap_profile_tracker_unittest.cc b/src/trace_processor/heap_profile_tracker_unittest.cc
index 91c3f93..d9d3e1d 100644
--- a/src/trace_processor/heap_profile_tracker_unittest.cc
+++ b/src/trace_processor/heap_profile_tracker_unittest.cc
@@ -181,11 +181,11 @@
int64_t FindCallstack(const TraceStorage& storage,
int64_t depth,
int64_t parent,
- int64_t frame_id) {
+ FrameId frame_id) {
const auto& callsites = storage.stack_profile_callsite_table();
for (uint32_t i = 0; i < callsites.row_count(); ++i) {
if (callsites.depth()[i] == depth && callsites.parent_id()[i] == parent &&
- callsites.frame_id()[i] == frame_id) {
+ callsites.frame_id()[i] == frame_id.value) {
return static_cast<int64_t>(i);
}
}
@@ -327,7 +327,6 @@
const StackProfileTracker::SourceCallstack& callstack = callstacks[i];
for (size_t depth = 0; depth < callstack.size(); ++depth) {
auto frame_id = spt->GetDatabaseFrameIdForTesting(callstack[depth]);
- ASSERT_NE(frame_id, -1);
int64_t self = FindCallstack(
*context.storage, static_cast<int64_t>(depth), parent, frame_id);
ASSERT_NE(self, -1);
diff --git a/src/trace_processor/importers/proto/packet_sequence_state.h b/src/trace_processor/importers/proto/packet_sequence_state.h
index 903f99d..81ec6e0 100644
--- a/src/trace_processor/importers/proto/packet_sequence_state.h
+++ b/src/trace_processor/importers/proto/packet_sequence_state.h
@@ -47,7 +47,7 @@
public:
InternedMessageView(TraceBlobView msg) : message_(std::move(msg)) {}
- InternedMessageView(InternedMessageView&&) noexcept = default;
+ InternedMessageView(InternedMessageView&&) = default;
InternedMessageView& operator=(InternedMessageView&&) = default;
// Allow copy by cloning the TraceBlobView. This is required for
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index b2b852f..4c5566d 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -445,15 +445,15 @@
break;
}
- auto maybe_callstack_id =
- stack_profile_tracker.FindCallstack(*callstack_it, &intern_lookup);
+ auto maybe_callstack_id = stack_profile_tracker.FindOrInsertCallstack(
+ *callstack_it, &intern_lookup);
if (!maybe_callstack_id) {
context_->storage->IncrementStats(stats::stackprofile_parser_error);
PERFETTO_ELOG("StreamingProfilePacket referencing invalid callstack!");
continue;
}
- int64_t callstack_id = *maybe_callstack_id;
+ uint32_t callstack_id = maybe_callstack_id->value;
tables::CpuProfileStackSampleTable::Row sample_row{
sequence_state->state()->IncrementAndGetTrackEventTimeNs(*timestamp_it *
@@ -631,10 +631,10 @@
protos::pbzero::ModuleSymbols::Decoder module_symbols(blob.data, blob.size);
std::string hex_build_id = base::ToHex(module_symbols.build_id().data,
module_symbols.build_id().size);
- auto mapping_rows = context_->storage->FindMappingRow(
+ auto mapping_ids = context_->storage->FindMappingRow(
context_->storage->InternString(module_symbols.path()),
context_->storage->InternString(base::StringView(hex_build_id)));
- if (mapping_rows.empty()) {
+ if (mapping_ids.empty()) {
context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
return;
}
@@ -643,16 +643,14 @@
uint32_t symbol_set_id = context_->storage->symbol_table().row_count();
bool frame_found = false;
- for (int64_t mapping_row : mapping_rows) {
- std::vector<int64_t> frame_rows = context_->storage->FindFrameRow(
- static_cast<size_t>(mapping_row), address_symbols.address());
+ for (MappingId mapping_id : mapping_ids) {
+ std::vector<FrameId> frame_ids = context_->storage->FindFrameIds(
+ mapping_id, address_symbols.address());
- for (const int64_t frame_row : frame_rows) {
- PERFETTO_DCHECK(frame_row >= 0);
-
- uint32_t row_idx = static_cast<uint32_t>(frame_row);
+ for (const FrameId frame_id : frame_ids) {
auto* frames = context_->storage->mutable_stack_profile_frame_table();
- frames->mutable_symbol_set_id()->Set(row_idx, symbol_set_id);
+ uint32_t frame_row = *frames->id().IndexOf(frame_id);
+ frames->mutable_symbol_set_id()->Set(frame_row, symbol_set_id);
frame_found = true;
}
}
diff --git a/src/trace_processor/importers/systrace/systrace_trace_parser.cc b/src/trace_processor/importers/systrace/systrace_trace_parser.cc
index 2ffaac4..d23581c 100644
--- a/src/trace_processor/importers/systrace/systrace_trace_parser.cc
+++ b/src/trace_processor/importers/systrace/systrace_trace_parser.cc
@@ -27,6 +27,7 @@
#include "src/trace_processor/track_tracker.h"
#include <inttypes.h>
+#include <cctype>
#include <string>
#include <unordered_map>
@@ -37,9 +38,9 @@
std::string SubstrTrim(const std::string& input) {
std::string s = input;
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
- [](int ch) { return !std::isspace(ch); }));
+ [](char ch) { return !std::isspace(ch); }));
s.erase(std::find_if(s.rbegin(), s.rend(),
- [](int ch) { return !std::isspace(ch); })
+ [](char ch) { return !std::isspace(ch); })
.base(),
s.end());
return s;
diff --git a/src/trace_processor/stack_profile_tracker.cc b/src/trace_processor/stack_profile_tracker.cc
index b4f8f9b..63443f4 100644
--- a/src/trace_processor/stack_profile_tracker.cc
+++ b/src/trace_processor/stack_profile_tracker.cc
@@ -43,14 +43,14 @@
string_map_.emplace(id, str.ToStdString());
}
-base::Optional<int64_t> StackProfileTracker::AddMapping(
+base::Optional<MappingId> StackProfileTracker::AddMapping(
SourceMappingId id,
const SourceMapping& mapping,
const InternLookup* intern_lookup) {
std::string path;
for (SourceStringId str_id : mapping.name_ids) {
- auto opt_str =
- FindString(str_id, intern_lookup, InternedStringType::kMappingPath);
+ auto opt_str = FindOrInsertString(str_id, intern_lookup,
+ InternedStringType::kMappingPath);
if (!opt_str)
break;
path += "/" + *opt_str;
@@ -84,42 +84,40 @@
tables::StackProfileMappingTable* mappings =
context_->storage->mutable_stack_profile_mapping_table();
- int64_t cur_row = -1;
+ base::Optional<MappingId> cur_id;
auto it = mapping_idx_.find(row);
if (it != mapping_idx_.end()) {
- cur_row = it->second;
+ cur_id = it->second;
} else {
- std::vector<int64_t> db_mappings =
+ std::vector<MappingId> db_mappings =
context_->storage->FindMappingRow(row.name, row.build_id);
- for (const int64_t preexisting_mapping : db_mappings) {
- PERFETTO_DCHECK(preexisting_mapping >= 0);
- uint32_t preexisting_row_id = static_cast<uint32_t>(preexisting_mapping);
- tables::StackProfileMappingTable::Row preexisting_row{
- mappings->build_id()[preexisting_row_id],
- mappings->exact_offset()[preexisting_row_id],
- mappings->start_offset()[preexisting_row_id],
- mappings->start()[preexisting_row_id],
- mappings->end()[preexisting_row_id],
- mappings->load_bias()[preexisting_row_id],
- mappings->name()[preexisting_row_id]};
+ for (const MappingId preexisting_mapping : db_mappings) {
+ uint32_t preexisting_row = *mappings->id().IndexOf(preexisting_mapping);
+ tables::StackProfileMappingTable::Row preexisting_data{
+ mappings->build_id()[preexisting_row],
+ mappings->exact_offset()[preexisting_row],
+ mappings->start_offset()[preexisting_row],
+ mappings->start()[preexisting_row],
+ mappings->end()[preexisting_row],
+ mappings->load_bias()[preexisting_row],
+ mappings->name()[preexisting_row]};
- if (row == preexisting_row) {
- cur_row = preexisting_mapping;
+ if (row == preexisting_data) {
+ cur_id = preexisting_mapping;
}
}
- if (cur_row == -1) {
+ if (!cur_id) {
MappingId mapping_id = mappings->Insert(row);
- uint32_t mapping_row = *mappings->id().IndexOf(mapping_id);
- context_->storage->InsertMappingRow(row.name, row.build_id, mapping_row);
- cur_row = mapping_row;
+ context_->storage->InsertMappingId(row.name, row.build_id, mapping_id);
+ cur_id = mapping_id;
}
- mapping_idx_.emplace(row, cur_row);
+ mapping_idx_.emplace(row, *cur_id);
}
- mappings_.emplace(id, cur_row);
- return cur_row;
+ mapping_ids_.emplace(id, *cur_id);
+ return cur_id;
}
-base::Optional<int64_t> StackProfileTracker::AddFrame(
+base::Optional<FrameId> StackProfileTracker::AddFrame(
SourceFrameId id,
const SourceFrame& frame,
const InternLookup* intern_lookup) {
@@ -132,93 +130,92 @@
}
const StringId& str_id = opt_str_id.value();
- auto maybe_mapping = FindMapping(frame.mapping_id, intern_lookup);
+ auto maybe_mapping = FindOrInsertMapping(frame.mapping_id, intern_lookup);
if (!maybe_mapping) {
context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
PERFETTO_ELOG("Invalid mapping for frame %" PRIu64, id);
return base::nullopt;
}
- int64_t mapping_row = *maybe_mapping;
+ MappingId mapping_id = *maybe_mapping;
- tables::StackProfileFrameTable::Row row{str_id, mapping_row,
+ tables::StackProfileFrameTable::Row row{str_id, mapping_id.value,
static_cast<int64_t>(frame.rel_pc)};
auto* frames = context_->storage->mutable_stack_profile_frame_table();
- int64_t cur_row = -1;
+ base::Optional<FrameId> cur_id;
auto it = frame_idx_.find(row);
if (it != frame_idx_.end()) {
- cur_row = it->second;
+ cur_id = it->second;
} else {
- std::vector<int64_t> db_frames = context_->storage->FindFrameRow(
- static_cast<size_t>(mapping_row), frame.rel_pc);
- for (const int64_t preexisting_frame : db_frames) {
- PERFETTO_DCHECK(preexisting_frame >= 0);
- uint32_t preexisting_row_id = static_cast<uint32_t>(preexisting_frame);
+ std::vector<FrameId> db_frames =
+ context_->storage->FindFrameIds(mapping_id, frame.rel_pc);
+ for (const FrameId preexisting_frame : db_frames) {
+ uint32_t preexisting_row_id = preexisting_frame.value;
tables::StackProfileFrameTable::Row preexisting_row{
frames->name()[preexisting_row_id],
frames->mapping()[preexisting_row_id],
frames->rel_pc()[preexisting_row_id]};
if (row == preexisting_row) {
- cur_row = preexisting_frame;
+ cur_id = preexisting_frame;
}
}
- if (cur_row == -1) {
- auto new_id = frames->Insert(row);
- cur_row = *frames->id().IndexOf(new_id);
- context_->storage->InsertFrameRow(static_cast<size_t>(row.mapping),
- static_cast<uint64_t>(row.rel_pc),
- static_cast<uint32_t>(cur_row));
+ if (!cur_id) {
+ cur_id = frames->Insert(row);
+ context_->storage->InsertFrameRow(
+ mapping_id, static_cast<uint64_t>(row.rel_pc), *cur_id);
}
- frame_idx_.emplace(row, cur_row);
+ frame_idx_.emplace(row, *cur_id);
}
- frames_.emplace(id, cur_row);
- return cur_row;
+ frame_ids_.emplace(id, *cur_id);
+ return cur_id;
}
-base::Optional<int64_t> StackProfileTracker::AddCallstack(
+base::Optional<CallsiteId> StackProfileTracker::AddCallstack(
SourceCallstackId id,
const SourceCallstack& frame_ids,
const InternLookup* intern_lookup) {
// TODO(fmayer): This should be NULL.
- int64_t parent_id = -1;
+ base::Optional<CallsiteId> parent_id;
for (size_t depth = 0; depth < frame_ids.size(); ++depth) {
- SourceFrameId frame_id = frame_ids[depth];
- auto maybe_frame_row = FindFrame(frame_id, intern_lookup);
- if (!maybe_frame_row) {
+ auto maybe_frame_id = FindOrInsertFrame(frame_ids[depth], intern_lookup);
+ if (!maybe_frame_id) {
context_->storage->IncrementStats(stats::stackprofile_invalid_frame_id);
PERFETTO_ELOG("Unknown frame in callstack; ignoring.");
return base::nullopt;
}
- int64_t frame_row = *maybe_frame_row;
+ FrameId frame_id = *maybe_frame_id;
+ // TODO(fmayer): Store roots as having null parent_id instead of -1.
+ int64_t db_parent_id = -1;
+ if (parent_id)
+ db_parent_id = parent_id->value;
tables::StackProfileCallsiteTable::Row row{static_cast<int64_t>(depth),
- parent_id, frame_row};
+ db_parent_id, frame_id.value};
- int64_t self_id;
+ CallsiteId self_id;
auto callsite_it = callsite_idx_.find(row);
if (callsite_it != callsite_idx_.end()) {
self_id = callsite_it->second;
} else {
auto* callsite =
context_->storage->mutable_stack_profile_callsite_table();
- auto callsite_id = callsite->Insert(row);
- self_id = callsite_id.value;
+ self_id = callsite->Insert(row);
callsite_idx_.emplace(row, self_id);
}
parent_id = self_id;
}
- callstacks_.emplace(id, parent_id);
+ callstack_ids_.emplace(id, *parent_id);
return parent_id;
}
-int64_t StackProfileTracker::GetDatabaseFrameIdForTesting(
+FrameId StackProfileTracker::GetDatabaseFrameIdForTesting(
SourceFrameId frame_id) {
- auto it = frames_.find(frame_id);
- if (it == frames_.end()) {
+ auto it = frame_ids_.find(frame_id);
+ if (it == frame_ids_.end()) {
PERFETTO_DLOG("Invalid frame.");
- return -1;
+ return {};
}
return it->second;
}
@@ -230,14 +227,14 @@
if (id == 0)
return GetEmptyStringId();
- auto opt_str = FindString(id, intern_lookup, type);
+ auto opt_str = FindOrInsertString(id, intern_lookup, type);
if (!opt_str)
return GetEmptyStringId();
return context_->storage->InternString(base::StringView(*opt_str));
}
-base::Optional<std::string> StackProfileTracker::FindString(
+base::Optional<std::string> StackProfileTracker::FindOrInsertString(
SourceStringId id,
const InternLookup* intern_lookup,
StackProfileTracker::InternedStringType type) {
@@ -262,12 +259,12 @@
return it->second;
}
-base::Optional<int64_t> StackProfileTracker::FindMapping(
+base::Optional<MappingId> StackProfileTracker::FindOrInsertMapping(
SourceMappingId mapping_id,
const InternLookup* intern_lookup) {
- base::Optional<int64_t> res;
- auto it = mappings_.find(mapping_id);
- if (it == mappings_.end()) {
+ base::Optional<MappingId> res;
+ auto it = mapping_ids_.find(mapping_id);
+ if (it == mapping_ids_.end()) {
if (intern_lookup) {
auto interned_mapping = intern_lookup->GetMapping(mapping_id);
if (interned_mapping) {
@@ -277,19 +274,19 @@
}
context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
PERFETTO_ELOG("Unknown mapping %" PRIu64 " : %zu", mapping_id,
- mappings_.size());
+ mapping_ids_.size());
return res;
}
res = it->second;
return res;
}
-base::Optional<int64_t> StackProfileTracker::FindFrame(
+base::Optional<FrameId> StackProfileTracker::FindOrInsertFrame(
SourceFrameId frame_id,
const InternLookup* intern_lookup) {
- base::Optional<int64_t> res;
- auto it = frames_.find(frame_id);
- if (it == frames_.end()) {
+ base::Optional<FrameId> res;
+ auto it = frame_ids_.find(frame_id);
+ if (it == frame_ids_.end()) {
if (intern_lookup) {
auto interned_frame = intern_lookup->GetFrame(frame_id);
if (interned_frame) {
@@ -298,19 +295,20 @@
}
}
context_->storage->IncrementStats(stats::stackprofile_invalid_frame_id);
- PERFETTO_DLOG("Unknown frame %" PRIu64 " : %zu", frame_id, frames_.size());
+ PERFETTO_DLOG("Unknown frame %" PRIu64 " : %zu", frame_id,
+ frame_ids_.size());
return res;
}
res = it->second;
return res;
}
-base::Optional<int64_t> StackProfileTracker::FindCallstack(
+base::Optional<CallsiteId> StackProfileTracker::FindOrInsertCallstack(
SourceCallstackId callstack_id,
const InternLookup* intern_lookup) {
- base::Optional<int64_t> res;
- auto it = callstacks_.find(callstack_id);
- if (it == callstacks_.end()) {
+ base::Optional<CallsiteId> res;
+ auto it = callstack_ids_.find(callstack_id);
+ if (it == callstack_ids_.end()) {
auto interned_callstack = intern_lookup->GetCallstack(callstack_id);
if (interned_callstack) {
res = AddCallstack(callstack_id, *interned_callstack, intern_lookup);
@@ -318,7 +316,7 @@
}
context_->storage->IncrementStats(stats::stackprofile_invalid_callstack_id);
PERFETTO_DLOG("Unknown callstack %" PRIu64 " : %zu", callstack_id,
- callstacks_.size());
+ callstack_ids_.size());
return res;
}
res = it->second;
@@ -327,9 +325,9 @@
void StackProfileTracker::ClearIndices() {
string_map_.clear();
- mappings_.clear();
- callstacks_.clear();
- frames_.clear();
+ mapping_ids_.clear();
+ callstack_ids_.clear();
+ frame_ids_.clear();
}
} // namespace trace_processor
diff --git a/src/trace_processor/stack_profile_tracker.h b/src/trace_processor/stack_profile_tracker.h
index 7862809..575715c 100644
--- a/src/trace_processor/stack_profile_tracker.h
+++ b/src/trace_processor/stack_profile_tracker.h
@@ -39,6 +39,41 @@
};
template <>
+struct hash<std::pair<uint32_t, perfetto::trace_processor::CallsiteId>> {
+ using argument_type =
+ std::pair<uint32_t, perfetto::trace_processor::CallsiteId>;
+ using result_type = size_t;
+
+ result_type operator()(const argument_type& p) const {
+ return std::hash<uint32_t>{}(p.first) ^
+ std::hash<uint32_t>{}(p.second.value);
+ }
+};
+
+template <>
+struct hash<std::pair<uint32_t, perfetto::trace_processor::MappingId>> {
+ using argument_type =
+ std::pair<uint32_t, perfetto::trace_processor::MappingId>;
+ using result_type = size_t;
+
+ result_type operator()(const argument_type& p) const {
+ return std::hash<uint32_t>{}(p.first) ^
+ std::hash<uint32_t>{}(p.second.value);
+ }
+};
+
+template <>
+struct hash<std::pair<uint32_t, perfetto::trace_processor::FrameId>> {
+ using argument_type = std::pair<uint32_t, perfetto::trace_processor::FrameId>;
+ using result_type = size_t;
+
+ result_type operator()(const argument_type& p) const {
+ return std::hash<uint32_t>{}(p.first) ^
+ std::hash<uint32_t>{}(p.second.value);
+ }
+};
+
+template <>
struct hash<std::vector<uint64_t>> {
using argument_type = std::vector<uint64_t>;
using result_type = size_t;
@@ -119,19 +154,19 @@
~StackProfileTracker();
void AddString(SourceStringId, base::StringView);
- base::Optional<int64_t> AddMapping(
+ base::Optional<MappingId> AddMapping(
SourceMappingId,
const SourceMapping&,
const InternLookup* intern_lookup = nullptr);
- base::Optional<int64_t> AddFrame(SourceFrameId,
+ base::Optional<FrameId> AddFrame(SourceFrameId,
const SourceFrame&,
const InternLookup* intern_lookup = nullptr);
- base::Optional<int64_t> AddCallstack(
+ base::Optional<CallsiteId> AddCallstack(
SourceCallstackId,
const SourceCallstack&,
const InternLookup* intern_lookup = nullptr);
- int64_t GetDatabaseFrameIdForTesting(SourceFrameId);
+ FrameId GetDatabaseFrameIdForTesting(SourceFrameId);
// Gets the row number of string / mapping / frame / callstack previously
// added through AddString / AddMapping/ AddFrame / AddCallstack.
@@ -147,15 +182,18 @@
SourceStringId,
const InternLookup* intern_lookup,
InternedStringType type);
- base::Optional<std::string> FindString(SourceStringId,
- const InternLookup* intern_lookup,
- InternedStringType type);
- base::Optional<int64_t> FindMapping(SourceMappingId,
- const InternLookup* intern_lookup);
- base::Optional<int64_t> FindFrame(SourceFrameId,
- const InternLookup* intern_lookup);
- base::Optional<int64_t> FindCallstack(SourceCallstackId,
- const InternLookup* intern_lookup);
+ base::Optional<std::string> FindOrInsertString(
+ SourceStringId,
+ const InternLookup* intern_lookup,
+ InternedStringType type);
+ base::Optional<MappingId> FindOrInsertMapping(
+ SourceMappingId,
+ const InternLookup* intern_lookup);
+ base::Optional<FrameId> FindOrInsertFrame(SourceFrameId,
+ const InternLookup* intern_lookup);
+ base::Optional<CallsiteId> FindOrInsertCallstack(
+ SourceCallstackId,
+ const InternLookup* intern_lookup);
// Clear indices when they're no longer needed.
void ClearIndices();
@@ -164,16 +202,21 @@
StringId GetEmptyStringId();
std::unordered_map<SourceStringId, std::string> string_map_;
- std::unordered_map<SourceMappingId, int64_t> mappings_;
- std::unordered_map<SourceFrameId, int64_t> frames_;
- std::unordered_map<SourceCallstackId, int64_t> callstacks_;
+
+ // Mapping from ID of mapping / frame / callstack in original trace and the
+ // index in the respective table it was inserted into.
+ std::unordered_map<SourceMappingId, MappingId> mapping_ids_;
+ std::unordered_map<SourceFrameId, FrameId> frame_ids_;
+ std::unordered_map<SourceCallstackId, CallsiteId> callstack_ids_;
// TODO(oysteine): Share these indices between the StackProfileTrackers,
// since they're not sequence-specific.
- std::unordered_map<tables::StackProfileMappingTable::Row, int64_t>
+ //
+ // Mapping from content of database row to the index of the raw.
+ std::unordered_map<tables::StackProfileMappingTable::Row, MappingId>
mapping_idx_;
- std::unordered_map<tables::StackProfileFrameTable::Row, int64_t> frame_idx_;
- std::unordered_map<tables::StackProfileCallsiteTable::Row, int64_t>
+ std::unordered_map<tables::StackProfileFrameTable::Row, FrameId> frame_idx_;
+ std::unordered_map<tables::StackProfileCallsiteTable::Row, CallsiteId>
callsite_idx_;
TraceProcessorContext* const context_;
diff --git a/src/trace_processor/tables/macros_internal.h b/src/trace_processor/tables/macros_internal.h
index 71895b2..2a4f47f 100644
--- a/src/trace_processor/tables/macros_internal.h
+++ b/src/trace_processor/tables/macros_internal.h
@@ -264,6 +264,7 @@
explicit constexpr DefinedId(uint32_t v) : value(v) {} \
\
bool operator==(const DefinedId& o) const { return o.value == value; } \
+ bool operator<(const DefinedId& o) const { return value < o.value; } \
\
uint32_t value; \
}; \
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 2970d97..db6ac60 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -73,6 +73,10 @@
using MappingId = tables::StackProfileMappingTable::Id;
+using FrameId = tables::StackProfileFrameTable::Id;
+
+using CallsiteId = tables::StackProfileCallsiteTable::Id;
+
using MetadataId = tables::MetadataTable::Id;
using RawId = tables::RawTable::Id;
@@ -612,7 +616,8 @@
std::pair<int64_t, int64_t> GetTraceTimestampBoundsNs() const;
// TODO(lalitm): remove this when we have a better home.
- std::vector<int64_t> FindMappingRow(StringId name, StringId build_id) const {
+ std::vector<MappingId> FindMappingRow(StringId name,
+ StringId build_id) const {
auto it = stack_profile_mapping_index_.find(std::make_pair(name, build_id));
if (it == stack_profile_mapping_index_.end())
return {};
@@ -620,13 +625,14 @@
}
// TODO(lalitm): remove this when we have a better home.
- void InsertMappingRow(StringId name, StringId build_id, uint32_t row) {
+ void InsertMappingId(StringId name, StringId build_id, MappingId row) {
auto pair = std::make_pair(name, build_id);
stack_profile_mapping_index_[pair].emplace_back(row);
}
// TODO(lalitm): remove this when we have a better home.
- std::vector<int64_t> FindFrameRow(size_t mapping_row, uint64_t rel_pc) const {
+ std::vector<FrameId> FindFrameIds(MappingId mapping_row,
+ uint64_t rel_pc) const {
auto it =
stack_profile_frame_index_.find(std::make_pair(mapping_row, rel_pc));
if (it == stack_profile_frame_index_.end())
@@ -635,7 +641,7 @@
}
// TODO(lalitm): remove this when we have a better home.
- void InsertFrameRow(size_t mapping_row, uint64_t rel_pc, uint32_t row) {
+ void InsertFrameRow(MappingId mapping_row, uint64_t rel_pc, FrameId row) {
auto pair = std::make_pair(mapping_row, rel_pc);
stack_profile_frame_index_[pair].emplace_back(row);
}
@@ -698,11 +704,11 @@
// TODO(lalitm): remove this when we find a better home for this.
using MappingKey = std::pair<StringId /* name */, StringId /* build id */>;
- std::map<MappingKey, std::vector<int64_t>> stack_profile_mapping_index_;
+ std::map<MappingKey, std::vector<MappingId>> stack_profile_mapping_index_;
// TODO(lalitm): remove this when we find a better home for this.
- using FrameKey = std::pair<size_t /* mapping row */, uint64_t /* rel_pc */>;
- std::map<FrameKey, std::vector<int64_t>> stack_profile_frame_index_;
+ using FrameKey = std::pair<MappingId, uint64_t /* rel_pc */>;
+ std::map<FrameKey, std::vector<FrameId>> stack_profile_frame_index_;
// One entry for each unique string in the trace.
StringPool string_pool_;
diff --git a/src/tracing/event_context.cc b/src/tracing/event_context.cc
index 2126e2c..a4f1ade 100644
--- a/src/tracing/event_context.cc
+++ b/src/tracing/event_context.cc
@@ -29,6 +29,9 @@
incremental_state_(incremental_state) {}
EventContext::~EventContext() {
+ if (!trace_packet_)
+ return;
+
// When the track event is finalized (i.e., the context is destroyed), we
// should flush any newly seen interned data to the trace. The data has
// earlier been written to a heap allocated protobuf message
diff --git a/ui/src/frontend/help_modal.ts b/ui/src/frontend/help_modal.ts
index 39ff0e4..1227d47 100644
--- a/ui/src/frontend/help_modal.ts
+++ b/ui/src/frontend/help_modal.ts
@@ -35,41 +35,39 @@
helpModelOpen = true;
showModal({
title: 'Perfetto Help',
- content:
- m('.help',
- m('h2', 'Navigation'),
- m(
- 'table',
- m(
- 'tr',
- m('td', keycap('w'), '/', keycap('s')),
- m('td', 'Zoom in/out'),
- ),
- m(
- 'tr',
- m('td', keycap('a'), '/', keycap('d')),
- m('td', 'Pan left/right'),
- ),
- ),
- m('h2', 'Mouse Controls'),
- m('table',
- m('tr', m('td', 'Click'), m('td', 'Select event')),
- m('tr', m('td', 'Ctrl + Scroll wheel'), m('td', 'Zoom in/out')),
- m('tr', m('td', 'Click + Drag'), m('td', 'Pan left/right')),
+ content: m(
+ '.help',
+ m('h2', 'Navigation'),
+ m(
+ 'table',
+ m(
+ 'tr',
+ m('td', keycap('w'), '/', keycap('s')),
+ m('td', 'Zoom in/out'),
+ ),
+ m(
+ 'tr',
+ m('td', keycap('a'), '/', keycap('d')),
+ m('td', 'Pan left/right'),
+ ),
+ ),
+ m('h2', 'Mouse Controls'),
+ m('table',
+ m('tr', m('td', 'Click'), m('td', 'Select event')),
+ m('tr', m('td', 'Ctrl + Scroll wheel'), m('td', 'Zoom in/out')),
+ m('tr', m('td', 'Click + Drag'), m('td', 'Select area')),
+ m('tr', m('td', 'Shift + Click + Drag'), m('td', 'Pan left/right'))),
+ m('h2', 'Other'),
+ m(
+ 'table',
m('tr',
- m('td', 'Shift + Click + Drag'),
- m('td', 'Select a time span'))),
- m('h2', 'Other'),
- m(
- 'table',
- m('tr',
- m('td', keycap('f'), ' (with event selected)'),
- m('td', 'Scroll + zoom to current selection')),
- m('tr',
- m('td', keycap('m'), ' (with event selected)'),
- m('td', 'Select time span of event')),
- m('tr', m('td', keycap('?')), m('td', 'Show help')),
- )),
+ m('td', keycap('f'), ' (with event selected)'),
+ m('td', 'Scroll + zoom to current selection')),
+ m('tr',
+ m('td', keycap('m'), ' (with event selected)'),
+ m('td', 'Select time span of event')),
+ m('tr', m('td', keycap('?')), m('td', 'Show help')),
+ )),
buttons: [],
}).finally(() => {
helpModelOpen = false;
diff --git a/ui/src/frontend/pan_and_zoom_handler.ts b/ui/src/frontend/pan_and_zoom_handler.ts
index 9d2bda1..1f504b4 100644
--- a/ui/src/frontend/pan_and_zoom_handler.ts
+++ b/ui/src/frontend/pan_and_zoom_handler.ts
@@ -44,8 +44,8 @@
const WHEEL_ZOOM_SPEED = -0.02;
const EDITING_RANGE_CURSOR = 'ew-resize';
-const SHIFT_CURSOR = 'text';
-const DEFAULT_CURSOR = 'default';
+const DRAG_CURSOR = 'text';
+const PAN_CURSOR = 'move';
enum Pan {
None = 0,
@@ -94,28 +94,29 @@
private contentOffsetX: number;
private onPanned: (movedPx: number) => void;
private onZoomed: (zoomPositionPx: number, zoomRatio: number) => void;
- private shouldDrag: (currentPx: number) => boolean;
- private onDrag:
+ private editSelection: (currentPx: number) => boolean;
+ private onSelection:
(dragStartX: number, dragStartY: number, prevX: number, currentX: number,
currentY: number, editing: boolean) => void;
constructor(
- {element, contentOffsetX, onPanned, onZoomed, shouldDrag, onDrag}: {
- element: HTMLElement,
- contentOffsetX: number,
- onPanned: (movedPx: number) => void,
- onZoomed: (zoomPositionPx: number, zoomRatio: number) => void,
- shouldDrag: (currentPx: number) => boolean,
- onDrag:
- (dragStartX: number, dragStartY: number, prevX: number,
- currentX: number, currentY: number, editing: boolean) => void,
- }) {
+ {element, contentOffsetX, onPanned, onZoomed, editSelection, onSelection}:
+ {
+ element: HTMLElement,
+ contentOffsetX: number,
+ onPanned: (movedPx: number) => void,
+ onZoomed: (zoomPositionPx: number, zoomRatio: number) => void,
+ editSelection: (currentPx: number) => boolean,
+ onSelection:
+ (dragStartX: number, dragStartY: number, prevX: number,
+ currentX: number, currentY: number, editing: boolean) => void,
+ }) {
this.element = element;
this.contentOffsetX = contentOffsetX;
this.onPanned = onPanned;
this.onZoomed = onZoomed;
- this.shouldDrag = shouldDrag;
- this.onDrag = onDrag;
+ this.editSelection = editSelection;
+ this.onSelection = onSelection;
document.body.addEventListener('keydown', this.boundOnKeyDown);
document.body.addEventListener('keyup', this.boundOnKeyUp);
@@ -125,16 +126,14 @@
let prevX = -1;
let dragStartX = -1;
let dragStartY = -1;
- let drag = false;
+ let edit = false;
new DragGestureHandler(
this.element,
(x, y) => {
- // If we started our drag on a time range boundary or shift is down
- // then we are drag selecting rather than panning.
- if (drag || this.shiftDown) {
- this.onDrag(dragStartX, dragStartY, prevX, x, y, !this.shiftDown);
- } else {
+ if (this.shiftDown) {
this.onPanned(prevX - x);
+ } else {
+ this.onSelection(dragStartX, dragStartY, prevX, x, y, edit);
}
prevX = x;
},
@@ -142,19 +141,18 @@
prevX = x;
dragStartX = x;
dragStartY = y;
- drag = this.shouldDrag(x);
+ edit = this.editSelection(x);
// Set the cursor style based on where the cursor is when the drag
// starts.
- if (drag) {
+ if (edit) {
this.element.style.cursor = EDITING_RANGE_CURSOR;
- } else if (this.shiftDown) {
- this.element.style.cursor = SHIFT_CURSOR;
+ } else if (!this.shiftDown) {
+ this.element.style.cursor = DRAG_CURSOR;
}
},
() => {
// Reset the cursor now the drag has ended.
- this.element.style.cursor =
- this.shiftDown ? SHIFT_CURSOR : DEFAULT_CURSOR;
+ this.element.style.cursor = this.shiftDown ? PAN_CURSOR : DRAG_CURSOR;
dragStartX = -1;
dragStartY = -1;
});
@@ -213,14 +211,13 @@
// the cursor flickering between styles if you drag fast and get too
// far from the current time range.
if (e.buttons === 0) {
- if (!this.shouldDrag(this.mousePositionX)) {
- this.element.style.cursor =
- this.shiftDown ? SHIFT_CURSOR : DEFAULT_CURSOR;
- } else {
+ if (this.editSelection(this.mousePositionX)) {
this.element.style.cursor = EDITING_RANGE_CURSOR;
+ } else {
+ this.element.style.cursor = this.shiftDown ? PAN_CURSOR : DRAG_CURSOR;
}
}
- if (this.shiftDown) {
+ if (!this.shiftDown) {
const pos = this.mousePositionX - TRACK_SHELL_WIDTH;
const ts = globals.frontendLocalState.timeScale.pxToTime(pos);
globals.frontendLocalState.setHoveredTimestamp(ts);
@@ -283,17 +280,15 @@
if (down === this.shiftDown) return;
this.shiftDown = down;
if (this.shiftDown) {
+ globals.frontendLocalState.setHoveredTimestamp(-1);
+ this.element.style.cursor = PAN_CURSOR;
+ } else {
if (this.mousePositionX) {
- this.element.style.cursor = SHIFT_CURSOR;
+ this.element.style.cursor = DRAG_CURSOR;
const pos = this.mousePositionX - TRACK_SHELL_WIDTH;
const ts = globals.frontendLocalState.timeScale.pxToTime(pos);
globals.frontendLocalState.setHoveredTimestamp(ts);
}
- } else {
- globals.frontendLocalState.setHoveredTimestamp(-1);
- this.element.style.cursor = DEFAULT_CURSOR;
}
-
- globals.frontendLocalState.setShowTimeSelectPreview(this.shiftDown);
}
}
diff --git a/ui/src/frontend/panel_container.ts b/ui/src/frontend/panel_container.ts
index 9d2eaa5..3c2e31f 100644
--- a/ui/src/frontend/panel_container.ts
+++ b/ui/src/frontend/panel_container.ts
@@ -234,6 +234,16 @@
const ctx = assertExists(this.ctx);
const canvas = assertExists(ctx.canvas);
canvas.style.height = `${this.canvasHeight}px`;
+
+ // If're we're non-scrolling canvas and the scroll-limiter should always
+ // have the same height. Enforce this by explicitly setting the height.
+ if (!this.attrs.doesScroll) {
+ const scrollLimiter = canvas.parentElement;
+ if (scrollLimiter) {
+ scrollLimiter.style.height = `${this.canvasHeight}px`;
+ }
+ }
+
const dpr = window.devicePixelRatio;
// On non-MacOS if there is a solid scroll bar it can cover important
// pixels, reduce the size of the canvas so it doesn't overlap with
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index 49e6d22..6dc5475 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -179,10 +179,10 @@
frontendLocalState.updateVisibleTime(newSpan);
globals.rafScheduler.scheduleRedraw();
},
- shouldDrag: (currentPx: number) => {
+ editSelection: (currentPx: number) => {
return onTimeRangeBoundary(currentPx) !== null;
},
- onDrag: (
+ onSelection: (
dragStartX: number,
dragStartY: number,
prevX: number,