Merge "perfetto-ui: Merging small callsites in flamegraph"
diff --git a/Android.bp b/Android.bp
index d93b0c1..514776e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -33,6 +33,7 @@
"src/trace_processor/metrics/android/android_startup_launches.sql",
"src/trace_processor/metrics/android/android_task_state.sql",
"src/trace_processor/metrics/android/heap_profile_callsites.sql",
+ "src/trace_processor/metrics/android/java_heap_stats.sql",
"src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql",
"src/trace_processor/metrics/android/process_mem.sql",
"src/trace_processor/metrics/android/process_unagg_mem_view.sql",
@@ -2397,6 +2398,7 @@
"protos/perfetto/metrics/android/cpu_metric.proto",
"protos/perfetto/metrics/android/heap_profile_callsites.proto",
"protos/perfetto/metrics/android/ion_metric.proto",
+ "protos/perfetto/metrics/android/java_heap_stats.proto",
"protos/perfetto/metrics/android/lmk_metric.proto",
"protos/perfetto/metrics/android/mem_metric.proto",
"protos/perfetto/metrics/android/mem_unagg_metric.proto",
@@ -2416,6 +2418,7 @@
"external/perfetto/protos/perfetto/metrics/android/cpu_metric.pbzero.cc",
"external/perfetto/protos/perfetto/metrics/android/heap_profile_callsites.pbzero.cc",
"external/perfetto/protos/perfetto/metrics/android/ion_metric.pbzero.cc",
+ "external/perfetto/protos/perfetto/metrics/android/java_heap_stats.pbzero.cc",
"external/perfetto/protos/perfetto/metrics/android/lmk_metric.pbzero.cc",
"external/perfetto/protos/perfetto/metrics/android/mem_metric.pbzero.cc",
"external/perfetto/protos/perfetto/metrics/android/mem_unagg_metric.pbzero.cc",
@@ -2435,6 +2438,7 @@
"protos/perfetto/metrics/android/cpu_metric.proto",
"protos/perfetto/metrics/android/heap_profile_callsites.proto",
"protos/perfetto/metrics/android/ion_metric.proto",
+ "protos/perfetto/metrics/android/java_heap_stats.proto",
"protos/perfetto/metrics/android/lmk_metric.proto",
"protos/perfetto/metrics/android/mem_metric.proto",
"protos/perfetto/metrics/android/mem_unagg_metric.proto",
@@ -2454,6 +2458,7 @@
"external/perfetto/protos/perfetto/metrics/android/cpu_metric.pbzero.h",
"external/perfetto/protos/perfetto/metrics/android/heap_profile_callsites.pbzero.h",
"external/perfetto/protos/perfetto/metrics/android/ion_metric.pbzero.h",
+ "external/perfetto/protos/perfetto/metrics/android/java_heap_stats.pbzero.h",
"external/perfetto/protos/perfetto/metrics/android/lmk_metric.pbzero.h",
"external/perfetto/protos/perfetto/metrics/android/mem_metric.pbzero.h",
"external/perfetto/protos/perfetto/metrics/android/mem_unagg_metric.pbzero.h",
@@ -4093,7 +4098,6 @@
name: "perfetto_src_base_unittests",
srcs: [
"src/base/circular_queue_unittest.cc",
- "src/base/copyable_ptr_unittest.cc",
"src/base/metatrace_unittest.cc",
"src/base/no_destructor_unittest.cc",
"src/base/optional_unittest.cc",
@@ -4502,6 +4506,7 @@
filegroup {
name: "perfetto_src_protozero_unittests",
srcs: [
+ "src/protozero/copyable_ptr_unittest.cc",
"src/protozero/message_handle_unittest.cc",
"src/protozero/message_unittest.cc",
"src/protozero/proto_decoder_unittest.cc",
@@ -5050,6 +5055,14 @@
],
}
+// GN: //src/tracing:sliced_protobuf_input_stream
+filegroup {
+ name: "perfetto_src_tracing_sliced_protobuf_input_stream",
+ srcs: [
+ "src/tracing/core/sliced_protobuf_input_stream.cc",
+ ],
+}
+
// GN: //src/tracing/test:api_test_support
filegroup {
name: "perfetto_src_tracing_test_api_test_support",
@@ -5076,7 +5089,6 @@
"src/tracing/core/packet_stream_validator.cc",
"src/tracing/core/shared_memory_abi.cc",
"src/tracing/core/shared_memory_arbiter_impl.cc",
- "src/tracing/core/sliced_protobuf_input_stream.cc",
"src/tracing/core/startup_trace_writer.cc",
"src/tracing/core/startup_trace_writer_registry.cc",
"src/tracing/core/trace_buffer.cc",
@@ -5449,6 +5461,7 @@
":perfetto_src_traced_service_unittests",
":perfetto_src_tracing_common",
":perfetto_src_tracing_ipc",
+ ":perfetto_src_tracing_sliced_protobuf_input_stream",
":perfetto_src_tracing_test_support",
":perfetto_src_tracing_tracing",
":perfetto_src_tracing_unittests",
diff --git a/BUILD b/BUILD
index 562fb80..57831e6 100644
--- a/BUILD
+++ b/BUILD
@@ -208,7 +208,6 @@
srcs = [
"include/perfetto/base/build_config.h",
"include/perfetto/base/compiler.h",
- "include/perfetto/base/copyable_ptr.h",
"include/perfetto/base/export.h",
"include/perfetto/base/logging.h",
"include/perfetto/base/task_runner.h",
@@ -311,7 +310,6 @@
"include/perfetto/ext/tracing/core/shared_memory_abi.h",
"include/perfetto/ext/tracing/core/shared_memory_arbiter.h",
"include/perfetto/ext/tracing/core/slice.h",
- "include/perfetto/ext/tracing/core/sliced_protobuf_input_stream.h",
"include/perfetto/ext/tracing/core/startup_trace_writer.h",
"include/perfetto/ext/tracing/core/startup_trace_writer_registry.h",
"include/perfetto/ext/tracing/core/trace_packet.h",
@@ -346,6 +344,7 @@
name = "include_perfetto_protozero_protozero",
srcs = [
"include/perfetto/protozero/contiguous_memory_range.h",
+ "include/perfetto/protozero/copyable_ptr.h",
"include/perfetto/protozero/field.h",
"include/perfetto/protozero/message.h",
"include/perfetto/protozero/message_handle.h",
@@ -576,6 +575,7 @@
"src/trace_processor/metrics/android/android_startup_launches.sql",
"src/trace_processor/metrics/android/android_task_state.sql",
"src/trace_processor/metrics/android/heap_profile_callsites.sql",
+ "src/trace_processor/metrics/android/java_heap_stats.sql",
"src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql",
"src/trace_processor/metrics/android/process_mem.sql",
"src/trace_processor/metrics/android/process_unagg_mem_view.sql",
@@ -1073,7 +1073,6 @@
"src/tracing/core/shared_memory_abi.cc",
"src/tracing/core/shared_memory_arbiter_impl.cc",
"src/tracing/core/shared_memory_arbiter_impl.h",
- "src/tracing/core/sliced_protobuf_input_stream.cc",
"src/tracing/core/startup_trace_writer.cc",
"src/tracing/core/startup_trace_writer_registry.cc",
"src/tracing/core/trace_buffer.cc",
@@ -1616,6 +1615,7 @@
"protos/perfetto/metrics/android/cpu_metric.proto",
"protos/perfetto/metrics/android/heap_profile_callsites.proto",
"protos/perfetto/metrics/android/ion_metric.proto",
+ "protos/perfetto/metrics/android/java_heap_stats.proto",
"protos/perfetto/metrics/android/lmk_metric.proto",
"protos/perfetto/metrics/android/mem_metric.proto",
"protos/perfetto/metrics/android/mem_unagg_metric.proto",
diff --git a/BUILD.gn b/BUILD.gn
index 965d68e..e912a12 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -211,12 +211,16 @@
component("libperfetto") {
public_configs = [ "gn:public_config" ]
deps = [
+ "src/trace_processor:export_json",
+ "src/trace_processor:storage",
"src/tracing",
]
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
public_deps = [
+ "include/perfetto/ext/trace_processor:export_json",
"include/perfetto/ext/tracing/core",
+ "include/perfetto/trace_processor:storage",
"protos/perfetto/common:zero",
"protos/perfetto/trace:zero",
"protos/perfetto/trace/chrome:zero",
@@ -238,17 +242,4 @@
]
}
}
- component("libproto_to_json") {
- public_configs = [ "gn:public_config" ]
- deps = [
- "src/trace_processor:export_json",
- "src/trace_processor:storage",
- ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
- public_deps = [
- "include/perfetto/ext/trace_processor:export_json",
- "include/perfetto/trace_processor:storage",
- ]
- }
}
diff --git a/docs/heapprofd.md b/docs/heapprofd.md
index 469ebac..fa2d2ff 100644
--- a/docs/heapprofd.md
+++ b/docs/heapprofd.md
@@ -33,6 +33,12 @@
This will create a pprof-compatible heap dump when Ctrl+C is pressed.
+You can also use the [Perfetto UI](https://ui.perfetto.dev/#!/record?p=memory)
+to record heapprofd profiles. Tick "Heap profiling" in the trace configuration,
+enter the processes you want to target, click "Add Device" to pair your phone,
+and record profiles straight from your browser. This is also possible on
+Windows.
+
## Viewing the data
The resulting profile proto contains four views on the data
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index 0e96e07..4dbcd42 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -194,7 +194,7 @@
declare_args() {
# Enables the SQL query layer of trace processor.
enable_perfetto_trace_processor_sqlite =
- enable_perfetto_trace_processor && !build_with_chromium
+ enable_perfetto_trace_processor && !(build_with_chromium && is_android)
# Enables the optional SQLite percentile module.
enable_perfetto_trace_processor_percentile =
@@ -207,23 +207,23 @@
# Enables ftrace support in the trace processor.
enable_perfetto_trace_processor_ftrace =
- enable_perfetto_trace_processor && !build_with_chromium
+ enable_perfetto_trace_processor && !(build_with_chromium && is_android)
# Enables parsing support for system probes in trace processor.
enable_perfetto_trace_processor_system_probes =
- enable_perfetto_trace_processor && !build_with_chromium
+ enable_perfetto_trace_processor && !(build_with_chromium && is_android)
# Enables parsing support for android system probes in trace processor.
enable_perfetto_trace_processor_android_probes =
- enable_perfetto_trace_processor && !build_with_chromium
+ enable_perfetto_trace_processor && !(build_with_chromium && is_android)
# Enables parsing support for heap graphs in trace processor.
enable_perfetto_trace_processor_heap_graphs =
- enable_perfetto_trace_processor && !build_with_chromium
+ enable_perfetto_trace_processor && !(build_with_chromium && is_android)
# Enables graphics event support in the trace processor.
enable_perfetto_trace_processor_graphics =
- enable_perfetto_trace_processor && !build_with_chromium
+ enable_perfetto_trace_processor && !(build_with_chromium && is_android)
# Enables JSON support in the trace processor. Required for JSON trace import
# and export. Importer support can also be disabled using
@@ -233,7 +233,7 @@
# Enables Fuchsia trace format support in trace processor.
enable_perfetto_trace_processor_fuchsia =
- enable_perfetto_trace_processor && !build_with_chromium
+ enable_perfetto_trace_processor && !(build_with_chromium && is_android)
# Enables httpd RPC support in the trace processor.
# Further per-OS conditionals are applied in gn/BUILD.gn.
@@ -244,7 +244,8 @@
declare_args() {
# Enables importer support for JSON traces in the trace processor.
enable_perfetto_trace_processor_json_import =
- enable_perfetto_trace_processor_json && !build_with_chromium
+ enable_perfetto_trace_processor_json &&
+ !(build_with_chromium && is_android)
# Enables syscall support in trace processor. Required for ftrace, system
# probes, and android probes support.
diff --git a/include/perfetto/base/BUILD.gn b/include/perfetto/base/BUILD.gn
index 9dc0893..e490551 100644
--- a/include/perfetto/base/BUILD.gn
+++ b/include/perfetto/base/BUILD.gn
@@ -18,7 +18,6 @@
sources = [
"build_config.h",
"compiler.h",
- "copyable_ptr.h",
"export.h",
"logging.h",
"task_runner.h",
diff --git a/include/perfetto/base/compiler.h b/include/perfetto/base/compiler.h
index fa44b6b..0b2efbf 100644
--- a/include/perfetto/base/compiler.h
+++ b/include/perfetto/base/compiler.h
@@ -57,6 +57,15 @@
#define PERFETTO_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
#endif
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __PRETTY_FUNCTION__
+#elif defined(_MSC_VER)
+#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __FUNCSIG__
+#else
+#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() \
+ static_assert(false, "Not implemented for this compiler")
+#endif
+
namespace perfetto {
namespace base {
diff --git a/include/perfetto/ext/tracing/core/BUILD.gn b/include/perfetto/ext/tracing/core/BUILD.gn
index e88fd76..69eff99 100644
--- a/include/perfetto/ext/tracing/core/BUILD.gn
+++ b/include/perfetto/ext/tracing/core/BUILD.gn
@@ -28,7 +28,6 @@
"shared_memory_abi.h",
"shared_memory_arbiter.h",
"slice.h",
- "sliced_protobuf_input_stream.h",
"startup_trace_writer.h",
"startup_trace_writer_registry.h",
"trace_packet.h",
diff --git a/include/perfetto/ext/tracing/core/shared_memory_arbiter.h b/include/perfetto/ext/tracing/core/shared_memory_arbiter.h
index 2465d43..0937621 100644
--- a/include/perfetto/ext/tracing/core/shared_memory_arbiter.h
+++ b/include/perfetto/ext/tracing/core/shared_memory_arbiter.h
@@ -34,7 +34,6 @@
class TaskRunner;
}
-class CommitDataRequest;
class StartupTraceWriter;
class StartupTraceWriterRegistry;
class SharedMemory;
diff --git a/include/perfetto/ext/tracing/core/trace_packet.h b/include/perfetto/ext/tracing/core/trace_packet.h
index 452c5b3..c1e7948 100644
--- a/include/perfetto/ext/tracing/core/trace_packet.h
+++ b/include/perfetto/ext/tracing/core/trace_packet.h
@@ -27,10 +27,6 @@
namespace perfetto {
-namespace protos {
-class TracePacket; // From protos/trace_packet.pb.h.
-} // namespace protos
-
// A wrapper around a byte buffer that contains a protobuf-encoded TracePacket
// (see trace_packet.proto). The TracePacket is decoded only if the Consumer
// requests that. This is to allow Consumer(s) to just stream the packet over
diff --git a/include/perfetto/protozero/BUILD.gn b/include/perfetto/protozero/BUILD.gn
index 7749684..994ff60 100644
--- a/include/perfetto/protozero/BUILD.gn
+++ b/include/perfetto/protozero/BUILD.gn
@@ -18,6 +18,7 @@
]
sources = [
"contiguous_memory_range.h",
+ "copyable_ptr.h",
"field.h",
"message.h",
"message_handle.h",
diff --git a/include/perfetto/base/copyable_ptr.h b/include/perfetto/protozero/copyable_ptr.h
similarity index 92%
rename from include/perfetto/base/copyable_ptr.h
rename to include/perfetto/protozero/copyable_ptr.h
index 236382f..2fe5ff6 100644
--- a/include/perfetto/base/copyable_ptr.h
+++ b/include/perfetto/protozero/copyable_ptr.h
@@ -14,13 +14,12 @@
* limitations under the License.
*/
-#ifndef INCLUDE_PERFETTO_BASE_COPYABLE_PTR_H_
-#define INCLUDE_PERFETTO_BASE_COPYABLE_PTR_H_
+#ifndef INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_
+#define INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_
#include <memory>
-namespace perfetto {
-namespace base {
+namespace protozero {
// This class is essentially a std::vector<T> of fixed size = 1.
// It's a pointer wrapper with deep copying and deep equality comparison.
@@ -83,7 +82,6 @@
std::unique_ptr<T> ptr_;
};
-} // namespace base
-} // namespace perfetto
+} // namespace protozero
-#endif // INCLUDE_PERFETTO_BASE_COPYABLE_PTR_H_
+#endif // INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_
diff --git a/include/perfetto/protozero/field.h b/include/perfetto/protozero/field.h
index 5bd3021..f76fe84 100644
--- a/include/perfetto/protozero/field.h
+++ b/include/perfetto/protozero/field.h
@@ -84,6 +84,11 @@
return static_cast<int32_t>(int_value_);
}
+ int32_t as_sint32() const {
+ PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt);
+ return proto_utils::ZigZagDecode(static_cast<uint32_t>(int_value_));
+ }
+
uint64_t as_uint64() const {
PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt ||
type() == proto_utils::ProtoWireType::kFixed32 ||
@@ -98,6 +103,11 @@
return static_cast<int64_t>(int_value_);
}
+ int64_t as_sint64() const {
+ PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt);
+ return proto_utils::ZigZagDecode(static_cast<uint64_t>(int_value_));
+ }
+
float as_float() const {
PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kFixed32);
float res;
@@ -159,8 +169,18 @@
void get(int64_t* val) const { *val = as_int64(); }
void get(float* val) const { *val = as_float(); }
void get(double* val) const { *val = as_double(); }
+ void get(std::string* val) const { *val = as_std_string(); }
void get(ConstChars* val) const { *val = as_string(); }
void get(ConstBytes* val) const { *val = as_bytes(); }
+ void get_signed(int32_t* val) const { *val = as_sint32(); }
+ void get_signed(int64_t* val) const { *val = as_sint64(); }
+
+ // For enum types.
+ template <typename T,
+ typename = typename std::enable_if<std::is_enum<T>::value, T>::type>
+ void get(T* val) const {
+ *val = static_cast<T>(as_int32());
+ }
private:
// Fields are deliberately not initialized to keep the class trivially
diff --git a/include/perfetto/protozero/proto_decoder.h b/include/perfetto/protozero/proto_decoder.h
index 584f7be..5794cc9 100644
--- a/include/perfetto/protozero/proto_decoder.h
+++ b/include/perfetto/protozero/proto_decoder.h
@@ -43,8 +43,11 @@
class ProtoDecoder {
public:
// Creates a ProtoDecoder using the given |buffer| with size |length| bytes.
- ProtoDecoder(const uint8_t* buffer, size_t length)
- : begin_(buffer), end_(buffer + length), read_ptr_(buffer) {}
+ ProtoDecoder(const void* buffer, size_t length)
+ : begin_(reinterpret_cast<const uint8_t*>(buffer)),
+ end_(begin_ + length),
+ read_ptr_(begin_) {}
+ ProtoDecoder(const std::string& str) : ProtoDecoder(str.data(), str.size()) {}
ProtoDecoder(const ConstBytes& cb) : ProtoDecoder(cb.data, cb.size) {}
// Reads the next field from the buffer and advances the read cursor. If a
@@ -113,6 +116,7 @@
iter_->get(&val);
return val;
}
+ const Field* operator->() const { return iter_; }
RepeatedFieldIterator& operator++() {
PERFETTO_DCHECK(iter_ != end_);
diff --git a/include/perfetto/protozero/proto_utils.h b/include/perfetto/protozero/proto_utils.h
index 3bfe470..8a93951 100644
--- a/include/perfetto/protozero/proto_utils.h
+++ b/include/perfetto/protozero/proto_utils.h
@@ -158,6 +158,15 @@
static_cast<UnsignedType>(value >> (sizeof(T) * 8 - 1));
}
+// Proto types: sint64, sint32.
+template <typename T>
+inline typename std::make_signed<T>::type ZigZagDecode(T value) {
+ using UnsignedType = typename std::make_unsigned<T>::type;
+ auto u_value = static_cast<UnsignedType>(value);
+ return static_cast<typename std::make_signed<T>::type>(
+ ((u_value >> 1) ^ -(u_value & 1)));
+}
+
template <typename T>
inline uint8_t* WriteVarInt(T value, uint8_t* target) {
// If value is <= 0 we must first sign extend to int64_t (see [1]).
diff --git a/include/perfetto/tracing/internal/track_event_internal.h b/include/perfetto/tracing/internal/track_event_internal.h
index 9cbdf34..c303938 100644
--- a/include/perfetto/tracing/internal/track_event_internal.h
+++ b/include/perfetto/tracing/internal/track_event_internal.h
@@ -24,15 +24,6 @@
#include <unordered_map>
-// Only used to DCHECK that one interned data field isn't accidentally shared by
-// multiple TrackEventInternedData subclasses.
-// TODO(skyostil): Add __FUNCSIG__ for MSVC.
-#if PERFETTO_DCHECK_IS_ON() && defined(__GNUC__)
-#define PERFETTO_INTERNAL_TYPE_IDENTIFIER __PRETTY_FUNCTION__
-#else // PERFETTO_DCHECK_IS_ON() && defined(__GNUC__)
-#define PERFETTO_INTERNAL_TYPE_IDENTIFIER ""
-#endif // PERFETTO_DCHECK_IS_ON() && defined(__GNUC__)
-
namespace perfetto {
class DataSourceConfig;
class DataSourceDescriptor;
diff --git a/include/perfetto/tracing/internal/track_event_macros.h b/include/perfetto/tracing/internal/track_event_macros.h
index 5ebf8a4..fca7deb 100644
--- a/include/perfetto/tracing/internal/track_event_macros.h
+++ b/include/perfetto/tracing/internal/track_event_macros.h
@@ -61,6 +61,8 @@
&g_category_state_storage[0]); \
extern const ::perfetto::internal::TrackEventCategoryRegistry \
kCategoryRegistry; \
+ static_assert(kConstExprCategoryRegistry.ValidateCategories(), \
+ "Invalid category names found"); \
} // namespace internal
// In a .cc file, declares storage for each category's runtime state.
@@ -95,4 +97,9 @@
PERFETTO_GET_CATEGORY_INDEX(category)>(instances, ##__VA_ARGS__); \
})
+// Generate a unique variable name with a given prefix.
+#define PERFETTO_INTERNAL_CONCAT2(a, b) a##b
+#define PERFETTO_INTERNAL_CONCAT(a, b) PERFETTO_INTERNAL_CONCAT2(a, b)
+#define PERFETTO_INTERNAL_UID(prefix) PERFETTO_INTERNAL_CONCAT(prefix, __LINE__)
+
#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_MACROS_H_
diff --git a/include/perfetto/tracing/track_event.h b/include/perfetto/tracing/track_event.h
index 83907ab..5b909be 100644
--- a/include/perfetto/tracing/track_event.h
+++ b/include/perfetto/tracing/track_event.h
@@ -54,8 +54,7 @@
//
// int main() {
// perfetto::TrackEvent::Register();
-// TRACK_EVENT_BEGIN("category", "MyEvent");
-// TRACK_EVENT_END("category");
+// TRACK_EVENT("category", "MyEvent");
// ...
// }
//
@@ -143,11 +142,26 @@
category, nullptr, \
::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END, ##__VA_ARGS__)
+// Begin a thread-scoped slice which gets automatically closed when going out of
+// scope.
+#define TRACE_EVENT(category, name, ...) \
+ TRACE_EVENT_BEGIN(category, name, ##__VA_ARGS__); \
+ struct { \
+ struct EventFinalizer { \
+ ~EventFinalizer() { TRACE_EVENT_END(category); } \
+ } finalizer; \
+ } PERFETTO_INTERNAL_UID(scoped_event)
+
+// Emit a thread-scoped slice which has zero duration.
+// TODO(skyostil): Add support for process-wide and global instant events.
+#define TRACE_EVENT_INSTANT(category, name, ...) \
+ PERFETTO_INTERNAL_TRACK_EVENT( \
+ category, name, ::perfetto::protos::pbzero::TrackEvent::TYPE_INSTANT, \
+ ##__VA_ARGS__)
+
// TODO(skyostil): Add arguments.
-// TODO(skyostil): Add scoped events.
// TODO(skyostil): Add async events.
// TODO(skyostil): Add flow events.
-// TODO(skyostil): Add instant events.
// TODO(skyostil): Add counters.
#endif // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_H_
diff --git a/include/perfetto/tracing/track_event_category_registry.h b/include/perfetto/tracing/track_event_category_registry.h
index 3e15db6..f31696b 100644
--- a/include/perfetto/tracing/track_event_category_registry.h
+++ b/include/perfetto/tracing/track_event_category_registry.h
@@ -89,8 +89,22 @@
return CategoryIndex;
}
+ constexpr bool ValidateCategories(size_t index = 0) const {
+ return (index == category_count_)
+ ? true
+ : IsValidCategoryName(categories_[index].name)
+ ? ValidateCategories(index + 1)
+ : false;
+ }
+
private:
// TODO(skyostil): Make the compile-time routines nicer with C++14.
+ static constexpr bool IsValidCategoryName(const char* name) {
+ return (*name == '\"' || *name == '*')
+ ? false
+ : *name ? IsValidCategoryName(name + 1) : true;
+ }
+
static constexpr bool StringEq(const char* a, const char* b) {
return *a != *b ? false
: (!*a || !*b) ? (*a == *b) : StringEq(a + 1, b + 1);
diff --git a/include/perfetto/tracing/track_event_interned_data_index.h b/include/perfetto/tracing/track_event_interned_data_index.h
index 197081b..e1ef7ee 100644
--- a/include/perfetto/tracing/track_event_interned_data_index.h
+++ b/include/perfetto/tracing/track_event_interned_data_index.h
@@ -19,6 +19,8 @@
#include "perfetto/tracing/internal/track_event_internal.h"
+#include "perfetto/base/compiler.h"
+
#include <map>
#include <type_traits>
#include <unordered_map>
@@ -194,11 +196,12 @@
for (const auto& entry : incremental_state->interned_data_indices) {
if (entry.first == FieldNumber) {
#if PERFETTO_DCHECK_IS_ON()
- if (strcmp(PERFETTO_INTERNAL_TYPE_IDENTIFIER, entry.second->type_id_)) {
+ if (strcmp(PERFETTO_DEBUG_FUNCTION_IDENTIFIER(),
+ entry.second->type_id_)) {
PERFETTO_FATAL(
"Interned data accessed under different types! Previous type: "
"%s. New type: %s.",
- entry.second->type_id_, PERFETTO_INTERNAL_TYPE_IDENTIFIER);
+ entry.second->type_id_, PERFETTO_DEBUG_FUNCTION_IDENTIFIER());
}
#endif // PERFETTO_DCHECK_IS_ON()
return reinterpret_cast<InternedDataType*>(entry.second.get());
@@ -210,7 +213,7 @@
entry.first = FieldNumber;
entry.second.reset(new InternedDataType());
#if PERFETTO_DCHECK_IS_ON()
- entry.second->type_id_ = PERFETTO_INTERNAL_TYPE_IDENTIFIER;
+ entry.second->type_id_ = PERFETTO_DEBUG_FUNCTION_IDENTIFIER();
#endif // PERFETTO_DCHECK_IS_ON()
return reinterpret_cast<InternedDataType*>(entry.second.get());
}
diff --git a/protos/perfetto/config/ftrace/ftrace_config.proto b/protos/perfetto/config/ftrace/ftrace_config.proto
index 56dc0d0..a612d89 100644
--- a/protos/perfetto/config/ftrace/ftrace_config.proto
+++ b/protos/perfetto/config/ftrace/ftrace_config.proto
@@ -27,16 +27,12 @@
optional uint32 buffer_size_kb = 10;
optional uint32 drain_period_ms = 11;
- // Configuration for compact encoding of scheduler events. If enabled, this
- // records a small subset of fields of selected scheduling events, and
- // encodes them in a denser proto format than normal. This is useful due to
- // scheduling events being abundant in a typical trace, and dominating its
- // size via a combination of unnecessary data being retained, and proto
- // format overheads.
- // TODO(rsavitski): unstable, do not use.
+ // Configuration for compact encoding of scheduler events. When enabled (and
+ // recording the relevant ftrace events), specific high-volume events are
+ // encoded in a denser format than normal.
message CompactSchedConfig {
- // If true, and sched_switch ftrace event is enabled, record those events
- // in the compact format.
+ // If true, and sched_switch or sched_waking ftrace events are enabled,
+ // record those events in the compact format.
optional bool enabled = 1;
}
optional CompactSchedConfig compact_sched = 12;
diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto
index 49e5a66..23c33eb 100644
--- a/protos/perfetto/config/perfetto_config.proto
+++ b/protos/perfetto/config/perfetto_config.proto
@@ -631,16 +631,12 @@
optional uint32 buffer_size_kb = 10;
optional uint32 drain_period_ms = 11;
- // Configuration for compact encoding of scheduler events. If enabled, this
- // records a small subset of fields of selected scheduling events, and
- // encodes them in a denser proto format than normal. This is useful due to
- // scheduling events being abundant in a typical trace, and dominating its
- // size via a combination of unnecessary data being retained, and proto
- // format overheads.
- // TODO(rsavitski): unstable, do not use.
+ // Configuration for compact encoding of scheduler events. When enabled (and
+ // recording the relevant ftrace events), specific high-volume events are
+ // encoded in a denser format than normal.
message CompactSchedConfig {
- // If true, and sched_switch ftrace event is enabled, record those events
- // in the compact format.
+ // If true, and sched_switch or sched_waking ftrace events are enabled,
+ // record those events in the compact format.
optional bool enabled = 1;
}
optional CompactSchedConfig compact_sched = 12;
@@ -1186,6 +1182,10 @@
// process.
optional bool block_client = 9;
+ // If set, stop the trace session after blocking the client for this
+ // timeout. Needs to be larger than 100 us, otherwise no retries are done.
+ optional uint32 block_client_timeout_us = 14;
+
// Do not profile processes from startup, only match already running
// processes.
//
diff --git a/protos/perfetto/config/profiling/heapprofd_config.proto b/protos/perfetto/config/profiling/heapprofd_config.proto
index 2d208d3..0f3a30f 100644
--- a/protos/perfetto/config/profiling/heapprofd_config.proto
+++ b/protos/perfetto/config/profiling/heapprofd_config.proto
@@ -81,6 +81,10 @@
// process.
optional bool block_client = 9;
+ // If set, stop the trace session after blocking the client for this
+ // timeout. Needs to be larger than 100 us, otherwise no retries are done.
+ optional uint32 block_client_timeout_us = 14;
+
// Do not profile processes from startup, only match already running
// processes.
//
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index 9d1d001..41353b0 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -20,6 +20,7 @@
"cpu_metric.proto",
"heap_profile_callsites.proto",
"ion_metric.proto",
+ "java_heap_stats.proto",
"lmk_metric.proto",
"mem_metric.proto",
"mem_unagg_metric.proto",
diff --git a/protos/perfetto/metrics/android/heap_profile_callsites.proto b/protos/perfetto/metrics/android/heap_profile_callsites.proto
index ce0bdca..d19bba3 100644
--- a/protos/perfetto/metrics/android/heap_profile_callsites.proto
+++ b/protos/perfetto/metrics/android/heap_profile_callsites.proto
@@ -51,10 +51,16 @@
}
// Callsites per process instance.
+ // Next id: 6
message InstanceStats {
optional uint32 pid = 1;
optional string process_name = 2;
repeated Callsite callsites = 3;
+
+ // Bytes allocated via malloc but not freed.
+ optional int64 profile_delta_bytes = 4;
+ // Bytes allocated via malloc irrespective of whether they were freed.
+ optional int64 profile_total_bytes = 5;
}
repeated InstanceStats instance_stats = 1;
diff --git a/protos/perfetto/metrics/android/java_heap_stats.proto b/protos/perfetto/metrics/android/java_heap_stats.proto
new file mode 100644
index 0000000..a5e1513
--- /dev/null
+++ b/protos/perfetto/metrics/android/java_heap_stats.proto
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+message JavaHeapStats {
+ message Sample {
+ optional int64 ts = 1;
+ optional int64 heap_size = 2;
+ optional int64 reachable_heap_size = 3;
+ }
+
+ // Heap stats per process. One sample per dump (can be > 1 if continuous
+ // dump is enabled).
+ message InstanceStats {
+ optional uint32 upid = 1;
+ optional string process_name = 2;
+ repeated Sample samples = 3;
+ }
+
+ repeated InstanceStats instance_stats = 1;
+}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index a197a38..508e830 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -31,6 +31,7 @@
import "protos/perfetto/metrics/android/heap_profile_callsites.proto";
import "protos/perfetto/metrics/android/package_list.proto";
import "protos/perfetto/metrics/android/unsymbolized_frames.proto";
+import "protos/perfetto/metrics/android/java_heap_stats.proto";
// Trace processor metadata (taken from the stats table schema and contents).
// TODO: perhaps add the other columns once we have enum support
@@ -48,7 +49,7 @@
// Root message for all Perfetto-based metrics.
//
-// Next id: 17
+// Next id: 18
message TraceMetrics {
reserved 4, 13, 14;
@@ -94,6 +95,9 @@
// Returns stack frames missing symbols.
optional UnsymbolizedFrames unsymbolized_frames = 15;
+ // If the trace contains a heap graph, output allocation statistics.
+ optional JavaHeapStats java_heap_stats = 17;
+
// Demo extensions.
extensions 450 to 499;
diff --git a/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto b/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
index e61377a..1d69b1f 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
@@ -36,8 +36,10 @@
// a subset of events & their fields is recorded.
// All fields (except comms) are stored in a structure-of-arrays form, one
// entry in each repeated field per event.
- // TODO(rsavitski): unstable, do not use.
message CompactSched {
+ // Interned table of unique strings for this bundle.
+ repeated string intern_table = 5;
+
// Delta-encoded timestamps across all sched_switch events within this
// bundle. The first is absolute, each next one is relative to its
// predecessor.
@@ -45,12 +47,20 @@
repeated int64 switch_prev_state = 2 [packed = true];
repeated int32 switch_next_pid = 3 [packed = true];
repeated int32 switch_next_prio = 4 [packed = true];
-
- // Interned table of unique comm strings for this bundle.
- repeated string switch_next_comm_table = 5;
- // One per event, index into |switch_next_comm_table| corresponding to the
+ // One per event, index into |intern_table| corresponding to the
// next_comm field of the event.
repeated uint32 switch_next_comm_index = 6 [packed = true];
+
+ // Delta-encoded timestamps across all sched_waking events within this
+ // bundle. The first is absolute, each next one is relative to its
+ // predecessor.
+ repeated uint64 waking_timestamp = 7 [packed = true];
+ repeated int32 waking_pid = 8 [packed = true];
+ repeated int32 waking_target_cpu = 9 [packed = true];
+ repeated int32 waking_prio = 10 [packed = true];
+ // One per event, index into |intern_table| corresponding to the
+ // comm field of the event.
+ repeated uint32 waking_comm_index = 11 [packed = true];
}
optional CompactSched compact_sched = 4;
}
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index f59d182..2585ba1 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -2316,8 +2316,10 @@
// a subset of events & their fields is recorded.
// All fields (except comms) are stored in a structure-of-arrays form, one
// entry in each repeated field per event.
- // TODO(rsavitski): unstable, do not use.
message CompactSched {
+ // Interned table of unique strings for this bundle.
+ repeated string intern_table = 5;
+
// Delta-encoded timestamps across all sched_switch events within this
// bundle. The first is absolute, each next one is relative to its
// predecessor.
@@ -2325,12 +2327,20 @@
repeated int64 switch_prev_state = 2 [packed = true];
repeated int32 switch_next_pid = 3 [packed = true];
repeated int32 switch_next_prio = 4 [packed = true];
-
- // Interned table of unique comm strings for this bundle.
- repeated string switch_next_comm_table = 5;
- // One per event, index into |switch_next_comm_table| corresponding to the
+ // One per event, index into |intern_table| corresponding to the
// next_comm field of the event.
repeated uint32 switch_next_comm_index = 6 [packed = true];
+
+ // Delta-encoded timestamps across all sched_waking events within this
+ // bundle. The first is absolute, each next one is relative to its
+ // predecessor.
+ repeated uint64 waking_timestamp = 7 [packed = true];
+ repeated int32 waking_pid = 8 [packed = true];
+ repeated int32 waking_target_cpu = 9 [packed = true];
+ repeated int32 waking_prio = 10 [packed = true];
+ // One per event, index into |intern_table| corresponding to the
+ // comm field of the event.
+ repeated uint32 waking_comm_index = 11 [packed = true];
}
optional CompactSched compact_sched = 4;
}
@@ -4457,16 +4467,12 @@
optional uint32 buffer_size_kb = 10;
optional uint32 drain_period_ms = 11;
- // Configuration for compact encoding of scheduler events. If enabled, this
- // records a small subset of fields of selected scheduling events, and
- // encodes them in a denser proto format than normal. This is useful due to
- // scheduling events being abundant in a typical trace, and dominating its
- // size via a combination of unnecessary data being retained, and proto
- // format overheads.
- // TODO(rsavitski): unstable, do not use.
+ // Configuration for compact encoding of scheduler events. When enabled (and
+ // recording the relevant ftrace events), specific high-volume events are
+ // encoded in a denser format than normal.
message CompactSchedConfig {
- // If true, and sched_switch ftrace event is enabled, record those events
- // in the compact format.
+ // If true, and sched_switch or sched_waking ftrace events are enabled,
+ // record those events in the compact format.
optional bool enabled = 1;
}
optional CompactSchedConfig compact_sched = 12;
@@ -5012,6 +5018,10 @@
// process.
optional bool block_client = 9;
+ // If set, stop the trace session after blocking the client for this
+ // timeout. Needs to be larger than 100 us, otherwise no retries are done.
+ optional uint32 block_client_timeout_us = 14;
+
// Do not profile processes from startup, only match already running
// processes.
//
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index 9f53d4b..0e7a0d0 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -122,7 +122,6 @@
sources = [
"circular_queue_unittest.cc",
- "copyable_ptr_unittest.cc",
"no_destructor_unittest.cc",
"optional_unittest.cc",
"paged_memory_unittest.cc",
diff --git a/src/ipc/buffered_frame_deserializer_fuzzer.cc b/src/ipc/buffered_frame_deserializer_fuzzer.cc
index 61a818d..086ccf7 100644
--- a/src/ipc/buffered_frame_deserializer_fuzzer.cc
+++ b/src/ipc/buffered_frame_deserializer_fuzzer.cc
@@ -20,8 +20,6 @@
#include "perfetto/ext/base/utils.h"
#include "src/ipc/buffered_frame_deserializer.h"
-#include "protos/perfetto/ipc/wire_protocol.pb.h"
-
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
diff --git a/src/ipc/client_impl.cc b/src/ipc/client_impl.cc
index b563d95..4d32e6e 100644
--- a/src/ipc/client_impl.cc
+++ b/src/ipc/client_impl.cc
@@ -73,7 +73,7 @@
return service_proxy->OnConnect(false /* success */);
}
QueuedRequest qr;
- qr.type = Frame::kMsgBindService;
+ qr.type = Frame::kMsgBindServiceFieldNumber;
qr.request_id = request_id;
qr.service_proxy = service_proxy;
queued_requests_.emplace(request_id, std::move(qr));
@@ -107,7 +107,7 @@
if (drop_reply)
return 0;
QueuedRequest qr;
- qr.type = Frame::kMsgInvokeMethod;
+ qr.type = Frame::kMsgInvokeMethodFieldNumber;
qr.request_id = request_id;
qr.method_name = method_name;
qr.service_proxy = std::move(service_proxy);
@@ -187,23 +187,23 @@
QueuedRequest req = std::move(queued_requests_it->second);
queued_requests_.erase(queued_requests_it);
- if (req.type == Frame::kMsgBindService &&
- frame.msg_case() == Frame::kMsgBindServiceReply) {
+ if (req.type == Frame::kMsgBindServiceFieldNumber &&
+ frame.has_msg_bind_service_reply()) {
return OnBindServiceReply(std::move(req), frame.msg_bind_service_reply());
}
- if (req.type == Frame::kMsgInvokeMethod &&
- frame.msg_case() == Frame::kMsgInvokeMethodReply) {
+ if (req.type == Frame::kMsgInvokeMethodFieldNumber &&
+ frame.has_msg_invoke_method_reply()) {
return OnInvokeMethodReply(std::move(req), frame.msg_invoke_method_reply());
}
- if (frame.msg_case() == Frame::kMsgRequestError) {
+ if (frame.has_msg_request_error()) {
PERFETTO_DLOG("Host error: %s", frame.msg_request_error().error().c_str());
return;
}
PERFETTO_DLOG(
- "OnFrameReceived() request msg_type=%d, received msg_type=%d in reply to "
+ "OnFrameReceived() request type=%d, received unknown frame in reply to "
"request_id=%" PRIu64,
- req.type, frame.msg_case(), static_cast<uint64_t>(frame.request_id()));
+ req.type, static_cast<uint64_t>(frame.request_id()));
}
void ClientImpl::OnBindServiceReply(QueuedRequest req,
diff --git a/src/ipc/client_impl_unittest.cc b/src/ipc/client_impl_unittest.cc
index e8e634e..56039d9 100644
--- a/src/ipc/client_impl_unittest.cc
+++ b/src/ipc/client_impl_unittest.cc
@@ -141,7 +141,7 @@
}
void OnFrameReceived(const Frame& req) {
- if (req.msg_case() == Frame::kMsgBindService) {
+ if (req.has_msg_bind_service()) {
auto svc_it = services.find(req.msg_bind_service().service_name());
ASSERT_NE(services.end(), svc_it);
const FakeService& svc = *svc_it->second;
@@ -155,7 +155,7 @@
method->set_id(method_it.second->id);
}
Reply(reply);
- } else if (req.msg_case() == Frame::kMsgInvokeMethod) {
+ } else if (req.has_msg_invoke_method()) {
// Lookup the service and method.
bool has_more = false;
do {
diff --git a/src/ipc/host_impl.cc b/src/ipc/host_impl.cc
index 0a56b85..1158fb8 100644
--- a/src/ipc/host_impl.cc
+++ b/src/ipc/host_impl.cc
@@ -126,13 +126,12 @@
void HostImpl::OnReceivedFrame(ClientConnection* client,
const Frame& req_frame) {
- if (req_frame.msg_case() == Frame::kMsgBindService)
+ if (req_frame.has_msg_bind_service())
return OnBindService(client, req_frame);
- if (req_frame.msg_case() == Frame::kMsgInvokeMethod)
+ if (req_frame.has_msg_invoke_method())
return OnInvokeMethod(client, req_frame);
- PERFETTO_DLOG("Received invalid RPC frame %u from client %" PRIu64,
- req_frame.msg_case(), client->id);
+ PERFETTO_DLOG("Received invalid RPC frame from client %" PRIu64, client->id);
Frame reply_frame;
reply_frame.set_request_id(req_frame.request_id());
reply_frame.mutable_msg_request_error()->set_error("unknown request");
diff --git a/src/ipc/host_impl_unittest.cc b/src/ipc/host_impl_unittest.cc
index 0624cd7..4e9216b 100644
--- a/src/ipc/host_impl_unittest.cc
+++ b/src/ipc/host_impl_unittest.cc
@@ -139,16 +139,16 @@
while (std::unique_ptr<Frame> frame = frame_deserializer_.PopNextFrame()) {
ASSERT_EQ(1u, requests_.count(frame->request_id()));
EXPECT_EQ(0, requests_[frame->request_id()]++);
- if (frame->msg_case() == Frame::kMsgBindServiceReply) {
+ if (frame->has_msg_bind_service_reply()) {
if (frame->msg_bind_service_reply().success())
last_bound_service_id_ = frame->msg_bind_service_reply().service_id();
return OnServiceBound(frame->msg_bind_service_reply());
}
- if (frame->msg_case() == Frame::kMsgInvokeMethodReply)
+ if (frame->has_msg_invoke_method_reply())
return OnInvokeMethodReply(frame->msg_invoke_method_reply());
- if (frame->msg_case() == Frame::kMsgRequestError)
+ if (frame->has_msg_request_error())
return OnRequestError();
- FAIL() << "Unexpected frame received from host " << frame->msg_case();
+ FAIL() << "Unexpected frame received from host";
}
}
diff --git a/src/perfetto_cmd/perfetto_config.descriptor.h b/src/perfetto_cmd/perfetto_config.descriptor.h
index 666bac9..0ce692b 100644
--- a/src/perfetto_cmd/perfetto_config.descriptor.h
+++ b/src/perfetto_cmd/perfetto_config.descriptor.h
@@ -12,15 +12,15 @@
// SHA1(tools/gen_binary_descriptors)
// 192b582ae52bb07b3d3ba66a94bcfd3127a5f42f
// SHA1(protos/perfetto/config/perfetto_config.proto)
-// 267f9d49ca0c50158496fd5dc90ab15480500724
+// edb4dea1679b47b02d9296a9db0cc4136f294edf
// This is the proto PerfettoConfig encoded as a ProtoFileDescriptor to allow
// for reflection without libprotobuf full/non-lite protos.
namespace perfetto {
-constexpr std::array<uint8_t, 16768> kPerfettoConfigDescriptor{
- {0x0a, 0xfc, 0x82, 0x01, 0x0a, 0x2c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+constexpr std::array<uint8_t, 16823> kPerfettoConfigDescriptor{
+ {0x0a, 0xb3, 0x83, 0x01, 0x0a, 0x2c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f,
@@ -995,7 +995,7 @@
0x1c, 0x0a, 0x18, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49,
0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x46, 0x4c,
0x41, 0x54, 0x45, 0x10, 0x01, 0x4a, 0x04, 0x08, 0x0f, 0x10, 0x10, 0x22,
- 0xed, 0x04, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66,
+ 0xa4, 0x05, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66,
0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x17, 0x73,
0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x76, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01,
@@ -1027,397 +1027,401 @@
0x73, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63,
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52,
0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
- 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74,
- 0x75, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6e, 0x6f,
- 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x6e,
- 0x6f, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x0b, 0x20,
- 0x01, 0x28, 0x08, 0x52, 0x09, 0x6e, 0x6f, 0x52, 0x75, 0x6e, 0x6e, 0x69,
- 0x6e, 0x67, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x6c, 0x65, 0x5f, 0x61,
- 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c,
- 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x64, 0x6c, 0x65, 0x41, 0x6c,
- 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a,
- 0x0b, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x61, 0x78,
- 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x64, 0x75, 0x6d, 0x70,
- 0x41, 0x74, 0x4d, 0x61, 0x78, 0x1a, 0x64, 0x0a, 0x14, 0x43, 0x6f, 0x6e,
- 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70, 0x43,
- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x22, 0x0a, 0x0d, 0x64, 0x75, 0x6d,
- 0x70, 0x5f, 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x05,
- 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x64, 0x75, 0x6d, 0x70, 0x50, 0x68,
- 0x61, 0x73, 0x65, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x64, 0x75, 0x6d,
- 0x70, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d,
- 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x64, 0x75, 0x6d,
- 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x73, 0x22,
- 0x9f, 0x02, 0x0a, 0x0f, 0x4a, 0x61, 0x76, 0x61, 0x48, 0x70, 0x72, 0x6f,
- 0x66, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x27, 0x0a, 0x0f, 0x70,
- 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6d, 0x64, 0x6c, 0x69,
- 0x6e, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x72,
- 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6d, 0x64, 0x6c, 0x69, 0x6e, 0x65,
- 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28,
- 0x04, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x6b, 0x0a, 0x16, 0x63, 0x6f,
- 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x5f, 0x64, 0x75, 0x6d,
- 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76,
- 0x61, 0x48, 0x70, 0x72, 0x6f, 0x66, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
- 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44,
- 0x75, 0x6d, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x14, 0x63,
- 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d,
- 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x64, 0x0a, 0x14, 0x43,
- 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d,
- 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x22, 0x0a, 0x0d, 0x64,
- 0x75, 0x6d, 0x70, 0x5f, 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6d, 0x73,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x64, 0x75, 0x6d, 0x70,
- 0x50, 0x68, 0x61, 0x73, 0x65, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x64,
- 0x75, 0x6d, 0x70, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
- 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x64,
- 0x75, 0x6d, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d,
- 0x73, 0x22, 0xb8, 0x01, 0x0a, 0x10, 0x47, 0x70, 0x75, 0x43, 0x6f, 0x75,
- 0x6e, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2a,
- 0x0a, 0x11, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x65,
- 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x04, 0x52, 0x0f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x50, 0x65,
- 0x72, 0x69, 0x6f, 0x64, 0x4e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f,
- 0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20,
- 0x03, 0x28, 0x0d, 0x52, 0x0a, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
- 0x49, 0x64, 0x73, 0x12, 0x33, 0x0a, 0x15, 0x69, 0x6e, 0x73, 0x74, 0x72,
- 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x61, 0x6d, 0x70,
- 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14,
- 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64,
- 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x12, 0x22, 0x0a, 0x0d,
- 0x66, 0x69, 0x78, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x63, 0x6c, 0x6f, 0x63,
- 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x66, 0x69, 0x78,
- 0x47, 0x70, 0x75, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x44, 0x0a, 0x12,
- 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74,
- 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x0a, 0x13, 0x70, 0x61,
- 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66,
- 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52,
- 0x11, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65,
- 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2a, 0x8e, 0x01, 0x0a, 0x0c, 0x41,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6f, 0x67, 0x49, 0x64, 0x12,
- 0x0f, 0x0a, 0x0b, 0x4c, 0x49, 0x44, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55,
- 0x4c, 0x54, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x49, 0x44, 0x5f,
- 0x52, 0x41, 0x44, 0x49, 0x4f, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x4c,
- 0x49, 0x44, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x53, 0x10, 0x02, 0x12,
- 0x0e, 0x0a, 0x0a, 0x4c, 0x49, 0x44, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45,
- 0x4d, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x49, 0x44, 0x5f, 0x43,
- 0x52, 0x41, 0x53, 0x48, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x49,
- 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x53, 0x10, 0x05, 0x12, 0x10, 0x0a,
- 0x0c, 0x4c, 0x49, 0x44, 0x5f, 0x53, 0x45, 0x43, 0x55, 0x52, 0x49, 0x54,
- 0x59, 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x49, 0x44, 0x5f, 0x4b,
- 0x45, 0x52, 0x4e, 0x45, 0x4c, 0x10, 0x07, 0x2a, 0x9b, 0x01, 0x0a, 0x12,
- 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6f, 0x67, 0x50, 0x72,
- 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x52,
- 0x49, 0x4f, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
- 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x52, 0x49, 0x4f,
- 0x5f, 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a,
- 0x0c, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x56, 0x45, 0x52, 0x42, 0x4f, 0x53,
- 0x45, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x49, 0x4f, 0x5f,
- 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x50,
- 0x52, 0x49, 0x4f, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x04, 0x12, 0x0d,
- 0x0a, 0x09, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x10,
- 0x05, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x45, 0x52,
- 0x52, 0x4f, 0x52, 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x49,
- 0x4f, 0x5f, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x07, 0x2a, 0xbf, 0x06,
- 0x0a, 0x0f, 0x4d, 0x65, 0x6d, 0x69, 0x6e, 0x66, 0x6f, 0x43, 0x6f, 0x75,
- 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d,
- 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49,
- 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45,
- 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x54, 0x4f,
- 0x54, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d,
- 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x46, 0x52, 0x45,
- 0x45, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
- 0x46, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x41, 0x56, 0x41, 0x49, 0x4c,
- 0x41, 0x42, 0x4c, 0x45, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x45,
- 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x42, 0x55, 0x46, 0x46, 0x45, 0x52,
- 0x53, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
- 0x46, 0x4f, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x44, 0x10, 0x05, 0x12,
- 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53,
- 0x57, 0x41, 0x50, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x44, 0x10, 0x06,
- 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
- 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10,
- 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43,
- 0x54, 0x49, 0x56, 0x45, 0x10, 0x08, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45,
- 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45,
- 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x09, 0x12, 0x19, 0x0a, 0x15, 0x4d,
- 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54,
- 0x49, 0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x0a, 0x12, 0x17,
- 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x43,
- 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x0b, 0x12,
- 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49,
- 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45,
- 0x10, 0x0c, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46,
- 0x4f, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c,
- 0x45, 0x10, 0x0d, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
- 0x46, 0x4f, 0x5f, 0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x0e,
+ 0x12, 0x35, 0x0a, 0x17, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6c,
+ 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
+ 0x5f, 0x75, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x62,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69,
+ 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x55, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6e,
+ 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x18, 0x0a, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x09, 0x6e, 0x6f, 0x53, 0x74, 0x61, 0x72, 0x74,
+ 0x75, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x5f, 0x72, 0x75, 0x6e,
+ 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09,
+ 0x6e, 0x6f, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x0a,
+ 0x10, 0x69, 0x64, 0x6c, 0x65, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x0f, 0x69, 0x64, 0x6c, 0x65, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x64, 0x75, 0x6d, 0x70,
+ 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x0d, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x09, 0x64, 0x75, 0x6d, 0x70, 0x41, 0x74, 0x4d, 0x61, 0x78,
+ 0x1a, 0x64, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f,
+ 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x12, 0x22, 0x0a, 0x0d, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x70, 0x68, 0x61,
+ 0x73, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52,
+ 0x0b, 0x64, 0x75, 0x6d, 0x70, 0x50, 0x68, 0x61, 0x73, 0x65, 0x4d, 0x73,
+ 0x12, 0x28, 0x0a, 0x10, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01,
+ 0x28, 0x0d, 0x52, 0x0e, 0x64, 0x75, 0x6d, 0x70, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x73, 0x22, 0x9f, 0x02, 0x0a, 0x0f, 0x4a,
+ 0x61, 0x76, 0x61, 0x48, 0x70, 0x72, 0x6f, 0x66, 0x43, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
+ 0x73, 0x5f, 0x63, 0x6d, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20,
+ 0x03, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+ 0x43, 0x6d, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x70,
+ 0x69, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x52, 0x03, 0x70, 0x69,
+ 0x64, 0x12, 0x6b, 0x0a, 0x16, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75,
+ 0x6f, 0x75, 0x73, 0x5f, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x63, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x48, 0x70, 0x72, 0x6f,
+ 0x66, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x74,
+ 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x52, 0x14, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e,
+ 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70, 0x43, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x1a, 0x64, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e,
+ 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70, 0x43, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x12, 0x22, 0x0a, 0x0d, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x70,
+ 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0d, 0x52, 0x0b, 0x64, 0x75, 0x6d, 0x70, 0x50, 0x68, 0x61, 0x73, 0x65,
+ 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x69,
+ 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x64, 0x75, 0x6d, 0x70, 0x49, 0x6e,
+ 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x73, 0x22, 0xb8, 0x01, 0x0a,
+ 0x10, 0x47, 0x70, 0x75, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x43,
+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f,
+ 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x63, 0x6f,
+ 0x75, 0x6e, 0x74, 0x65, 0x72, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4e,
+ 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
+ 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0a,
+ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x33,
+ 0x0a, 0x15, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x6d, 0x65, 0x6e, 0x74,
+ 0x65, 0x64, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x18,
+ 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x69, 0x6e, 0x73, 0x74, 0x72,
+ 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x53, 0x61, 0x6d, 0x70, 0x6c,
+ 0x69, 0x6e, 0x67, 0x12, 0x22, 0x0a, 0x0d, 0x66, 0x69, 0x78, 0x5f, 0x67,
+ 0x70, 0x75, 0x5f, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x0b, 0x66, 0x69, 0x78, 0x47, 0x70, 0x75, 0x43, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x22, 0x44, 0x0a, 0x12, 0x50, 0x61, 0x63, 0x6b, 0x61,
+ 0x67, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+ 0x67, 0x12, 0x2e, 0x0a, 0x13, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
+ 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72,
+ 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x70, 0x61, 0x63, 0x6b,
+ 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65,
+ 0x72, 0x2a, 0x8e, 0x01, 0x0a, 0x0c, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x4c, 0x6f, 0x67, 0x49, 0x64, 0x12, 0x0f, 0x0a, 0x0b, 0x4c, 0x49,
+ 0x44, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12,
+ 0x0d, 0x0a, 0x09, 0x4c, 0x49, 0x44, 0x5f, 0x52, 0x41, 0x44, 0x49, 0x4f,
+ 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x49, 0x44, 0x5f, 0x45, 0x56,
+ 0x45, 0x4e, 0x54, 0x53, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x49,
+ 0x44, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x10, 0x03, 0x12, 0x0d,
+ 0x0a, 0x09, 0x4c, 0x49, 0x44, 0x5f, 0x43, 0x52, 0x41, 0x53, 0x48, 0x10,
+ 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x49, 0x44, 0x5f, 0x53, 0x54, 0x41,
+ 0x54, 0x53, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x49, 0x44, 0x5f,
+ 0x53, 0x45, 0x43, 0x55, 0x52, 0x49, 0x54, 0x59, 0x10, 0x06, 0x12, 0x0e,
+ 0x0a, 0x0a, 0x4c, 0x49, 0x44, 0x5f, 0x4b, 0x45, 0x52, 0x4e, 0x45, 0x4c,
+ 0x10, 0x07, 0x2a, 0x9b, 0x01, 0x0a, 0x12, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x4c, 0x6f, 0x67, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74,
+ 0x79, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x55, 0x4e,
+ 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
+ 0x0f, 0x0a, 0x0b, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x55, 0x4e, 0x55, 0x53,
+ 0x45, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x49, 0x4f,
+ 0x5f, 0x56, 0x45, 0x52, 0x42, 0x4f, 0x53, 0x45, 0x10, 0x02, 0x12, 0x0e,
+ 0x0a, 0x0a, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x44, 0x45, 0x42, 0x55, 0x47,
+ 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x49,
+ 0x4e, 0x46, 0x4f, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x52, 0x49,
+ 0x4f, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x05, 0x12, 0x0e, 0x0a, 0x0a,
+ 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x06,
+ 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x46, 0x41, 0x54,
+ 0x41, 0x4c, 0x10, 0x07, 0x2a, 0xbf, 0x06, 0x0a, 0x0f, 0x4d, 0x65, 0x6d,
+ 0x69, 0x6e, 0x66, 0x6f, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73,
+ 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
+ 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
+ 0x00, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+ 0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x01,
+ 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
+ 0x4d, 0x45, 0x4d, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x10, 0x02, 0x12, 0x19,
+ 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x45,
+ 0x4d, 0x5f, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x10,
+ 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+ 0x5f, 0x42, 0x55, 0x46, 0x46, 0x45, 0x52, 0x53, 0x10, 0x04, 0x12, 0x12,
+ 0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x41,
+ 0x43, 0x48, 0x45, 0x44, 0x10, 0x05, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45,
+ 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x5f, 0x43,
+ 0x41, 0x43, 0x48, 0x45, 0x44, 0x10, 0x06, 0x12, 0x12, 0x0a, 0x0e, 0x4d,
+ 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56,
+ 0x45, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+ 0x46, 0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10,
+ 0x08, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+ 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e,
+ 0x10, 0x09, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46,
+ 0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41,
+ 0x4e, 0x4f, 0x4e, 0x10, 0x0a, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d,
+ 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f,
+ 0x46, 0x49, 0x4c, 0x45, 0x10, 0x0b, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45,
+ 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49,
+ 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x0c, 0x12, 0x17, 0x0a,
+ 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x55, 0x4e, 0x45,
+ 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x0d, 0x12, 0x13,
+ 0x0a, 0x0f, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x4c,
+ 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x0e, 0x12, 0x16, 0x0a, 0x12, 0x4d,
+ 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x5f,
+ 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x0f, 0x12, 0x15, 0x0a, 0x11, 0x4d,
+ 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x5f,
+ 0x46, 0x52, 0x45, 0x45, 0x10, 0x10, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x45,
+ 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x44, 0x49, 0x52, 0x54, 0x59, 0x10,
+ 0x11, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+ 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x12,
0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
- 0x53, 0x57, 0x41, 0x50, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x0f,
- 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
- 0x53, 0x57, 0x41, 0x50, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x10, 0x10, 0x12,
- 0x11, 0x0a, 0x0d, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x44,
- 0x49, 0x52, 0x54, 0x59, 0x10, 0x11, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45,
- 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x42,
- 0x41, 0x43, 0x4b, 0x10, 0x12, 0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, 0x4d,
- 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x5f, 0x50, 0x41,
- 0x47, 0x45, 0x53, 0x10, 0x13, 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d,
- 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x41, 0x50, 0x50, 0x45, 0x44, 0x10,
- 0x14, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
- 0x5f, 0x53, 0x48, 0x4d, 0x45, 0x4d, 0x10, 0x15, 0x12, 0x10, 0x0a, 0x0c,
- 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42,
- 0x10, 0x16, 0x12, 0x1c, 0x0a, 0x18, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46,
- 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x5f, 0x52, 0x45, 0x43, 0x4c, 0x41,
- 0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x17, 0x12, 0x1e, 0x0a, 0x1a,
- 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42,
- 0x5f, 0x55, 0x4e, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42,
- 0x4c, 0x45, 0x10, 0x18, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x4d, 0x49,
- 0x4e, 0x46, 0x4f, 0x5f, 0x4b, 0x45, 0x52, 0x4e, 0x45, 0x4c, 0x5f, 0x53,
- 0x54, 0x41, 0x43, 0x4b, 0x10, 0x19, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45,
- 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x5f, 0x54,
- 0x41, 0x42, 0x4c, 0x45, 0x53, 0x10, 0x1a, 0x12, 0x18, 0x0a, 0x14, 0x4d,
- 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49,
- 0x54, 0x5f, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x10, 0x1b, 0x12, 0x17, 0x0a,
- 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4f, 0x4d,
- 0x4d, 0x49, 0x54, 0x45, 0x44, 0x5f, 0x41, 0x53, 0x10, 0x1c, 0x12, 0x19,
- 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x56, 0x4d,
- 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10,
- 0x1d, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
- 0x5f, 0x56, 0x4d, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x55, 0x53, 0x45,
- 0x44, 0x10, 0x1e, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
- 0x46, 0x4f, 0x5f, 0x56, 0x4d, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x43,
- 0x48, 0x55, 0x4e, 0x4b, 0x10, 0x1f, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45,
- 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4d, 0x41, 0x5f, 0x54, 0x4f,
- 0x54, 0x41, 0x4c, 0x10, 0x20, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d,
- 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4d, 0x41, 0x5f, 0x46, 0x52, 0x45,
- 0x45, 0x10, 0x21, 0x2a, 0xc6, 0x15, 0x0a, 0x0e, 0x56, 0x6d, 0x73, 0x74,
- 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x16,
- 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x53,
- 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18,
- 0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
- 0x46, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x01,
- 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e,
- 0x52, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x42, 0x41, 0x54, 0x43,
- 0x48, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41,
- 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56,
- 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15,
- 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x43,
- 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x04, 0x12,
- 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
- 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49,
- 0x4c, 0x45, 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54,
- 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45,
- 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x06, 0x12, 0x19, 0x0a, 0x15, 0x56,
- 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x55, 0x4e, 0x45,
- 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x07, 0x12, 0x13,
- 0x0a, 0x0f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
- 0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x56,
- 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x4e, 0x4f,
- 0x4e, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x09, 0x12, 0x14, 0x0a,
- 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4d,
- 0x41, 0x50, 0x50, 0x45, 0x44, 0x10, 0x0a, 0x12, 0x18, 0x0a, 0x14, 0x56,
- 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x49, 0x4c,
- 0x45, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x0b, 0x12, 0x13, 0x0a,
- 0x0f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44,
- 0x49, 0x52, 0x54, 0x59, 0x10, 0x0c, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d,
- 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49, 0x54,
- 0x45, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x0d, 0x12, 0x1e, 0x0a, 0x1a, 0x56,
- 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x4c, 0x41,
+ 0x41, 0x4e, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x13,
+ 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
+ 0x4d, 0x41, 0x50, 0x50, 0x45, 0x44, 0x10, 0x14, 0x12, 0x11, 0x0a, 0x0d,
+ 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x48, 0x4d, 0x45,
+ 0x4d, 0x10, 0x15, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+ 0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x10, 0x16, 0x12, 0x1c, 0x0a,
+ 0x18, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41,
0x42, 0x5f, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42, 0x4c,
- 0x45, 0x10, 0x0e, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41,
- 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x5f, 0x55, 0x4e,
- 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10,
- 0x0f, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
- 0x4e, 0x52, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x41, 0x42, 0x4c,
- 0x45, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x10, 0x12, 0x1a, 0x0a,
- 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4b,
+ 0x45, 0x10, 0x17, 0x12, 0x1e, 0x0a, 0x1a, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+ 0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x5f, 0x55, 0x4e, 0x52, 0x45,
+ 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x18, 0x12,
+ 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4b,
0x45, 0x52, 0x4e, 0x45, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x43, 0x4b, 0x10,
- 0x11, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
- 0x4e, 0x52, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x48, 0x45, 0x41, 0x44, 0x10,
- 0x12, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
- 0x4e, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10,
- 0x13, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
- 0x4e, 0x52, 0x5f, 0x42, 0x4f, 0x55, 0x4e, 0x43, 0x45, 0x10, 0x14, 0x12,
- 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
- 0x5f, 0x56, 0x4d, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x57, 0x52, 0x49, 0x54,
- 0x45, 0x10, 0x15, 0x12, 0x26, 0x0a, 0x22, 0x56, 0x4d, 0x53, 0x54, 0x41,
- 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x56, 0x4d, 0x53, 0x43, 0x41, 0x4e, 0x5f,
- 0x49, 0x4d, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x54, 0x45, 0x5f, 0x52, 0x45,
- 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x10, 0x16, 0x12, 0x1c, 0x0a, 0x18, 0x56,
- 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49,
- 0x54, 0x45, 0x42, 0x41, 0x43, 0x4b, 0x5f, 0x54, 0x45, 0x4d, 0x50, 0x10,
- 0x17, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x19, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+ 0x5f, 0x50, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x53,
+ 0x10, 0x1a, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46,
+ 0x4f, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x5f, 0x4c, 0x49, 0x4d,
+ 0x49, 0x54, 0x10, 0x1b, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49,
+ 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x45, 0x44,
+ 0x5f, 0x41, 0x53, 0x10, 0x1c, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d,
+ 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x56, 0x4d, 0x41, 0x4c, 0x4c, 0x4f, 0x43,
+ 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x1d, 0x12, 0x18, 0x0a, 0x14,
+ 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x56, 0x4d, 0x41, 0x4c,
+ 0x4c, 0x4f, 0x43, 0x5f, 0x55, 0x53, 0x45, 0x44, 0x10, 0x1e, 0x12, 0x19,
+ 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x56, 0x4d,
+ 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x43, 0x48, 0x55, 0x4e, 0x4b, 0x10,
+ 0x1f, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+ 0x5f, 0x43, 0x4d, 0x41, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x20,
+ 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
+ 0x43, 0x4d, 0x41, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x10, 0x21, 0x2a, 0xc6,
+ 0x15, 0x0a, 0x0e, 0x56, 0x6d, 0x73, 0x74, 0x61, 0x74, 0x43, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53,
+ 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
+ 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53,
+ 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x5f,
+ 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x4c, 0x4c,
+ 0x4f, 0x43, 0x5f, 0x42, 0x41, 0x54, 0x43, 0x48, 0x10, 0x02, 0x12, 0x1b,
+ 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
+ 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f,
+ 0x4e, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f,
+ 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x04, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d,
+ 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x4e, 0x41, 0x43,
+ 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x05, 0x12,
+ 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
+ 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45,
+ 0x10, 0x06, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x4e, 0x52, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41,
+ 0x42, 0x4c, 0x45, 0x10, 0x07, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x4d, 0x53,
+ 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4d, 0x4c, 0x4f, 0x43, 0x4b,
+ 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x47,
+ 0x45, 0x53, 0x10, 0x09, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4d, 0x41, 0x50, 0x50, 0x45, 0x44,
+ 0x10, 0x0a, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x50, 0x41, 0x47,
+ 0x45, 0x53, 0x10, 0x0b, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x4d, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49, 0x52, 0x54, 0x59, 0x10,
+ 0x0c, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x42, 0x41, 0x43, 0x4b,
+ 0x10, 0x0d, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x5f, 0x52, 0x45, 0x43,
+ 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x0e, 0x12, 0x20,
+ 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
+ 0x53, 0x4c, 0x41, 0x42, 0x5f, 0x55, 0x4e, 0x52, 0x45, 0x43, 0x4c, 0x41,
+ 0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x0f, 0x12, 0x1e, 0x0a, 0x1a,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x50, 0x41,
+ 0x47, 0x45, 0x5f, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x41, 0x47,
+ 0x45, 0x53, 0x10, 0x10, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4b, 0x45, 0x52, 0x4e, 0x45, 0x4c,
+ 0x5f, 0x53, 0x54, 0x41, 0x43, 0x4b, 0x10, 0x11, 0x12, 0x16, 0x0a, 0x12,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4f, 0x56,
+ 0x45, 0x52, 0x48, 0x45, 0x41, 0x44, 0x10, 0x12, 0x12, 0x16, 0x0a, 0x12,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x55, 0x4e,
+ 0x53, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x13, 0x12, 0x14, 0x0a, 0x10,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x42, 0x4f,
+ 0x55, 0x4e, 0x43, 0x45, 0x10, 0x14, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d,
+ 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x56, 0x4d, 0x53, 0x43,
+ 0x41, 0x4e, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, 0x15, 0x12, 0x26,
+ 0x0a, 0x22, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
+ 0x56, 0x4d, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x49, 0x4d, 0x4d, 0x45, 0x44,
+ 0x49, 0x41, 0x54, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d,
+ 0x10, 0x16, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x42, 0x41, 0x43,
+ 0x4b, 0x5f, 0x54, 0x45, 0x4d, 0x50, 0x10, 0x17, 0x12, 0x1b, 0x0a, 0x17,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x53,
+ 0x4f, 0x4c, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10,
+ 0x18, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
0x4e, 0x52, 0x5f, 0x49, 0x53, 0x4f, 0x4c, 0x41, 0x54, 0x45, 0x44, 0x5f,
- 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x18, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d,
- 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x53, 0x4f, 0x4c,
- 0x41, 0x54, 0x45, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x19, 0x12,
- 0x13, 0x0a, 0x0f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
- 0x5f, 0x53, 0x48, 0x4d, 0x45, 0x4d, 0x10, 0x1a, 0x12, 0x15, 0x0a, 0x11,
- 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49,
- 0x52, 0x54, 0x49, 0x45, 0x44, 0x10, 0x1b, 0x12, 0x15, 0x0a, 0x11, 0x56,
- 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49,
- 0x54, 0x54, 0x45, 0x4e, 0x10, 0x1c, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d,
- 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x50, 0x41, 0x47, 0x45,
- 0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x1d, 0x12,
- 0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x57, 0x4f,
- 0x52, 0x4b, 0x49, 0x4e, 0x47, 0x53, 0x45, 0x54, 0x5f, 0x52, 0x45, 0x46,
- 0x41, 0x55, 0x4c, 0x54, 0x10, 0x1e, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d,
+ 0x46, 0x49, 0x4c, 0x45, 0x10, 0x19, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x4d,
+ 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x48, 0x4d, 0x45,
+ 0x4d, 0x10, 0x1a, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49, 0x52, 0x54, 0x49, 0x45, 0x44,
+ 0x10, 0x1b, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x54, 0x45, 0x4e, 0x10,
+ 0x1c, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x4e, 0x52, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x5f, 0x53, 0x43, 0x41,
+ 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x1d, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d,
0x53, 0x54, 0x41, 0x54, 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x49, 0x4e, 0x47,
- 0x53, 0x45, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45,
- 0x10, 0x1f, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
- 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x49, 0x4e, 0x47, 0x53, 0x45, 0x54, 0x5f,
- 0x4e, 0x4f, 0x44, 0x45, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x10,
- 0x20, 0x12, 0x28, 0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
- 0x4e, 0x52, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e,
- 0x53, 0x50, 0x41, 0x52, 0x45, 0x4e, 0x54, 0x5f, 0x48, 0x55, 0x47, 0x45,
- 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x21, 0x12, 0x16, 0x0a, 0x12, 0x56,
- 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x52, 0x45,
- 0x45, 0x5f, 0x43, 0x4d, 0x41, 0x10, 0x22, 0x12, 0x17, 0x0a, 0x13, 0x56,
- 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x57, 0x41,
- 0x50, 0x43, 0x41, 0x43, 0x48, 0x45, 0x10, 0x23, 0x12, 0x1d, 0x0a, 0x19,
- 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49,
- 0x52, 0x54, 0x59, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x53, 0x48, 0x4f, 0x4c,
- 0x44, 0x10, 0x24, 0x12, 0x28, 0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54, 0x41,
- 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49, 0x52, 0x54, 0x59, 0x5f, 0x42,
- 0x41, 0x43, 0x4b, 0x47, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x54, 0x48,
- 0x52, 0x45, 0x53, 0x48, 0x4f, 0x4c, 0x44, 0x10, 0x25, 0x12, 0x11, 0x0a,
- 0x0d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x50, 0x47,
- 0x49, 0x4e, 0x10, 0x26, 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4d, 0x53, 0x54,
- 0x41, 0x54, 0x5f, 0x50, 0x47, 0x50, 0x47, 0x4f, 0x55, 0x54, 0x10, 0x27,
+ 0x53, 0x45, 0x54, 0x5f, 0x52, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10,
+ 0x1e, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x57, 0x4f, 0x52, 0x4b, 0x49, 0x4e, 0x47, 0x53, 0x45, 0x54, 0x5f, 0x41,
+ 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x1f, 0x12, 0x21, 0x0a,
+ 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x57, 0x4f, 0x52, 0x4b,
+ 0x49, 0x4e, 0x47, 0x53, 0x45, 0x54, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x52,
+ 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x10, 0x20, 0x12, 0x28, 0x0a, 0x24,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x4e,
+ 0x4f, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x50, 0x41, 0x52, 0x45,
+ 0x4e, 0x54, 0x5f, 0x48, 0x55, 0x47, 0x45, 0x50, 0x41, 0x47, 0x45, 0x53,
+ 0x10, 0x21, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x5f, 0x43, 0x4d, 0x41,
+ 0x10, 0x22, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x43, 0x41, 0x43, 0x48,
+ 0x45, 0x10, 0x23, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49, 0x52, 0x54, 0x59, 0x5f, 0x54,
+ 0x48, 0x52, 0x45, 0x53, 0x48, 0x4f, 0x4c, 0x44, 0x10, 0x24, 0x12, 0x28,
+ 0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
+ 0x44, 0x49, 0x52, 0x54, 0x59, 0x5f, 0x42, 0x41, 0x43, 0x4b, 0x47, 0x52,
+ 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x53, 0x48, 0x4f,
+ 0x4c, 0x44, 0x10, 0x25, 0x12, 0x11, 0x0a, 0x0d, 0x56, 0x4d, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x50, 0x47, 0x50, 0x47, 0x49, 0x4e, 0x10, 0x26, 0x12,
+ 0x12, 0x0a, 0x0e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
+ 0x50, 0x47, 0x4f, 0x55, 0x54, 0x10, 0x27, 0x12, 0x17, 0x0a, 0x13, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x50, 0x47, 0x4f, 0x55,
+ 0x54, 0x43, 0x4c, 0x45, 0x41, 0x4e, 0x10, 0x28, 0x12, 0x11, 0x0a, 0x0d,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x53, 0x57, 0x50, 0x49,
+ 0x4e, 0x10, 0x29, 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x50, 0x53, 0x57, 0x50, 0x4f, 0x55, 0x54, 0x10, 0x2a, 0x12,
+ 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
+ 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x2b, 0x12,
+ 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
+ 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c,
+ 0x10, 0x2c, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x4d, 0x4f, 0x56,
+ 0x41, 0x42, 0x4c, 0x45, 0x10, 0x2d, 0x12, 0x11, 0x0a, 0x0d, 0x56, 0x4d,
+ 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x46, 0x52, 0x45, 0x45, 0x10,
+ 0x2e, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x50, 0x47, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x2f,
0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50,
- 0x47, 0x50, 0x47, 0x4f, 0x55, 0x54, 0x43, 0x4c, 0x45, 0x41, 0x4e, 0x10,
- 0x28, 0x12, 0x11, 0x0a, 0x0d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
- 0x50, 0x53, 0x57, 0x50, 0x49, 0x4e, 0x10, 0x29, 0x12, 0x12, 0x0a, 0x0e,
- 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x53, 0x57, 0x50, 0x4f,
- 0x55, 0x54, 0x10, 0x2a, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54,
- 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x44,
- 0x4d, 0x41, 0x10, 0x2b, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54,
- 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x4e,
- 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x2c, 0x12, 0x1a, 0x0a, 0x16, 0x56,
- 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f,
- 0x43, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x2d, 0x12,
- 0x11, 0x0a, 0x0d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
- 0x46, 0x52, 0x45, 0x45, 0x10, 0x2e, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d,
- 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x43, 0x54, 0x49, 0x56,
- 0x41, 0x54, 0x45, 0x10, 0x2f, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53,
- 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x44, 0x45, 0x41, 0x43, 0x54, 0x49,
- 0x56, 0x41, 0x54, 0x45, 0x10, 0x30, 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4d,
- 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x46, 0x41, 0x55, 0x4c, 0x54,
- 0x10, 0x31, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
- 0x5f, 0x50, 0x47, 0x4d, 0x41, 0x4a, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10,
- 0x32, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
- 0x50, 0x47, 0x52, 0x45, 0x46, 0x49, 0x4c, 0x4c, 0x5f, 0x44, 0x4d, 0x41,
- 0x10, 0x33, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
- 0x5f, 0x50, 0x47, 0x52, 0x45, 0x46, 0x49, 0x4c, 0x4c, 0x5f, 0x4e, 0x4f,
- 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x34, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d,
- 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x52, 0x45, 0x46, 0x49, 0x4c,
- 0x4c, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x35, 0x12,
- 0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
- 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44,
- 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x36, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d,
+ 0x47, 0x44, 0x45, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10,
+ 0x30, 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x50, 0x47, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x31, 0x12, 0x15, 0x0a,
+ 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x4d, 0x41,
+ 0x4a, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x32, 0x12, 0x17, 0x0a, 0x13,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x52, 0x45, 0x46,
+ 0x49, 0x4c, 0x4c, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x33, 0x12, 0x1a, 0x0a,
+ 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x52, 0x45,
+ 0x46, 0x49, 0x4c, 0x4c, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10,
+ 0x34, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x50, 0x47, 0x52, 0x45, 0x46, 0x49, 0x4c, 0x4c, 0x5f, 0x4d, 0x4f, 0x56,
+ 0x41, 0x42, 0x4c, 0x45, 0x10, 0x35, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d,
0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c,
- 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4e, 0x4f, 0x52, 0x4d,
- 0x41, 0x4c, 0x10, 0x37, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54,
- 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x4b,
- 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c,
- 0x45, 0x10, 0x38, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41,
- 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x44, 0x49,
- 0x52, 0x45, 0x43, 0x54, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x39, 0x12, 0x20,
- 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53,
- 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f,
- 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x3a, 0x12, 0x21, 0x0a, 0x1d,
- 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45,
- 0x41, 0x4c, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4d, 0x4f,
- 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x3b, 0x12, 0x1c, 0x0a, 0x18, 0x56,
- 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e,
0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x44, 0x4d, 0x41, 0x10,
- 0x3c, 0x12, 0x1f, 0x0a, 0x1b, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
- 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50,
- 0x44, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x3d, 0x12, 0x20,
- 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53,
- 0x43, 0x41, 0x4e, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4d,
- 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x3e, 0x12, 0x1c, 0x0a, 0x18,
+ 0x36, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x4b, 0x53, 0x57, 0x41,
+ 0x50, 0x44, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x37, 0x12,
+ 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
+ 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44,
+ 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x38, 0x12, 0x1d,
+ 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53,
+ 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f,
+ 0x44, 0x4d, 0x41, 0x10, 0x39, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53,
+ 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f,
+ 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41,
+ 0x4c, 0x10, 0x3a, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x44, 0x49,
+ 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45,
+ 0x10, 0x3b, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x4b, 0x53, 0x57, 0x41,
+ 0x50, 0x44, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x3c, 0x12, 0x1f, 0x0a, 0x1b,
0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41,
- 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x44, 0x4d, 0x41,
- 0x10, 0x3f, 0x12, 0x1f, 0x0a, 0x1b, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
- 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45,
- 0x43, 0x54, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x40, 0x12,
- 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
- 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f,
- 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x41, 0x12, 0x21, 0x0a,
- 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43,
- 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x54, 0x48,
- 0x52, 0x4f, 0x54, 0x54, 0x4c, 0x45, 0x10, 0x42, 0x12, 0x17, 0x0a, 0x13,
- 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x49, 0x4e, 0x4f,
- 0x44, 0x45, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x10, 0x43, 0x12, 0x18, 0x0a,
- 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x53, 0x4c, 0x41, 0x42,
- 0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x44, 0x12,
- 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53,
- 0x57, 0x41, 0x50, 0x44, 0x5f, 0x49, 0x4e, 0x4f, 0x44, 0x45, 0x53, 0x54,
- 0x45, 0x41, 0x4c, 0x10, 0x45, 0x12, 0x27, 0x0a, 0x23, 0x56, 0x4d, 0x53,
- 0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4c,
- 0x4f, 0x57, 0x5f, 0x57, 0x4d, 0x41, 0x52, 0x4b, 0x5f, 0x48, 0x49, 0x54,
- 0x5f, 0x51, 0x55, 0x49, 0x43, 0x4b, 0x4c, 0x59, 0x10, 0x46, 0x12, 0x28,
- 0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53, 0x57,
- 0x41, 0x50, 0x44, 0x5f, 0x48, 0x49, 0x47, 0x48, 0x5f, 0x57, 0x4d, 0x41,
- 0x52, 0x4b, 0x5f, 0x48, 0x49, 0x54, 0x5f, 0x51, 0x55, 0x49, 0x43, 0x4b,
- 0x4c, 0x59, 0x10, 0x47, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54,
- 0x41, 0x54, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x4f, 0x55, 0x54, 0x52, 0x55,
- 0x4e, 0x10, 0x48, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41,
- 0x54, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x53, 0x54, 0x41, 0x4c, 0x4c,
- 0x10, 0x49, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
- 0x5f, 0x50, 0x47, 0x52, 0x4f, 0x54, 0x41, 0x54, 0x45, 0x44, 0x10, 0x4a,
- 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x44,
- 0x52, 0x4f, 0x50, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x43, 0x41, 0x43, 0x48,
- 0x45, 0x10, 0x4b, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41,
- 0x54, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x10,
- 0x4c, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
- 0x50, 0x47, 0x4d, 0x49, 0x47, 0x52, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x55,
- 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x4d, 0x12, 0x19, 0x0a, 0x15, 0x56,
- 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x4d, 0x49, 0x47, 0x52,
- 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x4e, 0x12, 0x22,
- 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d,
- 0x50, 0x41, 0x43, 0x54, 0x5f, 0x4d, 0x49, 0x47, 0x52, 0x41, 0x54, 0x45,
- 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x4f, 0x12, 0x1f,
- 0x0a, 0x1b, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d,
- 0x50, 0x41, 0x43, 0x54, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x5f, 0x53, 0x43,
- 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x50, 0x12, 0x1b, 0x0a, 0x17, 0x56,
+ 0x4e, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4e, 0x4f, 0x52,
+ 0x4d, 0x41, 0x4c, 0x10, 0x3d, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53,
+ 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x4b,
+ 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c,
+ 0x45, 0x10, 0x3e, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52,
+ 0x45, 0x43, 0x54, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x3f, 0x12, 0x1f, 0x0a,
+ 0x1b, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43,
+ 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4e, 0x4f,
+ 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x40, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d,
+ 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f,
+ 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42,
+ 0x4c, 0x45, 0x10, 0x41, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44, 0x49,
+ 0x52, 0x45, 0x43, 0x54, 0x5f, 0x54, 0x48, 0x52, 0x4f, 0x54, 0x54, 0x4c,
+ 0x45, 0x10, 0x42, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x50, 0x47, 0x49, 0x4e, 0x4f, 0x44, 0x45, 0x53, 0x54, 0x45,
+ 0x41, 0x4c, 0x10, 0x43, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x53, 0x5f, 0x53, 0x43, 0x41,
+ 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x44, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d,
+ 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f,
+ 0x49, 0x4e, 0x4f, 0x44, 0x45, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x10, 0x45,
+ 0x12, 0x27, 0x0a, 0x23, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4b,
+ 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4c, 0x4f, 0x57, 0x5f, 0x57, 0x4d,
+ 0x41, 0x52, 0x4b, 0x5f, 0x48, 0x49, 0x54, 0x5f, 0x51, 0x55, 0x49, 0x43,
+ 0x4b, 0x4c, 0x59, 0x10, 0x46, 0x12, 0x28, 0x0a, 0x24, 0x56, 0x4d, 0x53,
+ 0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x48,
+ 0x49, 0x47, 0x48, 0x5f, 0x57, 0x4d, 0x41, 0x52, 0x4b, 0x5f, 0x48, 0x49,
+ 0x54, 0x5f, 0x51, 0x55, 0x49, 0x43, 0x4b, 0x4c, 0x59, 0x10, 0x47, 0x12,
+ 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x41,
+ 0x47, 0x45, 0x4f, 0x55, 0x54, 0x52, 0x55, 0x4e, 0x10, 0x48, 0x12, 0x15,
+ 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x41, 0x4c, 0x4c,
+ 0x4f, 0x43, 0x53, 0x54, 0x41, 0x4c, 0x4c, 0x10, 0x49, 0x12, 0x14, 0x0a,
+ 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x52, 0x4f,
+ 0x54, 0x41, 0x54, 0x45, 0x44, 0x10, 0x4a, 0x12, 0x19, 0x0a, 0x15, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x5f, 0x50,
+ 0x41, 0x47, 0x45, 0x43, 0x41, 0x43, 0x48, 0x45, 0x10, 0x4b, 0x12, 0x14,
+ 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x44, 0x52, 0x4f,
+ 0x50, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x10, 0x4c, 0x12, 0x1c, 0x0a, 0x18,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x4d, 0x49, 0x47,
+ 0x52, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53,
+ 0x10, 0x4d, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x50, 0x47, 0x4d, 0x49, 0x47, 0x52, 0x41, 0x54, 0x45, 0x5f, 0x46,
+ 0x41, 0x49, 0x4c, 0x10, 0x4e, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53,
+ 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f,
+ 0x4d, 0x49, 0x47, 0x52, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x43, 0x41, 0x4e,
+ 0x4e, 0x45, 0x44, 0x10, 0x4f, 0x12, 0x1f, 0x0a, 0x1b, 0x56, 0x4d, 0x53,
+ 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f,
+ 0x46, 0x52, 0x45, 0x45, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44,
+ 0x10, 0x50, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x49, 0x53, 0x4f,
+ 0x4c, 0x41, 0x54, 0x45, 0x44, 0x10, 0x51, 0x12, 0x18, 0x0a, 0x14, 0x56,
0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43,
- 0x54, 0x5f, 0x49, 0x53, 0x4f, 0x4c, 0x41, 0x54, 0x45, 0x44, 0x10, 0x51,
- 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43,
- 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x4c, 0x4c,
- 0x10, 0x52, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
- 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x46, 0x41, 0x49,
- 0x4c, 0x10, 0x53, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41,
- 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x53, 0x55,
- 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x54, 0x12, 0x1e, 0x0a, 0x1a, 0x56,
- 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43,
- 0x54, 0x5f, 0x44, 0x41, 0x45, 0x4d, 0x4f, 0x4e, 0x5f, 0x57, 0x41, 0x4b,
- 0x45, 0x10, 0x55, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41,
- 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c,
- 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x43, 0x55, 0x4c, 0x4c, 0x45, 0x44,
- 0x10, 0x56, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
- 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45,
- 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44,
- 0x10, 0x57, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
- 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45,
- 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x52, 0x45, 0x53, 0x43, 0x55, 0x45, 0x44,
- 0x10, 0x58, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
- 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45,
- 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44,
- 0x10, 0x59, 0x12, 0x24, 0x0a, 0x20, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
- 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45,
- 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x4d, 0x55, 0x4e, 0x4c, 0x4f, 0x43, 0x4b,
- 0x45, 0x44, 0x10, 0x5a, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54,
- 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42,
- 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x43, 0x4c, 0x45, 0x41, 0x52,
- 0x45, 0x44, 0x10, 0x5b, 0x12, 0x23, 0x0a, 0x1f, 0x56, 0x4d, 0x53, 0x54,
- 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42,
- 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x53, 0x54, 0x52, 0x41, 0x4e,
- 0x44, 0x45, 0x44, 0x10, 0x5c, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53,
- 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x5a, 0x53, 0x50, 0x41, 0x47,
- 0x45, 0x53, 0x10, 0x5d, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54,
- 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x4f, 0x4e, 0x5f, 0x48, 0x45,
- 0x41, 0x50, 0x10, 0x5e, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54,
- 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x47, 0x50, 0x55, 0x5f, 0x48, 0x45,
- 0x41, 0x50, 0x10, 0x5f}};
+ 0x54, 0x5f, 0x53, 0x54, 0x41, 0x4c, 0x4c, 0x10, 0x52, 0x12, 0x17, 0x0a,
+ 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50,
+ 0x41, 0x43, 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x53, 0x12, 0x1a,
+ 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d,
+ 0x50, 0x41, 0x43, 0x54, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53,
+ 0x10, 0x54, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x44, 0x41, 0x45,
+ 0x4d, 0x4f, 0x4e, 0x5f, 0x57, 0x41, 0x4b, 0x45, 0x10, 0x55, 0x12, 0x21,
+ 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45,
+ 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53,
+ 0x5f, 0x43, 0x55, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x56, 0x12, 0x22, 0x0a,
+ 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56,
+ 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f,
+ 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x57, 0x12, 0x22, 0x0a,
+ 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56,
+ 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f,
+ 0x52, 0x45, 0x53, 0x43, 0x55, 0x45, 0x44, 0x10, 0x58, 0x12, 0x22, 0x0a,
+ 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56,
+ 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f,
+ 0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x59, 0x12, 0x24, 0x0a,
+ 0x20, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56,
+ 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f,
+ 0x4d, 0x55, 0x4e, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x5a, 0x12,
+ 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e,
+ 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47,
+ 0x53, 0x5f, 0x43, 0x4c, 0x45, 0x41, 0x52, 0x45, 0x44, 0x10, 0x5b, 0x12,
+ 0x23, 0x0a, 0x1f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e,
+ 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47,
+ 0x53, 0x5f, 0x53, 0x54, 0x52, 0x41, 0x4e, 0x44, 0x45, 0x44, 0x10, 0x5c,
+ 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e,
+ 0x52, 0x5f, 0x5a, 0x53, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x5d, 0x12,
+ 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
+ 0x5f, 0x49, 0x4f, 0x4e, 0x5f, 0x48, 0x45, 0x41, 0x50, 0x10, 0x5e, 0x12,
+ 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
+ 0x5f, 0x47, 0x50, 0x55, 0x5f, 0x48, 0x45, 0x41, 0x50, 0x10, 0x5f}};
} // namespace perfetto
diff --git a/src/perfetto_cmd/trigger_producer.cc b/src/perfetto_cmd/trigger_producer.cc
index b121c6a..7aefabd 100644
--- a/src/perfetto_cmd/trigger_producer.cc
+++ b/src/perfetto_cmd/trigger_producer.cc
@@ -25,8 +25,6 @@
namespace perfetto {
-class DataSourceConfig;
-
TriggerProducer::TriggerProducer(base::TaskRunner* task_runner,
std::function<void(bool)> callback,
const std::vector<std::string>* const triggers)
diff --git a/src/profiling/memory/client.cc b/src/profiling/memory/client.cc
index 8065733..59fe313 100644
--- a/src/profiling/memory/client.cc
+++ b/src/profiling/memory/client.cc
@@ -30,6 +30,7 @@
#include <unwindstack/Regs.h>
#include <unwindstack/RegsGetLocal.h>
+#include <algorithm>
#include <atomic>
#include <new>
@@ -81,6 +82,17 @@
return 0;
}
+constexpr uint64_t kInfiniteTries = 0;
+
+uint64_t GetMaxTries(const ClientConfiguration& client_config) {
+ if (!client_config.block_client)
+ return 1u;
+ if (client_config.block_client_timeout_us == 0)
+ return kInfiniteTries;
+ return std::min<uint64_t>(
+ 1ul, client_config.block_client_timeout_us / kResendBackoffUs);
+}
+
} // namespace
const char* GetThreadStackBase() {
@@ -213,10 +225,7 @@
}
PERFETTO_DCHECK(client_config.interval >= 1);
- // TODO(fmayer): Always make this nonblocking.
- // This is so that without block_client, we get the old behaviour that rate
- // limits using the blocking socket. We do not want to change that for Q.
- sock.SetBlocking(!client_config.block_client);
+ sock.SetBlocking(false);
Sampler sampler{client_config.interval};
// note: the shared_ptr will retain a copy of the unhooked_allocator
return std::allocate_shared<Client>(unhooked_allocator, std::move(sock),
@@ -232,6 +241,7 @@
pid_t pid_at_creation,
const char* main_thread_stack_base)
: client_config_(client_config),
+ max_shmem_tries_(GetMaxTries(client_config_)),
sampler_(std::move(sampler)),
sock_(std::move(sock)),
main_thread_stack_base_(main_thread_stack_base),
@@ -310,17 +320,19 @@
}
bool Client::SendWireMessageWithRetriesIfBlocking(const WireMessage& msg) {
- for (;;) {
+ for (uint64_t i = 0;
+ max_shmem_tries_ == kInfiniteTries || i < max_shmem_tries_; ++i) {
if (PERFETTO_LIKELY(SendWireMessage(&shmem_, msg)))
return true;
// retry if in blocking mode and still connected
if (client_config_.block_client && base::IsAgain(errno) && IsConnected()) {
usleep(kResendBackoffUs);
- continue;
+ } else {
+ break;
}
- PERFETTO_PLOG("Failed to write to shared ring buffer. Disconnecting.");
- return false;
}
+ PERFETTO_PLOG("Failed to write to shared ring buffer. Disconnecting.");
+ return false;
}
bool Client::RecordFree(const uint64_t alloc_address) {
@@ -379,10 +391,12 @@
}
bool Client::SendControlSocketByte() {
- // TODO(fmayer): Fix the special casing that only block_client uses a
- // nonblocking socket.
+ // If base::IsAgain(errno), the socket buffer is full, so the service will
+ // pick up the notification even without adding another byte.
+ // In other error cases (usually EPIPE) we want to disconnect, because that
+ // is how the service signals the tracing session was torn down.
if (sock_.Send(kSingleByte, sizeof(kSingleByte)) == -1 &&
- (!client_config_.block_client || !base::IsAgain(errno))) {
+ !base::IsAgain(errno)) {
PERFETTO_PLOG("Failed to send control socket byte.");
return false;
}
diff --git a/src/profiling/memory/client.h b/src/profiling/memory/client.h
index d32f2e8..02e5a50 100644
--- a/src/profiling/memory/client.h
+++ b/src/profiling/memory/client.h
@@ -105,6 +105,7 @@
bool IsConnected();
ClientConfiguration client_config_;
+ uint64_t max_shmem_tries_;
// sampler_ operations are not thread-safe.
Sampler sampler_;
base::UnixSocketRaw sock_;
diff --git a/src/profiling/memory/heapprofd_producer.cc b/src/profiling/memory/heapprofd_producer.cc
index c10adc3..cdfca23 100644
--- a/src/profiling/memory/heapprofd_producer.cc
+++ b/src/profiling/memory/heapprofd_producer.cc
@@ -351,6 +351,8 @@
auto& cli_config = data_source.client_configuration;
cli_config.interval = heapprofd_config.sampling_interval_bytes();
cli_config.block_client = heapprofd_config.block_client();
+ cli_config.block_client_timeout_us =
+ heapprofd_config.block_client_timeout_us();
data_source.config = heapprofd_config;
data_source.normalized_cmdlines = std::move(normalized_cmdlines);
data_source.stop_timeout_ms = ds_config.stop_timeout_ms();
diff --git a/src/profiling/memory/malloc_hooks.cc b/src/profiling/memory/malloc_hooks.cc
index d70ac3c..7f6d1c3 100644
--- a/src/profiling/memory/malloc_hooks.cc
+++ b/src/profiling/memory/malloc_hooks.cc
@@ -84,12 +84,12 @@
int HEAPPROFD_ADD_PREFIX(_posix_memalign)(void** memptr,
size_t alignment,
size_t size);
-int HEAPPROFD_ADD_PREFIX(_iterate)(uintptr_t base,
- size_t size,
- void (*callback)(uintptr_t base,
- size_t size,
- void* arg),
- void* arg);
+int HEAPPROFD_ADD_PREFIX(_malloc_iterate)(uintptr_t base,
+ size_t size,
+ void (*callback)(uintptr_t base,
+ size_t size,
+ void* arg),
+ void* arg);
void HEAPPROFD_ADD_PREFIX(_malloc_disable)();
void HEAPPROFD_ADD_PREFIX(_malloc_enable)();
@@ -620,12 +620,12 @@
return dispatch->malloc_info(options, fp);
}
-int HEAPPROFD_ADD_PREFIX(_iterate)(uintptr_t,
- size_t,
- void (*)(uintptr_t base,
- size_t size,
- void* arg),
- void*) {
+int HEAPPROFD_ADD_PREFIX(_malloc_iterate)(uintptr_t,
+ size_t,
+ void (*)(uintptr_t base,
+ size_t size,
+ void* arg),
+ void*) {
return 0;
}
diff --git a/src/profiling/memory/unwinding.cc b/src/profiling/memory/unwinding.cc
index ced87f9..6b030c0 100644
--- a/src/profiling/memory/unwinding.cc
+++ b/src/profiling/memory/unwinding.cc
@@ -303,9 +303,7 @@
shmem.EndRead(std::move(buf));
// Reparsing takes time, so process the rest in a new batch to avoid timing
// out.
- // TODO(fmayer): Do not special case blocking mode.
- if (client_data.client_config.block_client &&
- reparses_before < client_data.metadata.reparses) {
+ if (reparses_before < client_data.metadata.reparses) {
repost_task = true;
break;
}
diff --git a/src/profiling/memory/wire_protocol.h b/src/profiling/memory/wire_protocol.h
index 3ca21d9..1a40b8f 100644
--- a/src/profiling/memory/wire_protocol.h
+++ b/src/profiling/memory/wire_protocol.h
@@ -45,6 +45,7 @@
// Must be >= 1.
uint64_t interval;
bool block_client;
+ uint64_t block_client_timeout_us;
};
// Types needed for the wire format used for communication between the client
diff --git a/src/protozero/BUILD.gn b/src/protozero/BUILD.gn
index bcc34e0..b2cc13a 100644
--- a/src/protozero/BUILD.gn
+++ b/src/protozero/BUILD.gn
@@ -57,6 +57,7 @@
"../base:test_support",
]
sources = [
+ "copyable_ptr_unittest.cc",
"message_handle_unittest.cc",
"message_unittest.cc",
"proto_decoder_unittest.cc",
diff --git a/src/base/copyable_ptr_unittest.cc b/src/protozero/copyable_ptr_unittest.cc
similarity index 94%
rename from src/base/copyable_ptr_unittest.cc
rename to src/protozero/copyable_ptr_unittest.cc
index ecbd1ef..d9be950 100644
--- a/src/base/copyable_ptr_unittest.cc
+++ b/src/protozero/copyable_ptr_unittest.cc
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-#include "perfetto/base/copyable_ptr.h"
+#include "perfetto/protozero/copyable_ptr.h"
#include "test/gtest_and_gmock.h"
-namespace perfetto {
-namespace base {
+namespace protozero {
namespace {
struct X {
@@ -116,5 +115,4 @@
}
} // namespace
-} // namespace base
-} // namespace perfetto
+} // namespace protozero
diff --git a/src/protozero/proto_decoder_unittest.cc b/src/protozero/proto_decoder_unittest.cc
index 1a63cef..eb9f6f7 100644
--- a/src/protozero/proto_decoder_unittest.cc
+++ b/src/protozero/proto_decoder_unittest.cc
@@ -25,8 +25,11 @@
#include "src/protozero/test/example_proto/test_messages.pb.h"
#include "src/protozero/test/example_proto/test_messages.pbzero.h"
-namespace pbtest = foo::bar::pbzero; // Generated by the protozero plugin.
-namespace pbgold = foo::bar; // Generated by the official protobuf compiler.
+// Generated by the protozero plugin.
+namespace pbtest = protozero::test::protos::pbzero;
+
+// Generated by the official protobuf compiler.
+namespace pbgold = protozero::test::protos;
namespace protozero {
namespace {
@@ -90,6 +93,28 @@
EXPECT_FALSE(++it);
}
+TEST(ProtoDecoderTest, RepeatedVariableLengthField) {
+ HeapBuffered<Message> message;
+
+ static constexpr char kTestString[] = "test";
+ static constexpr char kTestString2[] = "honk honk";
+ message->AppendString(1, kTestString);
+ message->AppendString(1, kTestString2);
+ std::vector<uint8_t> proto = message.SerializeAsArray();
+ TypedProtoDecoder<32, false> decoder(proto.data(), proto.size());
+
+ auto it = decoder.GetRepeated<ConstChars>(1);
+ ASSERT_EQ(it->type(), ProtoWireType::kLengthDelimited);
+ ASSERT_EQ(it->size(), sizeof(kTestString) - 1);
+ ASSERT_EQ(it->as_std_string(), std::string(kTestString));
+ ASSERT_EQ((*it).ToStdString(), std::string(kTestString));
+ ++it;
+ ASSERT_EQ(it->type(), ProtoWireType::kLengthDelimited);
+ ASSERT_EQ(it->size(), sizeof(kTestString2) - 1);
+ ASSERT_EQ(it->as_std_string(), std::string(kTestString2));
+ ASSERT_EQ((*it).ToStdString(), std::string(kTestString2));
+}
+
TEST(ProtoDecoderTest, SingleRepeatedFieldWithExpansion) {
Message message;
ScatteredHeapBuffer delegate(512, 512);
diff --git a/src/protozero/proto_utils_unittest.cc b/src/protozero/proto_utils_unittest.cc
index 9d56d07..a724189 100644
--- a/src/protozero/proto_utils_unittest.cc
+++ b/src/protozero/proto_utils_unittest.cc
@@ -103,6 +103,14 @@
ZigZagEncode(std::numeric_limits<int32_t>::min()));
EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
ZigZagEncode(std::numeric_limits<int64_t>::min()));
+
+ EXPECT_EQ(0, ZigZagDecode(ZigZagEncode(0)));
+ EXPECT_EQ(-1, ZigZagDecode(ZigZagEncode(-1)));
+ EXPECT_EQ(1, ZigZagDecode(ZigZagEncode(1)));
+ EXPECT_EQ(-127, ZigZagDecode(ZigZagEncode(-127)));
+ EXPECT_EQ(0x7fffffff, ZigZagDecode(ZigZagEncode(0x7fffffff)));
+ EXPECT_EQ(9000000000, ZigZagDecode(ZigZagEncode(9000000000)));
+ EXPECT_EQ(-9000000000, ZigZagDecode(ZigZagEncode(-9000000000)));
}
TEST(ProtoUtilsTest, VarIntEncoding) {
diff --git a/src/protozero/protoc_plugin/cppgen_plugin.cc b/src/protozero/protoc_plugin/cppgen_plugin.cc
index b396a67..bbd2b23 100644
--- a/src/protozero/protoc_plugin/cppgen_plugin.cc
+++ b/src/protozero/protoc_plugin/cppgen_plugin.cc
@@ -121,7 +121,7 @@
h_printer.Print("#include <vector>\n");
h_printer.Print("#include <string>\n");
h_printer.Print("#include <type_traits>\n\n");
- h_printer.Print("#include \"perfetto/base/copyable_ptr.h\"\n");
+ h_printer.Print("#include \"perfetto/protozero/copyable_ptr.h\"\n");
h_printer.Print("#include \"perfetto/base/export.h\"\n\n");
cc_printer.Print(kHeader);
@@ -314,10 +314,25 @@
void CppObjGenerator::GenEnum(const EnumDescriptor* enum_desc,
Printer* p) const {
std::string full_name = GetFullName(enum_desc);
+
+ // When generating enums, there are two cases:
+ // 1. Enums nested in a message (most frequent case), e.g.:
+ // message MyMsg { enum MyEnum { FOO=1; BAR=2; } }
+ // 2. Enum defined at the package level, outside of any message.
+ //
+ // In the case 1, the C++ code generated by the official protobuf library is:
+ // enum MyEnum { MyMsg_MyEnum_FOO=1, MyMsg_MyEnum_BAR=2 }
+ // class MyMsg { static const auto FOO = MyMsg_MyEnum_FOO; ... same for BAR }
+ //
+ // In the case 2, the C++ code is simply:
+ // enum MyEnum { FOO=1, BAR=2 }
+ // Hence this |prefix| logic.
+ std::string prefix = enum_desc->containing_type() ? full_name + "_" : "";
+
p->Print("enum $f$ : int {\n", "f", full_name);
for (int e = 0; e < enum_desc->value_count(); e++) {
const EnumValueDescriptor* value = enum_desc->value(e);
- p->Print(" $f$_$n$ = $v$,\n", "f", full_name, "n", value->name(), "v",
+ p->Print(" $p$$n$ = $v$,\n", "p", prefix, "n", value->name(), "v",
std::to_string(value->number()));
}
p->Print("};\n");
@@ -426,7 +441,7 @@
} else if (!field->is_repeated()) {
std::string type = GetCppType(field, false);
if (field->type() == TYPE_MESSAGE) {
- type = "::perfetto::base::CopyablePtr<" + type + ">";
+ type = "::protozero::CopyablePtr<" + type + ">";
p->Print("$t$ $n$_;\n", "t", type, "n", field->lowercase_name());
} else {
p->Print("$t$ $n$_{};\n", "t", type, "n", field->lowercase_name());
diff --git a/src/protozero/protoc_plugin/protozero_plugin.cc b/src/protozero/protoc_plugin/protozero_plugin.cc
index 72d380c..dd49d45 100644
--- a/src/protozero/protoc_plugin/protozero_plugin.cc
+++ b/src/protozero/protoc_plugin/protozero_plugin.cc
@@ -23,6 +23,7 @@
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/plugin.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
@@ -429,7 +430,7 @@
void GeneratePackedRepeatedFieldDescriptor(const FieldDescriptor* field) {
std::map<std::string, std::string> setter;
setter["id"] = std::to_string(field->number());
- setter["name"] = field->name();
+ setter["name"] = field->lowercase_name();
setter["action"] = "set";
setter["buffer_type"] = FieldTypeToPackedBufferType(field->type());
stub_h_->Print(
@@ -442,11 +443,15 @@
void GenerateSimpleFieldDescriptor(const FieldDescriptor* field) {
std::map<std::string, std::string> setter;
setter["id"] = std::to_string(field->number());
- setter["name"] = field->name();
+ setter["name"] = field->lowercase_name();
setter["action"] = field->is_repeated() ? "add" : "set";
std::string appender;
std::string cpp_type;
+ const char* code_stub =
+ "void $action$_$name$($cpp_type$ value) {\n"
+ " $appender$($id$, value);\n"
+ "}\n";
switch (field->type()) {
case FieldDescriptor::TYPE_BOOL: {
@@ -519,18 +524,21 @@
cpp_type = GetCppClassName(field->enum_type(), true);
break;
}
- case FieldDescriptor::TYPE_STRING: {
- appender = "AppendString";
- cpp_type = "const char*";
- break;
- }
+ case FieldDescriptor::TYPE_STRING:
case FieldDescriptor::TYPE_BYTES: {
- stub_h_->Print(
- setter,
- "void $action$_$name$(const uint8_t* data, size_t size) {\n"
+ if (field->type() == FieldDescriptor::TYPE_STRING) {
+ cpp_type = "const char*";
+ } else {
+ cpp_type = "const uint8_t*";
+ }
+ code_stub =
+ "void $action$_$name$(const std::string& value) {\n"
+ " AppendBytes($id$, value.data(), value.size());\n"
+ "}\n"
+ "void $action$_$name$($cpp_type$ data, size_t size) {\n"
" AppendBytes($id$, data, size);\n"
- "}\n");
- return;
+ "}\n";
+ break;
}
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE: {
@@ -540,20 +548,7 @@
}
setter["appender"] = appender;
setter["cpp_type"] = cpp_type;
- stub_h_->Print(setter,
- "void $action$_$name$($cpp_type$ value) {\n"
- " $appender$($id$, value);\n"
- "}\n");
-
- // For strings also generate a variant for non-null terminated strings.
- if (field->type() == FieldDescriptor::TYPE_STRING) {
- stub_h_->Print(setter,
- "// Doesn't check for null terminator.\n"
- "// Expects |value| to be at least |size| long.\n"
- "void $action$_$name$($cpp_type$ value, size_t size) {\n"
- " AppendBytes($id$, value, size);\n"
- "}\n");
- }
+ stub_h_->Print(setter, code_stub);
}
void GenerateNestedMessageFieldDescriptor(const FieldDescriptor* field) {
@@ -563,8 +558,17 @@
"template <typename T = $inner_class$> T* $action$_$name$() {\n"
" return BeginNestedMessage<T>($id$);\n"
"}\n\n",
- "id", std::to_string(field->number()), "name", field->name(), "action",
- action, "inner_class", inner_class);
+ "id", std::to_string(field->number()), "name", field->lowercase_name(),
+ "action", action, "inner_class", inner_class);
+ if (field->options().lazy()) {
+ stub_h_->Print(
+ "void $action$_$name$_raw(const std::string& raw) {\n"
+ " return AppendBytes($id$, raw.data(), raw.size());\n"
+ "}\n\n",
+ "id", std::to_string(field->number()), "name",
+ field->lowercase_name(), "action", action, "inner_class",
+ inner_class);
+ }
}
void GenerateDecoder(const Descriptor* message) {
@@ -664,7 +668,7 @@
}
stub_h_->Print("bool has_$name$() const { return at<$id$>().valid(); }\n",
- "name", field->name(), "id",
+ "name", field->lowercase_name(), "id",
std::to_string(field->number()));
if (field->is_packed()) {
@@ -676,19 +680,20 @@
"GetPackedRepeated<$wire_type$, $cpp_type$>($id$, "
"parse_error_ptr); }\n",
"wire_type", protozero_wire_type, "cpp_type", cpp_type, "name",
- field->name(), "id", std::to_string(field->number()));
+ field->lowercase_name(), "id", std::to_string(field->number()));
} else if (field->is_repeated()) {
stub_h_->Print(
"::protozero::RepeatedFieldIterator<$cpp_type$> $name$() const { "
"return "
"GetRepeated<$cpp_type$>($id$); }\n",
- "name", field->name(), "cpp_type", cpp_type, "id",
+ "name", field->lowercase_name(), "cpp_type", cpp_type, "id",
std::to_string(field->number()));
} else {
stub_h_->Print(
"$cpp_type$ $name$() const { return at<$id$>().$getter$(); }\n",
- "name", field->name(), "id", std::to_string(field->number()),
- "cpp_type", cpp_type, "getter", getter);
+ "name", field->lowercase_name(), "id",
+ std::to_string(field->number()), "cpp_type", cpp_type, "getter",
+ getter);
}
}
stub_h_->Outdent();
diff --git a/src/protozero/test/example_proto/library.proto b/src/protozero/test/example_proto/library.proto
index 4ff8fee..059080f 100644
--- a/src/protozero/test/example_proto/library.proto
+++ b/src/protozero/test/example_proto/library.proto
@@ -17,7 +17,7 @@
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
-package foo.bar;
+package protozero.test.protos;
import public "src/protozero/test/example_proto/library_internals/galaxies.proto";
diff --git a/src/protozero/test/example_proto/library_internals/galaxies.proto b/src/protozero/test/example_proto/library_internals/galaxies.proto
index 0b1c1c5..d2a1e42 100644
--- a/src/protozero/test/example_proto/library_internals/galaxies.proto
+++ b/src/protozero/test/example_proto/library_internals/galaxies.proto
@@ -17,7 +17,7 @@
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
-package foo.bar;
+package protozero.test.protos;
import public "src/protozero/test/example_proto/upper_import.proto";
diff --git a/src/protozero/test/example_proto/test_messages.proto b/src/protozero/test/example_proto/test_messages.proto
index d28b1e8..db8212c 100644
--- a/src/protozero/test/example_proto/test_messages.proto
+++ b/src/protozero/test/example_proto/test_messages.proto
@@ -17,7 +17,7 @@
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
-package foo.bar;
+package protozero.test.protos;
import "src/protozero/test/example_proto/library.proto";
diff --git a/src/protozero/test/example_proto/upper_import.proto b/src/protozero/test/example_proto/upper_import.proto
index 4aacd41..486eff9 100644
--- a/src/protozero/test/example_proto/upper_import.proto
+++ b/src/protozero/test/example_proto/upper_import.proto
@@ -17,6 +17,6 @@
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
-package foo.bar;
+package protozero.test.protos;
message TrickyPublicImport {}
diff --git a/src/protozero/test/protozero_conformance_unittest.cc b/src/protozero/test/protozero_conformance_unittest.cc
index a374c51..85eaf43 100644
--- a/src/protozero/test/protozero_conformance_unittest.cc
+++ b/src/protozero/test/protozero_conformance_unittest.cc
@@ -28,8 +28,11 @@
#include "src/protozero/test/example_proto/test_messages.pb.h"
#include "src/protozero/test/example_proto/test_messages.pbzero.h"
-namespace pbtest = foo::bar::pbzero; // Generated by the protozero plugin.
-namespace pbgold = foo::bar; // Generated by the official protobuf compiler.
+// Generated by the protozero plugin.
+namespace pbtest = protozero::test::protos::pbzero;
+
+// Generated by the official protobuf compiler.
+namespace pbgold = protozero::test::protos;
namespace protozero {
namespace {
diff --git a/src/trace_processor/android_logs_table.cc b/src/trace_processor/android_logs_table.cc
index b104280..017a89a 100644
--- a/src/trace_processor/android_logs_table.cc
+++ b/src/trace_processor/android_logs_table.cc
@@ -47,16 +47,15 @@
int AndroidLogsTable::BestIndex(const QueryConstraints& qc,
BestIndexInfo* info) {
info->estimated_cost = static_cast<uint32_t>(storage_->android_logs().size());
-
- info->order_by_consumed = true;
+ info->sqlite_omit_order_by = true;
// Only the string columns are handled by SQLite.
size_t tag_index = schema().ColumnIndexFromName("tag");
size_t msg_index = schema().ColumnIndexFromName("msg");
for (size_t i = 0; i < qc.constraints().size(); i++) {
- info->omit[i] =
- qc.constraints()[i].iColumn != static_cast<int>(tag_index) &&
- qc.constraints()[i].iColumn != static_cast<int>(msg_index);
+ info->sqlite_omit_constraint[i] =
+ qc.constraints()[i].column != static_cast<int>(tag_index) &&
+ qc.constraints()[i].column != static_cast<int>(msg_index);
}
return SQLITE_OK;
diff --git a/src/trace_processor/counter_values_table.cc b/src/trace_processor/counter_values_table.cc
index fc536b4..f77d91a 100644
--- a/src/trace_processor/counter_values_table.cc
+++ b/src/trace_processor/counter_values_table.cc
@@ -24,14 +24,14 @@
void CounterValuesTable::RegisterTable(sqlite3* db,
const TraceStorage* storage) {
- SqliteTable::Register<CounterValuesTable>(db, storage, "counter_values");
+ SqliteTable::Register<CounterValuesTable>(db, storage, "counter");
}
StorageSchema CounterValuesTable::CreateStorageSchema() {
const auto& cs = storage_->counter_values();
return StorageSchema::Builder()
.AddGenericNumericColumn("id", RowIdAccessor(TableId::kCounterValues))
- .AddNumericColumn("counter_id", &cs.track_ids(), &cs.rows_for_track_id())
+ .AddNumericColumn("track_id", &cs.track_ids(), &cs.rows_for_track_id())
.AddOrderedNumericColumn("ts", &cs.timestamps())
.AddNumericColumn("value", &cs.values())
.AddNumericColumn("arg_set_id", &cs.arg_set_ids())
@@ -45,17 +45,15 @@
int CounterValuesTable::BestIndex(const QueryConstraints& qc,
BestIndexInfo* info) {
info->estimated_cost = EstimateCost(qc);
-
- info->order_by_consumed = true;
- for (size_t i = 0; i < qc.constraints().size(); i++) {
- info->omit[i] = true;
- }
+ info->sqlite_omit_order_by = true;
+ auto& omit_cs = info->sqlite_omit_constraint;
+ std::fill(omit_cs.begin(), omit_cs.end(), true);
return SQLITE_OK;
}
uint32_t CounterValuesTable::EstimateCost(const QueryConstraints& qc) {
- if (HasEqConstraint(qc, "counter_id"))
+ if (HasEqConstraint(qc, "track_id"))
return RowCount() / 100;
return RowCount();
}
diff --git a/src/trace_processor/cpu_profile_stack_sample_table.cc b/src/trace_processor/cpu_profile_stack_sample_table.cc
index bb51404..1226020 100644
--- a/src/trace_processor/cpu_profile_stack_sample_table.cc
+++ b/src/trace_processor/cpu_profile_stack_sample_table.cc
@@ -46,7 +46,7 @@
int CpuProfileStackSampleTable::BestIndex(const QueryConstraints& qc,
BestIndexInfo* info) {
- info->order_by_consumed = true;
+ info->sqlite_omit_order_by = true;
info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
return SQLITE_OK;
}
diff --git a/src/trace_processor/db/column.cc b/src/trace_processor/db/column.cc
index 0fbe66e..648e490 100644
--- a/src/trace_processor/db/column.cc
+++ b/src/trace_processor/db/column.cc
@@ -50,9 +50,8 @@
string_pool_(table->string_pool_) {}
Column Column::IdColumn(Table* table, uint32_t col_idx, uint32_t row_map_idx) {
- return Column("id", ColumnType::kId,
- Flag::kId | Flag::kSorted | Flag::kNonNull, table, col_idx,
- row_map_idx, nullptr);
+ return Column("id", ColumnType::kId, Flag::kSorted | Flag::kNonNull, table,
+ col_idx, row_map_idx, nullptr);
}
const RowMap& Column::row_map() const {
diff --git a/src/trace_processor/db/column.h b/src/trace_processor/db/column.h
index fdcce59..d1361f2 100644
--- a/src/trace_processor/db/column.h
+++ b/src/trace_processor/db/column.h
@@ -71,17 +71,9 @@
// Indicates that this column has no special properties.
kNoFlag = 0,
- // Indiciates that the column is an "id" column. Specifically, this means
- // the backing data for this column has the property that data[i] = i;
- //
- // Note: generally, this flag should not be passed by users of this class.
- // Instead they should use the Column::IdColumn method to create an id
- // column.
- kId = 1 << 0,
-
// Indicates the data in the column is sorted. This can be used to speed
// up filtering and skip sorting.
- kSorted = 1 << 1,
+ kSorted = 1 << 0,
// Indicates the data in the column is non-null. That is, the SparseVector
// passed in will never have any null entries. This is only used for
@@ -90,7 +82,7 @@
//
// This is used to speed up filters as we can safely index SparseVector
// directly if this flag is set.
- kNonNull = 1 << 2
+ kNonNull = 1 << 1,
};
template <typename T>
@@ -154,7 +146,7 @@
// given filter constraint.
void FilterInto(FilterOp op, SqlValue value, RowMap* rm) const {
// TODO(lalitm): add special logic here to deal with kId and kSorted flags.
- if (type_ == ColumnType::kId && op == FilterOp::kEq) {
+ if (IsId() && op == FilterOp::kEq) {
auto opt_idx = IndexOf(value);
if (opt_idx) {
rm->Intersect(RowMap::SingleRow(*opt_idx));
@@ -200,7 +192,7 @@
}
// Returns true if this column is considered an id column.
- bool IsId() const { return (flags_ & Flag::kId) != 0; }
+ bool IsId() const { return type_ == ColumnType::kId; }
// Returns true if this column is a nullable column.
bool IsNullable() const { return (flags_ & Flag::kNonNull) == 0; }
diff --git a/src/trace_processor/db/table.cc b/src/trace_processor/db/table.cc
index 289b357..289d540 100644
--- a/src/trace_processor/db/table.cc
+++ b/src/trace_processor/db/table.cc
@@ -130,7 +130,7 @@
for (const Column& col : columns_) {
// We skip id columns as they are misleading on join tables.
- if ((col.flags_ & Column::kId) != 0)
+ if (col.IsId())
continue;
table.columns_.emplace_back(col, &table, table.columns_.size(),
col.row_map_idx_);
@@ -160,7 +160,7 @@
uint32_t left_row_maps_size = static_cast<uint32_t>(row_maps_.size());
for (const Column& col : other.columns_) {
// We skip id columns as they are misleading on join tables.
- if ((col.flags_ & Column::kId) != 0)
+ if (col.IsId())
continue;
// Ensure that we offset the RowMap index by the number of RowMaps in the
diff --git a/src/trace_processor/export_json.cc b/src/trace_processor/export_json.cc
index 15ad611..5d2d0a0 100644
--- a/src/trace_processor/export_json.cc
+++ b/src/trace_processor/export_json.cc
@@ -799,12 +799,22 @@
static_cast<int32_t>(storage->GetProcess(*thread.upid).pid);
}
- // Use "I" instead of "i" phase for backwards-compat with old consumers.
- event["ph"] = "I";
+ event["ph"] = "n";
event["cat"] = "disabled_by_default-cpu_profiler";
event["name"] = "StackCpuSampling";
event["s"] = "t";
+ // Add a dummy thread timestamp to this event to match the format of instant
+ // events. Useful in the UI to view args of a selected group of samples.
+ event["tts"] = Json::Int64(1);
+
+ // "n"-phase events are nestable async events which get tied together with
+ // their id, so we need to give each one a unique ID as we only
+ // want the samples to show up on their own track in the trace-viewer but
+ // not nested together.
+ static size_t g_id_counter = 0;
+ event["id"] = PrintUint64(++g_id_counter);
+
std::vector<std::string> callstack;
const auto& callsites = storage->stack_profile_callsite_table();
int64_t maybe_callsite_id = samples.callsite_ids()[i];
@@ -853,6 +863,12 @@
}
event["args"]["frames"] = merged_callstack;
+
+ // TODO(oysteine): Used for backwards compatibility with the memlog
+ // pipeline, should remove once we've switched to looking directly at the
+ // tid.
+ event["args"]["thread_id"] = thread.tid;
+
writer->WriteCommonEvent(event);
}
diff --git a/src/trace_processor/export_json_unittest.cc b/src/trace_processor/export_json_unittest.cc
index c5c949a..6b7ad59 100644
--- a/src/trace_processor/export_json_unittest.cc
+++ b/src/trace_processor/export_json_unittest.cc
@@ -1189,7 +1189,8 @@
EXPECT_EQ(result["traceEvents"].size(), 1u);
Json::Value event = result["traceEvents"][0];
- EXPECT_EQ(event["ph"].asString(), "I");
+ EXPECT_EQ(event["ph"].asString(), "n");
+ EXPECT_EQ(event["id"].asString(), "0x1");
EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
EXPECT_EQ(event["tid"].asUInt(), kThreadID);
EXPECT_EQ(event["cat"].asString(), "disabled_by_default-cpu_profiler");
diff --git a/src/trace_processor/heap_profile_allocation_table.cc b/src/trace_processor/heap_profile_allocation_table.cc
index 8bd050e..dcdb825 100644
--- a/src/trace_processor/heap_profile_allocation_table.cc
+++ b/src/trace_processor/heap_profile_allocation_table.cc
@@ -48,7 +48,7 @@
int HeapProfileAllocationTable::BestIndex(const QueryConstraints& qc,
BestIndexInfo* info) {
- info->order_by_consumed = true;
+ info->sqlite_omit_order_by = true;
info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
return SQLITE_OK;
}
diff --git a/src/trace_processor/importers/ftrace/ftrace_module.h b/src/trace_processor/importers/ftrace/ftrace_module.h
index 9d8d489..fd1ace0 100644
--- a/src/trace_processor/importers/ftrace/ftrace_module.h
+++ b/src/trace_processor/importers/ftrace/ftrace_module.h
@@ -65,14 +65,7 @@
ModuleResult ParseFtracePacket(uint32_t cpu,
const TimestampedTracePiece& ttp) {
- // Handle the (optional) alternative encoding format for sched_switch.
- if (ttp.inline_event.type == InlineEvent::Type::kSchedSwitch) {
- parser_.ParseInlineSchedSwitch(cpu, ttp.timestamp,
- ttp.inline_event.sched_switch);
- return ModuleResult::Handled();
- }
-
- return parser_.ParseFtraceEvent(cpu, ttp.timestamp, ttp.blob_view);
+ return parser_.ParseFtraceEvent(cpu, ttp);
}
private:
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index f325192..3ee0cf2 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -184,12 +184,32 @@
PERFETTO_ALWAYS_INLINE
util::Status FtraceParser::ParseFtraceEvent(uint32_t cpu,
- int64_t ts,
- const TraceBlobView& event) {
+ const TimestampedTracePiece& ttp) {
+ using protos::pbzero::FtraceEvent;
+ int64_t ts = ttp.timestamp;
+
+ // Handle the (optional) alternative encoding format for sched_switch.
+ if (ttp.inline_event.type == InlineEvent::Type::kSchedSwitch) {
+ const auto& event = ttp.inline_event.sched_switch;
+ context_->sched_tracker->PushSchedSwitchCompact(
+ cpu, ts, event.prev_state, static_cast<uint32_t>(event.next_pid),
+ event.next_prio, event.next_comm);
+ return util::OkStatus();
+ }
+
+ // Handle the (optional) alternative encoding format for sched_waking.
+ if (ttp.inline_event.type == InlineEvent::Type::kSchedWaking) {
+ const auto& event = ttp.inline_event.sched_waking;
+ context_->sched_tracker->PushSchedWakingCompact(
+ cpu, ts, static_cast<uint32_t>(event.pid), event.target_cpu, event.prio,
+ event.comm);
+ return util::OkStatus();
+ }
+
+ const TraceBlobView& event = ttp.blob_view;
ProtoDecoder decoder(event.data(), event.length());
uint64_t raw_pid = 0;
- if (auto pid_field =
- decoder.FindField(protos::pbzero::FtraceEvent::kPidFieldNumber)) {
+ if (auto pid_field = decoder.FindField(FtraceEvent::kPidFieldNumber)) {
raw_pid = pid_field.as_uint64();
} else {
return util::ErrStatus("Pid field not found in ftrace packet");
@@ -197,126 +217,125 @@
uint32_t pid = static_cast<uint32_t>(raw_pid);
for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
- bool is_metadata_field =
- fld.id() == protos::pbzero::FtraceEvent::kPidFieldNumber ||
- fld.id() == protos::pbzero::FtraceEvent::kTimestampFieldNumber;
+ bool is_metadata_field = fld.id() == FtraceEvent::kPidFieldNumber ||
+ fld.id() == FtraceEvent::kTimestampFieldNumber;
if (is_metadata_field)
continue;
ConstBytes data = fld.as_bytes();
- if (fld.id() == protos::pbzero::FtraceEvent::kGenericFieldNumber) {
+ if (fld.id() == FtraceEvent::kGenericFieldNumber) {
ParseGenericFtrace(ts, cpu, pid, data);
- } else if (fld.id() !=
- protos::pbzero::FtraceEvent::kSchedSwitchFieldNumber) {
+ } else if (fld.id() != FtraceEvent::kSchedSwitchFieldNumber) {
+ // sched_switch parsing populates the raw table by itself
ParseTypedFtraceToRaw(fld.id(), ts, cpu, pid, data);
}
switch (fld.id()) {
- case protos::pbzero::FtraceEvent::kSchedSwitchFieldNumber: {
+ case FtraceEvent::kSchedSwitchFieldNumber: {
ParseSchedSwitch(cpu, ts, data);
break;
}
- case protos::pbzero::FtraceEvent::kSchedWakeupFieldNumber: {
+ case FtraceEvent::kSchedWakeupFieldNumber: {
ParseSchedWakeup(ts, data);
break;
}
- case protos::pbzero::FtraceEvent::kSchedWakingFieldNumber: {
+ case FtraceEvent::kSchedWakingFieldNumber: {
ParseSchedWaking(ts, data);
break;
}
- case protos::pbzero::FtraceEvent::kSchedProcessFreeFieldNumber: {
+ case FtraceEvent::kSchedProcessFreeFieldNumber: {
ParseSchedProcessFree(ts, data);
break;
}
- case protos::pbzero::FtraceEvent::kCpuFrequencyFieldNumber: {
+ case FtraceEvent::kCpuFrequencyFieldNumber: {
ParseCpuFreq(ts, data);
break;
}
- case protos::pbzero::FtraceEvent::kGpuFrequencyFieldNumber: {
+ case FtraceEvent::kGpuFrequencyFieldNumber: {
ParseGpuFreq(ts, data);
break;
}
- case protos::pbzero::FtraceEvent::kCpuIdleFieldNumber: {
+ case FtraceEvent::kCpuIdleFieldNumber: {
ParseCpuIdle(ts, data);
break;
}
- case protos::pbzero::FtraceEvent::kPrintFieldNumber: {
+ case FtraceEvent::kPrintFieldNumber: {
ParsePrint(cpu, ts, pid, data);
break;
}
- case protos::pbzero::FtraceEvent::kZeroFieldNumber: {
+ case FtraceEvent::kZeroFieldNumber: {
ParseZero(cpu, ts, pid, data);
break;
}
- case protos::pbzero::FtraceEvent::kRssStatFieldNumber: {
+ case FtraceEvent::kRssStatFieldNumber: {
ParseRssStat(ts, pid, data);
break;
}
- case protos::pbzero::FtraceEvent::kIonHeapGrowFieldNumber: {
+ case FtraceEvent::kIonHeapGrowFieldNumber: {
ParseIonHeapGrowOrShrink(ts, pid, data, true);
break;
}
- case protos::pbzero::FtraceEvent::kIonHeapShrinkFieldNumber: {
+ case FtraceEvent::kIonHeapShrinkFieldNumber: {
ParseIonHeapGrowOrShrink(ts, pid, data, false);
break;
}
- case protos::pbzero::FtraceEvent::kSignalGenerateFieldNumber: {
+ case FtraceEvent::kSignalGenerateFieldNumber: {
ParseSignalGenerate(ts, data);
break;
}
- case protos::pbzero::FtraceEvent::kSignalDeliverFieldNumber: {
+ case FtraceEvent::kSignalDeliverFieldNumber: {
ParseSignalDeliver(ts, pid, data);
break;
}
- case protos::pbzero::FtraceEvent::kLowmemoryKillFieldNumber: {
+ case FtraceEvent::kLowmemoryKillFieldNumber: {
ParseLowmemoryKill(ts, data);
break;
}
- case protos::pbzero::FtraceEvent::kOomScoreAdjUpdateFieldNumber: {
+ case FtraceEvent::kOomScoreAdjUpdateFieldNumber: {
ParseOOMScoreAdjUpdate(ts, data);
break;
}
- case protos::pbzero::FtraceEvent::kMmEventRecordFieldNumber: {
+ case FtraceEvent::kMmEventRecordFieldNumber: {
ParseMmEventRecord(ts, pid, data);
break;
}
- case protos::pbzero::FtraceEvent::kSysEnterFieldNumber: {
+ case FtraceEvent::kSysEnterFieldNumber: {
ParseSysEvent(ts, pid, true, data);
break;
}
- case protos::pbzero::FtraceEvent::kSysExitFieldNumber: {
+ case FtraceEvent::kSysExitFieldNumber: {
ParseSysEvent(ts, pid, false, data);
break;
}
- case protos::pbzero::FtraceEvent::kTaskNewtaskFieldNumber: {
+ case FtraceEvent::kTaskNewtaskFieldNumber: {
ParseTaskNewTask(ts, pid, data);
break;
}
- case protos::pbzero::FtraceEvent::kTaskRenameFieldNumber: {
+ case FtraceEvent::kTaskRenameFieldNumber: {
ParseTaskRename(data);
break;
}
- case protos::pbzero::FtraceEvent::kBinderTransactionFieldNumber: {
+ case FtraceEvent::kBinderTransactionFieldNumber: {
ParseBinderTransaction(ts, pid, data);
break;
}
- case protos::pbzero::FtraceEvent::kBinderTransactionReceivedFieldNumber: {
+ case FtraceEvent::kBinderTransactionReceivedFieldNumber: {
ParseBinderTransactionReceived(ts, pid, data);
break;
}
- case protos::pbzero::FtraceEvent::kBinderTransactionAllocBufFieldNumber: {
+ case FtraceEvent::kBinderTransactionAllocBufFieldNumber: {
ParseBinderTransactionAllocBuf(ts, pid, data);
break;
}
- case protos::pbzero::FtraceEvent::kBinderLockFieldNumber: {
+ case FtraceEvent::kBinderLockFieldNumber: {
ParseBinderLock(ts, pid, data);
break;
}
- case protos::pbzero::FtraceEvent::kBinderUnlockFieldNumber: {
+ case FtraceEvent::kBinderUnlockFieldNumber: {
ParseBinderUnlock(ts, pid, data);
break;
}
- case protos::pbzero::FtraceEvent::kBinderLockedFieldNumber: {
+ case FtraceEvent::kBinderLockedFieldNumber: {
ParseBinderLocked(ts, pid, data);
break;
}
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.h b/src/trace_processor/importers/ftrace/ftrace_parser.h
index 0117d7c..3d7138b 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.h
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.h
@@ -34,17 +34,7 @@
void ParseFtraceStats(protozero::ConstBytes);
- void ParseInlineSchedSwitch(uint32_t cpu,
- int64_t ts,
- const InlineSchedSwitch& event) {
- context_->sched_tracker->PushSchedSwitchCompact(
- cpu, ts, event.prev_state, static_cast<uint32_t>(event.next_pid),
- event.next_prio, event.next_comm);
- }
-
- util::Status ParseFtraceEvent(uint32_t cpu,
- int64_t ts,
- const TraceBlobView& packet);
+ util::Status ParseFtraceEvent(uint32_t cpu, const TimestampedTracePiece& ttp);
private:
void ParseGenericFtrace(int64_t timestamp,
diff --git a/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc b/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc
index 8a183a7..4319e2d 100644
--- a/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc
@@ -65,19 +65,66 @@
}
PERFETTO_ALWAYS_INLINE
+void FtraceTokenizer::TokenizeFtraceEvent(uint32_t cpu, TraceBlobView event) {
+ constexpr auto kTimestampFieldNumber =
+ protos::pbzero::FtraceEvent::kTimestampFieldNumber;
+ const uint8_t* data = event.data();
+ const size_t length = event.length();
+ ProtoDecoder decoder(data, length);
+ uint64_t raw_timestamp = 0;
+ bool timestamp_found = false;
+
+ // Speculate on the fact that the timestamp is often the 1st field of the
+ // event.
+ constexpr auto timestampFieldTag = MakeTagVarInt(kTimestampFieldNumber);
+ if (PERFETTO_LIKELY(length > 10 && data[0] == timestampFieldTag)) {
+ // Fastpath.
+ const uint8_t* next = ParseVarInt(data + 1, data + 11, &raw_timestamp);
+ timestamp_found = next != data + 1;
+ decoder.Reset(next);
+ } else {
+ // Slowpath.
+ if (auto ts_field = decoder.FindField(kTimestampFieldNumber)) {
+ timestamp_found = true;
+ raw_timestamp = ts_field.as_uint64();
+ }
+ }
+
+ if (PERFETTO_UNLIKELY(!timestamp_found)) {
+ PERFETTO_ELOG("Timestamp field not found in FtraceEvent");
+ context_->storage->IncrementStats(stats::ftrace_bundle_tokenizer_errors);
+ return;
+ }
+
+ int64_t timestamp = static_cast<int64_t>(raw_timestamp);
+
+ // We don't need to parse this packet, just push it to be sorted with
+ // the timestamp.
+ context_->sorter->PushFtraceEvent(cpu, timestamp, std::move(event));
+}
+
+PERFETTO_ALWAYS_INLINE
void FtraceTokenizer::TokenizeFtraceCompactSched(uint32_t cpu,
const uint8_t* data,
size_t size) {
- protos::pbzero::FtraceEventBundle_CompactSched::Decoder compact(data, size);
-
- // Build the interning table for next_comm fields.
+ protos::pbzero::FtraceEventBundle::CompactSched::Decoder compact_sched(data,
+ size);
+ // Build the interning table for comm fields.
std::vector<StringId> string_table;
string_table.reserve(512);
- for (auto it = compact.switch_next_comm_table(); it; it++) {
+ for (auto it = compact_sched.intern_table(); it; it++) {
StringId value = context_->storage->InternString(*it);
string_table.push_back(value);
}
+ TokenizeFtraceCompactSchedSwitch(cpu, compact_sched, string_table);
+ TokenizeFtraceCompactSchedWaking(cpu, compact_sched, string_table);
+}
+
+void FtraceTokenizer::TokenizeFtraceCompactSchedSwitch(
+ uint32_t cpu,
+ const protos::pbzero::FtraceEventBundle::CompactSched::Decoder& compact,
+ const std::vector<StringId>& string_table) {
// Accumulator for timestamp deltas.
int64_t timestamp_acc = 0;
@@ -117,43 +164,48 @@
context_->storage->IncrementStats(stats::compact_sched_has_parse_errors);
}
-PERFETTO_ALWAYS_INLINE
-void FtraceTokenizer::TokenizeFtraceEvent(uint32_t cpu, TraceBlobView event) {
- constexpr auto kTimestampFieldNumber =
- protos::pbzero::FtraceEvent::kTimestampFieldNumber;
- const uint8_t* data = event.data();
- const size_t length = event.length();
- ProtoDecoder decoder(data, length);
- uint64_t raw_timestamp = 0;
- bool timestamp_found = false;
+void FtraceTokenizer::TokenizeFtraceCompactSchedWaking(
+ uint32_t cpu,
+ const protos::pbzero::FtraceEventBundle::CompactSched::Decoder& compact,
+ const std::vector<StringId>& string_table) {
+ // Accumulator for timestamp deltas.
+ int64_t timestamp_acc = 0;
- // Speculate on the fact that the timestamp is often the 1st field of the
- // event.
- constexpr auto timestampFieldTag = MakeTagVarInt(kTimestampFieldNumber);
- if (PERFETTO_LIKELY(length > 10 && data[0] == timestampFieldTag)) {
- // Fastpath.
- const uint8_t* next = ParseVarInt(data + 1, data + 11, &raw_timestamp);
- timestamp_found = next != data + 1;
- decoder.Reset(next);
- } else {
- // Slowpath.
- if (auto ts_field = decoder.FindField(kTimestampFieldNumber)) {
- timestamp_found = true;
- raw_timestamp = ts_field.as_uint64();
- }
+ // The events' fields are stored in a structure-of-arrays style, using packed
+ // repeated fields. Walk each repeated field in step to recover individual
+ // events.
+ bool parse_error = false;
+ auto timestamp_it = compact.waking_timestamp(&parse_error);
+ auto pid_it = compact.waking_pid(&parse_error);
+ auto tcpu_it = compact.waking_target_cpu(&parse_error);
+ auto prio_it = compact.waking_prio(&parse_error);
+ auto comm_it = compact.waking_comm_index(&parse_error);
+
+ for (; timestamp_it && pid_it && tcpu_it && prio_it && comm_it;
+ ++timestamp_it, ++pid_it, ++tcpu_it, ++prio_it, ++comm_it) {
+ InlineSchedWaking event{};
+
+ // delta-encoded timestamp
+ timestamp_acc += static_cast<int64_t>(*timestamp_it);
+ int64_t event_timestamp = timestamp_acc;
+
+ // index into the interned string table
+ PERFETTO_DCHECK(*comm_it < string_table.size());
+ event.comm = string_table[*comm_it];
+
+ event.pid = *pid_it;
+ event.target_cpu = *tcpu_it;
+ event.prio = *prio_it;
+
+ context_->sorter->PushInlineFtraceEvent(cpu, event_timestamp,
+ InlineEvent::SchedWaking(event));
}
- if (PERFETTO_UNLIKELY(!timestamp_found)) {
- PERFETTO_ELOG("Timestamp field not found in FtraceEvent");
- context_->storage->IncrementStats(stats::ftrace_bundle_tokenizer_errors);
- return;
- }
-
- int64_t timestamp = static_cast<int64_t>(raw_timestamp);
-
- // We don't need to parse this packet, just push it to be sorted with
- // the timestamp.
- context_->sorter->PushFtraceEvent(cpu, timestamp, std::move(event));
+ // Check that all packed buffers were decoded correctly, and fully.
+ bool sizes_match =
+ !timestamp_it && !pid_it && !tcpu_it && !prio_it && !comm_it;
+ if (parse_error || !sizes_match)
+ context_->storage->IncrementStats(stats::compact_sched_has_parse_errors);
}
} // namespace trace_processor
diff --git a/src/trace_processor/importers/ftrace/ftrace_tokenizer.h b/src/trace_processor/importers/ftrace/ftrace_tokenizer.h
index 30b5a5f..8d1007f 100644
--- a/src/trace_processor/importers/ftrace/ftrace_tokenizer.h
+++ b/src/trace_processor/importers/ftrace/ftrace_tokenizer.h
@@ -17,8 +17,10 @@
#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_TOKENIZER_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_TOKENIZER_H_
+#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
#include "src/trace_processor/trace_blob_view.h"
#include "src/trace_processor/trace_processor_context.h"
+#include "src/trace_processor/trace_storage.h"
namespace perfetto {
namespace trace_processor {
@@ -28,13 +30,21 @@
explicit FtraceTokenizer(TraceProcessorContext* context)
: context_(context) {}
- void TokenizeFtraceBundle(TraceBlobView);
+ void TokenizeFtraceBundle(TraceBlobView bundle);
private:
- void TokenizeFtraceEvent(uint32_t cpu, TraceBlobView);
+ void TokenizeFtraceEvent(uint32_t cpu, TraceBlobView event);
void TokenizeFtraceCompactSched(uint32_t cpu,
const uint8_t* data,
size_t size);
+ void TokenizeFtraceCompactSchedSwitch(
+ uint32_t cpu,
+ const protos::pbzero::FtraceEventBundle::CompactSched::Decoder& compact,
+ const std::vector<StringId>& string_table);
+ void TokenizeFtraceCompactSchedWaking(
+ uint32_t cpu,
+ const protos::pbzero::FtraceEventBundle::CompactSched::Decoder& compact,
+ const std::vector<StringId>& string_table);
TraceProcessorContext* context_;
};
diff --git a/src/trace_processor/importers/ftrace/sched_event_tracker.cc b/src/trace_processor/importers/ftrace/sched_event_tracker.cc
index 4c38e99..a4027f6 100644
--- a/src/trace_processor/importers/ftrace/sched_event_tracker.cc
+++ b/src/trace_processor/importers/ftrace/sched_event_tracker.cc
@@ -36,15 +36,27 @@
SchedEventTracker::SchedEventTracker(TraceProcessorContext* context)
: context_(context) {
- auto* descriptor = GetMessageDescriptorForId(
+ // pre-parse sched_switch
+ auto* switch_descriptor = GetMessageDescriptorForId(
protos::pbzero::FtraceEvent::kSchedSwitchFieldNumber);
- PERFETTO_CHECK(descriptor->max_field_id == kSchedSwitchMaxFieldId);
+ PERFETTO_CHECK(switch_descriptor->max_field_id == kSchedSwitchMaxFieldId);
for (size_t i = 1; i <= kSchedSwitchMaxFieldId; i++) {
sched_switch_field_ids_[i] =
- context->storage->InternString(descriptor->fields[i].name);
+ context->storage->InternString(switch_descriptor->fields[i].name);
}
- sched_switch_id_ = context->storage->InternString(descriptor->name);
+ sched_switch_id_ = context->storage->InternString(switch_descriptor->name);
+
+ // pre-parse sched_waking
+ auto* waking_descriptor = GetMessageDescriptorForId(
+ protos::pbzero::FtraceEvent::kSchedWakingFieldNumber);
+ PERFETTO_CHECK(waking_descriptor->max_field_id == kSchedWakingMaxFieldId);
+
+ for (size_t i = 1; i <= kSchedWakingMaxFieldId; i++) {
+ sched_waking_field_ids_[i] =
+ context->storage->InternString(waking_descriptor->fields[i].name);
+ }
+ sched_waking_id_ = context->storage->InternString(waking_descriptor->name);
}
SchedEventTracker::~SchedEventTracker() = default;
@@ -130,6 +142,8 @@
// create slices as normal, but the first per-cpu switch is effectively
// discarded.
if (pending_sched->last_utid == std::numeric_limits<UniqueTid>::max()) {
+ context_->storage->IncrementStats(stats::compact_sched_switch_skipped);
+
pending_sched->last_pid = next_pid;
pending_sched->last_utid = next_utid;
pending_sched->last_prio = next_prio;
@@ -226,6 +240,62 @@
slices->set_end_state(pending_slice_idx, task_state);
}
+// Processes a sched_waking that was decoded from a compact representation,
+// adding to the raw and instants tables.
+void SchedEventTracker::PushSchedWakingCompact(uint32_t cpu,
+ int64_t ts,
+ uint32_t wakee_pid,
+ int32_t target_cpu,
+ int32_t prio,
+ StringId comm_id) {
+ // At this stage all events should be globally timestamp ordered.
+ if (ts < context_->event_tracker->max_timestamp()) {
+ PERFETTO_ELOG("sched_waking event out of order by %.4f ms, skipping",
+ (context_->event_tracker->max_timestamp() - ts) / 1e6);
+ context_->storage->IncrementStats(stats::sched_waking_out_of_order);
+ return;
+ }
+ context_->event_tracker->UpdateMaxTimestamp(ts);
+ PERFETTO_DCHECK(cpu < base::kMaxCpus);
+
+ // We infer the task that emitted the event (i.e. common_pid) from the
+ // scheduling slices. Drop the event if we haven't seen any sched_switch
+ // events for this cpu yet.
+ // Note that if sched_switch wasn't enabled, we will have to skip all
+ // compact waking events.
+ auto* pending_sched = &pending_sched_per_cpu_[cpu];
+ if (pending_sched->last_utid == std::numeric_limits<UniqueTid>::max()) {
+ context_->storage->IncrementStats(stats::compact_sched_waking_skipped);
+ return;
+ }
+ auto curr_utid = pending_sched->last_utid;
+
+ // Add an entry to the raw table.
+ auto rid = context_->storage->mutable_raw_events()->AddRawEvent(
+ ts, sched_waking_id_, cpu, curr_utid);
+
+ // "success" is hardcoded as always 1 by the kernel, with a TODO to remove it.
+ static constexpr int32_t kHardcodedSuccess = 1;
+
+ using SW = protos::pbzero::SchedWakingFtraceEvent;
+ auto add_raw_arg = [this](RowId row_id, int field_num, Variadic var) {
+ StringId key = sched_waking_field_ids_[static_cast<size_t>(field_num)];
+ context_->args_tracker->AddArg(row_id, key, key, var);
+ };
+ add_raw_arg(rid, SW::kCommFieldNumber, Variadic::String(comm_id));
+ add_raw_arg(rid, SW::kPidFieldNumber, Variadic::Integer(wakee_pid));
+ add_raw_arg(rid, SW::kPrioFieldNumber, Variadic::Integer(prio));
+ add_raw_arg(rid, SW::kSuccessFieldNumber,
+ Variadic::Integer(kHardcodedSuccess));
+ add_raw_arg(rid, SW::kTargetCpuFieldNumber, Variadic::Integer(target_cpu));
+
+ // Add a waking entry to the instants.
+ auto wakee_utid = context_->process_tracker->GetOrCreateThread(wakee_pid);
+ auto* instants = context_->storage->mutable_instants();
+ instants->AddInstantEvent(ts, sched_waking_id_, /*value=*/0, wakee_utid,
+ RefType::kRefUtid);
+}
+
void SchedEventTracker::FlushPendingEvents() {
// TODO(lalitm): the day this method is called before end of trace, don't
// flush the sched events as they will probably be pushed in the next round
diff --git a/src/trace_processor/importers/ftrace/sched_event_tracker.h b/src/trace_processor/importers/ftrace/sched_event_tracker.h
index 46acb8f..3c100b6 100644
--- a/src/trace_processor/importers/ftrace/sched_event_tracker.h
+++ b/src/trace_processor/importers/ftrace/sched_event_tracker.h
@@ -59,6 +59,16 @@
int32_t next_prio,
StringId next_comm_id);
+ // This method is called when parsing a sched_waking encoded in the compact
+ // format. Note that the default encoding is handled by
+ // |EventTracker::PushInstant|.
+ void PushSchedWakingCompact(uint32_t cpu,
+ int64_t ts,
+ uint32_t wakee_pid,
+ int32_t target_cpu,
+ int32_t prio,
+ StringId comm_id);
+
// Called at the end of trace to flush any events which are pending to the
// storage.
void FlushPendingEvents();
@@ -99,6 +109,10 @@
std::array<StringId, kSchedSwitchMaxFieldId + 1> sched_switch_field_ids_;
StringId sched_switch_id_;
+ static constexpr uint8_t kSchedWakingMaxFieldId = 5;
+ std::array<StringId, kSchedWakingMaxFieldId + 1> sched_waking_field_ids_;
+ StringId sched_waking_id_;
+
TraceProcessorContext* const context_;
};
diff --git a/src/trace_processor/importers/proto/heap_graph_walker.cc b/src/trace_processor/importers/proto/heap_graph_walker.cc
index 5805b77..8655d85 100644
--- a/src/trace_processor/importers/proto/heap_graph_walker.cc
+++ b/src/trace_processor/importers/proto/heap_graph_walker.cc
@@ -72,6 +72,7 @@
void HeapGraphWalker::MarkRoot(int64_t row) {
Node& n = GetNode(row);
+ n.root = true;
ReachableNode(&n);
}
@@ -96,7 +97,9 @@
}
int64_t HeapGraphWalker::RetainedSize(const Component& component) {
- int64_t retained_size = static_cast<int64_t>(component.unique_retained_size);
+ int64_t retained_size =
+ static_cast<int64_t>(component.unique_retained_size) +
+ static_cast<int64_t>(component.unique_retained_root_size);
for (const int64_t child_component_id : component.children_components) {
const Component& child_component =
components_[static_cast<size_t>(child_component_id)];
@@ -150,6 +153,8 @@
// A node can never be part of two components.
PERFETTO_CHECK(stack_elem->component == -1);
stack_elem->component = component_id;
+ if (stack_elem->root)
+ component.root = true;
} while (stack_elem != node);
for (Node* elem : component_nodes) {
@@ -184,11 +189,20 @@
components_[static_cast<size_t>(grand_component_id)];
grand_component.pending_nodes -= count;
if (grand_component.pending_nodes == 0) {
- component.unique_retained_size += grand_component.unique_retained_size;
- if (IsUniqueOwner(component_to_node, count, grand_component_id,
- dc.last_node_row)) {
- unique_retained_by_node[dc.last_node_row] +=
+ component.unique_retained_root_size +=
+ grand_component.unique_retained_root_size;
+ if (grand_component.root) {
+ component.unique_retained_root_size +=
grand_component.unique_retained_size;
+ } else {
+ component.unique_retained_size +=
+ grand_component.unique_retained_size;
+
+ if (IsUniqueOwner(component_to_node, count, grand_component_id,
+ dc.last_node_row)) {
+ unique_retained_by_node[dc.last_node_row] +=
+ grand_component.unique_retained_size;
+ }
}
grand_component.children_components.clear();
component.children_components.erase(grand_component_id);
@@ -200,22 +214,22 @@
child_component.incoming_edges -= count;
child_component.pending_nodes -= count;
- if (child_component.orig_incoming_edges == count) {
+ if (child_component.pending_nodes == 0) {
PERFETTO_CHECK(child_component.incoming_edges == 0);
- PERFETTO_CHECK(child_component.pending_nodes == 0);
- component.unique_retained_size += child_component.unique_retained_size;
- if (count == 1) {
- unique_retained_by_node[dc.last_node_row] +=
+ component.unique_retained_root_size +=
+ child_component.unique_retained_root_size;
+ if (child_component.root) {
+ component.unique_retained_root_size +=
child_component.unique_retained_size;
- }
- } else if (child_component.pending_nodes == 0) {
- PERFETTO_CHECK(child_component.incoming_edges == 0);
- component.unique_retained_size += child_component.unique_retained_size;
- if (IsUniqueOwner(component_to_node, count, child_component_id,
- dc.last_node_row)) {
- unique_retained_by_node[dc.last_node_row] +=
- child_component.unique_retained_size;
+ } else {
+ component.unique_retained_size += child_component.unique_retained_size;
+
+ if (IsUniqueOwner(component_to_node, count, child_component_id,
+ dc.last_node_row)) {
+ unique_retained_by_node[dc.last_node_row] +=
+ child_component.unique_retained_size;
+ }
}
component.children_components.erase(child_component_id);
} else {
@@ -228,9 +242,11 @@
size_t parents = component.orig_incoming_edges;
// If this has no parents, but does not retain a node, we know that no other
- // node can retain this node. Add 1 to poison that node.
- if (parents == 0)
- parents = 1;
+ // node can uniquely retain this node. Add 1 to poison that node.
+ // If this is a root, but it does not retain a node, we also know that no
+ // node can uniquely retain that node.
+ if (parents == 0 || component.root)
+ parents += 1;
for (const int64_t child_component_id : component.children_components) {
Component& child_component =
components_[static_cast<size_t>(child_component_id)];
@@ -256,6 +272,7 @@
node_stack_.push_back(node);
node->on_stack = true;
for (Node* child : node->children) {
+ PERFETTO_CHECK(child->reachable);
if (child->node_index == 0) {
FindSCC(child);
if (child->lowlink < node->lowlink)
diff --git a/src/trace_processor/importers/proto/heap_graph_walker.h b/src/trace_processor/importers/proto/heap_graph_walker.h
index 57d4550..b23f2a3 100644
--- a/src/trace_processor/importers/proto/heap_graph_walker.h
+++ b/src/trace_processor/importers/proto/heap_graph_walker.h
@@ -135,15 +135,20 @@
bool reachable = false;
bool on_stack = false;
+ bool root = false;
};
struct Component {
+ uint64_t self_size = 0;
uint64_t unique_retained_size = 0;
+ uint64_t unique_retained_root_size = 0;
size_t incoming_edges = 0;
size_t orig_incoming_edges = 0;
size_t pending_nodes = 0;
std::set<int64_t> children_components;
uint64_t lowlink = 0;
+
+ bool root = false;
};
Node& GetNode(int64_t id) { return nodes_[static_cast<size_t>(id)]; }
diff --git a/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc b/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
index 74b98e7..7ec9c09 100644
--- a/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
+++ b/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
@@ -23,6 +23,9 @@
namespace trace_processor {
namespace {
+using ::testing::UnorderedElementsAre;
+using ::testing::UnorderedElementsAreArray;
+
class HeapGraphWalkerTestDelegate : public HeapGraphWalker::Delegate {
public:
~HeapGraphWalkerTestDelegate() override = default;
@@ -68,7 +71,7 @@
// 2 3 |
// ^ ^ |
// \ / |
-// 4 |
+// 4R |
TEST(HeapGraphWalkerTest, Diamond) {
HeapGraphWalkerTestDelegate delegate;
HeapGraphWalker walker(&delegate);
@@ -96,10 +99,10 @@
EXPECT_EQ(delegate.UniqueRetained(4), 10);
}
-// 1 2 |
-// ^ ^ |
-// \ / |
-// 3<->4 |
+// 1 2 |
+// ^ ^ |
+// \ / |
+// 3R<->4 |
TEST(HeapGraphWalkerTest, Loop) {
HeapGraphWalkerTestDelegate delegate;
HeapGraphWalker walker(&delegate);
@@ -127,7 +130,7 @@
EXPECT_EQ(delegate.UniqueRetained(4), 6);
}
-// 1 |
+// 1R |
// ^\ |
// / v |
// 3<-2 |
@@ -157,10 +160,10 @@
// 1 |
// ^ |
// | |
-// 2 4 |
-// ^ ^ |
-// | | |
-// 3 5 |
+// 2 4 |
+// ^ ^ |
+// | | |
+// 3R 5 |
TEST(HeapGraphWalkerTest, Disconnected) {
HeapGraphWalkerTestDelegate delegate;
HeapGraphWalker walker(&delegate);
@@ -201,7 +204,7 @@
// 4 5 |
// ^ ^ |
// \ / |
-// 6 |
+// 6R |
TEST(HeapGraphWalkerTest, Complex) {
HeapGraphWalkerTestDelegate delegate;
HeapGraphWalker walker(&delegate);
@@ -244,7 +247,7 @@
// 2<-> 3 |
// ^ |
// | |
-// 4 |
+// 4R |
TEST(HeapGraphWalkerTest, SharedInComponent) {
HeapGraphWalkerTestDelegate delegate;
HeapGraphWalker walker(&delegate);
@@ -268,6 +271,7 @@
EXPECT_EQ(delegate.Retained(4), 10);
EXPECT_EQ(delegate.UniqueRetained(1), 1);
+ // TODO(fmayer): this should be 6, as it breaks away the component.
EXPECT_EQ(delegate.UniqueRetained(2), 2);
EXPECT_EQ(delegate.UniqueRetained(3), 3);
EXPECT_EQ(delegate.UniqueRetained(4), 10);
@@ -276,7 +280,7 @@
// 1 <- 2 |
// ^ ^ |
// | | |
-// 3<-> 4 |
+// 3<-> 4R |
TEST(HeapGraphWalkerTest, TwoPaths) {
HeapGraphWalkerTestDelegate delegate;
HeapGraphWalker walker(&delegate);
@@ -308,7 +312,7 @@
// 1 |
// ^^ |
// / \ |
-// 2 3 |
+// 2R 3R |
TEST(HeapGraphWalkerTest, Diverge) {
HeapGraphWalkerTestDelegate delegate;
HeapGraphWalker walker(&delegate);
@@ -335,7 +339,7 @@
// 1 |
// ^^ |
// / \ |
-// 2 3 (dead) |
+// 2R 3 (dead) |
TEST(HeapGraphWalkerTest, Dead) {
HeapGraphWalkerTestDelegate delegate;
HeapGraphWalker walker(&delegate);
@@ -356,6 +360,229 @@
EXPECT_EQ(delegate.UniqueRetained(2), 3);
}
+// 2<->3 |
+// ^ |
+// | |
+// 1R |
+TEST(HeapGraphWalkerTest, Component) {
+ HeapGraphWalkerTestDelegate delegate;
+ HeapGraphWalker walker(&delegate);
+ walker.AddNode(1, 1);
+ walker.AddNode(2, 2);
+ walker.AddNode(3, 3);
+
+ walker.AddEdge(1, 2);
+ walker.AddEdge(2, 3);
+ walker.AddEdge(3, 2);
+
+ walker.MarkRoot(1);
+ walker.CalculateRetained();
+
+ EXPECT_EQ(delegate.Retained(1), 6);
+ EXPECT_EQ(delegate.Retained(2), 5);
+ EXPECT_EQ(delegate.Retained(3), 5);
+
+ EXPECT_EQ(delegate.UniqueRetained(1), 6);
+ // TODO(fmayer): this should be 5, as this breaks away the component.
+ EXPECT_EQ(delegate.UniqueRetained(2), 2);
+ EXPECT_EQ(delegate.UniqueRetained(3), 3);
+}
+
+// 2<->3R |
+// ^ |
+// | |
+// 1R |
+TEST(HeapGraphWalkerTest, ComponentWithRoot) {
+ HeapGraphWalkerTestDelegate delegate;
+ HeapGraphWalker walker(&delegate);
+ walker.AddNode(1, 1);
+ walker.AddNode(2, 2);
+ walker.AddNode(3, 3);
+
+ walker.AddEdge(1, 2);
+ walker.AddEdge(2, 3);
+ walker.AddEdge(3, 2);
+
+ walker.MarkRoot(1);
+ walker.MarkRoot(3);
+ walker.CalculateRetained();
+
+ EXPECT_EQ(delegate.Retained(1), 6);
+ EXPECT_EQ(delegate.Retained(2), 5);
+ EXPECT_EQ(delegate.Retained(3), 5);
+
+ EXPECT_EQ(delegate.UniqueRetained(1), 1);
+ EXPECT_EQ(delegate.UniqueRetained(2), 2);
+ EXPECT_EQ(delegate.UniqueRetained(3), 3);
+}
+
+// R
+// 2 <- 3 |
+// ^ ^ |
+// \ / |
+// 1R |
+TEST(HeapGraphWalkerTest, TwoRoots) {
+ HeapGraphWalkerTestDelegate delegate;
+ HeapGraphWalker walker(&delegate);
+ walker.AddNode(1, 1);
+ walker.AddNode(2, 2);
+ walker.AddNode(3, 3);
+
+ walker.AddEdge(1, 2);
+ walker.AddEdge(1, 3);
+ walker.AddEdge(3, 2);
+
+ walker.MarkRoot(1);
+ walker.MarkRoot(2);
+ walker.CalculateRetained();
+
+ EXPECT_EQ(delegate.Retained(1), 6);
+ EXPECT_EQ(delegate.Retained(2), 2);
+ EXPECT_EQ(delegate.Retained(3), 5);
+
+ EXPECT_EQ(delegate.UniqueRetained(1), 4);
+ EXPECT_EQ(delegate.UniqueRetained(2), 2);
+ EXPECT_EQ(delegate.UniqueRetained(3), 3);
+}
+
+// Call a function for every set in the powerset or the cartesian product
+// of v with itself.
+// TODO(fmayer): Find a smarter way to generate all graphs.
+template <typename F>
+void SquarePowerSet(const std::vector<int64_t>& v, F fn) {
+ for (uint64_t subset = 0; subset < pow(2, pow(v.size(), 2)); ++subset) {
+ std::vector<std::pair<int64_t, int64_t>> ps;
+ uint64_t node = 0;
+ for (int64_t n1 : v) {
+ for (int64_t n2 : v) {
+ if ((1 << node++) & subset)
+ ps.emplace_back(n1, n2);
+ }
+ }
+ fn(ps);
+ }
+}
+
+// Call a function for every set in the powerset.
+template <typename F>
+void PowerSet(const std::vector<int64_t>& v, F fn) {
+ for (uint64_t subset = 0; subset < pow(2, v.size()); ++subset) {
+ std::vector<int64_t> ps;
+ uint64_t node = 0;
+ for (int64_t n : v) {
+ if ((1 << node++) & subset)
+ ps.emplace_back(n);
+ }
+ fn(ps);
+ }
+}
+
+TEST(PowerSetTest, Simple) {
+ std::vector<int64_t> s = {0, 1, 2};
+ std::vector<std::vector<int64_t>> ps;
+ PowerSet(s, [&ps](const std::vector<int64_t>& x) { ps.emplace_back(x); });
+ EXPECT_THAT(ps, UnorderedElementsAre(std::vector<int64_t>{}, //
+ std::vector<int64_t>{0}, //
+ std::vector<int64_t>{1}, //
+ std::vector<int64_t>{2}, //
+ std::vector<int64_t>{0, 1}, //
+ std::vector<int64_t>{0, 2}, //
+ std::vector<int64_t>{1, 2}, //
+ std::vector<int64_t>{0, 1, 2}));
+}
+
+TEST(SquarePowerSetTest, Simple) {
+ std::vector<int64_t> s = {0, 1};
+ std::vector<std::vector<std::pair<int64_t, int64_t>>> ps;
+ SquarePowerSet(s, [&ps](const std::vector<std::pair<int64_t, int64_t>>& x) {
+ ps.emplace_back(x);
+ });
+
+ std::vector<std::pair<int64_t, int64_t>> expected[] = {
+ {}, //
+ {{0, 0}}, //
+ {{0, 1}}, //
+ {{1, 0}}, //
+ {{1, 1}}, //
+ {{0, 0}, {0, 1}}, //
+ {{0, 0}, {1, 0}}, //
+ {{0, 0}, {1, 1}}, //
+ {{0, 1}, {1, 0}}, //
+ {{0, 1}, {1, 1}}, //
+ {{1, 0}, {1, 1}}, //
+ {{0, 0}, {0, 1}, {1, 0}}, //
+ {{0, 0}, {0, 1}, {1, 1}}, //
+ {{0, 0}, {1, 0}, {1, 1}}, //
+ {{0, 1}, {1, 0}, {1, 1}}, //
+ {{0, 0}, {0, 1}, {1, 0}, {1, 1}}};
+ EXPECT_THAT(ps, UnorderedElementsAreArray(expected));
+}
+
+// Generate all graphs with 4 nodes, and assert that deleting one node frees
+// up more memory than that node's unique retained.
+TEST(HeapGraphWalkerTest, DISABLED_AllGraphs) {
+ std::vector<int64_t> nodes{1, 2, 3, 4};
+ std::vector<uint64_t> sizes{0, 1, 2, 3, 4};
+ PowerSet(nodes, [&nodes, &sizes](const std::vector<int64_t>& roots) {
+ SquarePowerSet(
+ nodes, [&nodes, &sizes,
+ &roots](const std::vector<std::pair<int64_t, int64_t>>& edges) {
+ HeapGraphWalkerTestDelegate delegate;
+ HeapGraphWalker walker(&delegate);
+
+ HeapGraphWalkerTestDelegate delegate2;
+ HeapGraphWalker walker2(&delegate2);
+
+ for (int64_t node : nodes) {
+ walker.AddNode(node, sizes[static_cast<size_t>(node)]);
+ // walker2 leaves out node 1.
+ if (node != 1)
+ walker2.AddNode(node, sizes[static_cast<size_t>(node)]);
+ }
+
+ for (const auto& p : edges) {
+ walker.AddEdge(p.first, p.second);
+ // walker2 leaves out node 1.
+ if (p.first != 1 && p.second != 1)
+ walker2.AddEdge(p.first, p.second);
+ }
+
+ for (int64_t r : roots) {
+ walker.MarkRoot(r);
+ // walker2 leaves out node 1.
+ if (r != 1)
+ walker2.MarkRoot(r);
+ }
+
+ walker.CalculateRetained();
+ // We do not need to CalculateRetained on walker2, because we only
+ // get the reachable nodes.
+
+ int64_t reachable = 0;
+ int64_t reachable2 = 0;
+
+ ASSERT_FALSE(delegate2.Reachable(1));
+ for (int64_t n : nodes) {
+ if (delegate.Reachable(n))
+ reachable += sizes[static_cast<size_t>(n)];
+ if (delegate2.Reachable(n))
+ reachable2 += sizes[static_cast<size_t>(n)];
+ }
+ EXPECT_LE(reachable2, reachable);
+ if (delegate.Reachable(1)) {
+ // TODO(fmayer): This should be EXPECT_EQ, but we do currently
+ // undercount the unique retained, because we do not include the
+ // memory that could get freed by the component being broken apart.
+ EXPECT_LE(delegate.UniqueRetained(1), reachable - reachable2)
+ << "roots: " << testing::PrintToString(roots)
+ << ", edges: " << testing::PrintToString(edges);
+ } else {
+ EXPECT_EQ(reachable2, reachable);
+ }
+ });
+ });
+}
+
} // namespace
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/packet_sequence_state.h b/src/trace_processor/importers/proto/packet_sequence_state.h
index 8ee597b..b6bc5a6 100644
--- a/src/trace_processor/importers/proto/packet_sequence_state.h
+++ b/src/trace_processor/importers/proto/packet_sequence_state.h
@@ -22,6 +22,7 @@
#include <unordered_map>
#include <vector>
+#include "perfetto/base/compiler.h"
#include "perfetto/protozero/proto_decoder.h"
#include "src/trace_processor/stack_profile_tracker.h"
#include "src/trace_processor/trace_blob_view.h"
@@ -31,13 +32,13 @@
namespace perfetto {
namespace trace_processor {
-#if PERFETTO_DCHECK_IS_ON() && defined(__GNUC__)
-// When called from GetOrCreateDecoder(), __PRETTY_FUNCTION__ (supported by GCC
-// + clang) should include the stringified name of the MessageType.
-#define PERFETTO_TYPE_IDENTIFIER __PRETTY_FUNCTION__
-#else // PERFETTO_DCHECK_IS_ON() && defined(__GNUC__)
+#if PERFETTO_DCHECK_IS_ON()
+// When called from GetOrCreateDecoder(), should include the stringified name of
+// the MessageType.
+#define PERFETTO_TYPE_IDENTIFIER PERFETTO_DEBUG_FUNCTION_IDENTIFIER()
+#else // PERFETTO_DCHECK_IS_ON()
#define PERFETTO_TYPE_IDENTIFIER nullptr
-#endif // PERFETTO_DCHECK_IS_ON() && defined(__GNUC__)
+#endif // PERFETTO_DCHECK_IS_ON()
class PacketSequenceState {
public:
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index 0811da4..bd19c0e 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -630,20 +630,26 @@
for (auto addr_it = module_symbols.address_symbols(); addr_it; ++addr_it) {
protos::pbzero::AddressSymbols::Decoder address_symbols(*addr_it);
- ssize_t frame_row = -1;
+ uint32_t symbol_set_id = context_->storage->symbol_table().size();
+ bool frame_found = false;
for (int64_t mapping_row : mapping_rows) {
- frame_row = context_->storage->stack_profile_frames().FindFrameRow(
- static_cast<size_t>(mapping_row), address_symbols.address());
- if (frame_row != -1)
- break;
+ std::vector<int64_t> frame_rows =
+ context_->storage->stack_profile_frames().FindFrameRow(
+ static_cast<size_t>(mapping_row), address_symbols.address());
+
+ for (const int64_t frame_row : frame_rows) {
+ PERFETTO_DCHECK(frame_row >= 0);
+ context_->storage->mutable_stack_profile_frames()->SetSymbolSetId(
+ static_cast<size_t>(frame_row), symbol_set_id);
+ frame_found = true;
+ }
}
- if (frame_row == -1) {
+
+ if (!frame_found) {
context_->storage->IncrementStats(stats::stackprofile_invalid_frame_id);
continue;
}
- uint32_t symbol_set_id = context_->storage->symbol_table().size();
- context_->storage->mutable_stack_profile_frames()->SetSymbolSetId(
- static_cast<size_t>(frame_row), symbol_set_id);
+
for (auto line_it = address_symbols.lines(); line_it; ++line_it) {
protos::pbzero::Line::Decoder line(*line_it);
context_->storage->mutable_symbol_table()->Insert(
diff --git a/src/trace_processor/instants_table.cc b/src/trace_processor/instants_table.cc
index 279e36c..53ddd80 100644
--- a/src/trace_processor/instants_table.cc
+++ b/src/trace_processor/instants_table.cc
@@ -50,15 +50,15 @@
int InstantsTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
info->estimated_cost =
static_cast<uint32_t>(storage_->instants().instant_count());
+ info->sqlite_omit_order_by = true;
// Only the string columns are handled by SQLite
- info->order_by_consumed = true;
size_t name_index = schema().ColumnIndexFromName("name");
size_t ref_type_index = schema().ColumnIndexFromName("ref_type");
for (size_t i = 0; i < qc.constraints().size(); i++) {
- info->omit[i] =
- qc.constraints()[i].iColumn != static_cast<int>(name_index) &&
- qc.constraints()[i].iColumn != static_cast<int>(ref_type_index);
+ info->sqlite_omit_constraint[i] =
+ qc.constraints()[i].column != static_cast<int>(name_index) &&
+ qc.constraints()[i].column != static_cast<int>(ref_type_index);
}
return SQLITE_OK;
diff --git a/src/trace_processor/metrics/BUILD.gn b/src/trace_processor/metrics/BUILD.gn
index bfa95de..28d6f01 100644
--- a/src/trace_processor/metrics/BUILD.gn
+++ b/src/trace_processor/metrics/BUILD.gn
@@ -32,6 +32,7 @@
"android/android_startup_cpu.sql",
"android/android_package_list.sql",
"android/heap_profile_callsites.sql",
+ "android/java_heap_stats.sql",
"android/process_unagg_mem_view.sql",
"android/process_mem.sql",
"android/mem_stats_priority_breakdown.sql",
diff --git a/src/trace_processor/metrics/android/heap_profile_callsites.sql b/src/trace_processor/metrics/android/heap_profile_callsites.sql
index a0cd0c4..ce2aeb4 100644
--- a/src/trace_processor/metrics/android/heap_profile_callsites.sql
+++ b/src/trace_processor/metrics/android/heap_profile_callsites.sql
@@ -14,6 +14,17 @@
-- limitations under the License.
--
+CREATE VIEW memory_delta AS
+SELECT upid, SUM(size) AS delta
+FROM heap_profile_allocation
+GROUP BY 1;
+
+CREATE VIEW memory_total AS
+SELECT upid, SUM(size) AS total
+FROM heap_profile_allocation
+WHERE size > 0
+GROUP BY 1;
+
-- Join frames with symbols and mappings to get a textual representation.
CREATE TABLE symbolized_frame AS
SELECT
@@ -205,9 +216,14 @@
SELECT HeapProfileCallsites_InstanceStats(
'pid', process.pid,
'process_name', process.name,
- 'callsites', repeated_callsite_proto
+ 'callsites', repeated_callsite_proto,
+ 'profile_delta_bytes', memory_delta.delta,
+ 'profile_total_bytes', memory_total.total
) AS instance_stats_proto
-FROM process_callsite_proto JOIN process USING (upid);
+FROM process_callsite_proto
+JOIN memory_total USING (upid)
+JOIN memory_delta USING (upid)
+JOIN process USING (upid);
CREATE VIEW heap_profile_callsites_output AS
SELECT HeapProfileCallsites(
diff --git a/src/trace_processor/metrics/android/java_heap_stats.sql b/src/trace_processor/metrics/android/java_heap_stats.sql
new file mode 100644
index 0000000..d8f2f34
--- /dev/null
+++ b/src/trace_processor/metrics/android/java_heap_stats.sql
@@ -0,0 +1,58 @@
+--
+-- Copyright 2019 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+
+CREATE VIEW total_size_samples AS
+SELECT upid, graph_sample_ts, SUM(self_size) AS total_size
+FROM heap_graph_object
+GROUP BY 1, 2;
+
+CREATE VIEW total_reachable_size_samples AS
+SELECT upid, graph_sample_ts, SUM(self_size) AS total_reachable_size
+FROM heap_graph_object
+WHERE reachable = TRUE
+GROUP BY 1, 2;
+
+CREATE TABLE heap_graph_samples AS
+SELECT upid, graph_sample_ts, total_size, total_reachable_size
+FROM total_size_samples JOIN total_reachable_size_samples
+USING (upid, graph_sample_ts);
+
+CREATE VIEW heap_graph_sample_protos AS
+SELECT
+ upid,
+ JavaHeapStats_Sample(
+ 'ts', graph_sample_ts,
+ 'heap_size', total_size,
+ 'reachable_heap_size', total_reachable_size
+ ) sample_proto
+FROM heap_graph_samples;
+
+CREATE TABLE heap_graph_instance_stats AS
+SELECT
+ upid,
+ process.name process_name,
+ RepeatedField(sample_proto) AS sample_protos
+FROM heap_graph_sample_protos JOIN process USING (upid)
+GROUP BY 1, 2;
+
+CREATE VIEW java_heap_stats_output AS
+SELECT JavaHeapStats(
+ 'instance_stats', RepeatedField(JavaHeapStats_InstanceStats(
+ 'upid', upid,
+ 'process_name', process_name,
+ 'samples', sample_protos
+ )))
+FROM heap_graph_instance_stats;
diff --git a/src/trace_processor/metrics/metrics.descriptor.h b/src/trace_processor/metrics/metrics.descriptor.h
index 5700d0b..df7696c 100644
--- a/src/trace_processor/metrics/metrics.descriptor.h
+++ b/src/trace_processor/metrics/metrics.descriptor.h
@@ -12,14 +12,14 @@
// SHA1(tools/gen_binary_descriptors)
// 192b582ae52bb07b3d3ba66a94bcfd3127a5f42f
// SHA1(protos/perfetto/metrics/metrics.proto)
-// 3617cd492d3a717441de21b0b04ce363e0669f57
+// 4279eeace6a7d9647e484e65b8265ea211a02b6c
// This is the proto Metrics encoded as a ProtoFileDescriptor to allow
// for reflection without libprotobuf full/non-lite protos.
namespace perfetto {
-constexpr std::array<uint8_t, 9666> kMetricsDescriptor{
+constexpr std::array<uint8_t, 10312> kMetricsDescriptor{
{0x0a, 0x98, 0x03, 0x0a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
@@ -540,14 +540,14 @@
0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54,
0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
0x0c, 0x74, 0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xd7, 0x06, 0x0a, 0x3c, 0x70, 0x72,
+ 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xb7, 0x07, 0x0a, 0x3c, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70,
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73,
0x69, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x22, 0x81, 0x06, 0x0a, 0x14, 0x48, 0x65, 0x61, 0x70,
+ 0x74, 0x6f, 0x73, 0x22, 0xe1, 0x06, 0x0a, 0x14, 0x48, 0x65, 0x61, 0x70,
0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
0x69, 0x74, 0x65, 0x73, 0x12, 0x5a, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74,
0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01,
@@ -599,7 +599,7 @@
0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
0x69, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
0x73, 0x52, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x41, 0x6c, 0x6c, 0x6f,
- 0x63, 0x73, 0x1a, 0x92, 0x01, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61,
+ 0x63, 0x73, 0x1a, 0xf2, 0x01, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61,
0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03,
0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x70,
0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
@@ -611,7 +611,15 @@
0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69,
0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e,
0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x52, 0x09, 0x63, 0x61,
- 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a,
+ 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x70,
+ 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
+ 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x11, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x6c,
+ 0x74, 0x61, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x70,
+ 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c,
+ 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x11, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x6f, 0x74,
+ 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a,
0x8c, 0x02, 0x0a, 0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
@@ -656,176 +664,222 @@
0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61,
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x02, 0x48,
- 0x03, 0x0a, 0xee, 0x0f, 0x0a, 0x25, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x1a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x62, 0x61,
- 0x74, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
- 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x2f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x75, 0x6e, 0x61,
- 0x67, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x1a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
- 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f,
- 0x77, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x69, 0x6f, 0x6e, 0x5f, 0x6d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
- 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b,
- 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x1a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70,
- 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x34, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75,
- 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x1a, 0x3c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
- 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
- 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x03, 0x0a, 0xa4, 0x03, 0x0a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69,
- 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x39, 0x70, 0x72,
+ 0x64, 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f,
+ 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+ 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xd5, 0x02, 0x0a, 0x0d, 0x4a, 0x61, 0x76,
+ 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x53,
+ 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73,
+ 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c,
+ 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61,
+ 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61,
+ 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x69, 0x6e,
+ 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x1a,
+ 0x65, 0x0a, 0x06, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x0e, 0x0a,
+ 0x02, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x74,
+ 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69,
+ 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x68, 0x65,
+ 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65,
+ 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x70,
+ 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x11, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x48, 0x65,
+ 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x87, 0x01, 0x0a, 0x0d, 0x49,
+ 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73,
+ 0x12, 0x12, 0x0a, 0x04, 0x75, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x0d, 0x52, 0x04, 0x75, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63,
+ 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x07, 0x73,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x48,
+ 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x53, 0x61, 0x6d,
+ 0x70, 0x6c, 0x65, 0x52, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73,
+ 0x42, 0x02, 0x48, 0x03, 0x0a, 0xed, 0x10, 0x0a, 0x25, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x1a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x2f, 0x62, 0x61, 0x74, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x2f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x75, 0x6e, 0x73, 0x79, 0x6d, 0x62,
- 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
- 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf1, 0x01, 0x0a, 0x0d,
- 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
- 0x61, 0x12, 0x50, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x73,
- 0x74, 0x61, 0x74, 0x73, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54,
- 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
- 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x65, 0x72, 0x72, 0x6f,
- 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
- 0x2a, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x64, 0x75, 0x72,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x0f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x44, 0x75, 0x72,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74,
- 0x72, 0x61, 0x63, 0x65, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x72, 0x61, 0x63, 0x65, 0x55, 0x75,
- 0x69, 0x64, 0x1a, 0x43, 0x0a, 0x05, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
- 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69,
- 0x64, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x69, 0x64,
- 0x78, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
- 0xb8, 0x08, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x12, 0x48, 0x0a, 0x0c, 0x61, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x5f, 0x62, 0x61, 0x74, 0x74, 0x18, 0x05, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
+ 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f,
+ 0x75, 0x6e, 0x61, 0x67, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x34, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
+ 0x67, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x69, 0x6f,
+ 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+ 0x6c, 0x6d, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x2f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
+ 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x74, 0x61,
+ 0x72, 0x74, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3c, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66,
+ 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
+ 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x32, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
+ 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
+ 0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x75, 0x6e, 0x73,
+ 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
+ 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6a, 0x61, 0x76, 0x61,
+ 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf1, 0x01, 0x0a, 0x0d, 0x54, 0x72,
+ 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12,
+ 0x50, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61,
+ 0x74, 0x73, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61,
+ 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x45,
+ 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x53,
+ 0x74, 0x61, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x2a, 0x0a,
+ 0x11, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x0f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x4e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x72, 0x61,
+ 0x63, 0x65, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x09, 0x74, 0x72, 0x61, 0x63, 0x65, 0x55, 0x75, 0x69, 0x64,
+ 0x1a, 0x43, 0x0a, 0x05, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x78,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x69, 0x64, 0x78, 0x12,
+ 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x80, 0x09,
+ 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x12, 0x48, 0x0a, 0x0c, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x5f, 0x62, 0x61, 0x74, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x4d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x52, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x42, 0x61, 0x74, 0x74, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x5f, 0x63, 0x70, 0x75, 0x18, 0x06, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75,
+ 0x12, 0x45, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f,
+ 0x6d, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d,
+ 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52,
+ 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x12,
+ 0x5c, 0x0a, 0x11, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6d,
+ 0x65, 0x6d, 0x5f, 0x75, 0x6e, 0x61, 0x67, 0x67, 0x18, 0x0b, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x4d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x63, 0x70, 0x75, 0x18, 0x06, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e,
+ 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x4d, 0x65, 0x6d, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x12, 0x55, 0x0a,
+ 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70, 0x61, 0x63,
+ 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0c, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43,
- 0x70, 0x75, 0x12, 0x45, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65,
- 0x6d, 0x12, 0x5c, 0x0a, 0x11, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x75, 0x6e, 0x61, 0x67, 0x67, 0x18, 0x0b,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
- 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64,
- 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x12,
- 0x55, 0x0a, 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70,
- 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18,
- 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
- 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61,
- 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x12, 0x61, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69,
- 0x73, 0x74, 0x12, 0x5b, 0x0a, 0x16, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72,
- 0x6f, 0x77, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25,
- 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74,
- 0x68, 0x52, 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72,
- 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x12,
- 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x69,
- 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
+ 0x4c, 0x69, 0x73, 0x74, 0x52, 0x12, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74,
+ 0x12, 0x5b, 0x0a, 0x16, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x77,
+ 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70,
0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f,
- 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0b, 0x61,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6d, 0x6b, 0x18, 0x08,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x4c, 0x6d, 0x6b, 0x12, 0x4d, 0x0a, 0x10, 0x61, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x5f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18,
- 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
- 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72,
- 0x52, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x50, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4e,
- 0x0a, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x73, 0x74,
- 0x61, 0x72, 0x74, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x52, 0x0e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
- 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x5b, 0x0a, 0x16, 0x68, 0x65,
- 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63,
- 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61,
- 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c,
- 0x73, 0x69, 0x74, 0x65, 0x73, 0x52, 0x14, 0x68, 0x65, 0x61, 0x70, 0x50,
+ 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x52,
+ 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63,
+ 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x12, 0x42, 0x0a,
+ 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x69, 0x6f, 0x6e,
+ 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6d, 0x6b, 0x18, 0x08, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d,
+ 0x6b, 0x12, 0x4d, 0x0a, 0x10, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x5f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x07, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61,
+ 0x69, 0x6c, 0x73, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x50, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0f,
+ 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72,
+ 0x74, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
+ 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x52, 0x0e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61,
+ 0x72, 0x74, 0x75, 0x70, 0x12, 0x5b, 0x0a, 0x16, 0x68, 0x65, 0x61, 0x70,
+ 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c,
+ 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50,
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69,
- 0x74, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x63, 0x65,
- 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20,
+ 0x74, 0x65, 0x73, 0x52, 0x14, 0x68, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f,
+ 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
+ 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x6d,
+ 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63,
+ 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x74,
+ 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x12, 0x54, 0x0a, 0x13, 0x75, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
+ 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18,
+ 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x12, 0x75, 0x6e, 0x73, 0x79,
+ 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x73, 0x12, 0x46, 0x0a, 0x0f, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68,
+ 0x65, 0x61, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x11, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72,
- 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52,
- 0x0d, 0x74, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
- 0x74, 0x61, 0x12, 0x54, 0x0a, 0x13, 0x75, 0x6e, 0x73, 0x79, 0x6d, 0x62,
- 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
- 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x2e, 0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a,
- 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x12, 0x75, 0x6e,
- 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72,
- 0x61, 0x6d, 0x65, 0x73, 0x2a, 0x06, 0x08, 0xc2, 0x03, 0x10, 0xf4, 0x03,
- 0x2a, 0x06, 0x08, 0xf4, 0x03, 0x10, 0xe9, 0x07, 0x4a, 0x04, 0x08, 0x04,
- 0x10, 0x05, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x4a, 0x04, 0x08, 0x0e,
- 0x10, 0x0f, 0x42, 0x02, 0x48, 0x03}};
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61,
+ 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52,
+ 0x0d, 0x6a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61,
+ 0x74, 0x73, 0x2a, 0x06, 0x08, 0xc2, 0x03, 0x10, 0xf4, 0x03, 0x2a, 0x06,
+ 0x08, 0xf4, 0x03, 0x10, 0xe9, 0x07, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05,
+ 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x4a, 0x04, 0x08, 0x0e, 0x10, 0x0f,
+ 0x42, 0x02, 0x48, 0x03}};
} // namespace perfetto
diff --git a/src/trace_processor/process_table.cc b/src/trace_processor/process_table.cc
index 9d0129a..adc9d1e 100644
--- a/src/trace_processor/process_table.cc
+++ b/src/trace_processor/process_table.cc
@@ -61,7 +61,7 @@
// because we can do that filter efficiently.
const auto& cs = qc.constraints();
auto fn = [](const QueryConstraints::Constraint& c) {
- return c.iColumn == Column::kUpid && sqlite_utils::IsOpEq(c.op);
+ return c.column == Column::kUpid && sqlite_utils::IsOpEq(c.op);
};
info->estimated_cost = std::find_if(cs.begin(), cs.end(), fn) != cs.end()
? 1
@@ -74,57 +74,56 @@
int ProcessTable::Cursor::Filter(const QueryConstraints& qc,
sqlite3_value** argv) {
- min = 0;
- max = static_cast<uint32_t>(storage_->process_count()) - 1;
- desc = false;
+ min_ = 0;
+ max_ = static_cast<uint32_t>(storage_->process_count());
+ desc_ = false;
for (size_t j = 0; j < qc.constraints().size(); j++) {
const auto& cs = qc.constraints()[j];
- if (cs.iColumn == Column::kUpid) {
+ if (cs.column == Column::kUpid) {
auto constraint_upid = static_cast<UniquePid>(sqlite3_value_int(argv[j]));
// Set the range of upids that we are interested in, based on the
- // constraints in the query. Everything between min and max (inclusive)
+ // constraints in the query. Everything between min and max (exclusive)
// will be returned.
if (IsOpEq(cs.op)) {
- min = constraint_upid;
- max = constraint_upid;
+ min_ = constraint_upid;
+ max_ = constraint_upid + 1;
} else if (IsOpGe(cs.op) || IsOpGt(cs.op)) {
- min = IsOpGt(cs.op) ? constraint_upid + 1 : constraint_upid;
+ min_ = IsOpGt(cs.op) ? constraint_upid + 1 : constraint_upid;
} else if (IsOpLe(cs.op) || IsOpLt(cs.op)) {
- max = IsOpLt(cs.op) ? constraint_upid - 1 : constraint_upid;
+ max_ = IsOpLt(cs.op) ? constraint_upid : constraint_upid + 1;
}
}
}
for (const auto& ob : qc.order_by()) {
if (ob.iColumn == Column::kUpid) {
- desc = ob.desc;
+ desc_ = ob.desc;
}
}
- current = desc ? max : min;
+ index_ = 0;
return SQLITE_OK;
}
int ProcessTable::Cursor::Column(sqlite3_context* context, int N) {
+ uint32_t current = desc_ ? max_ - index_ - 1 : min_ + index_;
+ const auto& process = storage_->GetProcess(current);
switch (N) {
case Column::kUpid: {
sqlite3_result_int64(context, current);
break;
}
case Column::kName: {
- const auto& process = storage_->GetProcess(current);
const auto& name = storage_->GetString(process.name_id);
sqlite3_result_text(context, name.c_str(), -1, kSqliteStatic);
break;
}
case Column::kPid: {
- const auto& process = storage_->GetProcess(current);
sqlite3_result_int64(context, process.pid);
break;
}
case Column::kStartTs: {
- const auto& process = storage_->GetProcess(current);
if (process.start_ns != 0) {
sqlite3_result_int64(context, process.start_ns);
} else {
@@ -133,7 +132,6 @@
break;
}
case Column::kEndTs: {
- const auto& process = storage_->GetProcess(current);
if (process.end_ns != 0) {
sqlite3_result_int64(context, process.end_ns);
} else {
@@ -142,7 +140,6 @@
break;
}
case Column::kParentUpid: {
- const auto& process = storage_->GetProcess(current);
if (process.parent_upid.has_value()) {
sqlite3_result_int64(context, process.parent_upid.value());
} else {
@@ -158,16 +155,12 @@
}
int ProcessTable::Cursor::Next() {
- if (desc) {
- --current;
- } else {
- ++current;
- }
+ ++index_;
return SQLITE_OK;
}
int ProcessTable::Cursor::Eof() {
- return desc ? current < min : current > max;
+ return index_ >= (max_ - min_);
}
} // namespace trace_processor
diff --git a/src/trace_processor/process_table.h b/src/trace_processor/process_table.h
index 4c8b208..c4c1ed5 100644
--- a/src/trace_processor/process_table.h
+++ b/src/trace_processor/process_table.h
@@ -50,10 +50,10 @@
private:
const TraceStorage* const storage_;
- UniquePid min;
- UniquePid max;
- UniquePid current;
- bool desc;
+ UniquePid min_ = 0;
+ UniquePid max_ = 0;
+ uint32_t index_ = 0;
+ bool desc_ = false;
};
static void RegisterTable(sqlite3* db, const TraceStorage* storage);
diff --git a/src/trace_processor/raw_table.cc b/src/trace_processor/raw_table.cc
index bf4f111..b4c2969 100644
--- a/src/trace_processor/raw_table.cc
+++ b/src/trace_processor/raw_table.cc
@@ -70,12 +70,13 @@
int RawTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
info->estimated_cost = RowCount();
+ info->sqlite_omit_order_by = true;
// Only the string columns are handled by SQLite
- info->order_by_consumed = true;
size_t name_index = schema().ColumnIndexFromName("name");
for (size_t i = 0; i < qc.constraints().size(); i++) {
- info->omit[i] = qc.constraints()[i].iColumn != static_cast<int>(name_index);
+ info->sqlite_omit_constraint[i] =
+ qc.constraints()[i].column != static_cast<int>(name_index);
}
return SQLITE_OK;
diff --git a/src/trace_processor/sched_slice_table.cc b/src/trace_processor/sched_slice_table.cc
index 05657c4..633e62f 100644
--- a/src/trace_processor/sched_slice_table.cc
+++ b/src/trace_processor/sched_slice_table.cc
@@ -51,8 +51,9 @@
// We should be able to handle any constraint and any order by clause given
// to us.
- info->order_by_consumed = true;
- std::fill(info->omit.begin(), info->omit.end(), true);
+ info->sqlite_omit_order_by = true;
+ auto& omit_cs = info->sqlite_omit_constraint;
+ std::fill(omit_cs.begin(), omit_cs.end(), true);
return SQLITE_OK;
}
@@ -62,7 +63,7 @@
size_t ts_idx = schema().ColumnIndexFromName("ts");
auto has_ts_column = [ts_idx](const QueryConstraints::Constraint& c) {
- return c.iColumn == static_cast<int>(ts_idx);
+ return c.column == static_cast<int>(ts_idx);
};
bool has_time_constraint = std::any_of(cs.begin(), cs.end(), has_ts_column);
if (has_time_constraint) {
@@ -73,8 +74,7 @@
size_t utid_idx = schema().ColumnIndexFromName("utid");
auto has_utid_eq_cs = [utid_idx](const QueryConstraints::Constraint& c) {
- return c.iColumn == static_cast<int>(utid_idx) &&
- sqlite_utils::IsOpEq(c.op);
+ return c.column == static_cast<int>(utid_idx) && sqlite_utils::IsOpEq(c.op);
};
bool has_utid_eq = std::any_of(cs.begin(), cs.end(), has_utid_eq_cs);
if (has_utid_eq) {
diff --git a/src/trace_processor/slice_table.cc b/src/trace_processor/slice_table.cc
index d2dca83..2570674 100644
--- a/src/trace_processor/slice_table.cc
+++ b/src/trace_processor/slice_table.cc
@@ -53,15 +53,15 @@
int SliceTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
info->estimated_cost = EstimateCost(qc);
+ info->sqlite_omit_order_by = true;
// Only the string columns are handled by SQLite
- info->order_by_consumed = true;
size_t name_index = schema().ColumnIndexFromName("name");
size_t cat_index = schema().ColumnIndexFromName("category");
size_t ref_type_index = schema().ColumnIndexFromName("ref_type");
for (size_t i = 0; i < qc.constraints().size(); i++) {
- auto col = static_cast<size_t>(qc.constraints()[i].iColumn);
- info->omit[i] =
+ auto col = static_cast<size_t>(qc.constraints()[i].column);
+ info->sqlite_omit_constraint[i] =
col != name_index && col != cat_index && col != ref_type_index;
}
return SQLITE_OK;
diff --git a/src/trace_processor/span_join_operator_table.cc b/src/trace_processor/span_join_operator_table.cc
index 57b1598..931289c 100644
--- a/src/trace_processor/span_join_operator_table.cc
+++ b/src/trace_processor/span_join_operator_table.cc
@@ -182,7 +182,7 @@
std::vector<std::string> constraints;
for (size_t i = 0; i < qc.constraints().size(); i++) {
const auto& cs = qc.constraints()[i];
- auto col_name = GetNameForGlobalColumnIndex(defn, cs.iColumn);
+ auto col_name = GetNameForGlobalColumnIndex(defn, cs.column);
if (col_name == "")
continue;
diff --git a/src/trace_processor/sql_stats_table.cc b/src/trace_processor/sql_stats_table.cc
index 3356f8e..0d434a0 100644
--- a/src/trace_processor/sql_stats_table.cc
+++ b/src/trace_processor/sql_stats_table.cc
@@ -57,7 +57,7 @@
}
int SqlStatsTable::BestIndex(const QueryConstraints&, BestIndexInfo* info) {
- info->order_by_consumed = false; // Delegate sorting to SQLite.
+ info->sqlite_omit_order_by = true;
return SQLITE_OK;
}
diff --git a/src/trace_processor/sqlite/db_sqlite_table.cc b/src/trace_processor/sqlite/db_sqlite_table.cc
index b2298ca..8b3dfc8 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table.cc
@@ -133,7 +133,7 @@
// This means we have at least one constraint. Check if any of the constraints
// is an equality constraint on an id column.
auto id_filter = [this](const QueryConstraints::Constraint& c) {
- uint32_t col_idx = static_cast<uint32_t>(c.iColumn);
+ uint32_t col_idx = static_cast<uint32_t>(c.column);
const auto& col = table_->GetColumn(col_idx);
return sqlite_utils::IsOpEq(c.op) && col.IsId();
};
@@ -167,7 +167,7 @@
constraints_.resize(qc.constraints().size());
for (size_t i = 0; i < qc.constraints().size(); ++i) {
const auto& cs = qc.constraints()[i];
- uint32_t col = static_cast<uint32_t>(cs.iColumn);
+ uint32_t col = static_cast<uint32_t>(cs.column);
FilterOp op = SqliteOpToFilterOp(cs.op);
SqlValue value = SqliteValueToSqlValue(argv[i]);
diff --git a/src/trace_processor/sqlite/query_constraints.cc b/src/trace_processor/sqlite/query_constraints.cc
index cc57838..9ff242f 100644
--- a/src/trace_processor/sqlite/query_constraints.cc
+++ b/src/trace_processor/sqlite/query_constraints.cc
@@ -42,7 +42,7 @@
}
for (size_t i = 0; i < constraints().size(); ++i) {
- if ((constraints()[i].iColumn != other.constraints()[i].iColumn) ||
+ if ((constraints()[i].column != other.constraints()[i].column) ||
(constraints()[i].op != other.constraints()[i].op)) {
return false;
}
@@ -58,10 +58,13 @@
return true;
}
-void QueryConstraints::AddConstraint(int column, unsigned char op) {
+void QueryConstraints::AddConstraint(int column,
+ unsigned char op,
+ int aconstraint_idx) {
Constraint c{};
- c.iColumn = column;
+ c.column = column;
c.op = op;
+ c.a_constraint_idx = aconstraint_idx;
constraints_.emplace_back(c);
}
@@ -79,7 +82,7 @@
str_result.append(std::to_string(constraints_.size()));
str_result.append(",");
for (const auto& cs : constraints_) {
- str_result.append(std::to_string(cs.iColumn));
+ str_result.append(std::to_string(cs.column));
str_result.append(",");
str_result.append(std::to_string(cs.op));
str_result.append(",");
@@ -117,7 +120,7 @@
PERFETTO_CHECK(splitter.Next());
unsigned char op =
static_cast<unsigned char>(strtol(splitter.cur_token(), nullptr, 10));
- qc.AddConstraint(col, op);
+ qc.AddConstraint(col, op, 0);
}
PERFETTO_CHECK(splitter.Next() && splitter.cur_token_size() > 1);
diff --git a/src/trace_processor/sqlite/query_constraints.h b/src/trace_processor/sqlite/query_constraints.h
index 2c47562..54c1b45 100644
--- a/src/trace_processor/sqlite/query_constraints.h
+++ b/src/trace_processor/sqlite/query_constraints.h
@@ -38,7 +38,19 @@
// in the xBestIndex call and passed to each corresponding xFilter call.
class QueryConstraints {
public:
- using Constraint = sqlite3_index_info::sqlite3_index_constraint;
+ struct Constraint {
+ // Column this constraint refers to.
+ int column;
+
+ // SQLite op for the constraint.
+ int op;
+
+ // The original index of this constraint in the aConstraint array.
+ // Used internally by SqliteTable for xBestIndex - this should not be
+ // read or modified by subclasses of SqliteTable.
+ int a_constraint_idx;
+ };
+
using OrderBy = sqlite3_index_info::sqlite3_index_orderby;
static int FreeSqliteString(char* resource);
@@ -54,7 +66,7 @@
// are equal.
bool operator==(const QueryConstraints& other) const;
- void AddConstraint(int column, unsigned char op);
+ void AddConstraint(int column, unsigned char op, int aconstraint_idx);
void AddOrderBy(int column, unsigned char desc);
@@ -73,6 +85,10 @@
const std::vector<Constraint>& constraints() const { return constraints_; }
+ std::vector<OrderBy>* mutable_order_by() { return &order_by_; }
+
+ std::vector<Constraint>* mutable_constraints() { return &constraints_; }
+
private:
QueryConstraints(const QueryConstraints&) = delete;
QueryConstraints& operator=(const QueryConstraints&) = delete;
diff --git a/src/trace_processor/sqlite/query_constraints_unittest.cc b/src/trace_processor/sqlite/query_constraints_unittest.cc
index 276cec1..402bc70 100644
--- a/src/trace_processor/sqlite/query_constraints_unittest.cc
+++ b/src/trace_processor/sqlite/query_constraints_unittest.cc
@@ -36,7 +36,7 @@
TEST_F(QueryConstraintsTest, ConvertToAndFromSqlString) {
QueryConstraints qc;
- qc.AddConstraint(12, 0);
+ qc.AddConstraint(12, 0, 0);
QueryConstraints::SqliteString only_constraint = qc.ToNewSqlite3String();
ASSERT_TRUE(strcmp(only_constraint.get(), "C1,12,0,O0") == 0);
diff --git a/src/trace_processor/sqlite/sqlite_table.cc b/src/trace_processor/sqlite/sqlite_table.cc
index 211ff7e..512d672 100644
--- a/src/trace_processor/sqlite/sqlite_table.cc
+++ b/src/trace_processor/sqlite/sqlite_table.cc
@@ -19,6 +19,7 @@
#include <ctype.h>
#include <string.h>
#include <algorithm>
+#include <map>
#include "perfetto/base/logging.h"
@@ -58,60 +59,69 @@
}
int SqliteTable::BestIndexInternal(sqlite3_index_info* idx) {
- QueryConstraints query_constraints;
-
- for (int i = 0; i < idx->nOrderBy; i++) {
- int column = idx->aOrderBy[i].iColumn;
- bool desc = idx->aOrderBy[i].desc;
- query_constraints.AddOrderBy(column, desc);
- }
+ QueryConstraints qc;
for (int i = 0; i < idx->nConstraint; i++) {
const auto& cs = idx->aConstraint[i];
if (!cs.usable)
continue;
- query_constraints.AddConstraint(cs.iColumn, cs.op);
-
- // argvIndex is 1-based so use the current size of the vector.
- int argv_index = static_cast<int>(query_constraints.constraints().size());
- idx->aConstraintUsage[i].argvIndex = argv_index;
+ qc.AddConstraint(cs.iColumn, cs.op, i);
}
- BestIndexInfo info;
- info.omit.resize(query_constraints.constraints().size());
-
- int ret = BestIndex(query_constraints, &info);
-
- if (SqliteTable::debug) {
- PERFETTO_LOG(
- "[%s::BestIndex] constraints=%s orderByConsumed=%d estimatedCost=%d",
- name_.c_str(), query_constraints.ToNewSqlite3String().get(),
- info.order_by_consumed, info.estimated_cost);
+ for (int i = 0; i < idx->nOrderBy; i++) {
+ int column = idx->aOrderBy[i].iColumn;
+ bool desc = idx->aOrderBy[i].desc;
+ qc.AddOrderBy(column, desc);
}
+ int ret = ModifyConstraints(&qc);
if (ret != SQLITE_OK)
return ret;
- idx->orderByConsumed = info.order_by_consumed;
+ BestIndexInfo info;
+ info.sqlite_omit_constraint.resize(qc.constraints().size());
+
+ ret = BestIndex(qc, &info);
+ if (ret != SQLITE_OK)
+ return ret;
+
+ idx->orderByConsumed = qc.order_by().empty() || info.sqlite_omit_order_by;
idx->estimatedCost = info.estimated_cost;
- size_t j = 0;
- for (int i = 0; i < idx->nConstraint; i++) {
- const auto& cs = idx->aConstraint[i];
- if (cs.usable)
- idx->aConstraintUsage[i].omit = info.omit[j++];
+ // First pass: mark all constraints as omitted to ensure that any pruned
+ // constraints are not checked for by SQLite.
+ for (int i = 0; i < idx->nConstraint; ++i) {
+ auto& u = idx->aConstraintUsage[i];
+ u.omit = true;
}
- if (!info.order_by_consumed)
- query_constraints.ClearOrderBy();
+ // Second pass: actually set the correct omit and index values for all
+ // retained constraints.
+ for (uint32_t i = 0; i < qc.constraints().size(); ++i) {
+ auto& u = idx->aConstraintUsage[qc.constraints()[i].a_constraint_idx];
+ u.omit = info.sqlite_omit_constraint[i];
+ u.argvIndex = static_cast<int>(i) + 1;
+ }
- idx->idxStr = query_constraints.ToNewSqlite3String().release();
+ auto out_qc_str = qc.ToNewSqlite3String();
+ if (SqliteTable::debug) {
+ PERFETTO_LOG(
+ "[%s::BestIndex] constraints=%s orderByConsumed=%d estimatedCost=%d",
+ name_.c_str(), out_qc_str.get(), idx->orderByConsumed,
+ info.estimated_cost);
+ }
+
+ idx->idxStr = out_qc_str.release();
idx->needToFreeIdxStr = true;
idx->idxNum = ++best_index_num_;
return SQLITE_OK;
}
+int SqliteTable::ModifyConstraints(QueryConstraints*) {
+ return SQLITE_OK;
+}
+
int SqliteTable::FindFunction(const char*, FindFunctionFn, void**) {
return 0;
}
diff --git a/src/trace_processor/sqlite/sqlite_table.h b/src/trace_processor/sqlite/sqlite_table.h
index 51557bf..c53baaf 100644
--- a/src/trace_processor/sqlite/sqlite_table.h
+++ b/src/trace_processor/sqlite/sqlite_table.h
@@ -136,9 +136,23 @@
// Populated by a BestIndex call to allow subclasses to tweak SQLite's
// handling of sets of constraints.
struct BestIndexInfo {
- bool order_by_consumed = false;
+ // Contains bools which indicate whether SQLite should omit double checking
+ // the constraint at that index.
+ //
+ // If there are no constraints, SQLite will be told it can omit checking for
+ // the whole query.
+ std::vector<bool> sqlite_omit_constraint;
+
+ // Indicates that SQLite should not double check the result of the order by
+ // clause.
+ //
+ // If there are no order by clauses, this value will be ignored and SQLite
+ // will be told that it can omit double checking (i.e. this value will
+ // implicitly be taken to be true).
+ bool sqlite_omit_order_by = false;
+
+ // Stores the estimated cost of this query.
uint32_t estimated_cost = 0;
- std::vector<bool> omit;
};
template <typename Context>
@@ -279,6 +293,7 @@
// Optional metods to implement.
using FindFunctionFn = void (**)(sqlite3_context*, int, sqlite3_value**);
+ virtual int ModifyConstraints(QueryConstraints* qc);
virtual int FindFunction(const char* name, FindFunctionFn fn, void** args);
// At registration time, the function should also pass true for |read_write|.
diff --git a/src/trace_processor/stack_profile_frame_table.cc b/src/trace_processor/stack_profile_frame_table.cc
index eb750e3..6939873 100644
--- a/src/trace_processor/stack_profile_frame_table.cc
+++ b/src/trace_processor/stack_profile_frame_table.cc
@@ -46,7 +46,7 @@
int StackProfileFrameTable::BestIndex(const QueryConstraints& qc,
BestIndexInfo* info) {
- info->order_by_consumed = true;
+ info->sqlite_omit_order_by = true;
info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
return SQLITE_OK;
}
diff --git a/src/trace_processor/stack_profile_mapping_table.cc b/src/trace_processor/stack_profile_mapping_table.cc
index a7644db..52a9038 100644
--- a/src/trace_processor/stack_profile_mapping_table.cc
+++ b/src/trace_processor/stack_profile_mapping_table.cc
@@ -50,7 +50,7 @@
int StackProfileMappingTable::BestIndex(const QueryConstraints& qc,
BestIndexInfo* info) {
- info->order_by_consumed = true;
+ info->sqlite_omit_order_by = true;
info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
return SQLITE_OK;
}
diff --git a/src/trace_processor/stack_profile_tracker.cc b/src/trace_processor/stack_profile_tracker.cc
index aa6b764..25815ea 100644
--- a/src/trace_processor/stack_profile_tracker.cc
+++ b/src/trace_processor/stack_profile_tracker.cc
@@ -82,12 +82,35 @@
static_cast<int64_t>(mapping.load_bias),
context_->storage->InternString(base::StringView(path))};
- int64_t cur_row;
+ TraceStorage::StackProfileMappings* mappings =
+ context_->storage->mutable_stack_profile_mappings();
+ int64_t cur_row = -1;
auto it = mapping_idx_.find(row);
if (it != mapping_idx_.end()) {
cur_row = it->second;
} else {
- cur_row = context_->storage->mutable_stack_profile_mappings()->Insert(row);
+ std::vector<int64_t> db_mappings =
+ mappings->FindMappingRow(row.name_id, row.build_id);
+ for (const int64_t preexisting_mapping : db_mappings) {
+ PERFETTO_DCHECK(preexisting_mapping >= 0);
+ size_t preexisting_row_id = static_cast<size_t>(preexisting_mapping);
+ TraceStorage::StackProfileMappings::Row preexisting_row{
+ mappings->build_ids()[preexisting_row_id],
+ mappings->exact_offsets()[preexisting_row_id],
+ mappings->start_offsets()[preexisting_row_id],
+ mappings->starts()[preexisting_row_id],
+ mappings->ends()[preexisting_row_id],
+ mappings->load_biases()[preexisting_row_id],
+ mappings->names()[preexisting_row_id]};
+
+ if (row == preexisting_row) {
+ cur_row = preexisting_mapping;
+ }
+ }
+ if (cur_row == -1) {
+ cur_row =
+ context_->storage->mutable_stack_profile_mappings()->Insert(row);
+ }
mapping_idx_.emplace(row, cur_row);
}
mappings_.emplace(id, cur_row);
@@ -118,12 +141,31 @@
TraceStorage::StackProfileFrames::Row row{str_id, mapping_row,
static_cast<int64_t>(frame.rel_pc)};
- int64_t cur_row;
+ TraceStorage::StackProfileFrames* frames =
+ context_->storage->mutable_stack_profile_frames();
+
+ int64_t cur_row = -1;
auto it = frame_idx_.find(row);
if (it != frame_idx_.end()) {
cur_row = it->second;
} else {
- cur_row = context_->storage->mutable_stack_profile_frames()->Insert(row);
+ std::vector<int64_t> db_frames =
+ frames->FindFrameRow(static_cast<size_t>(mapping_row), frame.rel_pc);
+ for (const int64_t preexisting_frame : db_frames) {
+ PERFETTO_DCHECK(preexisting_frame >= 0);
+ size_t preexisting_row_id = static_cast<size_t>(preexisting_frame);
+ TraceStorage::StackProfileFrames::Row preexisting_row{
+ frames->names()[preexisting_row_id],
+ frames->mappings()[preexisting_row_id],
+ frames->rel_pcs()[preexisting_row_id]};
+
+ if (row == preexisting_row) {
+ cur_row = preexisting_frame;
+ }
+ }
+ if (cur_row == -1) {
+ cur_row = context_->storage->mutable_stack_profile_frames()->Insert(row);
+ }
frame_idx_.emplace(row, cur_row);
}
frames_.emplace(id, cur_row);
diff --git a/src/trace_processor/stack_profile_tracker.h b/src/trace_processor/stack_profile_tracker.h
index 309c376..9496929 100644
--- a/src/trace_processor/stack_profile_tracker.h
+++ b/src/trace_processor/stack_profile_tracker.h
@@ -166,6 +166,8 @@
std::unordered_map<SourceCallstack, int64_t> callstacks_from_frames_;
std::unordered_map<SourceCallstackId, int64_t> callstacks_;
+ // TODO(oysteine): Share these indices between the StackProfileTrackers,
+ // since they're not sequence-specific.
std::unordered_map<TraceStorage::StackProfileMappings::Row, int64_t>
mapping_idx_;
std::unordered_map<TraceStorage::StackProfileFrames::Row, int64_t> frame_idx_;
diff --git a/src/trace_processor/stats.h b/src/trace_processor/stats.h
index 8c4452c..583dfa2 100644
--- a/src/trace_processor/stats.h
+++ b/src/trace_processor/stats.h
@@ -121,7 +121,10 @@
F(packages_list_has_parse_errors, kSingle, kError, kTrace), \
F(packages_list_has_read_errors, kSingle, kError, kTrace), \
F(compact_sched_has_parse_errors, kSingle, kError, kTrace), \
- F(misplaced_end_event, kSingle, kDataLoss, kAnalysis)
+ F(misplaced_end_event, kSingle, kDataLoss, kAnalysis), \
+ F(sched_waking_out_of_order, kSingle, kError, kAnalysis), \
+ F(compact_sched_switch_skipped, kSingle, kInfo, kAnalysis), \
+ F(compact_sched_waking_skipped, kSingle, kInfo, kAnalysis)
// clang-format on
enum Type {
diff --git a/src/trace_processor/storage_table.cc b/src/trace_processor/storage_table.cc
index 8cac8b2..aec5810 100644
--- a/src/trace_processor/storage_table.cc
+++ b/src/trace_processor/storage_table.cc
@@ -69,7 +69,7 @@
std::vector<size_t> bitvector_cs;
for (size_t i = 0; i < cs.size(); i++) {
const auto& c = cs[i];
- size_t column = static_cast<size_t>(c.iColumn);
+ size_t column = static_cast<size_t>(c.column);
auto bounds = schema_.GetColumn(column).BoundFilter(c.op, argv[i]);
min_idx = std::max(min_idx, bounds.min_idx);
@@ -90,7 +90,7 @@
const auto& c = cs[c_idx];
auto* value = argv[c_idx];
- const auto& schema_col = schema_.GetColumn(static_cast<size_t>(c.iColumn));
+ const auto& schema_col = schema_.GetColumn(static_cast<size_t>(c.column));
schema_col.Filter(c.op, value, &index);
if (!index.error().empty())
@@ -119,7 +119,7 @@
std::set<int> equality_cols;
for (const auto& c : cs) {
if (sqlite_utils::IsOpEq(c.op))
- equality_cols.emplace(c.iColumn);
+ equality_cols.emplace(c.column);
}
for (const auto& o : obs) {
if (equality_cols.count(o.iColumn) > 0)
@@ -160,7 +160,7 @@
const std::string& col_name) {
size_t c_idx = schema().ColumnIndexFromName(col_name);
auto fn = [c_idx](const QueryConstraints::Constraint& c) {
- return c.iColumn == static_cast<int>(c_idx) && sqlite_utils::IsOpEq(c.op);
+ return c.column == static_cast<int>(c_idx) && sqlite_utils::IsOpEq(c.op);
};
const auto& cs = qc.constraints();
return std::find_if(cs.begin(), cs.end(), fn) != cs.end();
diff --git a/src/trace_processor/string_pool.cc b/src/trace_processor/string_pool.cc
index 6c25229..6574e36 100644
--- a/src/trace_processor/string_pool.cc
+++ b/src/trace_processor/string_pool.cc
@@ -66,9 +66,13 @@
const uint8_t* StringPool::Block::TryInsert(base::StringView str) {
auto str_size = str.size();
- if (static_cast<uint64_t>(pos_) + str_size + kMaxMetadataSize > size_)
+ size_t max_pos = static_cast<size_t>(pos_) + str_size + kMaxMetadataSize;
+ if (max_pos > size_)
return nullptr;
+ // Ensure that we commit up until the end of the string to memory.
+ mem_.EnsureCommitted(max_pos);
+
// Get where we should start writing this string.
uint8_t* begin = Get(pos_);
@@ -86,6 +90,7 @@
// Update the end of the block and return the pointer to the string.
pos_ = OffsetOf(end);
+
return begin;
}
diff --git a/src/trace_processor/string_pool.h b/src/trace_processor/string_pool.h
index e2502e7..3724d5e 100644
--- a/src/trace_processor/string_pool.h
+++ b/src/trace_processor/string_pool.h
@@ -123,7 +123,9 @@
struct Block {
explicit Block(size_t size)
- : mem_(base::PagedMemory::Allocate(size)), size_(size) {}
+ : mem_(base::PagedMemory::Allocate(size,
+ base::PagedMemory::kDontCommit)),
+ size_(size) {}
~Block() = default;
// Allow std::move().
@@ -151,7 +153,7 @@
private:
base::PagedMemory mem_;
uint32_t pos_ = 0;
- size_t size_;
+ size_t size_ = 0;
};
friend class Iterator;
diff --git a/src/trace_processor/thread_table.cc b/src/trace_processor/thread_table.cc
index a951812..c98127d 100644
--- a/src/trace_processor/thread_table.cc
+++ b/src/trace_processor/thread_table.cc
@@ -62,7 +62,7 @@
// because we can do that filter efficiently.
const auto& constraints = qc.constraints();
for (const auto& cs : qc.constraints()) {
- if (cs.iColumn == Column::kUtid) {
+ if (cs.column == Column::kUtid) {
info->estimated_cost = IsOpEq(constraints.front().op) ? 1 : 10;
}
}
@@ -76,40 +76,41 @@
sqlite3_value** argv) {
*this = Cursor(table_);
- min = 0;
- max = static_cast<uint32_t>(storage_->thread_count()) - 1;
- desc = false;
+ min_ = 0;
+ max_ = static_cast<uint32_t>(storage_->thread_count());
+ desc_ = false;
for (size_t j = 0; j < qc.constraints().size(); j++) {
const auto& cs = qc.constraints()[j];
- if (cs.iColumn == Column::kUtid) {
+ if (cs.column == Column::kUtid) {
UniqueTid constraint_utid =
static_cast<UniqueTid>(sqlite3_value_int(argv[j]));
// Filter the range of utids that we are interested in, based on the
- // constraints in the query. Everything between min and max (inclusive)
+ // constraints in the query. Everything between min and max (exclusive)
// will be returned.
if (IsOpEq(cs.op)) {
- min = constraint_utid;
- max = constraint_utid;
+ min_ = constraint_utid;
+ max_ = constraint_utid + 1;
} else if (IsOpGe(cs.op) || IsOpGt(cs.op)) {
- min = IsOpGt(cs.op) ? constraint_utid + 1 : constraint_utid;
+ min_ = IsOpGt(cs.op) ? constraint_utid + 1 : constraint_utid;
} else if (IsOpLe(cs.op) || IsOpLt(cs.op)) {
- max = IsOpLt(cs.op) ? constraint_utid - 1 : constraint_utid;
+ max_ = IsOpLt(cs.op) ? constraint_utid : constraint_utid + 1;
}
}
}
for (const auto& ob : qc.order_by()) {
if (ob.iColumn == Column::kUtid) {
- desc = ob.desc;
+ desc_ = ob.desc;
}
}
- current = desc ? max : min;
+ index_ = 0;
return SQLITE_OK;
}
int ThreadTable::Cursor::Column(sqlite3_context* context, int N) {
+ uint32_t current = desc_ ? max_ - index_ - 1 : min_ + index_;
const auto& thread = storage_->GetThread(current);
switch (N) {
case Column::kUtid: {
@@ -158,16 +159,12 @@
}
int ThreadTable::Cursor::Next() {
- if (desc) {
- --current;
- } else {
- ++current;
- }
+ ++index_;
return SQLITE_OK;
}
int ThreadTable::Cursor::Eof() {
- return desc ? current < min : current > max;
+ return index_ >= (max_ - min_);
}
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/thread_table.h b/src/trace_processor/thread_table.h
index a72ed23..43484d1 100644
--- a/src/trace_processor/thread_table.h
+++ b/src/trace_processor/thread_table.h
@@ -55,10 +55,10 @@
Cursor(Cursor&&) noexcept = default;
Cursor& operator=(Cursor&&) = default;
- UniqueTid min;
- UniqueTid max;
- UniqueTid current;
- bool desc;
+ UniqueTid min_ = 0;
+ UniqueTid max_ = 0;
+ uint32_t index_ = 0;
+ bool desc_ = false;
const TraceStorage* storage_ = nullptr;
ThreadTable* table_ = nullptr;
diff --git a/src/trace_processor/timestamped_trace_piece.h b/src/trace_processor/timestamped_trace_piece.h
index 84e21fb..83b4932 100644
--- a/src/trace_processor/timestamped_trace_piece.h
+++ b/src/trace_processor/timestamped_trace_piece.h
@@ -44,10 +44,17 @@
StringId next_comm;
};
+struct InlineSchedWaking {
+ int32_t pid;
+ int32_t target_cpu;
+ int32_t prio;
+ StringId comm;
+};
+
// Discriminated union of events that are cannot be easily read from the
// mapped trace.
struct InlineEvent {
- enum class Type { kInvalid = 0, kSchedSwitch };
+ enum class Type { kInvalid = 0, kSchedSwitch, kSchedWaking };
static InlineEvent SchedSwitch(InlineSchedSwitch content) {
InlineEvent evt;
@@ -56,9 +63,17 @@
return evt;
}
+ static InlineEvent SchedWaking(InlineSchedWaking content) {
+ InlineEvent evt;
+ evt.type = Type::kSchedWaking;
+ evt.sched_waking = content;
+ return evt;
+ }
+
Type type = Type::kInvalid;
union {
InlineSchedSwitch sched_switch;
+ InlineSchedWaking sched_waking;
};
};
@@ -135,12 +150,16 @@
sequence_state,
InlineEvent{}) {}
+ // TODO(rsavitski): each "empty" TraceBlobView created by this constructor
+ // still allocates ref-counting structures for the nonexistent memory.
+ // It's not a significant overhead, but consider making the class have a
+ // legitimate empty state.
TimestampedTracePiece(int64_t ts, uint64_t idx, InlineEvent inline_evt)
: TimestampedTracePiece(ts,
/*thread_ts=*/0,
/*thread_instructions=*/0,
idx,
- /*tbv=*/TraceBlobView(nullptr, 0, 0),
+ TraceBlobView(nullptr, 0, 0),
/*value=*/nullptr,
/*fpv=*/nullptr,
/*sequence_state=*/nullptr,
diff --git a/src/trace_processor/trace_database_integrationtest.cc b/src/trace_processor/trace_database_integrationtest.cc
index f845dbb..b96e628 100644
--- a/src/trace_processor/trace_database_integrationtest.cc
+++ b/src/trace_processor/trace_database_integrationtest.cc
@@ -108,6 +108,26 @@
ASSERT_EQ(it.Get(0).long_value, static_cast<int64_t>(0xa9cb070fdc15f7a4));
}
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#define MAYBE_Demangle DISABLED_Demangle
+#else
+#define MAYBE_Demangle Demangle
+#endif
+TEST_F(TraceProcessorIntegrationTest, MAYBE_Demangle) {
+ auto it = Query("select DEMANGLE('_Znwm')");
+ ASSERT_TRUE(it.Next());
+ ASSERT_STRCASEEQ(it.Get(0).string_value, "operator new(unsigned long)");
+
+ it = Query("select DEMANGLE('_ZN3art6Thread14CreateCallbackEPv')");
+ ASSERT_TRUE(it.Next());
+ ASSERT_STRCASEEQ(it.Get(0).string_value,
+ "art::Thread::CreateCallback(void*)");
+
+ it = Query("select DEMANGLE('test')");
+ ASSERT_TRUE(it.Next());
+ ASSERT_TRUE(it.Get(0).is_null());
+}
+
#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
TEST_F(TraceProcessorIntegrationTest, Sfgate) {
ASSERT_TRUE(LoadTrace("sfgate.json", strlen("{\"traceEvents\":[")).ok());
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 80a7c9d..a51913a 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -56,6 +56,10 @@
#include "src/trace_processor/export_json.h"
#endif
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <cxxabi.h>
+#endif
+
// In Android and Chromium tree builds, we don't have the percentile module.
// Just don't include it.
#if PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
@@ -138,7 +142,7 @@
"CREATE VIEW counter_definitions AS "
"SELECT "
" *, "
- " id as counter_id "
+ " id AS counter_id "
"FROM counter_track",
0, 0, &error);
if (error) {
@@ -147,9 +151,23 @@
}
sqlite3_exec(db,
+ "CREATE VIEW counter_values AS "
+ "SELECT "
+ " *, "
+ " track_id as counter_id "
+ "FROM counter",
+ 0, 0, &error);
+ if (error) {
+ PERFETTO_ELOG("Error initializing: %s", error);
+ sqlite3_free(error);
+ }
+
+ sqlite3_exec(db,
"CREATE VIEW counters AS "
- "SELECT * FROM counter_values "
- "INNER JOIN counter_definitions USING(counter_id) "
+ "SELECT * "
+ "FROM counter_values v "
+ "INNER JOIN counter_track t "
+ "ON v.track_id = t.id "
"ORDER BY ts;",
0, 0, &error);
if (error) {
@@ -161,7 +179,7 @@
"CREATE VIEW slice AS "
"SELECT "
" *, "
- " category as cat, "
+ " category AS cat, "
" CASE ref_type "
" WHEN 'utid' THEN ref "
" ELSE NULL "
@@ -256,6 +274,32 @@
sqlite3_result_int64(ctx, static_cast<int64_t>(hash.digest()));
}
+void Demangle(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
+ if (argc != 1) {
+ sqlite3_result_error(ctx, "Unsupported number of arg passed to DEMANGLE",
+ -1);
+ return;
+ }
+ sqlite3_value* value = argv[0];
+ if (sqlite3_value_type(value) != SQLITE_TEXT) {
+ sqlite3_result_error(ctx, "Unsupported type of arg passed to DEMANGLE", -1);
+ return;
+ }
+ const char* ptr = reinterpret_cast<const char*>(sqlite3_value_text(value));
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ int ignored = 0;
+ // This memory was allocated by malloc and will be passed to SQLite to free.
+ char* demangled_name = abi::__cxa_demangle(ptr, nullptr, nullptr, &ignored);
+ if (!demangled_name) {
+ sqlite3_result_null(ctx);
+ return;
+ }
+ sqlite3_result_text(ctx, demangled_name, -1, free);
+#else
+ sqlite3_result_text(ctx, ptr, -1, sqlite_utils::kSqliteTransient);
+#endif
+}
+
void CreateHashFunction(sqlite3* db) {
auto ret = sqlite3_create_function_v2(
db, "HASH", -1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr, &Hash,
@@ -265,6 +309,15 @@
}
}
+void CreateDemangledNameFunction(sqlite3* db) {
+ auto ret = sqlite3_create_function_v2(
+ db, "DEMANGLE", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr, &Demangle,
+ nullptr, nullptr, nullptr);
+ if (ret != SQLITE_OK) {
+ PERFETTO_ELOG("Error initializing DEMANGLE: %s", sqlite3_errmsg(db));
+ }
+}
+
#if PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
void SetupMetrics(TraceProcessor* tp,
sqlite3* db,
@@ -314,6 +367,7 @@
CreateJsonExportFunction(this->context_.storage.get(), db);
#endif
CreateHashFunction(db);
+ CreateDemangledNameFunction(db);
#if PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
SetupMetrics(this, *db_, &sql_metrics_);
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index a832e9f..7243b42 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -787,15 +787,17 @@
rel_pcs_.emplace_back(row.rel_pc);
symbol_set_ids_.emplace_back(0);
size_t row_number = names_.size() - 1;
- index_.emplace(std::make_pair(row.mapping_row, row.rel_pc), row_number);
+ index_[std::make_pair(row.mapping_row, row.rel_pc)].emplace_back(
+ row_number);
return static_cast<uint32_t>(row_number);
}
- ssize_t FindFrameRow(size_t mapping_row, uint64_t rel_pc) const {
+ std::vector<int64_t> FindFrameRow(size_t mapping_row,
+ uint64_t rel_pc) const {
auto it = index_.find(std::make_pair(mapping_row, rel_pc));
if (it == index_.end())
- return -1;
- return static_cast<ssize_t>(it->second);
+ return {};
+ return it->second;
}
void SetSymbolSetId(size_t row_idx, uint32_t symbol_set_id) {
@@ -816,7 +818,8 @@
std::deque<int64_t> rel_pcs_;
std::deque<uint32_t> symbol_set_ids_;
- std::map<std::pair<size_t /* mapping row */, uint64_t /* rel_pc */>, size_t>
+ std::map<std::pair<size_t /* mapping row */, uint64_t /* rel_pc */>,
+ std::vector<int64_t>>
index_;
};
diff --git a/src/trace_processor/window_operator_table.cc b/src/trace_processor/window_operator_table.cc
index cbc8d78..a7a49e5 100644
--- a/src/trace_processor/window_operator_table.cc
+++ b/src/trace_processor/window_operator_table.cc
@@ -61,13 +61,16 @@
return std::unique_ptr<SqliteTable::Cursor>(new Cursor(this));
}
-int WindowOperatorTable::BestIndex(const QueryConstraints& qc,
- BestIndexInfo* info) {
+int WindowOperatorTable::BestIndex(const QueryConstraints&, BestIndexInfo*) {
+ return SQLITE_OK;
+}
+
+int WindowOperatorTable::ModifyConstraints(QueryConstraints* qc) {
// Remove ordering on timestamp if it is the only ordering as we are already
// sorted on TS. This makes span joining significantly faster.
- if (qc.order_by().size() == 1 && qc.order_by()[0].iColumn == Column::kTs &&
- !qc.order_by()[0].desc) {
- info->order_by_consumed = true;
+ const auto& ob = qc->order_by();
+ if (ob.size() == 1 && ob[0].iColumn == Column::kTs && !ob[0].desc) {
+ qc->mutable_order_by()->clear();
}
return SQLITE_OK;
}
@@ -111,7 +114,7 @@
// Set return first if there is a equals constraint on the row id asking to
// return the first row.
bool return_first = qc.constraints().size() == 1 &&
- qc.constraints()[0].iColumn == Column::kRowId &&
+ qc.constraints()[0].column == Column::kRowId &&
IsOpEq(qc.constraints()[0].op) &&
sqlite3_value_int(argv[0]) == 0;
if (return_first) {
diff --git a/src/trace_processor/window_operator_table.h b/src/trace_processor/window_operator_table.h
index 5959174..41fbbb7 100644
--- a/src/trace_processor/window_operator_table.h
+++ b/src/trace_processor/window_operator_table.h
@@ -78,6 +78,7 @@
util::Status Init(int, const char* const*, Schema* schema) override;
std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
+ int ModifyConstraints(QueryConstraints* qc) override;
int Update(int, sqlite3_value**, sqlite3_int64*) override;
private:
diff --git a/src/traced/probes/ftrace/BUILD.gn b/src/traced/probes/ftrace/BUILD.gn
index ddac4e8..11a84ef 100644
--- a/src/traced/probes/ftrace/BUILD.gn
+++ b/src/traced/probes/ftrace/BUILD.gn
@@ -109,7 +109,6 @@
"../../../../gn:default_deps",
"../../../../include/perfetto/ext/traced",
"../../../../protos/perfetto/config/ftrace:cpp",
- "../../../../protos/perfetto/config/ftrace:lite",
"../../../android_internal:lazy_library_loader",
"../../../base",
"../../../protozero",
diff --git a/src/traced/probes/ftrace/compact_sched.cc b/src/traced/probes/ftrace/compact_sched.cc
index 6bc7619..35309d8 100644
--- a/src/traced/probes/ftrace/compact_sched.cc
+++ b/src/traced/probes/ftrace/compact_sched.cc
@@ -23,6 +23,7 @@
#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
#include "src/traced/probes/ftrace/event_info_constants.h"
+#include "src/traced/probes/ftrace/ftrace_config_utils.h"
namespace perfetto {
@@ -37,12 +38,6 @@
CompactSchedSwitchFormat switch_format;
switch_format.event_id = event.ftrace_event_id;
-
- // We make a compile-time buffer capacity decision based on the expected event
- // size per a set of pages. Check that the assumption holds.
- if (event.size < CompactSchedBundleState::kMinSupportedSchedSwitchSize) {
- return base::nullopt;
- }
switch_format.size = event.size;
bool prev_state_valid = false;
@@ -81,7 +76,7 @@
next_comm_valid =
(field.ftrace_type == kFtraceFixedCString &&
- field.ftrace_size == CompactSchedBundleState::kExpectedCommLength);
+ field.ftrace_size == CommInterner::kExpectedCommLength);
break;
default:
break;
@@ -90,13 +85,69 @@
if (!prev_state_valid || !next_pid_valid || !next_prio_valid ||
!next_comm_valid) {
- PERFETTO_ELOG("unexpected sched_switch format");
return base::nullopt;
}
-
return base::make_optional(switch_format);
}
+// Pre-parse the format of sched_waking, checking if our simplifying
+// assumptions about possible widths/signedness hold, and record the subset
+// of the format that will be used during parsing.
+base::Optional<CompactSchedWakingFormat> ValidateSchedWakingFormat(
+ const Event& event) {
+ using protos::pbzero::SchedWakingFtraceEvent;
+
+ CompactSchedWakingFormat waking_format;
+ waking_format.event_id = event.ftrace_event_id;
+ waking_format.size = event.size;
+
+ bool pid_valid = false;
+ bool target_cpu_valid = false;
+ bool prio_valid = false;
+ bool comm_valid = false;
+ for (const auto& field : event.fields) {
+ switch (field.proto_field_id) {
+ case SchedWakingFtraceEvent::kPidFieldNumber:
+ waking_format.pid_offset = field.ftrace_offset;
+ waking_format.pid_type = field.ftrace_type;
+
+ // kernel type: pid_t
+ pid_valid = (field.ftrace_type == kFtracePid32);
+ break;
+
+ case SchedWakingFtraceEvent::kTargetCpuFieldNumber:
+ waking_format.target_cpu_offset = field.ftrace_offset;
+ waking_format.target_cpu_type = field.ftrace_type;
+
+ // kernel type: int
+ target_cpu_valid = (field.ftrace_type == kFtraceInt32);
+ break;
+
+ case SchedWakingFtraceEvent::kPrioFieldNumber:
+ waking_format.prio_offset = field.ftrace_offset;
+ waking_format.prio_type = field.ftrace_type;
+
+ // kernel type: int
+ prio_valid = (field.ftrace_type == kFtraceInt32);
+ break;
+
+ case SchedWakingFtraceEvent::kCommFieldNumber:
+ waking_format.comm_offset = field.ftrace_offset;
+
+ comm_valid = (field.ftrace_type == kFtraceFixedCString &&
+ field.ftrace_size == CommInterner::kExpectedCommLength);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!pid_valid || !target_cpu_valid || !prio_valid || !comm_valid) {
+ return base::nullopt;
+ }
+ return base::make_optional(waking_format);
+}
+
} // namespace
// TODO(rsavitski): could avoid looping over all events if the caller did the
@@ -107,31 +158,36 @@
using protos::pbzero::FtraceEvent;
base::Optional<CompactSchedSwitchFormat> switch_format;
+ base::Optional<CompactSchedWakingFormat> waking_format;
for (const Event& event : events) {
if (event.proto_field_id == FtraceEvent::kSchedSwitchFieldNumber) {
switch_format = ValidateSchedSwitchFormat(event);
}
+ if (event.proto_field_id == FtraceEvent::kSchedWakingFieldNumber) {
+ waking_format = ValidateSchedWakingFormat(event);
+ }
}
- if (switch_format.has_value()) {
- return CompactSchedEventFormat{/*format_valid=*/true,
- switch_format.value()};
+ if (switch_format.has_value() && waking_format.has_value()) {
+ return CompactSchedEventFormat{/*format_valid=*/true, switch_format.value(),
+ waking_format.value()};
} else {
+ PERFETTO_ELOG("Unexpected sched_switch or sched_waking format.");
return CompactSchedEventFormat{/*format_valid=*/false,
- CompactSchedSwitchFormat{}};
+ CompactSchedSwitchFormat{},
+ CompactSchedWakingFormat{}};
}
}
CompactSchedEventFormat InvalidCompactSchedEventFormatForTesting() {
return CompactSchedEventFormat{/*format_valid=*/false,
- CompactSchedSwitchFormat{}};
+ CompactSchedSwitchFormat{},
+ CompactSchedWakingFormat{}};
}
// TODO(rsavitski): find the correct place in the trace for, and method of,
// reporting rejection of compact_sched due to compile-time assumptions not
// holding at runtime.
-// TODO(rsavitski): consider checking if the ftrace config correctly enables
-// sched_switch, for at least an informative print for now?
CompactSchedConfig CreateCompactSchedConfig(
const FtraceConfig& request,
const CompactSchedEventFormat& compact_format) {
@@ -153,37 +209,76 @@
}
// Sanity check size of stack-allocated bundle state.
-static_assert(sizeof(CompactSchedBundleState) <= 1 << 20,
- "CompactSchedBundleState excessively large (used on the stack).");
+static_assert(sizeof(CompactSchedBuffer) <= 1 << 18,
+ "CompactSchedBuffer's on-stack size excessively large.");
-void CompactSchedBundleState::WriteAndReset(
+void CompactSchedSwitchBuffer::Write(
+ protos::pbzero::FtraceEventBundle::CompactSched* compact_out) const {
+ compact_out->set_switch_timestamp(timestamp_);
+ compact_out->set_switch_next_pid(next_pid_);
+ compact_out->set_switch_prev_state(prev_state_);
+ compact_out->set_switch_next_prio(next_prio_);
+ compact_out->set_switch_next_comm_index(next_comm_index_);
+}
+
+void CompactSchedSwitchBuffer::Reset() {
+ last_timestamp_ = 0;
+ timestamp_.Reset();
+ next_pid_.Reset();
+ prev_state_.Reset();
+ next_prio_.Reset();
+ next_comm_index_.Reset();
+}
+
+void CompactSchedWakingBuffer::Write(
+ protos::pbzero::FtraceEventBundle::CompactSched* compact_out) const {
+ compact_out->set_waking_timestamp(timestamp_);
+ compact_out->set_waking_pid(pid_);
+ compact_out->set_waking_target_cpu(target_cpu_);
+ compact_out->set_waking_prio(prio_);
+ compact_out->set_waking_comm_index(comm_index_);
+}
+
+void CompactSchedWakingBuffer::Reset() {
+ last_timestamp_ = 0;
+ timestamp_.Reset();
+ pid_.Reset();
+ target_cpu_.Reset();
+ prio_.Reset();
+ comm_index_.Reset();
+}
+
+void CommInterner::Write(
+ protos::pbzero::FtraceEventBundle::CompactSched* compact_out) const {
+ for (size_t i = 0; i < interned_comms_size_; i++) {
+ compact_out->add_intern_table(interned_comms_[i].data(),
+ interned_comms_[i].size());
+ }
+}
+
+void CommInterner::Reset() {
+ intern_buf_write_pos_ = 0;
+ interned_comms_size_ = 0;
+}
+
+void CompactSchedBuffer::WriteAndReset(
protos::pbzero::FtraceEventBundle* bundle) {
- // If we buffered at least one event (using the interner as a proxy),
- // write the state out.
- if (interned_switch_comms_size_ > 0) {
- auto compact_out = bundle->set_compact_sched();
+ if (switch_.size() > 0 || waking_.size() > 0) {
+ auto* compact_out = bundle->set_compact_sched();
- compact_out->set_switch_timestamp(switch_timestamp_);
- compact_out->set_switch_next_pid(switch_next_pid_);
- compact_out->set_switch_prev_state(switch_prev_state_);
- compact_out->set_switch_next_prio(switch_next_prio_);
+ PERFETTO_DCHECK(interner_.interned_comms_size() > 0);
+ interner_.Write(compact_out);
- for (size_t i = 0; i < interned_switch_comms_size_; i++) {
- compact_out->add_switch_next_comm_table(interned_switch_comms_[i].data(),
- interned_switch_comms_[i].size());
- }
- compact_out->set_switch_next_comm_index(switch_next_comm_index_);
+ if (switch_.size() > 0)
+ switch_.Write(compact_out);
+
+ if (waking_.size() > 0)
+ waking_.Write(compact_out);
}
- // Reset internal state.
- last_switch_timestamp_ = 0;
- switch_timestamp_.Reset();
- switch_next_pid_.Reset();
- switch_prev_state_.Reset();
- switch_next_prio_.Reset();
- switch_next_comm_index_.Reset();
- intern_buf_write_pos_ = 0;
- interned_switch_comms_size_ = 0;
+ interner_.Reset();
+ switch_.Reset();
+ waking_.Reset();
}
} // namespace perfetto
diff --git a/src/traced/probes/ftrace/compact_sched.h b/src/traced/probes/ftrace/compact_sched.h
index 6dc4692..657d651 100644
--- a/src/traced/probes/ftrace/compact_sched.h
+++ b/src/traced/probes/ftrace/compact_sched.h
@@ -28,7 +28,7 @@
class FtraceConfig;
-// The subset of the sched_switch event's format that is used when parsing &
+// The subset of the sched_switch event's format that is used when parsing and
// encoding into the compact format.
struct CompactSchedSwitchFormat {
uint32_t event_id;
@@ -43,6 +43,21 @@
uint16_t next_comm_offset;
};
+// The subset of the sched_waking event's format that is used when parsing and
+// encoding into the compact format.
+struct CompactSchedWakingFormat {
+ uint32_t event_id;
+ uint16_t size;
+
+ uint16_t pid_offset;
+ FtraceFieldType pid_type;
+ uint16_t target_cpu_offset;
+ FtraceFieldType target_cpu_type;
+ uint16_t prio_offset;
+ FtraceFieldType prio_type;
+ uint16_t comm_offset;
+};
+
// Pre-parsed format of a subset of scheduling events, for use during ftrace
// parsing if compact encoding is enabled. Holds a flag, |format_valid| to
// state whether the compile-time assumptions about the format held at runtime.
@@ -50,7 +65,9 @@
struct CompactSchedEventFormat {
// If false, the rest of the struct is considered invalid.
const bool format_valid;
+
const CompactSchedSwitchFormat sched_switch;
+ const CompactSchedWakingFormat sched_waking;
};
CompactSchedEventFormat ValidateFormatForCompactSched(
@@ -62,8 +79,8 @@
struct CompactSchedConfig {
CompactSchedConfig(bool _enabled) : enabled(_enabled) {}
- // If true, and sched_switch event is enabled, encode it in a compact format
- // instead of the normal form.
+ // If true, and sched_switch and/or sched_waking events are enabled, encode
+ // them in a compact format instead of the normal form.
const bool enabled = false;
};
@@ -74,97 +91,145 @@
CompactSchedConfig EnabledCompactSchedConfigForTesting();
CompactSchedConfig DisabledCompactSchedConfigForTesting();
-// Mutable state for buffering parts of scheduling events, that can later be
-// written out in a compact format with |WriteAndReset|. Used by the ftrace
-// reader, allocated on the stack.
-class CompactSchedBundleState {
+// Collects fields of sched_switch events, allowing them to be written out
+// in a compact encoding.
+class CompactSchedSwitchBuffer {
public:
- // Most of the state is stack-allocated, with a compile-time
- // size. We work in batches of pages (see kParsingBufferSizePages in
- // ftrace_controller.cc), and assume a minimum size of a sched event as
- // written by the kernel (validated at runtime). We therefore can calculate
- // the maximum necessary capacity for a given parsing buffer size (as
- // statically asserted in ftrace_controller.cc).
- // Note: be careful not to align the individual buffers at a multiple of the
- // cache size.
- // TODO(rsavitski): this will need a slight rework once we add sched_waking,
- // as it'll be the min size of the two events.
- static constexpr size_t kMaxElements = 2560;
- static constexpr size_t kMinSupportedSchedSwitchSize = 56;
+ protozero::PackedVarInt& timestamp() { return timestamp_; }
+ protozero::PackedVarInt& prev_state() { return prev_state_; }
+ protozero::PackedVarInt& next_pid() { return next_pid_; }
+ protozero::PackedVarInt& next_prio() { return next_prio_; }
+ protozero::PackedVarInt& next_comm_index() { return next_comm_index_; }
+
+ size_t size() const {
+ // Caller should fill all per-field buffers at the same rate.
+ return timestamp_.size();
+ }
+
+ inline void AppendTimestamp(uint64_t timestamp) {
+ timestamp_.Append(timestamp - last_timestamp_);
+ last_timestamp_ = timestamp;
+ }
+
+ void Write(
+ protos::pbzero::FtraceEventBundle::CompactSched* compact_out) const;
+ void Reset();
+
+ private:
+ // First timestamp in a bundle is absolute. The rest are all delta-encoded,
+ // each relative to the preceding sched_switch timestamp.
+ uint64_t last_timestamp_ = 0;
+
+ protozero::PackedVarInt timestamp_;
+ protozero::PackedVarInt prev_state_;
+ protozero::PackedVarInt next_pid_;
+ protozero::PackedVarInt next_prio_;
+ // Interning indices of the next_comm values. See |CommInterner|.
+ protozero::PackedVarInt next_comm_index_;
+};
+
+// As |CompactSchedSwitchBuffer|, but for sched_waking events.
+class CompactSchedWakingBuffer {
+ public:
+ protozero::PackedVarInt& pid() { return pid_; }
+ protozero::PackedVarInt& target_cpu() { return target_cpu_; }
+ protozero::PackedVarInt& prio() { return prio_; }
+ protozero::PackedVarInt& comm_index() { return comm_index_; }
+
+ size_t size() const {
+ // Caller should fill all per-field buffers at the same rate.
+ return timestamp_.size();
+ }
+
+ inline void AppendTimestamp(uint64_t timestamp) {
+ timestamp_.Append(timestamp - last_timestamp_);
+ last_timestamp_ = timestamp;
+ }
+
+ void Write(
+ protos::pbzero::FtraceEventBundle::CompactSched* compact_out) const;
+ void Reset();
+
+ private:
+ uint64_t last_timestamp_ = 0;
+
+ protozero::PackedVarInt timestamp_;
+ protozero::PackedVarInt pid_;
+ protozero::PackedVarInt target_cpu_;
+ protozero::PackedVarInt prio_;
+ // Interning indices of the comm values. See |CommInterner|.
+ protozero::PackedVarInt comm_index_;
+};
+
+class CommInterner {
+ public:
static constexpr size_t kExpectedCommLength = 16;
- protozero::PackedVarInt* switch_timestamp() { return &switch_timestamp_; }
-
- protozero::PackedVarInt* switch_prev_state() { return &switch_prev_state_; }
-
- protozero::PackedVarInt* switch_next_pid() { return &switch_next_pid_; }
-
- protozero::PackedVarInt* switch_next_prio() { return &switch_next_prio_; }
-
- size_t interned_switch_comms_size() const {
- return interned_switch_comms_size_;
- }
-
- inline void AppendSwitchTimestamp(uint64_t timestamp) {
- switch_timestamp_.Append(timestamp - last_switch_timestamp_);
- last_switch_timestamp_ = timestamp;
- }
-
- // TODO(rsavitski): see if we can use the fact that comms are <16 bytes
- // long when comparing them.
- void InternSwitchNextComm(const char* ptr) {
+ size_t InternComm(const char* ptr) {
// Linearly scan existing string views, ftrace reader will
// make sure this set doesn't grow too large.
base::StringView transient_view(ptr);
- for (size_t i = 0; i < interned_switch_comms_size_; i++) {
- if (transient_view == interned_switch_comms_[i]) {
- switch_next_comm_index_.Append(i);
- return;
+ for (size_t i = 0; i < interned_comms_size_; i++) {
+ if (transient_view == interned_comms_[i]) {
+ return i;
}
}
- // Unique next_comm, intern it. Null byte is not copied over.
+ // Unique comm, intern it. Null byte is not copied over.
char* start = intern_buf_ + intern_buf_write_pos_;
size_t size = transient_view.size();
memcpy(start, ptr, size);
intern_buf_write_pos_ += size;
- switch_next_comm_index_.Append(interned_switch_comms_size_);
+ size_t idx = interned_comms_size_;
base::StringView safe_view(start, size);
- interned_switch_comms_[interned_switch_comms_size_++] = safe_view;
+ interned_comms_[interned_comms_size_++] = safe_view;
PERFETTO_DCHECK(intern_buf_write_pos_ <= sizeof(intern_buf_));
+ PERFETTO_DCHECK(interned_comms_size_ < kMaxElements);
+ return idx;
}
+ size_t interned_comms_size() const { return interned_comms_size_; }
+
+ void Write(
+ protos::pbzero::FtraceEventBundle::CompactSched* compact_out) const;
+ void Reset();
+
+ private:
+ // TODO(rsavitski): Consider making the storage dynamically-expandable instead
+ // to not rely on sizing the buffer for the worst case.
+ static constexpr size_t kMaxElements = 4096;
+
+ char intern_buf_[kMaxElements * (kExpectedCommLength - 1)];
+ size_t intern_buf_write_pos_ = 0;
+
+ // Views into unique interned comm strings. Even if every event carries a
+ // unique comm, the ftrace reader is expected to flush the compact buffer way
+ // before this reaches capacity. This is since the cost of processing each
+ // event grows with every unique interned comm (as the interning needs to
+ // search all existing internings).
+ std::array<base::StringView, kMaxElements> interned_comms_;
+ uint32_t interned_comms_size_ = 0;
+};
+
+// Mutable state for buffering parts of scheduling events, that can later be
+// written out in a compact format with |WriteAndReset|. Used by the ftrace
+// reader.
+class CompactSchedBuffer {
+ public:
+ CompactSchedSwitchBuffer& sched_switch() { return switch_; }
+ CompactSchedWakingBuffer& sched_waking() { return waking_; }
+ CommInterner& interner() { return interner_; }
+
// Writes out the currently buffered events, and starts the next batch
// internally.
void WriteAndReset(protos::pbzero::FtraceEventBundle* bundle);
private:
- // First timestamp in a bundle is absolute. The rest are all delta-encoded,
- // each relative to the preceding sched_switch timestamp.
- uint64_t last_switch_timestamp_ = 0;
-
- protozero::PackedVarInt switch_timestamp_;
- protozero::PackedVarInt switch_prev_state_;
- protozero::PackedVarInt switch_next_pid_;
- protozero::PackedVarInt switch_next_prio_;
-
- // Storage for interned strings (without null bytes).
- char intern_buf_[kMaxElements * (kExpectedCommLength - 1)];
- size_t intern_buf_write_pos_ = 0;
-
- // Views into unique interned next_comm strings. Even if every sched_switch
- // carries a unique next_comm, the ftrace reader is expected to flush the
- // compact buffer way before this reaches capacity. This is since the cost of
- // processing each event grows with every unique interned next_comm (as the
- // interning needs to search all existing internings).
- std::array<base::StringView, kMaxElements> interned_switch_comms_;
- uint32_t interned_switch_comms_size_ = 0;
-
- // One entry per sched_switch event, contains the index of the interned
- // next_comm string view (i.e. array index into |interned_switch_comms|).
- protozero::PackedVarInt switch_next_comm_index_;
+ CommInterner interner_;
+ CompactSchedSwitchBuffer switch_;
+ CompactSchedWakingBuffer waking_;
};
} // namespace perfetto
diff --git a/src/traced/probes/ftrace/cpu_reader.cc b/src/traced/probes/ftrace/cpu_reader.cc
index 96f114a..6010e90 100644
--- a/src/traced/probes/ftrace/cpu_reader.cc
+++ b/src/traced/probes/ftrace/cpu_reader.cc
@@ -16,8 +16,8 @@
#include "src/traced/probes/ftrace/cpu_reader.h"
-#include <signal.h>
#include <dirent.h>
+#include <signal.h>
#include <utility>
@@ -279,7 +279,7 @@
const ProtoTranslationTable* table) {
// Begin an FtraceEventBundle, and allocate the buffer for compact scheduler
// events (which will be unused if the compact option isn't enabled).
- CompactSchedBundleState compact_sched;
+ CompactSchedBuffer compact_sched;
auto packet = trace_writer->NewTracePacket();
auto* bundle = packet->set_ftrace_events();
@@ -312,8 +312,9 @@
// a threshold. We need to flush the compact buffer to make the
// interning lookups cheap again.
bool interner_past_threshold =
- compact_sched_enabled && compact_sched.interned_switch_comms_size() >
- kCompactSchedInternerThreshold;
+ compact_sched_enabled &&
+ compact_sched.interner().interned_comms_size() >
+ kCompactSchedInternerThreshold;
if (page_header->lost_events || interner_past_threshold) {
if (compact_sched_enabled)
compact_sched.WriteAndReset(bundle);
@@ -330,9 +331,9 @@
ParsePagePayload(parse_pos, &page_header.value(), table, ds_config,
&compact_sched, bundle, metadata);
- // TODO(b/140866160): compare against header->size once padding size
- // off-by-4 is fixed.
- PERFETTO_DCHECK(evt_size > 0);
+ // TODO(rsavitski): propagate error to trace processor in release builds.
+ // (FtraceMetadata -> FtraceStats in trace).
+ PERFETTO_DCHECK(evt_size == page_header->size);
}
if (compact_sched_enabled)
@@ -398,14 +399,13 @@
// binary ftrace events. See |ParsePageHeader| for the format of the earlier.
//
// This method is deliberately static so it can be tested independently.
-size_t CpuReader::ParsePagePayload(
- const uint8_t* start_of_payload,
- const PageHeader* page_header,
- const ProtoTranslationTable* table,
- const FtraceDataSourceConfig* ds_config,
- CompactSchedBundleState* compact_sched_buffer,
- FtraceEventBundle* bundle,
- FtraceMetadata* metadata) {
+size_t CpuReader::ParsePagePayload(const uint8_t* start_of_payload,
+ const PageHeader* page_header,
+ const ProtoTranslationTable* table,
+ const FtraceDataSourceConfig* ds_config,
+ CompactSchedBuffer* compact_sched_buffer,
+ FtraceEventBundle* bundle,
+ FtraceMetadata* metadata) {
const uint8_t* ptr = start_of_payload;
const uint8_t* const end = ptr + page_header->size;
@@ -429,7 +429,10 @@
uint32_t length;
if (!ReadAndAdvance<uint32_t>(&ptr, end, &length))
return 0;
- ptr += length;
+ // length includes itself (4 bytes)
+ if (length < 4)
+ return 0;
+ ptr += length - 4;
break;
}
case kTypeTimeExtend: {
@@ -484,7 +487,10 @@
bool compact_sched_enabled = ds_config->compact_sched.enabled;
const CompactSchedSwitchFormat& sched_switch_format =
table->compact_sched_format().sched_switch;
+ const CompactSchedWakingFormat& sched_waking_format =
+ table->compact_sched_format().sched_waking;
+ // compact sched_switch
if (compact_sched_enabled &&
ftrace_event_id == sched_switch_format.event_id) {
if (event_size < sched_switch_format.size)
@@ -492,8 +498,18 @@
ParseSchedSwitchCompact(start, timestamp, &sched_switch_format,
compact_sched_buffer, metadata);
+
+ // compact sched_waking
+ } else if (compact_sched_enabled &&
+ ftrace_event_id == sched_waking_format.event_id) {
+ if (event_size < sched_waking_format.size)
+ return 0;
+
+ ParseSchedWakingCompact(start, timestamp, &sched_waking_format,
+ compact_sched_buffer, metadata);
+
} else {
- // Parse all other types of enabled events.
+ // Common case: parse all other types of enabled events.
protos::pbzero::FtraceEvent* event = bundle->add_event();
event->set_timestamp(timestamp);
if (!ParseEvent(ftrace_event_id, start, next, table, event,
@@ -663,31 +679,56 @@
// |CompactSchedSwitchFormat| for the assumptions made around the format, which
// this code is closely tied to.
// static
-void CpuReader::ParseSchedSwitchCompact(
- const uint8_t* start,
- uint64_t timestamp,
- const CompactSchedSwitchFormat* format,
- CompactSchedBundleState* compact_sched_buffer,
- FtraceMetadata* metadata) {
- compact_sched_buffer->AppendSwitchTimestamp(timestamp);
+void CpuReader::ParseSchedSwitchCompact(const uint8_t* start,
+ uint64_t timestamp,
+ const CompactSchedSwitchFormat* format,
+ CompactSchedBuffer* compact_buf,
+ FtraceMetadata* metadata) {
+ compact_buf->sched_switch().AppendTimestamp(timestamp);
int32_t next_pid = ReadValue<int32_t>(start + format->next_pid_offset);
- compact_sched_buffer->switch_next_pid()->Append(next_pid);
+ compact_buf->sched_switch().next_pid().Append(next_pid);
metadata->AddPid(next_pid);
int32_t next_prio = ReadValue<int32_t>(start + format->next_prio_offset);
- compact_sched_buffer->switch_next_prio()->Append(next_prio);
+ compact_buf->sched_switch().next_prio().Append(next_prio);
// Varint encoding of int32 and int64 is the same, so treat the value as
// int64 after reading.
int64_t prev_state = ReadSignedFtraceValue(start + format->prev_state_offset,
format->prev_state_type);
- compact_sched_buffer->switch_prev_state()->Append(prev_state);
+ compact_buf->sched_switch().prev_state().Append(prev_state);
// next_comm
const char* comm_ptr =
reinterpret_cast<const char*>(start + format->next_comm_offset);
- compact_sched_buffer->InternSwitchNextComm(comm_ptr);
+ size_t iid = compact_buf->interner().InternComm(comm_ptr);
+ compact_buf->sched_switch().next_comm_index().Append(iid);
+}
+
+// static
+void CpuReader::ParseSchedWakingCompact(const uint8_t* start,
+ uint64_t timestamp,
+ const CompactSchedWakingFormat* format,
+ CompactSchedBuffer* compact_buf,
+ FtraceMetadata* metadata) {
+ compact_buf->sched_waking().AppendTimestamp(timestamp);
+
+ int32_t pid = ReadValue<int32_t>(start + format->pid_offset);
+ compact_buf->sched_waking().pid().Append(pid);
+ metadata->AddPid(pid);
+
+ int32_t target_cpu = ReadValue<int32_t>(start + format->target_cpu_offset);
+ compact_buf->sched_waking().target_cpu().Append(target_cpu);
+
+ int32_t prio = ReadValue<int32_t>(start + format->prio_offset);
+ compact_buf->sched_waking().prio().Append(prio);
+
+ // comm
+ const char* comm_ptr =
+ reinterpret_cast<const char*>(start + format->comm_offset);
+ size_t iid = compact_buf->interner().InternComm(comm_ptr);
+ compact_buf->sched_waking().comm_index().Append(iid);
}
} // namespace perfetto
diff --git a/src/traced/probes/ftrace/cpu_reader.h b/src/traced/probes/ftrace/cpu_reader.h
index 139eebe..f329044 100644
--- a/src/traced/probes/ftrace/cpu_reader.h
+++ b/src/traced/probes/ftrace/cpu_reader.h
@@ -169,7 +169,7 @@
const PageHeader* page_header,
const ProtoTranslationTable* table,
const FtraceDataSourceConfig* ds_config,
- CompactSchedBundleState* compact_sched_buffer,
+ CompactSchedBuffer* compact_sched_buffer,
FtraceEventBundle* bundle,
FtraceMetadata* metadata);
@@ -198,7 +198,15 @@
static void ParseSchedSwitchCompact(const uint8_t* start,
uint64_t timestamp,
const CompactSchedSwitchFormat* format,
- CompactSchedBundleState* bundle_state,
+ CompactSchedBuffer* compact_buf,
+ FtraceMetadata* metadata);
+
+ // Parse a sched_waking event according to pre-validated format, and buffer
+ // the individual fields in the given compact encoding batch.
+ static void ParseSchedWakingCompact(const uint8_t* start,
+ uint64_t timestamp,
+ const CompactSchedWakingFormat* format,
+ CompactSchedBuffer* compact_buf,
FtraceMetadata* metadata);
// Parses & encodes the given range of contiguous tracing pages. Called by
diff --git a/src/traced/probes/ftrace/cpu_reader_benchmark.cc b/src/traced/probes/ftrace/cpu_reader_benchmark.cc
index b4d942f..58b4e20 100644
--- a/src/traced/probes/ftrace/cpu_reader_benchmark.cc
+++ b/src/traced/probes/ftrace/cpu_reader_benchmark.cc
@@ -289,7 +289,7 @@
} // namespace
-using perfetto::CompactSchedBundleState;
+using perfetto::CompactSchedBuffer;
using perfetto::CpuReader;
using perfetto::DisabledCompactSchedConfigForTesting;
using perfetto::EventFilter;
@@ -324,7 +324,7 @@
while (state.KeepRunning()) {
writer.Reset(&stream);
- CompactSchedBundleState compact_buffer;
+ CompactSchedBuffer compact_buffer;
const uint8_t* parse_pos = page.get();
perfetto::base::Optional<CpuReader::PageHeader> page_header =
CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
diff --git a/src/traced/probes/ftrace/cpu_reader_unittest.cc b/src/traced/probes/ftrace/cpu_reader_unittest.cc
index d008744..f8b58cf 100644
--- a/src/traced/probes/ftrace/cpu_reader_unittest.cc
+++ b/src/traced/probes/ftrace/cpu_reader_unittest.cc
@@ -381,7 +381,7 @@
table->EventToFtraceId(GroupAndName("ftrace", "print")));
FtraceMetadata metadata{};
- CompactSchedBundleState compact_buffer;
+ CompactSchedBuffer compact_buffer;
const uint8_t* parse_pos = page.get();
base::Optional<CpuReader::PageHeader> page_header =
CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
@@ -510,7 +510,7 @@
table->EventToFtraceId(GroupAndName("ftrace", "print")));
FtraceMetadata metadata{};
- CompactSchedBundleState compact_buffer;
+ CompactSchedBuffer compact_buffer;
const uint8_t* parse_pos = page.get();
base::Optional<CpuReader::PageHeader> page_header =
CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
@@ -560,7 +560,7 @@
table->EventToFtraceId(GroupAndName("ftrace", "print")));
FtraceMetadata metadata{};
- CompactSchedBundleState compact_buffer;
+ CompactSchedBuffer compact_buffer;
const uint8_t* parse_pos = page.get();
base::Optional<CpuReader::PageHeader> page_header =
CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
@@ -599,7 +599,7 @@
DisabledCompactSchedConfigForTesting()};
FtraceMetadata metadata{};
- CompactSchedBundleState compact_buffer;
+ CompactSchedBuffer compact_buffer;
const uint8_t* parse_pos = page.get();
base::Optional<CpuReader::PageHeader> page_header =
CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
@@ -665,7 +665,7 @@
table->EventToFtraceId(GroupAndName("ftrace", "print")));
FtraceMetadata metadata{};
- CompactSchedBundleState compact_buffer;
+ CompactSchedBuffer compact_buffer;
const uint8_t* parse_pos = page.get();
base::Optional<CpuReader::PageHeader> page_header =
CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
@@ -775,7 +775,7 @@
table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
FtraceMetadata metadata{};
- CompactSchedBundleState compact_buffer;
+ CompactSchedBuffer compact_buffer;
const uint8_t* parse_pos = page.get();
base::Optional<CpuReader::PageHeader> page_header =
CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
@@ -822,7 +822,7 @@
table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
FtraceMetadata metadata{};
- CompactSchedBundleState compact_buffer;
+ CompactSchedBuffer compact_buffer;
const uint8_t* parse_pos = page.get();
base::Optional<CpuReader::PageHeader> page_header =
CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
@@ -846,7 +846,8 @@
EXPECT_FALSE(bundle->has_compact_sched());
// Instead, sched switch fields were buffered:
- EXPECT_LT(0u, compact_buffer.interned_switch_comms_size());
+ EXPECT_LT(0u, compact_buffer.sched_switch().size());
+ EXPECT_LT(0u, compact_buffer.interner().interned_comms_size());
// Write the buffer out & check the serialized format:
compact_buffer.WriteAndReset(bundle_provider.writer());
@@ -861,7 +862,7 @@
EXPECT_EQ(6, compact_sched.switch_next_pid().size());
EXPECT_EQ(6, compact_sched.switch_next_prio().size());
// 4 unique interned next_comm strings:
- EXPECT_EQ(4, compact_sched.switch_next_comm_table().size());
+ EXPECT_EQ(4, compact_sched.intern_table().size());
EXPECT_EQ(6, compact_sched.switch_next_comm_index().size());
// First event exactly as expected (absolute timestamp):
@@ -870,7 +871,7 @@
EXPECT_EQ(1, compact_sched.switch_prev_state(0));
EXPECT_EQ(3733, compact_sched.switch_next_pid(0));
EXPECT_EQ(120, compact_sched.switch_next_prio(0));
- std::string next_comm = compact_sched.switch_next_comm_table(
+ std::string next_comm = compact_sched.intern_table(
static_cast<int>(compact_sched.switch_next_comm_index(0)));
EXPECT_EQ("sleep", next_comm);
}
@@ -1620,7 +1621,7 @@
table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
FtraceMetadata metadata{};
- CompactSchedBundleState compact_buffer;
+ CompactSchedBuffer compact_buffer;
const uint8_t* parse_pos = page.get();
base::Optional<CpuReader::PageHeader> page_header =
CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
@@ -2065,7 +2066,7 @@
table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
FtraceMetadata metadata{};
- CompactSchedBundleState compact_buffer;
+ CompactSchedBuffer compact_buffer;
const uint8_t* parse_pos = page.get();
base::Optional<CpuReader::PageHeader> page_header =
CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc b/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
index 8901cb5..890e07a 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
@@ -661,8 +661,9 @@
TEST_F(FtraceConfigMuxerTest, CompactSchedConfig) {
// Set scheduling event format as validated. The pre-parsed format itself
// doesn't need to be sensible, as the tests won't use it.
- auto valid_compact_format = CompactSchedEventFormat{
- /*format_valid=*/true, CompactSchedSwitchFormat{}};
+ auto valid_compact_format =
+ CompactSchedEventFormat{/*format_valid=*/true, CompactSchedSwitchFormat{},
+ CompactSchedWakingFormat{}};
NiceMock<MockFtraceProcfs> ftrace;
table_ = CreateFakeTable(valid_compact_format);
diff --git a/src/traced/probes/ftrace/ftrace_controller.cc b/src/traced/probes/ftrace/ftrace_controller.cc
index 0732527..a66ed05 100644
--- a/src/traced/probes/ftrace/ftrace_controller.cc
+++ b/src/traced/probes/ftrace/ftrace_controller.cc
@@ -34,7 +34,6 @@
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/metatrace.h"
#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "src/traced/probes/ftrace/compact_sched.h"
#include "src/traced/probes/ftrace/cpu_reader.h"
#include "src/traced/probes/ftrace/cpu_stats_parser.h"
#include "src/traced/probes/ftrace/event_info.h"
@@ -64,21 +63,10 @@
// data, which should fit in a typical L2D cache. Furthermore, the batching
// limits the memory usage of traced_probes.
//
-// Note that the compact scheduler event encoding buffers operate on the same
-// buffer size, and their maximum capacity is set at compile-time as it lives on
-// the stack. So the maximum possible number of events encoded in this many
-// tracing pages must not exceed compact_sched's capacity. See the static_assert
-// below.
// TODO(rsavitski): consider making buffering & parsing page counts independent,
// should be a single counter in the cpu_reader, similar to lost_events case.
constexpr size_t kParsingBufferSizePages = 32;
-static_assert(kParsingBufferSizePages *
- (base::kPageSize /
- CompactSchedBundleState::kMinSupportedSchedSwitchSize) <=
- CompactSchedBundleState::kMaxElements,
- "insufficient compact_sched buffer capacity");
-
uint32_t ClampDrainPeriodMs(uint32_t drain_period_ms) {
if (drain_period_ms == 0) {
return kDefaultDrainPeriodMs;
diff --git a/src/traced/probes/ftrace/proto_translation_table_unittest.cc b/src/traced/probes/ftrace/proto_translation_table_unittest.cc
index f3841d9..8f54e48 100644
--- a/src/traced/probes/ftrace/proto_translation_table_unittest.cc
+++ b/src/traced/probes/ftrace/proto_translation_table_unittest.cc
@@ -259,9 +259,10 @@
INSTANTIATE_TEST_SUITE_P(BySize, TranslationTableCreationTest, Values(4, 8));
-TEST(TranslationTableTest, CompactSchedFormatParsingSeedData) {
+TEST(TranslationTableTest, CompactSchedFormatParsingWalleyeData) {
std::string path =
- "src/traced/probes/ftrace/test/data/android_seed_N2F62_3.10.49/";
+ "src/traced/probes/ftrace/test/data/"
+ "android_walleye_OPM5.171019.017.A1_4.4.88/";
FtraceProcfs ftrace_procfs(path);
auto table = ProtoTranslationTable::Create(
&ftrace_procfs, GetStaticEventInfo(), GetStaticCommonFieldsInfo());
@@ -271,30 +272,7 @@
// Format matches compile-time assumptions.
ASSERT_TRUE(format.format_valid);
- // Check exact format (note: 32 bit long prev_state).
- EXPECT_EQ(68u, format.sched_switch.event_id);
- EXPECT_EQ(60u, format.sched_switch.size);
- EXPECT_EQ(52u, format.sched_switch.next_pid_offset);
- EXPECT_EQ(FtraceFieldType::kFtracePid32, format.sched_switch.next_pid_type);
- EXPECT_EQ(56u, format.sched_switch.next_prio_offset);
- EXPECT_EQ(FtraceFieldType::kFtraceInt32, format.sched_switch.next_prio_type);
- EXPECT_EQ(32u, format.sched_switch.prev_state_offset);
- EXPECT_EQ(FtraceFieldType::kFtraceInt32, format.sched_switch.prev_state_type);
- EXPECT_EQ(36u, format.sched_switch.next_comm_offset);
-}
-
-TEST(TranslationTableTest, CompactSchedFormatParsingSyntheticData) {
- std::string path = "src/traced/probes/ftrace/test/data/synthetic/";
- FtraceProcfs ftrace_procfs(path);
- auto table = ProtoTranslationTable::Create(
- &ftrace_procfs, GetStaticEventInfo(), GetStaticCommonFieldsInfo());
- PERFETTO_CHECK(table);
- const CompactSchedEventFormat& format = table->compact_sched_format();
-
- // Format matches compile-time assumptions.
- ASSERT_TRUE(format.format_valid);
-
- // Check exact format (note: 64 bit long prev_state).
+ // Check exact sched_switch format (note: 64 bit long prev_state).
EXPECT_EQ(47u, format.sched_switch.event_id);
EXPECT_EQ(64u, format.sched_switch.size);
EXPECT_EQ(56u, format.sched_switch.next_pid_offset);
@@ -304,6 +282,33 @@
EXPECT_EQ(32u, format.sched_switch.prev_state_offset);
EXPECT_EQ(FtraceFieldType::kFtraceInt64, format.sched_switch.prev_state_type);
EXPECT_EQ(40u, format.sched_switch.next_comm_offset);
+
+ // Check exact sched_waking format.
+ EXPECT_EQ(44u, format.sched_waking.event_id);
+ EXPECT_EQ(40u, format.sched_waking.size);
+ EXPECT_EQ(24u, format.sched_waking.pid_offset);
+ EXPECT_EQ(FtraceFieldType::kFtracePid32, format.sched_waking.pid_type);
+ EXPECT_EQ(36u, format.sched_waking.target_cpu_offset);
+ EXPECT_EQ(FtraceFieldType::kFtraceInt32, format.sched_waking.target_cpu_type);
+ EXPECT_EQ(28u, format.sched_waking.prio_offset);
+ EXPECT_EQ(FtraceFieldType::kFtraceInt32, format.sched_waking.prio_type);
+ EXPECT_EQ(8u, format.sched_waking.comm_offset);
+}
+
+TEST(TranslationTableTest, CompactSchedFormatParsingSeedData) {
+ std::string path =
+ "src/traced/probes/ftrace/test/data/android_seed_N2F62_3.10.49/";
+ FtraceProcfs ftrace_procfs(path);
+ auto table = ProtoTranslationTable::Create(
+ &ftrace_procfs, GetStaticEventInfo(), GetStaticCommonFieldsInfo());
+ PERFETTO_CHECK(table);
+ const CompactSchedEventFormat& format = table->compact_sched_format();
+
+ // We consider the entire format invalid as there's no sched_waking event
+ // available. This is a simplifying assumption. We could instead look at each
+ // event independently (and in this case, sched_switch does match compile-time
+ // assumptions).
+ ASSERT_FALSE(format.format_valid);
}
TEST(TranslationTableTest, InferFtraceType) {
diff --git a/src/traced/probes/ftrace/test/data/synthetic/available_events b/src/traced/probes/ftrace/test/data/synthetic/available_events
index 0a0ea6f..28798fa 100644
--- a/src/traced/probes/ftrace/test/data/synthetic/available_events
+++ b/src/traced/probes/ftrace/test/data/synthetic/available_events
@@ -1,4 +1,5 @@
sched:sched_switch
+sched:sched_waking
kmem:ion_heap_grow
kmem:ion_heap_shrink
kmem:rss_stat
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/sched/sched_waking/format b/src/traced/probes/ftrace/test/data/synthetic/events/sched/sched_waking/format
new file mode 100644
index 0000000..57bd43f
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/synthetic/events/sched/sched_waking/format
@@ -0,0 +1,15 @@
+name: sched_waking
+ID: 44
+format:
+ field:unsigned short common_type; offset:0; size:2; signed:0;
+ field:unsigned char common_flags; offset:2; size:1; signed:0;
+ field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
+ field:int common_pid; offset:4; size:4; signed:1;
+
+ field:char comm[16]; offset:8; size:16; signed:0;
+ field:pid_t pid; offset:24; size:4; signed:1;
+ field:int prio; offset:28; size:4; signed:1;
+ field:int success; offset:32; size:4; signed:1;
+ field:int target_cpu; offset:36; size:4; signed:1;
+
+print fmt: "comm=%s pid=%d prio=%d target_cpu=%03d", REC->comm, REC->pid, REC->prio, REC->target_cpu
diff --git a/src/traced/probes/power/android_power_data_source.h b/src/traced/probes/power/android_power_data_source.h
index c4efd39..e178fc5 100644
--- a/src/traced/probes/power/android_power_data_source.h
+++ b/src/traced/probes/power/android_power_data_source.h
@@ -27,7 +27,6 @@
namespace perfetto {
-class DataSourceConfig;
class TraceWriter;
namespace base {
class TaskRunner;
diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn
index 9c58d68..844da88 100644
--- a/src/tracing/BUILD.gn
+++ b/src/tracing/BUILD.gn
@@ -50,7 +50,6 @@
"core/shared_memory_abi.cc",
"core/shared_memory_arbiter_impl.cc",
"core/shared_memory_arbiter_impl.h",
- "core/sliced_protobuf_input_stream.cc",
"core/startup_trace_writer.cc",
"core/startup_trace_writer_registry.cc",
"core/trace_buffer.cc",
@@ -64,9 +63,30 @@
]
}
+# TODO(primiano): Remove this target as soon as chromium's
+# track_event_json_exporter.cc (which is the only user of this file) is no more.
+# This causes a dependency on libprotobuf, which we want to avoid for our
+# codebase.
+source_set("sliced_protobuf_input_stream") {
+ public_deps = [
+ "../../include/perfetto/base",
+ "../../include/perfetto/ext/tracing/core",
+ "../../protos/perfetto/common:lite",
+ ]
+ deps = [
+ ":tracing",
+ "../../gn:default_deps",
+ ]
+ sources = [
+ "../../include/perfetto/ext/tracing/core/sliced_protobuf_input_stream.h",
+ "core/sliced_protobuf_input_stream.cc",
+ ]
+}
+
perfetto_unittest_source_set("unittests") {
testonly = true
deps = [
+ ":sliced_protobuf_input_stream",
":test_support",
":tracing",
"../../gn:default_deps",
diff --git a/src/tracing/api_integrationtest.cc b/src/tracing/api_integrationtest.cc
index dee34a4..44fa477 100644
--- a/src/tracing/api_integrationtest.cc
+++ b/src/tracing/api_integrationtest.cc
@@ -311,6 +311,74 @@
return log_messages;
}
+ std::vector<std::string> ReadSlicesFromTrace(
+ perfetto::TracingSession* tracing_session) {
+ std::vector<char> raw_trace = tracing_session->ReadTraceBlocking();
+ EXPECT_GE(raw_trace.size(), 0u);
+
+ // Read back the trace, maintaining interning tables as we go.
+ std::vector<std::string> slices;
+ std::map<uint64_t, std::string> categories;
+ std::map<uint64_t, std::string> event_names;
+ perfetto::protos::Trace parsed_trace;
+ EXPECT_TRUE(
+ parsed_trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+
+ bool incremental_state_was_cleared = false;
+ uint32_t sequence_id = 0;
+ for (const auto& packet : parsed_trace.packet()) {
+ if (packet.incremental_state_cleared()) {
+ incremental_state_was_cleared = true;
+ categories.clear();
+ event_names.clear();
+ }
+
+ if (!packet.has_track_event())
+ continue;
+
+ // Make sure we only see track events on one sequence.
+ if (packet.trusted_packet_sequence_id()) {
+ if (!sequence_id)
+ sequence_id = packet.trusted_packet_sequence_id();
+ EXPECT_EQ(sequence_id, packet.trusted_packet_sequence_id());
+ }
+
+ // Update incremental state.
+ if (packet.has_interned_data()) {
+ const auto& interned_data = packet.interned_data();
+ for (const auto& it : interned_data.event_categories()) {
+ EXPECT_EQ(categories.find(it.iid()), categories.end());
+ categories[it.iid()] = it.name();
+ }
+ for (const auto& it : interned_data.event_names()) {
+ EXPECT_EQ(event_names.find(it.iid()), event_names.end());
+ event_names[it.iid()] = it.name();
+ }
+ }
+ const auto& track_event = packet.track_event();
+ std::string slice;
+ switch (track_event.type()) {
+ case perfetto::protos::TrackEvent::TYPE_SLICE_BEGIN:
+ slice += "B";
+ break;
+ case perfetto::protos::TrackEvent::TYPE_SLICE_END:
+ slice += "E";
+ break;
+ case perfetto::protos::TrackEvent::TYPE_INSTANT:
+ slice += "I";
+ break;
+ default:
+ case perfetto::protos::TrackEvent::TYPE_UNSPECIFIED:
+ EXPECT_FALSE(track_event.type());
+ }
+ slice += ":" + categories[track_event.category_iids().Get(0)] + "." +
+ event_names[track_event.name_iid()];
+ slices.push_back(slice);
+ }
+ EXPECT_TRUE(incremental_state_was_cleared);
+ return slices;
+ }
+
std::map<std::string, TestDataSourceHandle> data_sources_;
std::list<TestTracingSessionHandle> sessions_; // Needs stable pointers.
};
@@ -994,6 +1062,64 @@
ElementsAre("SomeFunction(file.cc:123): To be, or not to be"));
}
+TEST_F(PerfettoApiTest, TrackEventScoped) {
+ // Setup the trace config.
+ perfetto::TraceConfig cfg;
+ cfg.set_duration_ms(500);
+ cfg.add_buffers()->set_size_kb(1024);
+ auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+ ds_cfg->set_name("track_event");
+ ds_cfg->set_legacy_config("test");
+
+ // Create a new trace session.
+ auto* tracing_session = NewTrace(cfg);
+ tracing_session->get()->StartBlocking();
+
+ {
+ uint64_t arg = 123;
+ TRACE_EVENT("test", "TestEventWithArgs",
+ [&](perfetto::TrackEventContext ctx) {
+ ctx.track_event()->set_log_message()->set_body_iid(arg);
+ });
+ }
+
+ {
+ // Make sure you can have multiple scoped events in the same scope.
+ TRACE_EVENT("test", "TestEvent");
+ TRACE_EVENT("test", "AnotherEvent");
+ TRACE_EVENT("foo", "DisabledEvent");
+ }
+ perfetto::TrackEvent::Flush();
+
+ tracing_session->get()->StopBlocking();
+ auto slices = ReadSlicesFromTrace(tracing_session->get());
+ EXPECT_THAT(slices, ElementsAre("B:test.TestEventWithArgs", "E:test.",
+ "B:test.TestEvent", "B:test.AnotherEvent",
+ "E:test.", "E:test."));
+}
+
+TEST_F(PerfettoApiTest, TrackEventInstant) {
+ // Setup the trace config.
+ perfetto::TraceConfig cfg;
+ cfg.set_duration_ms(500);
+ cfg.add_buffers()->set_size_kb(1024);
+ auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+ ds_cfg->set_name("track_event");
+ ds_cfg->set_legacy_config("test");
+
+ // Create a new trace session.
+ auto* tracing_session = NewTrace(cfg);
+ tracing_session->get()->StartBlocking();
+
+ TRACE_EVENT_INSTANT("test", "TestEvent");
+ TRACE_EVENT_INSTANT("test", "AnotherEvent");
+ perfetto::TrackEvent::Flush();
+
+ tracing_session->get()->StopBlocking();
+ auto slices = ReadSlicesFromTrace(tracing_session->get());
+ EXPECT_THAT(slices, ElementsAre("I:test.TestEvent", "I:test.AnotherEvent"));
+}
+
TEST_F(PerfettoApiTest, OneDataSourceOneEvent) {
auto* data_source = &data_sources_["my_data_source"];
diff --git a/src/tracing/test/tracing_module.cc b/src/tracing/test/tracing_module.cc
index 731d68b..4b0283e 100644
--- a/src/tracing/test/tracing_module.cc
+++ b/src/tracing/test/tracing_module.cc
@@ -69,4 +69,11 @@
puts("Hello");
}
+void FunctionWithOneScopedTrackEvent() {
+ TRACE_EVENT("cat1", "ScopedEventFromModule");
+ // Simulates the non-tracing work of this function, which should take priority
+ // over the above trace event in terms of instruction scheduling.
+ puts("Hello");
+}
+
} // namespace tracing_module
diff --git a/src/tracing/test/tracing_module.h b/src/tracing/test/tracing_module.h
index 73ac7fd..bb255a1 100644
--- a/src/tracing/test/tracing_module.h
+++ b/src/tracing/test/tracing_module.h
@@ -35,6 +35,7 @@
// These functions are used to check the instruction size overhead track events.
void FunctionWithOneTrackEvent();
void FunctionWithOneTrackEventWithTypedArgument();
+void FunctionWithOneScopedTrackEvent();
} // namespace tracing_module
diff --git a/test/cts/heapprofd_java_test_cts.cc b/test/cts/heapprofd_java_test_cts.cc
index a1a6108..8ac3760 100644
--- a/test/cts/heapprofd_java_test_cts.cc
+++ b/test/cts/heapprofd_java_test_cts.cc
@@ -52,7 +52,7 @@
helper.WaitForConsumerConnect();
TraceConfig trace_config;
- trace_config.add_buffers()->set_size_kb(10 * 1024);
+ trace_config.add_buffers()->set_size_kb(20 * 1024);
trace_config.set_duration_ms(6000);
auto* ds_config = trace_config.add_data_sources()->mutable_config();
@@ -68,7 +68,8 @@
helper.WaitForTracingDisabled(10000 /*ms*/);
helper.ReadData();
helper.WaitForReadData();
-
+ StopApp(app_name, "new.app.stopped", &task_runner);
+ task_runner.RunUntilCheckpoint("new.app.stopped", 1000 /*ms*/);
return helper.trace();
}
@@ -99,14 +100,12 @@
std::string app_name = "android.perfetto.cts.app.debuggable";
const auto& packets = ProfileRuntime(app_name);
AssertGraphPresent(packets);
- StopApp(app_name);
}
TEST(HeapprofdJavaCtsTest, ProfileableAppRuntime) {
std::string app_name = "android.perfetto.cts.app.profileable";
const auto& packets = ProfileRuntime(app_name);
AssertGraphPresent(packets);
- StopApp(app_name);
}
TEST(HeapprofdJavaCtsTest, ReleaseAppRuntime) {
@@ -117,8 +116,6 @@
AssertGraphPresent(packets);
else
AssertNoProfileContents(packets);
-
- StopApp(app_name);
}
} // namespace
diff --git a/test/metrics/heap_profile_callsites.out b/test/metrics/heap_profile_callsites.out
index 6a975bb..5f8c14c 100644
--- a/test/metrics/heap_profile_callsites.out
+++ b/test/metrics/heap_profile_callsites.out
@@ -58,5 +58,7 @@
delta_bytes: 1090
}
}
+ profile_delta_bytes: 1090
+ profile_total_bytes: 2100
}
}
diff --git a/test/metrics/index b/test/metrics/index
index a159f21..8f29693 100644
--- a/test/metrics/index
+++ b/test/metrics/index
@@ -21,5 +21,7 @@
heap_profile.textproto heap_profile_callsites heap_profile_callsites.out
heap_profile_no_symbols.textproto unsymbolized_frames unsymbolized_frames.out
+../trace_processor/heap_graph.textproto java_heap_stats java_heap_stats.out
+
# Json output
../data/memory_counters.pb trace_metadata trace_metadata.json.out
diff --git a/test/metrics/java_heap_stats.out b/test/metrics/java_heap_stats.out
new file mode 100644
index 0000000..64db708
--- /dev/null
+++ b/test/metrics/java_heap_stats.out
@@ -0,0 +1,11 @@
+java_heap_stats {
+ instance_stats {
+ upid: 2
+ process_name: "system_server"
+ samples {
+ ts: 10
+ heap_size: 224
+ reachable_heap_size: 96
+ }
+ }
+}
diff --git a/test/trace_processor/heap_graph.textproto b/test/trace_processor/heap_graph.textproto
index eb32c54..b785578 100644
--- a/test/trace_processor/heap_graph.textproto
+++ b/test/trace_processor/heap_graph.textproto
@@ -16,6 +16,7 @@
trusted_packet_sequence_id: 999
timestamp: 10
heap_graph {
+ pid: 2
roots {
root_type: ROOT_JAVA_FRAME
object_ids: 0x01
@@ -32,12 +33,18 @@
type_id: 2
self_size: 32
}
+ objects {
+ id: 0x03
+ type_id: 2
+ self_size: 128
+ }
continued: true
index: 1
}
}
packet {
heap_graph {
+ pid: 2
type_names {
iid: 1
str: "FactoryProducerDelegateImplActor"
diff --git a/test/trace_processor/heap_graph_object.out b/test/trace_processor/heap_graph_object.out
index 48bc6b9..b0f9e43 100644
--- a/test/trace_processor/heap_graph_object.out
+++ b/test/trace_processor/heap_graph_object.out
@@ -1,3 +1,4 @@
"id","type","upid","graph_sample_ts","object_id","self_size","retained_size","unique_retained_size","reference_set_id","reachable","type_name","root_type"
-0,"heap_graph_object",0,10,1,64,96,96,0,1,"FactoryProducerDelegateImplActor","ROOT_JAVA_FRAME"
-1,"heap_graph_object",0,10,2,32,32,32,1,1,"Foo","[NULL]"
+0,"heap_graph_object",2,10,1,64,96,96,0,1,"FactoryProducerDelegateImplActor","ROOT_JAVA_FRAME"
+1,"heap_graph_object",2,10,2,32,32,32,1,1,"Foo","[NULL]"
+2,"heap_graph_object",2,10,3,128,-1,0,1,0,"Foo","[NULL]"
diff --git a/test/trace_processor/index b/test/trace_processor/index
index bf3c781..958b11e 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -149,3 +149,8 @@
# Config
config.textproto metadata.sql config_metadata.out
+
+# Decoding of sched_waking events from a trace with compact scheduling events.
+# Verifies the contents of raw & instants tables.
+../data/compact_sched.pb sched_waking_raw.sql sched_waking_raw_compact_sched.out
+../data/compact_sched.pb sched_waking_instants.sql sched_waking_instants_compact_sched.out
diff --git a/test/trace_processor/sched_waking_instants.sql b/test/trace_processor/sched_waking_instants.sql
new file mode 100644
index 0000000..1fe4a76
--- /dev/null
+++ b/test/trace_processor/sched_waking_instants.sql
@@ -0,0 +1 @@
+SELECT ts, instants.name, thread.name, thread.tid FROM instants JOIN thread ON instants.ref == thread.utid WHERE instants.name == "sched_waking" ORDER BY ts ASC
diff --git a/test/trace_processor/sched_waking_instants_compact_sched.out b/test/trace_processor/sched_waking_instants_compact_sched.out
new file mode 100644
index 0000000..201d48b
--- /dev/null
+++ b/test/trace_processor/sched_waking_instants_compact_sched.out
@@ -0,0 +1,82 @@
+"ts","name","name","tid"
+250978439491994,"sched_waking","rcu_sched",8
+250978441664547,"sched_waking","ksoftirqd/1",18
+250978441702515,"sched_waking","kworker/u16:18",17473
+250978444958245,"sched_waking","rcuop/0",10
+250978444974443,"sched_waking","rcuop/1",21
+250978444984234,"sched_waking","rcu_preempt",7
+250978445783141,"sched_waking","rcu_sched",8
+250978451590173,"sched_waking","rcu_preempt",7
+250978451591891,"sched_waking","rcu_sched",8
+250978451609131,"sched_waking","kworker/u16:18",17473
+250978451646579,"sched_waking","rcuos/0",11
+250978451716891,"sched_waking","rcuos/1",22
+250978452047048,"sched_waking","kworker/u16:18",17473
+250978458337725,"sched_waking","sugov:0",625
+250978458362100,"sched_waking","rcu_preempt",7
+250978458398455,"sched_waking","rcuop/0",10
+250978458419496,"sched_waking","rcuop/1",21
+250978459118038,"sched_waking","sugov:0",625
+250978465172309,"sched_waking","ksoftirqd/3",34
+250978465266789,"sched_waking","kworker/u16:18",17473
+250978593466697,"sched_waking","kworker/2:0",17438
+250978593734510,"sched_waking","kworker/u16:18",17473
+250978595521125,"sched_waking","kworker/2:3",17754
+250978595696645,"sched_waking","kworker/2:0",17438
+250978596068468,"sched_waking","kworker/2:3",17754
+250978596565656,"sched_waking","kworker/2:0",17438
+250978600598417,"sched_waking","kworker/2:0",17438
+250978600639042,"sched_waking","ksoftirqd/0",6
+250978604651907,"sched_waking","ksoftirqd/0",6
+250978604739980,"sched_waking","kworker/2:0",17438
+250978605185448,"sched_waking","ksoftirqd/2",26
+250978605260240,"sched_waking","kworker/u16:18",17473
+250978608903886,"sched_waking","kworker/2:0",17438
+250978608942220,"sched_waking","ksoftirqd/0",6
+250978612887272,"sched_waking","ksoftirqd/0",6
+250978612971283,"sched_waking","kworker/2:0",17438
+250978616876595,"sched_waking","kworker/2:0",17438
+250978616921700,"sched_waking","ksoftirqd/0",6
+250978617016804,"sched_waking","kworker/u16:18",17473
+250978620859669,"sched_waking","ksoftirqd/0",6
+250978620939148,"sched_waking","kworker/2:0",17438
+250978624836805,"sched_waking","kworker/2:0",17438
+250978624875398,"sched_waking","ksoftirqd/0",6
+250978624978003,"sched_waking","kworker/u16:18",17473
+250978628278107,"sched_waking","logd.klogd",651
+250978629289722,"sched_waking","rcuop/2",29
+250978629405763,"sched_waking","rcu_preempt",7
+250978635024462,"sched_waking","rcu_preempt",7
+250978635060191,"sched_waking","kworker/u16:18",17473
+250978635219514,"sched_waking","rcuop/2",29
+250978683441081,"sched_waking","kworker/2:0",17438
+250978683732331,"sched_waking","kworker/u16:18",17473
+250978685694259,"sched_waking","kworker/u16:18",17473
+250978740127441,"sched_waking","kworker/2:0",17438
+250978740425410,"sched_waking","kworker/u16:18",17473
+250978743210358,"sched_waking","kworker/u16:18",17473
+250978744945567,"sched_waking","logd.klogd",651
+250978746028431,"sched_waking","rcuop/2",29
+250978746173171,"sched_waking","rcu_preempt",7
+250978751622494,"sched_waking","rcu_preempt",7
+250978751661348,"sched_waking","kworker/u16:18",17473
+250978751792859,"sched_waking","rcuop/2",29
+250978751971817,"sched_waking","rcu_preempt",7
+250978758784578,"sched_waking","rcu_preempt",7
+250978758873745,"sched_waking","rcuop/2",29
+250978805144375,"sched_waking","traced_probes",17772
+250978806359896,"sched_waking","kworker/5:1",17667
+250978806428646,"sched_waking","kworker/u16:18",17473
+250978808058698,"sched_waking","rcuop/0",10
+250978808519271,"sched_waking","rcu_preempt",7
+250978815488490,"sched_waking","rcu_preempt",7
+250978815535678,"sched_waking","kworker/u16:18",17473
+250978815675782,"sched_waking","rcuop/0",10
+250978815738022,"sched_waking","rcuop/1",21
+250978860203182,"sched_waking","kworker/u16:18",17473
+250978880151205,"sched_waking","kworker/2:0",17438
+250978880432143,"sched_waking","kworker/u16:18",17473
+250978884120216,"sched_waking","traced",17771
+250978885260685,"sched_waking","rcuop/0",10
+250978885784018,"sched_waking","rcu_preempt",7
+250978885786674,"sched_waking","traced_probes",17772
diff --git a/test/trace_processor/sched_waking_raw.sql b/test/trace_processor/sched_waking_raw.sql
new file mode 100644
index 0000000..259e2fe
--- /dev/null
+++ b/test/trace_processor/sched_waking_raw.sql
@@ -0,0 +1 @@
+SELECT ts, name, cpu, key, int_value, string_value FROM raw JOIN args ON raw.arg_set_id == args.arg_set_id WHERE name == "sched_waking" ORDER BY cpu ASC, ts ASC;
diff --git a/test/trace_processor/sched_waking_raw_compact_sched.out b/test/trace_processor/sched_waking_raw_compact_sched.out
new file mode 100644
index 0000000..7067a25
--- /dev/null
+++ b/test/trace_processor/sched_waking_raw_compact_sched.out
@@ -0,0 +1,406 @@
+"ts","name","cpu","key","int_value","string_value"
+250978451591891,"sched_waking",0,"comm","[NULL]","rcu_sched"
+250978451591891,"sched_waking",0,"pid",8,"[NULL]"
+250978451591891,"sched_waking",0,"prio",120,"[NULL]"
+250978451591891,"sched_waking",0,"success",1,"[NULL]"
+250978451591891,"sched_waking",0,"target_cpu",0,"[NULL]"
+250978451609131,"sched_waking",0,"comm","[NULL]","kworker/u16:18"
+250978451609131,"sched_waking",0,"pid",17473,"[NULL]"
+250978451609131,"sched_waking",0,"prio",120,"[NULL]"
+250978451609131,"sched_waking",0,"success",1,"[NULL]"
+250978451609131,"sched_waking",0,"target_cpu",0,"[NULL]"
+250978596565656,"sched_waking",0,"comm","[NULL]","kworker/2:0"
+250978596565656,"sched_waking",0,"pid",17438,"[NULL]"
+250978596565656,"sched_waking",0,"prio",120,"[NULL]"
+250978596565656,"sched_waking",0,"success",1,"[NULL]"
+250978596565656,"sched_waking",0,"target_cpu",2,"[NULL]"
+250978600598417,"sched_waking",0,"comm","[NULL]","kworker/2:0"
+250978600598417,"sched_waking",0,"pid",17438,"[NULL]"
+250978600598417,"sched_waking",0,"prio",120,"[NULL]"
+250978600598417,"sched_waking",0,"success",1,"[NULL]"
+250978600598417,"sched_waking",0,"target_cpu",2,"[NULL]"
+250978600639042,"sched_waking",0,"comm","[NULL]","ksoftirqd/0"
+250978600639042,"sched_waking",0,"pid",6,"[NULL]"
+250978600639042,"sched_waking",0,"prio",120,"[NULL]"
+250978600639042,"sched_waking",0,"success",1,"[NULL]"
+250978600639042,"sched_waking",0,"target_cpu",0,"[NULL]"
+250978604651907,"sched_waking",0,"comm","[NULL]","ksoftirqd/0"
+250978604651907,"sched_waking",0,"pid",6,"[NULL]"
+250978604651907,"sched_waking",0,"prio",120,"[NULL]"
+250978604651907,"sched_waking",0,"success",1,"[NULL]"
+250978604651907,"sched_waking",0,"target_cpu",0,"[NULL]"
+250978604739980,"sched_waking",0,"comm","[NULL]","kworker/2:0"
+250978604739980,"sched_waking",0,"pid",17438,"[NULL]"
+250978604739980,"sched_waking",0,"prio",120,"[NULL]"
+250978604739980,"sched_waking",0,"success",1,"[NULL]"
+250978604739980,"sched_waking",0,"target_cpu",2,"[NULL]"
+250978608903886,"sched_waking",0,"comm","[NULL]","kworker/2:0"
+250978608903886,"sched_waking",0,"pid",17438,"[NULL]"
+250978608903886,"sched_waking",0,"prio",120,"[NULL]"
+250978608903886,"sched_waking",0,"success",1,"[NULL]"
+250978608903886,"sched_waking",0,"target_cpu",2,"[NULL]"
+250978608942220,"sched_waking",0,"comm","[NULL]","ksoftirqd/0"
+250978608942220,"sched_waking",0,"pid",6,"[NULL]"
+250978608942220,"sched_waking",0,"prio",120,"[NULL]"
+250978608942220,"sched_waking",0,"success",1,"[NULL]"
+250978608942220,"sched_waking",0,"target_cpu",0,"[NULL]"
+250978612887272,"sched_waking",0,"comm","[NULL]","ksoftirqd/0"
+250978612887272,"sched_waking",0,"pid",6,"[NULL]"
+250978612887272,"sched_waking",0,"prio",120,"[NULL]"
+250978612887272,"sched_waking",0,"success",1,"[NULL]"
+250978612887272,"sched_waking",0,"target_cpu",0,"[NULL]"
+250978612971283,"sched_waking",0,"comm","[NULL]","kworker/2:0"
+250978612971283,"sched_waking",0,"pid",17438,"[NULL]"
+250978612971283,"sched_waking",0,"prio",120,"[NULL]"
+250978612971283,"sched_waking",0,"success",1,"[NULL]"
+250978612971283,"sched_waking",0,"target_cpu",2,"[NULL]"
+250978616876595,"sched_waking",0,"comm","[NULL]","kworker/2:0"
+250978616876595,"sched_waking",0,"pid",17438,"[NULL]"
+250978616876595,"sched_waking",0,"prio",120,"[NULL]"
+250978616876595,"sched_waking",0,"success",1,"[NULL]"
+250978616876595,"sched_waking",0,"target_cpu",2,"[NULL]"
+250978616921700,"sched_waking",0,"comm","[NULL]","ksoftirqd/0"
+250978616921700,"sched_waking",0,"pid",6,"[NULL]"
+250978616921700,"sched_waking",0,"prio",120,"[NULL]"
+250978616921700,"sched_waking",0,"success",1,"[NULL]"
+250978616921700,"sched_waking",0,"target_cpu",0,"[NULL]"
+250978617016804,"sched_waking",0,"comm","[NULL]","kworker/u16:18"
+250978617016804,"sched_waking",0,"pid",17473,"[NULL]"
+250978617016804,"sched_waking",0,"prio",120,"[NULL]"
+250978617016804,"sched_waking",0,"success",1,"[NULL]"
+250978617016804,"sched_waking",0,"target_cpu",2,"[NULL]"
+250978620859669,"sched_waking",0,"comm","[NULL]","ksoftirqd/0"
+250978620859669,"sched_waking",0,"pid",6,"[NULL]"
+250978620859669,"sched_waking",0,"prio",120,"[NULL]"
+250978620859669,"sched_waking",0,"success",1,"[NULL]"
+250978620859669,"sched_waking",0,"target_cpu",0,"[NULL]"
+250978620939148,"sched_waking",0,"comm","[NULL]","kworker/2:0"
+250978620939148,"sched_waking",0,"pid",17438,"[NULL]"
+250978620939148,"sched_waking",0,"prio",120,"[NULL]"
+250978620939148,"sched_waking",0,"success",1,"[NULL]"
+250978620939148,"sched_waking",0,"target_cpu",2,"[NULL]"
+250978624836805,"sched_waking",0,"comm","[NULL]","kworker/2:0"
+250978624836805,"sched_waking",0,"pid",17438,"[NULL]"
+250978624836805,"sched_waking",0,"prio",120,"[NULL]"
+250978624836805,"sched_waking",0,"success",1,"[NULL]"
+250978624836805,"sched_waking",0,"target_cpu",2,"[NULL]"
+250978624875398,"sched_waking",0,"comm","[NULL]","ksoftirqd/0"
+250978624875398,"sched_waking",0,"pid",6,"[NULL]"
+250978624875398,"sched_waking",0,"prio",120,"[NULL]"
+250978624875398,"sched_waking",0,"success",1,"[NULL]"
+250978624875398,"sched_waking",0,"target_cpu",0,"[NULL]"
+250978624978003,"sched_waking",0,"comm","[NULL]","kworker/u16:18"
+250978624978003,"sched_waking",0,"pid",17473,"[NULL]"
+250978624978003,"sched_waking",0,"prio",120,"[NULL]"
+250978624978003,"sched_waking",0,"success",1,"[NULL]"
+250978624978003,"sched_waking",0,"target_cpu",0,"[NULL]"
+250978441664547,"sched_waking",1,"comm","[NULL]","ksoftirqd/1"
+250978441664547,"sched_waking",1,"pid",18,"[NULL]"
+250978441664547,"sched_waking",1,"prio",120,"[NULL]"
+250978441664547,"sched_waking",1,"success",1,"[NULL]"
+250978441664547,"sched_waking",1,"target_cpu",1,"[NULL]"
+250978441702515,"sched_waking",1,"comm","[NULL]","kworker/u16:18"
+250978441702515,"sched_waking",1,"pid",17473,"[NULL]"
+250978441702515,"sched_waking",1,"prio",120,"[NULL]"
+250978441702515,"sched_waking",1,"success",1,"[NULL]"
+250978441702515,"sched_waking",1,"target_cpu",2,"[NULL]"
+250978805144375,"sched_waking",1,"comm","[NULL]","traced_probes"
+250978805144375,"sched_waking",1,"pid",17772,"[NULL]"
+250978805144375,"sched_waking",1,"prio",120,"[NULL]"
+250978805144375,"sched_waking",1,"success",1,"[NULL]"
+250978805144375,"sched_waking",1,"target_cpu",1,"[NULL]"
+250978808058698,"sched_waking",1,"comm","[NULL]","rcuop/0"
+250978808058698,"sched_waking",1,"pid",10,"[NULL]"
+250978808058698,"sched_waking",1,"prio",120,"[NULL]"
+250978808058698,"sched_waking",1,"success",1,"[NULL]"
+250978808058698,"sched_waking",1,"target_cpu",2,"[NULL]"
+250978884120216,"sched_waking",1,"comm","[NULL]","traced"
+250978884120216,"sched_waking",1,"pid",17771,"[NULL]"
+250978884120216,"sched_waking",1,"prio",120,"[NULL]"
+250978884120216,"sched_waking",1,"success",1,"[NULL]"
+250978884120216,"sched_waking",1,"target_cpu",1,"[NULL]"
+250978885260685,"sched_waking",1,"comm","[NULL]","rcuop/0"
+250978885260685,"sched_waking",1,"pid",10,"[NULL]"
+250978885260685,"sched_waking",1,"prio",120,"[NULL]"
+250978885260685,"sched_waking",1,"success",1,"[NULL]"
+250978885260685,"sched_waking",1,"target_cpu",2,"[NULL]"
+250978885786674,"sched_waking",1,"comm","[NULL]","traced_probes"
+250978885786674,"sched_waking",1,"pid",17772,"[NULL]"
+250978885786674,"sched_waking",1,"prio",120,"[NULL]"
+250978885786674,"sched_waking",1,"success",1,"[NULL]"
+250978885786674,"sched_waking",1,"target_cpu",1,"[NULL]"
+250978444958245,"sched_waking",2,"comm","[NULL]","rcuop/0"
+250978444958245,"sched_waking",2,"pid",10,"[NULL]"
+250978444958245,"sched_waking",2,"prio",120,"[NULL]"
+250978444958245,"sched_waking",2,"success",1,"[NULL]"
+250978444958245,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978444974443,"sched_waking",2,"comm","[NULL]","rcuop/1"
+250978444974443,"sched_waking",2,"pid",21,"[NULL]"
+250978444974443,"sched_waking",2,"prio",120,"[NULL]"
+250978444974443,"sched_waking",2,"success",1,"[NULL]"
+250978444974443,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978444984234,"sched_waking",2,"comm","[NULL]","rcu_preempt"
+250978444984234,"sched_waking",2,"pid",7,"[NULL]"
+250978444984234,"sched_waking",2,"prio",120,"[NULL]"
+250978444984234,"sched_waking",2,"success",1,"[NULL]"
+250978444984234,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978451590173,"sched_waking",2,"comm","[NULL]","rcu_preempt"
+250978451590173,"sched_waking",2,"pid",7,"[NULL]"
+250978451590173,"sched_waking",2,"prio",120,"[NULL]"
+250978451590173,"sched_waking",2,"success",1,"[NULL]"
+250978451590173,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978451646579,"sched_waking",2,"comm","[NULL]","rcuos/0"
+250978451646579,"sched_waking",2,"pid",11,"[NULL]"
+250978451646579,"sched_waking",2,"prio",120,"[NULL]"
+250978451646579,"sched_waking",2,"success",1,"[NULL]"
+250978451646579,"sched_waking",2,"target_cpu",4,"[NULL]"
+250978451716891,"sched_waking",2,"comm","[NULL]","rcuos/1"
+250978451716891,"sched_waking",2,"pid",22,"[NULL]"
+250978451716891,"sched_waking",2,"prio",120,"[NULL]"
+250978451716891,"sched_waking",2,"success",1,"[NULL]"
+250978451716891,"sched_waking",2,"target_cpu",1,"[NULL]"
+250978452047048,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
+250978452047048,"sched_waking",2,"pid",17473,"[NULL]"
+250978452047048,"sched_waking",2,"prio",120,"[NULL]"
+250978452047048,"sched_waking",2,"success",1,"[NULL]"
+250978452047048,"sched_waking",2,"target_cpu",0,"[NULL]"
+250978458337725,"sched_waking",2,"comm","[NULL]","sugov:0"
+250978458337725,"sched_waking",2,"pid",625,"[NULL]"
+250978458337725,"sched_waking",2,"prio",49,"[NULL]"
+250978458337725,"sched_waking",2,"success",1,"[NULL]"
+250978458337725,"sched_waking",2,"target_cpu",3,"[NULL]"
+250978458362100,"sched_waking",2,"comm","[NULL]","rcu_preempt"
+250978458362100,"sched_waking",2,"pid",7,"[NULL]"
+250978458362100,"sched_waking",2,"prio",120,"[NULL]"
+250978458362100,"sched_waking",2,"success",1,"[NULL]"
+250978458362100,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978458398455,"sched_waking",2,"comm","[NULL]","rcuop/0"
+250978458398455,"sched_waking",2,"pid",10,"[NULL]"
+250978458398455,"sched_waking",2,"prio",120,"[NULL]"
+250978458398455,"sched_waking",2,"success",1,"[NULL]"
+250978458398455,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978458419496,"sched_waking",2,"comm","[NULL]","rcuop/1"
+250978458419496,"sched_waking",2,"pid",21,"[NULL]"
+250978458419496,"sched_waking",2,"prio",120,"[NULL]"
+250978458419496,"sched_waking",2,"success",1,"[NULL]"
+250978458419496,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978459118038,"sched_waking",2,"comm","[NULL]","sugov:0"
+250978459118038,"sched_waking",2,"pid",625,"[NULL]"
+250978459118038,"sched_waking",2,"prio",49,"[NULL]"
+250978459118038,"sched_waking",2,"success",1,"[NULL]"
+250978459118038,"sched_waking",2,"target_cpu",3,"[NULL]"
+250978593466697,"sched_waking",2,"comm","[NULL]","kworker/2:0"
+250978593466697,"sched_waking",2,"pid",17438,"[NULL]"
+250978593466697,"sched_waking",2,"prio",120,"[NULL]"
+250978593466697,"sched_waking",2,"success",1,"[NULL]"
+250978593466697,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978593734510,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
+250978593734510,"sched_waking",2,"pid",17473,"[NULL]"
+250978593734510,"sched_waking",2,"prio",120,"[NULL]"
+250978593734510,"sched_waking",2,"success",1,"[NULL]"
+250978593734510,"sched_waking",2,"target_cpu",3,"[NULL]"
+250978595521125,"sched_waking",2,"comm","[NULL]","kworker/2:3"
+250978595521125,"sched_waking",2,"pid",17754,"[NULL]"
+250978595521125,"sched_waking",2,"prio",120,"[NULL]"
+250978595521125,"sched_waking",2,"success",1,"[NULL]"
+250978595521125,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978595696645,"sched_waking",2,"comm","[NULL]","kworker/2:0"
+250978595696645,"sched_waking",2,"pid",17438,"[NULL]"
+250978595696645,"sched_waking",2,"prio",120,"[NULL]"
+250978595696645,"sched_waking",2,"success",1,"[NULL]"
+250978595696645,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978596068468,"sched_waking",2,"comm","[NULL]","kworker/2:3"
+250978596068468,"sched_waking",2,"pid",17754,"[NULL]"
+250978596068468,"sched_waking",2,"prio",120,"[NULL]"
+250978596068468,"sched_waking",2,"success",1,"[NULL]"
+250978596068468,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978605185448,"sched_waking",2,"comm","[NULL]","ksoftirqd/2"
+250978605185448,"sched_waking",2,"pid",26,"[NULL]"
+250978605185448,"sched_waking",2,"prio",120,"[NULL]"
+250978605185448,"sched_waking",2,"success",1,"[NULL]"
+250978605185448,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978605260240,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
+250978605260240,"sched_waking",2,"pid",17473,"[NULL]"
+250978605260240,"sched_waking",2,"prio",120,"[NULL]"
+250978605260240,"sched_waking",2,"success",1,"[NULL]"
+250978605260240,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978628278107,"sched_waking",2,"comm","[NULL]","logd.klogd"
+250978628278107,"sched_waking",2,"pid",651,"[NULL]"
+250978628278107,"sched_waking",2,"prio",130,"[NULL]"
+250978628278107,"sched_waking",2,"success",1,"[NULL]"
+250978628278107,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978629289722,"sched_waking",2,"comm","[NULL]","rcuop/2"
+250978629289722,"sched_waking",2,"pid",29,"[NULL]"
+250978629289722,"sched_waking",2,"prio",120,"[NULL]"
+250978629289722,"sched_waking",2,"success",1,"[NULL]"
+250978629289722,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978629405763,"sched_waking",2,"comm","[NULL]","rcu_preempt"
+250978629405763,"sched_waking",2,"pid",7,"[NULL]"
+250978629405763,"sched_waking",2,"prio",120,"[NULL]"
+250978629405763,"sched_waking",2,"success",1,"[NULL]"
+250978629405763,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978635024462,"sched_waking",2,"comm","[NULL]","rcu_preempt"
+250978635024462,"sched_waking",2,"pid",7,"[NULL]"
+250978635024462,"sched_waking",2,"prio",120,"[NULL]"
+250978635024462,"sched_waking",2,"success",1,"[NULL]"
+250978635024462,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978635060191,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
+250978635060191,"sched_waking",2,"pid",17473,"[NULL]"
+250978635060191,"sched_waking",2,"prio",120,"[NULL]"
+250978635060191,"sched_waking",2,"success",1,"[NULL]"
+250978635060191,"sched_waking",2,"target_cpu",0,"[NULL]"
+250978635219514,"sched_waking",2,"comm","[NULL]","rcuop/2"
+250978635219514,"sched_waking",2,"pid",29,"[NULL]"
+250978635219514,"sched_waking",2,"prio",120,"[NULL]"
+250978635219514,"sched_waking",2,"success",1,"[NULL]"
+250978635219514,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978683441081,"sched_waking",2,"comm","[NULL]","kworker/2:0"
+250978683441081,"sched_waking",2,"pid",17438,"[NULL]"
+250978683441081,"sched_waking",2,"prio",120,"[NULL]"
+250978683441081,"sched_waking",2,"success",1,"[NULL]"
+250978683441081,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978683732331,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
+250978683732331,"sched_waking",2,"pid",17473,"[NULL]"
+250978683732331,"sched_waking",2,"prio",120,"[NULL]"
+250978683732331,"sched_waking",2,"success",1,"[NULL]"
+250978683732331,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978685694259,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
+250978685694259,"sched_waking",2,"pid",17473,"[NULL]"
+250978685694259,"sched_waking",2,"prio",120,"[NULL]"
+250978685694259,"sched_waking",2,"success",1,"[NULL]"
+250978685694259,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978740127441,"sched_waking",2,"comm","[NULL]","kworker/2:0"
+250978740127441,"sched_waking",2,"pid",17438,"[NULL]"
+250978740127441,"sched_waking",2,"prio",120,"[NULL]"
+250978740127441,"sched_waking",2,"success",1,"[NULL]"
+250978740127441,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978740425410,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
+250978740425410,"sched_waking",2,"pid",17473,"[NULL]"
+250978740425410,"sched_waking",2,"prio",120,"[NULL]"
+250978740425410,"sched_waking",2,"success",1,"[NULL]"
+250978740425410,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978743210358,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
+250978743210358,"sched_waking",2,"pid",17473,"[NULL]"
+250978743210358,"sched_waking",2,"prio",120,"[NULL]"
+250978743210358,"sched_waking",2,"success",1,"[NULL]"
+250978743210358,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978744945567,"sched_waking",2,"comm","[NULL]","logd.klogd"
+250978744945567,"sched_waking",2,"pid",651,"[NULL]"
+250978744945567,"sched_waking",2,"prio",130,"[NULL]"
+250978744945567,"sched_waking",2,"success",1,"[NULL]"
+250978744945567,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978746028431,"sched_waking",2,"comm","[NULL]","rcuop/2"
+250978746028431,"sched_waking",2,"pid",29,"[NULL]"
+250978746028431,"sched_waking",2,"prio",120,"[NULL]"
+250978746028431,"sched_waking",2,"success",1,"[NULL]"
+250978746028431,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978746173171,"sched_waking",2,"comm","[NULL]","rcu_preempt"
+250978746173171,"sched_waking",2,"pid",7,"[NULL]"
+250978746173171,"sched_waking",2,"prio",120,"[NULL]"
+250978746173171,"sched_waking",2,"success",1,"[NULL]"
+250978746173171,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978751622494,"sched_waking",2,"comm","[NULL]","rcu_preempt"
+250978751622494,"sched_waking",2,"pid",7,"[NULL]"
+250978751622494,"sched_waking",2,"prio",120,"[NULL]"
+250978751622494,"sched_waking",2,"success",1,"[NULL]"
+250978751622494,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978751661348,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
+250978751661348,"sched_waking",2,"pid",17473,"[NULL]"
+250978751661348,"sched_waking",2,"prio",120,"[NULL]"
+250978751661348,"sched_waking",2,"success",1,"[NULL]"
+250978751661348,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978751792859,"sched_waking",2,"comm","[NULL]","rcuop/2"
+250978751792859,"sched_waking",2,"pid",29,"[NULL]"
+250978751792859,"sched_waking",2,"prio",120,"[NULL]"
+250978751792859,"sched_waking",2,"success",1,"[NULL]"
+250978751792859,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978751971817,"sched_waking",2,"comm","[NULL]","rcu_preempt"
+250978751971817,"sched_waking",2,"pid",7,"[NULL]"
+250978751971817,"sched_waking",2,"prio",120,"[NULL]"
+250978751971817,"sched_waking",2,"success",1,"[NULL]"
+250978751971817,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978758784578,"sched_waking",2,"comm","[NULL]","rcu_preempt"
+250978758784578,"sched_waking",2,"pid",7,"[NULL]"
+250978758784578,"sched_waking",2,"prio",120,"[NULL]"
+250978758784578,"sched_waking",2,"success",1,"[NULL]"
+250978758784578,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978758873745,"sched_waking",2,"comm","[NULL]","rcuop/2"
+250978758873745,"sched_waking",2,"pid",29,"[NULL]"
+250978758873745,"sched_waking",2,"prio",120,"[NULL]"
+250978758873745,"sched_waking",2,"success",1,"[NULL]"
+250978758873745,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978808519271,"sched_waking",2,"comm","[NULL]","rcu_preempt"
+250978808519271,"sched_waking",2,"pid",7,"[NULL]"
+250978808519271,"sched_waking",2,"prio",120,"[NULL]"
+250978808519271,"sched_waking",2,"success",1,"[NULL]"
+250978808519271,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978815488490,"sched_waking",2,"comm","[NULL]","rcu_preempt"
+250978815488490,"sched_waking",2,"pid",7,"[NULL]"
+250978815488490,"sched_waking",2,"prio",120,"[NULL]"
+250978815488490,"sched_waking",2,"success",1,"[NULL]"
+250978815488490,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978815535678,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
+250978815535678,"sched_waking",2,"pid",17473,"[NULL]"
+250978815535678,"sched_waking",2,"prio",120,"[NULL]"
+250978815535678,"sched_waking",2,"success",1,"[NULL]"
+250978815535678,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978815675782,"sched_waking",2,"comm","[NULL]","rcuop/0"
+250978815675782,"sched_waking",2,"pid",10,"[NULL]"
+250978815675782,"sched_waking",2,"prio",120,"[NULL]"
+250978815675782,"sched_waking",2,"success",1,"[NULL]"
+250978815675782,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978815738022,"sched_waking",2,"comm","[NULL]","rcuop/1"
+250978815738022,"sched_waking",2,"pid",21,"[NULL]"
+250978815738022,"sched_waking",2,"prio",120,"[NULL]"
+250978815738022,"sched_waking",2,"success",1,"[NULL]"
+250978815738022,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978860203182,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
+250978860203182,"sched_waking",2,"pid",17473,"[NULL]"
+250978860203182,"sched_waking",2,"prio",120,"[NULL]"
+250978860203182,"sched_waking",2,"success",1,"[NULL]"
+250978860203182,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978880151205,"sched_waking",2,"comm","[NULL]","kworker/2:0"
+250978880151205,"sched_waking",2,"pid",17438,"[NULL]"
+250978880151205,"sched_waking",2,"prio",120,"[NULL]"
+250978880151205,"sched_waking",2,"success",1,"[NULL]"
+250978880151205,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978880432143,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
+250978880432143,"sched_waking",2,"pid",17473,"[NULL]"
+250978880432143,"sched_waking",2,"prio",120,"[NULL]"
+250978880432143,"sched_waking",2,"success",1,"[NULL]"
+250978880432143,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978885784018,"sched_waking",2,"comm","[NULL]","rcu_preempt"
+250978885784018,"sched_waking",2,"pid",7,"[NULL]"
+250978885784018,"sched_waking",2,"prio",120,"[NULL]"
+250978885784018,"sched_waking",2,"success",1,"[NULL]"
+250978885784018,"sched_waking",2,"target_cpu",2,"[NULL]"
+250978465172309,"sched_waking",3,"comm","[NULL]","ksoftirqd/3"
+250978465172309,"sched_waking",3,"pid",34,"[NULL]"
+250978465172309,"sched_waking",3,"prio",120,"[NULL]"
+250978465172309,"sched_waking",3,"success",1,"[NULL]"
+250978465172309,"sched_waking",3,"target_cpu",3,"[NULL]"
+250978465266789,"sched_waking",3,"comm","[NULL]","kworker/u16:18"
+250978465266789,"sched_waking",3,"pid",17473,"[NULL]"
+250978465266789,"sched_waking",3,"prio",120,"[NULL]"
+250978465266789,"sched_waking",3,"success",1,"[NULL]"
+250978465266789,"sched_waking",3,"target_cpu",0,"[NULL]"
+250978439491994,"sched_waking",4,"comm","[NULL]","rcu_sched"
+250978439491994,"sched_waking",4,"pid",8,"[NULL]"
+250978439491994,"sched_waking",4,"prio",120,"[NULL]"
+250978439491994,"sched_waking",4,"success",1,"[NULL]"
+250978439491994,"sched_waking",4,"target_cpu",1,"[NULL]"
+250978445783141,"sched_waking",5,"comm","[NULL]","rcu_sched"
+250978445783141,"sched_waking",5,"pid",8,"[NULL]"
+250978445783141,"sched_waking",5,"prio",120,"[NULL]"
+250978445783141,"sched_waking",5,"success",1,"[NULL]"
+250978445783141,"sched_waking",5,"target_cpu",5,"[NULL]"
+250978806359896,"sched_waking",5,"comm","[NULL]","kworker/5:1"
+250978806359896,"sched_waking",5,"pid",17667,"[NULL]"
+250978806359896,"sched_waking",5,"prio",120,"[NULL]"
+250978806359896,"sched_waking",5,"success",1,"[NULL]"
+250978806359896,"sched_waking",5,"target_cpu",5,"[NULL]"
+250978806428646,"sched_waking",5,"comm","[NULL]","kworker/u16:18"
+250978806428646,"sched_waking",5,"pid",17473,"[NULL]"
+250978806428646,"sched_waking",5,"prio",120,"[NULL]"
+250978806428646,"sched_waking",5,"success",1,"[NULL]"
+250978806428646,"sched_waking",5,"target_cpu",2,"[NULL]"
diff --git a/tools/compact_reencode/main.cc b/tools/compact_reencode/main.cc
index d54db1c..ae4a2c4 100644
--- a/tools/compact_reencode/main.cc
+++ b/tools/compact_reencode/main.cc
@@ -30,8 +30,14 @@
// Re-encodes the given trace, converting sched events to their compact
// representation.
-// Note: doesn't do bundle splitting/merging, the original trace must already
-// have multi-page bundles for the re-encoding to be realistic.
+//
+// Notes:
+// * doesn't do bundle splitting/merging, the original trace must already
+// have multi-page bundles for the re-encoding to be realistic.
+// * when importing the resulting trace into trace_processor, a few leading
+// switch/wakeup events can be skipped (since there's not enough info to
+// reconstruct the full events at that point), and this might change the
+// trace_bounds.
namespace perfetto {
namespace compact_reencode {
@@ -91,11 +97,20 @@
return static_cast<uint32_t>(new_idx);
};
+ // sched_waking pieces
+ protozero::PackedVarInt waking_timestamp;
+ protozero::PackedVarInt waking_pid;
+ protozero::PackedVarInt waking_target_cpu;
+ protozero::PackedVarInt waking_prio;
+ protozero::PackedVarInt waking_comm_index;
+
+ uint64_t last_waking_timestamp = 0;
+
for (auto event_it = bundle.event(); event_it; ++event_it) {
protos::pbzero::FtraceEvent::Decoder event(*event_it);
- if (!event.has_sched_switch()) {
+ if (!event.has_sched_switch() && !event.has_sched_waking()) {
CopyField(bundle_out, event_it.field());
- } else {
+ } else if (event.has_sched_switch()) {
switch_timestamp.Append(event.timestamp() - last_switch_timestamp);
last_switch_timestamp = event.timestamp();
@@ -108,18 +123,38 @@
switch_next_pid.Append(sswitch.next_pid());
switch_next_prio.Append(sswitch.next_prio());
switch_prev_state.Append(sswitch.prev_state());
+ } else {
+ waking_timestamp.Append(event.timestamp() - last_waking_timestamp);
+ last_waking_timestamp = event.timestamp();
+
+ protos::pbzero::SchedWakingFtraceEvent::Decoder swaking(
+ event.sched_waking());
+
+ auto iid = intern(swaking.comm().ToStdString());
+ waking_comm_index.Append(iid);
+
+ waking_pid.Append(swaking.pid());
+ waking_target_cpu.Append(swaking.target_cpu());
+ waking_prio.Append(swaking.prio());
}
}
+
auto* compact_sched = bundle_out->set_compact_sched();
for (const auto& s : string_table)
- compact_sched->add_switch_next_comm_table(s.data(), s.size());
+ compact_sched->add_intern_table(s.data(), s.size());
compact_sched->set_switch_timestamp(switch_timestamp);
compact_sched->set_switch_next_comm_index(switch_next_comm_index);
compact_sched->set_switch_next_pid(switch_next_pid);
compact_sched->set_switch_next_prio(switch_next_prio);
compact_sched->set_switch_prev_state(switch_prev_state);
+
+ compact_sched->set_waking_timestamp(waking_timestamp);
+ compact_sched->set_waking_pid(waking_pid);
+ compact_sched->set_waking_target_cpu(waking_target_cpu);
+ compact_sched->set_waking_prio(waking_prio);
+ compact_sched->set_waking_comm_index(waking_comm_index);
}
std::string ReEncode(const std::string& raw) {
diff --git a/tools/heap_profile b/tools/heap_profile
index 8f57b59..967299e 100755
--- a/tools/heap_profile
+++ b/tools/heap_profile
@@ -188,6 +188,11 @@
"This is the default",
action="store_true")
parser.add_argument(
+ "--block-client-timeout",
+ help="If --block-client is given, do not block any allocation for "
+ "longer than this timeout (us).",
+ type=int)
+ parser.add_argument(
"--no-block-client",
help="When buffer is full, stop the "
"profile early.",
@@ -245,6 +250,8 @@
target_cfg = ""
if not args.no_block_client:
target_cfg += "block_client: true\n"
+ if args.block_client_timeout:
+ target_cfg += "block_client_timeout_us: %s\n" % args.block_client_timeout
if args.idle_allocations:
target_cfg += "idle_allocations: true\n"
if args.no_startup:
diff --git a/tools/install-build-deps b/tools/install-build-deps
index 1f454bb..a8cd83e 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -146,8 +146,8 @@
# Example traces for regression tests.
(
'buildtools/test_data.zip',
- 'https://storage.googleapis.com/perfetto/test-data-20191025-102200.zip',
- '25a61211f82cd73c6ce5b67da9d73f046de7b3f9',
+ 'https://storage.googleapis.com/perfetto/test-data-20191107-164334.zip',
+ '499f11fbc2b04ef7742662a26b85ef03141e24bd',
'all',
),
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index 885cc4c..56afebd 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -25,11 +25,11 @@
NewEngineMode,
OmniboxState,
RecordConfig,
+ RecordingTarget,
SCROLLING_TRACK_GROUP,
SelectedTimeRange,
State,
Status,
- TargetOs,
TraceSource,
TraceTime,
TrackState,
@@ -51,9 +51,9 @@
const nextId = state.nextId;
const recordConfig = state.recordConfig;
const route = state.route;
- const androidDeviceConnected = state.androidDeviceConnected;
+ const recordingTarget = state.recordingTarget;
const extensionInstalled = state.extensionInstalled;
- const availableDevices = state.availableDevices;
+ const availableAdbDevices = state.availableAdbDevices;
const chromeCategories = state.chromeCategories;
const newEngineMode = state.newEngineMode;
@@ -61,9 +61,9 @@
state.nextId = nextId;
state.recordConfig = recordConfig;
state.route = route;
- state.androidDeviceConnected = androidDeviceConnected;
+ state.recordingTarget = recordingTarget;
state.extensionInstalled = extensionInstalled;
- state.availableDevices = availableDevices;
+ state.availableAdbDevices = availableAdbDevices;
state.chromeCategories = chromeCategories;
state.newEngineMode = newEngineMode;
}
@@ -348,7 +348,7 @@
this.selectNote(state, {id});
},
- toggleVideo(state: StateDraft): void {
+ toggleVideo(state: StateDraft, _: {}): void {
state.videoEnabled = !state.videoEnabled;
if (!state.videoEnabled) {
state.video = null;
@@ -360,13 +360,13 @@
}
},
- toggleFlagPause(state: StateDraft): void {
+ toggleFlagPause(state: StateDraft, _: {}): void {
if (state.video != null) {
state.flagPauseEnabled = !state.flagPauseEnabled;
}
},
- toggleScrubbing(state: StateDraft): void {
+ toggleScrubbing(state: StateDraft, _: {}): void {
if (state.video != null) {
state.scrubbingEnabled = !state.scrubbingEnabled;
}
@@ -476,17 +476,17 @@
state.logsPagination = args;
},
- startRecording(state: StateDraft): void {
+ startRecording(state: StateDraft, _: {}): void {
state.recordingInProgress = true;
state.lastRecordingError = undefined;
state.recordingCancelled = false;
},
- stopRecording(state: StateDraft): void {
+ stopRecording(state: StateDraft, _: {}): void {
state.recordingInProgress = false;
},
- cancelRecording(state: StateDraft): void {
+ cancelRecording(state: StateDraft, _: {}): void {
state.recordingInProgress = false;
state.recordingCancelled = true;
},
@@ -499,17 +499,14 @@
state.bufferUsage = args.percentage;
},
- setAndroidDevice(state: StateDraft, args: {target?: AdbRecordingTarget}):
- void {
- state.recordConfig.targetOS =
- args.target ? args.target.os as TargetOs : 'Q';
- state.androidDeviceConnected = args.target;
- },
+ setRecordingTarget(state: StateDraft, args: {target: RecordingTarget}): void {
+ state.recordingTarget = args.target;
+ },
- setAvailableDevices(state: StateDraft, args: {devices: AdbRecordingTarget[]}):
- void {
- state.availableDevices = args.devices;
- },
+ setAvailableAdbDevices(
+ state: StateDraft, args: {devices: AdbRecordingTarget[]}): void {
+ state.availableAdbDevices = args.devices;
+ },
setOmnibox(state: StateDraft, args: OmniboxState): void {
state.frontendLocalState.omniboxState = args;
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index 10d7924..158bf05 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -178,10 +178,13 @@
count: number;
}
-export interface AdbRecordingTarget {
- serial: string;
+export interface RecordingTarget {
name: string;
- os: string;
+ os: TargetOs;
+}
+
+export interface AdbRecordingTarget extends RecordingTarget {
+ serial: string;
}
export interface State {
@@ -237,8 +240,8 @@
recordingInProgress: boolean;
recordingCancelled: boolean;
extensionInstalled: boolean;
- androidDeviceConnected?: AdbRecordingTarget;
- availableDevices: AdbRecordingTarget[];
+ recordingTarget: RecordingTarget;
+ availableAdbDevices: AdbRecordingTarget[];
lastRecordingError?: string;
recordingStatus?: string;
@@ -256,23 +259,28 @@
// 'Q','P','O' for Android, 'L' for Linux, 'C' for Chrome.
export declare type TargetOs = 'Q' | 'P' | 'O' | 'C' | 'L';
-export function isAndroidTarget(target: TargetOs) {
- return ['Q', 'P', 'O'].includes(target);
+export function isAndroidTarget(target: RecordingTarget) {
+ return ['Q', 'P', 'O'].includes(target.os);
}
-export function isChromeTarget(target: TargetOs) {
- return target === 'C';
+export function isChromeTarget(target: RecordingTarget) {
+ return target.os === 'C';
}
-export function isLinuxTarget(target: TargetOs) {
- return target === 'L';
+export function isLinuxTarget(target: RecordingTarget) {
+ return target.os === 'L';
+}
+
+export function isAdbTarget(target: RecordingTarget):
+ target is AdbRecordingTarget {
+ if ((target as AdbRecordingTarget).serial) return true;
+ return false;
}
export interface RecordConfig {
[key: string]: null|number|boolean|string|string[];
// Global settings
- targetOS: TargetOs;
mode: RecordMode;
durationMs: number;
bufferSizeMb: number;
@@ -330,7 +338,6 @@
export function createEmptyRecordConfig(): RecordConfig {
return {
- targetOS: 'Q',
mode: 'STOP_WHEN_FULL',
durationMs: 10000.0,
maxFileSizeMb: 100,
@@ -389,6 +396,16 @@
};
}
+export function getDefaultRecordingTargets(): RecordingTarget[] {
+ return [
+ {os: 'Q', name: 'Android Q+'},
+ {os: 'P', name: 'Android P'},
+ {os: 'O', name: 'Android O-'},
+ {os: 'C', name: 'Chrome'},
+ {os: 'L', name: 'Linux desktop'}
+ ];
+}
+
export function createEmptyState(): State {
return {
route: null,
@@ -443,8 +460,8 @@
recordingInProgress: false,
recordingCancelled: false,
extensionInstalled: false,
- androidDeviceConnected: undefined,
- availableDevices: [],
+ recordingTarget: getDefaultRecordingTargets()[0],
+ availableAdbDevices: [],
chromeCategories: undefined,
};
diff --git a/ui/src/controller/adb_base_controller.ts b/ui/src/controller/adb_base_controller.ts
index 6642c98..7f1afb1 100644
--- a/ui/src/controller/adb_base_controller.ts
+++ b/ui/src/controller/adb_base_controller.ts
@@ -14,6 +14,7 @@
import {extractDurationFromTraceConfig} from '../base/extract_utils';
import {extractTraceConfig} from '../base/extract_utils';
+import {isAdbTarget} from '../common/state';
import {Adb} from './adb_interfaces';
import {ReadBuffersResponse} from './consumer_port_types';
@@ -55,8 +56,9 @@
this.device = await this.findDevice();
if (!this.device) {
this.state = AdbAuthState.DISCONNECTED;
+ const target = globals.state.recordingTarget;
throw Error(`Device with serial ${
- globals.state.serialAndroidDeviceConnected} not found.`);
+ isAdbTarget(target) ? target.serial : 'n/a'} not found.`);
}
this.sendStatus(`Please allow USB debugging on device.
@@ -110,9 +112,9 @@
}
async findDevice(): Promise<USBDevice|undefined> {
- const deviceConnected = globals.state.androidDeviceConnected;
- if (!deviceConnected) return undefined;
+ const connectedDevice = globals.state.recordingTarget;
+ if (!isAdbTarget(connectedDevice)) return undefined;
const devices = await navigator.usb.getDevices();
- return devices.find(d => d.serialNumber === deviceConnected.serial);
+ return devices.find(d => d.serialNumber === connectedDevice.serial);
}
}
\ No newline at end of file
diff --git a/ui/src/controller/record_controller.ts b/ui/src/controller/record_controller.ts
index dbbed80..acfe936 100644
--- a/ui/src/controller/record_controller.ts
+++ b/ui/src/controller/record_controller.ts
@@ -36,11 +36,11 @@
import {MeminfoCounters, VmstatCounters} from '../common/protos';
import {
AdbRecordingTarget,
- isAndroidTarget,
+ isAdbTarget,
isChromeTarget,
MAX_TIME,
RecordConfig,
- TargetOs
+ RecordingTarget
} from '../common/state';
import {AdbOverWebUsb} from './adb';
@@ -630,9 +630,8 @@
// - Android device target: WebUSB is used to communicate using the adb
// protocol. Actually, there is no full consumer_port implementation, but
// only the support to start tracing and fetch the file.
- async getTargetController(target: TargetOs, device?: AdbRecordingTarget):
- Promise<RpcConsumerPort> {
- const identifier = this.getTargetIdentifier(target, device);
+ async getTargetController(target: RecordingTarget): Promise<RpcConsumerPort> {
+ const identifier = this.getTargetIdentifier(target);
// The reason why caching the target 'record controller' Promise is that
// multiple rcp calls can happen while we are trying to understand if an
@@ -646,16 +645,16 @@
if (isChromeTarget(target)) {
controller =
new ChromeExtensionConsumerPort(this.extensionPort, this);
- } else if (isAndroidTarget(target)) {
- if (!device) throw Error(`No android device connected`);
-
+ } else if (isAdbTarget(target)) {
this.onStatus(`Please allow USB debugging on device.
If you press cancel, reload the page.`);
- const socketAccess = await this.hasSocketAccess(device);
+ const socketAccess = await this.hasSocketAccess(target);
controller = socketAccess ?
new AdbSocketConsumerPort(this.adb, this) :
new AdbConsumerPort(this.adb, this);
+ } else {
+ throw Error(`No device connected`);
}
if (!controller) throw Error(`Unknown target: ${target}`);
@@ -666,9 +665,8 @@
return controllerPromise;
}
- private getTargetIdentifier(target: TargetOs, device?: AdbRecordingTarget):
- string {
- return device ? device.serial : target;
+ private getTargetIdentifier(target: RecordingTarget): string {
+ return isAdbTarget(target) ? target.serial : target.os;
}
private async hasSocketAccess(target: AdbRecordingTarget) {
@@ -684,8 +682,7 @@
_callback: RPCImplCallback) {
try {
const state = this.app.state;
- (await this.getTargetController(
- state.recordConfig.targetOS, state.androidDeviceConnected))
+ (await this.getTargetController(state.recordingTarget))
.handleCommand(method.name, requestData);
} catch (e) {
console.error(`error invoking ${method}: ${e.message}`);
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 8c93273..7edcbba 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -494,7 +494,9 @@
left join (select upid, sum(dur) as total_dur
from sched join thread using(utid)
group by upid
- ) using(upid) group by utid, upid
+ ) using(upid)
+ where utid != 0
+ group by utid, upid
order by total_dur desc, upid, utid`);
const upidToUuid = new Map<number, string>();
diff --git a/ui/src/frontend/record_page.ts b/ui/src/frontend/record_page.ts
index 5d87f7a..47c42e2 100644
--- a/ui/src/frontend/record_page.ts
+++ b/ui/src/frontend/record_page.ts
@@ -20,10 +20,12 @@
import {MeminfoCounters, VmstatCounters} from '../common/protos';
import {
AdbRecordingTarget,
+ getDefaultRecordingTargets,
+ isAdbTarget,
isAndroidTarget,
isChromeTarget,
isLinuxTarget,
- TargetOs
+ RecordingTarget
} from '../common/state';
import {MAX_TIME, RecordMode} from '../common/state';
import {AdbOverWebUsb} from '../controller/adb';
@@ -702,21 +704,20 @@
function RecordingPlatformSelection() {
if (globals.state.recordingInProgress) return [];
- const baseTargets = [
- m('option', {value: 'Q'}, 'Android Q+'),
- m('option', {value: 'P'}, 'Android P'),
- m('option', {value: 'O'}, 'Android O-'),
- m('option', {value: 'C'}, 'Chrome'),
- m('option', {value: 'L'}, 'Linux desktop')
- ];
- const availableAndroidDevices = globals.state.availableDevices;
- const selected = globals.state.androidDeviceConnected;
- const choices: m.Children[] =
- availableAndroidDevices.map(d => m('option', {value: d.serial}, d.name));
+ const availableAndroidDevices = globals.state.availableAdbDevices;
+ const recordingTarget = globals.state.recordingTarget;
- const selectedIndex = selected ? baseTargets.length +
- availableAndroidDevices.findIndex(d => d.serial === selected.serial) :
- 0;
+ const targets = [];
+ for (const {os, name} of getDefaultRecordingTargets()) {
+ targets.push(m('option', {value: os}, name));
+ }
+ for (const d of availableAndroidDevices) {
+ targets.push(m('option', {value: d.serial}, d.name));
+ }
+
+ const selectedIndex = isAdbTarget(recordingTarget) ?
+ targets.findIndex(node => node.attrs.value === recordingTarget.serial) :
+ targets.findIndex(node => node.attrs.value === recordingTarget.os);
return m(
'.target',
@@ -725,8 +726,7 @@
'Target platform:',
m('select',
{onchange: m.withAttr('value', onTargetChange), selectedIndex},
- ...baseTargets,
- ...choices),
+ ...targets),
),
m('.chip',
{onclick: addAndroidDevice},
@@ -734,16 +734,13 @@
m('i.material-icons', 'add')));
}
-// Target can be the targetOS or the android serial
+// |target| can be the TargetOs or the android serial.
function onTargetChange(target: string) {
- const adbDevice =
- globals.state.availableDevices.find(d => d.serial === target);
- globals.dispatch(Actions.setAndroidDevice({target: adbDevice}));
-
- const traceCfg = produce(globals.state.recordConfig, draft => {
- draft.targetOS = adbDevice ? adbDevice.os as TargetOs : target as TargetOs;
- });
- globals.dispatch(Actions.setRecordConfig({config: traceCfg}));
+ const recordingTarget: RecordingTarget =
+ globals.state.availableAdbDevices.find(d => d.serial === target) ||
+ getDefaultRecordingTargets().find(t => t.os === target) ||
+ getDefaultRecordingTargets()[0];
+ globals.dispatch(Actions.setRecordingTarget({target: recordingTarget}));
globals.rafScheduler.scheduleFullRedraw();
}
@@ -805,7 +802,7 @@
output directory. `,
doc);
- switch (globals.state.recordConfig.targetOS) {
+ switch (globals.state.recordingTarget.os) {
case 'Q':
break;
case 'P':
@@ -829,10 +826,10 @@
}
function RecordingSnippet() {
- const targetOs = globals.state.recordConfig.targetOS;
+ const target = globals.state.recordingTarget;
// We don't need commands to start tracing on chrome
- if (isChromeTarget(targetOs)) {
+ if (isChromeTarget(target)) {
return globals.state.extensionInstalled ?
m('div',
m('label',
@@ -840,11 +837,10 @@
'Start Recording'.`)) :
[];
}
- return m(
- CodeSnippet, {text: getRecordCommand(targetOs), hardWhitespace: true});
+ return m(CodeSnippet, {text: getRecordCommand(target), hardWhitespace: true});
}
-function getRecordCommand(targetOs: TargetOs) {
+function getRecordCommand(target: RecordingTarget) {
const data = globals.trackDataStore.get('config') as
{commandline: string, pbtxt: string} |
null;
@@ -864,8 +860,7 @@
cmd += `(sleep 0.5 && adb shell screenrecord --time-limit ${time}`;
cmd += ' "/sdcard/tracescr.mp4") &\\\n';
}
- cmd +=
- isAndroidTarget(targetOs) ? 'adb shell perfetto \\\n' : 'perfetto \\\n';
+ cmd += isAndroidTarget(target) ? 'adb shell perfetto \\\n' : 'perfetto \\\n';
cmd += ' -c - --txt \\\n';
cmd += ' -o /data/misc/perfetto-traces/trace \\\n';
cmd += '<<EOF\n\n';
@@ -877,7 +872,7 @@
function recordingButtons() {
const state = globals.state;
- const realDeviceTarget = state.androidDeviceConnected !== undefined;
+ const target = state.recordingTarget;
const recInProgress = state.recordingInProgress;
const start =
@@ -899,15 +894,14 @@
const buttons: m.Children = [];
- const targetOs = state.recordConfig.targetOS;
- if (isAndroidTarget(targetOs)) {
+ if (isAndroidTarget(target)) {
if (!recInProgress) {
buttons.push(showCmd);
- if (realDeviceTarget) buttons.push(start);
+ if (isAdbTarget(target)) buttons.push(start);
}
- } else if (isChromeTarget(targetOs) && state.extensionInstalled) {
+ } else if (isChromeTarget(target) && state.extensionInstalled) {
buttons.push(start);
- } else if (isLinuxTarget(targetOs)) {
+ } else if (isLinuxTarget(target)) {
buttons.push(showCmd);
}
@@ -934,8 +928,8 @@
location.href = '#!/record?p=instructions';
globals.rafScheduler.scheduleFullRedraw();
- const targetOs = globals.state.recordConfig.targetOS;
- if (isAndroidTarget(targetOs) || isChromeTarget(targetOs)) {
+ const target = globals.state.recordingTarget;
+ if (isAndroidTarget(target) || isChromeTarget(target)) {
globals.dispatch(Actions.startRecording({}));
}
}
@@ -962,12 +956,19 @@
// be inserted in the state, and the worker will be able to connect to the
// correct device.
async function addAndroidDevice() {
- const device = await new AdbOverWebUsb().findDevice();
+ let device: USBDevice;
+ try {
+ device = await new AdbOverWebUsb().findDevice();
+ } catch (e) {
+ console.error('No device found: ${e.name}: ${e.message}');
+ return;
+ }
if (!device.serialNumber) {
console.error('serial number undefined');
return;
}
+
// After the user has selected a device with the chrome UI, it will be
// available when listing all the available device from WebUSB. Therefore,
// we update the list of available devices.
@@ -990,7 +991,8 @@
}
});
- globals.dispatch(Actions.setAvailableDevices({devices: availableAdbDevices}));
+ globals.dispatch(
+ Actions.setAvailableAdbDevices({devices: availableAdbDevices}));
selectAndroidDeviceIfAvailable(availableAdbDevices);
globals.rafScheduler.scheduleFullRedraw();
return availableAdbDevices;
@@ -998,26 +1000,32 @@
function selectAndroidDeviceIfAvailable(
availableAdbDevices: AdbRecordingTarget[]) {
- // If there is an android device attached, but not selected, select it by
- // default.
- if (!globals.state.androidDeviceConnected && availableAdbDevices.length) {
+ const recordingTarget = globals.state.recordingTarget;
+ const deviceConnected = isAdbTarget(recordingTarget);
+ const connectedDeviceDisconnected = deviceConnected &&
+ availableAdbDevices.find(
+ e => e.serial === (recordingTarget as AdbRecordingTarget).serial) ===
+ undefined;
+
+ // If there is an android device attached, but not selected (or the currently
+ // selected device was disconnected), select it by default.
+ if ((!deviceConnected || connectedDeviceDisconnected) &&
+ availableAdbDevices.length) {
globals.dispatch(
- Actions.setAndroidDevice({target: availableAdbDevices[0]}));
+ Actions.setRecordingTarget({target: availableAdbDevices[0]}));
return;
}
- // If a device was selected, but it's not available anymore, reset the
- // androidConnectedDevice to null.
- const deviceConnected = globals.state.androidDeviceConnected;
- if (deviceConnected &&
- availableAdbDevices.find(e => e.serial === deviceConnected.serial) ===
- undefined) {
- globals.dispatch(Actions.setAndroidDevice({target: undefined}));
+ // If the currently selected device was disconnected, reset the recording
+ // target to the default one.
+ if (connectedDeviceDisconnected) {
+ globals.dispatch(
+ Actions.setRecordingTarget({target: getDefaultRecordingTargets()[0]}));
}
}
function recordMenu(routePage: string) {
- const targetOS = globals.state.recordConfig.targetOS;
+ const target = globals.state.recordingTarget;
const chromeProbe =
m('a[href="#!/record?p=chrome"]',
m(`li${routePage === 'chrome' ? '.active' : ''}`,
@@ -1045,7 +1053,7 @@
m('.title', 'Instructions'),
m('.sub', 'Generate config and instructions')))),
m('header', 'Probes'),
- m('ul', isChromeTarget(targetOS) ? [chromeProbe] : [
+ m('ul', isChromeTarget(target) ? [chromeProbe] : [
m('a[href="#!/record?p=cpu"]',
m(`li${routePage === 'cpu' ? '.active' : ''}`,
m('i.material-icons', 'subtitles'),