trace_processor: Flatten CPU freq storage and remove cycles
In order to join the cpu freq information quickly with the sched table
the cpu freq events need to be in timestamp order, rather than
stored per cpu. A side effect of that is that we can't quickly compute
cycles the way that we were doing before, but that's OK because we
can compute cycles when we span join with the sched table.
The counters table is not optimised. We let SQLite do the
filtering and ordering for now.
Since the counters are no longer stored by cpu, duration can not
be computed on the fly. Instead a stage is added to sched_tracker
(rename pending) similar to the sched slices that waits for the next
event on the same cpu before outputting the prev event with it's
duration.
Change-Id: I27da5366aae6bd4cf6a7d30b1e248b938f50b965
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 79b1492..5a7e1be 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -43,9 +43,7 @@
// StringId is an offset into |string_pool_|.
using StringId = size_t;
-// A map containing timestamps and the cpu frequency set at that time.
-using CpuFreq =
- std::deque<std::pair<uint64_t /*timestamp*/, uint32_t /*freq*/>>;
+enum RefType { kUPID = 0, kCPU_ID = 1 };
// Stores a data inside a trace file in a columnar form. This makes it efficient
// to read or search across a single field of the trace (e.g. all the thread
@@ -84,12 +82,10 @@
public:
inline void AddSlice(uint64_t start_ns,
uint64_t duration_ns,
- UniqueTid utid,
- uint64_t cycles) {
+ UniqueTid utid) {
start_ns_.emplace_back(start_ns);
durations_.emplace_back(duration_ns);
utids_.emplace_back(utid);
- cycles_.emplace_back(cycles);
}
size_t slice_count() const { return start_ns_.size(); }
@@ -100,15 +96,12 @@
const std::deque<UniqueTid>& utids() const { return utids_; }
- const std::deque<uint64_t>& cycles() const { return cycles_; }
-
private:
// Each deque below has the same number of entries (the number of slices
// in the trace for the CPU).
std::deque<uint64_t> start_ns_;
std::deque<uint64_t> durations_;
std::deque<UniqueTid> utids_;
- std::deque<uint64_t> cycles_;
};
class NestableSlices {
@@ -154,13 +147,50 @@
std::deque<uint64_t> parent_stack_ids_;
};
+ class Counters {
+ public:
+ inline void AddCounter(uint64_t timestamp,
+ uint64_t duration,
+ StringId name_id,
+ double value,
+ int64_t ref,
+ RefType type) {
+ timestamps_.emplace_back(timestamp);
+ durations_.emplace_back(duration);
+ name_ids_.emplace_back(name_id);
+ values_.emplace_back(value);
+ refs_.emplace_back(ref);
+ types_.emplace_back(type);
+ }
+ size_t counter_count() const { return timestamps_.size(); }
+
+ const std::deque<uint64_t>& timestamps() const { return timestamps_; }
+
+ const std::deque<uint64_t>& durations() const { return durations_; }
+
+ const std::deque<StringId>& name_ids() const { return name_ids_; }
+
+ const std::deque<double>& values() const { return values_; }
+
+ const std::deque<int64_t>& refs() const { return refs_; }
+
+ const std::deque<RefType>& types() const { return types_; }
+
+ private:
+ std::deque<uint64_t> timestamps_;
+ std::deque<uint64_t> durations_;
+ std::deque<StringId> name_ids_;
+ std::deque<double> values_;
+ std::deque<int64_t> refs_;
+ std::deque<RefType> types_;
+ };
+
void ResetStorage();
void AddSliceToCpu(uint32_t cpu,
uint64_t start_ns,
uint64_t duration_ns,
- UniqueTid utid,
- uint64_t cycles);
+ UniqueTid utid);
UniqueTid AddEmptyThread(uint32_t tid) {
unique_threads_.emplace_back(tid);
@@ -176,7 +206,8 @@
// Return an unqiue identifier for the contents of each string.
// The string is copied internally and can be destroyed after this called.
- StringId InternString(base::StringView);
+ // Virtual for testing.
+ virtual StringId InternString(base::StringView);
Process* GetMutableProcess(UniquePid upid) {
PERFETTO_DCHECK(upid > 0 && upid < unique_processes_.size());
@@ -213,24 +244,8 @@
const NestableSlices& nestable_slices() const { return nestable_slices_; }
NestableSlices* mutable_nestable_slices() { return &nestable_slices_; }
- // Virtual for testing.
- virtual void PushCpuFreq(uint64_t timestamp,
- uint32_t cpu,
- uint32_t new_freq) {
- auto& freqs = cpu_freq_[cpu];
- if (!freqs.empty() && timestamp < freqs.back().first) {
- PERFETTO_ELOG("cpufreq out of order by %.4f ms, skipping",
- (freqs.back().first - timestamp) / 1e6);
- return;
- }
- freqs.emplace_back(timestamp, new_freq);
- }
-
- const CpuFreq& GetFreqForCpu(uint32_t cpu) const { return cpu_freq_[cpu]; }
-
- uint32_t GetMaxCpu() const {
- return static_cast<uint32_t>(cpu_freq_.size() - 1);
- }
+ const Counters& counters() const { return counters_; }
+ Counters* mutable_counters() { return &counters_; }
// |unique_processes_| always contains at least 1 element becuase the 0th ID
// is reserved to indicate an invalid process.
@@ -254,10 +269,6 @@
// One entry for each CPU in the trace.
std::array<SlicesPerCpu, base::kMaxCpus> cpu_events_;
- // One map containing frequencies for every CPU in the trace. The map contains
- // timestamps and the cpu frequency value at that time.
- std::array<CpuFreq, base::kMaxCpus> cpu_freq_;
-
// One entry for each unique string in the trace.
std::deque<std::string> string_pool_;
@@ -272,6 +283,10 @@
// Slices coming from userspace events (e.g. Chromium TRACE_EVENT macros).
NestableSlices nestable_slices_;
+
+ // Counter events from the trace. This includes CPU frequency events as well
+ // systrace trace_marker counter events.
+ Counters counters_;
};
} // namespace trace_processor