Merge "UI: Add trace title to sidebar and tab title"
diff --git a/Android.bp b/Android.bp
index 2112df5..5230e56 100644
--- a/Android.bp
+++ b/Android.bp
@@ -613,6 +613,11 @@
"-DGOOGLE_PROTOBUF_NO_RTTI",
"-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.art.debug",
+ "com.android.art.release",
+ ],
}
// GN: //src/perfetto_cmd:perfetto
@@ -7502,6 +7507,11 @@
"-DGOOGLE_PROTOBUF_NO_RTTI",
"-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.art.debug",
+ "com.android.art.release",
+ ],
}
// GN: //:perfetto_unittests
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 7d76854..317209b 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
@@ -795,10 +795,9 @@
constexpr TrackId thread_time_track{1u};
InSequence in_sequence; // Below slices should be sorted by timestamp.
+ // Only the begin thread time can be imported into the counter table.
EXPECT_CALL(*event_, PushCounter(1005000, testing::DoubleEq(2003000),
thread_time_track));
- EXPECT_CALL(*event_, PushCounter(1028000, testing::DoubleEq(2015000),
- thread_time_track));
EXPECT_CALL(*slice_,
Scoped(1005000, track, kNullStringId, kNullStringId, 23000, _))
.WillOnce(DoAll(InvokeArgument<5>(&inserter), Return(0u)));
@@ -1038,14 +1037,11 @@
InSequence in_sequence; // Below slices should be sorted by timestamp.
MockBoundInserter inserter;
+ // Only the begin timestamp counters can be imported into the counter table.
EXPECT_CALL(*event_, PushCounter(1005000, testing::DoubleEq(2003000),
thread_time_track));
- EXPECT_CALL(*event_, PushCounter(1028000, testing::DoubleEq(2015000),
- thread_time_track));
EXPECT_CALL(*event_, PushCounter(1005000, testing::DoubleEq(3010),
thread_instruction_count_track));
- EXPECT_CALL(*event_, PushCounter(1028000, testing::DoubleEq(3060),
- thread_instruction_count_track));
EXPECT_CALL(*slice_, Scoped(1005000, thread_1_track, cat_2_3, ev_2, 23000, _))
.WillOnce(DoAll(InvokeArgument<5>(&inserter), Return(0u)));
EXPECT_CALL(inserter, AddArg(_, _, Variadic::UnsignedInteger(9999u), _));
@@ -2256,10 +2252,9 @@
Tokenize();
EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
+ // Only the begin thread time can be imported into the counter table.
EXPECT_CALL(*event_,
PushCounter(1010000, testing::DoubleEq(2005000), TrackId{1}));
- EXPECT_CALL(*event_,
- PushCounter(1033000, testing::DoubleEq(2020000), TrackId{1}));
tables::ThreadTable::Row row(16);
row.upid = 1u;
diff --git a/src/trace_processor/importers/proto/system_probes_parser.cc b/src/trace_processor/importers/proto/system_probes_parser.cc
index 29050b3..8a1c4f3 100644
--- a/src/trace_processor/importers/proto/system_probes_parser.cc
+++ b/src/trace_processor/importers/proto/system_probes_parser.cc
@@ -16,6 +16,8 @@
#include "src/trace_processor/importers/proto/system_probes_parser.h"
+#include <set>
+
#include "perfetto/base/logging.h"
#include "perfetto/ext/traced/sys_stats_counters.h"
#include "perfetto/protozero/proto_decoder.h"
@@ -302,10 +304,10 @@
protos::pbzero::ProcessStats::Thread::Decoder stats(blob.data, blob.size);
UniqueTid utid = context_->process_tracker->UpdateThread(
static_cast<uint32_t>(stats.tid()), pid);
- auto index_it = stats.cpu_freq_indices();
- auto tick_it = stats.cpu_freq_ticks();
- std::map<StringId, uint64_t> total_ticks_cpu;
- for (; index_it && tick_it; index_it++, tick_it++) {
+ TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
+
+ std::set<StringId> cpu_str_ids;
+ for (auto index_it = stats.cpu_freq_indices(); index_it; index_it++) {
auto freq_index = *index_it;
if (PERFETTO_UNLIKELY(freq_index == 0 ||
freq_index >=
@@ -314,14 +316,30 @@
stats::thread_time_in_state_unknown_cpu_freq);
continue;
}
- total_ticks_cpu[thread_time_in_state_cpu_str_ids_[freq_index]] += *tick_it;
+ cpu_str_ids.insert(thread_time_in_state_cpu_str_ids_[freq_index]);
}
- for (auto it : total_ticks_cpu) {
- TrackId track =
- context_->track_tracker->InternThreadCounterTrack(it.first, utid);
- auto ticks = it.second;
- context_->event_tracker->PushCounter(ts, ticks * ms_per_tick_, track);
+ for (StringId cpu_str_id : cpu_str_ids) {
+ context_->slice_tracker->Scoped(
+ ts, track_id, kNullStringId, cpu_str_id,
+ /* duration */ 0,
+ [&stats, &cpu_str_id, this](ArgsTracker::BoundInserter* args_table) {
+ auto index_it = stats.cpu_freq_indices();
+ auto tick_it = stats.cpu_freq_ticks();
+ for (; index_it && tick_it; index_it++, tick_it++) {
+ auto freq_index = *index_it;
+ if (PERFETTO_UNLIKELY(
+ freq_index == 0 ||
+ freq_index >= thread_time_in_state_cpu_str_ids_.size())) {
+ continue;
+ }
+ if (thread_time_in_state_cpu_str_ids_[freq_index] != cpu_str_id)
+ continue;
+ args_table->AddArg(
+ thread_time_in_state_cpu_freq_ids_[*index_it],
+ Variadic::UnsignedInteger(*tick_it * ms_per_tick_));
+ }
+ });
}
}
@@ -375,18 +393,24 @@
}
void SystemProbesParser::ParseCpuInfo(ConstBytes blob) {
+ // Frequency index 0 is invalid.
+ StringId invalid_str_id = context_->storage->InternString("invalid");
+ thread_time_in_state_cpu_str_ids_.push_back(invalid_str_id);
+ thread_time_in_state_cpu_freq_ids_.push_back(invalid_str_id);
+
protos::pbzero::CpuInfo::Decoder packet(blob.data, blob.size);
uint32_t cpu_index = 0;
- thread_time_in_state_cpu_str_ids_.push_back(
- context_->storage->InternString("invalid"));
for (auto it = packet.cpus(); it; it++) {
protos::pbzero::CpuInfo::Cpu::Decoder cpu(*it);
- std::string cpu_index_string =
- "cpu" + std::to_string(cpu_index) + ".time_in_state";
- base::StringView cpu_string(cpu_index_string);
+ std::string cpu_string = "time_in_state.cpu" + std::to_string(cpu_index);
+ base::StringView cpu_string_view(cpu_string);
for (auto freq_it = cpu.frequencies(); freq_it; freq_it++) {
thread_time_in_state_cpu_str_ids_.push_back(
- context_->storage->InternString(cpu_string));
+ context_->storage->InternString(cpu_string_view));
+ std::string freq_string = std::to_string(*freq_it);
+ base::StringView freq_string_view(freq_string);
+ thread_time_in_state_cpu_freq_ids_.push_back(
+ context_->storage->InternString(freq_string_view));
}
cpu_index++;
}
diff --git a/src/trace_processor/importers/proto/system_probes_parser.h b/src/trace_processor/importers/proto/system_probes_parser.h
index c9361db..bcaf44a 100644
--- a/src/trace_processor/importers/proto/system_probes_parser.h
+++ b/src/trace_processor/importers/proto/system_probes_parser.h
@@ -69,8 +69,11 @@
uint64_t ms_per_tick_ = 0;
- // Maps CPU frequency indices to CPU strings.
+ // Maps CPU frequency indices to CPU strings: time_in_state.cpuN.
std::vector<StringId> thread_time_in_state_cpu_str_ids_;
+
+ // Maps CPU frequency indices to frequency strings.
+ std::vector<StringId> thread_time_in_state_cpu_freq_ids_;
};
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/track_event_parser.cc b/src/trace_processor/importers/proto/track_event_parser.cc
index e432dbb..66880b9 100644
--- a/src/trace_processor/importers/proto/track_event_parser.cc
+++ b/src/trace_processor/importers/proto/track_event_parser.cc
@@ -479,34 +479,21 @@
return;
// When these fields are set, we don't expect TrackDescriptor-based counters
// for thread time or instruction count for this thread in the trace, so we
- // intern separate counter tracks based on name + utid.
+ // intern separate counter tracks based on name + utid. Note that we cannot
+ // import the counter values from the end of a complete event, because the
+ // EventTracker expects counters to be pushed in order of their timestamps.
+ // One more reason to switch to split begin/end events.
if (event_data_->thread_timestamp) {
TrackId track_id = context_->track_tracker->InternThreadCounterTrack(
parser_->counter_name_thread_time_id_, *utid_);
context_->event_tracker->PushCounter(ts_, event_data_->thread_timestamp,
track_id);
- if (legacy_event_.duration_us() &&
- legacy_event_.has_thread_duration_us()) {
- context_->event_tracker->PushCounter(
- ts_ + (legacy_event_.duration_us() * 1000),
- event_data_->thread_timestamp +
- (legacy_event_.thread_duration_us() * 1000),
- track_id);
- }
}
if (event_data_->thread_instruction_count) {
TrackId track_id = context_->track_tracker->InternThreadCounterTrack(
parser_->counter_name_thread_instruction_count_id_, *utid_);
context_->event_tracker->PushCounter(
ts_, event_data_->thread_instruction_count, track_id);
- if (legacy_event_.duration_us() &&
- legacy_event_.has_thread_instruction_delta()) {
- context_->event_tracker->PushCounter(
- ts_ + (legacy_event_.duration_us() * 1000),
- event_data_->thread_instruction_count +
- legacy_event_.thread_instruction_delta(),
- track_id);
- }
}
}
@@ -826,7 +813,7 @@
return;
// Log error but continue parsing the other args.
storage_->IncrementStats(stats::track_event_parser_errors);
- PERFETTO_DLOG("%s", status.c_message());
+ PERFETTO_DLOG("ParseTrackEventArgs error: %s", status.c_message());
};
for (auto it = event_.debug_annotations(); it; ++it) {
@@ -1401,7 +1388,7 @@
EventImporter(this, ts, event_data, std::move(blob)).Import();
if (!status.ok()) {
context_->storage->IncrementStats(stats::track_event_parser_errors);
- PERFETTO_DLOG("%s", status.c_message());
+ PERFETTO_DLOG("ParseTrackEvent error: %s", status.c_message());
}
}
diff --git a/src/trace_processor/metrics/android/android_thread_time_in_state.sql b/src/trace_processor/metrics/android/android_thread_time_in_state.sql
index 1cb65c8..69041a7 100644
--- a/src/trace_processor/metrics/android/android_thread_time_in_state.sql
+++ b/src/trace_processor/metrics/android/android_thread_time_in_state.sql
@@ -17,13 +17,17 @@
SELECT RUN_METRIC('android/cpu_info.sql');
SELECT RUN_METRIC('android/process_metadata.sql');
-CREATE VIEW android_thread_time_in_state_tracks AS
+CREATE VIEW android_thread_time_in_state_raw AS
SELECT
- id AS track_id,
utid,
- cast(REPLACE(REPLACE(name, '.time_in_state', ''), 'cpu', '') AS int) AS cpu
-FROM thread_counter_track
-WHERE name LIKE "cpu%.time_in_state";
+ CAST(SUBSTR(slices.name, 18) AS int) AS cpu,
+ key AS freq,
+ MAX(int_value) - MIN(int_value) runtime_ms
+FROM slices
+JOIN thread_track ON (slices.track_id = thread_track.id)
+JOIN args USING (arg_set_id)
+WHERE slices.name LIKE "time_in_state.%"
+GROUP by 1, 2, 3;
CREATE TABLE android_thread_time_in_state_counters AS
SELECT
@@ -40,9 +44,8 @@
END
FROM core_layout_type
) AS core_type,
- CAST((MAX(counter.value) - MIN(counter.value)) AS int) runtime_ms
-FROM counter
-JOIN android_thread_time_in_state_tracks USING (track_id)
+ SUM(runtime_ms) runtime_ms
+FROM android_thread_time_in_state_raw
GROUP BY 1, 2
HAVING runtime_ms > 0;
diff --git a/test/metrics/android_thread_time_in_state.out b/test/metrics/android_thread_time_in_state.out
index f4d7af5..61f7493 100644
--- a/test/metrics/android_thread_time_in_state.out
+++ b/test/metrics/android_thread_time_in_state.out
@@ -2,12 +2,12 @@
processes {
metrics_by_core_type {
core_type: "unknown"
- runtime_ms: 10
+ runtime_ms: 20
}
threads {
metrics_by_core_type {
core_type: "unknown"
- runtime_ms: 10
+ runtime_ms: 20
}
}
}
diff --git a/test/trace_processor/thread_time_in_state.out b/test/trace_processor/thread_time_in_state.out
index 7d88686..51aeb7a 100644
--- a/test/trace_processor/thread_time_in_state.out
+++ b/test/trace_processor/thread_time_in_state.out
@@ -1,8 +1,11 @@
-"name","tid","ts","value"
-"cpu0.time_in_state",5,2,20.000000
-"cpu0.time_in_state",5,3,30.000000
-"cpu2.time_in_state",7,3,10.000000
-"cpu2.time_in_state",11,3,10.000000
-"cpu2.time_in_state",12,3,10.000000
-"cpu2.time_in_state",11,4,20.000000
-"cpu2.time_in_state",12,4,20.000000
+"ts","tid","cpu","freq","time_ms"
+2,5,0,100,10
+2,5,0,200,10
+3,5,0,100,20
+3,5,0,200,10
+3,7,2,1000,10
+3,11,2,2000,10
+3,12,2,2000,10
+4,5,0,200,20
+4,11,2,2000,20
+4,12,2,2000,20
diff --git a/test/trace_processor/thread_time_in_state.sql b/test/trace_processor/thread_time_in_state.sql
index ac87c0f..5f2574d 100644
--- a/test/trace_processor/thread_time_in_state.sql
+++ b/test/trace_processor/thread_time_in_state.sql
@@ -1,9 +1,12 @@
SELECT
-t.name,
-tid,
-c.ts,
-c.value
-FROM counter c
-JOIN thread_counter_track t ON c.track_id = t.id
+ ts,
+ tid,
+ CAST(SUBSTR(slices.name, 18) AS int) AS cpu,
+ CAST(key AS int) AS freq,
+ int_value AS time_ms
+FROM slices
+JOIN thread_track ON (slices.track_id = thread_track.id)
JOIN thread USING (utid)
-ORDER BY c.ts;
+JOIN args USING (arg_set_id)
+WHERE slices.name LIKE "time_in_state.%"
+ORDER BY ts, tid, cpu, key;
diff --git a/test/trace_processor/thread_time_in_state.textproto b/test/trace_processor/thread_time_in_state.textproto
index 1d6c0f2..c76fe62 100644
--- a/test/trace_processor/thread_time_in_state.textproto
+++ b/test/trace_processor/thread_time_in_state.textproto
@@ -55,6 +55,15 @@
timestamp: 4
process_stats {
processes {
+ pid: 5
+ threads {
+ tid: 5
+ # cpu_freq_indices: 1 was skipped because it did not change.
+ cpu_freq_indices: 2
+ cpu_freq_ticks: 2
+ }
+ }
+ processes {
pid: 11
threads {
tid: 11
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index 5567f04..099c384 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -178,6 +178,18 @@
'trace_processor_shell': [
('stl', 'libc++_static'),
],
+ 'libperfetto_client_experimental': [
+ ('apex_available', {
+ '//apex_available:platform',
+ 'com.android.art.debug',
+ 'com.android.art.release'}),
+ ],
+ 'perfetto_trace_protos': [
+ ('apex_available', {
+ '//apex_available:platform',
+ 'com.android.art.debug',
+ 'com.android.art.release'}),
+ ],
}
@@ -367,6 +379,7 @@
self.dist = dict()
self.strip = dict()
self.data = set()
+ self.apex_available = set()
# The genrule_XXX below are properties that must to be propagated back
# on the module(s) that depend on the genrule.
self.genrule_headers = set()
@@ -400,6 +413,7 @@
self._output_field(output, 'tool_files')
self._output_field(output, 'data')
self._output_field(output, 'stl')
+ self._output_field(output, 'apex_available')
target_out = []
self._output_field(target_out, 'android')