tp: add sched table with upid included

This makes the process scheduling tracks a lot faster - the
join with the thread table were really slowing them down because of the
constant back and forth between SQLite and our code.
Change-Id: I53426bf754afc7bd0612c150cf2e56ee2b33a920
diff --git a/Android.bp b/Android.bp
index 66ca9a7..fb7da39 100644
--- a/Android.bp
+++ b/Android.bp
@@ -6752,6 +6752,7 @@
     "src/trace_processor/dynamic/describe_slice_generator.cc",
     "src/trace_processor/dynamic/experimental_counter_dur_generator.cc",
     "src/trace_processor/dynamic/experimental_flamegraph_generator.cc",
+    "src/trace_processor/dynamic/experimental_sched_upid_generator.cc",
     "src/trace_processor/dynamic/experimental_slice_layout_generator.cc",
     "src/trace_processor/iterator_impl.cc",
     "src/trace_processor/read_trace.cc",
diff --git a/BUILD b/BUILD
index bba653d..b2afa7f 100644
--- a/BUILD
+++ b/BUILD
@@ -953,6 +953,8 @@
         "src/trace_processor/dynamic/experimental_counter_dur_generator.h",
         "src/trace_processor/dynamic/experimental_flamegraph_generator.cc",
         "src/trace_processor/dynamic/experimental_flamegraph_generator.h",
+        "src/trace_processor/dynamic/experimental_sched_upid_generator.cc",
+        "src/trace_processor/dynamic/experimental_sched_upid_generator.h",
         "src/trace_processor/dynamic/experimental_slice_layout_generator.cc",
         "src/trace_processor/dynamic/experimental_slice_layout_generator.h",
         "src/trace_processor/iterator_impl.cc",
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index a42e905..97c090a 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -286,6 +286,8 @@
       "dynamic/experimental_counter_dur_generator.h",
       "dynamic/experimental_flamegraph_generator.cc",
       "dynamic/experimental_flamegraph_generator.h",
+      "dynamic/experimental_sched_upid_generator.cc",
+      "dynamic/experimental_sched_upid_generator.h",
       "dynamic/experimental_slice_layout_generator.cc",
       "dynamic/experimental_slice_layout_generator.h",
       "iterator_impl.cc",
diff --git a/src/trace_processor/db/table.h b/src/trace_processor/db/table.h
index eab80fc..c49a851 100644
--- a/src/trace_processor/db/table.h
+++ b/src/trace_processor/db/table.h
@@ -155,7 +155,7 @@
   Table ExtendWithColumn(const char* name,
                          std::unique_ptr<NullableVector<T>> sv,
                          uint32_t flags) const {
-    PERFETTO_DCHECK(sv->size() == row_count_);
+    PERFETTO_CHECK(sv->size() == row_count_);
     uint32_t size = sv->size();
     uint32_t row_map_count = static_cast<uint32_t>(row_maps_.size());
     Table ret = Copy();
@@ -170,7 +170,7 @@
   Table ExtendWithColumn(const char* name,
                          NullableVector<T>* sv,
                          uint32_t flags) const {
-    PERFETTO_DCHECK(sv->size() == row_count_);
+    PERFETTO_CHECK(sv->size() == row_count_);
     uint32_t size = sv->size();
     uint32_t row_map_count = static_cast<uint32_t>(row_maps_.size());
     Table ret = Copy();
diff --git a/src/trace_processor/dynamic/experimental_sched_upid_generator.cc b/src/trace_processor/dynamic/experimental_sched_upid_generator.cc
new file mode 100644
index 0000000..1906918
--- /dev/null
+++ b/src/trace_processor/dynamic/experimental_sched_upid_generator.cc
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/dynamic/experimental_sched_upid_generator.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+ExperimentalSchedUpidGenerator::ExperimentalSchedUpidGenerator(
+    const tables::SchedSliceTable& sched,
+    const tables::ThreadTable& thread)
+    : sched_slice_table_(&sched), thread_table_(&thread) {}
+ExperimentalSchedUpidGenerator::~ExperimentalSchedUpidGenerator() = default;
+
+Table::Schema ExperimentalSchedUpidGenerator::CreateSchema() {
+  Table::Schema schema = tables::SchedSliceTable::Schema();
+  schema.columns.emplace_back(
+      Table::Schema::Column{"upid", SqlValue::Type::kLong, false /* is_id */,
+                            false /* is_sorted */, false /* is_hidden */});
+  return schema;
+}
+
+std::string ExperimentalSchedUpidGenerator::TableName() {
+  return "experimental_sched_upid";
+}
+
+uint32_t ExperimentalSchedUpidGenerator::EstimateRowCount() {
+  return sched_slice_table_->row_count();
+}
+
+util::Status ExperimentalSchedUpidGenerator::ValidateConstraints(
+    const QueryConstraints&) {
+  return util::OkStatus();
+}
+
+std::unique_ptr<Table> ExperimentalSchedUpidGenerator::ComputeTable(
+    const std::vector<Constraint>&,
+    const std::vector<Order>&) {
+  if (!upid_column_) {
+    upid_column_.reset(new NullableVector<uint32_t>(ComputeUpidColumn()));
+  }
+  return std::unique_ptr<Table>(new Table(sched_slice_table_->ExtendWithColumn(
+      "upid", upid_column_.get(),
+      TypedColumn<base::Optional<uint32_t>>::default_flags())));
+}
+
+NullableVector<uint32_t> ExperimentalSchedUpidGenerator::ComputeUpidColumn() {
+  NullableVector<uint32_t> upid;
+  for (uint32_t i = 0; i < sched_slice_table_->row_count(); ++i) {
+    upid.Append(thread_table_->upid()[sched_slice_table_->utid()[i]]);
+  }
+  return upid;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/dynamic/experimental_sched_upid_generator.h b/src/trace_processor/dynamic/experimental_sched_upid_generator.h
new file mode 100644
index 0000000..09e0dfa
--- /dev/null
+++ b/src/trace_processor/dynamic/experimental_sched_upid_generator.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_SCHED_UPID_GENERATOR_H_
+#define SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_SCHED_UPID_GENERATOR_H_
+
+#include <set>
+
+#include "src/trace_processor/sqlite/db_sqlite_table.h"
+#include "src/trace_processor/storage/trace_storage.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class ExperimentalSchedUpidGenerator
+    : public DbSqliteTable::DynamicTableGenerator {
+ public:
+  ExperimentalSchedUpidGenerator(const tables::SchedSliceTable&,
+                                 const tables::ThreadTable&);
+  virtual ~ExperimentalSchedUpidGenerator() override;
+
+  Table::Schema CreateSchema() override;
+  std::string TableName() override;
+  uint32_t EstimateRowCount() override;
+  util::Status ValidateConstraints(const QueryConstraints&) override;
+  std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>&,
+                                      const std::vector<Order>&) override;
+
+ private:
+  NullableVector<uint32_t> ComputeUpidColumn();
+
+  const tables::SchedSliceTable* sched_slice_table_;
+  const tables::ThreadTable* thread_table_;
+  std::unique_ptr<NullableVector<uint32_t>> upid_column_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_SCHED_UPID_GENERATOR_H_
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 7e7518f..d5198c7 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -28,6 +28,7 @@
 #include "src/trace_processor/dynamic/describe_slice_generator.h"
 #include "src/trace_processor/dynamic/experimental_counter_dur_generator.h"
 #include "src/trace_processor/dynamic/experimental_flamegraph_generator.h"
+#include "src/trace_processor/dynamic/experimental_sched_upid_generator.h"
 #include "src/trace_processor/dynamic/experimental_slice_layout_generator.h"
 #include "src/trace_processor/export_json.h"
 #include "src/trace_processor/importers/additional_modules.h"
@@ -703,6 +704,9 @@
       new AncestorSliceGenerator(&context_)));
   RegisterDynamicTable(std::unique_ptr<DescendantSliceGenerator>(
       new DescendantSliceGenerator(&context_)));
+  RegisterDynamicTable(std::unique_ptr<ExperimentalSchedUpidGenerator>(
+      new ExperimentalSchedUpidGenerator(storage->sched_slice_table(),
+                                         storage->thread_table())));
 
   // New style db-backed tables.
   RegisterDbTable(storage->arg_table());
diff --git a/ui/src/tracks/process_scheduling/controller.ts b/ui/src/tracks/process_scheduling/controller.ts
index c763e85..aa0d7dd 100644
--- a/ui/src/tracks/process_scheduling/controller.ts
+++ b/ui/src/tracks/process_scheduling/controller.ts
@@ -54,12 +54,11 @@
       assertTrue(cpus.length > 0);
       this.maxCpu = Math.max(...cpus) + 1;
 
-      const maxDurResult = await this.query(`select max(dur)
-        from sched
-        join thread using(utid)
-        where
-          utid != 0 and
-          upid = ${this.config.upid}`);
+      const maxDurResult = await this.query(`
+        select max(dur)
+        from experimental_sched_upid
+        where utid != 0 and upid = ${this.config.upid}
+      `);
       if (maxDurResult.numRecords === 1) {
         this.maxDurNs = maxDurResult.columns[0].longValues![0];
       }
@@ -67,20 +66,21 @@
       this.setup = true;
     }
 
-    const rawResult = await this.query(`select
+    const rawResult = await this.query(`
+      select
         (ts + ${bucketNs / 2}) / ${bucketNs} * ${bucketNs} as tsq,
         ts,
         max(dur) as dur,
         cpu,
         utid
-      from sched
-      join thread using(utid)
+      from experimental_sched_upid
       where
         ts >= ${startNs - this.maxDurNs} and
         ts <= ${endNs} and
         utid != 0 and
         upid = ${this.config.upid}
-      group by cpu, tsq`);
+      group by cpu, tsq
+    `);
 
     const numRows = +rawResult.numRecords;
     const slices: Data = {