Merge "Add canned query for bytes per type."
diff --git a/Android.bp b/Android.bp
index dc329a6..c65df9d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -32,7 +32,7 @@
"src/trace_processor/metrics/android/android_startup_cpu.sql",
"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_callsite_stats.sql",
+ "src/trace_processor/metrics/android/heap_profile_callsites.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",
@@ -1859,7 +1859,7 @@
srcs: [
"protos/perfetto/metrics/android/batt_metric.proto",
"protos/perfetto/metrics/android/cpu_metric.proto",
- "protos/perfetto/metrics/android/heap_profile_callsite_stats.proto",
+ "protos/perfetto/metrics/android/heap_profile_callsites.proto",
"protos/perfetto/metrics/android/ion_metric.proto",
"protos/perfetto/metrics/android/lmk_metric.proto",
"protos/perfetto/metrics/android/mem_metric.proto",
@@ -1878,7 +1878,7 @@
out: [
"external/perfetto/protos/perfetto/metrics/android/batt_metric.pbzero.cc",
"external/perfetto/protos/perfetto/metrics/android/cpu_metric.pbzero.cc",
- "external/perfetto/protos/perfetto/metrics/android/heap_profile_callsite_stats.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/lmk_metric.pbzero.cc",
"external/perfetto/protos/perfetto/metrics/android/mem_metric.pbzero.cc",
@@ -1897,7 +1897,7 @@
srcs: [
"protos/perfetto/metrics/android/batt_metric.proto",
"protos/perfetto/metrics/android/cpu_metric.proto",
- "protos/perfetto/metrics/android/heap_profile_callsite_stats.proto",
+ "protos/perfetto/metrics/android/heap_profile_callsites.proto",
"protos/perfetto/metrics/android/ion_metric.proto",
"protos/perfetto/metrics/android/lmk_metric.proto",
"protos/perfetto/metrics/android/mem_metric.proto",
@@ -1916,7 +1916,7 @@
out: [
"external/perfetto/protos/perfetto/metrics/android/batt_metric.pbzero.h",
"external/perfetto/protos/perfetto/metrics/android/cpu_metric.pbzero.h",
- "external/perfetto/protos/perfetto/metrics/android/heap_profile_callsite_stats.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/lmk_metric.pbzero.h",
"external/perfetto/protos/perfetto/metrics/android/mem_metric.pbzero.h",
@@ -4017,6 +4017,7 @@
"src/trace_processor/proto_trace_parser.cc",
"src/trace_processor/proto_trace_tokenizer.cc",
"src/trace_processor/raw_table.cc",
+ "src/trace_processor/read_trace.cc",
"src/trace_processor/row_iterators.cc",
"src/trace_processor/sched_slice_table.cc",
"src/trace_processor/slice_table.cc",
diff --git a/BUILD b/BUILD
index e560b11..1170b2c 100644
--- a/BUILD
+++ b/BUILD
@@ -339,6 +339,7 @@
name = "include_perfetto_trace_processor_trace_processor",
srcs = [
"include/perfetto/trace_processor/basic_types.h",
+ "include/perfetto/trace_processor/read_trace.h",
"include/perfetto/trace_processor/status.h",
"include/perfetto/trace_processor/trace_processor.h",
],
@@ -520,7 +521,7 @@
"src/trace_processor/metrics/android/android_startup_cpu.sql",
"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_callsite_stats.sql",
+ "src/trace_processor/metrics/android/heap_profile_callsites.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",
@@ -660,6 +661,7 @@
"src/trace_processor/proto_trace_tokenizer.h",
"src/trace_processor/raw_table.cc",
"src/trace_processor/raw_table.h",
+ "src/trace_processor/read_trace.cc",
"src/trace_processor/row_iterators.cc",
"src/trace_processor/row_iterators.h",
"src/trace_processor/sched_slice_table.cc",
@@ -1396,7 +1398,7 @@
srcs = [
"protos/perfetto/metrics/android/batt_metric.proto",
"protos/perfetto/metrics/android/cpu_metric.proto",
- "protos/perfetto/metrics/android/heap_profile_callsite_stats.proto",
+ "protos/perfetto/metrics/android/heap_profile_callsites.proto",
"protos/perfetto/metrics/android/ion_metric.proto",
"protos/perfetto/metrics/android/lmk_metric.proto",
"protos/perfetto/metrics/android/mem_metric.proto",
diff --git a/gn/standalone/toolchain/BUILD.gn b/gn/standalone/toolchain/BUILD.gn
index 1a428b2..7394802 100644
--- a/gn/standalone/toolchain/BUILD.gn
+++ b/gn/standalone/toolchain/BUILD.gn
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import("//gn/perfetto.gni")
import("//gn/standalone/android.gni")
import("//gn/standalone/wasm.gni")
import("llvm.gni")
@@ -32,6 +33,7 @@
# 2. setting is_system_compiler=true in args.gn and the env vars AR/CC/CXX.
# This is used by OSSFuzz.
declare_args() {
+ sysroot = ""
ar = "ar"
if (is_linux_host) {
linker = "gold"
@@ -61,28 +63,28 @@
# Then determine the target toolchain.
-# GCC only: determine the cross-toolchain triplet.
declare_args() {
- if (is_clang || !is_cross_compiling) {
- gcc_target_triplet = ""
+ target_sysroot = sysroot
+ if (!is_cross_compiling) {
+ target_triplet = ""
} else if (target_os == "mac" && target_cpu == "x64") {
- gcc_target_triplet = "x86_64-apple-darwin"
+ target_triplet = "x86_64-apple-darwin"
} else if (target_os == "mac" && target_cpu == "x86") {
- gcc_target_triplet = "i686-apple-darwin"
+ target_triplet = "i686-apple-darwin"
} else if (target_os == "linux" && target_cpu == "arm64") {
- gcc_target_triplet = "aarch64-linux-gnu"
+ target_triplet = "aarch64-linux-gnu"
} else if (target_os == "linux" && target_cpu == "x64") {
- gcc_target_triplet = "x86_64-linux-gnu"
+ target_triplet = "x86_64-linux-gnu"
} else if (target_os == "linux" && target_cpu == "x86") {
- gcc_target_triplet = "i686-linux-gnu"
+ target_triplet = "i686-linux-gnu"
} else if (target_os == "android" && target_cpu == "arm64") {
- gcc_target_triplet = "aarch64-linux-android"
+ target_triplet = "aarch64-linux-android"
} else if (target_os == "android" && target_cpu == "arm") {
- gcc_target_triplet = "arm-linux-androideabi"
+ target_triplet = "arm-linux-androideabi"
} else if (target_os == "android" && target_cpu == "x86") {
- gcc_target_triplet = "i686-linux-android"
+ target_triplet = "i686-linux-android"
} else if (target_os == "android" && target_cpu == "x86_64") {
- gcc_target_triplet = "x86_64-linux-android"
+ target_triplet = "x86_64-linux-android"
} else {
assert(false,
"Unsupported cross-compilation for ${target_os}-${target_cpu}")
@@ -90,7 +92,7 @@
}
declare_args() {
- if (!is_cross_compiling) {
+ if (!is_cross_compiling || is_perfetto_build_generator) {
target_ar = ar
target_cc = cc
target_cxx = cxx
@@ -106,16 +108,18 @@
target_ar = "$android_toolchain_root/bin/$android_abi_target-ar"
target_cc = "$android_llvm_dir/bin/clang"
target_cxx = "$android_llvm_dir/bin/clang++"
- } else if (is_clang) {
- target_cc = linux_clang_bin
- target_cxx = linux_clangxx_bin
- target_linker = linux_clang_linker
- } else { # GCC
- assert(gcc_target_triplet != "",
- "gcc_target_triplet must be non-empty when cross-compiling")
- target_ar = "${gcc_target_triplet}-ar"
- target_cc = "${gcc_target_triplet}-gcc"
- target_cxx = "${gcc_target_triplet}-g++"
+ } else {
+ assert(target_triplet != "",
+ "target_triplet must be non-empty when cross-compiling")
+ if (is_clang) {
+ target_cc = "${linux_clang_bin} --target=${target_triplet}"
+ target_cxx = "${linux_clangxx_bin} --target=${target_triplet}"
+ target_linker = "${linux_clang_linker} --target=${target_triplet}"
+ } else { # GCC
+ target_ar = "${target_triplet}-ar"
+ target_cc = "${target_triplet}-gcc"
+ target_cxx = "${target_triplet}-g++"
+ }
}
}
}
@@ -128,10 +132,15 @@
lib_switch = "-l"
lib_dir_switch = "-L"
ld_arg = ""
- if (invoker.linker != "") {
+ if (defined(invoker.linker) && invoker.linker != "") {
_invoker_linker = invoker.linker
ld_arg = "-fuse-ld=$_invoker_linker"
}
+ if (defined(invoker.sysroot) && invoker.sysroot != "") {
+ _invoker_sysroot = invoker.sysroot
+ cc = "$cc --sysroot=$_invoker_sysroot"
+ cxx = "$cxx --sysroot=$_invoker_sysroot"
+ }
tool("cc") {
depfile = "{{output}}.d"
@@ -229,6 +238,7 @@
cc = target_cc
cxx = target_cxx
linker = target_linker
+ sysroot = target_sysroot
}
gcc_like_toolchain("gcc_like_host") {
@@ -238,6 +248,7 @@
cc = cc
cxx = cxx
linker = linker
+ sysroot = sysroot
}
gcc_like_toolchain("wasm") {
@@ -247,5 +258,4 @@
ar = "$emsdk_dir/emscripten/emar --em-config $em_config"
cc = "$emsdk_dir/emscripten/emcc --em-config $em_config"
cxx = "$emsdk_dir/emscripten/em++ --em-config $em_config"
- linker = ""
}
diff --git a/include/perfetto/trace_processor/BUILD.gn b/include/perfetto/trace_processor/BUILD.gn
index 90200fa..215be02 100644
--- a/include/perfetto/trace_processor/BUILD.gn
+++ b/include/perfetto/trace_processor/BUILD.gn
@@ -15,6 +15,7 @@
source_set("trace_processor") {
sources = [
"basic_types.h",
+ "read_trace.h",
"status.h",
"trace_processor.h",
]
diff --git a/include/perfetto/trace_processor/read_trace.h b/include/perfetto/trace_processor/read_trace.h
new file mode 100644
index 0000000..ac2053d
--- /dev/null
+++ b/include/perfetto/trace_processor/read_trace.h
@@ -0,0 +1,38 @@
+/*
+ * 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 INCLUDE_PERFETTO_TRACE_PROCESSOR_READ_TRACE_H_
+#define INCLUDE_PERFETTO_TRACE_PROCESSOR_READ_TRACE_H_
+
+#include <functional>
+
+#include "perfetto/base/export.h"
+#include "perfetto/trace_processor/status.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceProcessor;
+
+util::Status PERFETTO_EXPORT ReadTrace(
+ TraceProcessor* tp,
+ const char* filename,
+ const std::function<void(uint64_t parsed_size)>& progress_callback = {});
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACE_PROCESSOR_READ_TRACE_H_
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index a0d48a8..9d1d001 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -18,7 +18,7 @@
sources = [
"batt_metric.proto",
"cpu_metric.proto",
- "heap_profile_callsite_stats.proto",
+ "heap_profile_callsites.proto",
"ion_metric.proto",
"lmk_metric.proto",
"mem_metric.proto",
diff --git a/protos/perfetto/metrics/android/heap_profile_callsite_stats.proto b/protos/perfetto/metrics/android/heap_profile_callsite_stats.proto
deleted file mode 100644
index 74a836d..0000000
--- a/protos/perfetto/metrics/android/heap_profile_callsite_stats.proto
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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 HeapProfileCallsiteStats {
- message Frame {
- optional string name = 1;
- optional string mapping_name = 2;
- }
-
- message Callsite { repeated Frame frame = 1; }
-
- message CallsiteStats {
- optional Callsite callsite = 1;
-
- // Count of objects allocated at this callsite
- optional int64 total_count = 2;
- // Count of bytes allocated at this callsite
- optional int64 total_bytes = 3;
-
- // Count of allocated objects that were not freed
- optional int64 delta_count = 4;
- // Count of allocated bytes that were not freed
- optional int64 delta_bytes = 5;
- }
-
- // Next id: 4
- message InstanceStats {
- optional uint32 pid = 3;
- optional string process_name = 1;
- repeated CallsiteStats callsite_stats = 2;
- }
-
- repeated InstanceStats instance_stats = 1;
-}
diff --git a/protos/perfetto/metrics/android/heap_profile_callsites.proto b/protos/perfetto/metrics/android/heap_profile_callsites.proto
new file mode 100644
index 0000000..ce0bdca
--- /dev/null
+++ b/protos/perfetto/metrics/android/heap_profile_callsites.proto
@@ -0,0 +1,61 @@
+/*
+ * 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 HeapProfileCallsites {
+ message Frame {
+ optional string name = 1;
+ optional string mapping_name = 2;
+ }
+
+ message Counters {
+ // Count of objects allocated
+ optional int64 total_count = 1;
+ // Count of bytes allocated
+ optional int64 total_bytes = 2;
+
+ // Count of allocated objects that were not freed
+ optional int64 delta_count = 3;
+ // Count of allocated bytes that were not freed
+ optional int64 delta_bytes = 4;
+ }
+
+ message Callsite {
+ // The hash unambiguously identifies a callsite in a heap profile (as a
+ // traversal from the root node). It is based on the symbol names (instead
+ // of the addresses).
+ optional int64 hash = 1;
+ optional int64 parent_hash = 2;
+
+ // Leaf frame of the callsite. Use parent_hash to traverse to parent nodes.
+ optional Frame frame = 3;
+
+ optional Counters self_allocs = 4;
+ optional Counters child_allocs = 5;
+ }
+
+ // Callsites per process instance.
+ message InstanceStats {
+ optional uint32 pid = 1;
+ optional string process_name = 2;
+ repeated Callsite callsites = 3;
+ }
+
+ repeated InstanceStats instance_stats = 1;
+}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index 713ae1b..d0c7a1f 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -28,7 +28,7 @@
import "protos/perfetto/metrics/android/lmk_metric.proto";
import "protos/perfetto/metrics/android/powrails_metric.proto";
import "protos/perfetto/metrics/android/startup_metric.proto";
-import "protos/perfetto/metrics/android/heap_profile_callsite_stats.proto";
+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";
@@ -47,9 +47,9 @@
// Root message for all Perfetto-based metrics.
//
-// Next id: 16
+// Next id: 17
message TraceMetrics {
- reserved 4, 13;
+ reserved 4, 13, 14;
// Battery counters metric on Android.
optional AndroidBatteryMetric android_batt = 5;
@@ -85,7 +85,7 @@
optional AndroidStartupMetric android_startup = 2;
// Heap profiler callsite statistics.
- optional HeapProfileCallsiteStats heap_profile_callsite_stats = 14;
+ optional HeapProfileCallsites heap_profile_callsites = 16;
// Trace metadata (applicable to all traces).
optional TraceMetadata trace_metadata = 3;
diff --git a/protos/perfetto/trace/gpu/gpu_log.proto b/protos/perfetto/trace/gpu/gpu_log.proto
index 7e61139..1c39bc0 100644
--- a/protos/perfetto/trace/gpu/gpu_log.proto
+++ b/protos/perfetto/trace/gpu/gpu_log.proto
@@ -22,12 +22,12 @@
// Message for logging events GPU data producer.
message GpuLog {
enum Severity {
- SEVERITY_UNSPECIFIED = 0;
- SEVERITY_VERBOSE = 1;
- SEVERITY_DEBUG = 2;
- SEVERITY_INFO = 3;
- SEVERITY_WARNING = 4;
- SEVERITY_ERROR = 5;
+ LOG_SEVERITY_UNSPECIFIED = 0;
+ LOG_SEVERITY_VERBOSE = 1;
+ LOG_SEVERITY_DEBUG = 2;
+ LOG_SEVERITY_INFO = 3;
+ LOG_SEVERITY_WARNING = 4;
+ LOG_SEVERITY_ERROR = 5;
};
optional Severity severity = 1;
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index b27257f..51a7a6a 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -4149,12 +4149,12 @@
// Message for logging events GPU data producer.
message GpuLog {
enum Severity {
- SEVERITY_UNSPECIFIED = 0;
- SEVERITY_VERBOSE = 1;
- SEVERITY_DEBUG = 2;
- SEVERITY_INFO = 3;
- SEVERITY_WARNING = 4;
- SEVERITY_ERROR = 5;
+ LOG_SEVERITY_UNSPECIFIED = 0;
+ LOG_SEVERITY_VERBOSE = 1;
+ LOG_SEVERITY_DEBUG = 2;
+ LOG_SEVERITY_INFO = 3;
+ LOG_SEVERITY_WARNING = 4;
+ LOG_SEVERITY_ERROR = 5;
};
optional Severity severity = 1;
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 6f20e97..fe3ce2a 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -95,8 +95,6 @@
"heap_profile_tracker.h",
"instants_table.cc",
"instants_table.h",
- "vulkan_memory_tracker.cc",
- "vulkan_memory_tracker.h",
"metadata.h",
"metadata_table.cc",
"metadata_table.h",
@@ -111,6 +109,7 @@
"proto_trace_tokenizer.h",
"raw_table.cc",
"raw_table.h",
+ "read_trace.cc",
"row_iterators.cc",
"row_iterators.h",
"sched_slice_table.cc",
@@ -167,6 +166,8 @@
"track_tracker.h",
"variadic.h",
"virtual_destructors.cc",
+ "vulkan_memory_tracker.cc",
+ "vulkan_memory_tracker.h",
"window_operator_table.cc",
"window_operator_table.h",
]
diff --git a/src/trace_processor/heap_graph_tracker.cc b/src/trace_processor/heap_graph_tracker.cc
index c29b60d..1f5bb72 100644
--- a/src/trace_processor/heap_graph_tracker.cc
+++ b/src/trace_processor/heap_graph_tracker.cc
@@ -41,6 +41,11 @@
interned_type_names_.emplace(intern_id, strid);
}
+void HeapGraphTracker::AddInternedFieldName(uint64_t intern_id,
+ StringPool::Id strid) {
+ interned_field_names_.emplace(intern_id, strid);
+}
+
void HeapGraphTracker::SetPacketIndex(uint64_t index) {
if (prev_index_ != 0 && prev_index_ + 1 != index) {
PERFETTO_ELOG("Missing packets between %" PRIu64 " and %" PRIu64,
@@ -61,8 +66,48 @@
}
context_->storage->mutable_heap_graph_object_table()->Insert(
{current_upid_, current_ts_, static_cast<int64_t>(obj.object_id),
- static_cast<int64_t>(obj.self_size), it->second});
+ static_cast<int64_t>(obj.self_size), -1, it->second});
+ object_id_to_row_.emplace(
+ obj.object_id, context_->storage->heap_graph_object_table().size() - 1);
}
+
+ for (const SourceObject& obj : current_objects_) {
+ auto it = object_id_to_row_.find(obj.object_id);
+ if (it == object_id_to_row_.end())
+ continue;
+ int64_t owner_row = it->second;
+
+ int64_t reference_set_id =
+ context_->storage->heap_graph_reference_table().size();
+ for (const SourceObject::Reference& ref : obj.references) {
+ // This is true for unset reference fields.
+ if (ref.owned_object_id == 0)
+ continue;
+
+ it = object_id_to_row_.find(ref.owned_object_id);
+ // This can only happen for an invalid type string id, which is already
+ // reported as an error. Silently continue here.
+ if (it == object_id_to_row_.end())
+ continue;
+
+ int64_t owned_row = it->second;
+ auto field_name_it = interned_field_names_.find(obj.type_id);
+ if (field_name_it == interned_field_names_.end()) {
+ context_->storage->IncrementIndexedStats(
+ stats::heap_graph_invalid_string_id,
+ static_cast<int>(current_upid_));
+ continue;
+ }
+ StringPool::Id field_name = field_name_it->second;
+ context_->storage->mutable_heap_graph_reference_table()->Insert(
+ {reference_set_id, owner_row, owned_row, field_name});
+ }
+ context_->storage->mutable_heap_graph_object_table()
+ ->mutable_reference_set_id()
+ ->Set(static_cast<uint32_t>(owner_row), reference_set_id);
+ }
+ interned_field_names_.clear();
+ object_id_to_row_.clear();
interned_type_names_.clear();
current_objects_.clear();
current_upid_ = 0;
diff --git a/src/trace_processor/heap_graph_tracker.h b/src/trace_processor/heap_graph_tracker.h
index 3431fbc..c65a7b1 100644
--- a/src/trace_processor/heap_graph_tracker.h
+++ b/src/trace_processor/heap_graph_tracker.h
@@ -34,15 +34,23 @@
class HeapGraphTracker {
public:
struct SourceObject {
+ // All ids in this are in the trace iid space, not in the trace processor
+ // id space.
+ struct Reference {
+ uint64_t field_name_id = 0;
+ uint64_t owned_object_id = 0;
+ };
uint64_t object_id = 0;
uint64_t self_size = 0;
uint64_t type_id = 0;
+ std::vector<Reference> references;
};
explicit HeapGraphTracker(TraceProcessorContext* context);
void AddObject(UniquePid upid, int64_t ts, SourceObject obj);
void AddInternedTypeName(uint64_t intern_id, StringPool::Id strid);
+ void AddInternedFieldName(uint64_t intern_id, StringPool::Id strid);
void FinalizeProfile();
void SetPacketIndex(uint64_t index);
@@ -53,6 +61,8 @@
int64_t current_ts_ = 0;
std::vector<SourceObject> current_objects_;
std::map<uint64_t, StringPool::Id> interned_type_names_;
+ std::map<uint64_t, StringPool::Id> interned_field_names_;
+ std::map<uint64_t, int64_t> object_id_to_row_;
uint64_t prev_index_ = 0;
};
diff --git a/src/trace_processor/metrics/BUILD.gn b/src/trace_processor/metrics/BUILD.gn
index 5ca6401..6e40711 100644
--- a/src/trace_processor/metrics/BUILD.gn
+++ b/src/trace_processor/metrics/BUILD.gn
@@ -31,7 +31,7 @@
"android/android_startup.sql",
"android/android_startup_cpu.sql",
"android/android_package_list.sql",
- "android/heap_profile_callsite_stats.sql",
+ "android/heap_profile_callsites.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_callsite_stats.sql b/src/trace_processor/metrics/android/heap_profile_callsite_stats.sql
deleted file mode 100644
index f81b3d3..0000000
--- a/src/trace_processor/metrics/android/heap_profile_callsite_stats.sql
+++ /dev/null
@@ -1,124 +0,0 @@
---
--- 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 totals_per_callsite AS
-SELECT upid, callsite_id, SUM(count) AS total_count, SUM(size) AS total_size
-FROM heap_profile_allocation
-WHERE count > 0
-GROUP BY 1, 2;
-
-CREATE VIEW deltas_per_callsite AS
-SELECT upid, callsite_id, SUM(count) AS delta_count, SUM(size) AS delta_size
-FROM heap_profile_allocation
-GROUP BY 1, 2;
-
--- For each callsite ID traverse all frames to the root.
-CREATE TABLE flattened_callsite AS
-WITH RECURSIVE callsite_parser(callsite_id, current_id, position) AS (
- SELECT id, id, 0 FROM stack_profile_callsite
- UNION
- SELECT callsite_id, parent_id, position + 1
- FROM callsite_parser JOIN stack_profile_callsite ON stack_profile_callsite.id = current_id
- WHERE stack_profile_callsite.depth > 0
-)
-SELECT *
-FROM callsite_parser;
-
--- Join frames with symbols
-CREATE TABLE symbolized_frame AS
-SELECT
- spf.id AS id,
- spf.mapping AS mapping,
- IFNULL(
- (SELECT name FROM stack_profile_symbol symbol
- WHERE symbol.symbol_set_id = spf.symbol_set_id
- LIMIT 1),
- spf.name
- ) AS name
-FROM stack_profile_frame spf;
-
-CREATE UNIQUE INDEX symbolized_frame_idx ON symbolized_frame(id);
-
--- Join with the frames table to get the symbol names.
--- Output order for position matters (as will be the order in the subsequent aggregate operations).
--- We use the cross join to force the join order between virtual and non-virtual tables.
-CREATE VIEW frames_by_callsite_id AS
-SELECT
- callsite_id,
- position,
- HeapProfileCallsiteStats_Frame(
- 'name', spf.name,
- 'mapping_name', stack_profile_mapping.name
- ) AS frame_proto
-FROM flattened_callsite
-CROSS JOIN stack_profile_callsite
-CROSS JOIN symbolized_frame spf
-CROSS JOIN stack_profile_mapping
-WHERE
- flattened_callsite.current_id = stack_profile_callsite.id
- AND stack_profile_callsite.frame_id = spf.id
- AND spf.mapping = stack_profile_mapping.id
-ORDER BY callsite_id, position;
-
--- Map callsite ID to proto.
-CREATE TABLE callsites_by_id AS
-SELECT
- callsite_id,
- HeapProfileCallsiteStats_Callsite('frame', RepeatedField(frame_proto))
- AS callsite_proto
-FROM frames_by_callsite_id
-GROUP BY callsite_id;
-
-CREATE VIEW callsite_stats AS
-SELECT
- upid,
- callsite_proto,
- totals.total_count,
- totals.total_size,
- deltas.delta_count,
- deltas.delta_size
-FROM totals_per_callsite totals
-JOIN deltas_per_callsite deltas USING (upid, callsite_id)
-JOIN callsites_by_id USING (callsite_id);
-
-CREATE VIEW callsite_stats_proto AS
-SELECT
- upid,
- RepeatedField(
- HeapProfileCallsiteStats_CallsiteStats(
- 'callsite', callsite_proto,
- 'total_count', total_count,
- 'total_bytes', total_size,
- 'delta_count', delta_count,
- 'delta_bytes', delta_size
- )
- ) AS repeated_callsite_stats
-FROM callsite_stats
-GROUP BY 1;
-
-CREATE VIEW instance_stats_view AS
-SELECT HeapProfileCallsiteStats_InstanceStats(
- 'pid', process.pid,
- 'process_name', process.name,
- 'callsite_stats', repeated_callsite_stats
-) AS instance_stats_proto
-FROM callsite_stats_proto JOIN process USING (upid);
-
-CREATE VIEW heap_profile_callsite_stats_output AS
-SELECT HeapProfileCallsiteStats(
- 'instance_stats',
- (SELECT RepeatedField(instance_stats_proto) FROM instance_stats_view)
-);
diff --git a/src/trace_processor/metrics/android/heap_profile_callsites.sql b/src/trace_processor/metrics/android/heap_profile_callsites.sql
new file mode 100644
index 0000000..a0cd0c4
--- /dev/null
+++ b/src/trace_processor/metrics/android/heap_profile_callsites.sql
@@ -0,0 +1,216 @@
+--
+-- 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.
+--
+
+-- Join frames with symbols and mappings to get a textual representation.
+CREATE TABLE symbolized_frame AS
+SELECT
+ frame_id,
+ symbol_name,
+ mapping_name,
+ HASH(symbol_name, mapping_name) frame_hash,
+ HeapProfileCallsites_Frame(
+ 'name', symbol_name,
+ 'mapping_name', mapping_name
+ ) AS frame_proto
+FROM (
+ SELECT
+ spf.id AS frame_id,
+ IFNULL(
+ (SELECT name FROM stack_profile_symbol symbol
+ WHERE symbol.symbol_set_id = spf.symbol_set_id
+ LIMIT 1),
+ spf.name
+ ) AS symbol_name,
+ spm.name AS mapping_name
+ FROM stack_profile_frame spf
+ JOIN stack_profile_mapping spm
+ ON spf.mapping = spm.id
+);
+
+-- Required to join with callsites
+CREATE UNIQUE INDEX symbolized_frame_idx ON symbolized_frame(frame_id);
+
+-- View that joins callsites with frames. Allocation-agnostic, only used to
+-- generated the hashed callsites.
+CREATE TABLE callsites AS
+SELECT cs.id, cs.parent_id, cs.depth, sf.frame_hash
+FROM stack_profile_callsite cs
+JOIN symbolized_frame sf USING(frame_id);
+
+DROP INDEX symbolized_frame_idx;
+
+-- heapprofd-based callsite ids are based on frame addresses, whereas we want
+-- to group by symbol names.
+-- Create a unique ID for each subtree by traversing from the root.
+-- 1 self_hash can correspond to N callsite_ids (which can then be used to join
+-- with allocs).
+CREATE TABLE hashed_callsites AS
+WITH RECURSIVE callsite_hasher(id, self_hash, parent_hash, frame_hash) AS (
+ SELECT
+ cs.id,
+ cs.frame_hash,
+ -1,
+ cs.frame_hash
+ FROM callsites cs
+ WHERE cs.depth = 0
+ UNION ALL
+ SELECT
+ child.id,
+ HASH(child.frame_hash, parent.self_hash),
+ parent.self_hash,
+ child.frame_hash
+ FROM callsite_hasher parent
+ JOIN callsites child
+ ON parent.id = child.parent_id
+)
+SELECT
+ self_hash,
+ parent_hash,
+ frame_hash,
+ id callsite_id
+FROM callsite_hasher;
+
+DROP TABLE callsites;
+
+CREATE VIEW hashed_callsite_tree AS
+SELECT DISTINCT self_hash, parent_hash, frame_hash
+FROM hashed_callsites;
+
+-- Required to join with allocs
+CREATE INDEX hashed_callsites_id_idx ON hashed_callsites(callsite_id);
+
+-- Computes the allocations for each hash-based callsite.
+CREATE TABLE self_allocs AS
+SELECT
+ hc.self_hash,
+ alloc.upid,
+ SUM(alloc.count) AS delta_count,
+ SUM(CASE WHEN alloc.count > 0 THEN alloc.count ELSE 0 END) AS total_count,
+ SUM(alloc.size) AS delta_bytes,
+ SUM(CASE WHEN alloc.size > 0 THEN alloc.size ELSE 0 END) AS total_bytes
+FROM hashed_callsites hc
+JOIN heap_profile_allocation alloc USING (callsite_id)
+GROUP BY 1, 2;
+
+DROP INDEX hashed_callsites_id_idx;
+
+-- For each allocation (each self_alloc), emit a row for each ancestor and
+-- aggregate them by self_hash.
+CREATE TABLE child_allocs AS
+WITH RECURSIVE parent_traversal(
+ self_hash, parent_hash, upid,
+ delta_count, total_count, delta_bytes, total_bytes) AS (
+ SELECT
+ sa.self_hash,
+ hc.parent_hash,
+ sa.upid,
+ sa.delta_count,
+ sa.total_count,
+ sa.delta_bytes,
+ sa.total_bytes
+ FROM self_allocs sa
+ JOIN hashed_callsite_tree hc ON sa.self_hash = hc.self_hash
+ UNION ALL
+ SELECT
+ parent.self_hash,
+ parent.parent_hash,
+ child.upid,
+ child.delta_count,
+ child.total_count,
+ child.delta_bytes,
+ child.total_bytes
+ FROM parent_traversal child
+ JOIN hashed_callsite_tree parent
+ ON child.parent_hash = parent.self_hash
+)
+SELECT
+ self_hash,
+ upid,
+ SUM(delta_count) AS delta_count,
+ SUM(total_count) AS total_count,
+ SUM(delta_bytes) AS delta_bytes,
+ SUM(total_bytes) AS total_bytes
+FROM parent_traversal
+GROUP BY 1, 2;
+
+CREATE VIEW self_allocs_proto AS
+SELECT
+ self_hash,
+ upid,
+ HeapProfileCallsites_Counters(
+ 'delta_count', delta_count, 'total_count', total_count,
+ 'delta_bytes', delta_bytes, 'total_bytes', total_bytes
+ ) AS allocs_proto
+FROM self_allocs;
+
+CREATE VIEW child_allocs_proto AS
+SELECT
+ self_hash,
+ upid,
+ HeapProfileCallsites_Counters(
+ 'delta_count', delta_count, 'total_count', total_count,
+ 'delta_bytes', delta_bytes, 'total_bytes', total_bytes
+ ) AS allocs_proto
+FROM child_allocs;
+
+-- Required to map back to the symbol.
+CREATE INDEX symbolized_frame_hash_idx ON symbolized_frame(frame_hash);
+
+CREATE TABLE process_callsite AS
+SELECT
+ ca.upid,
+ ca.self_hash,
+ tree.parent_hash,
+ frame.frame_proto,
+ sa.allocs_proto AS self_allocs_proto,
+ ca.allocs_proto AS child_allocs_proto
+FROM hashed_callsite_tree tree
+JOIN (SELECT DISTINCT frame_hash, frame_proto FROM symbolized_frame) frame
+ USING (frame_hash)
+JOIN child_allocs_proto ca
+ USING (self_hash)
+LEFT JOIN self_allocs_proto sa
+ USING (self_hash, upid)
+ORDER BY 1, 2;
+
+DROP INDEX symbolized_frame_hash_idx;
+
+CREATE VIEW process_callsite_proto AS
+SELECT
+ upid,
+ RepeatedField(HeapProfileCallsites_Callsite(
+ 'hash', self_hash,
+ 'parent_hash', parent_hash,
+ 'frame', frame_proto,
+ 'self_allocs', self_allocs_proto,
+ 'child_allocs', child_allocs_proto
+ )) AS repeated_callsite_proto
+FROM process_callsite
+GROUP BY 1;
+
+CREATE VIEW instance_stats_view AS
+SELECT HeapProfileCallsites_InstanceStats(
+ 'pid', process.pid,
+ 'process_name', process.name,
+ 'callsites', repeated_callsite_proto
+) AS instance_stats_proto
+FROM process_callsite_proto JOIN process USING (upid);
+
+CREATE VIEW heap_profile_callsites_output AS
+SELECT HeapProfileCallsites(
+ 'instance_stats',
+ (SELECT RepeatedField(instance_stats_proto) FROM instance_stats_view)
+);
diff --git a/src/trace_processor/metrics/metrics.descriptor.h b/src/trace_processor/metrics/metrics.descriptor.h
index 23afda4..f50e3ee 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)
// 5600f41770c36931db20de64a430f87e1a38fe05
// SHA1(protos/perfetto/metrics/metrics.proto)
-// e37a486a88d9234259ae74e68ffdc43aa424891c
+// 9410d04aaa3afacc42cdfa881f34ab41f3bff56b
// 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, 9549> kMetricsDescriptor{
+constexpr std::array<uint8_t, 9635> 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,282 +540,289 @@
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, 0xf5, 0x05, 0x0a, 0x41, 0x70, 0x72,
+ 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xd7, 0x06, 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, 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, 0x9a, 0x05, 0x0a,
- 0x18, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
- 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74,
- 0x73, 0x12, 0x5e, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
- 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x37, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70,
+ 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,
0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
- 0x69, 0x74, 0x65, 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, 0x3e, 0x0a, 0x05, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x12,
- 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61,
- 0x70, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e,
- 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x51, 0x0a, 0x08, 0x43, 0x61, 0x6c,
- 0x6c, 0x73, 0x69, 0x74, 0x65, 0x12, 0x45, 0x0a, 0x05, 0x66, 0x72, 0x61,
- 0x6d, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 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, 0x53, 0x74,
- 0x61, 0x74, 0x73, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x05, 0x66,
- 0x72, 0x61, 0x6d, 0x65, 0x1a, 0xe3, 0x01, 0x0a, 0x0d, 0x43, 0x61, 0x6c,
- 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x4e,
- 0x0a, 0x08, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x69, 0x74, 0x65, 0x73, 0x12, 0x5a, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74,
+ 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 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, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e,
- 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x52, 0x08, 0x63, 0x61,
- 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f,
- 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f,
- 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c,
- 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
- 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73,
- 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x63, 0x6f,
- 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64,
- 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a,
- 0x0b, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73,
- 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x74,
- 0x61, 0x42, 0x79, 0x74, 0x65, 0x73, 0x1a, 0xa4, 0x01, 0x0a, 0x0d, 0x49,
+ 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 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,
- 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x0d, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72,
- 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
- 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5e, 0x0a, 0x0e, 0x63, 0x61, 0x6c,
- 0x6c, 0x73, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18,
- 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 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, 0x53, 0x74, 0x61, 0x74, 0x73,
- 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61,
- 0x74, 0x73, 0x52, 0x0d, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
- 0x53, 0x74, 0x61, 0x74, 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, 0x70, 0x61,
- 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xc0, 0x01,
- 0x0a, 0x12, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63,
- 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x08,
- 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03,
+ 0x1a, 0x3e, 0x0a, 0x05, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x70,
+ 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67,
+ 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x8e, 0x01, 0x0a, 0x08, 0x43, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74,
+ 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75,
+ 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
+ 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12,
+ 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65,
+ 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b,
+ 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x74, 0x61,
+ 0x42, 0x79, 0x74, 0x65, 0x73, 0x1a, 0xa6, 0x02, 0x0a, 0x08, 0x43, 0x61,
+ 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61,
+ 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x68, 0x61,
+ 0x73, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
+ 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12,
+ 0x41, 0x0a, 0x05, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x2b, 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, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52,
- 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x1a, 0x61, 0x0a,
- 0x07, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x21, 0x0a, 0x0c,
- 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b,
- 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75,
- 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x75, 0x69,
- 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
- 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52,
- 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65,
- 0x42, 0x02, 0x48, 0x03, 0x0a, 0x80, 0x02, 0x0a, 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,
+ 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, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
+ 0x05, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x4f, 0x0a, 0x0b, 0x73, 0x65,
+ 0x6c, 0x66, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x2e, 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, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+ 0x65, 0x72, 0x73, 0x52, 0x0a, 0x73, 0x65, 0x6c, 0x66, 0x41, 0x6c, 0x6c,
+ 0x6f, 0x63, 0x73, 0x12, 0x51, 0x0a, 0x0c, 0x63, 0x68, 0x69, 0x6c, 0x64,
+ 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x2e, 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, 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,
+ 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,
+ 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, 0x4c, 0x0a, 0x09, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74,
+ 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 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, 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,
+ 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,
+ 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66,
0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22,
- 0xad, 0x01, 0x0a, 0x12, 0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
- 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x41,
- 0x0a, 0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x29, 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, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x06, 0x66,
- 0x72, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x54, 0x0a, 0x05, 0x46, 0x72, 0x61,
- 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x75,
- 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
- 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 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,
- 0xdb, 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,
+ 0xc0, 0x01, 0x0a, 0x12, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
+ 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x47,
+ 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 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, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67,
+ 0x65, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x1a,
+ 0x61, 0x0a, 0x07, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x21,
+ 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61,
+ 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a,
+ 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03,
+ 0x75, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69,
+ 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f,
+ 0x64, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x80, 0x02, 0x0a, 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, 0x12, 0x0f, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x22, 0xad, 0x01, 0x0a, 0x12, 0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62,
+ 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
+ 0x12, 0x41, 0x0a, 0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 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, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
+ 0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x54, 0x0a, 0x05, 0x46,
+ 0x72, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75,
+ 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f,
+ 0x64, 0x75, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c,
+ 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
+ 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, 0xcf, 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, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 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, 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,
+ 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, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70,
+ 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, 0x6c, 0x6d, 0x6b, 0x5f, 0x6d,
+ 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x69, 0x6f, 0x6e, 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,
+ 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, 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, 0x41, 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, 0x5f, 0x73, 0x74, 0x61, 0x74,
- 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, 0x22, 0xd2,
- 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,
+ 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, 0x22, 0xd2, 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, 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, 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, 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, 0xbf, 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,
+ 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, 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,
- 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, 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,
+ 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, 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, 0x65, 0x72, 0x66, 0x65,
+ 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, 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,
+ 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, 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, 0x68, 0x0a, 0x1b, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70,
- 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73,
- 0x69, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x0e, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x29, 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, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x18,
+ 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, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43,
- 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 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,
+ 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, 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, 0x42, 0x02, 0x48, 0x03}};
+ 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}};
} // namespace perfetto
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index 5fbb119..8bc2fc9 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -2730,6 +2730,21 @@
obj.object_id = object.id();
obj.self_size = object.self_size();
obj.type_id = object.type_id();
+ auto ref_field_ids_it = object.reference_field_id();
+ auto ref_object_ids_it = object.reference_object_id();
+ for (; ref_field_ids_it && ref_object_ids_it;
+ ++ref_field_ids_it, ++ref_object_ids_it) {
+ HeapGraphTracker::SourceObject::Reference ref;
+ ref.field_name_id = ref_field_ids_it->as_uint64();
+ ref.owned_object_id = ref_object_ids_it->as_uint64();
+ obj.references.emplace_back(std::move(ref));
+ }
+
+ if (ref_field_ids_it || ref_object_ids_it) {
+ context_->storage->IncrementIndexedStats(stats::heap_graph_missing_packet,
+ static_cast<int>(upid));
+ continue;
+ }
context_->heap_graph_tracker->AddObject(upid, ts, std::move(obj));
}
for (auto it = heap_graph.type_names(); it; ++it) {
@@ -2740,6 +2755,14 @@
context_->heap_graph_tracker->AddInternedTypeName(
entry.iid(), context_->storage->InternString(str_view));
}
+ for (auto it = heap_graph.field_names(); it; ++it) {
+ protos::pbzero::InternedString::Decoder entry(it->data(), it->size());
+ const char* str = reinterpret_cast<const char*>(entry.str().data);
+ auto str_view = base::StringView(str, entry.str().size);
+
+ context_->heap_graph_tracker->AddInternedFieldName(
+ entry.iid(), context_->storage->InternString(str_view));
+ }
if (!heap_graph.continued()) {
context_->heap_graph_tracker->FinalizeProfile();
}
diff --git a/src/trace_processor/read_trace.cc b/src/trace_processor/read_trace.cc
new file mode 100644
index 0000000..8ba8f16
--- /dev/null
+++ b/src/trace_processor/read_trace.cc
@@ -0,0 +1,123 @@
+/*
+ * 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 "perfetto/trace_processor/read_trace.h"
+
+#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/trace_processor/trace_processor.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
+#define PERFETTO_HAS_AIO_H() 1
+#else
+#define PERFETTO_HAS_AIO_H() 0
+#endif
+
+#if PERFETTO_HAS_AIO_H()
+#include <aio.h>
+#endif
+
+namespace perfetto {
+namespace trace_processor {
+
+util::Status ReadTrace(
+ TraceProcessor* tp,
+ const char* filename,
+ const std::function<void(uint64_t parsed_size)>& progress_callback) {
+ base::ScopedFile fd(base::OpenFile(filename, O_RDONLY));
+ if (!fd)
+ return util::ErrStatus("Could not open trace file (path: %s)", filename);
+
+ // 1MB chunk size seems the best tradeoff on a MacBook Pro 2013 - i7 2.8 GHz.
+ constexpr size_t kChunkSize = 1024 * 1024;
+ uint64_t file_size = 0;
+
+#if PERFETTO_HAS_AIO_H()
+ // Load the trace in chunks using async IO. We create a simple pipeline where,
+ // at each iteration, we parse the current chunk and asynchronously start
+ // reading the next chunk.
+ struct aiocb cb {};
+ cb.aio_nbytes = kChunkSize;
+ cb.aio_fildes = *fd;
+
+ std::unique_ptr<uint8_t[]> aio_buf(new uint8_t[kChunkSize]);
+#if defined(MEMORY_SANITIZER)
+ // Just initialize the memory to make the memory sanitizer happy as it
+ // cannot track aio calls below.
+ memset(aio_buf.get(), 0, kChunkSize);
+#endif // defined(MEMORY_SANITIZER)
+ cb.aio_buf = aio_buf.get();
+
+ PERFETTO_CHECK(aio_read(&cb) == 0);
+ struct aiocb* aio_list[1] = {&cb};
+
+ for (int i = 0;; i++) {
+ if (progress_callback && i % 128 == 0)
+ progress_callback(file_size);
+
+ // Block waiting for the pending read to complete.
+ PERFETTO_CHECK(aio_suspend(aio_list, 1, nullptr) == 0);
+ auto rsize = aio_return(&cb);
+ if (rsize <= 0)
+ break;
+ file_size += static_cast<uint64_t>(rsize);
+
+ // Take ownership of the completed buffer and enqueue a new async read
+ // with a fresh buffer.
+ std::unique_ptr<uint8_t[]> buf(std::move(aio_buf));
+ aio_buf.reset(new uint8_t[kChunkSize]);
+#if defined(MEMORY_SANITIZER)
+ // Just initialize the memory to make the memory sanitizer happy as it
+ // cannot track aio calls below.
+ memset(aio_buf.get(), 0, kChunkSize);
+#endif // defined(MEMORY_SANITIZER)
+ cb.aio_buf = aio_buf.get();
+ cb.aio_offset += rsize;
+ PERFETTO_CHECK(aio_read(&cb) == 0);
+
+ // Parse the completed buffer while the async read is in-flight.
+ util::Status status = tp->Parse(std::move(buf), static_cast<size_t>(rsize));
+ if (PERFETTO_UNLIKELY(!status.ok()))
+ return status;
+ }
+#else // PERFETTO_HAS_AIO_H()
+ // Load the trace in chunks using ordinary read().
+ // This version is used on Windows, since there's no aio library.
+ for (int i = 0;; i++) {
+ if (progress_callback && i % 128 == 0)
+ progress_callback(file_size);
+
+ std::unique_ptr<uint8_t[]> buf(new uint8_t[kChunkSize]);
+ auto rsize = read(*fd, buf.get(), kChunkSize);
+ if (rsize <= 0)
+ break;
+ file_size += static_cast<uint64_t>(rsize);
+
+ util::Status status = tp->Parse(std::move(buf), static_cast<size_t>(rsize));
+ if (PERFETTO_UNLIKELY(!status.ok()))
+ return status;
+ }
+#endif // PERFETTO_HAS_AIO_H()
+
+ tp->NotifyEndOfFile();
+
+ if (progress_callback)
+ progress_callback(file_size);
+ return util::OkStatus();
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/stats.h b/src/trace_processor/stats.h
index 8387f37..74eec50 100644
--- a/src/trace_processor/stats.h
+++ b/src/trace_processor/stats.h
@@ -110,6 +110,7 @@
F(json_tokenizer_failure, kSingle, kError, kTrace), \
F(heap_graph_invalid_string_id, kIndexed, kError, kTrace), \
F(heap_graph_non_finalized_graph, kSingle, kError, kTrace), \
+ F(heap_graph_malformed_packet, kIndexed, kError, kTrace), \
F(heap_graph_missing_packet, kIndexed, kDataLoss, kTrace), \
F(heapprofd_buffer_corrupted, kIndexed, kError, kTrace), \
F(heapprofd_buffer_overran, kIndexed, kDataLoss, kTrace), \
diff --git a/src/trace_processor/tables/profiler_tables.h b/src/trace_processor/tables/profiler_tables.h
index bf70637..16133d8 100644
--- a/src/trace_processor/tables/profiler_tables.h
+++ b/src/trace_processor/tables/profiler_tables.h
@@ -40,10 +40,21 @@
C(int64_t, graph_sample_ts) \
C(int64_t, object_id) \
C(int64_t, self_size) \
+ C(int64_t, reference_set_id) \
C(StringPool::Id, type_name)
PERFETTO_TP_TABLE(PERFETTO_TP_HEAP_GRAPH_OBJECT_DEF);
+#define PERFETTO_TP_HEAP_GRAPH_REFERENCE_DEF(NAME, PARENT, C) \
+ NAME(HeapGraphReferenceTable, "heap_graph_reference") \
+ PERFETTO_TP_ROOT_TABLE(PARENT, C) \
+ C(int64_t, reference_set_id) \
+ C(int64_t, owner_id) \
+ C(int64_t, owned_id) \
+ C(StringPool::Id, field_name)
+
+PERFETTO_TP_TABLE(PERFETTO_TP_HEAP_GRAPH_REFERENCE_DEF);
+
#define PERFETTO_TP_VULKAN_MEMORY_ALLOCATIONS_DEF(NAME, PARENT, C) \
NAME(VulkanMemoryAllocationsTable, "vulkan_memory_allocations") \
PERFETTO_TP_ROOT_TABLE(PARENT, C) \
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 2086b74..1492cf7 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -376,6 +376,9 @@
DbSqliteTable::RegisterTable(*db_, &storage->heap_graph_object_table(),
storage->heap_graph_object_table().table_name());
DbSqliteTable::RegisterTable(
+ *db_, &storage->heap_graph_reference_table(),
+ storage->heap_graph_reference_table().table_name());
+ DbSqliteTable::RegisterTable(
*db_, &storage->vulkan_memory_allocations_table(),
storage->vulkan_memory_allocations_table().table_name());
}
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index f37b5ab..e86f220 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -34,6 +34,7 @@
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/string_splitter.h"
+#include "perfetto/trace_processor/read_trace.h"
#include "perfetto/trace_processor/trace_processor.h"
#include "src/trace_processor/metrics/metrics.descriptor.h"
#include "src/trace_processor/proto_to_json.h"
@@ -46,13 +47,6 @@
#define PERFETTO_HAS_SIGNAL_H() 0
#endif
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
- PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
-#define PERFETTO_HAS_AIO_H() 1
-#else
-#define PERFETTO_HAS_AIO_H() 0
-#endif
-
#if PERFETTO_BUILDFLAG(PERFETTO_TP_LINENOISE)
#include <linenoise.h>
#include <pwd.h>
@@ -69,10 +63,6 @@
#include <signal.h>
#endif
-#if PERFETTO_HAS_AIO_H()
-#include <aio.h>
-#endif
-
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#define ftruncate _chsize
#else
@@ -643,94 +633,6 @@
bool wide = false;
};
-#if PERFETTO_HAS_AIO_H()
-uint64_t ReadTrace(TraceProcessor* tp, int file_descriptor) {
- // Load the trace in chunks using async IO. We create a simple pipeline where,
- // at each iteration, we parse the current chunk and asynchronously start
- // reading the next chunk.
-
- // 1MB chunk size seems the best tradeoff on a MacBook Pro 2013 - i7 2.8 GHz.
- constexpr size_t kChunkSize = 1024 * 1024;
- uint64_t file_size = 0;
-
- struct aiocb cb {};
- cb.aio_nbytes = kChunkSize;
- cb.aio_fildes = file_descriptor;
-
- std::unique_ptr<uint8_t[]> aio_buf(new uint8_t[kChunkSize]);
-#if defined(MEMORY_SANITIZER)
- // Just initialize the memory to make the memory sanitizer happy as it
- // cannot track aio calls below.
- memset(aio_buf.get(), 0, kChunkSize);
-#endif // defined(MEMORY_SANITIZER)
- cb.aio_buf = aio_buf.get();
-
- PERFETTO_CHECK(aio_read(&cb) == 0);
- struct aiocb* aio_list[1] = {&cb};
-
- for (int i = 0;; i++) {
- if (i % 128 == 0)
- fprintf(stderr, "\rLoading trace: %.2f MB\r", file_size / 1E6);
-
- // Block waiting for the pending read to complete.
- PERFETTO_CHECK(aio_suspend(aio_list, 1, nullptr) == 0);
- auto rsize = aio_return(&cb);
- if (rsize <= 0)
- break;
- file_size += static_cast<uint64_t>(rsize);
-
- // Take ownership of the completed buffer and enqueue a new async read
- // with a fresh buffer.
- std::unique_ptr<uint8_t[]> buf(std::move(aio_buf));
- aio_buf.reset(new uint8_t[kChunkSize]);
-#if defined(MEMORY_SANITIZER)
- // Just initialize the memory to make the memory sanitizer happy as it
- // cannot track aio calls below.
- memset(aio_buf.get(), 0, kChunkSize);
-#endif // defined(MEMORY_SANITIZER)
- cb.aio_buf = aio_buf.get();
- cb.aio_offset += rsize;
- PERFETTO_CHECK(aio_read(&cb) == 0);
-
- // Parse the completed buffer while the async read is in-flight.
- util::Status status = tp->Parse(std::move(buf), static_cast<size_t>(rsize));
- if (PERFETTO_UNLIKELY(!status.ok())) {
- PERFETTO_ELOG("Fatal error while parsing trace: %s", status.c_message());
- exit(1);
- }
- }
- tp->NotifyEndOfFile();
- return file_size;
-}
-#else // PERFETTO_HAS_AIO_H()
-uint64_t ReadTrace(TraceProcessor* tp, int file_descriptor) {
- // Load the trace in chunks using ordinary read().
- // This version is used on Windows, since there's no aio library.
-
- constexpr size_t kChunkSize = 1024 * 1024;
- uint64_t file_size = 0;
-
- for (int i = 0;; i++) {
- if (i % 128 == 0)
- fprintf(stderr, "\rLoading trace: %.2f MB\r", file_size / 1E6);
-
- std::unique_ptr<uint8_t[]> buf(new uint8_t[kChunkSize]);
- auto rsize = read(file_descriptor, buf.get(), kChunkSize);
- if (rsize <= 0)
- break;
- file_size += static_cast<uint64_t>(rsize);
-
- util::Status status = tp->Parse(std::move(buf), static_cast<size_t>(rsize));
- if (PERFETTO_UNLIKELY(!status.ok())) {
- PERFETTO_ELOG("Fatal error while parsing trace: %s", status.c_message());
- exit(1);
- }
- }
- tp->NotifyEndOfFile();
- return file_size;
-}
-#endif // PERFETTO_HAS_AIO_H()
-
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
void PrintUsage(char** argv) {
PERFETTO_ELOG(
@@ -955,18 +857,22 @@
// Load the trace file into the trace processor.
Config config;
std::unique_ptr<TraceProcessor> tp = TraceProcessor::CreateInstance(config);
- base::ScopedFile fd(base::OpenFile(options.trace_file_path, O_RDONLY));
- if (!fd) {
- PERFETTO_ELOG("Could not open trace file (path: %s)",
- options.trace_file_path.c_str());
- return 1;
- }
auto t_load_start = base::GetWallTimeNs();
- uint64_t file_size = ReadTrace(tp.get(), *fd);
+ double size_mb = 0;
+ util::Status read_status =
+ ReadTrace(tp.get(), options.trace_file_path.c_str(),
+ [&size_mb](size_t parsed_size) {
+ size_mb = parsed_size / 1E6;
+ fprintf(stderr, "\rLoading trace: %.2f MB\r", size_mb);
+ });
+ if (!read_status.ok()) {
+ PERFETTO_ELOG("Could not read trace file (path: %s): %s",
+ options.trace_file_path.c_str(), read_status.c_message());
+ return 1;
+ }
auto t_load = base::GetWallTimeNs() - t_load_start;
double t_load_s = t_load.count() / 1E9;
- double size_mb = file_size / 1E6;
PERFETTO_ILOG("Trace loaded: %.2f MB (%.1f MB/s)", size_mb,
size_mb / t_load_s);
g_tp = tp.get();
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 536fcd5..2f6f77e 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -1284,6 +1284,14 @@
return &heap_graph_object_table_;
}
+ const tables::HeapGraphReferenceTable& heap_graph_reference_table() const {
+ return heap_graph_reference_table_;
+ }
+
+ tables::HeapGraphReferenceTable* mutable_heap_graph_reference_table() {
+ return &heap_graph_reference_table_;
+ }
+
const tables::GpuTrackTable& gpu_track_table() const {
return gpu_track_table_;
}
@@ -1405,6 +1413,8 @@
// Symbol tables (mappings from frames to symbol names)
tables::SymbolTable symbol_table_{&string_pool_, nullptr};
tables::HeapGraphObjectTable heap_graph_object_table_{&string_pool_, nullptr};
+ tables::HeapGraphReferenceTable heap_graph_reference_table_{&string_pool_,
+ nullptr};
tables::VulkanMemoryAllocationsTable vulkan_memory_allocations_table_{
&string_pool_, nullptr};
diff --git a/test/metrics/heap_profile.textproto b/test/metrics/heap_profile.textproto
index 5e91061..2d83244 100644
--- a/test/metrics/heap_profile.textproto
+++ b/test/metrics/heap_profile.textproto
@@ -54,12 +54,23 @@
mapping_id: 1
rel_pc: 0x3000
}
+ frames {
+ iid: 4
+ function_name_id: 2
+ mapping_id: 1
+ rel_pc: 0x4000
+ }
callstacks {
iid: 1
frame_ids: 1
frame_ids: 2
frame_ids: 3
}
+ callstacks {
+ iid: 2
+ frame_ids: 1
+ frame_ids: 4
+ }
mappings {
iid: 1
path_string_ids: 4
@@ -74,6 +85,13 @@
alloc_count: 2
free_count: 1
}
+ samples {
+ callstack_id: 2
+ self_allocated: 100
+ self_freed: 10
+ alloc_count: 10
+ free_count: 1
+ }
}
}
}
diff --git a/test/metrics/heap_profile_callsite_stats.out b/test/metrics/heap_profile_callsite_stats.out
deleted file mode 100644
index d923353..0000000
--- a/test/metrics/heap_profile_callsite_stats.out
+++ /dev/null
@@ -1,26 +0,0 @@
-heap_profile_callsite_stats {
- instance_stats {
- process_name: "system_server"
- callsite_stats {
- callsite {
- frame {
- name: "symbolized f3"
- mapping_name: "/liblib.so"
- }
- frame {
- name: "f2"
- mapping_name: "/liblib.so"
- }
- frame {
- name: "f1"
- mapping_name: "/liblib.so"
- }
- }
- total_count: 2
- total_bytes: 2000
- delta_count: 1
- delta_bytes: 1000
- }
- pid: 2
- }
-}
diff --git a/test/metrics/heap_profile_callsites.out b/test/metrics/heap_profile_callsites.out
new file mode 100644
index 0000000..3ca8b70
--- /dev/null
+++ b/test/metrics/heap_profile_callsites.out
@@ -0,0 +1,60 @@
+heap_profile_callsites {
+ instance_stats {
+ pid: 2
+ process_name: "system_server"
+ callsites {
+ hash: -3761178652842017503
+ parent_hash: 5412623030728177384
+ frame {
+ name: "symbolized f3"
+ mapping_name: "/liblib.so"
+ }
+ self_allocs {
+ total_count: 2
+ total_bytes: 2000
+ delta_count: 1
+ delta_bytes: 1000
+ }
+ child_allocs {
+ total_count: 2
+ total_bytes: 2000
+ delta_count: 1
+ delta_bytes: 1000
+ }
+ }
+ callsites {
+ hash: 5412623030728177384
+ parent_hash: 6947621464292123521
+ frame {
+ name: "f2"
+ mapping_name: "/liblib.so"
+ }
+ self_allocs {
+ total_count: 10
+ total_bytes: 100
+ delta_count: 9
+ delta_bytes: 90
+ }
+ child_allocs {
+ total_count: 12
+ total_bytes: 2100
+ delta_count: 10
+ delta_bytes: 1090
+ }
+ }
+ callsites {
+ hash: 6947621464292123521
+ parent_hash: -1
+ frame {
+ name: "f1"
+ mapping_name: "/liblib.so"
+ }
+ child_allocs {
+ total_count: 12
+ total_bytes: 2100
+ delta_count: 10
+ delta_bytes: 1090
+ }
+ }
+ }
+}
diff --git a/test/metrics/index b/test/metrics/index
index 4e0c3de..a159f21 100644
--- a/test/metrics/index
+++ b/test/metrics/index
@@ -18,8 +18,8 @@
android_package_list.py android_package_list android_package_list.out
-heap_profile.textproto heap_profile_callsite_stats heap_profile_callsite_stats.out
+heap_profile.textproto heap_profile_callsites heap_profile_callsites.out
heap_profile_no_symbols.textproto unsymbolized_frames unsymbolized_frames.out
# Json output
-../data/memory_counters.pb trace_metadata trace_metadata.json.out
\ No newline at end of file
+../data/memory_counters.pb trace_metadata trace_metadata.json.out
diff --git a/tools/gen_amalgamated b/tools/gen_amalgamated
index 9113a5e..e7892b5 100755
--- a/tools/gen_amalgamated
+++ b/tools/gen_amalgamated
@@ -548,10 +548,10 @@
if args.check:
output = os.path.join(tempfile.mkdtemp(), 'perfetto_amalgamated')
+ out = gn_utils.prepare_out_directory(args.gn_args, 'tmp.gen_amalgamated')
+ if not args.quiet:
+ print('Building project...')
try:
- if not args.quiet:
- print('Building project...')
- out = gn_utils.prepare_out_directory(args.gn_args, 'tmp.gen_amalgamated')
desc = gn_utils.load_build_description(out)
# We need to build everything first so that the necessary header
diff --git a/tools/gn_utils.py b/tools/gn_utils.py
index 1494279..450f8ee 100644
--- a/tools/gn_utils.py
+++ b/tools/gn_utils.py
@@ -39,10 +39,10 @@
print(
'Command "{}" failed in {}:'.format(' '.join(cmd), cwd),
file=sys.stderr)
- print(e.output, file=sys.stderr)
+ print(e.output.decode(), file=sys.stderr)
sys.exit(1)
else:
- return output
+ return output.decode()
def repo_root():
diff --git a/tools/test_gen_amalgamated.py b/tools/test_gen_amalgamated.py
index c4b7813..a5354c6 100755
--- a/tools/test_gen_amalgamated.py
+++ b/tools/test_gen_amalgamated.py
@@ -20,6 +20,15 @@
from compat import quote
+GN_ARGS = ' '.join(
+ quote(s) for s in (
+ 'is_debug=false',
+ 'is_perfetto_build_generator=true',
+ 'is_perfetto_embedder=true',
+ 'use_custom_libcxx=false',
+ 'enable_perfetto_ipc=true',
+ ))
+
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
@@ -28,7 +37,7 @@
command = [path] + list(args)
print('Running:', ' '.join(quote(c) for c in command))
try:
- return subprocess.check_output(command, cwd=ROOT_DIR)
+ return subprocess.check_output(command, cwd=ROOT_DIR).decode()
except subprocess.CalledProcessError as e:
assert False, 'Command: {} failed'.format(' '.join(command))
@@ -40,9 +49,9 @@
def check_amalgamated_dependencies():
os_deps = {}
for os_name in ['android', 'linux', 'mac']:
- os_deps[os_name] = call('gen_amalgamated', '--gn_args',
- 'target_os="%s"' % os_name, '--dump-deps',
- '--quiet').split('\n')
+ gn_args = (' target_os="%s"' % os_name) + GN_ARGS
+ os_deps[os_name] = call('gen_amalgamated', '--gn_args', gn_args,
+ '--dump-deps', '--quiet').split('\n')
for os_name, deps in os_deps.items():
for dep in deps:
for other_os, other_deps in os_deps.items():
diff --git a/tools/trace_to_text/main.cc b/tools/trace_to_text/main.cc
index eef61b0..66651f8 100644
--- a/tools/trace_to_text/main.cc
+++ b/tools/trace_to_text/main.cc
@@ -20,6 +20,7 @@
#include <vector>
#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_utils.h"
#include "tools/trace_to_text/symbolize_profile.h"
#include "tools/trace_to_text/trace_to_json.h"
#include "tools/trace_to_text/trace_to_profile.h"
@@ -38,16 +39,34 @@
int Usage(const char* argv0) {
printf(
- "Usage: %s systrace|json|ctrace|text|profile [--truncate start|end] "
+ "Usage: %s systrace|json|ctrace|text|profile [--pid PID] "
+ "[--timestamps TIMESTAMP1,TIMESTAMP2,...] "
+ "[--truncate start|end] "
"[trace.pb] "
- "[trace.txt]\n",
+ "[trace.txt]\n"
+ "\nProfile mode only:\n"
+ "\t--timestamps TIMESTAMP1,TIMESTAMP2,... generate profiles "
+ "only for these timestamps\n"
+ "\t--pid PID generate profiles only for this process id\n",
argv0);
return 1;
}
+uint64_t StringToUint64OrDie(const char* str) {
+ char* end;
+ uint64_t number = static_cast<uint64_t>(strtoll(str, &end, 10));
+ if (*end != '\0') {
+ PERFETTO_ELOG("Invalid %s. Expected decimal integer.", str);
+ exit(1);
+ }
+ return number;
+}
+
int Main(int argc, char** argv) {
std::vector<const char*> positional_args;
Keep truncate_keep = Keep::kAll;
+ uint64_t pid = 0;
+ std::vector<uint64_t> timestamps;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
printf("%s\n", PERFETTO_GET_GIT_REVISION());
@@ -65,6 +84,15 @@
"start of the trace.");
return Usage(argv[0]);
}
+ } else if (i <= argc && strcmp(argv[i], "--pid") == 0) {
+ i++;
+ pid = StringToUint64OrDie(argv[i]);
+ } else if (i <= argc && strcmp(argv[i], "--timestamps") == 0) {
+ i++;
+ std::vector<std::string> ts_strings = base::SplitString(argv[i], ",");
+ for (const std::string& ts : ts_strings) {
+ timestamps.emplace_back(StringToUint64OrDie(ts.c_str()));
+ }
} else {
positional_args.push_back(argv[i]);
}
@@ -105,6 +133,12 @@
std::string format(positional_args[0]);
+ if (format != "profile" && (pid != 0 || !timestamps.empty())) {
+ PERFETTO_ELOG(
+ "--pid and --timestamps are supported only for profile format.");
+ return 1;
+ }
+
if (format == "json")
return TraceToJson(input_stream, output_stream, /*compress=*/false,
truncate_keep);
@@ -127,7 +161,7 @@
return TraceToText(input_stream, output_stream);
if (format == "profile")
- return TraceToProfile(input_stream, output_stream);
+ return TraceToProfile(input_stream, output_stream, pid, timestamps);
if (format == "symbolize")
return SymbolizeProfile(input_stream, output_stream);
diff --git a/ui/PRESUBMIT.py b/ui/PRESUBMIT.py
index eecdfeb..a4d6df0 100644
--- a/ui/PRESUBMIT.py
+++ b/ui/PRESUBMIT.py
@@ -53,6 +53,9 @@
return [
output_api.PresubmitError("""\
There were tslint errors. You may be able to fix some of them using
-$ {} {} --project {} --fix""".format(relpath(node), relpath(tslint), ui_path))
+$ {} {} --project {} --fix
+
+If this is unexpected: did you remember to do a UI build before running the
+presubmit?""".format(relpath(node), relpath(tslint), ui_path))
]
return []
diff --git a/ui/src/frontend/keyboard_event_handler.ts b/ui/src/frontend/keyboard_event_handler.ts
index 64758b6..ab590ef 100644
--- a/ui/src/frontend/keyboard_event_handler.ts
+++ b/ui/src/frontend/keyboard_event_handler.ts
@@ -43,7 +43,7 @@
if (down && '?' === key) {
toggleHelp();
}
- if (down && 'Enter' === key) {
+ if (down && 'enter' === key) {
e.preventDefault();
executeSearch(e.shiftKey);
}
diff --git a/ui/src/frontend/pan_and_zoom_handler.ts b/ui/src/frontend/pan_and_zoom_handler.ts
index 7401eb6..e771abb 100644
--- a/ui/src/frontend/pan_and_zoom_handler.ts
+++ b/ui/src/frontend/pan_and_zoom_handler.ts
@@ -43,6 +43,10 @@
const HORIZONTAL_WHEEL_PAN_SPEED = 1;
const WHEEL_ZOOM_SPEED = -0.02;
+const EDITING_RANGE_CURSOR = 'ew-resize';
+const SHIFT_CURSOR = 'text';
+const DEFAULT_CURSOR = 'default';
+
enum Pan {
None = 0,
Left = -1,
@@ -91,20 +95,28 @@
private contentOffsetX: number;
private onPanned: (movedPx: number) => void;
private onZoomed: (zoomPositionPx: number, zoomRatio: number) => void;
- private onDragSelect: (selectStartPx: number, selectEndPx: number) => void;
+ private shouldDrag: (currentPx: number) => boolean;
+ private onDrag:
+ (dragStartPx: number, prevPx: number, currentPx: number,
+ editing: boolean) => void;
- constructor({element, contentOffsetX, onPanned, onZoomed, onDragSelect}: {
- element: HTMLElement,
- contentOffsetX: number,
- onPanned: (movedPx: number) => void,
- onZoomed: (zoomPositionPx: number, zoomRatio: number) => void,
- onDragSelect: (selectStartPx: number, selectEndPx: number) => void
- }) {
+ constructor(
+ {element, contentOffsetX, onPanned, onZoomed, shouldDrag, onDrag}: {
+ element: HTMLElement,
+ contentOffsetX: number,
+ onPanned: (movedPx: number) => void,
+ onZoomed: (zoomPositionPx: number, zoomRatio: number) => void,
+ shouldDrag: (currentPx: number) => boolean,
+ onDrag:
+ (dragStartPx: number, prevPx: number, currentPx: number,
+ editing: boolean) => void,
+ }) {
this.element = element;
this.contentOffsetX = contentOffsetX;
this.onPanned = onPanned;
this.onZoomed = onZoomed;
- this.onDragSelect = onDragSelect;
+ this.shouldDrag = shouldDrag;
+ this.onDrag = onDrag;
document.body.addEventListener('keydown', this.boundOnKeyDown);
document.body.addEventListener('keyup', this.boundOnKeyUp);
@@ -112,23 +124,40 @@
this.element.addEventListener('wheel', this.boundOnWheel, {passive: true});
let lastX = -1;
- new DragGestureHandler(this.element, x => {
- if (this.shiftDown && this.dragStartPx !== -1) {
- this.onDragSelect(this.dragStartPx, x);
- } else {
- this.onPanned(lastX - x);
- }
- lastX = x;
- }, x => {
- lastX = x;
- if (this.shiftDown) {
- this.dragStartPx = x;
- }
- }, () => {
- this.dragStartPx = -1;
- });
+ let drag = false;
+ new DragGestureHandler(
+ this.element,
+ x => {
+ // If we started our drag on a time range boundary or shift is down
+ // then we are drag selecting rather than panning.
+ if (drag || this.shiftDown) {
+ this.onDrag(this.dragStartPx, lastX, x, !this.shiftDown);
+ } else {
+ this.onPanned(lastX - x);
+ }
+ lastX = x;
+ },
+ x => {
+ lastX = x;
+ this.dragStartPx = x;
+ drag = this.shouldDrag(x);
+ // Set the cursor style based on where the cursor is when the drag
+ // starts.
+ if (drag) {
+ this.element.style.cursor = EDITING_RANGE_CURSOR;
+ } else if (this.shiftDown) {
+ this.element.style.cursor = SHIFT_CURSOR;
+ }
+ },
+ () => {
+ // Reset the cursor now the drag has ended.
+ this.element.style.cursor =
+ this.shiftDown ? SHIFT_CURSOR : DEFAULT_CURSOR;
+ this.dragStartPx = -1;
+ });
}
+
shutdown() {
document.body.removeEventListener('keydown', this.boundOnKeyDown);
document.body.removeEventListener('keyup', this.boundOnKeyUp);
@@ -176,10 +205,21 @@
globals.frontendLocalState.sidebarVisible ? this.contentOffsetX : 0;
// We can't use layerX here because there are many layers in this element.
this.mousePositionX = e.clientX - pageOffset;
+ // Only change the cursor when hovering, the DragGestureHandler handles
+ // changing the cursor during drag events. This avoids the problem of
+ // the cursor flickering between styles if you drag fast and get too
+ // far from the current time range.
+ if (e.buttons === 0) {
+ if (!this.shouldDrag(this.mousePositionX)) {
+ this.element.style.cursor =
+ this.shiftDown ? SHIFT_CURSOR : DEFAULT_CURSOR;
+ } else {
+ this.element.style.cursor = EDITING_RANGE_CURSOR;
+ }
+ }
if (this.shiftDown) {
const pos = this.mousePositionX - TRACK_SHELL_WIDTH;
- const ts =
- globals.frontendLocalState.timeScale.pxToTime(pos);
+ const ts = globals.frontendLocalState.timeScale.pxToTime(pos);
globals.frontendLocalState.setHoveredTimestamp(ts);
}
}
@@ -235,19 +275,20 @@
handleKey(e, false);
}
+ // TODO(taylori): Move this shift handling into the viewer page.
private updateShift(down: boolean) {
if (down === this.shiftDown) return;
this.shiftDown = down;
if (this.shiftDown) {
if (this.mousePositionX) {
- this.element.style.cursor = 'text';
+ this.element.style.cursor = SHIFT_CURSOR;
const pos = this.mousePositionX - TRACK_SHELL_WIDTH;
const ts = globals.frontendLocalState.timeScale.pxToTime(pos);
globals.frontendLocalState.setHoveredTimestamp(ts);
}
} else {
globals.frontendLocalState.setHoveredTimestamp(-1);
- this.element.style.cursor = 'default';
+ this.element.style.cursor = DEFAULT_CURSOR;
}
globals.frontendLocalState.setShowTimeSelectPreview(this.shiftDown);
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index a1beb3b..9bea6254 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -179,6 +179,26 @@
}
}
+// Checks if the mousePos is within 3px of the start or end of the
+// current selected time range.
+function onTimeRangeBoundary(mousePos: number): 'START'|'END'|null {
+ const startSec = globals.frontendLocalState.selectedTimeRange.startSec;
+ const endSec = globals.frontendLocalState.selectedTimeRange.endSec;
+ if (startSec !== undefined && endSec !== undefined) {
+ const start = globals.frontendLocalState.timeScale.timeToPx(startSec);
+ const end = globals.frontendLocalState.timeScale.timeToPx(endSec);
+ const startDrag = mousePos - TRACK_SHELL_WIDTH;
+ const startDistance = Math.abs(start - startDrag);
+ const endDistance = Math.abs(end - startDrag);
+ const range = 3 * window.devicePixelRatio;
+ // We might be within 3px of both boundaries but we should choose
+ // the closest one.
+ if (startDistance < range && startDistance <= endDistance) return 'START';
+ if (endDistance < range && endDistance <= startDistance) return 'END';
+ }
+ return null;
+}
+
/**
* Top-most level component for the viewer page. Holds tracks, brush timeline,
* panels, and everything else that's part of the main trace viewer page.
@@ -245,19 +265,39 @@
frontendLocalState.updateVisibleTime(newSpan);
globals.rafScheduler.scheduleRedraw();
},
- onDragSelect: (selectStartPx: number|null, selectEndPx: number) => {
- if (!selectStartPx) return;
- this.keepCurrentSelection = true;
- globals.frontendLocalState.setShowTimeSelectPreview(false);
+ shouldDrag: (currentPx: number) => {
+ return onTimeRangeBoundary(currentPx) !== null;
+ },
+ onDrag: (
+ dragStartPx: number,
+ prevPx: number,
+ currentPx: number,
+ editing: boolean) => {
const traceTime = globals.state.traceTime;
const scale = frontendLocalState.timeScale;
- const startPx = Math.min(selectStartPx, selectEndPx);
- const endPx = Math.max(selectStartPx, selectEndPx);
- const startTs = Math.max(traceTime.startSec,
- scale.pxToTime(startPx - TRACK_SHELL_WIDTH));
- const endTs = Math.min(traceTime.endSec,
- scale.pxToTime(endPx - TRACK_SHELL_WIDTH));
- globals.frontendLocalState.selectTimeRange(startTs, endTs);
+ this.keepCurrentSelection = true;
+ if (editing) {
+ const startSec = frontendLocalState.selectedTimeRange.startSec;
+ const endSec = frontendLocalState.selectedTimeRange.endSec;
+ if (startSec !== undefined && endSec !== undefined) {
+ const newTime = scale.pxToTime(currentPx - TRACK_SHELL_WIDTH);
+ // Have to check again for when one boundary crosses over the other.
+ const curBoundary = onTimeRangeBoundary(prevPx);
+ if (curBoundary == null) return;
+ const keepTime = curBoundary === 'START' ? endSec : startSec;
+ frontendLocalState.selectTimeRange(
+ Math.max(Math.min(keepTime, newTime), traceTime.startSec),
+ Math.min(Math.max(keepTime, newTime), traceTime.endSec));
+ }
+ } else {
+ frontendLocalState.setShowTimeSelectPreview(false);
+ const dragStartTime = scale.pxToTime(dragStartPx - TRACK_SHELL_WIDTH);
+ const dragEndTime = scale.pxToTime(currentPx - TRACK_SHELL_WIDTH);
+ frontendLocalState.selectTimeRange(
+ Math.max(
+ Math.min(dragStartTime, dragEndTime), traceTime.startSec),
+ Math.min(Math.max(dragStartTime, dragEndTime), traceTime.endSec));
+ }
globals.rafScheduler.scheduleRedraw();
}
});
diff --git a/ui/src/tracks/cpu_slices/frontend.ts b/ui/src/tracks/cpu_slices/frontend.ts
index 40b91fa..e670291 100644
--- a/ui/src/tracks/cpu_slices/frontend.ts
+++ b/ui/src/tracks/cpu_slices/frontend.ts
@@ -306,7 +306,7 @@
const time = timeScale.pxToTime(x);
const index = search(data.starts, time);
const id = index === -1 ? undefined : data.ids[index];
- if (!id) return false;
+ if (!id || this.utidHoveredInThisTrack === -1) return false;
globals.makeSelection(Actions.selectSlice({id}));
return true;
}