Merge "Change usage message for trace_processor_shell."
diff --git a/src/trace_processor/counters_table.cc b/src/trace_processor/counters_table.cc
index b01400f..000891f 100644
--- a/src/trace_processor/counters_table.cc
+++ b/src/trace_processor/counters_table.cc
@@ -27,6 +27,45 @@
using namespace sqlite_utils;
+PERFETTO_ALWAYS_INLINE int CompareCountersOnColumn(
+ const TraceStorage* storage,
+ size_t f_idx,
+ size_t s_idx,
+ const QueryConstraints::OrderBy& ob) {
+ const auto& co = storage->counters();
+ switch (ob.iColumn) {
+ case CountersTable::Column::kTimestamp:
+ return CompareValues(co.timestamps(), f_idx, s_idx, ob.desc);
+ case CountersTable::Column::kValue:
+ return CompareValues(co.values(), f_idx, s_idx, ob.desc);
+ case CountersTable::Column::kName:
+ return CompareValues(co.name_ids(), f_idx, s_idx, ob.desc);
+ case CountersTable::Column::kRef:
+ return CompareValues(co.refs(), f_idx, s_idx, ob.desc);
+ case CountersTable::Column::kDuration:
+ return CompareValues(co.durations(), f_idx, s_idx, ob.desc);
+ case CountersTable::Column::kValueDelta:
+ return CompareValues(co.value_deltas(), f_idx, s_idx, ob.desc);
+ case CountersTable::Column::kRefType:
+ return CompareValues(co.types(), f_idx, s_idx, ob.desc);
+ default:
+ PERFETTO_FATAL("Unexpected column %d", ob.iColumn);
+ }
+}
+
+PERFETTO_ALWAYS_INLINE int CompareCounters(
+ const TraceStorage* storage,
+ size_t f_idx,
+ size_t s_idx,
+ const std::vector<QueryConstraints::OrderBy>& order_by) {
+ for (const auto& ob : order_by) {
+ int c = CompareCountersOnColumn(storage, f_idx, s_idx, ob);
+ if (c != 0)
+ return c;
+ }
+ return 0;
+}
+
} // namespace
CountersTable::CountersTable(sqlite3*, const TraceStorage* storage)
@@ -51,49 +90,89 @@
}
std::unique_ptr<Table::Cursor> CountersTable::CreateCursor(
- const QueryConstraints&,
- sqlite3_value**) {
- return std::unique_ptr<Table::Cursor>(new Cursor(storage_));
+ const QueryConstraints& qc,
+ sqlite3_value** argv) {
+ return std::unique_ptr<Table::Cursor>(new Cursor(storage_, qc, argv));
}
int CountersTable::BestIndex(const QueryConstraints&, BestIndexInfo* info) {
// TODO(taylori): Work out cost dependant on constraints.
info->estimated_cost =
static_cast<uint32_t>(storage_->counters().counter_count());
+ info->order_by_consumed = true;
+
return SQLITE_OK;
}
-CountersTable::Cursor::Cursor(const TraceStorage* storage) : storage_(storage) {
- num_rows_ = storage->counters().counter_count();
+CountersTable::Cursor::Cursor(const TraceStorage* storage,
+ const QueryConstraints& qc,
+ sqlite3_value** argv)
+ : storage_(storage) {
+ const auto& counters = storage->counters();
+
+ std::vector<bool> filter(counters.counter_count(), true);
+ for (size_t i = 0; i < qc.constraints().size(); i++) {
+ const auto& cs = qc.constraints()[i];
+ auto* v = argv[i];
+ switch (cs.iColumn) {
+ case CountersTable::Column::kTimestamp:
+ FilterColumn(counters.timestamps(), 0, cs, v, &filter);
+ break;
+ case CountersTable::Column::kValue:
+ FilterColumn(counters.values(), 0, cs, v, &filter);
+ break;
+ case CountersTable::Column::kName:
+ FilterColumn(counters.name_ids(), 0, cs, v, &filter);
+ break;
+ case CountersTable::Column::kRef:
+ FilterColumn(counters.refs(), 0, cs, v, &filter);
+ break;
+ case CountersTable::Column::kDuration:
+ FilterColumn(counters.durations(), 0, cs, v, &filter);
+ break;
+ case CountersTable::Column::kValueDelta:
+ FilterColumn(counters.value_deltas(), 0, cs, v, &filter);
+ break;
+ case CountersTable::Column::kRefType: {
+ // TODO(lalitm): add support for filtering here.
+ }
+ }
+ }
+
+ sorted_rows_ = CreateSortedIndexFromFilter(
+ 0, filter, [this, &qc](uint32_t f, uint32_t s) {
+ return CompareCounters(storage_, f, s, qc.order_by()) < 0;
+ });
}
int CountersTable::Cursor::Column(sqlite3_context* context, int N) {
+ size_t row = sorted_rows_[next_row_idx_];
switch (N) {
case Column::kTimestamp: {
sqlite3_result_int64(
context,
- static_cast<int64_t>(storage_->counters().timestamps()[row_]));
+ static_cast<int64_t>(storage_->counters().timestamps()[row]));
break;
}
case Column::kValue: {
sqlite3_result_int64(
- context, static_cast<int64_t>(storage_->counters().values()[row_]));
+ context, static_cast<int64_t>(storage_->counters().values()[row]));
break;
}
case Column::kName: {
sqlite3_result_text(
context,
- storage_->GetString(storage_->counters().name_ids()[row_]).c_str(),
- -1, nullptr);
+ storage_->GetString(storage_->counters().name_ids()[row]).c_str(), -1,
+ nullptr);
break;
}
case Column::kRef: {
sqlite3_result_int64(
- context, static_cast<int64_t>(storage_->counters().refs()[row_]));
+ context, static_cast<int64_t>(storage_->counters().refs()[row]));
break;
}
case Column::kRefType: {
- switch (storage_->counters().types()[row_]) {
+ switch (storage_->counters().types()[row]) {
case RefType::kCPU_ID: {
sqlite3_result_text(context, "cpu", -1, nullptr);
break;
@@ -119,14 +198,13 @@
}
case Column::kDuration: {
sqlite3_result_int64(
- context,
- static_cast<int64_t>(storage_->counters().durations()[row_]));
+ context, 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_]));
+ static_cast<int64_t>(storage_->counters().value_deltas()[row]));
break;
}
default:
@@ -137,12 +215,12 @@
}
int CountersTable::Cursor::Next() {
- row_++;
+ next_row_idx_++;
return SQLITE_OK;
}
int CountersTable::Cursor::Eof() {
- return row_ >= num_rows_;
+ return next_row_idx_ >= sorted_rows_.size();
}
} // namespace trace_processor
diff --git a/src/trace_processor/counters_table.h b/src/trace_processor/counters_table.h
index 90929ec..c35b887 100644
--- a/src/trace_processor/counters_table.h
+++ b/src/trace_processor/counters_table.h
@@ -51,7 +51,7 @@
private:
class Cursor : public Table::Cursor {
public:
- Cursor(const TraceStorage*);
+ Cursor(const TraceStorage*, const QueryConstraints&, sqlite3_value**);
// Implementation of Table::Cursor.
int Next() override;
@@ -59,8 +59,11 @@
int Column(sqlite3_context*, int N) override;
private:
- size_t num_rows_;
- size_t row_ = 0;
+ // Vector of row ids sorted by some order by constraints.
+ std::vector<uint32_t> sorted_rows_;
+
+ // An offset into |sorted_row_ids_| indicating the next row to return.
+ uint32_t next_row_idx_ = 0;
const TraceStorage* const storage_;
};
diff --git a/src/trace_processor/sched_slice_table.cc b/src/trace_processor/sched_slice_table.cc
index 079168f..0575f00 100644
--- a/src/trace_processor/sched_slice_table.cc
+++ b/src/trace_processor/sched_slice_table.cc
@@ -34,16 +34,6 @@
constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
-template <class T>
-inline int Compare(T first, T second, bool desc) {
- if (first < second) {
- return desc ? 1 : -1;
- } else if (first > second) {
- return desc ? -1 : 1;
- }
- return 0;
-}
-
// Compares the slice at index |f| with the slice at index |s| on the
// criteria in |order_by|.
// Returns -1 if the first slice is before the second in the ordering, 1 if
@@ -56,13 +46,13 @@
const auto& sl = storage->slices();
switch (ob.iColumn) {
case SchedSliceTable::Column::kTimestamp:
- return Compare(sl.start_ns()[f_idx], sl.start_ns()[s_idx], ob.desc);
+ return CompareValues(sl.start_ns(), f_idx, s_idx, ob.desc);
case SchedSliceTable::Column::kDuration:
- return Compare(sl.durations()[f_idx], sl.durations()[s_idx], ob.desc);
+ return CompareValues(sl.durations(), f_idx, s_idx, ob.desc);
case SchedSliceTable::Column::kCpu:
- return Compare(sl.cpus()[f_idx], sl.cpus()[s_idx], ob.desc);
+ return CompareValues(sl.cpus(), f_idx, s_idx, ob.desc);
case SchedSliceTable::Column::kUtid:
- return Compare(sl.utids()[f_idx], sl.utids()[s_idx], ob.desc);
+ return CompareValues(sl.utids(), f_idx, s_idx, ob.desc);
default:
PERFETTO_FATAL("Unexpected column %d", ob.iColumn);
}
@@ -133,8 +123,6 @@
uint32_t min_idx,
uint32_t max_idx) {
const auto& slices = storage->slices();
- ptrdiff_t min_idx_ptr = static_cast<ptrdiff_t>(min_idx);
- ptrdiff_t max_idx_ptr = static_cast<ptrdiff_t>(max_idx);
auto dist = static_cast<size_t>(max_idx - min_idx);
std::vector<bool> filter(dist, true);
@@ -142,21 +130,15 @@
const auto& cs = qc.constraints()[i];
auto* v = argv[i];
switch (cs.iColumn) {
- case SchedSliceTable::Column::kCpu: {
- auto it = slices.cpus().begin();
- FilterColumn(it + min_idx_ptr, it + max_idx_ptr, cs, v, &filter);
+ case SchedSliceTable::Column::kCpu:
+ FilterColumn(slices.cpus(), min_idx, cs, v, &filter);
break;
- }
- case SchedSliceTable::Column::kDuration: {
- auto it = slices.durations().begin();
- FilterColumn(it + min_idx_ptr, it + max_idx_ptr, cs, v, &filter);
+ case SchedSliceTable::Column::kDuration:
+ FilterColumn(slices.durations(), min_idx, cs, v, &filter);
break;
- }
- case SchedSliceTable::Column::kUtid: {
- auto it = slices.utids().begin();
- FilterColumn(it + min_idx_ptr, it + max_idx_ptr, cs, v, &filter);
+ case SchedSliceTable::Column::kUtid:
+ FilterColumn(slices.utids(), min_idx, cs, v, &filter);
break;
- }
}
}
return filter;
@@ -219,8 +201,8 @@
return std::unique_ptr<Table::Cursor>(
new FilterCursor(storage_, min_idx, max_idx, std::move(filter), desc));
}
- return std::unique_ptr<Table::Cursor>(new SortedCursor(
- storage_, min_idx, max_idx, qc.order_by(), std::move(filter)));
+ return std::unique_ptr<Table::Cursor>(
+ new SortedCursor(storage_, min_idx, qc.order_by(), std::move(filter)));
}
int SchedSliceTable::BestIndex(const QueryConstraints& qc,
@@ -342,27 +324,14 @@
SchedSliceTable::SortedCursor::SortedCursor(
const TraceStorage* storage,
- uint32_t min_idx,
- uint32_t max_idx,
+ uint32_t offset,
const std::vector<QueryConstraints::OrderBy>& ob,
const std::vector<bool>& filter)
: BaseCursor(storage) {
- auto diff = static_cast<size_t>(max_idx - min_idx);
- PERFETTO_CHECK(diff == filter.size());
-
- auto set_bits = std::count(filter.begin(), filter.end(), true);
- sorted_rows_.resize(static_cast<size_t>(set_bits));
-
- auto it = std::find(filter.begin(), filter.end(), true);
- for (size_t i = 0; it != filter.end(); i++) {
- auto index = static_cast<uint32_t>(std::distance(filter.begin(), it));
- sorted_rows_[i] = min_idx + index;
- it = std::find(it + 1, filter.end(), true);
- }
- std::sort(sorted_rows_.begin(), sorted_rows_.end(),
- [this, &ob](uint32_t f, uint32_t s) {
- return CompareSlices(storage_, f, s, ob) < 0;
- });
+ sorted_rows_ = CreateSortedIndexFromFilter(
+ offset, filter, [this, &ob](uint32_t f, uint32_t s) {
+ return CompareSlices(storage_, f, s, ob) < 0;
+ });
}
int SchedSliceTable::SortedCursor::Next() {
diff --git a/src/trace_processor/sched_slice_table.h b/src/trace_processor/sched_slice_table.h
index bd63df8..ea41cae 100644
--- a/src/trace_processor/sched_slice_table.h
+++ b/src/trace_processor/sched_slice_table.h
@@ -122,8 +122,7 @@
uint32_t max_idx,
const std::vector<QueryConstraints::OrderBy>&);
SortedCursor(const TraceStorage* storage,
- uint32_t min_idx,
- uint32_t max_idx,
+ uint32_t offset,
const std::vector<QueryConstraints::OrderBy>&,
const std::vector<bool>& filter);
diff --git a/src/trace_processor/span_operator_table.cc b/src/trace_processor/span_operator_table.cc
index 6f898bc..091427f 100644
--- a/src/trace_processor/span_operator_table.cc
+++ b/src/trace_processor/span_operator_table.cc
@@ -334,6 +334,7 @@
value->text_value =
reinterpret_cast<const char*>(sqlite3_column_text(stmt, i));
break;
+ case Table::ColumnType::kDouble:
case Table::ColumnType::kInt:
PERFETTO_CHECK(false);
}
@@ -427,6 +428,7 @@
kSqliteTransient);
break;
}
+ case Table::ColumnType::kDouble:
case Table::ColumnType::kInt:
PERFETTO_CHECK(false);
}
diff --git a/src/trace_processor/sqlite_utils.h b/src/trace_processor/sqlite_utils.h
index 191f316..83d5074 100644
--- a/src/trace_processor/sqlite_utils.h
+++ b/src/trace_processor/sqlite_utils.h
@@ -68,57 +68,99 @@
}
}
+template <class D>
+int CompareValues(const D& deque, size_t a, size_t b, bool desc) {
+ const auto& first = deque[a];
+ const auto& second = deque[b];
+ if (first < second) {
+ return desc ? 1 : -1;
+ } else if (first > second) {
+ return desc ? -1 : 1;
+ }
+ return 0;
+}
+
template <typename F>
-bool Compare(uint32_t actual, sqlite3_value* value) {
+bool CompareToSqliteValue(uint32_t actual, sqlite3_value* value) {
PERFETTO_DCHECK(sqlite3_value_type(value) == SQLITE_INTEGER);
return F()(actual, static_cast<uint32_t>(sqlite3_value_int64(value)));
}
template <typename F>
-bool Compare(uint64_t actual, sqlite3_value* value) {
- PERFETTO_CHECK(sqlite3_value_type(value) == SQLITE_INTEGER);
+bool CompareToSqliteValue(uint64_t actual, sqlite3_value* value) {
+ PERFETTO_DCHECK(sqlite3_value_type(value) == SQLITE_INTEGER);
return F()(actual, static_cast<uint64_t>(sqlite3_value_int64(value)));
}
-template <class RandomAccessIterator>
-void FilterColumn(RandomAccessIterator begin,
- RandomAccessIterator end,
+template <typename F>
+bool CompareToSqliteValue(int64_t actual, sqlite3_value* value) {
+ PERFETTO_DCHECK(sqlite3_value_type(value) == SQLITE_INTEGER);
+ return F()(actual, static_cast<int64_t>(sqlite3_value_int64(value)));
+}
+
+template <typename F>
+bool CompareToSqliteValue(double actual, sqlite3_value* value) {
+ auto type = sqlite3_value_type(value);
+ PERFETTO_DCHECK(type == SQLITE_FLOAT || type == SQLITE_INTEGER);
+ return F()(actual, sqlite3_value_double(value));
+}
+
+template <class D>
+void FilterColumn(const D& deque,
+ size_t offset,
const QueryConstraints::Constraint& constraint,
sqlite3_value* argv,
- std::vector<bool>* row_filter) {
- using T = typename RandomAccessIterator::value_type;
- PERFETTO_DCHECK(static_cast<size_t>(std::distance(begin, end)) ==
- row_filter->size());
+ std::vector<bool>* filter) {
+ using T = typename D::value_type;
- auto it = std::find(row_filter->begin(), row_filter->end(), true);
- while (it != row_filter->end()) {
- auto index = std::distance(row_filter->begin(), it);
+ auto it = std::find(filter->begin(), filter->end(), true);
+ while (it != filter->end()) {
+ auto filter_idx = static_cast<size_t>(std::distance(filter->begin(), it));
+ T actual = deque[offset + filter_idx];
switch (constraint.op) {
case SQLITE_INDEX_CONSTRAINT_EQ:
- *it = Compare<std::equal_to<T>>(begin[index], argv);
+ *it = CompareToSqliteValue<std::equal_to<T>>(actual, argv);
break;
case SQLITE_INDEX_CONSTRAINT_GE:
- *it = Compare<std::greater_equal<T>>(begin[index], argv);
+ *it = CompareToSqliteValue<std::greater_equal<T>>(actual, argv);
break;
case SQLITE_INDEX_CONSTRAINT_GT:
- *it = Compare<std::greater<T>>(begin[index], argv);
+ *it = CompareToSqliteValue<std::greater<T>>(actual, argv);
break;
case SQLITE_INDEX_CONSTRAINT_LE:
- *it = Compare<std::less_equal<T>>(begin[index], argv);
+ *it = CompareToSqliteValue<std::less_equal<T>>(actual, argv);
break;
case SQLITE_INDEX_CONSTRAINT_LT:
- *it = Compare<std::less<T>>(begin[index], argv);
+ *it = CompareToSqliteValue<std::less<T>>(actual, argv);
break;
case SQLITE_INDEX_CONSTRAINT_NE:
- *it = Compare<std::not_equal_to<T>>(begin[index], argv);
+ *it = CompareToSqliteValue<std::not_equal_to<T>>(actual, argv);
break;
default:
PERFETTO_CHECK(false);
}
- it = std::find(it + 1, row_filter->end(), true);
+ it = std::find(it + 1, filter->end(), true);
}
}
+template <class Comparator>
+std::vector<uint32_t> CreateSortedIndexFromFilter(
+ uint32_t offset,
+ const std::vector<bool>& filter,
+ Comparator comparator) {
+ auto set_bits = std::count(filter.begin(), filter.end(), true);
+
+ std::vector<uint32_t> sorted_rows(static_cast<size_t>(set_bits));
+ auto it = std::find(filter.begin(), filter.end(), true);
+ for (size_t i = 0; it != filter.end(); i++) {
+ auto filter_idx = static_cast<uint32_t>(std::distance(filter.begin(), it));
+ sorted_rows[i] = offset + filter_idx;
+ it = std::find(it + 1, filter.end(), true);
+ }
+ std::sort(sorted_rows.begin(), sorted_rows.end(), comparator);
+ return sorted_rows;
+}
+
} // namespace sqlite_utils
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/table.cc b/src/trace_processor/table.cc
index 228551d..72eb3c2 100644
--- a/src/trace_processor/table.cc
+++ b/src/trace_processor/table.cc
@@ -51,6 +51,8 @@
return "UNSIGNED BIG INT";
case Table::ColumnType::kInt:
return "INT";
+ case Table::ColumnType::kDouble:
+ return "DOUBLE";
}
PERFETTO_CHECK(false);
}
diff --git a/src/trace_processor/table.h b/src/trace_processor/table.h
index db1af75..5cf22f2 100644
--- a/src/trace_processor/table.h
+++ b/src/trace_processor/table.h
@@ -45,6 +45,7 @@
kUlong = 2,
kUint = 3,
kInt = 4,
+ kDouble = 5,
};
// Describes a column of this table.
diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn
index cae4c23..b90ce18 100644
--- a/src/tracing/BUILD.gn
+++ b/src/tracing/BUILD.gn
@@ -65,19 +65,6 @@
]
}
-executable("consumer_api_test") {
- deps = [
- ":api",
- "../../gn:default_deps",
- "../../protos/perfetto/config:lite",
- "../../protos/perfetto/trace:lite",
- "../base",
- ]
- sources = [
- "api_impl/consumer_api_test.cc",
- ]
-}
-
source_set("unittests") {
testonly = true
deps = [
@@ -146,6 +133,19 @@
}
if (!build_with_chromium) {
+ executable("consumer_api_test") {
+ deps = [
+ ":api",
+ "../../gn:default_deps",
+ "../../protos/perfetto/config:lite",
+ "../../protos/perfetto/trace:lite",
+ "../base",
+ ]
+ sources = [
+ "api_impl/consumer_api_test.cc",
+ ]
+ }
+
# IPC transport: only consumer side
# TODO(fmayer): Remove duplication between this and ipc.
source_set("ipc_consumer") {