trace_processor: Parse systrace counter events
Parsing systrace counter events, made tracker code generic
and added value delta.
Change-Id: I81bfce42ad3bba1f893d38cec4dc46aa0c5800ae
diff --git a/src/trace_processor/counters_table.cc b/src/trace_processor/counters_table.cc
index eec57f9..4f2173f 100644
--- a/src/trace_processor/counters_table.cc
+++ b/src/trace_processor/counters_table.cc
@@ -42,8 +42,9 @@
"name text, "
"value UNSIGNED BIG INT, "
"dur UNSIGNED BIG INT, "
+ "value_delta UNSIGNED BIG INT, "
"ref UNSIGNED INT, "
- "reftype TEXT, "
+ "ref_type TEXT, "
"PRIMARY KEY(name, ts, ref)"
") WITHOUT ROWID;";
}
@@ -107,6 +108,12 @@
static_cast<int64_t>(storage_->counters().durations()[row_]));
break;
}
+ case Column::kValueDelta: {
+ sqlite3_result_int64(
+ context,
+ static_cast<int64_t>(storage_->counters().value_deltas()[row_]));
+ break;
+ }
default:
PERFETTO_FATAL("Unknown column %d", N);
break;
diff --git a/src/trace_processor/counters_table.h b/src/trace_processor/counters_table.h
index 9e257e3..5ef21ba 100644
--- a/src/trace_processor/counters_table.h
+++ b/src/trace_processor/counters_table.h
@@ -33,8 +33,9 @@
kName = 1,
kValue = 2,
kDuration = 3,
- kRef = 4,
- kRefType = 5,
+ kValueDelta = 4,
+ kRef = 5,
+ kRefType = 6,
};
static void RegisterTable(sqlite3* db, const TraceStorage* storage);
diff --git a/src/trace_processor/counters_table_unittest.cc b/src/trace_processor/counters_table_unittest.cc
index 0ff7cde..211cb78 100644
--- a/src/trace_processor/counters_table_unittest.cc
+++ b/src/trace_processor/counters_table_unittest.cc
@@ -63,11 +63,11 @@
uint64_t timestamp = 1000;
uint32_t freq = 3000;
context_.storage->mutable_counters()->AddCounter(
- timestamp, 0, 1, freq, 1 /* cpu */, RefType::kCPU_ID);
+ timestamp, 0, 1, freq, 0, 1 /* cpu */, RefType::kCPU_ID);
context_.storage->mutable_counters()->AddCounter(
- timestamp + 1, 1, 1, freq + 1000, 1 /* cpu */, RefType::kCPU_ID);
+ timestamp + 1, 1, 1, freq + 1000, 1000, 1 /* cpu */, RefType::kCPU_ID);
context_.storage->mutable_counters()->AddCounter(
- timestamp + 2, 1, 1, freq + 2000, 2 /* cpu */, RefType::kCPU_ID);
+ timestamp + 2, 1, 1, freq + 2000, 1000, 2 /* cpu */, RefType::kCPU_ID);
PrepareValidStatement("SELECT ts, dur, value FROM counters where ref = 1");
@@ -87,12 +87,16 @@
TEST_F(CountersTableUnittest, GroupByFreq) {
uint64_t timestamp = 1000;
uint32_t freq = 3000;
+ uint32_t name_id = 1;
context_.storage->mutable_counters()->AddCounter(
- timestamp, 1, 1, freq, 1 /* cpu */, RefType::kCPU_ID);
+ timestamp, 1 /* dur */, name_id, freq, 0 /* value delta */, 1 /* cpu */,
+ RefType::kCPU_ID);
context_.storage->mutable_counters()->AddCounter(
- timestamp + 1, 2, 1, freq + 1000, 1 /* cpu */, RefType::kCPU_ID);
+ timestamp + 1, 2 /* dur */, name_id, freq + 1000, 1000 /* value delta */,
+ 1 /* cpu */, RefType::kCPU_ID);
context_.storage->mutable_counters()->AddCounter(
- timestamp + 3, 0, 1, freq, 1 /* cpu */, RefType::kCPU_ID);
+ timestamp + 3, 0 /* dur */, name_id, freq, -1000 /* value delta */,
+ 1 /* cpu */, RefType::kCPU_ID);
PrepareValidStatement(
"SELECT value, sum(dur) as dur_sum FROM counters where value > 0 group "
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index 78ee7ad..8593a26 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -71,10 +71,25 @@
out->name = base::StringView(s + name_index, len - name_index);
return true;
}
- case 'E':
+ case 'E': {
return true;
- case 'C':
+ }
+ case 'C': {
+ size_t name_index = 2 + pid_length + 1;
+ size_t name_length = 0;
+ for (size_t i = name_index; i < len; i++) {
+ if (s[i] == '|' || s[i] == '\n') {
+ name_length = i - name_index;
+ break;
+ }
+ }
+ out->name = base::StringView(s + name_index, name_length);
+ size_t value_index = name_index + name_length + 1;
+ char value_str[32];
+ std::strcpy(value_str, s + value_index);
+ out->value = std::stod(value_str);
return true;
+ }
default:
return false;
}
@@ -285,6 +300,12 @@
context_->slice_tracker->End(timestamp, upid);
break;
}
+
+ case 'C': {
+ StringId name_id = context_->storage->InternString(point.name);
+ context_->sched_tracker->PushCounter(timestamp, point.value, name_id,
+ upid, RefType::kUPID);
+ }
}
PERFETTO_DCHECK(decoder.IsEndOfBuffer());
}
diff --git a/src/trace_processor/proto_trace_parser.h b/src/trace_processor/proto_trace_parser.h
index bccf534..2586e5c 100644
--- a/src/trace_processor/proto_trace_parser.h
+++ b/src/trace_processor/proto_trace_parser.h
@@ -37,7 +37,7 @@
base::StringView name;
// For phase = 'C' only.
- int64_t value;
+ double value;
};
inline bool operator==(const SystraceTracePoint& x,
diff --git a/src/trace_processor/proto_trace_parser_unittest.cc b/src/trace_processor/proto_trace_parser_unittest.cc
index a2c1576..c0881c8 100644
--- a/src/trace_processor/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/proto_trace_parser_unittest.cc
@@ -297,6 +297,10 @@
ASSERT_TRUE(ParseSystraceTracePoint(base::StringView("B|42|Bar"), &result));
EXPECT_EQ(result, (SystraceTracePoint{'B', 42, base::StringView("Bar"), 0}));
+
+ ASSERT_TRUE(
+ ParseSystraceTracePoint(base::StringView("C|543|foo|8"), &result));
+ EXPECT_EQ(result, (SystraceTracePoint{'C', 543, base::StringView("foo"), 8}));
}
} // namespace
diff --git a/src/trace_processor/sched_tracker.cc b/src/trace_processor/sched_tracker.cc
index 5e9021b..4dcc097 100644
--- a/src/trace_processor/sched_tracker.cc
+++ b/src/trace_processor/sched_tracker.cc
@@ -81,21 +81,24 @@
return;
}
prev_timestamp_ = timestamp;
- Counter& prev = last_counter_per_cpu_[static_cast<size_t>(ref)];
+
+ // The previous counter with the same ref and name_id.
+ Counter& prev = prev_counters_[CounterKey{ref, name_id}];
+
+ uint64_t duration = 0;
+ double value_delta = 0;
+
if (prev.timestamp != 0) {
- uint64_t duration = 0;
- // TODO(taylori): Add handling of events other than cpu freq.
- if (ref_type == RefType::kCPU_ID) {
- duration = timestamp - prev.timestamp;
- }
+ duration = timestamp - prev.timestamp;
+ value_delta = value - prev.value;
+
context_->storage->mutable_counters()->AddCounter(
- prev.timestamp, duration, name_id, prev.value,
- static_cast<int64_t>(ref), RefType::kCPU_ID);
+ prev.timestamp, duration, name_id, prev.value, value_delta,
+ static_cast<int64_t>(ref), ref_type);
}
prev.timestamp = timestamp;
prev.value = value;
- prev.name_id = name_id;
};
} // namespace trace_processor
diff --git a/src/trace_processor/sched_tracker.h b/src/trace_processor/sched_tracker.h
index 71037b6..b2c5791 100644
--- a/src/trace_processor/sched_tracker.h
+++ b/src/trace_processor/sched_tracker.h
@@ -52,7 +52,25 @@
struct Counter {
uint64_t timestamp = 0;
double value = 0;
- StringId name_id = 0;
+ };
+
+ // Used as the key in |prev_counters_| to find the previous counter with the
+ // same ref and name_id.
+ struct CounterKey {
+ uint64_t ref; // cpu, utid, ...
+ StringId name_id; // "cpufreq"
+
+ bool operator==(const CounterKey& other) const {
+ return (ref == other.ref && name_id == other.name_id);
+ }
+
+ struct Hasher {
+ size_t operator()(const CounterKey& c) const {
+ size_t const h1(std::hash<uint64_t>{}(c.ref));
+ size_t const h2(std::hash<size_t>{}(c.name_id));
+ return h1 ^ (h2 << 1);
+ }
+ };
};
// This method is called when a sched switch event is seen in the trace.
@@ -64,7 +82,6 @@
uint32_t next_pid);
// This method is called when a cpu freq event is seen in the trace.
- // In the future it will be called for all counters.
// TODO(taylori): Move to a more appropriate class or rename class.
virtual void PushCounter(uint64_t timestamp,
double value,
@@ -76,9 +93,9 @@
// Store the previous sched event to calculate the duration before storing it.
std::array<SchedSwitchEvent, base::kMaxCpus> last_sched_per_cpu_;
- // Store the previous counter event to calculate the duration before storing
- // in trace storage.
- std::array<Counter, base::kMaxCpus> last_counter_per_cpu_;
+ // Store the previous counter event to calculate the duration and value delta
+ // before storing it in trace storage.
+ std::unordered_map<CounterKey, Counter, CounterKey::Hasher> prev_counters_;
// Timestamp of the previous event. Used to discard events arriving out
// of order.
diff --git a/src/trace_processor/sched_tracker_unittest.cc b/src/trace_processor/sched_tracker_unittest.cc
index 298de15..de20f3b 100644
--- a/src/trace_processor/sched_tracker_unittest.cc
+++ b/src/trace_processor/sched_tracker_unittest.cc
@@ -126,6 +126,33 @@
ASSERT_EQ(context.storage->counters().values().at(2), 5000);
}
+TEST_F(SchedTrackerTest, MixedEventsValueDelta) {
+ uint32_t cpu = 3;
+ uint64_t timestamp = 100;
+ StringId name_id_cpu = 0;
+ StringId name_id_upid = 0;
+ UniquePid upid = 12;
+ context.sched_tracker->PushCounter(timestamp, 1000, name_id_cpu, cpu,
+ RefType::kCPU_ID);
+ context.sched_tracker->PushCounter(timestamp + 1, 0, name_id_upid, upid,
+ RefType::kUPID);
+ context.sched_tracker->PushCounter(timestamp + 3, 5000, name_id_cpu, cpu,
+ RefType::kCPU_ID);
+ context.sched_tracker->PushCounter(timestamp + 9, 1, name_id_upid, upid,
+ RefType::kUPID);
+
+ ASSERT_EQ(context.storage->counters().counter_count(), 2ul);
+ ASSERT_EQ(context.storage->counters().timestamps().at(0), timestamp);
+ ASSERT_EQ(context.storage->counters().durations().at(0), 3);
+ ASSERT_EQ(context.storage->counters().values().at(0), 1000);
+ ASSERT_EQ(context.storage->counters().value_deltas().at(0), 4000);
+
+ ASSERT_EQ(context.storage->counters().timestamps().at(1), timestamp + 1);
+ ASSERT_EQ(context.storage->counters().durations().at(1), 8);
+ ASSERT_EQ(context.storage->counters().values().at(1), 0);
+ ASSERT_EQ(context.storage->counters().value_deltas().at(1), 1);
+}
+
} // namespace
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 5a7e1be..fe2651b 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -153,12 +153,14 @@
uint64_t duration,
StringId name_id,
double value,
+ double value_delta,
int64_t ref,
RefType type) {
timestamps_.emplace_back(timestamp);
durations_.emplace_back(duration);
name_ids_.emplace_back(name_id);
values_.emplace_back(value);
+ value_deltas_.emplace_back(value_delta);
refs_.emplace_back(ref);
types_.emplace_back(type);
}
@@ -172,6 +174,8 @@
const std::deque<double>& values() const { return values_; }
+ const std::deque<double>& value_deltas() const { return value_deltas_; }
+
const std::deque<int64_t>& refs() const { return refs_; }
const std::deque<RefType>& types() const { return types_; }
@@ -181,6 +185,7 @@
std::deque<uint64_t> durations_;
std::deque<StringId> name_ids_;
std::deque<double> values_;
+ std::deque<double> value_deltas_;
std::deque<int64_t> refs_;
std::deque<RefType> types_;
};