Merge "compact sched_waking: cfg/trace protos"
diff --git a/Android.bp b/Android.bp
index d93b0c1..bad324b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -33,6 +33,7 @@
     "src/trace_processor/metrics/android/android_startup_launches.sql",
     "src/trace_processor/metrics/android/android_task_state.sql",
     "src/trace_processor/metrics/android/heap_profile_callsites.sql",
+    "src/trace_processor/metrics/android/java_heap_stats.sql",
     "src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql",
     "src/trace_processor/metrics/android/process_mem.sql",
     "src/trace_processor/metrics/android/process_unagg_mem_view.sql",
@@ -2397,6 +2398,7 @@
     "protos/perfetto/metrics/android/cpu_metric.proto",
     "protos/perfetto/metrics/android/heap_profile_callsites.proto",
     "protos/perfetto/metrics/android/ion_metric.proto",
+    "protos/perfetto/metrics/android/java_heap_stats.proto",
     "protos/perfetto/metrics/android/lmk_metric.proto",
     "protos/perfetto/metrics/android/mem_metric.proto",
     "protos/perfetto/metrics/android/mem_unagg_metric.proto",
@@ -2416,6 +2418,7 @@
     "external/perfetto/protos/perfetto/metrics/android/cpu_metric.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/heap_profile_callsites.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/ion_metric.pbzero.cc",
+    "external/perfetto/protos/perfetto/metrics/android/java_heap_stats.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/lmk_metric.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/mem_metric.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/mem_unagg_metric.pbzero.cc",
@@ -2435,6 +2438,7 @@
     "protos/perfetto/metrics/android/cpu_metric.proto",
     "protos/perfetto/metrics/android/heap_profile_callsites.proto",
     "protos/perfetto/metrics/android/ion_metric.proto",
+    "protos/perfetto/metrics/android/java_heap_stats.proto",
     "protos/perfetto/metrics/android/lmk_metric.proto",
     "protos/perfetto/metrics/android/mem_metric.proto",
     "protos/perfetto/metrics/android/mem_unagg_metric.proto",
@@ -2454,6 +2458,7 @@
     "external/perfetto/protos/perfetto/metrics/android/cpu_metric.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/heap_profile_callsites.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/ion_metric.pbzero.h",
+    "external/perfetto/protos/perfetto/metrics/android/java_heap_stats.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/lmk_metric.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/mem_metric.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/mem_unagg_metric.pbzero.h",
@@ -4093,7 +4098,6 @@
   name: "perfetto_src_base_unittests",
   srcs: [
     "src/base/circular_queue_unittest.cc",
-    "src/base/copyable_ptr_unittest.cc",
     "src/base/metatrace_unittest.cc",
     "src/base/no_destructor_unittest.cc",
     "src/base/optional_unittest.cc",
@@ -4502,6 +4506,7 @@
 filegroup {
   name: "perfetto_src_protozero_unittests",
   srcs: [
+    "src/protozero/copyable_ptr_unittest.cc",
     "src/protozero/message_handle_unittest.cc",
     "src/protozero/message_unittest.cc",
     "src/protozero/proto_decoder_unittest.cc",
diff --git a/BUILD b/BUILD
index 562fb80..8dd4ff4 100644
--- a/BUILD
+++ b/BUILD
@@ -208,7 +208,6 @@
     srcs = [
         "include/perfetto/base/build_config.h",
         "include/perfetto/base/compiler.h",
-        "include/perfetto/base/copyable_ptr.h",
         "include/perfetto/base/export.h",
         "include/perfetto/base/logging.h",
         "include/perfetto/base/task_runner.h",
@@ -346,6 +345,7 @@
     name = "include_perfetto_protozero_protozero",
     srcs = [
         "include/perfetto/protozero/contiguous_memory_range.h",
+        "include/perfetto/protozero/copyable_ptr.h",
         "include/perfetto/protozero/field.h",
         "include/perfetto/protozero/message.h",
         "include/perfetto/protozero/message_handle.h",
@@ -576,6 +576,7 @@
         "src/trace_processor/metrics/android/android_startup_launches.sql",
         "src/trace_processor/metrics/android/android_task_state.sql",
         "src/trace_processor/metrics/android/heap_profile_callsites.sql",
+        "src/trace_processor/metrics/android/java_heap_stats.sql",
         "src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql",
         "src/trace_processor/metrics/android/process_mem.sql",
         "src/trace_processor/metrics/android/process_unagg_mem_view.sql",
@@ -1616,6 +1617,7 @@
         "protos/perfetto/metrics/android/cpu_metric.proto",
         "protos/perfetto/metrics/android/heap_profile_callsites.proto",
         "protos/perfetto/metrics/android/ion_metric.proto",
+        "protos/perfetto/metrics/android/java_heap_stats.proto",
         "protos/perfetto/metrics/android/lmk_metric.proto",
         "protos/perfetto/metrics/android/mem_metric.proto",
         "protos/perfetto/metrics/android/mem_unagg_metric.proto",
diff --git a/include/perfetto/base/BUILD.gn b/include/perfetto/base/BUILD.gn
index 9dc0893..e490551 100644
--- a/include/perfetto/base/BUILD.gn
+++ b/include/perfetto/base/BUILD.gn
@@ -18,7 +18,6 @@
   sources = [
     "build_config.h",
     "compiler.h",
-    "copyable_ptr.h",
     "export.h",
     "logging.h",
     "task_runner.h",
diff --git a/include/perfetto/base/compiler.h b/include/perfetto/base/compiler.h
index fa44b6b..0b2efbf 100644
--- a/include/perfetto/base/compiler.h
+++ b/include/perfetto/base/compiler.h
@@ -57,6 +57,15 @@
 #define PERFETTO_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
 #endif
 
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __PRETTY_FUNCTION__
+#elif defined(_MSC_VER)
+#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __FUNCSIG__
+#else
+#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() \
+  static_assert(false, "Not implemented for this compiler")
+#endif
+
 namespace perfetto {
 namespace base {
 
diff --git a/include/perfetto/protozero/BUILD.gn b/include/perfetto/protozero/BUILD.gn
index 7749684..994ff60 100644
--- a/include/perfetto/protozero/BUILD.gn
+++ b/include/perfetto/protozero/BUILD.gn
@@ -18,6 +18,7 @@
   ]
   sources = [
     "contiguous_memory_range.h",
+    "copyable_ptr.h",
     "field.h",
     "message.h",
     "message_handle.h",
diff --git a/include/perfetto/base/copyable_ptr.h b/include/perfetto/protozero/copyable_ptr.h
similarity index 92%
rename from include/perfetto/base/copyable_ptr.h
rename to include/perfetto/protozero/copyable_ptr.h
index 236382f..2fe5ff6 100644
--- a/include/perfetto/base/copyable_ptr.h
+++ b/include/perfetto/protozero/copyable_ptr.h
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-#ifndef INCLUDE_PERFETTO_BASE_COPYABLE_PTR_H_
-#define INCLUDE_PERFETTO_BASE_COPYABLE_PTR_H_
+#ifndef INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_
+#define INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_
 
 #include <memory>
 
-namespace perfetto {
-namespace base {
+namespace protozero {
 
 // This class is essentially a std::vector<T> of fixed size = 1.
 // It's a pointer wrapper with deep copying and deep equality comparison.
@@ -83,7 +82,6 @@
   std::unique_ptr<T> ptr_;
 };
 
-}  // namespace base
-}  // namespace perfetto
+}  // namespace protozero
 
-#endif  // INCLUDE_PERFETTO_BASE_COPYABLE_PTR_H_
+#endif  // INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_
diff --git a/include/perfetto/tracing/internal/track_event_internal.h b/include/perfetto/tracing/internal/track_event_internal.h
index 9cbdf34..c303938 100644
--- a/include/perfetto/tracing/internal/track_event_internal.h
+++ b/include/perfetto/tracing/internal/track_event_internal.h
@@ -24,15 +24,6 @@
 
 #include <unordered_map>
 
-// Only used to DCHECK that one interned data field isn't accidentally shared by
-// multiple TrackEventInternedData subclasses.
-// TODO(skyostil): Add __FUNCSIG__ for MSVC.
-#if PERFETTO_DCHECK_IS_ON() && defined(__GNUC__)
-#define PERFETTO_INTERNAL_TYPE_IDENTIFIER __PRETTY_FUNCTION__
-#else  // PERFETTO_DCHECK_IS_ON() && defined(__GNUC__)
-#define PERFETTO_INTERNAL_TYPE_IDENTIFIER ""
-#endif  // PERFETTO_DCHECK_IS_ON() && defined(__GNUC__)
-
 namespace perfetto {
 class DataSourceConfig;
 class DataSourceDescriptor;
diff --git a/include/perfetto/tracing/track_event_interned_data_index.h b/include/perfetto/tracing/track_event_interned_data_index.h
index 197081b..e1ef7ee 100644
--- a/include/perfetto/tracing/track_event_interned_data_index.h
+++ b/include/perfetto/tracing/track_event_interned_data_index.h
@@ -19,6 +19,8 @@
 
 #include "perfetto/tracing/internal/track_event_internal.h"
 
+#include "perfetto/base/compiler.h"
+
 #include <map>
 #include <type_traits>
 #include <unordered_map>
@@ -194,11 +196,12 @@
     for (const auto& entry : incremental_state->interned_data_indices) {
       if (entry.first == FieldNumber) {
 #if PERFETTO_DCHECK_IS_ON()
-        if (strcmp(PERFETTO_INTERNAL_TYPE_IDENTIFIER, entry.second->type_id_)) {
+        if (strcmp(PERFETTO_DEBUG_FUNCTION_IDENTIFIER(),
+                   entry.second->type_id_)) {
           PERFETTO_FATAL(
               "Interned data accessed under different types! Previous type: "
               "%s. New type: %s.",
-              entry.second->type_id_, PERFETTO_INTERNAL_TYPE_IDENTIFIER);
+              entry.second->type_id_, PERFETTO_DEBUG_FUNCTION_IDENTIFIER());
         }
 #endif  // PERFETTO_DCHECK_IS_ON()
         return reinterpret_cast<InternedDataType*>(entry.second.get());
@@ -210,7 +213,7 @@
         entry.first = FieldNumber;
         entry.second.reset(new InternedDataType());
 #if PERFETTO_DCHECK_IS_ON()
-        entry.second->type_id_ = PERFETTO_INTERNAL_TYPE_IDENTIFIER;
+        entry.second->type_id_ = PERFETTO_DEBUG_FUNCTION_IDENTIFIER();
 #endif  // PERFETTO_DCHECK_IS_ON()
         return reinterpret_cast<InternedDataType*>(entry.second.get());
       }
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index 9d1d001..41353b0 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -20,6 +20,7 @@
     "cpu_metric.proto",
     "heap_profile_callsites.proto",
     "ion_metric.proto",
+    "java_heap_stats.proto",
     "lmk_metric.proto",
     "mem_metric.proto",
     "mem_unagg_metric.proto",
diff --git a/protos/perfetto/metrics/android/heap_profile_callsites.proto b/protos/perfetto/metrics/android/heap_profile_callsites.proto
index ce0bdca..d19bba3 100644
--- a/protos/perfetto/metrics/android/heap_profile_callsites.proto
+++ b/protos/perfetto/metrics/android/heap_profile_callsites.proto
@@ -51,10 +51,16 @@
   }
 
   // Callsites per process instance.
+  // Next id: 6
   message InstanceStats {
     optional uint32 pid = 1;
     optional string process_name = 2;
     repeated Callsite callsites = 3;
+
+    // Bytes allocated via malloc but not freed.
+    optional int64 profile_delta_bytes = 4;
+    // Bytes allocated via malloc irrespective of whether they were freed.
+    optional int64 profile_total_bytes = 5;
   }
 
   repeated InstanceStats instance_stats = 1;
diff --git a/protos/perfetto/metrics/android/java_heap_stats.proto b/protos/perfetto/metrics/android/java_heap_stats.proto
new file mode 100644
index 0000000..a5e1513
--- /dev/null
+++ b/protos/perfetto/metrics/android/java_heap_stats.proto
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+message JavaHeapStats {
+  message Sample {
+    optional int64 ts = 1;
+    optional int64 heap_size = 2;
+    optional int64 reachable_heap_size = 3;
+  }
+
+  // Heap stats per process. One sample per dump (can be > 1 if continuous
+  // dump is enabled).
+  message InstanceStats {
+    optional uint32 upid = 1;
+    optional string process_name = 2;
+    repeated Sample samples = 3;
+  }
+
+  repeated InstanceStats instance_stats = 1;
+}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index a197a38..508e830 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -31,6 +31,7 @@
 import "protos/perfetto/metrics/android/heap_profile_callsites.proto";
 import "protos/perfetto/metrics/android/package_list.proto";
 import "protos/perfetto/metrics/android/unsymbolized_frames.proto";
+import "protos/perfetto/metrics/android/java_heap_stats.proto";
 
 // Trace processor metadata (taken from the stats table schema and contents).
 // TODO: perhaps add the other columns once we have enum support
@@ -48,7 +49,7 @@
 
 // Root message for all Perfetto-based metrics.
 //
-// Next id: 17
+// Next id: 18
 message TraceMetrics {
   reserved 4, 13, 14;
 
@@ -94,6 +95,9 @@
   // Returns stack frames missing symbols.
   optional UnsymbolizedFrames unsymbolized_frames = 15;
 
+  // If the trace contains a heap graph, output allocation statistics.
+  optional JavaHeapStats java_heap_stats = 17;
+
   // Demo extensions.
   extensions 450 to 499;
 
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index 9f53d4b..0e7a0d0 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -122,7 +122,6 @@
 
   sources = [
     "circular_queue_unittest.cc",
-    "copyable_ptr_unittest.cc",
     "no_destructor_unittest.cc",
     "optional_unittest.cc",
     "paged_memory_unittest.cc",
diff --git a/src/protozero/BUILD.gn b/src/protozero/BUILD.gn
index bcc34e0..b2cc13a 100644
--- a/src/protozero/BUILD.gn
+++ b/src/protozero/BUILD.gn
@@ -57,6 +57,7 @@
     "../base:test_support",
   ]
   sources = [
+    "copyable_ptr_unittest.cc",
     "message_handle_unittest.cc",
     "message_unittest.cc",
     "proto_decoder_unittest.cc",
diff --git a/src/base/copyable_ptr_unittest.cc b/src/protozero/copyable_ptr_unittest.cc
similarity index 94%
rename from src/base/copyable_ptr_unittest.cc
rename to src/protozero/copyable_ptr_unittest.cc
index ecbd1ef..d9be950 100644
--- a/src/base/copyable_ptr_unittest.cc
+++ b/src/protozero/copyable_ptr_unittest.cc
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-#include "perfetto/base/copyable_ptr.h"
+#include "perfetto/protozero/copyable_ptr.h"
 
 #include "test/gtest_and_gmock.h"
 
-namespace perfetto {
-namespace base {
+namespace protozero {
 namespace {
 
 struct X {
@@ -116,5 +115,4 @@
 }
 
 }  // namespace
-}  // namespace base
-}  // namespace perfetto
+}  // namespace protozero
diff --git a/src/protozero/protoc_plugin/cppgen_plugin.cc b/src/protozero/protoc_plugin/cppgen_plugin.cc
index b396a67..e50c01e 100644
--- a/src/protozero/protoc_plugin/cppgen_plugin.cc
+++ b/src/protozero/protoc_plugin/cppgen_plugin.cc
@@ -121,7 +121,7 @@
   h_printer.Print("#include <vector>\n");
   h_printer.Print("#include <string>\n");
   h_printer.Print("#include <type_traits>\n\n");
-  h_printer.Print("#include \"perfetto/base/copyable_ptr.h\"\n");
+  h_printer.Print("#include \"perfetto/protozero/copyable_ptr.h\"\n");
   h_printer.Print("#include \"perfetto/base/export.h\"\n\n");
 
   cc_printer.Print(kHeader);
@@ -426,7 +426,7 @@
     } else if (!field->is_repeated()) {
       std::string type = GetCppType(field, false);
       if (field->type() == TYPE_MESSAGE) {
-        type = "::perfetto::base::CopyablePtr<" + type + ">";
+        type = "::protozero::CopyablePtr<" + type + ">";
         p->Print("$t$ $n$_;\n", "t", type, "n", field->lowercase_name());
       } else {
         p->Print("$t$ $n$_{};\n", "t", type, "n", field->lowercase_name());
diff --git a/src/trace_processor/android_logs_table.cc b/src/trace_processor/android_logs_table.cc
index b104280..d58508b 100644
--- a/src/trace_processor/android_logs_table.cc
+++ b/src/trace_processor/android_logs_table.cc
@@ -47,14 +47,13 @@
 int AndroidLogsTable::BestIndex(const QueryConstraints& qc,
                                 BestIndexInfo* info) {
   info->estimated_cost = static_cast<uint32_t>(storage_->android_logs().size());
-
-  info->order_by_consumed = true;
+  info->sqlite_omit_order_by = true;
 
   // Only the string columns are handled by SQLite.
   size_t tag_index = schema().ColumnIndexFromName("tag");
   size_t msg_index = schema().ColumnIndexFromName("msg");
   for (size_t i = 0; i < qc.constraints().size(); i++) {
-    info->omit[i] =
+    info->constraint_info[i].sqlite_omit =
         qc.constraints()[i].iColumn != static_cast<int>(tag_index) &&
         qc.constraints()[i].iColumn != static_cast<int>(msg_index);
   }
diff --git a/src/trace_processor/counter_values_table.cc b/src/trace_processor/counter_values_table.cc
index fc536b4..7176fd3 100644
--- a/src/trace_processor/counter_values_table.cc
+++ b/src/trace_processor/counter_values_table.cc
@@ -24,14 +24,14 @@
 
 void CounterValuesTable::RegisterTable(sqlite3* db,
                                        const TraceStorage* storage) {
-  SqliteTable::Register<CounterValuesTable>(db, storage, "counter_values");
+  SqliteTable::Register<CounterValuesTable>(db, storage, "counter");
 }
 
 StorageSchema CounterValuesTable::CreateStorageSchema() {
   const auto& cs = storage_->counter_values();
   return StorageSchema::Builder()
       .AddGenericNumericColumn("id", RowIdAccessor(TableId::kCounterValues))
-      .AddNumericColumn("counter_id", &cs.track_ids(), &cs.rows_for_track_id())
+      .AddNumericColumn("track_id", &cs.track_ids(), &cs.rows_for_track_id())
       .AddOrderedNumericColumn("ts", &cs.timestamps())
       .AddNumericColumn("value", &cs.values())
       .AddNumericColumn("arg_set_id", &cs.arg_set_ids())
@@ -45,17 +45,15 @@
 int CounterValuesTable::BestIndex(const QueryConstraints& qc,
                                   BestIndexInfo* info) {
   info->estimated_cost = EstimateCost(qc);
-
-  info->order_by_consumed = true;
-  for (size_t i = 0; i < qc.constraints().size(); i++) {
-    info->omit[i] = true;
-  }
+  info->sqlite_omit_order_by = true;
+  for (auto& c_info : info->constraint_info)
+    c_info.sqlite_omit = true;
 
   return SQLITE_OK;
 }
 
 uint32_t CounterValuesTable::EstimateCost(const QueryConstraints& qc) {
-  if (HasEqConstraint(qc, "counter_id"))
+  if (HasEqConstraint(qc, "track_id"))
     return RowCount() / 100;
   return RowCount();
 }
diff --git a/src/trace_processor/cpu_profile_stack_sample_table.cc b/src/trace_processor/cpu_profile_stack_sample_table.cc
index bb51404..1226020 100644
--- a/src/trace_processor/cpu_profile_stack_sample_table.cc
+++ b/src/trace_processor/cpu_profile_stack_sample_table.cc
@@ -46,7 +46,7 @@
 
 int CpuProfileStackSampleTable::BestIndex(const QueryConstraints& qc,
                                           BestIndexInfo* info) {
-  info->order_by_consumed = true;
+  info->sqlite_omit_order_by = true;
   info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
   return SQLITE_OK;
 }
diff --git a/src/trace_processor/heap_profile_allocation_table.cc b/src/trace_processor/heap_profile_allocation_table.cc
index 8bd050e..dcdb825 100644
--- a/src/trace_processor/heap_profile_allocation_table.cc
+++ b/src/trace_processor/heap_profile_allocation_table.cc
@@ -48,7 +48,7 @@
 
 int HeapProfileAllocationTable::BestIndex(const QueryConstraints& qc,
                                           BestIndexInfo* info) {
-  info->order_by_consumed = true;
+  info->sqlite_omit_order_by = true;
   info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
   return SQLITE_OK;
 }
diff --git a/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc b/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
index 74b98e7..29b2a3f 100644
--- a/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
+++ b/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
@@ -356,6 +356,37 @@
   EXPECT_EQ(delegate.UniqueRetained(2), 3);
 }
 
+// We defined unique_retained as follows:
+//       the number of bytes that are only retained through this object.
+//       if this object were destroyed, this many bytes would be freed up.
+// The following test-case is a counter-example for the current
+// implementation.
+//    2<->3  |
+//    ^      |
+//    |      |
+//    1      |
+TEST(HeapGraphWalkerTest, DISABLED_UnreachableComponent) {
+  HeapGraphWalkerTestDelegate delegate;
+  HeapGraphWalker walker(&delegate);
+  walker.AddNode(1, 1);
+  walker.AddNode(2, 2);
+  walker.AddNode(3, 3);
+
+  walker.AddEdge(1, 2);
+  walker.AddEdge(2, 3);
+  walker.AddEdge(3, 2);
+
+  walker.MarkRoot(1);
+  walker.CalculateRetained();
+
+  EXPECT_EQ(delegate.Retained(1), 6);
+  EXPECT_EQ(delegate.Retained(2), 5);
+  EXPECT_EQ(delegate.Retained(3), 5);
+
+  EXPECT_EQ(delegate.UniqueRetained(1), 6);
+  EXPECT_EQ(delegate.UniqueRetained(2), 5);
+  EXPECT_EQ(delegate.UniqueRetained(3), 3);
+}
 }  // namespace
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/packet_sequence_state.h b/src/trace_processor/importers/proto/packet_sequence_state.h
index 8ee597b..b6bc5a6 100644
--- a/src/trace_processor/importers/proto/packet_sequence_state.h
+++ b/src/trace_processor/importers/proto/packet_sequence_state.h
@@ -22,6 +22,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include "perfetto/base/compiler.h"
 #include "perfetto/protozero/proto_decoder.h"
 #include "src/trace_processor/stack_profile_tracker.h"
 #include "src/trace_processor/trace_blob_view.h"
@@ -31,13 +32,13 @@
 namespace perfetto {
 namespace trace_processor {
 
-#if PERFETTO_DCHECK_IS_ON() && defined(__GNUC__)
-// When called from GetOrCreateDecoder(), __PRETTY_FUNCTION__ (supported by GCC
-// + clang) should include the stringified name of the MessageType.
-#define PERFETTO_TYPE_IDENTIFIER __PRETTY_FUNCTION__
-#else  // PERFETTO_DCHECK_IS_ON() && defined(__GNUC__)
+#if PERFETTO_DCHECK_IS_ON()
+// When called from GetOrCreateDecoder(), should include the stringified name of
+// the MessageType.
+#define PERFETTO_TYPE_IDENTIFIER PERFETTO_DEBUG_FUNCTION_IDENTIFIER()
+#else  // PERFETTO_DCHECK_IS_ON()
 #define PERFETTO_TYPE_IDENTIFIER nullptr
-#endif  // PERFETTO_DCHECK_IS_ON() && defined(__GNUC__)
+#endif  // PERFETTO_DCHECK_IS_ON()
 
 class PacketSequenceState {
  public:
diff --git a/src/trace_processor/instants_table.cc b/src/trace_processor/instants_table.cc
index 279e36c..e0a52ad 100644
--- a/src/trace_processor/instants_table.cc
+++ b/src/trace_processor/instants_table.cc
@@ -50,13 +50,13 @@
 int InstantsTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
   info->estimated_cost =
       static_cast<uint32_t>(storage_->instants().instant_count());
+  info->sqlite_omit_order_by = true;
 
   // Only the string columns are handled by SQLite
-  info->order_by_consumed = true;
   size_t name_index = schema().ColumnIndexFromName("name");
   size_t ref_type_index = schema().ColumnIndexFromName("ref_type");
   for (size_t i = 0; i < qc.constraints().size(); i++) {
-    info->omit[i] =
+    info->constraint_info[i].sqlite_omit =
         qc.constraints()[i].iColumn != static_cast<int>(name_index) &&
         qc.constraints()[i].iColumn != static_cast<int>(ref_type_index);
   }
diff --git a/src/trace_processor/metrics/BUILD.gn b/src/trace_processor/metrics/BUILD.gn
index bfa95de..28d6f01 100644
--- a/src/trace_processor/metrics/BUILD.gn
+++ b/src/trace_processor/metrics/BUILD.gn
@@ -32,6 +32,7 @@
   "android/android_startup_cpu.sql",
   "android/android_package_list.sql",
   "android/heap_profile_callsites.sql",
+  "android/java_heap_stats.sql",
   "android/process_unagg_mem_view.sql",
   "android/process_mem.sql",
   "android/mem_stats_priority_breakdown.sql",
diff --git a/src/trace_processor/metrics/android/heap_profile_callsites.sql b/src/trace_processor/metrics/android/heap_profile_callsites.sql
index a0cd0c4..ce2aeb4 100644
--- a/src/trace_processor/metrics/android/heap_profile_callsites.sql
+++ b/src/trace_processor/metrics/android/heap_profile_callsites.sql
@@ -14,6 +14,17 @@
 -- limitations under the License.
 --
 
+CREATE VIEW memory_delta AS
+SELECT upid, SUM(size) AS delta
+FROM heap_profile_allocation
+GROUP BY 1;
+
+CREATE VIEW memory_total AS
+SELECT upid, SUM(size) AS total
+FROM heap_profile_allocation
+WHERE size > 0
+GROUP BY 1;
+
 -- Join frames with symbols and mappings to get a textual representation.
 CREATE TABLE symbolized_frame AS
 SELECT
@@ -205,9 +216,14 @@
 SELECT HeapProfileCallsites_InstanceStats(
     'pid', process.pid,
     'process_name', process.name,
-    'callsites', repeated_callsite_proto
+    'callsites', repeated_callsite_proto,
+    'profile_delta_bytes', memory_delta.delta,
+    'profile_total_bytes', memory_total.total
 ) AS instance_stats_proto
-FROM process_callsite_proto JOIN process USING (upid);
+FROM process_callsite_proto
+JOIN memory_total USING (upid)
+JOIN memory_delta USING (upid)
+JOIN process USING (upid);
 
 CREATE VIEW heap_profile_callsites_output AS
 SELECT HeapProfileCallsites(
diff --git a/src/trace_processor/metrics/android/java_heap_stats.sql b/src/trace_processor/metrics/android/java_heap_stats.sql
new file mode 100644
index 0000000..d8f2f34
--- /dev/null
+++ b/src/trace_processor/metrics/android/java_heap_stats.sql
@@ -0,0 +1,58 @@
+--
+-- Copyright 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
+--
+--     https://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.
+--
+
+CREATE VIEW total_size_samples AS
+SELECT upid, graph_sample_ts, SUM(self_size) AS total_size
+FROM heap_graph_object
+GROUP BY 1, 2;
+
+CREATE VIEW total_reachable_size_samples AS
+SELECT upid, graph_sample_ts, SUM(self_size) AS total_reachable_size
+FROM heap_graph_object
+WHERE reachable = TRUE
+GROUP BY 1, 2;
+
+CREATE TABLE heap_graph_samples AS
+SELECT upid, graph_sample_ts, total_size, total_reachable_size
+FROM total_size_samples JOIN total_reachable_size_samples
+USING (upid, graph_sample_ts);
+
+CREATE VIEW heap_graph_sample_protos AS
+SELECT
+  upid,
+  JavaHeapStats_Sample(
+    'ts', graph_sample_ts,
+    'heap_size', total_size,
+    'reachable_heap_size', total_reachable_size
+  ) sample_proto
+FROM heap_graph_samples;
+
+CREATE TABLE heap_graph_instance_stats AS
+SELECT
+  upid,
+  process.name process_name,
+  RepeatedField(sample_proto) AS sample_protos
+FROM heap_graph_sample_protos JOIN process USING (upid)
+GROUP BY 1, 2;
+
+CREATE VIEW java_heap_stats_output AS
+SELECT JavaHeapStats(
+  'instance_stats', RepeatedField(JavaHeapStats_InstanceStats(
+    'upid', upid,
+    'process_name', process_name,
+    'samples', sample_protos
+  )))
+FROM heap_graph_instance_stats;
diff --git a/src/trace_processor/metrics/metrics.descriptor.h b/src/trace_processor/metrics/metrics.descriptor.h
index 5700d0b..df7696c 100644
--- a/src/trace_processor/metrics/metrics.descriptor.h
+++ b/src/trace_processor/metrics/metrics.descriptor.h
@@ -12,14 +12,14 @@
 // SHA1(tools/gen_binary_descriptors)
 // 192b582ae52bb07b3d3ba66a94bcfd3127a5f42f
 // SHA1(protos/perfetto/metrics/metrics.proto)
-// 3617cd492d3a717441de21b0b04ce363e0669f57
+// 4279eeace6a7d9647e484e65b8265ea211a02b6c
 
 // This is the proto Metrics encoded as a ProtoFileDescriptor to allow
 // for reflection without libprotobuf full/non-lite protos.
 
 namespace perfetto {
 
-constexpr std::array<uint8_t, 9666> kMetricsDescriptor{
+constexpr std::array<uint8_t, 10312> kMetricsDescriptor{
     {0x0a, 0x98, 0x03, 0x0a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
      0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
      0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
@@ -540,14 +540,14 @@
      0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54,
      0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
      0x0c, 0x74, 0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
-     0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xd7, 0x06, 0x0a, 0x3c, 0x70, 0x72,
+     0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xb7, 0x07, 0x0a, 0x3c, 0x70, 0x72,
      0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
      0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
      0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70,
      0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73,
      0x69, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
      0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x22, 0x81, 0x06, 0x0a, 0x14, 0x48, 0x65, 0x61, 0x70,
+     0x74, 0x6f, 0x73, 0x22, 0xe1, 0x06, 0x0a, 0x14, 0x48, 0x65, 0x61, 0x70,
      0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
      0x69, 0x74, 0x65, 0x73, 0x12, 0x5a, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74,
      0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01,
@@ -599,7 +599,7 @@
      0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
      0x69, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
      0x73, 0x52, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x41, 0x6c, 0x6c, 0x6f,
-     0x63, 0x73, 0x1a, 0x92, 0x01, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61,
+     0x63, 0x73, 0x1a, 0xf2, 0x01, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61,
      0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03,
      0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x70,
      0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
@@ -611,7 +611,15 @@
      0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69,
      0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e,
      0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x52, 0x09, 0x63, 0x61,
-     0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a,
+     0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x70,
+     0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
+     0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x11, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x6c,
+     0x74, 0x61, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x70,
+     0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c,
+     0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x11, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x6f, 0x74,
+     0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a,
      0x8c, 0x02, 0x0a, 0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
      0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
      0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
@@ -656,176 +664,222 @@
      0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61,
      0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
      0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x02, 0x48,
-     0x03, 0x0a, 0xee, 0x0f, 0x0a, 0x25, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x1a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x62, 0x61,
-     0x74, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x2f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x75, 0x6e, 0x61,
-     0x67, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x1a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f,
-     0x77, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x69, 0x6f, 0x6e, 0x5f, 0x6d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
-     0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
-     0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b,
-     0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x1a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70,
-     0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x34, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75,
-     0x70, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x1a, 0x3c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
-     0x68, 0x65, 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
-     0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x03, 0x0a, 0xa4, 0x03, 0x0a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
      0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
      0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69,
-     0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x39, 0x70, 0x72,
+     0x64, 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f,
+     0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+     0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x22, 0xd5, 0x02, 0x0a, 0x0d, 0x4a, 0x61, 0x76,
+     0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x53,
+     0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73,
+     0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c,
+     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61,
+     0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61,
+     0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x69, 0x6e,
+     0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x1a,
+     0x65, 0x0a, 0x06, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x0e, 0x0a,
+     0x02, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x74,
+     0x73, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69,
+     0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x68, 0x65,
+     0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65,
+     0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x70,
+     0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x11, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x48, 0x65,
+     0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x87, 0x01, 0x0a, 0x0d, 0x49,
+     0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73,
+     0x12, 0x12, 0x0a, 0x04, 0x75, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+     0x28, 0x0d, 0x52, 0x04, 0x75, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x07, 0x73,
+     0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
+     0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x48,
+     0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x53, 0x61, 0x6d,
+     0x70, 0x6c, 0x65, 0x52, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73,
+     0x42, 0x02, 0x48, 0x03, 0x0a, 0xed, 0x10, 0x0a, 0x25, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74,
+     0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x1a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
+     0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x2f, 0x62, 0x61, 0x74, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
+     0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x2f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72,
      0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
      0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x75, 0x6e, 0x73, 0x79, 0x6d, 0x62,
-     0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
-     0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf1, 0x01, 0x0a, 0x0d,
-     0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
-     0x61, 0x12, 0x50, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x73,
-     0x74, 0x61, 0x74, 0x73, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01,
-     0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54,
-     0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
-     0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x65, 0x72, 0x72, 0x6f,
-     0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
-     0x2a, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x64, 0x75, 0x72,
-     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x0f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x44, 0x75, 0x72,
-     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74,
-     0x72, 0x61, 0x63, 0x65, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20,
-     0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x72, 0x61, 0x63, 0x65, 0x55, 0x75,
-     0x69, 0x64, 0x1a, 0x43, 0x0a, 0x05, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
-     0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-     0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69,
-     0x64, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x69, 0x64,
-     0x78, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03,
-     0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
-     0xb8, 0x08, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x73, 0x12, 0x48, 0x0a, 0x0c, 0x61, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x5f, 0x62, 0x61, 0x74, 0x74, 0x18, 0x05, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x65,
+     0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
+     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f,
+     0x75, 0x6e, 0x61, 0x67, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x34, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
+     0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
+     0x67, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x69, 0x6f,
+     0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
+     0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+     0x6c, 0x6d, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
+     0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x2f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
+     0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+     0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x74, 0x61,
+     0x72, 0x74, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3c, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+     0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+     0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66,
+     0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
+     0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x32, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
+     0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
+     0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
+     0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+     0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x75, 0x6e, 0x73,
+     0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72,
+     0x61, 0x6d, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
+     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6a, 0x61, 0x76, 0x61,
+     0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf1, 0x01, 0x0a, 0x0d, 0x54, 0x72,
+     0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12,
+     0x50, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61,
+     0x74, 0x73, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03,
+     0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61,
+     0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x45,
+     0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x53,
+     0x74, 0x61, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x2a, 0x0a,
+     0x11, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74,
+     0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x0f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74,
+     0x69, 0x6f, 0x6e, 0x4e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x72, 0x61,
+     0x63, 0x65, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+     0x09, 0x52, 0x09, 0x74, 0x72, 0x61, 0x63, 0x65, 0x55, 0x75, 0x69, 0x64,
+     0x1a, 0x43, 0x0a, 0x05, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x78,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x69, 0x64, 0x78, 0x12,
+     0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01,
+     0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x80, 0x09,
+     0x0a, 0x0c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69,
+     0x63, 0x73, 0x12, 0x48, 0x0a, 0x0c, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x5f, 0x62, 0x61, 0x74, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
+     0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+     0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x4d, 0x65, 0x74,
+     0x72, 0x69, 0x63, 0x52, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x42, 0x61, 0x74, 0x74, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x5f, 0x63, 0x70, 0x75, 0x18, 0x06, 0x20, 0x01, 0x28,
+     0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75,
+     0x12, 0x45, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f,
+     0x6d, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d,
+     0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52,
+     0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x12,
+     0x5c, 0x0a, 0x11, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6d,
+     0x65, 0x6d, 0x5f, 0x75, 0x6e, 0x61, 0x67, 0x67, 0x18, 0x0b, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
      0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x4d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x63, 0x70, 0x75, 0x18, 0x06, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e,
+     0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65,
+     0x74, 0x72, 0x69, 0x63, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x4d, 0x65, 0x6d, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x12, 0x55, 0x0a,
+     0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70, 0x61, 0x63,
+     0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0c, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
      0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43,
-     0x70, 0x75, 0x12, 0x45, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
-     0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65,
-     0x6d, 0x12, 0x5c, 0x0a, 0x11, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x75, 0x6e, 0x61, 0x67, 0x67, 0x18, 0x0b,
-     0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
-     0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64,
-     0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x12,
-     0x55, 0x0a, 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70,
-     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18,
-     0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61,
-     0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x12, 0x61, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69,
-     0x73, 0x74, 0x12, 0x5b, 0x0a, 0x16, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72,
-     0x6f, 0x77, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25,
-     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74,
-     0x68, 0x52, 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72,
-     0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x12,
-     0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x69,
-     0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70,
+     0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
+     0x4c, 0x69, 0x73, 0x74, 0x52, 0x12, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74,
+     0x12, 0x5b, 0x0a, 0x16, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x77,
+     0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70,
      0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f,
-     0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0b, 0x61,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6d, 0x6b, 0x18, 0x08,
-     0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x4c, 0x6d, 0x6b, 0x12, 0x4d, 0x0a, 0x10, 0x61, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x5f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18,
-     0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72,
-     0x52, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x50, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4e,
-     0x0a, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x73, 0x74,
-     0x61, 0x72, 0x74, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
-     0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x52, 0x0e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
-     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x5b, 0x0a, 0x16, 0x68, 0x65,
-     0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63,
-     0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61,
-     0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c,
-     0x73, 0x69, 0x74, 0x65, 0x73, 0x52, 0x14, 0x68, 0x65, 0x61, 0x70, 0x50,
+     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72,
+     0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x52,
+     0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x12, 0x42, 0x0a,
+     0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x69, 0x6f, 0x6e,
+     0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d,
+     0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+     0x69, 0x64, 0x49, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64,
+     0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6d, 0x6b, 0x18, 0x08, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
+     0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69,
+     0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d,
+     0x6b, 0x12, 0x4d, 0x0a, 0x10, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x5f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x07, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
+     0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61,
+     0x69, 0x6c, 0x73, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x50, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0f,
+     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72,
+     0x74, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
+     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+     0x52, 0x0e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61,
+     0x72, 0x74, 0x75, 0x70, 0x12, 0x5b, 0x0a, 0x16, 0x68, 0x65, 0x61, 0x70,
+     0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c,
+     0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b,
+     0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50,
      0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69,
-     0x74, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x63, 0x65,
-     0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20,
+     0x74, 0x65, 0x73, 0x52, 0x14, 0x68, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f,
+     0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
+     0x73, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x6d,
+     0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28,
+     0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63,
+     0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x74,
+     0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+     0x12, 0x54, 0x0a, 0x13, 0x75, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
+     0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18,
+     0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64,
+     0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x12, 0x75, 0x6e, 0x73, 0x79,
+     0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d,
+     0x65, 0x73, 0x12, 0x46, 0x0a, 0x0f, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68,
+     0x65, 0x61, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x11, 0x20,
      0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72,
-     0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52,
-     0x0d, 0x74, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
-     0x74, 0x61, 0x12, 0x54, 0x0a, 0x13, 0x75, 0x6e, 0x73, 0x79, 0x6d, 0x62,
-     0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
-     0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a,
-     0x65, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x12, 0x75, 0x6e,
-     0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72,
-     0x61, 0x6d, 0x65, 0x73, 0x2a, 0x06, 0x08, 0xc2, 0x03, 0x10, 0xf4, 0x03,
-     0x2a, 0x06, 0x08, 0xf4, 0x03, 0x10, 0xe9, 0x07, 0x4a, 0x04, 0x08, 0x04,
-     0x10, 0x05, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x4a, 0x04, 0x08, 0x0e,
-     0x10, 0x0f, 0x42, 0x02, 0x48, 0x03}};
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61,
+     0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52,
+     0x0d, 0x6a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61,
+     0x74, 0x73, 0x2a, 0x06, 0x08, 0xc2, 0x03, 0x10, 0xf4, 0x03, 0x2a, 0x06,
+     0x08, 0xf4, 0x03, 0x10, 0xe9, 0x07, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05,
+     0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x4a, 0x04, 0x08, 0x0e, 0x10, 0x0f,
+     0x42, 0x02, 0x48, 0x03}};
 
 }  // namespace perfetto
 
diff --git a/src/trace_processor/process_table.cc b/src/trace_processor/process_table.cc
index 9d0129a..c85177a 100644
--- a/src/trace_processor/process_table.cc
+++ b/src/trace_processor/process_table.cc
@@ -74,57 +74,56 @@
 
 int ProcessTable::Cursor::Filter(const QueryConstraints& qc,
                                  sqlite3_value** argv) {
-  min = 0;
-  max = static_cast<uint32_t>(storage_->process_count()) - 1;
-  desc = false;
+  min_ = 0;
+  max_ = static_cast<uint32_t>(storage_->process_count());
+  desc_ = false;
 
   for (size_t j = 0; j < qc.constraints().size(); j++) {
     const auto& cs = qc.constraints()[j];
     if (cs.iColumn == Column::kUpid) {
       auto constraint_upid = static_cast<UniquePid>(sqlite3_value_int(argv[j]));
       // Set the range of upids that we are interested in, based on the
-      // constraints in the query. Everything between min and max (inclusive)
+      // constraints in the query. Everything between min and max (exclusive)
       // will be returned.
       if (IsOpEq(cs.op)) {
-        min = constraint_upid;
-        max = constraint_upid;
+        min_ = constraint_upid;
+        max_ = constraint_upid + 1;
       } else if (IsOpGe(cs.op) || IsOpGt(cs.op)) {
-        min = IsOpGt(cs.op) ? constraint_upid + 1 : constraint_upid;
+        min_ = IsOpGt(cs.op) ? constraint_upid + 1 : constraint_upid;
       } else if (IsOpLe(cs.op) || IsOpLt(cs.op)) {
-        max = IsOpLt(cs.op) ? constraint_upid - 1 : constraint_upid;
+        max_ = IsOpLt(cs.op) ? constraint_upid : constraint_upid + 1;
       }
     }
   }
 
   for (const auto& ob : qc.order_by()) {
     if (ob.iColumn == Column::kUpid) {
-      desc = ob.desc;
+      desc_ = ob.desc;
     }
   }
-  current = desc ? max : min;
+  index_ = 0;
 
   return SQLITE_OK;
 }
 
 int ProcessTable::Cursor::Column(sqlite3_context* context, int N) {
+  uint32_t current = desc_ ? max_ - index_ - 1 : min_ + index_;
+  const auto& process = storage_->GetProcess(current);
   switch (N) {
     case Column::kUpid: {
       sqlite3_result_int64(context, current);
       break;
     }
     case Column::kName: {
-      const auto& process = storage_->GetProcess(current);
       const auto& name = storage_->GetString(process.name_id);
       sqlite3_result_text(context, name.c_str(), -1, kSqliteStatic);
       break;
     }
     case Column::kPid: {
-      const auto& process = storage_->GetProcess(current);
       sqlite3_result_int64(context, process.pid);
       break;
     }
     case Column::kStartTs: {
-      const auto& process = storage_->GetProcess(current);
       if (process.start_ns != 0) {
         sqlite3_result_int64(context, process.start_ns);
       } else {
@@ -133,7 +132,6 @@
       break;
     }
     case Column::kEndTs: {
-      const auto& process = storage_->GetProcess(current);
       if (process.end_ns != 0) {
         sqlite3_result_int64(context, process.end_ns);
       } else {
@@ -142,7 +140,6 @@
       break;
     }
     case Column::kParentUpid: {
-      const auto& process = storage_->GetProcess(current);
       if (process.parent_upid.has_value()) {
         sqlite3_result_int64(context, process.parent_upid.value());
       } else {
@@ -158,16 +155,12 @@
 }
 
 int ProcessTable::Cursor::Next() {
-  if (desc) {
-    --current;
-  } else {
-    ++current;
-  }
+  ++index_;
   return SQLITE_OK;
 }
 
 int ProcessTable::Cursor::Eof() {
-  return desc ? current < min : current > max;
+  return index_ >= (max_ - min_);
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/process_table.h b/src/trace_processor/process_table.h
index 4c8b208..c4c1ed5 100644
--- a/src/trace_processor/process_table.h
+++ b/src/trace_processor/process_table.h
@@ -50,10 +50,10 @@
 
    private:
     const TraceStorage* const storage_;
-    UniquePid min;
-    UniquePid max;
-    UniquePid current;
-    bool desc;
+    UniquePid min_ = 0;
+    UniquePid max_ = 0;
+    uint32_t index_ = 0;
+    bool desc_ = false;
   };
 
   static void RegisterTable(sqlite3* db, const TraceStorage* storage);
diff --git a/src/trace_processor/raw_table.cc b/src/trace_processor/raw_table.cc
index bf4f111..29d86ef 100644
--- a/src/trace_processor/raw_table.cc
+++ b/src/trace_processor/raw_table.cc
@@ -70,12 +70,13 @@
 
 int RawTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
   info->estimated_cost = RowCount();
+  info->sqlite_omit_order_by = true;
 
   // Only the string columns are handled by SQLite
-  info->order_by_consumed = true;
   size_t name_index = schema().ColumnIndexFromName("name");
   for (size_t i = 0; i < qc.constraints().size(); i++) {
-    info->omit[i] = qc.constraints()[i].iColumn != static_cast<int>(name_index);
+    info->constraint_info[i].sqlite_omit =
+        qc.constraints()[i].iColumn != static_cast<int>(name_index);
   }
 
   return SQLITE_OK;
diff --git a/src/trace_processor/sched_slice_table.cc b/src/trace_processor/sched_slice_table.cc
index 05657c4..0385fab 100644
--- a/src/trace_processor/sched_slice_table.cc
+++ b/src/trace_processor/sched_slice_table.cc
@@ -51,8 +51,9 @@
 
   // We should be able to handle any constraint and any order by clause given
   // to us.
-  info->order_by_consumed = true;
-  std::fill(info->omit.begin(), info->omit.end(), true);
+  info->sqlite_omit_order_by = true;
+  for (auto& c_info : info->constraint_info)
+    c_info.sqlite_omit = true;
 
   return SQLITE_OK;
 }
diff --git a/src/trace_processor/slice_table.cc b/src/trace_processor/slice_table.cc
index d2dca83..5eef8c0 100644
--- a/src/trace_processor/slice_table.cc
+++ b/src/trace_processor/slice_table.cc
@@ -53,15 +53,15 @@
 
 int SliceTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
   info->estimated_cost = EstimateCost(qc);
+  info->sqlite_omit_order_by = true;
 
   // Only the string columns are handled by SQLite
-  info->order_by_consumed = true;
   size_t name_index = schema().ColumnIndexFromName("name");
   size_t cat_index = schema().ColumnIndexFromName("category");
   size_t ref_type_index = schema().ColumnIndexFromName("ref_type");
   for (size_t i = 0; i < qc.constraints().size(); i++) {
     auto col = static_cast<size_t>(qc.constraints()[i].iColumn);
-    info->omit[i] =
+    info->constraint_info[i].sqlite_omit =
         col != name_index && col != cat_index && col != ref_type_index;
   }
   return SQLITE_OK;
diff --git a/src/trace_processor/sql_stats_table.cc b/src/trace_processor/sql_stats_table.cc
index 3356f8e..0d434a0 100644
--- a/src/trace_processor/sql_stats_table.cc
+++ b/src/trace_processor/sql_stats_table.cc
@@ -57,7 +57,7 @@
 }
 
 int SqlStatsTable::BestIndex(const QueryConstraints&, BestIndexInfo* info) {
-  info->order_by_consumed = false;  // Delegate sorting to SQLite.
+  info->sqlite_omit_order_by = true;
   return SQLITE_OK;
 }
 
diff --git a/src/trace_processor/sqlite/sqlite_table.cc b/src/trace_processor/sqlite/sqlite_table.cc
index 211ff7e..9a41763 100644
--- a/src/trace_processor/sqlite/sqlite_table.cc
+++ b/src/trace_processor/sqlite/sqlite_table.cc
@@ -58,54 +58,84 @@
 }
 
 int SqliteTable::BestIndexInternal(sqlite3_index_info* idx) {
-  QueryConstraints query_constraints;
+  using ConstraintInfo = BestIndexInfo::ConstraintInfo;
 
-  for (int i = 0; i < idx->nOrderBy; i++) {
-    int column = idx->aOrderBy[i].iColumn;
-    bool desc = idx->aOrderBy[i].desc;
-    query_constraints.AddOrderBy(column, desc);
-  }
-
+  QueryConstraints in_qc;
+  BestIndexInfo info;
   for (int i = 0; i < idx->nConstraint; i++) {
     const auto& cs = idx->aConstraint[i];
     if (!cs.usable)
       continue;
-    query_constraints.AddConstraint(cs.iColumn, cs.op);
+    in_qc.AddConstraint(cs.iColumn, cs.op);
 
-    // argvIndex is 1-based so use the current size of the vector.
-    int argv_index = static_cast<int>(query_constraints.constraints().size());
-    idx->aConstraintUsage[i].argvIndex = argv_index;
+    ConstraintInfo c_info;
+    c_info.qc_idx = static_cast<uint32_t>(in_qc.constraints().size() - 1);
+    info.constraint_info.emplace_back(c_info);
   }
 
-  BestIndexInfo info;
-  info.omit.resize(query_constraints.constraints().size());
-
-  int ret = BestIndex(query_constraints, &info);
-
-  if (SqliteTable::debug) {
-    PERFETTO_LOG(
-        "[%s::BestIndex] constraints=%s orderByConsumed=%d estimatedCost=%d",
-        name_.c_str(), query_constraints.ToNewSqlite3String().get(),
-        info.order_by_consumed, info.estimated_cost);
+  for (int i = 0; i < idx->nOrderBy; i++) {
+    int column = idx->aOrderBy[i].iColumn;
+    bool desc = idx->aOrderBy[i].desc;
+    in_qc.AddOrderBy(column, desc);
   }
 
+  int ret = BestIndex(in_qc, &info);
   if (ret != SQLITE_OK)
     return ret;
 
-  idx->orderByConsumed = info.order_by_consumed;
-  idx->estimatedCost = info.estimated_cost;
+  auto& cs_info = info.constraint_info;
 
-  size_t j = 0;
-  for (int i = 0; i < idx->nConstraint; i++) {
-    const auto& cs = idx->aConstraint[i];
-    if (cs.usable)
-      idx->aConstraintUsage[i].omit = info.omit[j++];
+  // Remove all the pruned terms from the constraints.
+  {
+    auto prune_fn = [](const ConstraintInfo& t) { return t.prune; };
+    auto prune_cs_it = std::remove_if(cs_info.begin(), cs_info.end(), prune_fn);
+    cs_info.erase(prune_cs_it, cs_info.end());
   }
 
-  if (!info.order_by_consumed)
-    query_constraints.ClearOrderBy();
+  idx->orderByConsumed = info.prune_order_by || info.sqlite_omit_order_by;
+  idx->estimatedCost = info.estimated_cost;
 
-  idx->idxStr = query_constraints.ToNewSqlite3String().release();
+  uint32_t in_qc_idx = 0;
+  for (int i = 0; i < idx->nConstraint; i++) {
+    const auto& c = idx->aConstraint[i];
+    if (c.usable) {
+      auto cs_fn = [in_qc_idx](const ConstraintInfo& t) {
+        return t.qc_idx == in_qc_idx;
+      };
+      auto it = std::find_if(cs_info.begin(), cs_info.end(), cs_fn);
+
+      // If the iterator no longer exists, we must have pruned it.
+      if (it == cs_info.end()) {
+        idx->aConstraintUsage[i].omit = true;
+      } else {
+        idx->aConstraintUsage[i].argvIndex =
+            static_cast<int>(std::distance(cs_info.begin(), it)) + 1;
+        idx->aConstraintUsage[i].omit = it->sqlite_omit;
+      }
+      in_qc_idx++;
+    }
+  }
+
+  QueryConstraints out_qc;
+  for (const auto& c_info : cs_info) {
+    const auto& c = in_qc.constraints()[c_info.qc_idx];
+    out_qc.AddConstraint(c.iColumn, c.op);
+  }
+  if (!info.prune_order_by) {
+    for (const auto& o : in_qc.order_by()) {
+      out_qc.AddOrderBy(o.iColumn, o.desc);
+    }
+  }
+
+  auto out_qc_str = out_qc.ToNewSqlite3String();
+  if (SqliteTable::debug) {
+    PERFETTO_LOG(
+        "[%s::BestIndex] constraints=%s orderByConsumed=%d estimatedCost=%d",
+        name_.c_str(), out_qc_str.get(), idx->orderByConsumed,
+        info.estimated_cost);
+  }
+
+  idx->idxStr = out_qc_str.release();
   idx->needToFreeIdxStr = true;
   idx->idxNum = ++best_index_num_;
 
diff --git a/src/trace_processor/sqlite/sqlite_table.h b/src/trace_processor/sqlite/sqlite_table.h
index 51557bf..3b9f83c 100644
--- a/src/trace_processor/sqlite/sqlite_table.h
+++ b/src/trace_processor/sqlite/sqlite_table.h
@@ -136,9 +136,41 @@
   // Populated by a BestIndex call to allow subclasses to tweak SQLite's
   // handling of sets of constraints.
   struct BestIndexInfo {
-    bool order_by_consumed = false;
+    // Contains info about a single constraint.
+    struct ConstraintInfo {
+      // Gives the index of this constraint in the QueryConstraints class.
+      uint32_t qc_idx = 0;
+
+      // Indicates whether this constraint should be removed from the
+      // QueryConstraint class when passed to SqliteTable::Filter.
+      bool prune = false;
+
+      // Indiciates whether SQLite should omit double checking this constraint.
+      //
+      // If |prune| is set to true, this value will be ignored and SQLite will
+      // be told that it can omit double checking (i.e. this value will
+      // implicitly be taken to be true).
+      bool sqlite_omit = false;
+    };
+
+    // Stores the estimated cost of this query.
     uint32_t estimated_cost = 0;
-    std::vector<bool> omit;
+
+    // Stores the information about each constraint.
+    std::vector<ConstraintInfo> constraint_info;
+
+    // Indicates that all the order by constraints should be pruned. This should
+    // be set to true if the table is exactly ordered by the order by terms in
+    // QueryConstraints.
+    bool prune_order_by = false;
+
+    // Indicates that SQLite should not double check the result of the order by
+    // clause.
+    //
+    // If |prune_order_by| is set to true, this value will be ignored and SQLite
+    // will be told that it can omit double checking (i.e. this value will
+    // implicitly be taken to be true).
+    bool sqlite_omit_order_by = false;
   };
 
   template <typename Context>
diff --git a/src/trace_processor/stack_profile_frame_table.cc b/src/trace_processor/stack_profile_frame_table.cc
index eb750e3..6939873 100644
--- a/src/trace_processor/stack_profile_frame_table.cc
+++ b/src/trace_processor/stack_profile_frame_table.cc
@@ -46,7 +46,7 @@
 
 int StackProfileFrameTable::BestIndex(const QueryConstraints& qc,
                                       BestIndexInfo* info) {
-  info->order_by_consumed = true;
+  info->sqlite_omit_order_by = true;
   info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
   return SQLITE_OK;
 }
diff --git a/src/trace_processor/stack_profile_mapping_table.cc b/src/trace_processor/stack_profile_mapping_table.cc
index a7644db..52a9038 100644
--- a/src/trace_processor/stack_profile_mapping_table.cc
+++ b/src/trace_processor/stack_profile_mapping_table.cc
@@ -50,7 +50,7 @@
 
 int StackProfileMappingTable::BestIndex(const QueryConstraints& qc,
                                         BestIndexInfo* info) {
-  info->order_by_consumed = true;
+  info->sqlite_omit_order_by = true;
   info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
   return SQLITE_OK;
 }
diff --git a/src/trace_processor/thread_table.cc b/src/trace_processor/thread_table.cc
index a951812..ba339e8 100644
--- a/src/trace_processor/thread_table.cc
+++ b/src/trace_processor/thread_table.cc
@@ -76,9 +76,9 @@
                                 sqlite3_value** argv) {
   *this = Cursor(table_);
 
-  min = 0;
-  max = static_cast<uint32_t>(storage_->thread_count()) - 1;
-  desc = false;
+  min_ = 0;
+  max_ = static_cast<uint32_t>(storage_->thread_count());
+  desc_ = false;
 
   for (size_t j = 0; j < qc.constraints().size(); j++) {
     const auto& cs = qc.constraints()[j];
@@ -86,30 +86,31 @@
       UniqueTid constraint_utid =
           static_cast<UniqueTid>(sqlite3_value_int(argv[j]));
       // Filter the range of utids that we are interested in, based on the
-      // constraints in the query. Everything between min and max (inclusive)
+      // constraints in the query. Everything between min and max (exclusive)
       // will be returned.
       if (IsOpEq(cs.op)) {
-        min = constraint_utid;
-        max = constraint_utid;
+        min_ = constraint_utid;
+        max_ = constraint_utid + 1;
       } else if (IsOpGe(cs.op) || IsOpGt(cs.op)) {
-        min = IsOpGt(cs.op) ? constraint_utid + 1 : constraint_utid;
+        min_ = IsOpGt(cs.op) ? constraint_utid + 1 : constraint_utid;
       } else if (IsOpLe(cs.op) || IsOpLt(cs.op)) {
-        max = IsOpLt(cs.op) ? constraint_utid - 1 : constraint_utid;
+        max_ = IsOpLt(cs.op) ? constraint_utid : constraint_utid + 1;
       }
     }
   }
 
   for (const auto& ob : qc.order_by()) {
     if (ob.iColumn == Column::kUtid) {
-      desc = ob.desc;
+      desc_ = ob.desc;
     }
   }
-  current = desc ? max : min;
+  index_ = 0;
 
   return SQLITE_OK;
 }
 
 int ThreadTable::Cursor::Column(sqlite3_context* context, int N) {
+  uint32_t current = desc_ ? max_ - index_ - 1 : min_ + index_;
   const auto& thread = storage_->GetThread(current);
   switch (N) {
     case Column::kUtid: {
@@ -158,16 +159,12 @@
 }
 
 int ThreadTable::Cursor::Next() {
-  if (desc) {
-    --current;
-  } else {
-    ++current;
-  }
+  ++index_;
   return SQLITE_OK;
 }
 
 int ThreadTable::Cursor::Eof() {
-  return desc ? current < min : current > max;
+  return index_ >= (max_ - min_);
 }
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/thread_table.h b/src/trace_processor/thread_table.h
index a72ed23..43484d1 100644
--- a/src/trace_processor/thread_table.h
+++ b/src/trace_processor/thread_table.h
@@ -55,10 +55,10 @@
     Cursor(Cursor&&) noexcept = default;
     Cursor& operator=(Cursor&&) = default;
 
-    UniqueTid min;
-    UniqueTid max;
-    UniqueTid current;
-    bool desc;
+    UniqueTid min_ = 0;
+    UniqueTid max_ = 0;
+    uint32_t index_ = 0;
+    bool desc_ = false;
 
     const TraceStorage* storage_ = nullptr;
     ThreadTable* table_ = nullptr;
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 80a7c9d..bbbe087 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -138,7 +138,7 @@
                "CREATE VIEW counter_definitions AS "
                "SELECT "
                "  *, "
-               "  id as counter_id "
+               "  id AS counter_id "
                "FROM counter_track",
                0, 0, &error);
   if (error) {
@@ -147,9 +147,23 @@
   }
 
   sqlite3_exec(db,
+               "CREATE VIEW counter_values AS "
+               "SELECT "
+               "  *, "
+               "  track_id as counter_id "
+               "FROM counter",
+               0, 0, &error);
+  if (error) {
+    PERFETTO_ELOG("Error initializing: %s", error);
+    sqlite3_free(error);
+  }
+
+  sqlite3_exec(db,
                "CREATE VIEW counters AS "
-               "SELECT * FROM counter_values "
-               "INNER JOIN counter_definitions USING(counter_id) "
+               "SELECT * "
+               "FROM counter_values v "
+               "INNER JOIN counter_track t "
+               "ON v.track_id = t.id "
                "ORDER BY ts;",
                0, 0, &error);
   if (error) {
@@ -161,7 +175,7 @@
                "CREATE VIEW slice AS "
                "SELECT "
                "  *, "
-               "  category as cat, "
+               "  category AS cat, "
                "  CASE ref_type "
                "    WHEN 'utid' THEN ref "
                "    ELSE NULL "
diff --git a/src/trace_processor/window_operator_table.cc b/src/trace_processor/window_operator_table.cc
index cbc8d78..727b32a 100644
--- a/src/trace_processor/window_operator_table.cc
+++ b/src/trace_processor/window_operator_table.cc
@@ -65,10 +65,9 @@
                                    BestIndexInfo* info) {
   // Remove ordering on timestamp if it is the only ordering as we are already
   // sorted on TS. This makes span joining significantly faster.
-  if (qc.order_by().size() == 1 && qc.order_by()[0].iColumn == Column::kTs &&
-      !qc.order_by()[0].desc) {
-    info->order_by_consumed = true;
-  }
+  const auto& ob = qc.order_by();
+  info->prune_order_by =
+      ob.size() == 1 && ob[0].iColumn == Column::kTs && !ob[0].desc;
   return SQLITE_OK;
 }
 
diff --git a/test/metrics/heap_profile_callsites.out b/test/metrics/heap_profile_callsites.out
index 6a975bb..5f8c14c 100644
--- a/test/metrics/heap_profile_callsites.out
+++ b/test/metrics/heap_profile_callsites.out
@@ -58,5 +58,7 @@
         delta_bytes: 1090
       }
     }
+    profile_delta_bytes: 1090
+    profile_total_bytes: 2100
   }
 }
diff --git a/test/metrics/index b/test/metrics/index
index a159f21..8f29693 100644
--- a/test/metrics/index
+++ b/test/metrics/index
@@ -21,5 +21,7 @@
 heap_profile.textproto heap_profile_callsites heap_profile_callsites.out
 heap_profile_no_symbols.textproto unsymbolized_frames unsymbolized_frames.out
 
+../trace_processor/heap_graph.textproto java_heap_stats java_heap_stats.out
+
 # Json output
 ../data/memory_counters.pb trace_metadata trace_metadata.json.out
diff --git a/test/metrics/java_heap_stats.out b/test/metrics/java_heap_stats.out
new file mode 100644
index 0000000..64db708
--- /dev/null
+++ b/test/metrics/java_heap_stats.out
@@ -0,0 +1,11 @@
+java_heap_stats {
+  instance_stats {
+    upid: 2
+    process_name: "system_server"
+    samples {
+      ts: 10
+      heap_size: 224
+      reachable_heap_size: 96
+    }
+  }
+}
diff --git a/test/trace_processor/heap_graph.textproto b/test/trace_processor/heap_graph.textproto
index eb32c54..b785578 100644
--- a/test/trace_processor/heap_graph.textproto
+++ b/test/trace_processor/heap_graph.textproto
@@ -16,6 +16,7 @@
   trusted_packet_sequence_id: 999
   timestamp: 10
   heap_graph {
+    pid: 2
     roots {
       root_type: ROOT_JAVA_FRAME
       object_ids: 0x01
@@ -32,12 +33,18 @@
       type_id: 2
       self_size: 32
     }
+    objects {
+      id: 0x03
+      type_id: 2
+      self_size: 128
+    }
     continued: true
     index: 1
   }
 }
 packet {
   heap_graph {
+    pid: 2
     type_names {
       iid: 1
       str: "FactoryProducerDelegateImplActor"
diff --git a/test/trace_processor/heap_graph_object.out b/test/trace_processor/heap_graph_object.out
index 48bc6b9..b0f9e43 100644
--- a/test/trace_processor/heap_graph_object.out
+++ b/test/trace_processor/heap_graph_object.out
@@ -1,3 +1,4 @@
 "id","type","upid","graph_sample_ts","object_id","self_size","retained_size","unique_retained_size","reference_set_id","reachable","type_name","root_type"
-0,"heap_graph_object",0,10,1,64,96,96,0,1,"FactoryProducerDelegateImplActor","ROOT_JAVA_FRAME"
-1,"heap_graph_object",0,10,2,32,32,32,1,1,"Foo","[NULL]"
+0,"heap_graph_object",2,10,1,64,96,96,0,1,"FactoryProducerDelegateImplActor","ROOT_JAVA_FRAME"
+1,"heap_graph_object",2,10,2,32,32,32,1,1,"Foo","[NULL]"
+2,"heap_graph_object",2,10,3,128,-1,0,1,0,"Foo","[NULL]"
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 8c93273..7edcbba 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -494,7 +494,9 @@
           left join (select upid, sum(dur) as total_dur
               from sched join thread using(utid)
               group by upid
-            ) using(upid) group by utid, upid
+            ) using(upid)
+        where utid != 0
+        group by utid, upid
         order by total_dur desc, upid, utid`);
 
     const upidToUuid = new Map<number, string>();