Merge "trace_processor: bump min chunk size in trace processor"
diff --git a/Android.bp b/Android.bp
index cbbed46..62bf1cf 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3215,6 +3215,10 @@
     "src/trace_processor/fuchsia_trace_parser.cc",
     "src/trace_processor/fuchsia_trace_tokenizer.cc",
     "src/trace_processor/fuchsia_trace_utils.cc",
+    "src/trace_processor/heap_profile_allocation_table.cc",
+    "src/trace_processor/heap_profile_callsite_table.cc",
+    "src/trace_processor/heap_profile_frame_table.cc",
+    "src/trace_processor/heap_profile_mapping_table.cc",
     "src/trace_processor/heap_profile_tracker.cc",
     "src/trace_processor/instants_table.cc",
     "src/trace_processor/metrics/metrics.cc",
diff --git a/BUILD b/BUILD
index 80a7419..164767e 100644
--- a/BUILD
+++ b/BUILD
@@ -179,6 +179,14 @@
         "src/trace_processor/fuchsia_trace_tokenizer.h",
         "src/trace_processor/fuchsia_trace_utils.cc",
         "src/trace_processor/fuchsia_trace_utils.h",
+        "src/trace_processor/heap_profile_allocation_table.cc",
+        "src/trace_processor/heap_profile_allocation_table.h",
+        "src/trace_processor/heap_profile_callsite_table.cc",
+        "src/trace_processor/heap_profile_callsite_table.h",
+        "src/trace_processor/heap_profile_frame_table.cc",
+        "src/trace_processor/heap_profile_frame_table.h",
+        "src/trace_processor/heap_profile_mapping_table.cc",
+        "src/trace_processor/heap_profile_mapping_table.h",
         "src/trace_processor/heap_profile_tracker.cc",
         "src/trace_processor/heap_profile_tracker.h",
         "src/trace_processor/instants_table.cc",
@@ -430,6 +438,14 @@
         "src/trace_processor/fuchsia_trace_tokenizer.h",
         "src/trace_processor/fuchsia_trace_utils.cc",
         "src/trace_processor/fuchsia_trace_utils.h",
+        "src/trace_processor/heap_profile_allocation_table.cc",
+        "src/trace_processor/heap_profile_allocation_table.h",
+        "src/trace_processor/heap_profile_callsite_table.cc",
+        "src/trace_processor/heap_profile_callsite_table.h",
+        "src/trace_processor/heap_profile_frame_table.cc",
+        "src/trace_processor/heap_profile_frame_table.h",
+        "src/trace_processor/heap_profile_mapping_table.cc",
+        "src/trace_processor/heap_profile_mapping_table.h",
         "src/trace_processor/heap_profile_tracker.cc",
         "src/trace_processor/heap_profile_tracker.h",
         "src/trace_processor/instants_table.cc",
@@ -637,6 +653,14 @@
         "src/trace_processor/fuchsia_trace_tokenizer.h",
         "src/trace_processor/fuchsia_trace_utils.cc",
         "src/trace_processor/fuchsia_trace_utils.h",
+        "src/trace_processor/heap_profile_allocation_table.cc",
+        "src/trace_processor/heap_profile_allocation_table.h",
+        "src/trace_processor/heap_profile_callsite_table.cc",
+        "src/trace_processor/heap_profile_callsite_table.h",
+        "src/trace_processor/heap_profile_frame_table.cc",
+        "src/trace_processor/heap_profile_frame_table.h",
+        "src/trace_processor/heap_profile_mapping_table.cc",
+        "src/trace_processor/heap_profile_mapping_table.h",
         "src/trace_processor/heap_profile_tracker.cc",
         "src/trace_processor/heap_profile_tracker.h",
         "src/trace_processor/instants_table.cc",
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 0a76207..f38484d 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -72,6 +72,14 @@
     "fuchsia_trace_tokenizer.h",
     "fuchsia_trace_utils.cc",
     "fuchsia_trace_utils.h",
+    "heap_profile_allocation_table.cc",
+    "heap_profile_allocation_table.h",
+    "heap_profile_callsite_table.cc",
+    "heap_profile_callsite_table.h",
+    "heap_profile_frame_table.cc",
+    "heap_profile_frame_table.h",
+    "heap_profile_mapping_table.cc",
+    "heap_profile_mapping_table.h",
     "heap_profile_tracker.cc",
     "heap_profile_tracker.h",
     "instants_table.cc",
diff --git a/src/trace_processor/counter_values_table.cc b/src/trace_processor/counter_values_table.cc
index 7398b2b..0d1254c 100644
--- a/src/trace_processor/counter_values_table.cc
+++ b/src/trace_processor/counter_values_table.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 9 The Android Open Source Project
+ * Copyright (C) 2019 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.
diff --git a/src/trace_processor/heap_profile_allocation_table.cc b/src/trace_processor/heap_profile_allocation_table.cc
new file mode 100644
index 0000000..7c057cf
--- /dev/null
+++ b/src/trace_processor/heap_profile_allocation_table.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019 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/heap_profile_allocation_table.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+HeapProfileAllocationTable::HeapProfileAllocationTable(
+    sqlite3*,
+    const TraceStorage* storage)
+    : storage_(storage) {}
+
+void HeapProfileAllocationTable::RegisterTable(sqlite3* db,
+                                               const TraceStorage* storage) {
+  Table::Register<HeapProfileAllocationTable>(db, storage,
+                                              "heap_profile_allocation");
+}
+
+StorageSchema HeapProfileAllocationTable::CreateStorageSchema() {
+  const auto& allocs = storage_->heap_profile_allocations();
+  return StorageSchema::Builder()
+      .AddGenericNumericColumn("id", RowAccessor())
+      .AddOrderedNumericColumn("ts", &allocs.timestamps())
+      .AddNumericColumn("pid", &allocs.pids())
+      .AddNumericColumn("callsite_id", &allocs.callsite_ids())
+      .AddNumericColumn("count", &allocs.counts())
+      .AddNumericColumn("size", &allocs.sizes())
+      .Build({"id"});
+}
+
+uint32_t HeapProfileAllocationTable::RowCount() {
+  return storage_->heap_profile_allocations().size();
+}
+
+int HeapProfileAllocationTable::BestIndex(const QueryConstraints&,
+                                          BestIndexInfo* info) {
+  info->order_by_consumed = true;
+  return SQLITE_OK;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/heap_profile_allocation_table.h b/src/trace_processor/heap_profile_allocation_table.h
new file mode 100644
index 0000000..9f7fd44
--- /dev/null
+++ b/src/trace_processor/heap_profile_allocation_table.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 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_HEAP_PROFILE_ALLOCATION_TABLE_H_
+#define SRC_TRACE_PROCESSOR_HEAP_PROFILE_ALLOCATION_TABLE_H_
+
+#include "src/trace_processor/storage_table.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class HeapProfileAllocationTable : public StorageTable {
+ public:
+  static void RegisterTable(sqlite3* db, const TraceStorage* storage);
+
+  HeapProfileAllocationTable(sqlite3*, const TraceStorage*);
+
+  // StorageTable implementation.
+  StorageSchema CreateStorageSchema() override;
+  uint32_t RowCount() override;
+  int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
+
+ private:
+  const TraceStorage* const storage_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_HEAP_PROFILE_ALLOCATION_TABLE_H_
diff --git a/src/trace_processor/heap_profile_callsite_table.cc b/src/trace_processor/heap_profile_callsite_table.cc
new file mode 100644
index 0000000..b76d413
--- /dev/null
+++ b/src/trace_processor/heap_profile_callsite_table.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 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/heap_profile_callsite_table.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+HeapProfileCallsiteTable::HeapProfileCallsiteTable(sqlite3*,
+                                                   const TraceStorage* storage)
+    : storage_(storage) {}
+
+void HeapProfileCallsiteTable::RegisterTable(sqlite3* db,
+                                             const TraceStorage* storage) {
+  Table::Register<HeapProfileCallsiteTable>(db, storage,
+                                            "heap_profile_callsite");
+}
+
+StorageSchema HeapProfileCallsiteTable::CreateStorageSchema() {
+  const auto& callsites = storage_->heap_profile_callsites();
+  return StorageSchema::Builder()
+      .AddGenericNumericColumn("id", RowAccessor())
+      .AddNumericColumn("depth", &callsites.frame_depths())
+      .AddNumericColumn("parent_id", &callsites.parent_callsite_ids())
+      .AddNumericColumn("frame_id", &callsites.frame_ids())
+      .Build({"id"});
+}
+
+uint32_t HeapProfileCallsiteTable::RowCount() {
+  return storage_->heap_profile_callsites().size();
+}
+
+int HeapProfileCallsiteTable::BestIndex(const QueryConstraints&,
+                                        BestIndexInfo* info) {
+  info->order_by_consumed = true;
+  return SQLITE_OK;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/heap_profile_callsite_table.h b/src/trace_processor/heap_profile_callsite_table.h
new file mode 100644
index 0000000..54712a1
--- /dev/null
+++ b/src/trace_processor/heap_profile_callsite_table.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 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_HEAP_PROFILE_CALLSITE_TABLE_H_
+#define SRC_TRACE_PROCESSOR_HEAP_PROFILE_CALLSITE_TABLE_H_
+
+#include "src/trace_processor/storage_table.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class HeapProfileCallsiteTable : public StorageTable {
+ public:
+  static void RegisterTable(sqlite3* db, const TraceStorage* storage);
+
+  HeapProfileCallsiteTable(sqlite3*, const TraceStorage*);
+
+  // StorageTable implementation.
+  StorageSchema CreateStorageSchema() override;
+  uint32_t RowCount() override;
+  int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
+
+ private:
+  const TraceStorage* const storage_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_HEAP_PROFILE_CALLSITE_TABLE_H_
diff --git a/src/trace_processor/heap_profile_frame_table.cc b/src/trace_processor/heap_profile_frame_table.cc
new file mode 100644
index 0000000..06bda90
--- /dev/null
+++ b/src/trace_processor/heap_profile_frame_table.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 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/heap_profile_frame_table.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+HeapProfileFrameTable::HeapProfileFrameTable(sqlite3*,
+                                             const TraceStorage* storage)
+    : storage_(storage) {}
+
+void HeapProfileFrameTable::RegisterTable(sqlite3* db,
+                                          const TraceStorage* storage) {
+  Table::Register<HeapProfileFrameTable>(db, storage, "heap_profile_frame");
+}
+
+StorageSchema HeapProfileFrameTable::CreateStorageSchema() {
+  const auto& frames = storage_->heap_profile_frames();
+  return StorageSchema::Builder()
+      .AddGenericNumericColumn("id", RowAccessor())
+      .AddStringColumn("name", &frames.names(), &storage_->string_pool())
+      .AddNumericColumn("mapping", &frames.mappings())
+      .AddNumericColumn("rel_pc", &frames.rel_pcs())
+      .Build({"id"});
+}
+
+uint32_t HeapProfileFrameTable::RowCount() {
+  return storage_->heap_profile_frames().size();
+}
+
+int HeapProfileFrameTable::BestIndex(const QueryConstraints&,
+                                     BestIndexInfo* info) {
+  info->order_by_consumed = true;
+  return SQLITE_OK;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/heap_profile_frame_table.h b/src/trace_processor/heap_profile_frame_table.h
new file mode 100644
index 0000000..db8f3b9
--- /dev/null
+++ b/src/trace_processor/heap_profile_frame_table.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 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_HEAP_PROFILE_FRAME_TABLE_H_
+#define SRC_TRACE_PROCESSOR_HEAP_PROFILE_FRAME_TABLE_H_
+
+#include "src/trace_processor/storage_table.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class HeapProfileFrameTable : public StorageTable {
+ public:
+  static void RegisterTable(sqlite3* db, const TraceStorage* storage);
+
+  HeapProfileFrameTable(sqlite3*, const TraceStorage*);
+
+  // StorageTable implementation.
+  StorageSchema CreateStorageSchema() override;
+  uint32_t RowCount() override;
+  int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
+
+ private:
+  const TraceStorage* const storage_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_HEAP_PROFILE_FRAME_TABLE_H_
diff --git a/src/trace_processor/heap_profile_mapping_table.cc b/src/trace_processor/heap_profile_mapping_table.cc
new file mode 100644
index 0000000..fcbbb46
--- /dev/null
+++ b/src/trace_processor/heap_profile_mapping_table.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 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/heap_profile_mapping_table.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+HeapProfileMappingTable::HeapProfileMappingTable(sqlite3*,
+                                                 const TraceStorage* storage)
+    : storage_(storage) {}
+
+void HeapProfileMappingTable::RegisterTable(sqlite3* db,
+                                            const TraceStorage* storage) {
+  Table::Register<HeapProfileMappingTable>(db, storage, "heap_profile_mapping");
+}
+
+StorageSchema HeapProfileMappingTable::CreateStorageSchema() {
+  const auto& mappings = storage_->heap_profile_mappings();
+  return StorageSchema::Builder()
+      .AddGenericNumericColumn("id", RowAccessor())
+      // TODO(lalitm): we should hex encode this string before exposing as
+      // a column.
+      //.AddStringColumn("build_id", &mappings.build_ids(),
+      //                 &storage_->string_pool())
+      .AddNumericColumn("offset", &mappings.offsets())
+      .AddNumericColumn("start", &mappings.starts())
+      .AddNumericColumn("end", &mappings.ends())
+      .AddNumericColumn("load_bias", &mappings.load_biases())
+      .AddStringColumn("name", &mappings.names(), &storage_->string_pool())
+      .Build({"id"});
+}
+
+uint32_t HeapProfileMappingTable::RowCount() {
+  return storage_->heap_profile_mappings().size();
+}
+
+int HeapProfileMappingTable::BestIndex(const QueryConstraints&,
+                                       BestIndexInfo* info) {
+  info->order_by_consumed = true;
+  return SQLITE_OK;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/heap_profile_mapping_table.h b/src/trace_processor/heap_profile_mapping_table.h
new file mode 100644
index 0000000..ffa52b2
--- /dev/null
+++ b/src/trace_processor/heap_profile_mapping_table.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 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_HEAP_PROFILE_MAPPING_TABLE_H_
+#define SRC_TRACE_PROCESSOR_HEAP_PROFILE_MAPPING_TABLE_H_
+
+#include "src/trace_processor/storage_table.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class HeapProfileMappingTable : public StorageTable {
+ public:
+  static void RegisterTable(sqlite3* db, const TraceStorage* storage);
+
+  HeapProfileMappingTable(sqlite3*, const TraceStorage*);
+
+  // StorageTable implementation.
+  StorageSchema CreateStorageSchema() override;
+  uint32_t RowCount() override;
+  int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
+
+ private:
+  const TraceStorage* const storage_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_HEAP_PROFILE_MAPPING_TABLE_H_
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index 5cf13a9..50bd57f 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -669,8 +669,10 @@
                                                 ConstBytes blob,
                                                 bool grow) {
   protos::pbzero::IonHeapGrowFtraceEvent::Decoder ion(blob.data, blob.size);
-  int64_t total_bytes = ion.total_allocated();
   int64_t change_bytes = static_cast<int64_t>(ion.len()) * (grow ? 1 : -1);
+  // The total_allocated ftrace event reports the value before the
+  // atomic_long_add / sub takes place.
+  int64_t total_bytes = ion.total_allocated() + change_bytes;
   StringId global_name_id = ion_total_unknown_id_;
   StringId change_name_id = ion_change_unknown_id_;
 
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 4313b2d..40a79e8 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -33,6 +33,10 @@
 #include "src/trace_processor/event_tracker.h"
 #include "src/trace_processor/fuchsia_trace_parser.h"
 #include "src/trace_processor/fuchsia_trace_tokenizer.h"
+#include "src/trace_processor/heap_profile_allocation_table.h"
+#include "src/trace_processor/heap_profile_callsite_table.h"
+#include "src/trace_processor/heap_profile_frame_table.h"
+#include "src/trace_processor/heap_profile_mapping_table.h"
 #include "src/trace_processor/heap_profile_tracker.h"
 #include "src/trace_processor/instants_table.h"
 #include "src/trace_processor/metrics/metrics.h"
@@ -248,6 +252,10 @@
   StatsTable::RegisterTable(*db_, context_.storage.get());
   AndroidLogsTable::RegisterTable(*db_, context_.storage.get());
   RawTable::RegisterTable(*db_, context_.storage.get());
+  HeapProfileAllocationTable::RegisterTable(*db_, context_.storage.get());
+  HeapProfileCallsiteTable::RegisterTable(*db_, context_.storage.get());
+  HeapProfileFrameTable::RegisterTable(*db_, context_.storage.get());
+  HeapProfileMappingTable::RegisterTable(*db_, context_.storage.get());
 }
 
 TraceProcessorImpl::~TraceProcessorImpl() {
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 36f8164..6c49114 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -599,6 +599,8 @@
       }
     };
 
+    uint32_t size() const { return static_cast<uint32_t>(names_.size()); }
+
     int64_t Insert(const Row& row) {
       names_.emplace_back(row.name_id);
       mappings_.emplace_back(row.mapping_row);
@@ -629,6 +631,8 @@
       }
     };
 
+    uint32_t size() const { return static_cast<uint32_t>(frame_ids_.size()); }
+
     int64_t Insert(const Row& row) {
       frame_depths_.emplace_back(row.depth);
       parent_callsite_ids_.emplace_back(row.parent_id);
@@ -665,6 +669,8 @@
       }
     };
 
+    uint32_t size() const { return static_cast<uint32_t>(names_.size()); }
+
     int64_t Insert(const Row& row) {
       build_ids_.emplace_back(row.build_id);
       offsets_.emplace_back(row.offset);
@@ -701,6 +707,8 @@
       int64_t size;
     };
 
+    uint32_t size() const { return static_cast<uint32_t>(timestamps_.size()); }
+
     void Insert(const Row& row) {
       timestamps_.emplace_back(row.timestamp);
       pids_.emplace_back(row.pid);
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 88b5081..e6905cd 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -259,7 +259,9 @@
           cpu,
         }
       }));
+    }
 
+    for (let cpu = 0; cpu < numCpus; cpu++) {
       // Only add a cpu freq track if we have
       // cpu freq data.
       // TODO(taylori): Find a way to display cpu idle