Merge "Revert "Infra: Revert LUCI changes for Mac-arm64""
diff --git a/Android.bp b/Android.bp
index fbf6d49..f3ebaa9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -925,7 +925,7 @@
":perfetto_src_ipc_client",
":perfetto_src_ipc_common",
":perfetto_src_perfetto_cmd_perfetto_cmd",
- ":perfetto_src_perfetto_cmd_protos_gen",
+ ":perfetto_src_perfetto_cmd_protos_cpp_gen",
":perfetto_src_perfetto_cmd_trigger_producer",
":perfetto_src_protozero_protozero",
":perfetto_src_tracing_common",
@@ -986,7 +986,7 @@
"perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
"perfetto_src_base_version_gen_h",
"perfetto_src_perfetto_cmd_gen_cc_config_descriptor",
- "perfetto_src_perfetto_cmd_protos_gen_headers",
+ "perfetto_src_perfetto_cmd_protos_cpp_gen_headers",
],
defaults: [
"perfetto_defaults",
@@ -2921,9 +2921,9 @@
],
}
-// GN: //protos/perfetto/config:perfetto_config_descriptor
+// GN: //protos/perfetto/config:merged_config_descriptor
genrule {
- name: "perfetto_protos_perfetto_config_perfetto_config_descriptor",
+ name: "perfetto_protos_perfetto_config_merged_config_descriptor",
srcs: [
"protos/perfetto/config/perfetto_config.proto",
],
@@ -2932,7 +2932,7 @@
],
cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --descriptor_set_out=$(out) $(in)",
out: [
- "perfetto_protos_perfetto_config_perfetto_config_descriptor.bin",
+ "perfetto_protos_perfetto_config_merged_config_descriptor.bin",
],
}
@@ -4143,6 +4143,7 @@
"protos/perfetto/trace/ftrace/clk.proto",
"protos/perfetto/trace/ftrace/compaction.proto",
"protos/perfetto/trace/ftrace/cpuhp.proto",
+ "protos/perfetto/trace/ftrace/cros_ec.proto",
"protos/perfetto/trace/ftrace/dmabuf_heap.proto",
"protos/perfetto/trace/ftrace/dpu.proto",
"protos/perfetto/trace/ftrace/ext4.proto",
@@ -4364,6 +4365,7 @@
"protos/perfetto/trace/ftrace/clk.proto",
"protos/perfetto/trace/ftrace/compaction.proto",
"protos/perfetto/trace/ftrace/cpuhp.proto",
+ "protos/perfetto/trace/ftrace/cros_ec.proto",
"protos/perfetto/trace/ftrace/dmabuf_heap.proto",
"protos/perfetto/trace/ftrace/dpu.proto",
"protos/perfetto/trace/ftrace/ext4.proto",
@@ -4419,6 +4421,7 @@
"external/perfetto/protos/perfetto/trace/ftrace/clk.gen.cc",
"external/perfetto/protos/perfetto/trace/ftrace/compaction.gen.cc",
"external/perfetto/protos/perfetto/trace/ftrace/cpuhp.gen.cc",
+ "external/perfetto/protos/perfetto/trace/ftrace/cros_ec.gen.cc",
"external/perfetto/protos/perfetto/trace/ftrace/dmabuf_heap.gen.cc",
"external/perfetto/protos/perfetto/trace/ftrace/dpu.gen.cc",
"external/perfetto/protos/perfetto/trace/ftrace/ext4.gen.cc",
@@ -4474,6 +4477,7 @@
"protos/perfetto/trace/ftrace/clk.proto",
"protos/perfetto/trace/ftrace/compaction.proto",
"protos/perfetto/trace/ftrace/cpuhp.proto",
+ "protos/perfetto/trace/ftrace/cros_ec.proto",
"protos/perfetto/trace/ftrace/dmabuf_heap.proto",
"protos/perfetto/trace/ftrace/dpu.proto",
"protos/perfetto/trace/ftrace/ext4.proto",
@@ -4529,6 +4533,7 @@
"external/perfetto/protos/perfetto/trace/ftrace/clk.gen.h",
"external/perfetto/protos/perfetto/trace/ftrace/compaction.gen.h",
"external/perfetto/protos/perfetto/trace/ftrace/cpuhp.gen.h",
+ "external/perfetto/protos/perfetto/trace/ftrace/cros_ec.gen.h",
"external/perfetto/protos/perfetto/trace/ftrace/dmabuf_heap.gen.h",
"external/perfetto/protos/perfetto/trace/ftrace/dpu.gen.h",
"external/perfetto/protos/perfetto/trace/ftrace/ext4.gen.h",
@@ -4588,6 +4593,7 @@
"protos/perfetto/trace/ftrace/clk.proto",
"protos/perfetto/trace/ftrace/compaction.proto",
"protos/perfetto/trace/ftrace/cpuhp.proto",
+ "protos/perfetto/trace/ftrace/cros_ec.proto",
"protos/perfetto/trace/ftrace/dmabuf_heap.proto",
"protos/perfetto/trace/ftrace/dpu.proto",
"protos/perfetto/trace/ftrace/ext4.proto",
@@ -4642,6 +4648,7 @@
"external/perfetto/protos/perfetto/trace/ftrace/clk.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/compaction.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/cpuhp.pb.cc",
+ "external/perfetto/protos/perfetto/trace/ftrace/cros_ec.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/dmabuf_heap.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/dpu.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/ext4.pb.cc",
@@ -4697,6 +4704,7 @@
"protos/perfetto/trace/ftrace/clk.proto",
"protos/perfetto/trace/ftrace/compaction.proto",
"protos/perfetto/trace/ftrace/cpuhp.proto",
+ "protos/perfetto/trace/ftrace/cros_ec.proto",
"protos/perfetto/trace/ftrace/dmabuf_heap.proto",
"protos/perfetto/trace/ftrace/dpu.proto",
"protos/perfetto/trace/ftrace/ext4.proto",
@@ -4751,6 +4759,7 @@
"external/perfetto/protos/perfetto/trace/ftrace/clk.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/compaction.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/cpuhp.pb.h",
+ "external/perfetto/protos/perfetto/trace/ftrace/cros_ec.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/dmabuf_heap.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/dpu.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/ext4.pb.h",
@@ -4810,6 +4819,7 @@
"protos/perfetto/trace/ftrace/clk.proto",
"protos/perfetto/trace/ftrace/compaction.proto",
"protos/perfetto/trace/ftrace/cpuhp.proto",
+ "protos/perfetto/trace/ftrace/cros_ec.proto",
"protos/perfetto/trace/ftrace/dmabuf_heap.proto",
"protos/perfetto/trace/ftrace/dpu.proto",
"protos/perfetto/trace/ftrace/ext4.proto",
@@ -4865,6 +4875,7 @@
"external/perfetto/protos/perfetto/trace/ftrace/clk.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/compaction.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/cpuhp.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/ftrace/cros_ec.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/dmabuf_heap.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/dpu.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/ext4.pbzero.cc",
@@ -4920,6 +4931,7 @@
"protos/perfetto/trace/ftrace/clk.proto",
"protos/perfetto/trace/ftrace/compaction.proto",
"protos/perfetto/trace/ftrace/cpuhp.proto",
+ "protos/perfetto/trace/ftrace/cros_ec.proto",
"protos/perfetto/trace/ftrace/dmabuf_heap.proto",
"protos/perfetto/trace/ftrace/dpu.proto",
"protos/perfetto/trace/ftrace/ext4.proto",
@@ -4975,6 +4987,7 @@
"external/perfetto/protos/perfetto/trace/ftrace/clk.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/compaction.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/cpuhp.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/ftrace/cros_ec.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/dmabuf_heap.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/dpu.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/ext4.pbzero.h",
@@ -6536,6 +6549,44 @@
],
}
+// GN: //protos/perfetto/trace/track_event:descriptor
+genrule {
+ name: "perfetto_protos_perfetto_trace_track_event_descriptor",
+ srcs: [
+ "protos/perfetto/trace/track_event/chrome_application_state_info.proto",
+ "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
+ "protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto",
+ "protos/perfetto/trace/track_event/chrome_frame_reporter.proto",
+ "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
+ "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
+ "protos/perfetto/trace/track_event/chrome_latency_info.proto",
+ "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
+ "protos/perfetto/trace/track_event/chrome_message_pump.proto",
+ "protos/perfetto/trace/track_event/chrome_mojo_event_info.proto",
+ "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
+ "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto",
+ "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
+ "protos/perfetto/trace/track_event/chrome_user_event.proto",
+ "protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto",
+ "protos/perfetto/trace/track_event/counter_descriptor.proto",
+ "protos/perfetto/trace/track_event/debug_annotation.proto",
+ "protos/perfetto/trace/track_event/log_message.proto",
+ "protos/perfetto/trace/track_event/process_descriptor.proto",
+ "protos/perfetto/trace/track_event/source_location.proto",
+ "protos/perfetto/trace/track_event/task_execution.proto",
+ "protos/perfetto/trace/track_event/thread_descriptor.proto",
+ "protos/perfetto/trace/track_event/track_descriptor.proto",
+ "protos/perfetto/trace/track_event/track_event.proto",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --descriptor_set_out=$(out) $(in)",
+ out: [
+ "perfetto_protos_perfetto_trace_track_event_descriptor.bin",
+ ],
+}
+
// GN: //protos/perfetto/trace/track_event:lite
genrule {
name: "perfetto_protos_perfetto_trace_track_event_lite_gen",
@@ -6662,44 +6713,6 @@
],
}
-// GN: //protos/perfetto/trace/track_event:track_event_descriptor
-genrule {
- name: "perfetto_protos_perfetto_trace_track_event_track_event_descriptor",
- srcs: [
- "protos/perfetto/trace/track_event/chrome_application_state_info.proto",
- "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
- "protos/perfetto/trace/track_event/chrome_content_settings_event_info.proto",
- "protos/perfetto/trace/track_event/chrome_frame_reporter.proto",
- "protos/perfetto/trace/track_event/chrome_histogram_sample.proto",
- "protos/perfetto/trace/track_event/chrome_keyed_service.proto",
- "protos/perfetto/trace/track_event/chrome_latency_info.proto",
- "protos/perfetto/trace/track_event/chrome_legacy_ipc.proto",
- "protos/perfetto/trace/track_event/chrome_message_pump.proto",
- "protos/perfetto/trace/track_event/chrome_mojo_event_info.proto",
- "protos/perfetto/trace/track_event/chrome_process_descriptor.proto",
- "protos/perfetto/trace/track_event/chrome_renderer_scheduler_state.proto",
- "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto",
- "protos/perfetto/trace/track_event/chrome_user_event.proto",
- "protos/perfetto/trace/track_event/chrome_window_handle_event_info.proto",
- "protos/perfetto/trace/track_event/counter_descriptor.proto",
- "protos/perfetto/trace/track_event/debug_annotation.proto",
- "protos/perfetto/trace/track_event/log_message.proto",
- "protos/perfetto/trace/track_event/process_descriptor.proto",
- "protos/perfetto/trace/track_event/source_location.proto",
- "protos/perfetto/trace/track_event/task_execution.proto",
- "protos/perfetto/trace/track_event/thread_descriptor.proto",
- "protos/perfetto/trace/track_event/track_descriptor.proto",
- "protos/perfetto/trace/track_event/track_event.proto",
- ],
- tools: [
- "aprotoc",
- ],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --descriptor_set_out=$(out) $(in)",
- out: [
- "perfetto_protos_perfetto_trace_track_event_track_event_descriptor.bin",
- ],
-}
-
// GN: //protos/perfetto/trace/track_event:zero
genrule {
name: "perfetto_protos_perfetto_trace_track_event_zero_gen",
@@ -6828,9 +6841,9 @@
],
}
-// GN: //protos/third_party/chromium:chrome_track_event_descriptor
+// GN: //protos/third_party/chromium:descriptor
genrule {
- name: "perfetto_protos_third_party_chromium_chrome_track_event_descriptor",
+ name: "perfetto_protos_third_party_chromium_descriptor",
srcs: [
"protos/perfetto/trace/track_event/chrome_application_state_info.proto",
"protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto",
@@ -6863,7 +6876,7 @@
],
cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --descriptor_set_out=$(out) $(in)",
out: [
- "perfetto_protos_third_party_chromium_chrome_track_event_descriptor.bin",
+ "perfetto_protos_third_party_chromium_descriptor.bin",
],
}
@@ -7208,7 +7221,7 @@
genrule {
name: "perfetto_src_perfetto_cmd_gen_cc_config_descriptor",
srcs: [
- ":perfetto_protos_perfetto_config_perfetto_config_descriptor",
+ ":perfetto_protos_perfetto_config_merged_config_descriptor",
],
cmd: "$(location tools/gen_cc_proto_descriptor.py) --gen_dir=$(genDir) --cpp_out=$(out) $(in)",
out: [
@@ -7232,9 +7245,9 @@
],
}
-// GN: //src/perfetto_cmd:protos
+// GN: //src/perfetto_cmd:protos_cpp
genrule {
- name: "perfetto_src_perfetto_cmd_protos_gen",
+ name: "perfetto_src_perfetto_cmd_protos_cpp_gen",
srcs: [
"src/perfetto_cmd/perfetto_cmd_state.proto",
],
@@ -7248,9 +7261,9 @@
],
}
-// GN: //src/perfetto_cmd:protos
+// GN: //src/perfetto_cmd:protos_cpp
genrule {
- name: "perfetto_src_perfetto_cmd_protos_gen_headers",
+ name: "perfetto_src_perfetto_cmd_protos_cpp_gen_headers",
srcs: [
"src/perfetto_cmd/perfetto_cmd_state.proto",
],
@@ -7989,7 +8002,7 @@
genrule {
name: "perfetto_src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
srcs: [
- ":perfetto_protos_third_party_chromium_chrome_track_event_descriptor",
+ ":perfetto_protos_third_party_chromium_descriptor",
],
cmd: "$(location tools/gen_cc_proto_descriptor.py) --gen_dir=$(genDir) --cpp_out=$(out) $(in)",
out: [
@@ -8019,7 +8032,7 @@
genrule {
name: "perfetto_src_trace_processor_importers_gen_cc_track_event_descriptor",
srcs: [
- ":perfetto_protos_perfetto_trace_track_event_track_event_descriptor",
+ ":perfetto_protos_perfetto_trace_track_event_descriptor",
],
cmd: "$(location tools/gen_cc_proto_descriptor.py) --gen_dir=$(genDir) --cpp_out=$(out) $(in)",
out: [
@@ -8146,6 +8159,7 @@
"src/trace_processor/metrics/sql/android/android_surfaceflinger.sql",
"src/trace_processor/metrics/sql/android/android_sysui_cuj.sql",
"src/trace_processor/metrics/sql/android/android_sysui_cuj_jank_query.sql",
+ "src/trace_processor/metrics/sql/android/android_sysui_cuj_surfaceflinger.sql",
"src/trace_processor/metrics/sql/android/android_task_names.sql",
"src/trace_processor/metrics/sql/android/android_thread_time_in_state.sql",
"src/trace_processor/metrics/sql/android/android_trace_quality.sql",
@@ -8332,6 +8346,7 @@
"src/trace_processor/importers/ftrace/ftrace_module.cc",
"src/trace_processor/importers/json/json_utils.cc",
"src/trace_processor/importers/ninja/ninja_log_parser.cc",
+ "src/trace_processor/importers/proto/android_camera_event_module.cc",
"src/trace_processor/importers/proto/async_track_set_tracker.cc",
"src/trace_processor/importers/proto/chrome_string_lookup.cc",
"src/trace_processor/importers/proto/chrome_system_probes_module.cc",
@@ -8417,6 +8432,7 @@
"src/trace_processor/dynamic/experimental_slice_layout_generator_unittest.cc",
"src/trace_processor/dynamic/thread_state_generator_unittest.cc",
"src/trace_processor/forwarding_trace_parser_unittest.cc",
+ "src/trace_processor/importers/ftrace/binder_tracker_unittest.cc",
"src/trace_processor/importers/ftrace/sched_event_tracker_unittest.cc",
"src/trace_processor/importers/fuchsia/fuchsia_trace_utils_unittest.cc",
"src/trace_processor/importers/memory_tracker/graph_processor_unittest.cc",
@@ -8477,6 +8493,7 @@
name: "perfetto_src_trace_processor_util_unittests",
srcs: [
"src/trace_processor/util/debug_annotation_parser_unittest.cc",
+ "src/trace_processor/util/gzip_utils_unittest.cc",
"src/trace_processor/util/proto_to_args_parser_unittest.cc",
"src/trace_processor/util/protozero_to_text_unittests.cc",
],
@@ -9166,7 +9183,6 @@
name: "perfetto_tools_trace_to_text_full",
srcs: [
"tools/trace_to_text/proto_full_utils.cc",
- "tools/trace_to_text/trace_to_text.cc",
],
}
@@ -9193,6 +9209,22 @@
],
}
+// GN: //tools/trace_to_text:trace_to_text_lib
+filegroup {
+ name: "perfetto_tools_trace_to_text_trace_to_text_lib",
+ srcs: [
+ "tools/trace_to_text/trace_to_text.cc",
+ ],
+}
+
+// GN: //tools/trace_to_text:unittests
+filegroup {
+ name: "perfetto_tools_trace_to_text_unittests",
+ srcs: [
+ "tools/trace_to_text/trace_to_text_unittest.cc",
+ ],
+}
+
// GN: //tools/trace_to_text:utils
filegroup {
name: "perfetto_tools_trace_to_text_utils",
@@ -9438,7 +9470,7 @@
":perfetto_src_kallsyms_kallsyms",
":perfetto_src_kallsyms_unittests",
":perfetto_src_perfetto_cmd_perfetto_cmd",
- ":perfetto_src_perfetto_cmd_protos_gen",
+ ":perfetto_src_perfetto_cmd_protos_cpp_gen",
":perfetto_src_perfetto_cmd_trigger_producer",
":perfetto_src_perfetto_cmd_unittests",
":perfetto_src_profiling_common_callstack_trie",
@@ -9463,6 +9495,7 @@
":perfetto_src_profiling_perf_producer_unittests",
":perfetto_src_profiling_perf_regs_parsing",
":perfetto_src_profiling_perf_unwinding",
+ ":perfetto_src_profiling_symbolizer_symbolize_database",
":perfetto_src_profiling_symbolizer_symbolizer",
":perfetto_src_profiling_symbolizer_unittests",
":perfetto_src_profiling_unittests",
@@ -9563,6 +9596,9 @@
":perfetto_src_tracing_test_tracing_integration_test",
":perfetto_src_tracing_unittests",
":perfetto_tools_sanitizers_unittests_sanitizers_unittests",
+ ":perfetto_tools_trace_to_text_trace_to_text_lib",
+ ":perfetto_tools_trace_to_text_unittests",
+ ":perfetto_tools_trace_to_text_utils",
],
shared_libs: [
"libandroidicu",
@@ -9674,7 +9710,7 @@
"perfetto_src_ipc_test_messages_cpp_gen_headers",
"perfetto_src_ipc_test_messages_ipc_gen_headers",
"perfetto_src_perfetto_cmd_gen_cc_config_descriptor",
- "perfetto_src_perfetto_cmd_protos_gen_headers",
+ "perfetto_src_perfetto_cmd_protos_cpp_gen_headers",
"perfetto_src_protozero_testing_messages_cpp_gen_headers",
"perfetto_src_protozero_testing_messages_lite_gen_headers",
"perfetto_src_protozero_testing_messages_zero_gen_headers",
@@ -9688,6 +9724,7 @@
"perfetto_src_traced_probes_ftrace_test_messages_cpp_gen_headers",
"perfetto_src_traced_probes_ftrace_test_messages_lite_gen_headers",
"perfetto_src_traced_probes_ftrace_test_messages_zero_gen_headers",
+ "perfetto_tools_trace_to_text_gen_cc_trace_descriptor",
],
defaults: [
"perfetto_defaults",
@@ -9964,6 +10001,7 @@
":perfetto_tools_trace_to_text_common",
":perfetto_tools_trace_to_text_full",
":perfetto_tools_trace_to_text_pprofbuilder",
+ ":perfetto_tools_trace_to_text_trace_to_text_lib",
":perfetto_tools_trace_to_text_utils",
],
static_libs: [
@@ -10287,7 +10325,7 @@
":perfetto_src_base_unix_socket",
":perfetto_src_ipc_client",
":perfetto_src_ipc_common",
- ":perfetto_src_perfetto_cmd_protos_gen",
+ ":perfetto_src_perfetto_cmd_protos_cpp_gen",
":perfetto_src_perfetto_cmd_trigger_perfetto_cmd",
":perfetto_src_perfetto_cmd_trigger_producer",
":perfetto_src_protozero_protozero",
@@ -10346,7 +10384,7 @@
"perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
"perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
"perfetto_src_base_version_gen_h",
- "perfetto_src_perfetto_cmd_protos_gen_headers",
+ "perfetto_src_perfetto_cmd_protos_cpp_gen_headers",
],
defaults: [
"perfetto_defaults",
diff --git a/BUILD b/BUILD
index ab6cc4c..283d9ce 100644
--- a/BUILD
+++ b/BUILD
@@ -787,7 +787,7 @@
perfetto_cc_proto_descriptor(
name = "src_perfetto_cmd_gen_cc_config_descriptor",
deps = [
- ":protos_perfetto_config_perfetto_config_descriptor",
+ ":protos_perfetto_config_merged_config_descriptor",
],
outs = [
"src/perfetto_cmd/perfetto_config.descriptor.h",
@@ -1005,7 +1005,7 @@
perfetto_cc_proto_descriptor(
name = "src_trace_processor_importers_gen_cc_chrome_track_event_descriptor",
deps = [
- ":protos_third_party_chromium_chrome_track_event_descriptor",
+ ":protos_third_party_chromium_descriptor",
],
outs = [
"src/trace_processor/importers/chrome_track_event.descriptor.h",
@@ -1025,7 +1025,7 @@
perfetto_cc_proto_descriptor(
name = "src_trace_processor_importers_gen_cc_track_event_descriptor",
deps = [
- ":protos_perfetto_trace_track_event_track_event_descriptor",
+ ":protos_perfetto_trace_track_event_descriptor",
],
outs = [
"src/trace_processor/importers/track_event.descriptor.h",
@@ -1067,6 +1067,7 @@
"src/trace_processor/metrics/sql/android/android_surfaceflinger.sql",
"src/trace_processor/metrics/sql/android/android_sysui_cuj.sql",
"src/trace_processor/metrics/sql/android/android_sysui_cuj_jank_query.sql",
+ "src/trace_processor/metrics/sql/android/android_sysui_cuj_surfaceflinger.sql",
"src/trace_processor/metrics/sql/android/android_task_names.sql",
"src/trace_processor/metrics/sql/android/android_thread_time_in_state.sql",
"src/trace_processor/metrics/sql/android/android_trace_quality.sql",
@@ -1475,6 +1476,8 @@
"src/trace_processor/importers/json/json_utils.h",
"src/trace_processor/importers/ninja/ninja_log_parser.cc",
"src/trace_processor/importers/ninja/ninja_log_parser.h",
+ "src/trace_processor/importers/proto/android_camera_event_module.cc",
+ "src/trace_processor/importers/proto/android_camera_event_module.h",
"src/trace_processor/importers/proto/async_track_set_tracker.cc",
"src/trace_processor/importers/proto/async_track_set_tracker.h",
"src/trace_processor/importers/proto/chrome_string_lookup.cc",
@@ -1927,7 +1930,6 @@
srcs = [
"tools/trace_to_text/proto_full_utils.cc",
"tools/trace_to_text/proto_full_utils.h",
- "tools/trace_to_text/trace_to_text.cc",
],
)
@@ -1949,6 +1951,16 @@
],
)
+# GN target: //tools/trace_to_text:trace_to_text_lib
+perfetto_filegroup(
+ name = "tools_trace_to_text_trace_to_text_lib",
+ srcs = [
+ "tools/trace_to_text/proto_full_utils.h",
+ "tools/trace_to_text/trace_to_text.cc",
+ "tools/trace_to_text/trace_to_text.h",
+ ],
+)
+
# GN target: //tools/trace_to_text:utils
perfetto_filegroup(
name = "tools_trace_to_text_utils",
@@ -1978,7 +1990,7 @@
],
)
-# GN target: //protos/perfetto/common:zero
+# GN target: //protos/perfetto/common:source_set
perfetto_proto_library(
name = "protos_perfetto_common_protos",
srcs = [
@@ -2028,7 +2040,7 @@
],
)
-# GN target: //protos/perfetto/config/android:zero
+# GN target: //protos/perfetto/config/android:source_set
perfetto_proto_library(
name = "protos_perfetto_config_android_protos",
srcs = [
@@ -2099,7 +2111,7 @@
],
)
-# GN target: //protos/perfetto/config/ftrace:zero
+# GN target: //protos/perfetto/config/ftrace:source_set
perfetto_proto_library(
name = "protos_perfetto_config_ftrace_protos",
srcs = [
@@ -2134,7 +2146,7 @@
],
)
-# GN target: //protos/perfetto/config/gpu:zero
+# GN target: //protos/perfetto/config/gpu:source_set
perfetto_proto_library(
name = "protos_perfetto_config_gpu_protos",
srcs = [
@@ -2170,7 +2182,7 @@
],
)
-# GN target: //protos/perfetto/config/inode_file:zero
+# GN target: //protos/perfetto/config/inode_file:source_set
perfetto_proto_library(
name = "protos_perfetto_config_inode_file_protos",
srcs = [
@@ -2206,7 +2218,7 @@
],
)
-# GN target: //protos/perfetto/config/interceptors:zero
+# GN target: //protos/perfetto/config/interceptors:source_set
perfetto_proto_library(
name = "protos_perfetto_config_interceptors_protos",
srcs = [
@@ -2237,15 +2249,18 @@
],
)
-# GN target: //protos/perfetto/config:merged_config
-perfetto_cc_proto_library(
- name = "protos_perfetto_config_merged_config",
+# GN target: //protos/perfetto/config:merged_config_descriptor
+perfetto_proto_descriptor(
+ name = "protos_perfetto_config_merged_config_descriptor",
deps = [
":protos_perfetto_config_merged_config_protos",
],
+ outs = [
+ "protos_perfetto_config_merged_config_descriptor.bin",
+ ],
)
-# GN target: //protos/perfetto/config:merged_config
+# GN target: //protos/perfetto/config:merged_config_source_set
perfetto_proto_library(
name = "protos_perfetto_config_merged_config_protos",
srcs = [
@@ -2254,28 +2269,6 @@
visibility = PERFETTO_CONFIG.public_visibility,
)
-# GN target: //protos/perfetto/config:perfetto_config_descriptor
-perfetto_proto_descriptor(
- name = "protos_perfetto_config_perfetto_config_descriptor",
- deps = [
- ":protos_perfetto_config_perfetto_config_protos",
- ],
- outs = [
- "protos_perfetto_config_perfetto_config_descriptor.bin",
- ],
-)
-
-# GN target: //protos/perfetto/config:perfetto_config_descriptor
-perfetto_proto_library(
- name = "protos_perfetto_config_perfetto_config_protos",
- srcs = [
- "protos/perfetto/config/perfetto_config.proto",
- ],
- visibility = [
- PERFETTO_CONFIG.proto_library_visibility,
- ],
-)
-
# GN target: //protos/perfetto/config/power:cpp
perfetto_cc_protocpp_library(
name = "protos_perfetto_config_power_cpp",
@@ -2292,7 +2285,7 @@
],
)
-# GN target: //protos/perfetto/config/power:zero
+# GN target: //protos/perfetto/config/power:source_set
perfetto_proto_library(
name = "protos_perfetto_config_power_protos",
srcs = [
@@ -2327,7 +2320,7 @@
],
)
-# GN target: //protos/perfetto/config/process_stats:zero
+# GN target: //protos/perfetto/config/process_stats:source_set
perfetto_proto_library(
name = "protos_perfetto_config_process_stats_protos",
srcs = [
@@ -2363,7 +2356,7 @@
],
)
-# GN target: //protos/perfetto/config/profiling:zero
+# GN target: //protos/perfetto/config/profiling:source_set
perfetto_proto_library(
name = "protos_perfetto_config_profiling_protos",
srcs = [
@@ -2388,7 +2381,7 @@
],
)
-# GN target: //protos/perfetto/config:zero
+# GN target: //protos/perfetto/config:source_set
perfetto_proto_library(
name = "protos_perfetto_config_protos",
srcs = [
@@ -2432,7 +2425,7 @@
],
)
-# GN target: //protos/perfetto/config/sys_stats:zero
+# GN target: //protos/perfetto/config/sys_stats:source_set
perfetto_proto_library(
name = "protos_perfetto_config_sys_stats_protos",
srcs = [
@@ -2471,7 +2464,7 @@
],
)
-# GN target: //protos/perfetto/config/track_event:zero
+# GN target: //protos/perfetto/config/track_event:source_set
perfetto_proto_library(
name = "protos_perfetto_config_track_event_protos",
srcs = [
@@ -2550,7 +2543,7 @@
],
)
-# GN target: //protos/perfetto/ipc:ipc
+# GN target: //protos/perfetto/ipc:source_set
perfetto_proto_library(
name = "protos_perfetto_ipc_protos",
srcs = [
@@ -2584,7 +2577,7 @@
],
)
-# GN target: //protos/perfetto/ipc:wire_protocol_cpp
+# GN target: //protos/perfetto/ipc:wire_protocol_source_set
perfetto_proto_library(
name = "protos_perfetto_ipc_wire_protocol_protos",
srcs = [
@@ -2735,7 +2728,7 @@
],
)
-# GN target: //protos/perfetto/trace/android:zero
+# GN target: //protos/perfetto/trace/android:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_android_protos",
srcs = [
@@ -2772,7 +2765,7 @@
],
)
-# GN target: //protos/perfetto/trace/chrome:zero
+# GN target: //protos/perfetto/trace/chrome:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_chrome_protos",
srcs = [
@@ -2797,7 +2790,7 @@
perfetto_proto_descriptor(
name = "protos_perfetto_trace_descriptor",
deps = [
- ":protos_perfetto_trace_protos",
+ ":protos_perfetto_trace_non_minimal_protos",
],
outs = [
"protos_perfetto_trace_descriptor.bin",
@@ -2812,7 +2805,7 @@
],
)
-# GN target: //protos/perfetto/trace/filesystem:zero
+# GN target: //protos/perfetto/trace/filesystem:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_filesystem_protos",
srcs = [
@@ -2839,7 +2832,7 @@
],
)
-# GN target: //protos/perfetto/trace/ftrace:zero
+# GN target: //protos/perfetto/trace/ftrace:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_ftrace_protos",
srcs = [
@@ -2849,6 +2842,7 @@
"protos/perfetto/trace/ftrace/clk.proto",
"protos/perfetto/trace/ftrace/compaction.proto",
"protos/perfetto/trace/ftrace/cpuhp.proto",
+ "protos/perfetto/trace/ftrace/cros_ec.proto",
"protos/perfetto/trace/ftrace/dmabuf_heap.proto",
"protos/perfetto/trace/ftrace/dpu.proto",
"protos/perfetto/trace/ftrace/ext4.proto",
@@ -2913,7 +2907,7 @@
],
)
-# GN target: //protos/perfetto/trace/gpu:zero
+# GN target: //protos/perfetto/trace/gpu:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_gpu_protos",
srcs = [
@@ -2948,7 +2942,7 @@
],
)
-# GN target: //protos/perfetto/trace/interned_data:zero
+# GN target: //protos/perfetto/trace/interned_data:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_interned_data_protos",
srcs = [
@@ -2977,15 +2971,7 @@
],
)
-# GN target: //protos/perfetto/trace:merged_trace
-perfetto_cc_proto_library(
- name = "protos_perfetto_trace_merged_trace",
- deps = [
- ":protos_perfetto_trace_merged_trace_protos",
- ],
-)
-
-# GN target: //protos/perfetto/trace:merged_trace
+# GN target: //protos/perfetto/trace:merged_trace_source_set
perfetto_proto_library(
name = "protos_perfetto_trace_merged_trace_protos",
srcs = [
@@ -3002,7 +2988,7 @@
],
)
-# GN target: //protos/perfetto/trace:minimal_zero
+# GN target: //protos/perfetto/trace:minimal_source_set
perfetto_proto_library(
name = "protos_perfetto_trace_minimal_protos",
srcs = [
@@ -3057,7 +3043,7 @@
],
)
-# GN target: //protos/perfetto/trace:non_minimal_zero
+# GN target: //protos/perfetto/trace:non_minimal_source_set
perfetto_proto_library(
name = "protos_perfetto_trace_non_minimal_protos",
srcs = [
@@ -3099,6 +3085,9 @@
":protos_perfetto_trace_system_info_protos",
":protos_perfetto_trace_track_event_protos",
],
+ exports = [
+ ":protos_perfetto_trace_track_event_protos",
+ ],
)
# GN target: //protos/perfetto/trace:non_minimal_zero
@@ -3143,7 +3132,7 @@
],
)
-# GN target: //protos/perfetto/trace/perfetto:zero
+# GN target: //protos/perfetto/trace/perfetto:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_perfetto_protos",
srcs = [
@@ -3171,7 +3160,7 @@
],
)
-# GN target: //protos/perfetto/trace/power:zero
+# GN target: //protos/perfetto/trace/power:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_power_protos",
srcs = [
@@ -3196,7 +3185,7 @@
],
)
-# GN target: //protos/perfetto/trace_processor:metrics_impl_zero
+# GN target: //protos/perfetto/trace_processor:metrics_impl_source_set
perfetto_proto_library(
name = "protos_perfetto_trace_processor_metrics_impl_protos",
srcs = [
@@ -3215,7 +3204,7 @@
],
)
-# GN target: //protos/perfetto/trace_processor:zero
+# GN target: //protos/perfetto/trace_processor:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_processor_protos",
srcs = [
@@ -3246,7 +3235,7 @@
],
)
-# GN target: //protos/perfetto/trace/profiling:zero
+# GN target: //protos/perfetto/trace/profiling:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_profiling_protos",
srcs = [
@@ -3273,46 +3262,6 @@
],
)
-# GN target: //protos/perfetto/trace:descriptor
-perfetto_proto_library(
- name = "protos_perfetto_trace_protos",
- srcs = [
- "protos/perfetto/trace/trace.proto",
- ],
- visibility = [
- PERFETTO_CONFIG.proto_library_visibility,
- ],
- deps = [
- ":protos_perfetto_common_protos",
- ":protos_perfetto_config_android_protos",
- ":protos_perfetto_config_ftrace_protos",
- ":protos_perfetto_config_gpu_protos",
- ":protos_perfetto_config_inode_file_protos",
- ":protos_perfetto_config_interceptors_protos",
- ":protos_perfetto_config_power_protos",
- ":protos_perfetto_config_process_stats_protos",
- ":protos_perfetto_config_profiling_protos",
- ":protos_perfetto_config_protos",
- ":protos_perfetto_config_sys_stats_protos",
- ":protos_perfetto_config_track_event_protos",
- ":protos_perfetto_trace_android_protos",
- ":protos_perfetto_trace_chrome_protos",
- ":protos_perfetto_trace_filesystem_protos",
- ":protos_perfetto_trace_ftrace_protos",
- ":protos_perfetto_trace_gpu_protos",
- ":protos_perfetto_trace_interned_data_protos",
- ":protos_perfetto_trace_minimal_protos",
- ":protos_perfetto_trace_non_minimal_protos",
- ":protos_perfetto_trace_perfetto_protos",
- ":protos_perfetto_trace_power_protos",
- ":protos_perfetto_trace_profiling_protos",
- ":protos_perfetto_trace_ps_protos",
- ":protos_perfetto_trace_sys_stats_protos",
- ":protos_perfetto_trace_system_info_protos",
- ":protos_perfetto_trace_track_event_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace/ps:lite
perfetto_cc_proto_library(
name = "protos_perfetto_trace_ps_lite",
@@ -3321,7 +3270,7 @@
],
)
-# GN target: //protos/perfetto/trace/ps:zero
+# GN target: //protos/perfetto/trace/ps:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_ps_protos",
srcs = [
@@ -3349,7 +3298,7 @@
],
)
-# GN target: //protos/perfetto/trace/sys_stats:zero
+# GN target: //protos/perfetto/trace/sys_stats:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_sys_stats_protos",
srcs = [
@@ -3380,7 +3329,7 @@
],
)
-# GN target: //protos/perfetto/trace/system_info:zero
+# GN target: //protos/perfetto/trace/system_info:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_system_info_protos",
srcs = [
@@ -3407,6 +3356,17 @@
],
)
+# GN target: //protos/perfetto/trace/track_event:descriptor
+perfetto_proto_descriptor(
+ name = "protos_perfetto_trace_track_event_descriptor",
+ deps = [
+ ":protos_perfetto_trace_track_event_protos",
+ ],
+ outs = [
+ "protos_perfetto_trace_track_event_descriptor.bin",
+ ],
+)
+
# GN target: //protos/perfetto/trace/track_event:lite
perfetto_cc_proto_library(
name = "protos_perfetto_trace_track_event_lite",
@@ -3415,7 +3375,7 @@
],
)
-# GN target: //protos/perfetto/trace/track_event:zero
+# GN target: //protos/perfetto/trace/track_event:source_set
perfetto_proto_library(
name = "protos_perfetto_trace_track_event_protos",
srcs = [
@@ -3449,31 +3409,6 @@
],
)
-# GN target: //protos/perfetto/trace/track_event:track_event_descriptor
-perfetto_proto_descriptor(
- name = "protos_perfetto_trace_track_event_track_event_descriptor",
- deps = [
- ":protos_perfetto_trace_track_event_track_event_protos",
- ],
- outs = [
- "protos_perfetto_trace_track_event_track_event_descriptor.bin",
- ],
-)
-
-# GN target: //protos/perfetto/trace/track_event:track_event_descriptor
-perfetto_proto_library(
- name = "protos_perfetto_trace_track_event_track_event_protos",
- srcs = [
- "protos/perfetto/trace/track_event/track_event.proto",
- ],
- visibility = [
- PERFETTO_CONFIG.proto_library_visibility,
- ],
- deps = [
- ":protos_perfetto_trace_track_event_protos",
- ],
-)
-
# GN target: //protos/perfetto/trace/track_event:zero
perfetto_cc_protozero_library(
name = "protos_perfetto_trace_track_event_zero",
@@ -3482,28 +3417,14 @@
],
)
-# GN target: //protos/third_party/chromium:chrome_track_event_descriptor
+# GN target: //protos/third_party/chromium:descriptor
perfetto_proto_descriptor(
- name = "protos_third_party_chromium_chrome_track_event_descriptor",
+ name = "protos_third_party_chromium_descriptor",
deps = [
- ":protos_third_party_chromium_chrome_track_event_protos",
+ ":protos_third_party_chromium_protos",
],
outs = [
- "protos_third_party_chromium_chrome_track_event_descriptor.bin",
- ],
-)
-
-# GN target: //protos/third_party/chromium:chrome_track_event_descriptor
-perfetto_proto_library(
- name = "protos_third_party_chromium_chrome_track_event_protos",
- srcs = [
- "protos/third_party/chromium/chrome_track_event.proto",
- ],
- visibility = [
- PERFETTO_CONFIG.proto_library_visibility,
- ],
- deps = [
- ":protos_perfetto_trace_track_event_protos",
+ "protos_third_party_chromium_descriptor.bin",
],
)
@@ -3515,7 +3436,7 @@
],
)
-# GN target: //protos/third_party/chromium:lite
+# GN target: //protos/third_party/chromium:source_set
perfetto_proto_library(
name = "protos_third_party_chromium_protos",
srcs = [
@@ -3525,9 +3446,12 @@
deps = [
":protos_perfetto_trace_track_event_protos",
],
+ exports = [
+ ":protos_perfetto_trace_track_event_protos",
+ ],
)
-# GN target: //protos/third_party/pprof:zero
+# GN target: //protos/third_party/pprof:source_set
perfetto_proto_library(
name = "protos_third_party_pprof_protos",
srcs = [
@@ -3546,15 +3470,15 @@
],
)
-# GN target: //src/perfetto_cmd:protos
+# GN target: //src/perfetto_cmd:protos_cpp
perfetto_cc_protocpp_library(
- name = "src_perfetto_cmd_protos",
+ name = "src_perfetto_cmd_protos_cpp",
deps = [
":src_perfetto_cmd_protos_protos",
],
)
-# GN target: //src/perfetto_cmd:protos
+# GN target: //src/perfetto_cmd:protos_source_set
perfetto_proto_library(
name = "src_perfetto_cmd_protos_protos",
srcs = [
@@ -3732,7 +3656,7 @@
":protozero",
":src_base_base",
":src_perfetto_cmd_gen_cc_config_descriptor",
- ":src_perfetto_cmd_protos",
+ ":src_perfetto_cmd_protos_cpp",
] + PERFETTO_CONFIG.deps.zlib,
)
@@ -4047,6 +3971,7 @@
":tools_trace_to_text_common",
":tools_trace_to_text_full",
":tools_trace_to_text_pprofbuilder",
+ ":tools_trace_to_text_trace_to_text_lib",
":tools_trace_to_text_utils",
],
visibility = [
diff --git a/BUILD.gn b/BUILD.gn
index 2e07e14..53b8d9a 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -77,6 +77,9 @@
if (enable_perfetto_unittests) {
import("gn/perfetto_unittests.gni")
test("perfetto_unittests") {
+ if (is_fuchsia) {
+ use_cfv2 = false
+ }
deps = perfetto_unittests_targets
}
all_targets += [ ":perfetto_unittests" ]
@@ -130,9 +133,9 @@
all_targets += [
"test/configs",
- # For syntax-checking the proto.
- "protos/perfetto/config:merged_config",
- "protos/perfetto/trace:merged_trace", # For syntax-checking the proto.
+ # For syntax-checking the protos.
+ "protos/perfetto/config:merged_config_lite",
+ "protos/perfetto/trace:merged_trace_lite",
# For checking all generated xxx.gen.{cc,h} files without waiting for
# embedders to try to use them and fail.
diff --git a/CHANGELOG b/CHANGELOG
index 95103e5..ebad664 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,23 +1,63 @@
Unreleased:
Tracing service and probes:
- * Changed output format of perfetto --query. Made the output more compact
- and added a summary of ongoing tracing sessions for the caller UID.
- * Added "cpufreq_period_ms" in data source "linux.sys_stats" to poll
- /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq periodically for
- current frequency of CPUs in kHz.
+ *
Trace Processor:
- * Add support for multiple SQL statements to be passed to
- TraceProcessor::ExecuteQuery. All queries will be executed fully, with
- the returned iterator yielding rows for the final statement.
- * Add support for multi-line SQL comments; previously only single line
- comments were supported.
+ *
UI:
- * Changed HTTP+RPC to use the /websocket endpoint available in newer
- versions of trace_processor --httpd.
+ * Added flow arrows between binder transaction pairs (request/reply
+ and async send/async recv).
SDK:
*
+v24.2 - 2022-02-10:
+ SDK:
+ * Revert of incremental timestamps, introduced in v24.0.
+ Some clients were depending on non-incremental timestamps.
+ Future releases will re-enable this but offer an opt-out.
+
+
+v24.1 - 2022-02-09:
+ Tracing service and probes:
+ * Fixed build failures on Windows.
+ Trace Processor:
+ * Fixed build failures on Windows.
+
+
+v24.0 - 2022-02-08:
+ Tracing service and probes:
+ * Added "cpufreq_period_ms" in data source "linux.sys_stats" to poll
+ /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq periodically.
+ * Added support for Trusty TEE workqueue events.
+ * Added support for more PMU events in traced_perf.
+ * Changed output format of perfetto --query. Made the output more compact
+ and added a summary of ongoing tracing sessions for the caller UID.
+ * Changed timeout for traced stall detection from 2s to 4s.
+ * Changed internal buffer management to split trace filtering in smaller
+ tasks and avoid too large memory allocation when filtering.
+ * Fixed a bug that could cause producers to see Flush() requests after an
+ OnStop() and mis-behave if the tracing session is extremely short.
+ Trace Processor:
+ * Added support for passing multiple SQL statements to ExecuteQuery(). All
+ queries will be executed fully, with the returned iterator yielding rows
+ for the final statement.
+ * Added support for multi-line SQL comments; previously only single line
+ comments were supported.
+ UI:
+ * Added support for parsing instant events from legacy systrace formats.
+ * Added ingestion and visualization for inet_sock_set_state and
+ tcp_retransmit_skb events, showing TCP connections on dedicated tracks.
+ * Changed HTTP+RPC to use the /websocket endpoint available in newer
+ versions of trace_processor --httpd.
+ * Changed text selection/copy: now allowed by default for DOM elements.
+ * Changed search to also lookup slices by ID when the term is a number.
+ * Changed postMessage() API, suppressed confirmation dialog when the opener
+ is in the same origin, for cases when the UI is self-hosted.
+ SDK:
+ * Changed timestamps emitted by the SDK to be incremental by default, using
+ ClockSnapshot + TracePacketDefaults.
+
+
v23.0 - 2022-01-11:
Tracing service and probes:
* Added workaround for a kernel ftrace bug causing some "comm" fields to be
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index c970450..a755b8c 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -289,7 +289,8 @@
# Enables Zlib support. This is used both by the "perfetto" cmdline client
# (for compressing traces) and by trace processor (for compressed traces).
enable_perfetto_zlib =
- enable_perfetto_trace_processor || enable_perfetto_platform_services
+ (enable_perfetto_trace_processor && !build_with_chromium) ||
+ enable_perfetto_platform_services
}
declare_args() {
diff --git a/gn/perfetto_unittests.gni b/gn/perfetto_unittests.gni
index 1a2b482..dbfa0fa 100644
--- a/gn/perfetto_unittests.gni
+++ b/gn/perfetto_unittests.gni
@@ -80,6 +80,7 @@
if (enable_perfetto_trace_processor) {
perfetto_unittests_targets += [ "src/trace_processor:unittests" ]
+ perfetto_unittests_targets += [ "tools/trace_to_text:unittests" ]
if (enable_perfetto_trace_processor_sqlite) {
perfetto_unittests_targets += [ "src/trace_processor/metrics:unittests" ]
diff --git a/gn/proto_library.gni b/gn/proto_library.gni
index 5b87753..d1794d5 100644
--- a/gn/proto_library.gni
+++ b/gn/proto_library.gni
@@ -254,6 +254,16 @@
}
}
+ # The distinction between deps and public_deps does not matter for GN
+ # but Bazel cares about the difference so we distinguish between the two.
+ public_deps_ = []
+ if (defined(invoker.public_deps)) {
+ foreach(dep, invoker.public_deps) {
+ public_deps_ = [ string_replace(dep, expansion_token, gen_type) ]
+ }
+ }
+ deps_ += public_deps_
+
if (gen_type == "zero") {
protozero_library(target_name_) {
proto_in_dir = proto_path
@@ -328,6 +338,7 @@
metadata = {
proto_library_sources = invoker.sources
import_dirs = import_dirs_
+ exports = get_path_info(public_deps_, "abspath")
}
forward_variables_from(invoker, vars_to_forward)
}
diff --git a/include/perfetto/ext/base/hash.h b/include/perfetto/ext/base/hash.h
index 50669f9..158a886 100644
--- a/include/perfetto/ext/base/hash.h
+++ b/include/perfetto/ext/base/hash.h
@@ -45,11 +45,14 @@
void Update(const char* data, size_t size) {
for (size_t i = 0; i < size; i++) {
result_ ^= static_cast<uint8_t>(data[i]);
+ // Note: Arithmetic overflow of unsigned integers is well defined in C++
+ // standard unlike signed integers.
+ // https://stackoverflow.com/a/41280273
result_ *= kFnv1a64Prime;
}
}
- uint64_t digest() { return result_; }
+ uint64_t digest() const { return result_; }
private:
static constexpr uint64_t kFnv1a64OffsetBasis = 0xcbf29ce484222325;
diff --git a/include/perfetto/tracing/internal/track_event_data_source.h b/include/perfetto/tracing/internal/track_event_data_source.h
index 3a3db7e..9229153 100644
--- a/include/perfetto/tracing/internal/track_event_data_source.h
+++ b/include/perfetto/tracing/internal/track_event_data_source.h
@@ -35,16 +35,14 @@
namespace perfetto {
-// A function for converting an abstract timestamp into a
-// perfetto::TraceTimestamp struct. By specialising this template and defining
+// This template provides a way to convert an abstract timestamp into the trace
+// clock timebase in nanoseconds. By specialising this template and defining
// static ConvertTimestampToTraceTimeNs function in it the user can register
-// additional timestamp types. The return value should specify the
-// clock domain used by the timestamp as well as its value.
+// additional timestamp types. The return value should specify the clock used by
+// the timestamp as well as its value in nanoseconds.
//
-// The supported clock domains are the ones described in
-// perfetto.protos.ClockSnapshot. However, custom clock IDs (>=64) are
-// reserved for internal use by the SDK for the time being.
-// The timestamp value should be in nanoseconds regardless of the clock domain.
+// The users should see the specialisation for uint64_t below as an example.
+// Note that the specialisation should be defined in perfetto namespace.
template <typename T>
struct TraceTimestampTraits;
@@ -241,7 +239,7 @@
Arguments&&... args) PERFETTO_NO_INLINE {
TraceForCategoryImpl(instances, category, event_name, type,
TrackEventInternal::kDefaultTrack,
- TrackEventInternal::GetTraceTime(),
+ TrackEventInternal::GetTimeNs(),
std::forward<Arguments>(args)...);
}
@@ -263,7 +261,7 @@
Arguments&&... args) PERFETTO_NO_INLINE {
TraceForCategoryImpl(
instances, category, event_name, type, std::forward<TrackType>(track),
- TrackEventInternal::GetTraceTime(), std::forward<Arguments>(args)...);
+ TrackEventInternal::GetTimeNs(), std::forward<Arguments>(args)...);
}
// Trace point which takes a timestamp, but not track.
@@ -316,7 +314,7 @@
ValueType value) PERFETTO_ALWAYS_INLINE {
PERFETTO_DCHECK(type == perfetto::protos::pbzero::TrackEvent::TYPE_COUNTER);
TraceForCategory(instances, category, /*name=*/nullptr, type, track,
- TrackEventInternal::GetTraceTime(), value);
+ TrackEventInternal::GetTimeNs(), value);
}
// Trace point with with a timestamp and a counter sample.
@@ -362,8 +360,7 @@
TrackRegistry::Get()->UpdateTrack(track, desc.SerializeAsString());
Base::template Trace([&](typename Base::TraceContext ctx) {
TrackEventInternal::WriteTrackDescriptor(
- track, ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState(),
- TrackEventInternal::GetTraceTime());
+ track, ctx.tls_inst_->trace_writer.get());
});
}
@@ -455,14 +452,14 @@
TrackEventIncrementalState* incr_state = ctx.GetIncrementalState();
if (incr_state->was_cleared) {
incr_state->was_cleared = false;
- TrackEventInternal::ResetIncrementalState(trace_writer, incr_state,
+ TrackEventInternal::ResetIncrementalState(trace_writer,
trace_timestamp);
}
// Write the track descriptor before any event on the track.
if (track) {
TrackEventInternal::WriteTrackDescriptorIfNeeded(
- track, trace_writer, incr_state, trace_timestamp);
+ track, trace_writer, incr_state);
}
// Write the event itself.
@@ -516,8 +513,7 @@
TrackRegistry::Get()->UpdateTrack(track, std::move(callback));
Base::template Trace([&](typename Base::TraceContext ctx) {
TrackEventInternal::WriteTrackDescriptor(
- track, ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState(),
- TrackEventInternal::GetTraceTime());
+ track, ctx.tls_inst_->trace_writer.get());
});
}
diff --git a/include/perfetto/tracing/internal/track_event_internal.h b/include/perfetto/tracing/internal/track_event_internal.h
index 6fed09e..037dc09 100644
--- a/include/perfetto/tracing/internal/track_event_internal.h
+++ b/include/perfetto/tracing/internal/track_event_internal.h
@@ -35,24 +35,13 @@
// Represents a point in time for the clock specified by |clock_id|.
struct TraceTimestamp {
- // Clock IDs have the following semantic:
- // [1, 63]: Builtin types, see BuiltinClock from
- // ../common/builtin_clock.proto.
- // [64, 127]: User-defined clocks. These clocks are sequence-scoped. They
- // are only valid within the same |trusted_packet_sequence_id|
- // (i.e. only for TracePacket(s) emitted by the same TraceWriter
- // that emitted the clock snapshot).
- // [128, MAX]: Reserved for future use. The idea is to allow global clock
- // IDs and setting this ID to hash(full_clock_name) & ~127.
- // Learn more: `clock_snapshot.proto`
- uint32_t clock_id;
- uint64_t value;
+ protos::pbzero::BuiltinClock clock_id;
+ uint64_t nanoseconds;
};
class EventContext;
class TrackEventSessionObserver;
struct Category;
-struct TraceTimestamp;
namespace protos {
namespace gen {
class TrackEventConfig;
@@ -96,12 +85,6 @@
struct TrackEventIncrementalState {
static constexpr size_t kMaxInternedDataFields = 32;
- // Packet-sequence-scoped clock that encodes microsecond timestamps in the
- // domain of the clock returned by GetClockId() as delta values - see
- // Clock::is_incremental in perfetto/trace/clock_snapshot.proto.
- // Default unit: nanoseconds.
- static constexpr uint32_t kClockIdIncremental = 64;
-
bool was_cleared = true;
// A heap-allocated message for storing newly seen interned data while we are
@@ -133,11 +116,6 @@
// this tracing session. The value in the map indicates whether the category
// is enabled or disabled.
std::unordered_map<std::string, bool> dynamic_categories;
-
- // The latest reference timestamp that was used in a TracePacket or in a
- // ClockSnapshot. The increment between this timestamp and the current trace
- // time (GetTimeNs) is a value in kClockIdIncremental's domain.
- uint64_t last_timestamp_ns = 0;
};
// The backend portion of the track event trace point implemention. Outlined to
@@ -168,11 +146,9 @@
const Category* category,
const char* name,
perfetto::protos::pbzero::TrackEvent::Type,
- const TraceTimestamp& timestamp);
+ TraceTimestamp timestamp = {GetClockId(), GetTimeNs()});
- static void ResetIncrementalState(TraceWriterBase* trace_writer,
- TrackEventIncrementalState* incr_state,
- const TraceTimestamp& timestamp);
+ static void ResetIncrementalState(TraceWriterBase*, TraceTimestamp);
// TODO(altimin): Remove this method once Chrome uses
// EventContext::AddDebugAnnotation directly.
@@ -192,29 +168,24 @@
static void WriteTrackDescriptorIfNeeded(
const TrackType& track,
TraceWriterBase* trace_writer,
- TrackEventIncrementalState* incr_state,
- const TraceTimestamp& timestamp) {
+ TrackEventIncrementalState* incr_state) {
auto it_and_inserted = incr_state->seen_tracks.insert(track.uuid);
if (PERFETTO_LIKELY(!it_and_inserted.second))
return;
- WriteTrackDescriptor(track, trace_writer, incr_state, timestamp);
+ WriteTrackDescriptor(track, trace_writer);
}
// Unconditionally write a track descriptor into the trace.
template <typename TrackType>
static void WriteTrackDescriptor(const TrackType& track,
- TraceWriterBase* trace_writer,
- TrackEventIncrementalState* incr_state,
- const TraceTimestamp& timestamp) {
+ TraceWriterBase* trace_writer) {
TrackRegistry::Get()->SerializeTrack(
- track, NewTracePacket(trace_writer, incr_state, timestamp));
+ track, NewTracePacket(trace_writer, {GetClockId(), GetTimeNs()}));
}
// Get the current time in nanoseconds in the trace clock timebase.
static uint64_t GetTimeNs();
- static TraceTimestamp GetTraceTime();
-
// Get the clock used by GetTimeNs().
static constexpr protos::pbzero::BuiltinClock GetClockId() {
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) && \
@@ -233,8 +204,7 @@
private:
static protozero::MessageHandle<protos::pbzero::TracePacket> NewTracePacket(
TraceWriterBase*,
- TrackEventIncrementalState*,
- const TraceTimestamp&,
+ TraceTimestamp,
uint32_t seq_flags =
protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
static protos::pbzero::DebugAnnotation* AddDebugAnnotation(
diff --git a/include/perfetto/tracing/track_event_state_tracker.h b/include/perfetto/tracing/track_event_state_tracker.h
index e97f035..7b2437e 100644
--- a/include/perfetto/tracing/track_event_state_tracker.h
+++ b/include/perfetto/tracing/track_event_state_tracker.h
@@ -80,10 +80,6 @@
std::map<uint64_t /*iid*/, std::string> event_names;
std::map<uint64_t /*iid*/, std::string> event_categories;
std::map<uint64_t /*iid*/, std::string> debug_annotation_names;
- // Current absolute timestamp of the incremental clock.
- uint64_t most_recent_absolute_time_ns = 0;
- // default_clock_id == 0 means, no default clock_id is set.
- uint32_t default_clock_id = 0;
};
// State for the entire tracing session. Shared by all trace writer sequences
diff --git a/infra/luci/generated/cr-buildbucket.cfg b/infra/luci/generated/cr-buildbucket.cfg
index 18a7c5a..a835dad 100644
--- a/infra/luci/generated/cr-buildbucket.cfg
+++ b/infra/luci/generated/cr-buildbucket.cfg
@@ -29,12 +29,11 @@
cipd_version: "refs/heads/master"
cmd: "luciexe"
}
- properties: "{\"recipe\":\"perfetto\"}"
+ properties:
+ '{'
+ ' "recipe": "perfetto"'
+ '}'
service_account: "perfetto-luci-official-builder@chops-service-accounts.iam.gserviceaccount.com"
- experiments {
- key: "luci.use_realms"
- value: 100
- }
}
builders {
name: "perfetto-official-builder-linux"
@@ -47,12 +46,11 @@
cipd_version: "refs/heads/master"
cmd: "luciexe"
}
- properties: "{\"recipe\":\"perfetto\"}"
+ properties:
+ '{'
+ ' "recipe": "perfetto"'
+ '}'
service_account: "perfetto-luci-official-builder@chops-service-accounts.iam.gserviceaccount.com"
- experiments {
- key: "luci.use_realms"
- value: 100
- }
}
builders {
name: "perfetto-official-builder-mac"
@@ -65,12 +63,15 @@
cipd_version: "refs/heads/master"
cmd: "luciexe"
}
- properties: "{\"recipe\":\"perfetto\"}"
- service_account: "perfetto-luci-official-builder@chops-service-accounts.iam.gserviceaccount.com"
- experiments {
- key: "luci.use_realms"
- value: 100
+ properties:
+ '{'
+ ' "recipe": "perfetto"'
+ '}'
+ caches {
+ name: "macos_sdk"
+ path: "macos_sdk"
}
+ service_account: "perfetto-luci-official-builder@chops-service-accounts.iam.gserviceaccount.com"
}
builders {
name: "perfetto-official-builder-windows"
@@ -83,12 +84,15 @@
cipd_version: "refs/heads/master"
cmd: "luciexe"
}
- properties: "{\"recipe\":\"perfetto\"}"
- service_account: "perfetto-luci-official-builder@chops-service-accounts.iam.gserviceaccount.com"
- experiments {
- key: "luci.use_realms"
- value: 100
+ properties:
+ '{'
+ ' "recipe": "perfetto"'
+ '}'
+ caches {
+ name: "windows_sdk"
+ path: "windows_sdk"
}
+ service_account: "perfetto-luci-official-builder@chops-service-accounts.iam.gserviceaccount.com"
}
}
}
diff --git a/infra/luci/generated/luci-scheduler.cfg b/infra/luci/generated/luci-scheduler.cfg
index 89ae71b..dd7f20b 100644
--- a/infra/luci/generated/luci-scheduler.cfg
+++ b/infra/luci/generated/luci-scheduler.cfg
@@ -10,7 +10,7 @@
acl_sets: "official"
buildbucket {
server: "cr-buildbucket.appspot.com"
- bucket: "luci.perfetto.official"
+ bucket: "official"
builder: "perfetto-official-builder-android"
}
}
@@ -20,7 +20,7 @@
acl_sets: "official"
buildbucket {
server: "cr-buildbucket.appspot.com"
- bucket: "luci.perfetto.official"
+ bucket: "official"
builder: "perfetto-official-builder-linux"
}
}
@@ -30,7 +30,7 @@
acl_sets: "official"
buildbucket {
server: "cr-buildbucket.appspot.com"
- bucket: "luci.perfetto.official"
+ bucket: "official"
builder: "perfetto-official-builder-mac"
}
}
@@ -40,7 +40,7 @@
acl_sets: "official"
buildbucket {
server: "cr-buildbucket.appspot.com"
- bucket: "luci.perfetto.official"
+ bucket: "official"
builder: "perfetto-official-builder-windows"
}
}
diff --git a/infra/luci/generated/project.cfg b/infra/luci/generated/project.cfg
index fbf2a59..2aad4e1 100644
--- a/infra/luci/generated/project.cfg
+++ b/infra/luci/generated/project.cfg
@@ -6,3 +6,10 @@
name: "perfetto"
access: "group:all"
+lucicfg {
+ version: "1.30.9"
+ package_dir: ".."
+ config_dir: "generated"
+ entry_point: "main.star"
+ experiments: "crbug.com/1182002"
+}
diff --git a/infra/luci/main.star b/infra/luci/main.star
index 4119e2d..316a505 100755
--- a/infra/luci/main.star
+++ b/infra/luci/main.star
@@ -13,11 +13,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-lucicfg.check_version("1.23.3", "Please update depot_tools")
+lucicfg.check_version("1.30.9", "Please update depot_tools")
-# Enable LUCI Realms support and launch all builds in realms-aware mode.
-lucicfg.enable_experiment("crbug.com/1085650")
-luci.builder.defaults.experiments.set({"luci.use_realms": 100})
+# Use LUCI Scheduler BBv2 names and add Scheduler realms configs.
+lucicfg.enable_experiment("crbug.com/1182002")
# Enable bbagent.
luci.recipe.defaults.use_bbagent.set(True)
@@ -75,7 +74,7 @@
],
)
-def official_builder(name, os):
+def official_builder(name, os, caches=[]):
luci.builder(
name = name,
bucket = "official",
@@ -98,9 +97,13 @@
refs = ["refs/tags/v.+"],
),
],
+ caches = [
+ swarming.cache(cache, name = cache)
+ for cache in caches
+ ]
)
official_builder("perfetto-official-builder-linux", "Linux")
-official_builder("perfetto-official-builder-mac", "Mac")
-official_builder("perfetto-official-builder-windows", "Windows")
+official_builder("perfetto-official-builder-mac", "Mac", ["macos_sdk"])
+official_builder("perfetto-official-builder-windows", "Windows", ["windows_sdk"])
official_builder("perfetto-official-builder-android", "Linux")
diff --git a/protos/perfetto/common/trace_stats.proto b/protos/perfetto/common/trace_stats.proto
index c6a9fbf..f1afc2a 100644
--- a/protos/perfetto/common/trace_stats.proto
+++ b/protos/perfetto/common/trace_stats.proto
@@ -20,7 +20,7 @@
// Statistics for the internals of the tracing service.
//
-// Next id: 11.
+// Next id: 16.
message TraceStats {
// From TraceBuffer::Stats.
//
@@ -167,4 +167,23 @@
optional uint64 errors = 4;
}
optional FilterStats filter_stats = 11;
+
+ // Count of Flush() requests (either from the Consumer, or self-induced
+ // periodic flushes). The final Flush() is also included in the count.
+ optional uint64 flushes_requested = 12;
+
+ // The count of the Flush() requests that were completed succesfully.
+ // In a well behaving trace this should always be == `flush_requests`.
+ optional uint64 flushes_succeeded = 13;
+
+ // The count of the Flush() requests that failed (in most timed out).
+ // In a well behaving trace this should always be == 0.
+ optional uint64 flushes_failed = 14;
+
+ enum FinalFlushOutcome {
+ FINAL_FLUSH_UNSPECIFIED = 0;
+ FINAL_FLUSH_SUCCEEDED = 1;
+ FINAL_FLUSH_FAILED = 2;
+ }
+ optional FinalFlushOutcome final_flush_outcome = 15;
}
diff --git a/protos/perfetto/config/BUILD.gn b/protos/perfetto/config/BUILD.gn
index de9c1f5..471bfbe 100644
--- a/protos/perfetto/config/BUILD.gn
+++ b/protos/perfetto/config/BUILD.gn
@@ -43,13 +43,6 @@
]
}
-# This target is not used in the tree and is built only to guarantee that the
-# autogenerated merged proto has a valid syntax.
-perfetto_proto_library("merged_config") {
- proto_generators = [ "lite" ]
- sources = [ "perfetto_config.proto" ]
-}
-
perfetto_proto_library("descriptor") {
proto_generators = [ "descriptor" ]
generate_descriptor = "config.descriptor"
@@ -57,8 +50,19 @@
sources = [ "trace_config.proto" ]
}
-perfetto_proto_library("perfetto_config_descriptor") {
+# This target is not used in the tree and is built only to guarantee that the
+# autogenerated merged proto has a valid syntax.
+perfetto_proto_library("merged_config_@TYPE@") {
+ proto_generators = [
+ "lite",
+ "source_set",
+ ]
+ sources = [ "perfetto_config.proto" ]
+}
+
+perfetto_proto_library("merged_config_descriptor") {
proto_generators = [ "descriptor" ]
generate_descriptor = "perfetto_config.descriptor"
sources = [ "perfetto_config.proto" ]
+ deps = [ ":merged_config_source_set" ]
}
diff --git a/protos/perfetto/ipc/BUILD.gn b/protos/perfetto/ipc/BUILD.gn
index 49c077e..fb9bfcf 100644
--- a/protos/perfetto/ipc/BUILD.gn
+++ b/protos/perfetto/ipc/BUILD.gn
@@ -21,6 +21,7 @@
proto_generators = [
"ipc",
"cpp",
+ "source_set",
]
sources = [
"consumer_port.proto",
@@ -39,6 +40,7 @@
proto_generators = [
"zero",
"cpp",
+ "source_set",
]
sources = [ "wire_protocol.proto" ]
}
diff --git a/protos/perfetto/metrics/BUILD.gn b/protos/perfetto/metrics/BUILD.gn
index a0aec35..751ed94 100644
--- a/protos/perfetto/metrics/BUILD.gn
+++ b/protos/perfetto/metrics/BUILD.gn
@@ -33,6 +33,6 @@
perfetto_proto_library("descriptor") {
proto_generators = [ "descriptor" ]
generate_descriptor = "metrics.descriptor"
- deps = [ "android:source_set" ]
+ deps = [ ":source_set" ]
sources = [ "metrics.proto" ]
}
diff --git a/protos/perfetto/metrics/android/network_metric.proto b/protos/perfetto/metrics/android/network_metric.proto
index fea1d1d..393e76f 100644
--- a/protos/perfetto/metrics/android/network_metric.proto
+++ b/protos/perfetto/metrics/android/network_metric.proto
@@ -50,13 +50,16 @@
// Per core packets statistic.
repeated CorePacketStatistic core = 2;
+
+ // GRO aggregation ratio.
+ optional string gro_aggregation_ratio = 3;
}
message Tx {
- // Total packets statistic
+ // Total packets statistic.
optional PacketStatistic total = 1;
- // Per core packets statistic
+ // Per core packets statistic.
repeated CorePacketStatistic core = 2;
}
@@ -110,4 +113,7 @@
// SoftIrq NET_RX action metrics.
optional NetRxAction net_rx_action = 2;
+
+ // Packet retransmission rate.
+ optional double retransmission_rate = 3;
}
diff --git a/protos/perfetto/metrics/chrome/scroll_jank.proto b/protos/perfetto/metrics/chrome/scroll_jank.proto
index 6fea1d8..3fe397d 100644
--- a/protos/perfetto/metrics/chrome/scroll_jank.proto
+++ b/protos/perfetto/metrics/chrome/scroll_jank.proto
@@ -30,4 +30,5 @@
optional int64 num_scroll_update_count = 5 [(unit) = "count_biggerIsBetter"];
optional int64 num_scroll_update_jank_count = 6
[(unit) = "count_smallerIsBetter"];
+ optional double scroll_jank_budget_ms = 7 [(unit) = "ms_smallerIsBetter"];
}
diff --git a/protos/perfetto/metrics/chrome/touch_jank.proto b/protos/perfetto/metrics/chrome/touch_jank.proto
index beebfb5..20318b8 100644
--- a/protos/perfetto/metrics/chrome/touch_jank.proto
+++ b/protos/perfetto/metrics/chrome/touch_jank.proto
@@ -31,4 +31,5 @@
optional int64 num_touch_update_count = 5 [(unit) = "count_biggerIsBetter"];
optional int64 num_touch_update_jank_count = 6
[(unit) = "count_smallerIsBetter"];
+ optional double touch_jank_budget_ms = 7 [(unit) = "ms_smallerIsBetter"];
}
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index 03f6690..afcb6d7 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -907,13 +907,16 @@
// Per core packets statistic.
repeated CorePacketStatistic core = 2;
+
+ // GRO aggregation ratio.
+ optional string gro_aggregation_ratio = 3;
}
message Tx {
- // Total packets statistic
+ // Total packets statistic.
optional PacketStatistic total = 1;
- // Per core packets statistic
+ // Per core packets statistic.
repeated CorePacketStatistic core = 2;
}
@@ -967,6 +970,9 @@
// SoftIrq NET_RX action metrics.
optional NetRxAction net_rx_action = 2;
+
+ // Packet retransmission rate.
+ optional double retransmission_rate = 3;
}
// End of protos/perfetto/metrics/android/network_metric.proto
diff --git a/protos/perfetto/trace/BUILD.gn b/protos/perfetto/trace/BUILD.gn
index a807061..cfcca49 100644
--- a/protos/perfetto/trace/BUILD.gn
+++ b/protos/perfetto/trace/BUILD.gn
@@ -71,6 +71,15 @@
]
}
+# This is only for Bazel build generation.
+group("source_set") {
+ testonly = true
+ public_deps = [
+ ":minimal_source_set",
+ ":non_minimal_source_set",
+ ]
+}
+
perfetto_proto_library("non_minimal_@TYPE@") {
proto_generators = [
"cpp",
@@ -96,6 +105,7 @@
"track_event:@TYPE@",
]
sources = proto_sources_non_minimal
+ public_deps = [ "track_event:@TYPE@" ]
}
perfetto_proto_library("minimal_@TYPE@") {
@@ -103,13 +113,6 @@
sources = proto_sources_minimal
}
-# This target is not used in the tree and is built only to guarantee that the
-# autogenerated merged proto has a valid syntax.
-perfetto_proto_library("merged_trace") {
- proto_generators = [ "lite" ]
- sources = [ "perfetto_trace.proto" ]
-}
-
perfetto_proto_library("descriptor") {
proto_generators = [ "descriptor" ]
generate_descriptor = "trace.descriptor"
@@ -130,3 +133,13 @@
sources = [ "test_extensions.proto" ]
deps = [ "track_event:source_set" ]
}
+
+# This target are not used in the tree and is built only to guarantee that the
+# autogenerated merged proto has a valid syntax.
+perfetto_proto_library("merged_trace_@TYPE@") {
+ proto_generators = [
+ "lite",
+ "source_set",
+ ]
+ sources = [ "perfetto_trace.proto" ]
+}
diff --git a/protos/perfetto/trace/chrome/BUILD.gn b/protos/perfetto/trace/chrome/BUILD.gn
index dc4ecb2..2cad830 100644
--- a/protos/perfetto/trace/chrome/BUILD.gn
+++ b/protos/perfetto/trace/chrome/BUILD.gn
@@ -22,7 +22,7 @@
]
}
-perfetto_proto_library("minimal_complete_lite") {
+perfetto_proto_library("minimal_complete_@TYPE@") {
proto_generators = [ "lite" ]
deps = [
":@TYPE@",
diff --git a/protos/perfetto/trace/ftrace/BUILD.gn b/protos/perfetto/trace/ftrace/BUILD.gn
index 7edf7fe..2b6182d 100644
--- a/protos/perfetto/trace/ftrace/BUILD.gn
+++ b/protos/perfetto/trace/ftrace/BUILD.gn
@@ -17,12 +17,6 @@
import("all_protos.gni")
perfetto_proto_library("@TYPE@") {
- proto_generators = [
- "cpp",
- "zero",
- "lite",
- "source_set",
- ]
sources = ftrace_proto_names
}
diff --git a/protos/perfetto/trace/ftrace/all_protos.gni b/protos/perfetto/trace/ftrace/all_protos.gni
index ae4e3d0..7d43696 100644
--- a/protos/perfetto/trace/ftrace/all_protos.gni
+++ b/protos/perfetto/trace/ftrace/all_protos.gni
@@ -26,6 +26,7 @@
"clk.proto",
"compaction.proto",
"cpuhp.proto",
+ "cros_ec.proto",
"dmabuf_heap.proto",
"dpu.proto",
"ext4.proto",
diff --git a/protos/perfetto/trace/ftrace/cros_ec.proto b/protos/perfetto/trace/ftrace/cros_ec.proto
new file mode 100644
index 0000000..b3ba4fb
--- /dev/null
+++ b/protos/perfetto/trace/ftrace/cros_ec.proto
@@ -0,0 +1,15 @@
+// Autogenerated by:
+// ../../tools/ftrace_proto_gen/ftrace_proto_gen.cc
+// Do not edit.
+
+syntax = "proto2";
+package perfetto.protos;
+
+message CrosEcSensorhubDataFtraceEvent {
+ optional int64 current_time = 1;
+ optional int64 current_timestamp = 2;
+ optional int64 delta = 3;
+ optional uint32 ec_fifo_timestamp = 4;
+ optional uint32 ec_sensor_num = 5;
+ optional int64 fifo_timestamp = 6;
+}
diff --git a/protos/perfetto/trace/ftrace/ftrace_event.proto b/protos/perfetto/trace/ftrace/ftrace_event.proto
index 5b42169..13b3acb 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event.proto
@@ -26,6 +26,7 @@
import "protos/perfetto/trace/ftrace/clk.proto";
import "protos/perfetto/trace/ftrace/compaction.proto";
import "protos/perfetto/trace/ftrace/cpuhp.proto";
+import "protos/perfetto/trace/ftrace/cros_ec.proto";
import "protos/perfetto/trace/ftrace/dmabuf_heap.proto";
import "protos/perfetto/trace/ftrace/dpu.proto";
import "protos/perfetto/trace/ftrace/ext4.proto";
@@ -456,5 +457,8 @@
NetDevXmitFtraceEvent net_dev_xmit = 361;
InetSockSetStateFtraceEvent inet_sock_set_state = 362;
TcpRetransmitSkbFtraceEvent tcp_retransmit_skb = 363;
+ CrosEcSensorhubDataFtraceEvent cros_ec_sensorhub_data = 364;
+ NapiGroReceiveEntryFtraceEvent napi_gro_receive_entry = 365;
+ NapiGroReceiveExitFtraceEvent napi_gro_receive_exit = 366;
}
}
diff --git a/protos/perfetto/trace/ftrace/net.proto b/protos/perfetto/trace/ftrace/net.proto
index e5ffbfb..866a599 100644
--- a/protos/perfetto/trace/ftrace/net.proto
+++ b/protos/perfetto/trace/ftrace/net.proto
@@ -16,3 +16,27 @@
optional int32 rc = 3;
optional uint64 skbaddr = 4;
}
+message NapiGroReceiveEntryFtraceEvent {
+ optional uint32 data_len = 1;
+ optional uint32 gso_size = 2;
+ optional uint32 gso_type = 3;
+ optional uint32 hash = 4;
+ optional uint32 ip_summed = 5;
+ optional uint32 l4_hash = 6;
+ optional uint32 len = 7;
+ optional int32 mac_header = 8;
+ optional uint32 mac_header_valid = 9;
+ optional string name = 10;
+ optional uint32 napi_id = 11;
+ optional uint32 nr_frags = 12;
+ optional uint32 protocol = 13;
+ optional uint32 queue_mapping = 14;
+ optional uint64 skbaddr = 15;
+ optional uint32 truesize = 16;
+ optional uint32 vlan_proto = 17;
+ optional uint32 vlan_tagged = 18;
+ optional uint32 vlan_tci = 19;
+}
+message NapiGroReceiveExitFtraceEvent {
+ optional int32 ret = 1;
+}
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 8e6b639..7e7747c 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -2109,7 +2109,7 @@
// Statistics for the internals of the tracing service.
//
-// Next id: 11.
+// Next id: 16.
message TraceStats {
// From TraceBuffer::Stats.
//
@@ -2256,6 +2256,25 @@
optional uint64 errors = 4;
}
optional FilterStats filter_stats = 11;
+
+ // Count of Flush() requests (either from the Consumer, or self-induced
+ // periodic flushes). The final Flush() is also included in the count.
+ optional uint64 flushes_requested = 12;
+
+ // The count of the Flush() requests that were completed succesfully.
+ // In a well behaving trace this should always be == `flush_requests`.
+ optional uint64 flushes_succeeded = 13;
+
+ // The count of the Flush() requests that failed (in most timed out).
+ // In a well behaving trace this should always be == 0.
+ optional uint64 flushes_failed = 14;
+
+ enum FinalFlushOutcome {
+ FINAL_FLUSH_UNSPECIFIED = 0;
+ FINAL_FLUSH_SUCCEEDED = 1;
+ FINAL_FLUSH_FAILED = 2;
+ }
+ optional FinalFlushOutcome final_flush_outcome = 15;
}
// End of protos/perfetto/common/trace_stats.proto
@@ -3544,6 +3563,19 @@
// End of protos/perfetto/trace/ftrace/cpuhp.proto
+// Begin of protos/perfetto/trace/ftrace/cros_ec.proto
+
+message CrosEcSensorhubDataFtraceEvent {
+ optional int64 current_time = 1;
+ optional int64 current_timestamp = 2;
+ optional int64 delta = 3;
+ optional uint32 ec_fifo_timestamp = 4;
+ optional uint32 ec_sensor_num = 5;
+ optional int64 fifo_timestamp = 6;
+}
+
+// End of protos/perfetto/trace/ftrace/cros_ec.proto
+
// Begin of protos/perfetto/trace/ftrace/dmabuf_heap.proto
message DmaHeapStatFtraceEvent {
@@ -5132,6 +5164,30 @@
optional int32 rc = 3;
optional uint64 skbaddr = 4;
}
+message NapiGroReceiveEntryFtraceEvent {
+ optional uint32 data_len = 1;
+ optional uint32 gso_size = 2;
+ optional uint32 gso_type = 3;
+ optional uint32 hash = 4;
+ optional uint32 ip_summed = 5;
+ optional uint32 l4_hash = 6;
+ optional uint32 len = 7;
+ optional int32 mac_header = 8;
+ optional uint32 mac_header_valid = 9;
+ optional string name = 10;
+ optional uint32 napi_id = 11;
+ optional uint32 nr_frags = 12;
+ optional uint32 protocol = 13;
+ optional uint32 queue_mapping = 14;
+ optional uint64 skbaddr = 15;
+ optional uint32 truesize = 16;
+ optional uint32 vlan_proto = 17;
+ optional uint32 vlan_tagged = 18;
+ optional uint32 vlan_tci = 19;
+}
+message NapiGroReceiveExitFtraceEvent {
+ optional int32 ret = 1;
+}
// End of protos/perfetto/trace/ftrace/net.proto
@@ -5932,6 +5988,9 @@
NetDevXmitFtraceEvent net_dev_xmit = 361;
InetSockSetStateFtraceEvent inet_sock_set_state = 362;
TcpRetransmitSkbFtraceEvent tcp_retransmit_skb = 363;
+ CrosEcSensorhubDataFtraceEvent cros_ec_sensorhub_data = 364;
+ NapiGroReceiveEntryFtraceEvent napi_gro_receive_entry = 365;
+ NapiGroReceiveExitFtraceEvent napi_gro_receive_exit = 366;
}
}
diff --git a/protos/perfetto/trace/track_event/BUILD.gn b/protos/perfetto/trace/track_event/BUILD.gn
index d1a8177..ab9d273 100644
--- a/protos/perfetto/trace/track_event/BUILD.gn
+++ b/protos/perfetto/trace/track_event/BUILD.gn
@@ -43,7 +43,7 @@
]
}
-perfetto_proto_library("track_event_@TYPE@") {
+perfetto_proto_library("@TYPE@") {
proto_generators = [ "descriptor" ]
generate_descriptor = "track_event.descriptor"
sources = [ "track_event.proto" ]
diff --git a/protos/perfetto/trace_processor/BUILD.gn b/protos/perfetto/trace_processor/BUILD.gn
index ee1c795..c8671b1 100644
--- a/protos/perfetto/trace_processor/BUILD.gn
+++ b/protos/perfetto/trace_processor/BUILD.gn
@@ -16,7 +16,10 @@
import("proto_files.gni")
perfetto_proto_library("@TYPE@") {
- proto_generators = [ "zero" ]
+ proto_generators = [
+ "zero",
+ "source_set",
+ ]
deps = [ "../common:zero" ] # ../common:zero needed for descriptor.proto.
sources = []
foreach(source, trace_processor_protos) {
@@ -24,7 +27,10 @@
}
}
-perfetto_proto_library("metrics_impl_zero") {
- proto_generators = [ "zero" ]
+perfetto_proto_library("metrics_impl_@TYPE@") {
+ proto_generators = [
+ "zero",
+ "source_set",
+ ]
sources = [ "metrics_impl.proto" ]
}
diff --git a/protos/third_party/chromium/BUILD.gn b/protos/third_party/chromium/BUILD.gn
index 83228a6..b0f4f77 100644
--- a/protos/third_party/chromium/BUILD.gn
+++ b/protos/third_party/chromium/BUILD.gn
@@ -4,14 +4,14 @@
perfetto_proto_library("@TYPE@") {
sources = chrome_track_event_sources
- deps = [ "../../perfetto/trace/track_event:@TYPE@" ]
+ public_deps = [ "../../perfetto/trace/track_event:@TYPE@" ]
}
-perfetto_proto_library("chrome_track_event_@TYPE@") {
+perfetto_proto_library("@TYPE@") {
proto_generators = [ "descriptor" ]
sources = chrome_track_event_sources
generate_descriptor = "chrome_track_event.descriptor"
- deps = [ "../../perfetto/trace/track_event:source_set" ]
+ deps = [ ":source_set" ]
# When rolled into Chrome, extension descriptor is going to be linked into
# binary, therefore increasing its size. Including imports means that the
diff --git a/protos/third_party/chromium/chrome_track_event.proto b/protos/third_party/chromium/chrome_track_event.proto
index d856269..1984ebc 100644
--- a/protos/third_party/chromium/chrome_track_event.proto
+++ b/protos/third_party/chromium/chrome_track_event.proto
@@ -130,6 +130,7 @@
SHOULD_SWAP_BROWSING_INSTANCE_NO_HAS_NOT_COMMITTED_ANY_NAVIGATION = 20;
SHOULD_SWAP_BROWSING_INSTANCE_NO_UNLOAD_HANDLER_EXISTS_ON_SAME_SITE_NAVIGATION =
21;
+ SHOULD_SWAP_BROWSING_INSTANCE_NO_NOT_PRIMARY_MAIN_FRAME = 22;
}
message ShouldSwapBrowsingInstancesResult {
@@ -615,9 +616,76 @@
optional FrameType frame_type = 4;
}
+message EventLatency {
+ enum EventType {
+ EVENT_TYPE_UNSPECIFIED = 0;
+ MOUSE_PRESSED = 1;
+ MOUSE_RELEASED = 2;
+ MOUSE_WHEEL = 3;
+ KEY_PRESSED = 4;
+ KEY_RELEASED = 5;
+ TOUCH_PRESSED = 6;
+ TOUCH_RELEASED = 7;
+ TOUCH_MOVED = 8;
+ GESTURE_SCROLL_BEGIN = 9;
+ GESTURE_SCROLL_UPDATE = 10;
+ GESTURE_SCROLL_END = 11;
+ GESTURE_DOUBLE_TAP = 12;
+ GESTURE_LONG_PRESS = 13;
+ GESTURE_LONG_TAP = 14;
+ GESTURE_SHOW_PRESS = 15;
+ GESTURE_TAP = 16;
+ GESTURE_TAP_CANCEL = 17;
+ GESTURE_TAP_DOWN = 18;
+ GESTURE_TAP_UNCONFIRMED = 19;
+ GESTURE_TWO_FINGER_TAP = 20;
+ FIRST_GESTURE_SCROLL_UPDATE = 21;
+ MOUSE_DRAGGED = 22;
+ GESTURE_PINCH_BEGIN = 23;
+ GESTURE_PINCH_END = 24;
+ GESTURE_PINCH_UPDATE = 25;
+ INERTIAL_GESTURE_SCROLL_UPDATE = 26;
+ }
+
+ optional EventType event_type = 1;
+}
+
+message ProcessSingleton {
+ enum RemoteProcessInteractionResult {
+ INTERACTION_RESULT_UNSPECIFIED = 0;
+ TERMINATE_FAILED = 1;
+ REMOTE_PROCESS_NOT_FOUND = 2;
+ TERMINATE_WAIT_TIMEOUT = 3;
+ RUNNING_PROCESS_NOTIFY_ERROR = 4;
+ TERMINATE_NOT_ENOUGH_PERMISSIONS = 5;
+ REMOTE_PROCESS_SHUTTING_DOWN = 6;
+ PROFILE_UNLOCKED = 7;
+ PROFILE_UNLOCKED_BEFORE_KILL = 8;
+ SAME_BROWSER_INSTANCE = 9;
+ SAME_BROWSER_INSTANCE_BEFORE_KILL = 10;
+ FAILED_TO_EXTRACT_PID = 11;
+ INVALID_LOCK_FILE = 12;
+ ORPHANED_LOCK_FILE = 13;
+ USER_REFUSED_TERMINATION = 14;
+ TERMINATE_SUCCEEDED = 100;
+ }
+
+ enum RemoteHungProcessTerminateReason {
+ TERMINATE_REASON_UNSPECIFIED = 0;
+ USER_ACCEPTED_TERMINATION = 1;
+ NO_VISIBLE_WINDOW_FOUND = 2;
+ NOTIFY_ATTEMPTS_EXCEEDED = 3;
+ SOCKET_WRITE_FAILED = 4;
+ SOCKET_READ_FAILED = 5;
+ }
+
+ optional RemoteProcessInteractionResult remote_process_interaction_result = 1;
+ optional RemoteHungProcessTerminateReason remote_process_terminate_reason = 2;
+}
+
message ChromeTrackEvent {
// Extension range for Chrome: 1000-1999
- // Next ID: 1032
+ // Next ID: 1034
extend TrackEvent {
optional ChromeAppState chrome_app_state = 1000;
@@ -687,5 +755,9 @@
optional RendererMainThreadTaskExecution
renderer_main_thread_task_execution = 1031;
+
+ optional EventLatency event_latency = 1032;
+
+ optional ProcessSingleton process_singleton = 1033;
}
}
diff --git a/protos/third_party/pprof/BUILD.gn b/protos/third_party/pprof/BUILD.gn
index 553d0ac..adbdf95 100644
--- a/protos/third_party/pprof/BUILD.gn
+++ b/protos/third_party/pprof/BUILD.gn
@@ -15,6 +15,9 @@
import("../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- proto_generators = [ "zero" ]
+ proto_generators = [
+ "zero",
+ "source_set",
+ ]
sources = [ "profile.proto" ]
}
diff --git a/python/perfetto/trace_processor/metrics.descriptor b/python/perfetto/trace_processor/metrics.descriptor
index 6c95b59..1b9135c 100644
--- a/python/perfetto/trace_processor/metrics.descriptor
+++ b/python/perfetto/trace_processor/metrics.descriptor
Binary files differ
diff --git a/python/perfetto/trace_processor/platform.py b/python/perfetto/trace_processor/platform.py
index e271012..6508058 100644
--- a/python/perfetto/trace_processor/platform.py
+++ b/python/perfetto/trace_processor/platform.py
@@ -46,7 +46,8 @@
req = request.Request(SHELL_URL)
with request.urlopen(req) as req:
file.write(req.read())
- subprocess.check_output(['chmod', '+x', file.name])
+ if os.name != 'nt':
+ subprocess.check_output(['chmod', '+x', file.name])
return file.name
def get_bind_addr(self, port: int) -> Tuple[str, int]:
diff --git a/python/perfetto/trace_processor/shell.py b/python/perfetto/trace_processor/shell.py
index b0e3950..a7c997d 100644
--- a/python/perfetto/trace_processor/shell.py
+++ b/python/perfetto/trace_processor/shell.py
@@ -13,7 +13,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import os
import subprocess
+import sys
import time
from urllib import request, error
@@ -30,10 +32,15 @@
url = f'{addr}:{str(port)}'
shell_path = platform_delegate.get_shell_path(bin_path=bin_path)
- p = subprocess.Popen([shell_path, '-D', '--http-port',
- str(port)],
- stdout=subprocess.DEVNULL,
- stderr=None if verbose else subprocess.DEVNULL)
+ if os.name == 'nt' and not shell_path.endswith('.exe'):
+ tp_exec = [sys.executable, shell_path]
+ else:
+ tp_exec = [shell_path]
+
+ p = subprocess.Popen(
+ tp_exec + ['-D', '--http-port', str(port)],
+ stdout=subprocess.DEVNULL,
+ stderr=None if verbose else subprocess.DEVNULL)
while True:
try:
diff --git a/python/perfetto/trace_uri_resolver/__init__.py b/python/perfetto/trace_uri_resolver/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/python/perfetto/trace_uri_resolver/__init__.py
diff --git a/python/perfetto/trace_uri_resolver/util.py b/python/perfetto/trace_uri_resolver/util.py
index 8cec762..673d688 100644
--- a/python/perfetto/trace_uri_resolver/util.py
+++ b/python/perfetto/trace_uri_resolver/util.py
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import os
from typing import BinaryIO, Dict, Optional, Tuple
# Limit parsing file to 32MB to maintain parity with the UI
@@ -45,4 +46,12 @@
if idx == -1:
return None, uri
+ # If there is only a single character before the colon
+ # this is likely a Windows path; throw an error on other platforms
+ # to prevent single character names causing issues on Windows.
+ if idx == 1:
+ if os.name != 'nt':
+ raise Exception('Single character resolvers are not allowed')
+ return None, uri
+
return (uri[:idx], uri[idx + 1:])
diff --git a/python/setup.py b/python/setup.py
index 3c1598e..19d30dd 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -2,10 +2,13 @@
setup(
name='perfetto',
- packages=['perfetto', 'perfetto.trace_processor'],
+ packages=[
+ 'perfetto', 'perfetto.batch_trace_processor',
+ 'perfetto.trace_processor', 'perfetto.trace_uri_resolver'
+ ],
package_data={'perfetto.trace_processor': ['*.descriptor']},
include_package_data=True,
- version='0.3.0',
+ version='0.4.0',
license='apache-2.0',
description='Python API for Perfetto\'s Trace Processor',
author='Perfetto',
diff --git a/src/android_stats/perfetto_atoms.h b/src/android_stats/perfetto_atoms.h
index 2f48055..75cbbd8 100644
--- a/src/android_stats/perfetto_atoms.h
+++ b/src/android_stats/perfetto_atoms.h
@@ -73,13 +73,20 @@
// Checkpoints inside perfetto_cmd after tracing has finished.
kOnTracingDisabled = 4,
- kUploadIncidentBegin = 8,
kFinalizeTraceAndExit = 11,
+ kCmdFwReportBegin = 49,
+ // Will be removed once incidentd is no longer used.
+ kUploadIncidentBegin = 8,
kNotUploadingEmptyTrace = 17,
// Guardrails inside perfetto_cmd after tracing has finished.
+ kCmdFwReportEmptyTrace = 50,
+ // Will be removed once incidentd is no longer used.
kUploadIncidentFailure = 10,
+ // "Successful" terminal states inside perfetto_cmd.
+ kCmdFwReportHandoff = 51,
+
// Deprecated as "success" is misleading; it simply means we were
// able to communicate with incidentd. Will be removed once
// incidentd is no longer used.
diff --git a/src/perfetto_cmd/BUILD.gn b/src/perfetto_cmd/BUILD.gn
index 637436f..9cfe232 100644
--- a/src/perfetto_cmd/BUILD.gn
+++ b/src/perfetto_cmd/BUILD.gn
@@ -45,7 +45,7 @@
# is shared both by the executable and tests.
source_set("perfetto_cmd") {
public_deps = [
- ":protos",
+ ":protos_cpp",
"../../include/perfetto/ext/traced",
]
deps = [
@@ -83,12 +83,12 @@
perfetto_cc_proto_descriptor("gen_cc_config_descriptor") {
descriptor_name = "perfetto_config.descriptor"
- descriptor_target = "../../protos/perfetto/config:perfetto_config_descriptor"
+ descriptor_target = "../../protos/perfetto/config:merged_config_descriptor"
}
source_set("trigger_perfetto_cmd") {
public_deps = [
- ":protos",
+ ":protos_cpp",
"../../include/perfetto/ext/traced",
]
deps = [
@@ -113,8 +113,11 @@
]
}
-perfetto_proto_library("protos") {
- proto_generators = [ "cpp" ]
+perfetto_proto_library("protos_@TYPE@") {
+ proto_generators = [
+ "cpp",
+ "source_set",
+ ]
sources = [ "perfetto_cmd_state.proto" ]
proto_path = perfetto_root_path
}
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index ed57c99..e104296 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -1240,8 +1240,8 @@
TRACING SESSIONS:
-ID UID STATE NAME BUF (#) KB DUR (s) #DS STARTED
-=== === ===== ==== ========== ======= === =======
+ID UID STATE BUF (#) KB DUR (s) #DS STARTED NAME
+=== === ===== ========== ======= === ======= ====
)");
for (const auto& sess : svc_state.tracing_sessions()) {
uint32_t buf_tot_kb = 0;
@@ -1252,14 +1252,22 @@
int h = sec / 3600;
int m = (sec - (h * 3600)) / 60;
int s = (sec - h * 3600 - m * 60);
- printf("%-7" PRIu64
- " %-7d %-10s %-12s (%d) %-8u %-9u %-4u %02d:%02d:%02d\n",
+ printf("%-7" PRIu64 " %-7d %-10s (%d) %-8u %-9u %-4u %02d:%02d:%02d %s\n",
sess.id(), sess.consumer_uid(), sess.state().c_str(),
- sess.unique_session_name().c_str(), sess.buffer_size_kb_size(),
- buf_tot_kb, sess.duration_ms() / 1000, sess.num_data_sources(), h,
- m, s);
+ sess.buffer_size_kb_size(), buf_tot_kb, sess.duration_ms() / 1000,
+ sess.num_data_sources(), h, m, s,
+ sess.unique_session_name().c_str());
} // for tracing_sessions()
- } // if (supports_tracing_sessions)
+
+ int sessions_listed = static_cast<int>(svc_state.tracing_sessions().size());
+ if (sessions_listed != svc_state.num_sessions() && geteuid() != 0) {
+ printf(
+ "\n"
+ "NOTE: Some tracing sessions are not reported in the list above.\n"
+ "This is likely because they are owned by a different UID.\n"
+ "If you want to list all session, run again this command as root.\n");
+ }
+ } // if (supports_tracing_sessions)
}
void PerfettoCmd::OnObservableEvents(
diff --git a/src/perfetto_cmd/perfetto_cmd_android.cc b/src/perfetto_cmd/perfetto_cmd_android.cc
index 6a2d949..c1fa07b 100644
--- a/src/perfetto_cmd/perfetto_cmd_android.cc
+++ b/src/perfetto_cmd/perfetto_cmd_android.cc
@@ -80,14 +80,12 @@
PERFETTO_CHECK(!cfg.skip_report());
if (bytes_written_ == 0) {
- // TODO(lalitm): change this to a dedicated atom decoupled from
- // incidentd.
- LogUploadEvent(PerfettoStatsdAtom::kNotUploadingEmptyTrace);
+ LogUploadEvent(PerfettoStatsdAtom::kCmdFwReportEmptyTrace);
PERFETTO_LOG("Skipping reporting trace to Android. Empty trace.");
return;
}
- // TODO(lalitm): add atom for beginning report here.
+ LogUploadEvent(PerfettoStatsdAtom::kCmdFwReportBegin);
base::StackString<128> self_fd("/proc/self/fd/%d",
fileno(*trace_out_stream_));
base::ScopedFile fd(base::OpenFile(self_fd.c_str(), O_RDONLY | O_CLOEXEC));
@@ -110,6 +108,7 @@
uuid.ToPrettyString().c_str(),
trace_config_->unique_session_name().c_str(), bytes_written_);
}
+ LogUploadEvent(PerfettoStatsdAtom::kCmdFwReportHandoff);
}
// Open a staging file (unlinking the previous instance), copy the trace
diff --git a/src/profiling/symbolizer/local_symbolizer.cc b/src/profiling/symbolizer/local_symbolizer.cc
index bcacb37..1fe4dbd 100644
--- a/src/profiling/symbolizer/local_symbolizer.cc
+++ b/src/profiling/symbolizer/local_symbolizer.cc
@@ -423,8 +423,8 @@
}
if (base::StartsWith(filename, kApkPrefix)) {
- symbol_file =
- root_str + "/" + dirname + "/" + filename.substr(sizeof(kApkPrefix));
+ symbol_file = root_str + "/" + dirname + "/" +
+ filename.substr(sizeof(kApkPrefix) - 1);
result = IsCorrectFile(symbol_file, build_id);
if (result) {
return result;
@@ -438,7 +438,7 @@
}
if (base::StartsWith(filename, kApkPrefix)) {
- symbol_file = root_str + "/" + filename.substr(sizeof(kApkPrefix));
+ symbol_file = root_str + "/" + filename.substr(sizeof(kApkPrefix) - 1);
result = IsCorrectFile(symbol_file, build_id);
if (result) {
return result;
diff --git a/src/profiling/symbolizer/local_symbolizer_unittest.cc b/src/profiling/symbolizer/local_symbolizer_unittest.cc
index 921c878..cb0c11d 100644
--- a/src/profiling/symbolizer/local_symbolizer_unittest.cc
+++ b/src/profiling/symbolizer/local_symbolizer_unittest.cc
@@ -162,6 +162,79 @@
EXPECT_EQ(bin2.value().file_name, tmp.path() + "/dir2/elf1");
}
+TEST(LocalBinaryFinderTest, AbsolutePath) {
+ base::TmpDirTree tmp;
+ tmp.AddDir("root");
+ tmp.AddDir("root/dir");
+ tmp.AddFile("root/dir/elf1.so", CreateElfWithBuildId("AAAAAAAAAAAAAAAAAAAA"));
+
+ LocalBinaryFinder finder({tmp.path() + "/root"});
+
+ base::Optional<FoundBinary> bin1 =
+ finder.FindBinary("/dir/elf1.so", "AAAAAAAAAAAAAAAAAAAA");
+ ASSERT_TRUE(bin1.has_value());
+ EXPECT_EQ(bin1.value().file_name, tmp.path() + "/root/dir/elf1.so");
+}
+
+TEST(LocalBinaryFinderTest, AbsolutePathWithoutBaseApk) {
+ base::TmpDirTree tmp;
+ tmp.AddDir("root");
+ tmp.AddDir("root/dir");
+ tmp.AddFile("root/dir/elf1.so", CreateElfWithBuildId("AAAAAAAAAAAAAAAAAAAA"));
+
+ LocalBinaryFinder finder({tmp.path() + "/root"});
+
+ base::Optional<FoundBinary> bin1 =
+ finder.FindBinary("/dir/base.apk!elf1.so", "AAAAAAAAAAAAAAAAAAAA");
+ ASSERT_TRUE(bin1.has_value());
+ EXPECT_EQ(bin1.value().file_name, tmp.path() + "/root/dir/elf1.so");
+}
+
+TEST(LocalBinaryFinderTest, OnlyFilename) {
+ base::TmpDirTree tmp;
+ tmp.AddDir("root");
+ tmp.AddFile("root/elf1.so", CreateElfWithBuildId("AAAAAAAAAAAAAAAAAAAA"));
+
+ LocalBinaryFinder finder({tmp.path() + "/root"});
+
+ base::Optional<FoundBinary> bin1 =
+ finder.FindBinary("/ignored_dir/elf1.so", "AAAAAAAAAAAAAAAAAAAA");
+ ASSERT_TRUE(bin1.has_value());
+ EXPECT_EQ(bin1.value().file_name, tmp.path() + "/root/elf1.so");
+}
+
+TEST(LocalBinaryFinderTest, OnlyFilenameWithoutBaseApk) {
+ base::TmpDirTree tmp;
+ tmp.AddDir("root");
+ tmp.AddFile("root/elf1.so", CreateElfWithBuildId("AAAAAAAAAAAAAAAAAAAA"));
+
+ LocalBinaryFinder finder({tmp.path() + "/root"});
+
+ base::Optional<FoundBinary> bin1 = finder.FindBinary(
+ "/ignored_dir/base.apk!elf1.so", "AAAAAAAAAAAAAAAAAAAA");
+ ASSERT_TRUE(bin1.has_value());
+ EXPECT_EQ(bin1.value().file_name, tmp.path() + "/root/elf1.so");
+}
+
+TEST(LocalBinaryFinderTest, BuildIdSubdir) {
+ base::TmpDirTree tmp;
+ tmp.AddDir("root");
+ tmp.AddDir("root/.build-id");
+ tmp.AddDir("root/.build-id/41");
+ tmp.AddFile("root/.build-id/41/41414141414141414141414141414141414141.debug",
+ CreateElfWithBuildId("AAAAAAAAAAAAAAAAAAAA"));
+
+ LocalBinaryFinder finder({tmp.path() + "/root"});
+
+ base::Optional<FoundBinary> bin1 =
+ finder.FindBinary("/ignored_dir/ignored_name.so", "AAAAAAAAAAAAAAAAAAAA");
+ ASSERT_TRUE(bin1.has_value());
+ EXPECT_EQ(
+ bin1.value().file_name,
+ tmp.path() +
+ "/root/.build-id/41/41414141414141414141414141414141414141.debug");
+}
+
} // namespace
} // namespace profiling
} // namespace perfetto
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 4ce7cec..3cbfca5 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -80,6 +80,8 @@
"importers/json/json_utils.h",
"importers/ninja/ninja_log_parser.cc",
"importers/ninja/ninja_log_parser.h",
+ "importers/proto/android_camera_event_module.cc",
+ "importers/proto/android_camera_event_module.h",
"importers/proto/async_track_set_tracker.cc",
"importers/proto/async_track_set_tracker.h",
"importers/proto/chrome_string_lookup.cc",
@@ -392,6 +394,7 @@
testonly = true
sources = [
"forwarding_trace_parser_unittest.cc",
+ "importers/ftrace/binder_tracker_unittest.cc",
"importers/ftrace/sched_event_tracker_unittest.cc",
"importers/fuchsia/fuchsia_trace_utils_unittest.cc",
"importers/memory_tracker/graph_processor_unittest.cc",
@@ -429,6 +432,7 @@
"../base",
"../protozero",
"../protozero:testing_messages_zero",
+ "containers",
"containers:unittests",
"db:unittests",
"importers/common",
diff --git a/src/trace_processor/db/column.cc b/src/trace_processor/db/column.cc
index 00496b3..3339c82 100644
--- a/src/trace_processor/db/column.cc
+++ b/src/trace_processor/db/column.cc
@@ -69,10 +69,19 @@
PERFETTO_CHECK(nullable_vector<StringPool::Id>().IsDense() == IsDense());
break;
case ColumnType::kId:
+ case ColumnType::kDummy:
break;
}
}
+Column Column::DummyColumn(const char* name,
+ Table* table,
+ uint32_t col_idx_in_table) {
+ return Column(name, ColumnType::kDummy, Flag::kNoFlag, table,
+ col_idx_in_table, std::numeric_limits<uint32_t>::max(), nullptr,
+ nullptr);
+}
+
Column Column::IdColumn(Table* table, uint32_t col_idx, uint32_t row_map_idx) {
return Column("id", ColumnType::kId, kIdFlags, table, col_idx, row_map_idx,
nullptr, nullptr);
@@ -128,6 +137,8 @@
FilterIntoIdSlow(op, value, rm);
break;
}
+ case ColumnType::kDummy:
+ PERFETTO_FATAL("FilterIntoSlow not allowed on dummy column");
}
}
@@ -443,6 +454,9 @@
int res = compare::Numeric(a_idx, b_idx);
return desc ? res > 0 : res < 0;
});
+ break;
+ case ColumnType::kDummy:
+ PERFETTO_FATAL("StableSort not allowed on dummy column");
}
}
@@ -469,6 +483,7 @@
}
const RowMap& Column::row_map() const {
+ PERFETTO_DCHECK(type_ != ColumnType::kDummy);
return table_->row_maps_[row_map_idx_];
}
diff --git a/src/trace_processor/db/column.h b/src/trace_processor/db/column.h
index dacbe60..ba0a981 100644
--- a/src/trace_processor/db/column.h
+++ b/src/trace_processor/db/column.h
@@ -69,11 +69,6 @@
bool desc;
};
-// Represents a column which is to be joined on.
-struct JoinKey {
- uint32_t col_idx;
-};
-
class Table;
// Represents a named, strongly typed list of data.
@@ -201,6 +196,11 @@
row_map_idx, ptr, std::move(storage));
}
+ // Creates a Column which does not have any data backing it.
+ static Column DummyColumn(const char* name,
+ Table* table,
+ uint32_t col_idx_in_table);
+
// Creates a Column which returns the index as the value of the row.
static Column IdColumn(Table* table,
uint32_t col_idx_in_table,
@@ -231,6 +231,8 @@
return base::nullopt;
return row_map().RowOf(static_cast<uint32_t>(value.long_value));
}
+ case ColumnType::kDummy:
+ PERFETTO_FATAL("IndexOf not allowed on dummy column");
}
PERFETTO_FATAL("For GCC");
}
@@ -265,6 +267,8 @@
case ColumnType::kId: {
PERFETTO_FATAL("Cannot set value on a id column");
}
+ case ColumnType::kDummy:
+ PERFETTO_FATAL("Set not allowed on dummy column");
}
}
@@ -330,6 +334,9 @@
// Returns true if this column is considered an id column.
bool IsId() const { return type_ == ColumnType::kId; }
+ // Returns true if this column is a dummy column.
+ bool IsDummy() const { return type_ == ColumnType::kDummy; }
+
// Returns true if this column is a nullable column.
bool IsNullable() const { return (flags_ & Flag::kNonNull) == 0; }
@@ -389,9 +396,6 @@
Order ascending() const { return Order{col_idx_in_table_, false}; }
Order descending() const { return Order{col_idx_in_table_, true}; }
- // Returns the JoinKey for this Column.
- JoinKey join_key() const { return JoinKey{col_idx_in_table_}; }
-
// Returns an iterator to the first entry in this column.
Iterator begin() const { return Iterator(this, 0); }
@@ -434,6 +438,9 @@
// Types generated on the fly.
kId,
+
+ // Types which don't have any data backing them.
+ kDummy,
};
friend class Table;
@@ -476,6 +483,8 @@
}
case ColumnType::kId:
return SqlValue::Long(idx);
+ case ColumnType::kDummy:
+ PERFETTO_FATAL("GetAtIdx not allowed on dummy column");
}
PERFETTO_FATAL("For GCC");
}
@@ -586,6 +595,8 @@
return SqlValue::Type::kDouble;
case ColumnType::kString:
return SqlValue::Type::kString;
+ case ColumnType::kDummy:
+ PERFETTO_FATAL("ToSqlValueType not allowed on dummy column");
}
PERFETTO_FATAL("For GCC");
}
diff --git a/src/trace_processor/db/table.cc b/src/trace_processor/db/table.cc
index 940d8b1..019df20 100644
--- a/src/trace_processor/db/table.cc
+++ b/src/trace_processor/db/table.cc
@@ -144,57 +144,5 @@
return table;
}
-Table Table::LookupJoin(JoinKey left, const Table& other, JoinKey right) {
- // The join table will have the same size and RowMaps as the left (this)
- // table because the left column is indexing the right table.
- Table table(string_pool_, nullptr);
- table.row_count_ = row_count_;
- for (const RowMap& rm : row_maps_) {
- table.row_maps_.emplace_back(rm.Copy());
- }
-
- for (const Column& col : columns_) {
- // We skip id columns as they are misleading on join tables.
- if (col.IsId())
- continue;
- table.columns_.emplace_back(col, &table, table.columns_.size(),
- col.row_map_idx_);
- }
-
- const Column& left_col = columns_[left.col_idx];
- const Column& right_col = other.columns_[right.col_idx];
-
- // For each index in the left column, retrieve the index of the row inside
- // the RowMap of the right column. By getting the index of the row rather
- // than the row number itself, we can call |Apply| on the other RowMaps
- // in the right table.
- std::vector<uint32_t> indices(row_count_);
- for (uint32_t i = 0; i < row_count_; ++i) {
- SqlValue val = left_col.Get(i);
- PERFETTO_CHECK(val.type != SqlValue::Type::kNull);
- indices[i] = right_col.IndexOf(val).value();
- }
-
- // Apply the computed RowMap to each of the right RowMaps, adding it to the
- // join table as we go.
- RowMap rm(std::move(indices));
- for (const RowMap& ot : other.row_maps_) {
- table.row_maps_.emplace_back(ot.SelectRows(rm));
- }
-
- 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.IsId())
- continue;
-
- // Ensure that we offset the RowMap index by the number of RowMaps in the
- // left table.
- table.columns_.emplace_back(col, &table, table.columns_.size(),
- col.row_map_idx_ + left_row_maps_size);
- }
- return table;
-}
-
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/db/table.h b/src/trace_processor/db/table.h
index e13ad58..cb54d53 100644
--- a/src/trace_processor/db/table.h
+++ b/src/trace_processor/db/table.h
@@ -38,7 +38,7 @@
// Iterator over the rows of the table.
class Iterator {
public:
- Iterator(const Table* table) : table_(table) {
+ explicit Iterator(const Table* table) : table_(table) {
for (const auto& rm : table->row_maps()) {
its_.emplace_back(rm.IterateRows());
}
@@ -134,22 +134,6 @@
// Sorts the Table using the specified order by constraints.
Table Sort(const std::vector<Order>& od) const;
- // Joins |this| table with the |other| table using the values of column |left|
- // of |this| table to lookup the row in |right| column of the |other| table.
- //
- // Concretely, for each row in the returned table we lookup the value of
- // |left| in |right|. The found row is used as the values for |other|'s
- // columns in the returned table.
- //
- // This means we obtain the following invariants:
- // 1. this->size() == ret->size()
- // 2. this->Rows()[i].Get(j) == ret->Rows()[i].Get(j)
- //
- // It also means there are few restrictions on the data in |left| and |right|:
- // * |left| is not allowed to have any nulls.
- // * |left|'s values must exist in |right|
- Table LookupJoin(JoinKey left, const Table& other, JoinKey right);
-
// Extends the table with a new column called |name| with data |sv|.
template <typename T>
Table ExtendWithColumn(const char* name,
diff --git a/src/trace_processor/dynamic/ancestor_generator.cc b/src/trace_processor/dynamic/ancestor_generator.cc
index f603d67..c126ced 100644
--- a/src/trace_processor/dynamic/ancestor_generator.cc
+++ b/src/trace_processor/dynamic/ancestor_generator.cc
@@ -111,7 +111,8 @@
std::unique_ptr<Table> AncestorGenerator::ComputeTable(
const std::vector<Constraint>& cs,
- const std::vector<Order>&) {
+ const std::vector<Order>&,
+ const BitVector&) {
uint32_t column = GetConstraintColumnIndex(type_, context_);
auto it = std::find_if(cs.begin(), cs.end(), [column](const Constraint& c) {
return c.col_idx == column && c.op == FilterOp::kEq;
diff --git a/src/trace_processor/dynamic/ancestor_generator.h b/src/trace_processor/dynamic/ancestor_generator.h
index 2e1f8f0..48947ac 100644
--- a/src/trace_processor/dynamic/ancestor_generator.h
+++ b/src/trace_processor/dynamic/ancestor_generator.h
@@ -48,7 +48,8 @@
uint32_t EstimateRowCount() override;
util::Status ValidateConstraints(const QueryConstraints&) override;
std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob) override;
+ const std::vector<Order>& ob,
+ const BitVector& cols_used) override;
// Returns a RowMap of slice IDs which are ancestors of |slice_id|. Returns
// NULL if an invalid |slice_id| is given. This is used by
diff --git a/src/trace_processor/dynamic/connected_flow_generator.cc b/src/trace_processor/dynamic/connected_flow_generator.cc
index d3cf976..1032fd7 100644
--- a/src/trace_processor/dynamic/connected_flow_generator.cc
+++ b/src/trace_processor/dynamic/connected_flow_generator.cc
@@ -198,7 +198,8 @@
std::unique_ptr<Table> ConnectedFlowGenerator::ComputeTable(
const std::vector<Constraint>& cs,
- const std::vector<Order>&) {
+ const std::vector<Order>&,
+ const BitVector&) {
const auto& flow = context_->storage->flow_table();
const auto& slice = context_->storage->slice_table();
diff --git a/src/trace_processor/dynamic/connected_flow_generator.h b/src/trace_processor/dynamic/connected_flow_generator.h
index e6d01b3..b2117af 100644
--- a/src/trace_processor/dynamic/connected_flow_generator.h
+++ b/src/trace_processor/dynamic/connected_flow_generator.h
@@ -55,7 +55,8 @@
uint32_t EstimateRowCount() override;
util::Status ValidateConstraints(const QueryConstraints&) override;
std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob) override;
+ const std::vector<Order>& ob,
+ const BitVector& cols_used) override;
private:
Mode mode_;
diff --git a/src/trace_processor/dynamic/descendant_generator.cc b/src/trace_processor/dynamic/descendant_generator.cc
index cc33bf1..ebec3f3 100644
--- a/src/trace_processor/dynamic/descendant_generator.cc
+++ b/src/trace_processor/dynamic/descendant_generator.cc
@@ -96,7 +96,8 @@
std::unique_ptr<Table> DescendantGenerator::ComputeTable(
const std::vector<Constraint>& cs,
- const std::vector<Order>&) {
+ const std::vector<Order>&,
+ const BitVector&) {
const auto& slices = context_->storage->slice_table();
uint32_t column = GetConstraintColumnIndex(context_);
diff --git a/src/trace_processor/dynamic/descendant_generator.h b/src/trace_processor/dynamic/descendant_generator.h
index 6e87a61..216b7e1 100644
--- a/src/trace_processor/dynamic/descendant_generator.h
+++ b/src/trace_processor/dynamic/descendant_generator.h
@@ -43,7 +43,8 @@
uint32_t EstimateRowCount() override;
util::Status ValidateConstraints(const QueryConstraints&) override;
std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob) override;
+ const std::vector<Order>& ob,
+ const BitVector& cols_used) override;
// Returns a RowMap of slice IDs which are descendants of |slice_id|. Returns
// NULL if an invalid |slice_id| is given. This is used by
diff --git a/src/trace_processor/dynamic/describe_slice_generator.cc b/src/trace_processor/dynamic/describe_slice_generator.cc
index edc610d..500d561 100644
--- a/src/trace_processor/dynamic/describe_slice_generator.cc
+++ b/src/trace_processor/dynamic/describe_slice_generator.cc
@@ -70,7 +70,8 @@
std::unique_ptr<Table> DescribeSliceGenerator::ComputeTable(
const std::vector<Constraint>& cs,
- const std::vector<Order>&) {
+ const std::vector<Order>&,
+ const BitVector&) {
auto input = GetDescribeSliceInputValues(cs);
const auto& slices = context_->storage->slice_table();
diff --git a/src/trace_processor/dynamic/describe_slice_generator.h b/src/trace_processor/dynamic/describe_slice_generator.h
index af59529..fc7d991 100644
--- a/src/trace_processor/dynamic/describe_slice_generator.h
+++ b/src/trace_processor/dynamic/describe_slice_generator.h
@@ -43,7 +43,8 @@
uint32_t EstimateRowCount() override;
util::Status ValidateConstraints(const QueryConstraints&) override;
std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob) override;
+ const std::vector<Order>& ob,
+ const BitVector& cols_used) override;
private:
TraceProcessorContext* context_ = nullptr;
diff --git a/src/trace_processor/dynamic/experimental_annotated_stack_generator.cc b/src/trace_processor/dynamic/experimental_annotated_stack_generator.cc
index 1af5ad1..617c658 100644
--- a/src/trace_processor/dynamic/experimental_annotated_stack_generator.cc
+++ b/src/trace_processor/dynamic/experimental_annotated_stack_generator.cc
@@ -119,7 +119,8 @@
std::unique_ptr<Table> ExperimentalAnnotatedStackGenerator::ComputeTable(
const std::vector<Constraint>& cs,
- const std::vector<Order>&) {
+ const std::vector<Order>&,
+ const BitVector&) {
const auto& cs_table = context_->storage->stack_profile_callsite_table();
const auto& f_table = context_->storage->stack_profile_frame_table();
const auto& m_table = context_->storage->stack_profile_mapping_table();
diff --git a/src/trace_processor/dynamic/experimental_annotated_stack_generator.h b/src/trace_processor/dynamic/experimental_annotated_stack_generator.h
index 7e6a62d..f61c166 100644
--- a/src/trace_processor/dynamic/experimental_annotated_stack_generator.h
+++ b/src/trace_processor/dynamic/experimental_annotated_stack_generator.h
@@ -40,7 +40,8 @@
uint32_t EstimateRowCount() override;
util::Status ValidateConstraints(const QueryConstraints&) override;
std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob) override;
+ const std::vector<Order>& ob,
+ const BitVector& cols_used) override;
private:
TraceProcessorContext* context_ = nullptr;
diff --git a/src/trace_processor/dynamic/experimental_counter_dur_generator.cc b/src/trace_processor/dynamic/experimental_counter_dur_generator.cc
index 88d167f..530fe39 100644
--- a/src/trace_processor/dynamic/experimental_counter_dur_generator.cc
+++ b/src/trace_processor/dynamic/experimental_counter_dur_generator.cc
@@ -50,7 +50,8 @@
std::unique_ptr<Table> ExperimentalCounterDurGenerator::ComputeTable(
const std::vector<Constraint>&,
- const std::vector<Order>&) {
+ const std::vector<Order>&,
+ const BitVector&) {
if (!dur_column_) {
dur_column_.reset(
new NullableVector<int64_t>(ComputeDurColumn(*counter_table_)));
diff --git a/src/trace_processor/dynamic/experimental_counter_dur_generator.h b/src/trace_processor/dynamic/experimental_counter_dur_generator.h
index 38f9773..4ec9f24 100644
--- a/src/trace_processor/dynamic/experimental_counter_dur_generator.h
+++ b/src/trace_processor/dynamic/experimental_counter_dur_generator.h
@@ -35,7 +35,8 @@
uint32_t EstimateRowCount() override;
util::Status ValidateConstraints(const QueryConstraints&) override;
std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>&,
- const std::vector<Order>&) override;
+ const std::vector<Order>&,
+ const BitVector& cols_used) override;
// public + static for testing
static NullableVector<int64_t> ComputeDurColumn(const Table& table);
diff --git a/src/trace_processor/dynamic/experimental_flamegraph_generator.cc b/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
index 559e3ca..1475eab 100644
--- a/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
+++ b/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
@@ -324,7 +324,8 @@
std::unique_ptr<Table> ExperimentalFlamegraphGenerator::ComputeTable(
const std::vector<Constraint>& cs,
- const std::vector<Order>&) {
+ const std::vector<Order>&,
+ const BitVector&) {
// Get the input column values and compute the flamegraph using them.
auto values = GetFlamegraphInputValues(cs);
diff --git a/src/trace_processor/dynamic/experimental_flamegraph_generator.h b/src/trace_processor/dynamic/experimental_flamegraph_generator.h
index 652193c..c8531ad 100644
--- a/src/trace_processor/dynamic/experimental_flamegraph_generator.h
+++ b/src/trace_processor/dynamic/experimental_flamegraph_generator.h
@@ -49,7 +49,8 @@
uint32_t EstimateRowCount() override;
util::Status ValidateConstraints(const QueryConstraints&) override;
std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob) override;
+ const std::vector<Order>& ob,
+ const BitVector& cols_used) override;
private:
TraceProcessorContext* context_ = nullptr;
diff --git a/src/trace_processor/dynamic/experimental_flat_slice_generator.cc b/src/trace_processor/dynamic/experimental_flat_slice_generator.cc
index a05cb81..4e8d697 100644
--- a/src/trace_processor/dynamic/experimental_flat_slice_generator.cc
+++ b/src/trace_processor/dynamic/experimental_flat_slice_generator.cc
@@ -46,7 +46,8 @@
std::unique_ptr<Table> ExperimentalFlatSliceGenerator::ComputeTable(
const std::vector<Constraint>& cs,
- const std::vector<Order>&) {
+ const std::vector<Order>&,
+ const BitVector&) {
using CI = tables::ExperimentalFlatSliceTable::ColumnIndex;
auto start_it = std::find_if(cs.begin(), cs.end(), [](const Constraint& c) {
return c.col_idx == static_cast<uint32_t>(CI::start_bound) &&
diff --git a/src/trace_processor/dynamic/experimental_flat_slice_generator.h b/src/trace_processor/dynamic/experimental_flat_slice_generator.h
index b0838c4..480e477 100644
--- a/src/trace_processor/dynamic/experimental_flat_slice_generator.h
+++ b/src/trace_processor/dynamic/experimental_flat_slice_generator.h
@@ -62,7 +62,8 @@
uint32_t EstimateRowCount() override;
util::Status ValidateConstraints(const QueryConstraints&) override;
std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob) override;
+ const std::vector<Order>& ob,
+ const BitVector& cols_used) override;
// Visibile for testing.
static std::unique_ptr<tables::ExperimentalFlatSliceTable>
diff --git a/src/trace_processor/dynamic/experimental_sched_upid_generator.cc b/src/trace_processor/dynamic/experimental_sched_upid_generator.cc
index 1906918..60d325f 100644
--- a/src/trace_processor/dynamic/experimental_sched_upid_generator.cc
+++ b/src/trace_processor/dynamic/experimental_sched_upid_generator.cc
@@ -48,7 +48,8 @@
std::unique_ptr<Table> ExperimentalSchedUpidGenerator::ComputeTable(
const std::vector<Constraint>&,
- const std::vector<Order>&) {
+ const std::vector<Order>&,
+ const BitVector&) {
if (!upid_column_) {
upid_column_.reset(new NullableVector<uint32_t>(ComputeUpidColumn()));
}
diff --git a/src/trace_processor/dynamic/experimental_sched_upid_generator.h b/src/trace_processor/dynamic/experimental_sched_upid_generator.h
index 09e0dfa..e144eea 100644
--- a/src/trace_processor/dynamic/experimental_sched_upid_generator.h
+++ b/src/trace_processor/dynamic/experimental_sched_upid_generator.h
@@ -37,7 +37,8 @@
uint32_t EstimateRowCount() override;
util::Status ValidateConstraints(const QueryConstraints&) override;
std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>&,
- const std::vector<Order>&) override;
+ const std::vector<Order>&,
+ const BitVector& cols_used) override;
private:
NullableVector<uint32_t> ComputeUpidColumn();
diff --git a/src/trace_processor/dynamic/experimental_slice_layout_generator.cc b/src/trace_processor/dynamic/experimental_slice_layout_generator.cc
index 5d0f2db..9b842bb 100644
--- a/src/trace_processor/dynamic/experimental_slice_layout_generator.cc
+++ b/src/trace_processor/dynamic/experimental_slice_layout_generator.cc
@@ -75,7 +75,8 @@
std::unique_ptr<Table> ExperimentalSliceLayoutGenerator::ComputeTable(
const std::vector<Constraint>& cs,
- const std::vector<Order>&) {
+ const std::vector<Order>&,
+ const BitVector&) {
std::set<TrackId> selected_tracks;
std::string filter_string = "";
for (const auto& c : cs) {
diff --git a/src/trace_processor/dynamic/experimental_slice_layout_generator.h b/src/trace_processor/dynamic/experimental_slice_layout_generator.h
index 4b033f7..b2d731e 100644
--- a/src/trace_processor/dynamic/experimental_slice_layout_generator.h
+++ b/src/trace_processor/dynamic/experimental_slice_layout_generator.h
@@ -40,7 +40,8 @@
uint32_t EstimateRowCount() override;
util::Status ValidateConstraints(const QueryConstraints&) override;
std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>&,
- const std::vector<Order>&) override;
+ const std::vector<Order>&,
+ const BitVector& cols_used) override;
private:
Table ComputeLayoutTable(const Table& table, StringPool::Id filter_id);
diff --git a/src/trace_processor/dynamic/experimental_slice_layout_generator_unittest.cc b/src/trace_processor/dynamic/experimental_slice_layout_generator_unittest.cc
index 0f2945a..efb8ae8 100644
--- a/src/trace_processor/dynamic/experimental_slice_layout_generator_unittest.cc
+++ b/src/trace_processor/dynamic/experimental_slice_layout_generator_unittest.cc
@@ -18,6 +18,7 @@
#include <algorithm>
+#include "src/trace_processor/containers/bit_vector.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
@@ -104,7 +105,8 @@
ExperimentalSliceLayoutGenerator gen(&pool, &slice_table);
std::unique_ptr<Table> table = gen.ComputeTable(
- {Constraint{kColumn, FilterOp::kEq, SqlValue::String("1")}}, {});
+ {Constraint{kColumn, FilterOp::kEq, SqlValue::String("1")}}, {},
+ BitVector());
ExpectOutput(*table, R"(
#####
)");
@@ -122,7 +124,8 @@
ExperimentalSliceLayoutGenerator gen(&pool, &slice_table);
std::unique_ptr<Table> table = gen.ComputeTable(
- {Constraint{kColumn, FilterOp::kEq, SqlValue::String("1")}}, {});
+ {Constraint{kColumn, FilterOp::kEq, SqlValue::String("1")}}, {},
+ BitVector());
ExpectOutput(*table, R"(
#####
#####
@@ -145,7 +148,8 @@
ExperimentalSliceLayoutGenerator gen(&pool, &slice_table);
std::unique_ptr<Table> table = gen.ComputeTable(
- {Constraint{kColumn, FilterOp::kEq, SqlValue::String("1")}}, {});
+ {Constraint{kColumn, FilterOp::kEq, SqlValue::String("1")}}, {},
+ BitVector());
ExpectOutput(*table, R"(
#####
####
@@ -175,7 +179,8 @@
ExperimentalSliceLayoutGenerator gen(&pool, &slice_table);
std::unique_ptr<Table> table = gen.ComputeTable(
- {Constraint{kColumn, FilterOp::kEq, SqlValue::String("1,2")}}, {});
+ {Constraint{kColumn, FilterOp::kEq, SqlValue::String("1,2")}}, {},
+ BitVector());
ExpectOutput(*table, R"(
####
##
@@ -210,7 +215,8 @@
ExperimentalSliceLayoutGenerator gen(&pool, &slice_table);
std::unique_ptr<Table> table = gen.ComputeTable(
- {Constraint{kColumn, FilterOp::kEq, SqlValue::String("1,2")}}, {});
+ {Constraint{kColumn, FilterOp::kEq, SqlValue::String("1,2")}}, {},
+ BitVector());
ExpectOutput(*table, R"(
#### ####
## ##
@@ -242,7 +248,8 @@
ExperimentalSliceLayoutGenerator gen(&pool, &slice_table);
std::unique_ptr<Table> table = gen.ComputeTable(
- {Constraint{kColumn, FilterOp::kEq, SqlValue::String("1,2")}}, {});
+ {Constraint{kColumn, FilterOp::kEq, SqlValue::String("1,2")}}, {},
+ BitVector());
ExpectOutput(*table, R"(
####
##
diff --git a/src/trace_processor/dynamic/thread_state_generator.cc b/src/trace_processor/dynamic/thread_state_generator.cc
index 74115cd..f68f127 100644
--- a/src/trace_processor/dynamic/thread_state_generator.cc
+++ b/src/trace_processor/dynamic/thread_state_generator.cc
@@ -38,7 +38,8 @@
std::unique_ptr<Table> ThreadStateGenerator::ComputeTable(
const std::vector<Constraint>&,
- const std::vector<Order>&) {
+ const std::vector<Order>&,
+ const BitVector&) {
if (!unsorted_thread_state_table_) {
int64_t trace_end_ts =
context_->storage->GetTraceTimestampBoundsNs().second;
diff --git a/src/trace_processor/dynamic/thread_state_generator.h b/src/trace_processor/dynamic/thread_state_generator.h
index 439d4bb..db97925 100644
--- a/src/trace_processor/dynamic/thread_state_generator.h
+++ b/src/trace_processor/dynamic/thread_state_generator.h
@@ -40,7 +40,8 @@
uint32_t EstimateRowCount() override;
util::Status ValidateConstraints(const QueryConstraints&) override;
std::unique_ptr<Table> ComputeTable(const std::vector<Constraint>& cs,
- const std::vector<Order>& ob) override;
+ const std::vector<Order>& ob,
+ const BitVector& cols_used) override;
// Visible for testing.
std::unique_ptr<tables::ThreadStateTable> ComputeThreadStateTable(
diff --git a/src/trace_processor/importers/BUILD.gn b/src/trace_processor/importers/BUILD.gn
index fceb53f..908ae8d 100644
--- a/src/trace_processor/importers/BUILD.gn
+++ b/src/trace_processor/importers/BUILD.gn
@@ -21,12 +21,10 @@
perfetto_cc_proto_descriptor("gen_cc_chrome_track_event_descriptor") {
descriptor_name = "chrome_track_event.descriptor"
- descriptor_target =
- "../../../protos/third_party/chromium:chrome_track_event_descriptor"
+ descriptor_target = "../../../protos/third_party/chromium:descriptor"
}
perfetto_cc_proto_descriptor("gen_cc_track_event_descriptor") {
descriptor_name = "track_event.descriptor"
- descriptor_target =
- "../../../protos/perfetto/trace/track_event:track_event_descriptor"
+ descriptor_target = "../../../protos/perfetto/trace/track_event:descriptor"
}
diff --git a/src/trace_processor/importers/common/track_tracker.h b/src/trace_processor/importers/common/track_tracker.h
index e38cc66..d51d41a 100644
--- a/src/trace_processor/importers/common/track_tracker.h
+++ b/src/trace_processor/importers/common/track_tracker.h
@@ -95,7 +95,7 @@
StringId description = StringId::Null(),
StringId unit = StringId::Null());
- // Creaates a counter track for values within perf samples.
+ // Creates a counter track for values within perf samples.
// The tracks themselves are managed by PerfSampleTracker.
TrackId CreatePerfCounterTrack(StringId name,
uint32_t perf_session_id,
diff --git a/src/trace_processor/importers/default_modules.cc b/src/trace_processor/importers/default_modules.cc
index 19345cf..b14f357 100644
--- a/src/trace_processor/importers/default_modules.cc
+++ b/src/trace_processor/importers/default_modules.cc
@@ -16,6 +16,7 @@
#include "src/trace_processor/importers/default_modules.h"
#include "src/trace_processor/importers/ftrace/ftrace_module.h"
+#include "src/trace_processor/importers/proto/android_camera_event_module.h"
#include "src/trace_processor/importers/proto/chrome_system_probes_module.h"
#include "src/trace_processor/importers/proto/memory_tracker_snapshot_module.h"
#include "src/trace_processor/importers/proto/metadata_module.h"
@@ -38,6 +39,7 @@
context->modules.emplace_back(new TrackEventModule(context));
context->modules.emplace_back(new ProfileModule(context));
context->modules.emplace_back(new MetadataModule(context));
+ context->modules.emplace_back(new AndroidCameraEventModule(context));
}
} // namespace trace_processor
diff --git a/src/trace_processor/importers/ftrace/binder_tracker.cc b/src/trace_processor/importers/ftrace/binder_tracker.cc
index 64eee90..fd229f1 100644
--- a/src/trace_processor/importers/ftrace/binder_tracker.cc
+++ b/src/trace_processor/importers/ftrace/binder_tracker.cc
@@ -17,9 +17,11 @@
#include "src/trace_processor/importers/ftrace/binder_tracker.h"
#include "perfetto/base/compiler.h"
#include "perfetto/ext/base/string_utils.h"
+#include "src/trace_processor/importers/common/flow_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/slice_tracker.h"
#include "src/trace_processor/importers/common/track_tracker.h"
+#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"
namespace perfetto {
@@ -74,7 +76,6 @@
flags_(context->storage->InternString("flags")),
code_(context->storage->InternString("code")),
calling_tid_(context->storage->InternString("calling tid")),
- dest_slice_id_(context->storage->InternString("destination slice id")),
data_size_(context->storage->InternString("data size")),
offsets_size_(context->storage->InternString("offsets size")) {}
@@ -84,8 +85,8 @@
uint32_t tid,
int32_t transaction_id,
int32_t dest_node,
- int32_t dest_tgid,
- int32_t dest_tid,
+ uint32_t dest_tgid,
+ uint32_t dest_tid,
bool is_reply,
uint32_t flags,
StringId code) {
@@ -105,95 +106,95 @@
base::StringView(flag_str))));
inserter->AddArg(code_, Variadic::String(code));
inserter->AddArg(calling_tid_, Variadic::UnsignedInteger(tid));
- // TODO(hjd): The legacy UI included the calling pid in the args,
- // is this necessary? It's complicated in our case because process
- // association might not happen until after the binder transaction slices
- // have been parsed. We would need to backfill the arg.
};
- if (is_reply) {
- // Reply slices have accurate dest information, so we can add it.
- const auto& thread_table = context_->storage->thread_table();
- UniqueTid utid = context_->process_tracker->GetOrCreateThread(
- static_cast<uint32_t>(dest_tid));
- StringId dest_thread_name = thread_table.name()[utid];
- auto dest_args_inserter = [this, dest_tid, &dest_thread_name](
- ArgsTracker::BoundInserter* inserter) {
- inserter->AddArg(dest_thread_, Variadic::Integer(dest_tid));
- inserter->AddArg(dest_name_, Variadic::String(dest_thread_name));
- };
- context_->slice_tracker->AddArgs(track_id, binder_category_id_, reply_id_,
- dest_args_inserter);
- context_->slice_tracker->End(ts, track_id, kNullStringId, kNullStringId,
- args_inserter);
- awaiting_rcv_for_reply_.insert(transaction_id);
- return;
- }
+ bool is_oneway = (flags & kOneWay) == kOneWay;
+ auto insert_slice = [&]() {
+ if (is_reply) {
+ UniqueTid utid = context_->process_tracker->GetOrCreateThread(
+ static_cast<uint32_t>(dest_tid));
+ StringId dest_thread_name =
+ context_->storage->thread_table().name()[utid];
+ auto dest_args_inserter = [this, dest_tid, &dest_thread_name](
+ ArgsTracker::BoundInserter* inserter) {
+ inserter->AddArg(dest_thread_, Variadic::Integer(dest_tid));
+ inserter->AddArg(dest_name_, Variadic::String(dest_thread_name));
+ };
+ context_->slice_tracker->AddArgs(track_id, binder_category_id_, reply_id_,
+ dest_args_inserter);
+ return context_->slice_tracker->End(ts, track_id, kNullStringId,
+ kNullStringId, args_inserter);
+ }
+ if (is_oneway) {
+ return context_->slice_tracker->Scoped(ts, track_id, binder_category_id_,
+ transaction_async_id_, 0,
+ args_inserter);
+ }
+ return context_->slice_tracker->Begin(ts, track_id, binder_category_id_,
+ transaction_slice_id_, args_inserter);
+ };
- bool expects_reply = !is_reply && ((flags & kOneWay) == 0);
-
- if (expects_reply) {
- context_->slice_tracker->Begin(ts, track_id, binder_category_id_,
- transaction_slice_id_, args_inserter);
- transaction_await_rcv[transaction_id] = track_id;
- } else {
- context_->slice_tracker->Scoped(ts, track_id, binder_category_id_,
- transaction_async_id_, 0, args_inserter);
- awaiting_async_rcv_[transaction_id] = args_inserter;
- }
+ OutstandingTransaction transaction;
+ transaction.is_reply = is_reply;
+ transaction.is_oneway = is_oneway;
+ transaction.args_inserter = args_inserter;
+ transaction.send_track_id = track_id;
+ transaction.send_slice_id = insert_slice();
+ outstanding_transactions_.Insert(transaction_id, std::move(transaction));
}
void BinderTracker::TransactionReceived(int64_t ts,
uint32_t pid,
int32_t transaction_id) {
+ const OutstandingTransaction* opt_transaction =
+ outstanding_transactions_.Find(transaction_id);
+ if (!opt_transaction) {
+ // If we don't know what type of transaction it is, we don't know how to
+ // insert the slice.
+ // TODO(lalitm): maybe we should insert a dummy slice anyway - seems like
+ // a questionable idea to just ignore these completely.
+ return;
+ }
+
+ OutstandingTransaction transaction(std::move(*opt_transaction));
+ outstanding_transactions_.Erase(transaction_id);
+
UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
- const auto& thread_table = context_->storage->thread_table();
- StringId thread_name = thread_table.name()[utid];
TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
- if (awaiting_rcv_for_reply_.count(transaction_id) > 0) {
+
+ if (transaction.is_reply) {
+ // Simply end the slice started back when the first |expects_reply|
+ // transaction was sent.
context_->slice_tracker->End(ts, track_id);
- awaiting_rcv_for_reply_.erase(transaction_id);
return;
}
- TrackId* rcv_track_id = transaction_await_rcv.Find(transaction_id);
- if (rcv_track_id) {
- // First begin the reply slice to get its slice id.
- auto reply_slice_id = context_->slice_tracker->Begin(
+ base::Optional<SliceId> recv_slice_id;
+ if (transaction.is_oneway) {
+ recv_slice_id = context_->slice_tracker->Scoped(
+ ts, track_id, binder_category_id_, async_rcv_id_, 0,
+ std::move(transaction.args_inserter));
+ } else {
+ if (transaction.send_track_id) {
+ auto args_inserter = [this, utid,
+ pid](ArgsTracker::BoundInserter* inserter) {
+ inserter->AddArg(dest_thread_, Variadic::UnsignedInteger(pid));
+ inserter->AddArg(
+ dest_name_,
+ Variadic::String(context_->storage->thread_table().name()[utid]));
+ };
+ context_->slice_tracker->AddArgs(*transaction.send_track_id,
+ binder_category_id_,
+ transaction_slice_id_, args_inserter);
+ }
+ recv_slice_id = context_->slice_tracker->Begin(
ts, track_id, binder_category_id_, reply_id_);
- // Add accurate dest info to the binder transaction slice.
- auto args_inserter = [this, pid, &thread_name, &reply_slice_id](
- ArgsTracker::BoundInserter* inserter) {
- inserter->AddArg(dest_thread_, Variadic::UnsignedInteger(pid));
- inserter->AddArg(dest_name_, Variadic::String(thread_name));
- if (reply_slice_id.has_value())
- inserter->AddArg(dest_slice_id_,
- Variadic::UnsignedInteger(reply_slice_id->value));
- };
- // Add the dest args to the current transaction slice and get the slice id.
- auto transaction_slice_id =
- context_->slice_tracker->AddArgs(*rcv_track_id, binder_category_id_,
- transaction_slice_id_, args_inserter);
-
- // Add the dest slice id to the reply slice that has just begun.
- auto reply_dest_inserter =
- [this, &transaction_slice_id](ArgsTracker::BoundInserter* inserter) {
- if (transaction_slice_id.has_value())
- inserter->AddArg(dest_slice_id_, Variadic::UnsignedInteger(
- transaction_slice_id.value()));
- };
- context_->slice_tracker->AddArgs(track_id, binder_category_id_, reply_id_,
- reply_dest_inserter);
- transaction_await_rcv.Erase(transaction_id);
- return;
}
- SetArgsCallback* args = awaiting_async_rcv_.Find(transaction_id);
- if (args) {
- context_->slice_tracker->Scoped(ts, track_id, binder_category_id_,
- async_rcv_id_, 0, *args);
- awaiting_async_rcv_.Erase(transaction_id);
- return;
+ // Create a flow between the sending slice and this slice.
+ if (transaction.send_slice_id && recv_slice_id) {
+ context_->flow_tracker->InsertFlow(*transaction.send_slice_id,
+ *recv_slice_id);
}
}
diff --git a/src/trace_processor/importers/ftrace/binder_tracker.h b/src/trace_processor/importers/ftrace/binder_tracker.h
index a9482de..aa710e3 100644
--- a/src/trace_processor/importers/ftrace/binder_tracker.h
+++ b/src/trace_processor/importers/ftrace/binder_tracker.h
@@ -21,6 +21,7 @@
#include "perfetto/base/flat_set.h"
#include "perfetto/ext/base/flat_hash_map.h"
+#include "perfetto/ext/base/optional.h"
#include "src/trace_processor/importers/common/args_tracker.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/destructible.h"
@@ -50,8 +51,8 @@
uint32_t tid,
int32_t transaction_id,
int32_t dest_node,
- int32_t dest_tgid,
- int32_t dest_tid,
+ uint32_t dest_tgid,
+ uint32_t dest_tid,
bool is_reply,
uint32_t flags,
StringId code);
@@ -67,14 +68,19 @@
uint64_t offsets_size);
private:
- TraceProcessorContext* const context_;
- base::FlatSet<int32_t> awaiting_rcv_for_reply_;
+ struct OutstandingTransaction {
+ bool is_reply = false;
+ bool is_oneway = false;
+ SetArgsCallback args_inserter;
+ base::Optional<TrackId> send_track_id;
+ base::Optional<SliceId> send_slice_id;
+ };
- base::FlatHashMap<int32_t, TrackId> transaction_await_rcv;
- base::FlatHashMap<int32_t, SetArgsCallback> awaiting_async_rcv_;
+ TraceProcessorContext* const context_;
+
+ base::FlatHashMap<int32_t, OutstandingTransaction> outstanding_transactions_;
base::FlatHashMap<uint32_t, int64_t> attempt_lock_;
-
base::FlatHashMap<uint32_t, int64_t> lock_acquired_;
const StringId binder_category_id_;
@@ -93,7 +99,6 @@
const StringId flags_;
const StringId code_;
const StringId calling_tid_;
- const StringId dest_slice_id_;
const StringId data_size_;
const StringId offsets_size_;
};
diff --git a/src/trace_processor/importers/ftrace/binder_tracker_unittest.cc b/src/trace_processor/importers/ftrace/binder_tracker_unittest.cc
new file mode 100644
index 0000000..7f62c06
--- /dev/null
+++ b/src/trace_processor/importers/ftrace/binder_tracker_unittest.cc
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/importers/ftrace/binder_tracker.h"
+
+#include "perfetto/base/logging.h"
+#include "src/trace_processor/importers/common/args_tracker.h"
+#include "src/trace_processor/importers/common/event_tracker.h"
+#include "src/trace_processor/importers/common/flow_tracker.h"
+#include "src/trace_processor/importers/common/process_tracker.h"
+#include "src/trace_processor/importers/common/slice_tracker.h"
+#include "src/trace_processor/importers/common/track_tracker.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+constexpr int kOneWay = 0x01;
+
+class BinderTrackerTest : public ::testing::Test {
+ public:
+ BinderTrackerTest() {
+ context.storage.reset(new TraceStorage());
+ context.global_args_tracker.reset(new GlobalArgsTracker(&context));
+ context.args_tracker.reset(new ArgsTracker(&context));
+ context.slice_tracker.reset(new SliceTracker(&context));
+ context.process_tracker.reset(new ProcessTracker(&context));
+ context.track_tracker.reset(new TrackTracker(&context));
+ context.flow_tracker.reset(new FlowTracker(&context));
+ binder_tracker = BinderTracker::GetOrCreate(&context);
+ }
+
+ protected:
+ TraceProcessorContext context;
+ BinderTracker* binder_tracker;
+};
+
+TEST_F(BinderTrackerTest, RequestReply) {
+ int64_t req_ts = 100;
+ int64_t req_recv_ts = 105;
+ int64_t rep_ts = 150;
+ int64_t rep_recv_ts = 155;
+
+ uint32_t req_tid = 5;
+ uint32_t rep_tid = 10;
+
+ int32_t req_transaction_id = 1234;
+ int32_t rep_transaction_id = 5678;
+
+ binder_tracker->Transaction(req_ts, req_tid, req_transaction_id, 9, rep_tid,
+ rep_tid, false, 0, kNullStringId);
+ binder_tracker->TransactionReceived(req_recv_ts, rep_tid, req_transaction_id);
+
+ binder_tracker->Transaction(rep_ts, rep_tid, rep_transaction_id, 99, req_tid,
+ req_tid, true, 0, kNullStringId);
+ binder_tracker->TransactionReceived(rep_recv_ts, req_tid, rep_transaction_id);
+
+ const auto& thread = context.storage->thread_table();
+ const auto& track = context.storage->thread_track_table();
+ const auto& slice = context.storage->slice_table();
+ const auto& flow = context.storage->flow_table();
+ ASSERT_EQ(slice.row_count(), 2u);
+
+ auto tid_for_slice = [&](uint32_t row) {
+ TrackId track_id = slice.track_id()[row];
+ UniqueTid utid = track.utid()[*track.id().IndexOf(track_id)];
+ return thread.tid()[utid];
+ };
+
+ ASSERT_EQ(slice.ts()[0], req_ts);
+ ASSERT_EQ(slice.dur()[0], rep_recv_ts - req_ts);
+ ASSERT_EQ(tid_for_slice(0), req_tid);
+
+ ASSERT_EQ(slice.ts()[1], req_recv_ts);
+ ASSERT_EQ(slice.dur()[1], rep_ts - req_recv_ts);
+ ASSERT_EQ(tid_for_slice(1), rep_tid);
+
+ ASSERT_EQ(flow.row_count(), 1u);
+ ASSERT_EQ(flow.slice_out()[0], slice.id()[0]);
+ ASSERT_EQ(flow.slice_in()[0], slice.id()[1]);
+}
+
+TEST_F(BinderTrackerTest, Oneway) {
+ int64_t sen_ts = 100;
+ int64_t rec_ts = 150;
+
+ uint32_t sen_tid = 5;
+ uint32_t rec_tid = 10;
+
+ int32_t transaction_id = 1234;
+
+ binder_tracker->Transaction(sen_ts, sen_tid, transaction_id, 9, rec_tid,
+ rec_tid, false, kOneWay, kNullStringId);
+ binder_tracker->TransactionReceived(rec_ts, rec_tid, transaction_id);
+
+ const auto& thread = context.storage->thread_table();
+ const auto& track = context.storage->thread_track_table();
+ const auto& slice = context.storage->slice_table();
+ const auto& flow = context.storage->flow_table();
+ ASSERT_EQ(slice.row_count(), 2u);
+
+ auto tid_for_slice = [&](uint32_t row) {
+ TrackId track_id = slice.track_id()[row];
+ UniqueTid utid = track.utid()[*track.id().IndexOf(track_id)];
+ return thread.tid()[utid];
+ };
+
+ ASSERT_EQ(slice.ts()[0], sen_ts);
+ ASSERT_EQ(slice.dur()[0], 0);
+ ASSERT_EQ(tid_for_slice(0), sen_tid);
+
+ ASSERT_EQ(slice.ts()[1], rec_ts);
+ ASSERT_EQ(slice.dur()[1], 0);
+ ASSERT_EQ(tid_for_slice(1), rec_tid);
+
+ ASSERT_EQ(flow.row_count(), 1u);
+ ASSERT_EQ(flow.slice_out()[0], slice.id()[0]);
+ ASSERT_EQ(flow.slice_in()[0], slice.id()[1]);
+}
+
+} // namespace
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
index 4782a3b..e397165 100644
--- a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
@@ -24,7 +24,7 @@
namespace trace_processor {
namespace {
-std::array<MessageDescriptor, 364> descriptors{{
+std::array<MessageDescriptor, 367> descriptors{{
{nullptr, 0, {}},
{nullptr, 0, {}},
{nullptr, 0, {}},
@@ -3876,6 +3876,22 @@
},
},
{
+ "inet_sock_set_state",
+ 9,
+ {
+ {},
+ {"daddr", ProtoSchemaType::kUint32},
+ {"dport", ProtoSchemaType::kUint32},
+ {"family", ProtoSchemaType::kUint32},
+ {"newstate", ProtoSchemaType::kInt32},
+ {"oldstate", ProtoSchemaType::kInt32},
+ {"protocol", ProtoSchemaType::kUint32},
+ {"saddr", ProtoSchemaType::kUint32},
+ {"skaddr", ProtoSchemaType::kUint64},
+ {"sport", ProtoSchemaType::kUint32},
+ },
+ },
+ {
"tcp_retransmit_skb",
7,
{
@@ -3890,19 +3906,50 @@
},
},
{
- "inet_sock_set_state",
- 9,
+ "cros_ec_sensorhub_data",
+ 6,
{
{},
- {"daddr", ProtoSchemaType::kUint32},
- {"dport", ProtoSchemaType::kUint32},
- {"family", ProtoSchemaType::kUint32},
- {"newstate", ProtoSchemaType::kInt32},
- {"oldstate", ProtoSchemaType::kInt32},
+ {"current_time", ProtoSchemaType::kInt64},
+ {"current_timestamp", ProtoSchemaType::kInt64},
+ {"delta", ProtoSchemaType::kInt64},
+ {"ec_fifo_timestamp", ProtoSchemaType::kUint32},
+ {"ec_sensor_num", ProtoSchemaType::kUint32},
+ {"fifo_timestamp", ProtoSchemaType::kInt64},
+ },
+ },
+ {
+ "napi_gro_receive_entry",
+ 19,
+ {
+ {},
+ {"data_len", ProtoSchemaType::kUint32},
+ {"gso_size", ProtoSchemaType::kUint32},
+ {"gso_type", ProtoSchemaType::kUint32},
+ {"hash", ProtoSchemaType::kUint32},
+ {"ip_summed", ProtoSchemaType::kUint32},
+ {"l4_hash", ProtoSchemaType::kUint32},
+ {"len", ProtoSchemaType::kUint32},
+ {"mac_header", ProtoSchemaType::kInt32},
+ {"mac_header_valid", ProtoSchemaType::kUint32},
+ {"name", ProtoSchemaType::kString},
+ {"napi_id", ProtoSchemaType::kUint32},
+ {"nr_frags", ProtoSchemaType::kUint32},
{"protocol", ProtoSchemaType::kUint32},
- {"saddr", ProtoSchemaType::kUint32},
- {"skaddr", ProtoSchemaType::kUint64},
- {"sport", ProtoSchemaType::kUint32},
+ {"queue_mapping", ProtoSchemaType::kUint32},
+ {"skbaddr", ProtoSchemaType::kUint64},
+ {"truesize", ProtoSchemaType::kUint32},
+ {"vlan_proto", ProtoSchemaType::kUint32},
+ {"vlan_tagged", ProtoSchemaType::kUint32},
+ {"vlan_tci", ProtoSchemaType::kUint32},
+ },
+ },
+ {
+ "napi_gro_receive_exit",
+ 1,
+ {
+ {},
+ {"ret", ProtoSchemaType::kInt32},
},
},
}};
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index e9bdddb..9d5e382 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -132,9 +132,11 @@
irq_id_(context_->storage->InternString("irq")),
tcp_state_id_(context_->storage->InternString("tcp_state")),
tcp_event_id_(context_->storage->InternString("tcp_event")),
+ napi_gro_id_(context_->storage->InternString("napi_gro")),
tcp_retransmited_name_id_(
context_->storage->InternString("TCP Retransmit Skb")),
ret_arg_id_(context_->storage->InternString("ret")),
+ len_arg_id_(context->storage->InternString("len")),
direct_reclaim_nr_reclaimed_id_(
context->storage->InternString("direct_reclaim_nr_reclaimed")),
direct_reclaim_order_id_(
@@ -666,6 +668,14 @@
ParseTcpRetransmitSkb(ts, data);
break;
}
+ case FtraceEvent::kNapiGroReceiveEntryFieldNumber: {
+ ParseNapiGroReceiveEntry(cpu, ts, data);
+ break;
+ }
+ case FtraceEvent::kNapiGroReceiveExitFieldNumber: {
+ ParseNapiGroReceiveExit(cpu, ts, data);
+ break;
+ }
default:
break;
}
@@ -1279,8 +1289,8 @@
protos::pbzero::BinderTransactionFtraceEvent::Decoder evt(blob.data,
blob.size);
int32_t dest_node = static_cast<int32_t>(evt.target_node());
- int32_t dest_tgid = static_cast<int32_t>(evt.to_proc());
- int32_t dest_tid = static_cast<int32_t>(evt.to_thread());
+ uint32_t dest_tgid = static_cast<uint32_t>(evt.to_proc());
+ uint32_t dest_tid = static_cast<uint32_t>(evt.to_thread());
int32_t transaction_id = static_cast<int32_t>(evt.debug_id());
bool is_reply = static_cast<int32_t>(evt.reply()) == 1;
uint32_t flags = static_cast<uint32_t>(evt.flags());
@@ -1724,12 +1734,10 @@
if (!id) {
return;
}
- // Store cpu & len as args for metrics computation
- StringId cpu_key = context_->storage->InternString("cpu");
- StringId len_key = context_->storage->InternString("len");
+ // Store cpu & len as args for metrics computation.
context_->args_tracker->AddArgsTo(*id)
- .AddArg(cpu_key, Variadic::UnsignedInteger(cpu))
- .AddArg(len_key, Variadic::UnsignedInteger(evt.len()));
+ .AddArg(cpu_id_, Variadic::UnsignedInteger(cpu))
+ .AddArg(len_arg_id_, Variadic::UnsignedInteger(evt.len()));
}
void FtraceParser::ParseInetSockSetState(int64_t timestamp,
@@ -1809,5 +1817,41 @@
slice_name_id, 0);
}
+void FtraceParser::ParseNapiGroReceiveEntry(uint32_t cpu,
+ int64_t timestamp,
+ protozero::ConstBytes blob) {
+ protos::pbzero::NapiGroReceiveEntryFtraceEvent::Decoder evt(blob.data,
+ blob.size);
+ base::StackString<255> track_name("Napi Gro Cpu %d", cpu);
+ StringId track_name_id =
+ context_->storage->InternString(track_name.string_view());
+ base::StringView net_device = evt.name();
+ StringId slice_name_id = context_->storage->InternString(net_device);
+ TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
+ auto len = evt.len();
+ auto args_inserter = [this, len](ArgsTracker::BoundInserter* inserter) {
+ inserter->AddArg(len_arg_id_, Variadic::Integer(len));
+ };
+ context_->slice_tracker->Begin(timestamp, track, napi_gro_id_, slice_name_id,
+ args_inserter);
+}
+
+void FtraceParser::ParseNapiGroReceiveExit(uint32_t cpu,
+ int64_t timestamp,
+ protozero::ConstBytes blob) {
+ protos::pbzero::NapiGroReceiveExitFtraceEvent::Decoder evt(blob.data,
+ blob.size);
+ base::StackString<255> track_name("Napi Gro Cpu %d", cpu);
+ StringId track_name_id =
+ context_->storage->InternString(track_name.string_view());
+ TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
+ auto ret = evt.ret();
+ auto args_inserter = [this, ret](ArgsTracker::BoundInserter* inserter) {
+ inserter->AddArg(ret_arg_id_, Variadic::Integer(ret));
+ };
+ context_->slice_tracker->End(timestamp, track, napi_gro_id_, {},
+ args_inserter);
+}
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.h b/src/trace_processor/importers/ftrace/ftrace_parser.h
index 6863cac..cb040de 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.h
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.h
@@ -161,6 +161,12 @@
uint32_t pid,
protozero::ConstBytes);
void ParseTcpRetransmitSkb(int64_t timestamp, protozero::ConstBytes);
+ void ParseNapiGroReceiveEntry(uint32_t cpu,
+ int64_t timestamp,
+ protozero::ConstBytes);
+ void ParseNapiGroReceiveExit(uint32_t cpu,
+ int64_t timestamp,
+ protozero::ConstBytes);
TraceProcessorContext* context_;
RssStatTracker rss_stat_tracker_;
@@ -190,8 +196,10 @@
const StringId irq_id_;
const StringId tcp_state_id_;
const StringId tcp_event_id_;
+ const StringId napi_gro_id_;
const StringId tcp_retransmited_name_id_;
const StringId ret_arg_id_;
+ const StringId len_arg_id_;
const StringId direct_reclaim_nr_reclaimed_id_;
const StringId direct_reclaim_order_id_;
const StringId direct_reclaim_may_writepage_id_;
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc b/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc
index 5e61475..74de318 100644
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc
+++ b/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc
@@ -262,14 +262,8 @@
UniqueTid utid =
procs->UpdateThread(static_cast<uint32_t>(tinfo.tid),
static_cast<uint32_t>(tinfo.pid));
- InstantId id = context_->event_tracker->PushInstant(
- ts, name, utid, RefType::kRefUtid);
- auto inserter = context_->args_tracker->AddArgsTo(id);
- for (const Arg& arg : args) {
- inserter.AddArg(
- arg.name, arg.value.ToStorageVariadic(context_->storage.get()));
- }
- context_->args_tracker->Flush();
+ TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
+ slices->Scoped(ts, track_id, cat, name, 0, insert_args);
break;
}
case kCounter: {
@@ -379,9 +373,6 @@
break;
}
case kAsyncInstant: {
- // TODO(eseckler): Consider storing these instants as 0-duration
- // slices instead, so that they get nested underneath begin/end
- // slices.
int64_t correlation_id;
if (!cursor.ReadInt64(&correlation_id)) {
context_->storage->IncrementStats(stats::fuchsia_invalid_event);
@@ -391,15 +382,7 @@
procs->GetOrCreateProcess(static_cast<uint32_t>(tinfo.pid));
TrackId track_id = context_->track_tracker->InternFuchsiaAsyncTrack(
name, upid, correlation_id);
- InstantId id = context_->event_tracker->PushInstant(
- ts, name, track_id.value, RefType::kRefTrack);
- auto inserter = context_->args_tracker->AddArgsTo(id);
- for (const Arg& arg : args) {
- inserter.AddArg(
- arg.name, arg.name,
- arg.value.ToStorageVariadic(context_->storage.get()));
- }
- context_->args_tracker->Flush();
+ slices->Scoped(ts, track_id, cat, name, 0, insert_args);
break;
}
case kAsyncEnd: {
diff --git a/src/trace_processor/importers/gzip/gzip_trace_parser.cc b/src/trace_processor/importers/gzip/gzip_trace_parser.cc
index e8e9494..640f2f1 100644
--- a/src/trace_processor/importers/gzip/gzip_trace_parser.cc
+++ b/src/trace_processor/importers/gzip/gzip_trace_parser.cc
@@ -75,7 +75,7 @@
constexpr size_t kUncompressedBufferSize = 32 * 1024 * 1024;
needs_more_input_ = false;
- decompressor_.SetInput(start, len);
+ decompressor_.Feed(start, len);
for (auto ret = ResultCode::kOk; ret != ResultCode::kEof;) {
if (!buffer_) {
@@ -84,10 +84,10 @@
}
auto result =
- decompressor_.Decompress(buffer_.get() + bytes_written_,
- kUncompressedBufferSize - bytes_written_);
+ decompressor_.ExtractOutput(buffer_.get() + bytes_written_,
+ kUncompressedBufferSize - bytes_written_);
ret = result.ret;
- if (ret == ResultCode::kError || ret == ResultCode::kNoProgress)
+ if (ret == ResultCode::kError)
return util::ErrStatus("Failed to decompress trace chunk");
if (ret == ResultCode::kNeedsMoreInput) {
diff --git a/src/trace_processor/importers/proto/android_camera_event_module.cc b/src/trace_processor/importers/proto/android_camera_event_module.cc
new file mode 100644
index 0000000..7082310
--- /dev/null
+++ b/src/trace_processor/importers/proto/android_camera_event_module.cc
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "src/trace_processor/importers/proto/android_camera_event_module.h"
+
+#include "perfetto/ext/base/string_utils.h"
+#include "protos/perfetto/trace/android/camera_event.pbzero.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "src/trace_processor/importers/common/slice_tracker.h"
+#include "src/trace_processor/importers/common/track_tracker.h"
+#include "src/trace_processor/importers/proto/async_track_set_tracker.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/timestamped_trace_piece.h"
+#include "src/trace_processor/trace_sorter.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+using perfetto::protos::pbzero::TracePacket;
+
+AndroidCameraEventModule::AndroidCameraEventModule(
+ TraceProcessorContext* context)
+ : context_(context) {
+ RegisterForField(TracePacket::kAndroidCameraFrameEventFieldNumber, context);
+}
+
+AndroidCameraEventModule::~AndroidCameraEventModule() = default;
+
+ModuleResult AndroidCameraEventModule::TokenizePacket(
+ const protos::pbzero::TracePacket::Decoder& decoder,
+ TraceBlobView* packet,
+ int64_t /*packet_timestamp*/,
+ PacketSequenceState* state,
+ uint32_t field_id) {
+ if (field_id != TracePacket::kAndroidCameraFrameEventFieldNumber) {
+ return ModuleResult::Ignored();
+ }
+ const auto android_camera_frame_event =
+ protos::pbzero::AndroidCameraFrameEvent::Decoder(
+ decoder.android_camera_frame_event());
+ context_->sorter->PushTracePacket(
+ android_camera_frame_event.request_processing_started_ns(), state,
+ std::move(*packet));
+ return ModuleResult::Handled();
+}
+
+void AndroidCameraEventModule::ParsePacket(const TracePacket::Decoder& decoder,
+ const TimestampedTracePiece& /*ttp*/,
+ uint32_t field_id) {
+ if (field_id != TracePacket::kAndroidCameraFrameEventFieldNumber) {
+ return;
+ }
+ InsertCameraFrameSlice(decoder.android_camera_frame_event());
+}
+
+void AndroidCameraEventModule::InsertCameraFrameSlice(
+ protozero::ConstBytes bytes) {
+ const auto android_camera_frame_event =
+ protos::pbzero::AndroidCameraFrameEvent::Decoder(bytes);
+ StringId track_name = context_->storage->InternString(
+ base::StackString<32>("Camera %d Frames",
+ android_camera_frame_event.camera_id())
+ .string_view());
+ StringId slice_name = context_->storage->InternString(
+ base::StackString<32>("Frame %" PRId64,
+ android_camera_frame_event.frame_number())
+ .string_view());
+ int64_t ts = android_camera_frame_event.request_processing_started_ns();
+ int64_t dur = android_camera_frame_event.responses_all_sent_ns() -
+ android_camera_frame_event.request_processing_started_ns();
+ auto track_set_id =
+ context_->async_track_set_tracker->InternGlobalTrackSet(track_name);
+ auto track_id =
+ context_->async_track_set_tracker->Scoped(track_set_id, ts, dur);
+ context_->slice_tracker->Scoped(ts, track_id, /*category=*/kNullStringId,
+ slice_name, dur);
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/android_camera_event_module.h b/src/trace_processor/importers/proto/android_camera_event_module.h
new file mode 100644
index 0000000..fd117c6
--- /dev/null
+++ b/src/trace_processor/importers/proto/android_camera_event_module.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ANDROID_CAMERA_EVENT_MODULE_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ANDROID_CAMERA_EVENT_MODULE_H_
+
+#include <cstdint>
+#include <unordered_map>
+
+#include "perfetto/ext/base/optional.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "src/trace_processor/importers/proto/proto_importer_module.h"
+#include "src/trace_processor/tables/slice_tables.h"
+#include "src/trace_processor/tables/track_tables.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class AndroidCameraEventModule : public ProtoImporterModule {
+ public:
+ explicit AndroidCameraEventModule(TraceProcessorContext* context);
+
+ ~AndroidCameraEventModule() override;
+
+ ModuleResult TokenizePacket(const protos::pbzero::TracePacket::Decoder& decoder,
+ TraceBlobView* packet,
+ int64_t packet_timestamp,
+ PacketSequenceState* state,
+ uint32_t field_id) override;
+
+ void ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
+ const TimestampedTracePiece& ttp,
+ uint32_t field_id) override;
+
+ private:
+ void InsertCameraFrameSlice(protozero::ConstBytes bytes);
+
+ TraceProcessorContext* context_;
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ANDROID_CAMERA_EVENT_MODULE_H_
diff --git a/src/trace_processor/importers/proto/async_track_set_tracker.cc b/src/trace_processor/importers/proto/async_track_set_tracker.cc
index c45148c..2593a12 100644
--- a/src/trace_processor/importers/proto/async_track_set_tracker.cc
+++ b/src/trace_processor/importers/proto/async_track_set_tracker.cc
@@ -133,8 +133,10 @@
return state.slice_type == TrackState::SliceType::kTimestamp &&
state.ts_end <= ts;
});
- if (it != set.tracks.end())
+ if (it != set.tracks.end()) {
+ it->ts_end = ts + dur;
return it->id;
+ }
TrackState state;
state.slice_type = TrackState::SliceType::kTimestamp;
diff --git a/src/trace_processor/importers/proto/heap_graph_module.cc b/src/trace_processor/importers/proto/heap_graph_module.cc
index 309590a..2172533 100644
--- a/src/trace_processor/importers/proto/heap_graph_module.cc
+++ b/src/trace_processor/importers/proto/heap_graph_module.cc
@@ -138,6 +138,7 @@
decoder.heap_graph());
return;
case TracePacket::kDeobfuscationMappingFieldNumber:
+ HeapGraphTracker::GetOrCreate(context_)->FinalizeAllProfiles();
ParseDeobfuscationMapping(decoder.deobfuscation_mapping());
return;
}
@@ -288,7 +289,6 @@
const std::vector<tables::HeapGraphClassTable::Id>* cls_objects =
heap_graph_tracker->RowsForType(package_name_id,
obfuscated_class_name_id);
-
if (cls_objects) {
for (tables::HeapGraphClassTable::Id id : *cls_objects) {
uint32_t row =
@@ -375,7 +375,7 @@
void HeapGraphModule::NotifyEndOfFile() {
auto* heap_graph_tracker = HeapGraphTracker::GetOrCreate(context_);
- heap_graph_tracker->NotifyEndOfFile();
+ heap_graph_tracker->FinalizeAllProfiles();
}
} // namespace trace_processor
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.cc b/src/trace_processor/importers/proto/heap_graph_tracker.cc
index f789511..1224972 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker.cc
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.cc
@@ -643,39 +643,33 @@
base::StringView normalized_type =
NormalizeTypeName(context_->storage->GetString(interned_type.name));
- // Annoyingly, some apps have a relative path to base.apk. We take this to
- // mean the main package, so we treat it as if the location was unknown.
- bool is_base_apk = false;
+ base::Optional<StringPool::Id> class_package;
if (location_name) {
- base::StringView base_apk("base.apk");
- is_base_apk = context_->storage->GetString(*location_name)
- .substr(0, base_apk.size()) == base_apk;
- }
-
- if (location_name && !is_base_apk) {
base::Optional<std::string> package_name =
PackageFromLocation(context_->storage.get(),
context_->storage->GetString(*location_name));
if (package_name) {
- class_to_rows_[std::make_pair(
- context_->storage->InternString(
- base::StringView(*package_name)),
- context_->storage->InternString(normalized_type))]
- .emplace_back(type_id);
+ class_package =
+ context_->storage->InternString(base::StringView(*package_name));
}
- } else {
- // TODO(b/153552977): Remove this workaround.
- // For profiles collected for old versions of perfetto_hprof, we do not
- // have any location information. We store them using the nullopt
- // location, and assume they are all part of the main APK.
- //
- // This is to keep ingestion of old profiles working (especially
- // important for the UI).
- class_to_rows_[std::make_pair(
- base::nullopt,
- context_->storage->InternString(normalized_type))]
- .emplace_back(type_id);
}
+ if (!class_package) {
+ auto app_id = context_->storage->process_table()
+ .android_appid()[sequence_state.current_upid];
+ if (app_id) {
+ auto pkg_row =
+ context_->storage->package_list_table().uid().IndexOf(*app_id);
+ if (pkg_row) {
+ class_package =
+ context_->storage->package_list_table().package_name()[*pkg_row];
+ }
+ }
+ }
+
+ class_to_rows_[std::make_pair(
+ class_package,
+ context_->storage->InternString(normalized_type))]
+ .emplace_back(type_id);
}
if (!sequence_state.deferred_size_objects_for_type_.empty() ||
@@ -1057,7 +1051,7 @@
return tbl;
}
-void HeapGraphTracker::NotifyEndOfFile() {
+void HeapGraphTracker::FinalizeAllProfiles() {
if (!sequence_state_.empty()) {
context_->storage->IncrementStats(stats::heap_graph_non_finalized_graph);
// There might still be valuable data even though the trace is truncated.
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.h b/src/trace_processor/importers/proto/heap_graph_tracker.h
index 7f804ed..5255639 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker.h
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.h
@@ -119,10 +119,10 @@
uint64_t intern_id,
StringPool::Id str);
void FinalizeProfile(uint32_t seq);
+ void FinalizeAllProfiles();
void SetPacketIndex(uint32_t seq_id, uint64_t index);
~HeapGraphTracker() override;
- void NotifyEndOfFile();
const std::vector<tables::HeapGraphClassTable::Id>* RowsForType(
base::Optional<StringPool::Id> package_name,
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc b/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc
index 6e76214..2d01187 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc
+++ b/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc
@@ -16,9 +16,9 @@
#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
-#include "src/trace_processor/importers/proto/profiler_util.h"
-
#include "perfetto/base/logging.h"
+#include "src/trace_processor/importers/common/process_tracker.h"
+#include "src/trace_processor/importers/proto/profiler_util.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
@@ -53,6 +53,8 @@
TraceProcessorContext context;
context.storage.reset(new TraceStorage());
+ context.process_tracker.reset(new ProcessTracker(&context));
+ context.process_tracker->GetOrCreateProcess(kPid);
HeapGraphTracker tracker(&context);
@@ -193,6 +195,8 @@
TraceProcessorContext context;
context.storage.reset(new TraceStorage());
+ context.process_tracker.reset(new ProcessTracker(&context));
+ context.process_tracker->GetOrCreateProcess(kPid);
HeapGraphTracker tracker(&context);
diff --git a/src/trace_processor/importers/proto/metadata_tracker.cc b/src/trace_processor/importers/proto/metadata_tracker.cc
index e286dea..7f324b9 100644
--- a/src/trace_processor/importers/proto/metadata_tracker.cc
+++ b/src/trace_processor/importers/proto/metadata_tracker.cc
@@ -16,12 +16,20 @@
#include "src/trace_processor/importers/proto/metadata_tracker.h"
+#include "perfetto/ext/base/crash_keys.h"
#include "src/trace_processor/importers/common/process_tracker.h"
+#include "src/trace_processor/storage/metadata.h"
#include "src/trace_processor/types/trace_processor_context.h"
namespace perfetto {
namespace trace_processor {
+namespace {
+
+base::CrashKey g_crash_key_uuid("trace_uuid");
+
+}
+
MetadataTracker::MetadataTracker(TraceProcessorContext* context)
: context_(context) {
for (uint32_t i = 0; i < kNumKeys; ++i) {
@@ -37,6 +45,13 @@
PERFETTO_DCHECK(metadata::kKeyTypes[key] == metadata::KeyType::kSingle);
PERFETTO_DCHECK(value.type == metadata::kValueTypes[key]);
+ // When the trace_uuid is set, store a copy in a crash key, so in case of
+ // a crash in the pipelines we can tell which trace caused the crash.
+ if (key == metadata::trace_uuid && value.type == Variadic::kString) {
+ auto uuid_string_view = context_->storage->GetString(value.string_value);
+ g_crash_key_uuid.Set(uuid_string_view);
+ }
+
auto* metadata_table = context_->storage->mutable_metadata_table();
uint32_t key_idx = static_cast<uint32_t>(key);
base::Optional<uint32_t> opt_row =
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index 0c3f315..3ce7b77 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -166,6 +166,22 @@
static_cast<int64_t>(evt.chunks_discarded()));
storage->SetStats(stats::traced_patches_discarded,
static_cast<int64_t>(evt.patches_discarded()));
+ storage->SetStats(stats::traced_flushes_requested,
+ static_cast<int64_t>(evt.flushes_requested()));
+ storage->SetStats(stats::traced_flushes_succeeded,
+ static_cast<int64_t>(evt.flushes_succeeded()));
+ storage->SetStats(stats::traced_flushes_failed,
+ static_cast<int64_t>(evt.flushes_failed()));
+ switch (evt.final_flush_outcome()) {
+ case protos::pbzero::TraceStats::FINAL_FLUSH_SUCCEEDED:
+ storage->IncrementStats(stats::traced_final_flush_succeeded, 1);
+ break;
+ case protos::pbzero::TraceStats::FINAL_FLUSH_FAILED:
+ storage->IncrementStats(stats::traced_final_flush_failed, 1);
+ break;
+ case protos::pbzero::TraceStats::FINAL_FLUSH_UNSPECIFIED:
+ break;
+ }
int buf_num = 0;
for (auto it = evt.buffer_stats(); it; ++it, ++buf_num) {
diff --git a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
index 1a96191..b6b5937 100644
--- a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
+++ b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
@@ -28,26 +28,21 @@
TraceBlobView* output) {
PERFETTO_DCHECK(util::IsGzipSupported());
- uint8_t zbuf[4096];
-
std::vector<uint8_t> data;
data.reserve(input.length());
// Ensure that the decompressor is able to cope with a new stream of data.
decompressor_.Reset();
- decompressor_.SetInput(input.data(), input.length());
-
using ResultCode = util::GzipDecompressor::ResultCode;
- for (auto ret = ResultCode::kOk; ret != ResultCode::kEof;) {
- auto res = decompressor_.Decompress(zbuf, base::ArraySize(zbuf));
- ret = res.ret;
- if (ret == ResultCode::kError || ret == ResultCode::kNoProgress ||
- ret == ResultCode::kNeedsMoreInput) {
- return util::ErrStatus("Failed to decompress (error code: %d)",
- static_cast<int>(ret));
- }
+ ResultCode ret = decompressor_.FeedAndExtract(
+ input.data(), input.length(),
+ [&data](const uint8_t* buffer, size_t buffer_len) {
+ data.insert(data.end(), buffer, buffer + buffer_len);
+ });
- data.insert(data.end(), zbuf, zbuf + res.bytes_written);
+ if (ret == ResultCode::kError || ret == ResultCode::kNeedsMoreInput) {
+ return util::ErrStatus("Failed to decompress (error code: %d)",
+ static_cast<int>(ret));
}
TraceBlob out_blob = TraceBlob::CopyFrom(data.data(), data.size());
diff --git a/src/trace_processor/importers/systrace/systrace_line_parser.cc b/src/trace_processor/importers/systrace/systrace_line_parser.cc
index 9120e65..4cfd788 100644
--- a/src/trace_processor/importers/systrace/systrace_line_parser.cc
+++ b/src/trace_processor/importers/systrace/systrace_line_parser.cc
@@ -41,6 +41,7 @@
rss_stat_tracker_(context_),
sched_wakeup_name_id_(ctx->storage->InternString("sched_wakeup")),
sched_waking_name_id_(ctx->storage->InternString("sched_waking")),
+ cpufreq_name_id_(ctx->storage->InternString("cpufreq")),
cpuidle_name_id_(ctx->storage->InternString("cpuidle")),
workqueue_name_id_(ctx->storage->InternString("workqueue")),
sched_blocked_reason_id_(
@@ -123,6 +124,19 @@
context_->args_tracker->AddArgsTo(instant_id)
.AddArg(waker_utid_id_, Variadic::UnsignedInteger(utid));
+ } else if (line.event_name == "cpu_frequency") {
+ base::Optional<uint32_t> event_cpu = base::StringToUInt32(args["cpu_id"]);
+ base::Optional<double> new_state = base::StringToDouble(args["state"]);
+ if (!event_cpu.has_value()) {
+ return util::Status("Could not convert event cpu");
+ }
+ if (!event_cpu.has_value()) {
+ return util::Status("Could not convert state");
+ }
+
+ TrackId track = context_->track_tracker->InternCpuCounterTrack(
+ cpufreq_name_id_, event_cpu.value());
+ context_->event_tracker->PushCounter(line.ts, new_state.value(), track);
} else if (line.event_name == "cpu_idle") {
base::Optional<uint32_t> event_cpu = base::StringToUInt32(args["cpu_id"]);
base::Optional<double> new_state = base::StringToDouble(args["state"]);
@@ -139,8 +153,8 @@
} else if (line.event_name == "binder_transaction") {
auto id = base::StringToInt32(args["transaction"]);
auto dest_node = base::StringToInt32(args["dest_node"]);
- auto dest_tgid = base::StringToInt32(args["dest_proc"]);
- auto dest_tid = base::StringToInt32(args["dest_thread"]);
+ auto dest_tgid = base::StringToUInt32(args["dest_proc"]);
+ auto dest_tid = base::StringToUInt32(args["dest_thread"]);
auto is_reply = base::StringToInt32(args["reply"]).value() == 1;
auto flags_str = args["flags"];
char* end;
diff --git a/src/trace_processor/importers/systrace/systrace_line_parser.h b/src/trace_processor/importers/systrace/systrace_line_parser.h
index 24331fe..126fca7 100644
--- a/src/trace_processor/importers/systrace/systrace_line_parser.h
+++ b/src/trace_processor/importers/systrace/systrace_line_parser.h
@@ -39,6 +39,7 @@
const StringId sched_wakeup_name_id_ = kNullStringId;
const StringId sched_waking_name_id_ = kNullStringId;
+ const StringId cpufreq_name_id_ = kNullStringId;
const StringId cpuidle_name_id_ = kNullStringId;
const StringId workqueue_name_id_ = kNullStringId;
const StringId sched_blocked_reason_id_ = kNullStringId;
diff --git a/src/trace_processor/metrics/sql/BUILD.gn b/src/trace_processor/metrics/sql/BUILD.gn
index 4135e50..f8de2ad 100644
--- a/src/trace_processor/metrics/sql/BUILD.gn
+++ b/src/trace_processor/metrics/sql/BUILD.gn
@@ -69,6 +69,7 @@
"android/android_multiuser_populator.sql",
"android/span_view_stats.sql",
"android/android_sysui_cuj.sql",
+ "android/android_sysui_cuj_surfaceflinger.sql",
"android/android_sysui_cuj_jank_query.sql",
"android/process_counter_span_view.sql",
"android/global_counter_span_view.sql",
diff --git a/src/trace_processor/metrics/sql/android/android_netperf.sql b/src/trace_processor/metrics/sql/android/android_netperf.sql
index 8a67a7d..6471d94 100644
--- a/src/trace_processor/metrics/sql/android/android_netperf.sql
+++ b/src/trace_processor/metrics/sql/android/android_netperf.sql
@@ -26,6 +26,17 @@
WHERE name GLOB "* Received KB"
ORDER BY ts DESC;
+DROP VIEW IF EXISTS gro_rx_packet_count;
+CREATE VIEW gro_rx_packet_count AS
+ SELECT
+ s.name AS dev,
+ COUNT(1) AS cnt
+ FROM slice s
+ LEFT JOIN track t
+ ON s.track_id = t.id
+ WHERE t.name GLOB "Napi Gro Cpu *"
+ GROUP BY s.name;
+
DROP VIEW IF EXISTS tx_packets;
CREATE VIEW tx_packets AS
SELECT
@@ -47,6 +58,16 @@
SELECT DISTINCT dev
FROM rx_packets;
+DROP VIEW IF EXISTS tcp_retransmitted_count;
+CREATE VIEW tcp_retransmitted_count AS
+ SELECT
+ COUNT(1) AS cnt
+ FROM slice s
+ LEFT JOIN track t
+ ON s.track_id = t.id
+ WHERE
+ t.name = "TCP Retransmit Skb";
+
DROP VIEW IF EXISTS device_per_core_ingress_traffic;
CREATE VIEW device_per_core_ingress_traffic AS
SELECT
@@ -128,7 +149,16 @@
RepeatedField(proto)
FROM device_per_core_ingress_traffic
WHERE device_per_core_ingress_traffic.dev = device_total_ingress_traffic.dev
- )
+ ),
+ 'gro_aggregation_ratio', (
+ SELECT
+ CASE
+ WHEN packets > 0 THEN '1:' || CAST( (cnt*1.0/packets) AS text)
+ ELSE '0:' || cnt
+ END
+ FROM gro_rx_packet_count
+ WHERE gro_rx_packet_count.dev = net_devices.dev
+ )
)
FROM device_total_ingress_traffic
WHERE device_total_ingress_traffic.dev = net_devices.dev
@@ -241,6 +271,11 @@
runtime/total_packet/1e6
FROM total_net_rx_action_statistic
)
+ ),
+ 'retransmission_rate', (
+ SELECT
+ (SELECT cnt FROM tcp_retransmitted_count) * 100.0 / COUNT(1)
+ FROM tx_packets
)
);
diff --git a/src/trace_processor/metrics/sql/android/android_sysui_cuj.sql b/src/trace_processor/metrics/sql/android/android_sysui_cuj.sql
index 073c247..48b5b41 100644
--- a/src/trace_processor/metrics/sql/android/android_sysui_cuj.sql
+++ b/src/trace_processor/metrics/sql/android/android_sysui_cuj.sql
@@ -31,7 +31,8 @@
JOIN process_metadata USING (upid)
WHERE
slice.name GLOB 'J<*>'
- AND slice.dur > 0
+ -- Filter out CUJs that are <4ms long - assuming CUJ was cancelled.
+ AND slice.dur > 4000000
AND (
process.name GLOB 'com.google.android*'
OR process.name GLOB 'com.android.*')
@@ -57,6 +58,22 @@
SELECT MIN(vsync) as vsync_min, MAX(vsync) as vsync_max
FROM android_sysui_cuj_do_frame_slices_in_cuj;
+DROP TABLE IF EXISTS android_sysui_cuj_frame_expected_timeline_events;
+CREATE TABLE android_sysui_cuj_frame_expected_timeline_events AS
+ SELECT
+ CAST(e.name as INTEGER) as vsync,
+ e.ts as ts_expected,
+ e.dur as dur_expected,
+ MIN(a.ts) as ts_actual,
+ MAX(a.dur) as dur_actual
+ FROM android_sysui_cuj_last_cuj cuj
+ JOIN expected_frame_timeline_slice e USING (upid)
+ JOIN android_sysui_cuj_vsync_boundaries vsync
+ ON CAST(e.name as INTEGER) >= vsync.vsync_min
+ AND CAST(e.name as INTEGER) <= vsync.vsync_max
+ JOIN actual_frame_timeline_slice a ON e.upid = a.upid AND e.name = a.name
+ GROUP BY e.name, e.ts, e.dur;
+
DROP TABLE IF EXISTS android_sysui_cuj_frame_timeline_events;
CREATE TABLE android_sysui_cuj_frame_timeline_events AS
SELECT
@@ -83,18 +100,18 @@
SELECT
slices.*,
CASE
- WHEN fte.ts_actual IS NULL
+ WHEN fte.ts_expected IS NULL
THEN ts
- ELSE MAX(COALESCE(slices.ts_prev_frame_end, 0), fte.ts_actual)
+ ELSE MAX(COALESCE(slices.ts_prev_frame_end, 0), fte.ts_expected)
END as ts_adjusted
FROM android_sysui_cuj_do_frame_slices_in_cuj slices
-LEFT JOIN android_sysui_cuj_frame_timeline_events fte
-ON slices.vsync = fte.vsync
+LEFT JOIN android_sysui_cuj_frame_expected_timeline_events fte
+ ON slices.vsync = fte.vsync
-- In rare cases there is a clock drift after device suspends
-- This may cause the actual/expected timeline to be misaligned with the rest
-- of the trace for a short period.
-- Do not use the timelines if it seems that this happened.
-AND slices.ts >= fte.ts_actual AND slices.ts <= fte.ts_actual + fte.dur_actual;
+AND slices.ts >= fte.ts_actual AND slices.ts <= (fte.ts_actual + fte.dur_actual);
DROP TABLE IF EXISTS android_sysui_cuj_ts_boundaries;
CREATE TABLE android_sysui_cuj_ts_boundaries AS
@@ -169,57 +186,47 @@
DROP TABLE IF EXISTS android_sysui_cuj_frames;
CREATE TABLE android_sysui_cuj_frames AS
WITH gcs_to_rt_match AS (
- -- Match GPU Completion with the last RT slice before it
SELECT
- gcs.ts as gcs_ts,
- gcs.ts_end as gcs_ts_end,
- gcs.dur as gcs_dur,
- gcs.idx as idx,
- MAX(rts.ts) as rts_ts
- FROM android_sysui_cuj_gpu_completion_slices_in_cuj gcs
- JOIN android_sysui_cuj_render_thread_slices_in_cuj rts ON rts.ts < gcs.ts
+ rts.ts,
+ CASE
+ WHEN rtfence.name GLOB 'GPU completion fence *'
+ THEN CAST(STR_SPLIT(rtfence.name, ' ', 3) AS INTEGER)
+ WHEN rtfence.name GLOB 'Trace GPU completion fence *'
+ THEN CAST(STR_SPLIT(rtfence.name, ' ', 4) AS INTEGER)
+ ELSE NULL
+ END AS idx
+ FROM android_sysui_cuj_render_thread_slices_in_cuj rts
+ JOIN descendant_slice(rts.id) rtfence ON rtfence.name GLOB '*GPU completion fence*'
-- dispatchFrameCallbacks might be seen in case of
-- drawing that happens on RT only (e.g. ripple effect)
WHERE (rts.name GLOB 'DrawFrame*' OR rts.name = 'dispatchFrameCallbacks')
- GROUP BY gcs.ts, gcs.ts_end, gcs.dur, gcs.idx
- ),
- frame_boundaries AS (
- -- Match main thread doFrame with RT DrawFrame and optional GPU Completion
- SELECT
- mts.ts_adjusted as mts_ts,
- mts.ts_end as mts_ts_end,
- mts.ts_end - mts.ts_adjusted as mts_dur,
- mts.vsync as vsync,
- MAX(gcs_rt.gcs_ts) as gcs_ts_start,
- MAX(gcs_rt.gcs_ts_end) as gcs_ts_end
- FROM android_sysui_cuj_do_frame_slices_in_cuj_adjusted mts
- JOIN android_sysui_cuj_draw_frame_slices_in_cuj rts
- ON mts.vsync = rts.vsync
- LEFT JOIN gcs_to_rt_match gcs_rt ON gcs_rt.rts_ts = rts.ts
- GROUP BY mts.ts, mts.ts_end, mts.dur
)
SELECT
- ROW_NUMBER() OVER (ORDER BY f.mts_ts) AS frame_number,
- f.vsync as vsync,
- f.mts_ts as ts_main_thread_start,
- f.mts_ts_end as ts_main_thread_end,
- f.mts_dur AS dur_main_thread,
+ ROW_NUMBER() OVER (ORDER BY mts.ts) AS frame_number,
+ mts.vsync as vsync,
+ -- Main thread timings
+ mts.ts_adjusted as ts_main_thread_start,
+ mts.ts_end as ts_main_thread_end,
+ mts.ts_end - mts.ts_adjusted AS dur_main_thread,
+ -- RenderThread timings
MIN(rts.ts) AS ts_render_thread_start,
MAX(rts.ts_end) AS ts_render_thread_end,
SUM(rts.dur) AS dur_render_thread,
- MAX(gcs_rt.gcs_ts_end) AS ts_frame_end,
- MAX(gcs_rt.gcs_ts_end) - f.mts_ts AS dur_frame,
- SUM(gcs_rt.gcs_ts_end - MAX(COALESCE(hwc.ts_end, 0), gcs_rt.gcs_ts)) as dur_gcs,
- COUNT(DISTINCT(rts.ts)) as draw_frames,
- COUNT(DISTINCT(gcs_rt.gcs_ts)) as gpu_completions
- FROM frame_boundaries f
- JOIN android_sysui_cuj_draw_frame_slices_in_cuj rts
- ON f.vsync = rts.vsync
- LEFT JOIN gcs_to_rt_match gcs_rt
- ON rts.ts = gcs_rt.rts_ts
- LEFT JOIN android_sysui_cuj_hwc_release_slices_in_cuj hwc USING (idx)
- GROUP BY f.mts_ts
- HAVING gpu_completions >= 1;
+ -- HWC and GPU
+ SUM(gcs.ts_end - MAX(COALESCE(hwc.ts_end, 0), gcs.ts)) as dur_gcs,
+ -- Overall frame timings
+ COALESCE(MAX(gcs.ts_end), MAX(rts.ts_end)) AS ts_frame_end,
+ COALESCE(MAX(gcs.ts_end), MAX(rts.ts_end)) - mts.ts_adjusted AS dur_frame,
+ MAX(gcs_rt.idx) IS NOT NULL as drew_anything
+ -- Match main thread doFrame with RT DrawFrame and optional GPU Completion
+ FROM android_sysui_cuj_do_frame_slices_in_cuj_adjusted mts
+ JOIN android_sysui_cuj_draw_frame_slices_in_cuj rts
+ ON mts.vsync = rts.vsync
+ LEFT JOIN gcs_to_rt_match gcs_rt ON gcs_rt.ts = rts.ts
+ LEFT JOIN android_sysui_cuj_gpu_completion_slices_in_cuj gcs USING(idx)
+ LEFT JOIN android_sysui_cuj_hwc_release_slices_in_cuj hwc USING (idx)
+ GROUP BY mts.vsync, mts.ts_adjusted, mts.ts_end
+ HAVING drew_anything;
DROP TABLE IF EXISTS android_sysui_cuj_missed_frames;
CREATE TABLE android_sysui_cuj_missed_frames AS
diff --git a/src/trace_processor/metrics/sql/android/android_sysui_cuj_surfaceflinger.sql b/src/trace_processor/metrics/sql/android/android_sysui_cuj_surfaceflinger.sql
new file mode 100644
index 0000000..0d82725
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/android_sysui_cuj_surfaceflinger.sql
@@ -0,0 +1,251 @@
+-- Isolate the SurfaceFlinger process Id
+DROP TABLE IF EXISTS android_sysui_cuj_sf_process;
+CREATE TABLE android_sysui_cuj_sf_process AS
+SELECT name, upid FROM process
+WHERE process.name='/system/bin/surfaceflinger'
+LIMIT 1;
+
+DROP VIEW IF EXISTS android_sysui_cuj_sf_actual_frame_timeline_slice;
+CREATE VIEW android_sysui_cuj_sf_actual_frame_timeline_slice AS
+SELECT
+ actual.*,
+ actual.ts + actual.dur AS ts_end,
+ CAST(actual.name AS integer) AS vsync
+FROM actual_frame_timeline_slice actual JOIN android_sysui_cuj_sf_process USING (upid);
+
+DROP TABLE IF EXISTS android_sysui_cuj_surfaceflinger_main_thread;
+CREATE TABLE android_sysui_cuj_surfaceflinger_main_thread AS
+ SELECT android_sysui_cuj_sf_process.name AS process_name, thread.utid
+ FROM thread JOIN android_sysui_cuj_sf_process USING (upid)
+ WHERE thread.is_main_thread;
+
+DROP TABLE IF EXISTS android_sysui_cuj_sf_main_thread_track;
+CREATE TABLE android_sysui_cuj_sf_main_thread_track AS
+SELECT thread_track.id
+FROM thread_track
+JOIN android_sysui_cuj_surfaceflinger_main_thread thread USING (utid);
+
+DROP VIEW IF EXISTS android_sysui_cuj_surfaceflinger_gpu_completion_thread;
+CREATE VIEW android_sysui_cuj_surfaceflinger_gpu_completion_thread AS
+ SELECT android_sysui_cuj_sf_process.name AS process_name, thread.utid
+ FROM thread JOIN android_sysui_cuj_sf_process USING (upid)
+ WHERE thread.name = 'GPU completion';
+
+DROP VIEW IF EXISTS android_sysui_cuj_surfaceflinger_renderengine_thread;
+CREATE VIEW android_sysui_cuj_surfaceflinger_renderengine_thread AS
+ SELECT android_sysui_cuj_sf_process.name AS process_name, thread.utid
+ FROM thread JOIN android_sysui_cuj_sf_process USING (upid)
+ WHERE thread.name = 'RenderEngine';
+
+DROP VIEW IF EXISTS android_sysui_cuj_surfaceflinger_gpu_completion_slices;
+CREATE VIEW android_sysui_cuj_surfaceflinger_gpu_completion_slices AS
+ SELECT
+ process_name,
+ thread.utid,
+ slice.*,
+ slice.ts + slice.dur AS ts_end,
+ -- Extracts 1234 from 'waiting for GPU completion 1234'
+ CAST(STR_SPLIT(slice.name, ' ', 4) AS INTEGER) AS idx
+ FROM slice
+ JOIN thread_track ON slice.track_id = thread_track.id
+ JOIN android_sysui_cuj_surfaceflinger_gpu_completion_thread thread USING (utid)
+ WHERE slice.name GLOB 'waiting for GPU completion *'
+ AND dur > 0;
+
+-- Find flows between actual frame slices from app process to surfaceflinger, allowing us to
+-- correlate vsyncs.
+DROP VIEW IF EXISTS android_sysui_cuj_surfaceflinger_app_flow_vsyncs;
+CREATE VIEW android_sysui_cuj_surfaceflinger_app_flow_vsyncs AS
+SELECT
+ app_slice.name AS app_vsync,
+ app_slice.id AS app_slice_id,
+ cuj_process.name AS app_process,
+ sf_slice.name AS sf_vsync,
+ sf_slice.id AS sf_slice_id
+FROM android_sysui_cuj_sf_actual_frame_timeline_slice sf_slice
+JOIN directly_connected_flow(sf_slice.id) flow
+JOIN actual_frame_timeline_slice app_slice ON slice_in = app_slice.id
+JOIN android_sysui_cuj_last_cuj cuj_process ON app_slice.upid = cuj_process.upid
+GROUP BY app_vsync, sf_vsync;
+
+-- Filter to those SF frames which flow from app frames that are within the app vsync boundaries of
+-- the CUJ
+DROP TABLE IF EXISTS android_sysui_cuj_sf_frames_in_cuj;
+CREATE TABLE android_sysui_cuj_sf_frames_in_cuj AS
+SELECT
+ sf_frame.ts,
+ sf_frame.dur,
+ sf_frame.jank_type,
+ sf_frame.ts + sf_frame.dur AS ts_end,
+ flows.sf_vsync,
+ flows.app_vsync
+-- This table contains only the frame timeline slices within the CUJ app vsync boundaries
+FROM android_sysui_cuj_frame_timeline_events app_frames
+-- Find the matching SF frame via flow
+JOIN android_sysui_cuj_surfaceflinger_app_flow_vsyncs flows ON app_frames.vsync = flows.app_vsync
+JOIN android_sysui_cuj_sf_actual_frame_timeline_slice sf_frame ON sf_frame.id = flows.sf_slice_id
+GROUP BY flows.sf_vsync;
+
+-- Take the min and max vsync to define the SurfaceFlinger boundaries
+DROP TABLE IF EXISTS android_sysui_cuj_sf_vsync_boundaries;
+CREATE TABLE android_sysui_cuj_sf_vsync_boundaries AS
+SELECT MIN(sf_vsync) as vsync_min, MAX(sf_vsync) as vsync_max
+FROM android_sysui_cuj_sf_frames_in_cuj;
+
+-- Find just the commit slices, within the CUJ (by vsync)
+DROP TABLE IF EXISTS android_sysui_cuj_surfaceflinger_commit_slices_in_cuj;
+CREATE TABLE android_sysui_cuj_surfaceflinger_commit_slices_in_cuj AS
+SELECT * FROM
+ (SELECT
+ -- Extract the vsync number from name like 'commit 235991 vsyncIn 15.992ms'
+ CAST(STR_SPLIT(slice.name, ' ', 1) AS INTEGER) as vsync,
+ slice.name,
+ slice.ts,
+ slice.dur,
+ slice.ts + slice.dur AS ts_end
+ FROM slice
+ JOIN android_sysui_cuj_sf_main_thread_track main_track ON slice.track_id = main_track.id
+ WHERE slice.dur > 0 AND slice.name GLOB 'commit *')
+JOIN android_sysui_cuj_sf_vsync_boundaries cuj_boundaries
+WHERE vsync >= cuj_boundaries.vsync_min AND vsync <= cuj_boundaries.vsync_max;
+
+-- Find just the onMessageInvalidate slices, within the CUJ (by vsync)
+DROP VIEW IF EXISTS android_sysui_cuj_surfaceflinger_on_message_invalidate_slices_in_cuj;
+CREATE VIEW android_sysui_cuj_surfaceflinger_on_message_invalidate_slices_in_cuj AS
+ WITH on_msg AS (SELECT
+ -- Extract the vsync number from name like 'onMessageInvalidate 235991 vsyncIn 15.992ms'
+ CAST(STR_SPLIT(slice.name, ' ', 1) AS INTEGER) as vsync,
+ slice.ts,
+ slice.ts + slice.dur AS ts_end,
+ slice.dur
+ FROM slice
+ JOIN android_sysui_cuj_sf_main_thread_track main_track ON slice.track_id = main_track.id
+ WHERE slice.name GLOB 'onMessageInvalidate *'
+ )
+SELECT
+ on_msg.vsync,
+ on_msg.ts,
+ on_msg.ts_end,
+ on_msg.dur,
+ lag(on_msg.ts_end) OVER (ORDER BY on_msg.ts_end ASC) AS ts_prev_frame_end,
+ lead(on_msg.ts) OVER (ORDER BY on_msg.ts ASC) AS ts_next_frame_start
+FROM on_msg
+JOIN android_sysui_cuj_sf_vsync_boundaries cuj_boundaries
+WHERE on_msg.vsync >= cuj_boundaries.vsync_min AND on_msg.vsync <= cuj_boundaries.vsync_max;
+
+-- Find just the composite slices
+DROP TABLE IF EXISTS android_sysui_cuj_surfaceflinger_composite_slices;
+CREATE TABLE android_sysui_cuj_surfaceflinger_composite_slices AS
+ SELECT
+ slice.name,
+ slice.ts,
+ slice.dur,
+ slice.ts + slice.dur AS ts_end
+ FROM slice
+ JOIN android_sysui_cuj_sf_main_thread_track main_track ON slice.track_id = main_track.id
+ WHERE slice.dur > 0 AND slice.name = 'composite';
+
+DROP VIEW IF EXISTS android_sysui_cuj_surfaceflinger_commit_composite_frames_in_cuj;
+CREATE VIEW android_sysui_cuj_surfaceflinger_commit_composite_frames_in_cuj AS
+ WITH commit_to_composite AS (
+ SELECT
+ commits.vsync,
+ commits.ts AS commit_ts,
+ commits.name AS name,
+ min(composite.ts) AS composite_ts
+ FROM android_sysui_cuj_surfaceflinger_commit_slices_in_cuj commits
+ JOIN android_sysui_cuj_surfaceflinger_composite_slices composite ON composite.ts > commits.ts_end
+ GROUP BY commits.vsync
+ )
+ SELECT
+ vsync,
+ match.commit_ts AS ts,
+ composite.ts_end AS ts_end,
+ composite.ts_end - match.commit_ts AS dur,
+ lag(composite.ts_end) OVER (ORDER BY composite.ts_end ASC) AS ts_prev_frame_end,
+ lead(match.commit_ts) OVER (ORDER BY match.commit_ts ASC) AS ts_next_frame_start
+ FROM commit_to_composite match
+ JOIN android_sysui_cuj_surfaceflinger_composite_slices composite ON match.composite_ts = composite.ts;
+
+-- All SF frames in the CUJ
+DROP TABLE IF EXISTS android_sysui_cuj_surfaceflinger_main_thread_frames;
+CREATE TABLE android_sysui_cuj_surfaceflinger_main_thread_frames AS
+SELECT * FROM android_sysui_cuj_surfaceflinger_on_message_invalidate_slices_in_cuj
+UNION ALL
+SELECT * FROM android_sysui_cuj_surfaceflinger_commit_composite_frames_in_cuj;
+
+-- Our timestamp boundaries are the earliest ts and latest ts_end of the main thread frames (e.g.
+-- onMessageInvalidate or commit/composite pair) which flow from app frames within the CUJ
+DROP TABLE IF EXISTS android_sysui_cuj_sf_ts_boundaries;
+CREATE TABLE android_sysui_cuj_sf_ts_boundaries AS
+SELECT ts, ts_end - ts AS dur, ts_end
+FROM (SELECT MIN(ts) as ts, MAX(ts_end) as ts_end FROM android_sysui_cuj_surfaceflinger_main_thread_frames);
+
+DROP TABLE IF EXISTS android_sysui_cuj_surfaceflinger_main_thread_slices_in_cuj;
+CREATE TABLE android_sysui_cuj_surfaceflinger_main_thread_slices_in_cuj AS
+ SELECT
+ slice.*,
+ slice.ts + slice.dur AS ts_end
+ FROM slice
+ JOIN android_sysui_cuj_sf_main_thread_track main_track ON slice.track_id = main_track.id
+ JOIN android_sysui_cuj_sf_ts_boundaries cuj_boundaries
+ ON slice.ts >= cuj_boundaries.ts AND slice.ts <= cuj_boundaries.ts_end
+ WHERE slice.dur > 0;
+
+-- Find SurfaceFlinger GPU completions that are within the CUJ
+DROP TABLE IF EXISTS android_sysui_cuj_surfaceflinger_gpu_completion_slices_in_cuj;
+CREATE TABLE android_sysui_cuj_surfaceflinger_gpu_completion_slices_in_cuj AS
+SELECT slice.* FROM android_sysui_cuj_surfaceflinger_gpu_completion_slices slice
+JOIN android_sysui_cuj_sf_ts_boundaries cuj_boundaries
+ON slice.ts >= cuj_boundaries.ts AND slice.ts <= cuj_boundaries.ts_end;
+
+DROP TABLE IF EXISTS android_sysui_cuj_surfaceflinger_renderengine_slices_in_cuj;
+CREATE TABLE android_sysui_cuj_surfaceflinger_renderengine_slices_in_cuj AS
+ SELECT
+ process_name,
+ thread.utid,
+ slice.*,
+ slice.ts + slice.dur AS ts_end
+ FROM slice
+ JOIN thread_track ON slice.track_id = thread_track.id
+ JOIN android_sysui_cuj_surfaceflinger_renderengine_thread thread USING (utid)
+ JOIN android_sysui_cuj_sf_ts_boundaries cuj_boundaries
+ ON slice.ts >= cuj_boundaries.ts AND slice.ts <= cuj_boundaries.ts_end
+ WHERE slice.dur > 0;
+
+DROP VIEW IF EXISTS android_sysui_cuj_gcs_to_mt_match;
+CREATE VIEW android_sysui_cuj_gcs_to_mt_match AS
+-- Match Mainthread slice with the first GPU Completion that begins during it
+SELECT
+gcs.ts as gcs_ts,
+gcs.ts_end as gcs_ts_end,
+gcs.dur as gcs_dur,
+gcs.idx as idx,
+mtf.ts as mts_ts,
+mtf.vsync as vsync
+FROM android_sysui_cuj_surfaceflinger_gpu_completion_slices_in_cuj gcs
+-- join with all previous render frames but take latest start time
+JOIN android_sysui_cuj_surfaceflinger_main_thread_frames mtf ON gcs.ts > mtf.ts AND gcs.ts < mtf.ts + mtf.dur
+GROUP BY gcs.ts, gcs.ts_end, gcs.dur, gcs.idx;
+
+-- Those SurfaceFlinger Frames where we missed the deadline
+-- To avoid overlap - which could result in counting janky slices more than once - we limit the
+-- definition of each frame to:
+-- * beginning when the shared timeline actual frame starts, or - if later -
+-- when the previous main thread computation ended
+-- * ending when the next main thread computation begins, but no later than the
+-- shared timeline actual frame ends
+DROP TABLE IF EXISTS android_sysui_cuj_sf_missed_frames;
+CREATE TABLE android_sysui_cuj_sf_missed_frames AS
+SELECT
+ CAST(frame.name AS integer) AS frame_number,
+ max(mtf.ts_prev_frame_end, frame.ts) AS ts,
+ min(mtf.ts_next_frame_start, frame.ts_end) AS ts_end,
+ min(mtf.ts_next_frame_start, frame.ts_end) - max(mtf.ts_prev_frame_end, frame.ts) AS dur,
+ gcs.gcs_ts,
+ gcs.gcs_ts_end,
+ gcs.gcs_dur
+FROM android_sysui_cuj_sf_actual_frame_timeline_slice frame
+JOIN android_sysui_cuj_surfaceflinger_main_thread_frames mtf ON frame.name = mtf.vsync
+JOIN android_sysui_cuj_gcs_to_mt_match gcs ON gcs.vsync = frame.name
+WHERE frame.jank_type != 'None';
diff --git a/src/trace_processor/metrics/sql/chrome/gesture_jank.sql b/src/trace_processor/metrics/sql/chrome/gesture_jank.sql
index cfbc96b..6e7ea1a 100644
--- a/src/trace_processor/metrics/sql/chrome/gesture_jank.sql
+++ b/src/trace_processor/metrics/sql/chrome/gesture_jank.sql
@@ -221,7 +221,7 @@
-- rate more than 1 FPS (and therefore VSync interval less than a second), this
-- ratio should increase with increments more than minimal value in numerator
-- (1ns) divided by maximum value in denominator, giving 1e-9.
--- Note: Logic is inside the isJankyFrame function found in jank_utilities.sql.
+-- Note: Logic is inside the IsJankyFrame function found in jank_utilities.sql.
DROP VIEW IF EXISTS {{prefix}}_jank_maybe_null_prev_and_next;
CREATE VIEW {{prefix}}_jank_maybe_null_prev_and_next AS
SELECT
@@ -237,6 +237,15 @@
-- This just uses prev_jank and next_jank to see if each "update" event is a
-- jank.
+--
+-- JankBudget is the time in ns that we need to reduce the current
+-- gesture (|id|) for this frame not to be considered janky (i.e., how much
+-- faster for IsJankyFrame() to have not returned true).
+--
+-- For JankBudget we use the frames_exact of current, previous and next to find
+-- the jank budget in exact frame count. We then multiply by avg_vsync_internal
+-- to get the jank budget time.
+-- Note: Logic is inside the JankBudget function found in jank_utilities.sql.
DROP VIEW IF EXISTS {{prefix}}_jank;
CREATE VIEW {{prefix}}_jank AS
SELECT
@@ -244,6 +253,8 @@
(next_jank IS NOT NULL AND next_jank) OR
(prev_jank IS NOT NULL AND prev_jank)
AS jank,
+ JankBudget(gesture_frames_exact, prev_gesture_frames_exact,
+ next_gesture_frames_exact) * avg_vsync_interval AS jank_budget,
*
FROM {{prefix}}_jank_maybe_null_prev_and_next
ORDER BY {{id_field}} ASC, ts ASC;
@@ -274,6 +285,9 @@
SELECT CAST(SUM(dur)/1e6 AS REAL) FROM {{prefix}}_jank WHERE jank
),
'num_{{prefix}}_update_count', COUNT(*),
- 'num_{{prefix}}_update_jank_count', SUM(jank)
+ 'num_{{prefix}}_update_jank_count', SUM(jank),
+ '{{prefix}}_jank_budget_ms', (
+ SELECT CAST(SUM(jank_budget) AS REAL) FROM {{prefix}}_jank WHERE jank
+ )
)
FROM {{prefix}}_jank;
diff --git a/src/trace_processor/metrics/sql/chrome/jank_utilities.sql b/src/trace_processor/metrics/sql/chrome/jank_utilities.sql
index 494b88c..44edb42 100644
--- a/src/trace_processor/metrics/sql/chrome/jank_utilities.sql
+++ b/src/trace_processor/metrics/sql/chrome/jank_utilities.sql
@@ -44,3 +44,40 @@
$cur_frame_exact > $neighbour_frame_exact + 0.5 + 1e-9
END'
);
+
+SELECT CREATE_FUNCTION(
+ -- Function : function takes the cur_frame_exact, prev_frame_exact and
+ -- next_frame_exact and returns the value of the jank budget of the current
+ -- frame.
+ --
+ -- JankBudget is the minimum amount of frames/time we need to reduce the frame
+ -- duration by for it to be no longer considered janky.
+ 'JankBudget(cur_frame_exact FLOAT, prev_frame_exact FLOAT, ' ||
+ ' next_frame_exact FLOAT)',
+ -- Returns the jank budget in percentage (i.e. 0.75) of vsync interval
+ -- percentage.
+ --
+ -- We determine the difference between the frame count of the current frame
+ -- and its consecutive frames by subtracting with the frame_exact values. We
+ -- null check for cases when the neighbor frame count can be null for the
+ -- first and last frames.
+ --
+ -- Since a frame is considered janky, if the difference in the frame count
+ -- with its adjacent frame is greater than 0.5 (half a vsync) which means we
+ -- need to reduce the frame count by a value less than 0.5 of maximum
+ -- difference in frame count for it to be no longer janky. We subtract 1e-9 as
+ -- we want to output minimum amount required.
+ 'FLOAT',
+ 'SELECT
+ COALESCE(
+ -- Could be null if next or previous is null.
+ MAX(
+ ($cur_frame_exact - $prev_frame_exact),
+ ($cur_frame_exact - $next_frame_exact)
+ ),
+ -- If one of them is null output the first non-null.
+ ($cur_frame_exact - $prev_frame_exact),
+ ($cur_frame_exact - $next_frame_exact)
+ -- Otherwise return null
+ ) - 0.5 - 1e-9'
+);
diff --git a/src/trace_processor/metrics/sql/experimental/chrome_dropped_frames.sql b/src/trace_processor/metrics/sql/experimental/chrome_dropped_frames.sql
index 595491d..b73516a 100644
--- a/src/trace_processor/metrics/sql/experimental/chrome_dropped_frames.sql
+++ b/src/trace_processor/metrics/sql/experimental/chrome_dropped_frames.sql
@@ -49,6 +49,8 @@
-- All tracks generated from chrome_dropped_frames_event are
-- placed under a track group named 'Dropped Frames', whose summary
-- track is the first track ('All Processes') in chrome_dropped_frames_event.
+-- Note that the 'All Processes' track is generated only when dropped frames
+-- come from more than one origin process.
DROP VIEW IF EXISTS chrome_dropped_frames_event;
CREATE VIEW chrome_dropped_frames_event AS
SELECT
@@ -59,6 +61,8 @@
'Dropped Frame' AS slice_name,
'Dropped Frames' AS group_name
FROM dropped_frames_with_process_info
+WHERE (SELECT COUNT(DISTINCT process_id)
+ FROM dropped_frames_with_process_info) > 1
GROUP BY ts
UNION ALL
SELECT
diff --git a/src/trace_processor/read_trace.cc b/src/trace_processor/read_trace.cc
index a8f1b52..c4cb67a 100644
--- a/src/trace_processor/read_trace.cc
+++ b/src/trace_processor/read_trace.cc
@@ -196,18 +196,13 @@
// Make sure that to reset the stream between the gzip streams.
auto bytes = packet.compressed_packets();
decompressor.Reset();
- decompressor.SetInput(bytes.data, bytes.size);
-
using ResultCode = util::GzipDecompressor::ResultCode;
- uint8_t out[4096];
- for (auto ret = ResultCode::kOk; ret != ResultCode::kEof;) {
- auto res = decompressor.Decompress(out, base::ArraySize(out));
- ret = res.ret;
- if (ret == ResultCode::kError || ret == ResultCode::kNoProgress ||
- ret == ResultCode::kNeedsMoreInput) {
- return util::ErrStatus("Failed while decompressing stream");
- }
- output->insert(output->end(), out, out + res.bytes_written);
+ ResultCode ret = decompressor.FeedAndExtract(
+ bytes.data, bytes.size, [&output](const uint8_t* buf, size_t buf_len) {
+ output->insert(output->end(), buf, buf + buf_len);
+ });
+ if (ret == ResultCode::kError || ret == ResultCode::kNeedsMoreInput) {
+ return util::ErrStatus("Failed while decompressing stream");
}
}
return util::OkStatus();
diff --git a/src/trace_processor/read_trace_integrationtest.cc b/src/trace_processor/read_trace_integrationtest.cc
index 390a7ef..439f1fa 100644
--- a/src/trace_processor/read_trace_integrationtest.cc
+++ b/src/trace_processor/read_trace_integrationtest.cc
@@ -103,7 +103,7 @@
std::vector<uint8_t> decompressed;
util::Status status = trace_processor::DecompressTrace(
raw_compressed_trace.data(), raw_compressed_trace.size(), &decompressed);
- ASSERT_TRUE(status.ok());
+ ASSERT_TRUE(status.ok()) << status.message();
protos::pbzero::Trace::Decoder decoder(decompressed.data(),
decompressed.size());
diff --git a/src/trace_processor/sqlite/BUILD.gn b/src/trace_processor/sqlite/BUILD.gn
index 7863cc5..e5be608 100644
--- a/src/trace_processor/sqlite/BUILD.gn
+++ b/src/trace_processor/sqlite/BUILD.gn
@@ -51,6 +51,7 @@
"../../../include/perfetto/trace_processor",
"../../../protos/perfetto/trace/ftrace:zero",
"../../base",
+ "../containers",
"../db",
"../importers/common",
"../storage",
diff --git a/src/trace_processor/sqlite/db_sqlite_table.cc b/src/trace_processor/sqlite/db_sqlite_table.cc
index bc2ee69..b6897e1 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table.cc
@@ -17,6 +17,7 @@
#include "src/trace_processor/sqlite/db_sqlite_table.h"
#include "perfetto/ext/base/string_writer.h"
+#include "src/trace_processor/containers/bit_vector.h"
#include "src/trace_processor/sqlite/query_cache.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"
#include "src/trace_processor/tp_metatrace.h"
@@ -83,6 +84,17 @@
return value;
}
+BitVector ColsUsedBitVector(uint64_t sqlite_cols_used, size_t col_count) {
+ return BitVector::Range(
+ 0, static_cast<uint32_t>(col_count), [sqlite_cols_used](uint32_t idx) {
+ // If the lowest bit of |sqlite_cols_used| is set, the first column is
+ // used. The second lowest bit corresponds to the second column etc. If
+ // the most significant bit of |sqlite_cols_used| is set, that means
+ // that any column after the first 63 columns could be used.
+ return sqlite_cols_used & (1ull << std::min(idx, 63u));
+ });
+}
+
} // namespace
DbSqliteTable::DbSqliteTable(sqlite3*, Context context)
@@ -111,7 +123,8 @@
// Figure out if the table needs explicit args (in the form of constraints
// on hidden columns) passed to it in order to make the query valid.
- util::Status status = generator->ValidateConstraints({});
+ util::Status status = generator->ValidateConstraints(
+ QueryConstraints(std::numeric_limits<uint64_t>::max()));
bool requires_args = !status.ok();
Context context{cache, std::move(schema), TableComputation::kDynamic, nullptr,
@@ -438,8 +451,10 @@
});
// If we have a dynamically created table, regenerate the table based on
// the new constraints.
- dynamic_table_ =
- db_sqlite_table_->generator_->ComputeTable(constraints_, orders_);
+ BitVector cols_used_bv = ColsUsedBitVector(
+ qc.cols_used(), db_sqlite_table_->schema_.columns.size());
+ dynamic_table_ = db_sqlite_table_->generator_->ComputeTable(
+ constraints_, orders_, cols_used_bv);
upstream_table_ = dynamic_table_.get();
if (!upstream_table_)
return SQLITE_CONSTRAINT;
diff --git a/src/trace_processor/sqlite/db_sqlite_table.h b/src/trace_processor/sqlite/db_sqlite_table.h
index 64231de..1e713b2 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.h
+++ b/src/trace_processor/sqlite/db_sqlite_table.h
@@ -17,6 +17,7 @@
#ifndef SRC_TRACE_PROCESSOR_SQLITE_DB_SQLITE_TABLE_H_
#define SRC_TRACE_PROCESSOR_SQLITE_DB_SQLITE_TABLE_H_
+#include "src/trace_processor/containers/bit_vector.h"
#include "src/trace_processor/db/table.h"
#include "src/trace_processor/sqlite/query_cache.h"
#include "src/trace_processor/sqlite/sqlite_table.h"
@@ -65,7 +66,8 @@
// vectors.
virtual std::unique_ptr<Table> ComputeTable(
const std::vector<Constraint>& cs,
- const std::vector<Order>& ob) = 0;
+ const std::vector<Order>& ob,
+ const BitVector& cols_used) = 0;
};
class Cursor : public SqliteTable::Cursor {
diff --git a/src/trace_processor/sqlite/query_constraints.cc b/src/trace_processor/sqlite/query_constraints.cc
index 942fe47..67f1812 100644
--- a/src/trace_processor/sqlite/query_constraints.cc
+++ b/src/trace_processor/sqlite/query_constraints.cc
@@ -26,10 +26,12 @@
namespace perfetto {
namespace trace_processor {
-QueryConstraints::QueryConstraints() = default;
+QueryConstraints::QueryConstraints(uint64_t cols_used)
+ : cols_used_(cols_used) {}
QueryConstraints::~QueryConstraints() = default;
QueryConstraints::QueryConstraints(QueryConstraints&&) noexcept = default;
-QueryConstraints& QueryConstraints::operator=(QueryConstraints&&) = default;
+QueryConstraints& QueryConstraints::operator=(QueryConstraints&&) noexcept =
+ default;
int QueryConstraints::FreeSqliteString(char* resource) {
sqlite3_free(resource);
@@ -38,7 +40,8 @@
bool QueryConstraints::operator==(const QueryConstraints& other) const {
if ((other.constraints().size() != constraints().size()) ||
- (other.order_by().size() != order_by().size())) {
+ (other.order_by().size() != order_by().size()) ||
+ other.cols_used() != cols_used()) {
return false;
}
@@ -79,6 +82,8 @@
QueryConstraints::SqliteString QueryConstraints::ToNewSqlite3String() const {
std::string str_result;
str_result.reserve(512);
+
+ // Add all the constraints.
str_result.append("C");
str_result.append(std::to_string(constraints_.size()));
str_result.append(",");
@@ -88,6 +93,9 @@
str_result.append(std::to_string(cs.op));
str_result.append(",");
}
+ str_result.back() = ';';
+
+ // Add all the clauses.
str_result.append("O");
str_result.append(std::to_string(order_by_.size()));
str_result.append(",");
@@ -97,44 +105,67 @@
str_result.append(std::to_string(ob.desc));
str_result.append(",");
}
+ str_result.back() = ';';
- // The last char is a "," so overwriting with the null terminator on purpose.
- SqliteString result(
- static_cast<char*>(sqlite3_malloc(static_cast<int>(str_result.size()))));
- base::StringCopy(result.get(), str_result.c_str(), str_result.size());
+ // Add the columns used.
+ str_result.append("U");
+ str_result.append(std::to_string(cols_used_));
+
+ SqliteString result(static_cast<char*>(
+ sqlite3_malloc(static_cast<int>(str_result.size() + 1))));
+ base::StringCopy(result.get(), str_result.c_str(), str_result.size() + 1);
return result;
}
QueryConstraints QueryConstraints::FromString(const char* idxStr) {
QueryConstraints qc;
- base::StringSplitter splitter(std::string(idxStr), ',');
+ base::StringSplitter outer_splitter(std::string(idxStr), ';');
- PERFETTO_CHECK(splitter.Next() && splitter.cur_token_size() > 1);
- // The '+ 1' skips the letter 'C' in the first token.
- long num_constraints = strtol(splitter.cur_token() + 1, nullptr, 10);
- for (int i = 0; i < num_constraints; ++i) {
- PERFETTO_CHECK(splitter.Next());
- int col = static_cast<int>(strtol(splitter.cur_token(), nullptr, 10));
- PERFETTO_CHECK(splitter.Next());
- unsigned char op =
- static_cast<unsigned char>(strtol(splitter.cur_token(), nullptr, 10));
- qc.AddConstraint(col, op, 0);
+ // Handle the CONSTRAINT section of the string.
+ PERFETTO_CHECK(outer_splitter.Next() && outer_splitter.cur_token_size() > 1);
+ {
+ base::StringSplitter splitter(&outer_splitter, ',');
+ PERFETTO_CHECK(splitter.Next() && splitter.cur_token_size() > 1);
+
+ // The '[1]' skips the letter 'C' in the first token.
+ int64_t num_constraints = *base::CStringToInt64(&splitter.cur_token()[1]);
+ for (int i = 0; i < num_constraints; ++i) {
+ PERFETTO_CHECK(splitter.Next());
+ int col = static_cast<int>(*base::CStringToInt32(splitter.cur_token()));
+ PERFETTO_CHECK(splitter.Next());
+ unsigned char op = static_cast<unsigned char>(
+ *base::CStringToUInt32(splitter.cur_token()));
+ qc.AddConstraint(col, op, 0);
+ }
}
- PERFETTO_CHECK(splitter.Next() && splitter.cur_token_size() > 1);
- // The '+ 1' skips the letter 'O' in the current token.
- long num_order_by = strtol(splitter.cur_token() + 1, nullptr, 10);
- for (int i = 0; i < num_order_by; ++i) {
- PERFETTO_CHECK(splitter.Next());
- int col = static_cast<int>(strtol(splitter.cur_token(), nullptr, 10));
- PERFETTO_CHECK(splitter.Next());
- unsigned char desc =
- static_cast<unsigned char>(strtol(splitter.cur_token(), nullptr, 10));
- qc.AddOrderBy(col, desc);
+ // Handle the ORDER BY section of the string.
+ PERFETTO_CHECK(outer_splitter.Next() && outer_splitter.cur_token_size() > 1);
+ {
+ base::StringSplitter splitter(&outer_splitter, ',');
+ PERFETTO_CHECK(splitter.Next() && splitter.cur_token_size() > 1);
+
+ // The '[1]' skips the letter 'O' in the current token.
+ int64_t num_order_by = *base::CStringToInt64(&splitter.cur_token()[1]);
+ for (int i = 0; i < num_order_by; ++i) {
+ PERFETTO_CHECK(splitter.Next());
+ int col = static_cast<int>(*base::CStringToInt32(splitter.cur_token()));
+ PERFETTO_CHECK(splitter.Next());
+ unsigned char desc = static_cast<unsigned char>(
+ *base::CStringToUInt32(splitter.cur_token()));
+ qc.AddOrderBy(col, desc);
+ }
}
- PERFETTO_DCHECK(!splitter.Next());
+ // Handle the COLS USED section of the string.
+ PERFETTO_CHECK(outer_splitter.Next() && outer_splitter.cur_token_size() > 1);
+ {
+ // The '[1]' skips the letter 'U' in the current token.
+ qc.cols_used_ = *base::CStringToUInt64(&outer_splitter.cur_token()[1]);
+ }
+
+ PERFETTO_DCHECK(!outer_splitter.Next());
return qc;
}
diff --git a/src/trace_processor/sqlite/query_constraints.h b/src/trace_processor/sqlite/query_constraints.h
index 54c1b45..10ee3e6 100644
--- a/src/trace_processor/sqlite/query_constraints.h
+++ b/src/trace_processor/sqlite/query_constraints.h
@@ -19,6 +19,7 @@
#include <sqlite3.h>
+#include <limits>
#include <vector>
#include "perfetto/ext/base/scoped_file.h"
@@ -57,10 +58,11 @@
using SqliteString = base::ScopedResource<char*, FreeSqliteString, nullptr>;
- QueryConstraints();
+ explicit QueryConstraints(
+ uint64_t cols_used = std::numeric_limits<uint64_t>::max());
~QueryConstraints();
QueryConstraints(QueryConstraints&&) noexcept;
- QueryConstraints& operator=(QueryConstraints&&);
+ QueryConstraints& operator=(QueryConstraints&&) noexcept;
// Two QueryConstraints with the same constraint and orderby vectors
// are equal.
@@ -89,12 +91,20 @@
std::vector<Constraint>* mutable_constraints() { return &constraints_; }
+ uint64_t cols_used() const { return cols_used_; }
+
private:
QueryConstraints(const QueryConstraints&) = delete;
QueryConstraints& operator=(const QueryConstraints&) = delete;
std::vector<OrderBy> order_by_;
std::vector<Constraint> constraints_;
+
+ // Stores information about which column is used by this query.
+ // If the lowest bit of is set, the first column is used. The second lowest
+ // bit corresponds to the second column etc. If the most significant bit is
+ // set, that means that any column after the first 63 columns could be used.
+ uint64_t cols_used_ = std::numeric_limits<uint64_t>::max();
};
} // namespace trace_processor
diff --git a/src/trace_processor/sqlite/query_constraints_unittest.cc b/src/trace_processor/sqlite/query_constraints_unittest.cc
index 402bc70..d4be555 100644
--- a/src/trace_processor/sqlite/query_constraints_unittest.cc
+++ b/src/trace_processor/sqlite/query_constraints_unittest.cc
@@ -35,11 +35,11 @@
};
TEST_F(QueryConstraintsTest, ConvertToAndFromSqlString) {
- QueryConstraints qc;
+ QueryConstraints qc(0);
qc.AddConstraint(12, 0, 0);
QueryConstraints::SqliteString only_constraint = qc.ToNewSqlite3String();
- ASSERT_TRUE(strcmp(only_constraint.get(), "C1,12,0,O0") == 0);
+ ASSERT_TRUE(strcmp(only_constraint.get(), "C1,12,0;O0;U0") == 0);
QueryConstraints qc_constraint =
QueryConstraints::FromString(only_constraint.get());
@@ -49,17 +49,17 @@
qc.AddOrderBy(21, true);
QueryConstraints::SqliteString result = qc.ToNewSqlite3String();
- ASSERT_TRUE(strcmp(result.get(), "C1,12,0,O2,1,0,21,1") == 0);
+ ASSERT_TRUE(strcmp(result.get(), "C1,12,0;O2,1,0,21,1;U0") == 0);
QueryConstraints qc_result = QueryConstraints::FromString(result.get());
ASSERT_EQ(qc, qc_result);
}
TEST_F(QueryConstraintsTest, CheckEmptyConstraints) {
- QueryConstraints qc;
+ QueryConstraints qc(0);
QueryConstraints::SqliteString string_result = qc.ToNewSqlite3String();
- ASSERT_TRUE(strcmp(string_result.get(), "C0,O0") == 0);
+ ASSERT_TRUE(strcmp(string_result.get(), "C0;O0;U0") == 0);
QueryConstraints qc_result =
QueryConstraints::FromString(string_result.get());
@@ -68,17 +68,35 @@
}
TEST_F(QueryConstraintsTest, OnlyOrderBy) {
- QueryConstraints qc;
+ QueryConstraints qc(0);
qc.AddOrderBy(3, true);
QueryConstraints::SqliteString string_result = qc.ToNewSqlite3String();
- ASSERT_TRUE(strcmp(string_result.get(), "C0,O1,3,1") == 0);
+ ASSERT_TRUE(strcmp(string_result.get(), "C0;O1,3,1;U0") == 0);
QueryConstraints qc_result =
QueryConstraints::FromString(string_result.get());
ASSERT_EQ(qc, qc_result);
}
+TEST_F(QueryConstraintsTest, ColsUsed) {
+ ASSERT_EQ(QueryConstraints(0), QueryConstraints::FromString("C0;O0;U0"));
+
+ ASSERT_EQ(QueryConstraints(4), QueryConstraints::FromString("C0;O0;U4"));
+
+ ASSERT_EQ(QueryConstraints(1ull << 63),
+ QueryConstraints::FromString("C0;O0;U9223372036854775808"));
+
+ ASSERT_EQ(QueryConstraints(9223372036854775807ull),
+ QueryConstraints::FromString("C0;O0;U9223372036854775807"));
+
+ ASSERT_EQ(QueryConstraints(),
+ QueryConstraints::FromString("C0;O0;U18446744073709551615"));
+
+ auto str = QueryConstraints(0xFFFFFFFFFFFFFFFF).ToNewSqlite3String();
+ ASSERT_STREQ(str.get(), "C0;O0;U18446744073709551615");
+}
+
} // namespace
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/sqlite/sqlite_table.cc b/src/trace_processor/sqlite/sqlite_table.cc
index d155c98..6fad97b 100644
--- a/src/trace_processor/sqlite/sqlite_table.cc
+++ b/src/trace_processor/sqlite/sqlite_table.cc
@@ -61,7 +61,7 @@
}
int SqliteTable::BestIndexInternal(sqlite3_index_info* idx) {
- QueryConstraints qc;
+ QueryConstraints qc(idx->colUsed);
for (int i = 0; i < idx->nConstraint; i++) {
const auto& cs = idx->aConstraint[i];
diff --git a/src/trace_processor/sqlite/sqlite_table.h b/src/trace_processor/sqlite/sqlite_table.h
index cfb7d43..0d42ae4 100644
--- a/src/trace_processor/sqlite/sqlite_table.h
+++ b/src/trace_processor/sqlite/sqlite_table.h
@@ -90,7 +90,7 @@
kSame = 1,
};
- Cursor(SqliteTable* table);
+ explicit Cursor(SqliteTable* table);
virtual ~Cursor();
// Methods to be implemented by derived table classes.
diff --git a/src/trace_processor/storage/stats.h b/src/trace_processor/storage/stats.h
index 9fb73f8b..4064c80 100644
--- a/src/trace_processor/storage/stats.h
+++ b/src/trace_processor/storage/stats.h
@@ -114,6 +114,11 @@
F(traced_chunks_discarded, kSingle, kInfo, kTrace, ""), \
F(traced_data_sources_registered, kSingle, kInfo, kTrace, ""), \
F(traced_data_sources_seen, kSingle, kInfo, kTrace, ""), \
+ F(traced_final_flush_failed, kSingle, kDataLoss, kTrace, ""), \
+ F(traced_final_flush_succeeded, kSingle, kInfo, kTrace, ""), \
+ F(traced_flushes_failed, kSingle, kDataLoss, kTrace, ""), \
+ F(traced_flushes_requested, kSingle, kInfo, kTrace, ""), \
+ F(traced_flushes_succeeded, kSingle, kInfo, kTrace, ""), \
F(traced_patches_discarded, kSingle, kInfo, kTrace, ""), \
F(traced_producers_connected, kSingle, kInfo, kTrace, ""), \
F(traced_producers_seen, kSingle, kInfo, kTrace, ""), \
diff --git a/src/trace_processor/util/BUILD.gn b/src/trace_processor/util/BUILD.gn
index 78ee878..82b2c7e 100644
--- a/src/trace_processor/util/BUILD.gn
+++ b/src/trace_processor/util/BUILD.gn
@@ -117,9 +117,13 @@
"proto_to_args_parser_unittest.cc",
"protozero_to_text_unittests.cc",
]
+ if (enable_perfetto_zlib) {
+ sources += [ "gzip_utils_unittest.cc" ]
+ }
testonly = true
deps = [
":descriptors",
+ ":gzip",
":proto_to_args_parser",
":protozero_to_text",
"..:gen_cc_test_messages_descriptor",
diff --git a/src/trace_processor/util/gzip_utils.cc b/src/trace_processor/util/gzip_utils.cc
index b16e56b..2279b87 100644
--- a/src/trace_processor/util/gzip_utils.cc
+++ b/src/trace_processor/util/gzip_utils.cc
@@ -38,46 +38,33 @@
#endif
}
-#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB) // Real Implementation
+
GzipDecompressor::GzipDecompressor() : z_stream_(new z_stream()) {
z_stream_->zalloc = nullptr;
z_stream_->zfree = nullptr;
z_stream_->opaque = nullptr;
- inflateInit2(z_stream_.get(), 32 + 15);
+ inflateInit2(z_stream_.get(), 32 + MAX_WBITS);
}
-#else
-GzipDecompressor::GzipDecompressor() = default;
-#endif
GzipDecompressor::~GzipDecompressor() {
-#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
- // Ensure the call to inflateEnd to prevent leaks of internal state.
inflateEnd(z_stream_.get());
-#endif
}
void GzipDecompressor::Reset() {
-#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
inflateReset(z_stream_.get());
-#endif
}
-void GzipDecompressor::SetInput(const uint8_t* data, size_t size) {
-#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+void GzipDecompressor::Feed(const uint8_t* data, size_t size) {
// This const_cast is not harmfull as zlib will not modify the data in this
// pointer. This is only necessary because of the build flags we use to be
// compatible with other embedders.
z_stream_->next_in = const_cast<uint8_t*>(data);
z_stream_->avail_in = static_cast<uInt>(size);
-#else
- base::ignore_result(data);
- base::ignore_result(size);
-#endif
}
-GzipDecompressor::Result GzipDecompressor::Decompress(uint8_t* out,
- size_t out_size) {
-#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+GzipDecompressor::Result GzipDecompressor::ExtractOutput(uint8_t* out,
+ size_t out_size) {
if (z_stream_->avail_in == 0)
return Result{ResultCode::kNeedsMoreInput, 0};
@@ -95,15 +82,34 @@
case Z_STREAM_END:
return Result{ResultCode::kEof, out_size - z_stream_->avail_out};
case Z_BUF_ERROR:
- return Result{ResultCode::kNoProgress, 0};
+ return Result{ResultCode::kNeedsMoreInput, 0};
default:
return Result{ResultCode::kOk, out_size - z_stream_->avail_out};
}
-#else
- base::ignore_result(out);
- base::ignore_result(out_size);
+}
+
+#else // Dummy Implementation
+
+GzipDecompressor::GzipDecompressor() = default;
+GzipDecompressor::~GzipDecompressor() = default;
+void GzipDecompressor::Reset() {}
+void GzipDecompressor::Feed(const uint8_t*, size_t) {}
+GzipDecompressor::Result GzipDecompressor::ExtractOutput(uint8_t*, size_t) {
return Result{ResultCode::kError, 0};
-#endif
+}
+
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
+// static
+std::vector<uint8_t> GzipDecompressor::DecompressFully(const uint8_t* data,
+ size_t len) {
+ std::vector<uint8_t> whole_data;
+ GzipDecompressor decompressor;
+ auto decom_output_consumer = [&](const uint8_t* buf, size_t buf_len) {
+ whole_data.insert(whole_data.end(), buf, buf + buf_len);
+ };
+ decompressor.FeedAndExtract(data, len, decom_output_consumer);
+ return whole_data;
}
} // namespace util
diff --git a/src/trace_processor/util/gzip_utils.h b/src/trace_processor/util/gzip_utils.h
index 189cfbd..711541f 100644
--- a/src/trace_processor/util/gzip_utils.h
+++ b/src/trace_processor/util/gzip_utils.h
@@ -18,6 +18,7 @@
#define SRC_TRACE_PROCESSOR_UTIL_GZIP_UTILS_H_
#include <memory>
+#include <vector>
struct z_stream_s;
@@ -29,13 +30,32 @@
// build flags.
bool IsGzipSupported();
+// Usage: To decompress in a streaming way, there are two ways of using it:
+// 1. [Commonly used] - Feed the sequence of mem-blocks in 'FeedAndExtract' one
+// by one. Output will be produced in given output_consumer, which is simply
+// a callback. On each 'FeedAndExtract', output_consumer could get invoked
+// any number of times, based on how much partial output is available.
+
+// 2. [Uncommon ; Discouraged] - Feed the sequence of mem-blocks one by one, by
+// calling 'Feed'. For each time 'Feed' is called, client should call
+// 'ExtractOutput' again and again to extrat the partially available output,
+// until there in no more output to extract. Also see 'ResultCode' enum.
class GzipDecompressor {
public:
enum class ResultCode {
+ // 'kOk' means nothing bad happened so far, but continue doing what you
+ // were doing.
kOk,
+ // While calling 'ExtractOutput' repeatedly, if we get 'kEof', it means
+ // we have extracted all the partially available data and we are also
+ // done, i.e. there is no need to feed more input.
kEof,
+ // Some error. Possibly invalid compressed stream or corrupted data.
kError,
- kNoProgress,
+ // While calling 'ExtractOutput' repeatedly, if we get 'kNeedsMoreInput',
+ // it means we have extracted all the partially available data, but we are
+ // not done yet. We need to call the 'Feed' to feed the next input
+ // mem-block and go through the ExtractOutput loop again.
kNeedsMoreInput,
};
struct Result {
@@ -43,22 +63,52 @@
ResultCode ret;
// The amount of bytes written to output.
- // Only valid if |ResultCode::kOk|.
+ // Valid in all cases except |ResultCode::kError|.
size_t bytes_written;
};
GzipDecompressor();
~GzipDecompressor();
+ GzipDecompressor(const GzipDecompressor&) = delete;
+ GzipDecompressor& operator=(const GzipDecompressor&) = delete;
- // Sets the input pointer and size of the gzip stream to inflate.
- void SetInput(const uint8_t* data, size_t size);
+ // Feed the next mem-block.
+ void Feed(const uint8_t* data, size_t size);
- // Decompresses the input previously provided in |SetInput|.
- Result Decompress(uint8_t* out, size_t out_size);
+ // Feed the next mem-block and extract output in the callback consumer.
+ // callback can get invoked multiple times if there are multiple
+ // mem-blocks to output.
+ template <typename Callback = void(const uint8_t* ptr, size_t size)>
+ ResultCode FeedAndExtract(const uint8_t* data,
+ size_t size,
+ const Callback& output_consumer) {
+ Feed(data, size);
+ uint8_t buffer[4096];
+ Result result;
+ do {
+ result = ExtractOutput(buffer, sizeof(buffer));
+ if (result.ret != ResultCode::kError && result.bytes_written > 0) {
+ output_consumer(buffer, result.bytes_written);
+ }
+ } while (result.ret == ResultCode::kOk);
+ return result.ret;
+ }
+
+ // Extract the newly available partial output. On each 'Feed', this method
+ // should be called repeatedly until there is no more data to output
+ // i.e. (either 'kEof' or 'kNeedsMoreInput').
+ Result ExtractOutput(uint8_t* out, size_t out_capacity);
// Sets the state of the decompressor to reuse with other gzip streams.
+ // This is almost like constructing a new 'GzipDecompressor' object
+ // but without paying the cost of internal memory allocation.
void Reset();
+ // Decompress the entire mem-block and return decompressed mem-block.
+ // This is used for decompressing small strings or small files
+ // which doesn't require streaming decompression.
+ static std::vector<uint8_t> DecompressFully(const uint8_t* data, size_t len);
+
private:
std::unique_ptr<z_stream_s> z_stream_;
};
diff --git a/src/trace_processor/util/gzip_utils_unittest.cc b/src/trace_processor/util/gzip_utils_unittest.cc
new file mode 100644
index 0000000..a58332e
--- /dev/null
+++ b/src/trace_processor/util/gzip_utils_unittest.cc
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test/gtest_and_gmock.h"
+
+#include "src/trace_processor/util/gzip_utils.h"
+
+#include <zlib.h>
+#include <fstream>
+#include <iostream>
+#include "perfetto/base/logging.h"
+
+using std::string;
+
+namespace perfetto {
+namespace trace_processor {
+namespace util {
+
+static std::string TrivialGzipCompress(const std::string& input) {
+ constexpr auto buffer_len = 10000;
+ std::unique_ptr<char[]> output_ptr(new char[buffer_len]);
+ char* output = output_ptr.get();
+ z_stream defstream;
+ defstream.zalloc = Z_NULL;
+ defstream.zfree = Z_NULL;
+ defstream.opaque = Z_NULL;
+ defstream.avail_in = uint32_t(input.size());
+ defstream.next_in =
+ const_cast<Bytef*>(reinterpret_cast<const Bytef*>(input.data()));
+ defstream.avail_out = buffer_len;
+ defstream.next_out = reinterpret_cast<Bytef*>(output);
+ deflateInit(&defstream, Z_BEST_COMPRESSION); // GZip decompress
+ deflate(&defstream, Z_FINISH);
+ deflateEnd(&defstream);
+ PERFETTO_CHECK(defstream.avail_out > 0);
+ return std::string(output, buffer_len - defstream.avail_out);
+}
+
+// Trivially decompress using ZlibOnlineDecompress.
+// It's called 'trivial' because we are feeding the entire input in one shot.
+static std::string TrivialDecompress(const std::string& input) {
+ string output;
+ GzipDecompressor decompressor;
+ decompressor.FeedAndExtract(
+ reinterpret_cast<const uint8_t*>(input.data()), uint32_t(input.size()),
+ [&](const uint8_t* data, size_t len) {
+ output.append(reinterpret_cast<const char*>(data), len);
+ });
+ return output;
+}
+
+// Decompress a large GZip file using a in-memory buffer of 4KB, and write the
+// decompressed output in another file.
+static void DecompressGzipFileInFileOut(const std::string& input_file,
+ const std::string& output_file) {
+ std::ofstream output(output_file.c_str(), std::ios::out | std::ios::binary);
+ std::ifstream input(input_file.c_str(), std::ios::binary);
+ GzipDecompressor decompressor;
+ constexpr uint32_t buffer_sizeof = 4096;
+ char buffer[buffer_sizeof];
+ while (!input.eof()) {
+ input.read(buffer, buffer_sizeof);
+ decompressor.FeedAndExtract(
+ reinterpret_cast<const uint8_t*>(buffer), size_t(input.gcount()),
+ [&](const uint8_t* data, size_t len) {
+ output.write(reinterpret_cast<const char*>(data),
+ std::streamsize(len));
+ });
+ }
+ EXPECT_FALSE(input.bad());
+}
+
+TEST(GzipDecompressor, Basic) {
+ string input = "Abc..Def..Ghi";
+ string compressed = TrivialGzipCompress(input);
+ EXPECT_EQ(21u, compressed.size());
+ string decompressed = TrivialDecompress(compressed);
+ EXPECT_EQ(input, decompressed);
+}
+
+TEST(GzipDecompressor, Streaming) {
+ string input = "Abc..Def..Ghi";
+ string compressed = TrivialGzipCompress(input);
+ string decompressed;
+ auto consumer = [&](const uint8_t* data, size_t len) {
+ decompressed.append(reinterpret_cast<const char*>(data), len);
+ };
+ GzipDecompressor decompressor;
+ auto compressed_u8 = reinterpret_cast<const uint8_t*>(compressed.data());
+ ASSERT_GT(compressed.size(), 17u);
+ decompressor.FeedAndExtract(compressed_u8, 7, consumer);
+ decompressor.FeedAndExtract(compressed_u8 + 7, 10, consumer);
+ decompressor.FeedAndExtract(compressed_u8 + 17, compressed.size() - 17,
+ consumer);
+
+ EXPECT_EQ(input, decompressed);
+}
+
+static std::string ReadFile(const std::string& file_name) {
+ std::ifstream fd(file_name, std::ios::binary);
+ std::stringstream buffer;
+ buffer << fd.rdbuf();
+ fd.close();
+ return buffer.str();
+}
+
+static void WriteFile(const std::string& file_name,
+ const std::string& content) {
+ std::ofstream fd(file_name, std::ios::out | std::ios::binary);
+ fd.write(content.data(), std::streamsize(content.size()));
+ fd.close();
+}
+
+TEST(GzipDecompressor, DISABLED_FileInFileOut) {
+ auto big_string = []() {
+ std::string output;
+ for (int i = 0; i < 1000; i++) {
+ output += "Abc..Def..Ghi."; // len = 14
+ }
+ return output;
+ }();
+ constexpr auto gz_file = "/tmp/abc.gz";
+ constexpr auto txt_file = "/tmp/abc.txt";
+ EXPECT_EQ(size_t(1000 * 14), big_string.size());
+ WriteFile(gz_file, TrivialGzipCompress(big_string));
+ DecompressGzipFileInFileOut(gz_file, txt_file);
+ EXPECT_TRUE(ReadFile(txt_file) == big_string);
+}
+
+} // namespace util
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/traced/probes/ftrace/atrace_wrapper.cc b/src/traced/probes/ftrace/atrace_wrapper.cc
index aa28916..22523f1 100644
--- a/src/traced/probes/ftrace/atrace_wrapper.cc
+++ b/src/traced/probes/ftrace/atrace_wrapper.cc
@@ -164,7 +164,6 @@
bool ok = WIFEXITED(status) && WEXITSTATUS(status) == 0;
if (!ok) {
- // TODO(lalitm): use the stderr result from atrace.
PERFETTO_ELOG("%s", error.c_str());
}
return ok;
diff --git a/src/traced/probes/ftrace/event_info.cc b/src/traced/probes/ftrace/event_info.cc
index 0b3d5b3..baf5468 100644
--- a/src/traced/probes/ftrace/event_info.cc
+++ b/src/traced/probes/ftrace/event_info.cc
@@ -1110,6 +1110,31 @@
kUnsetFtraceId,
352,
kUnsetSize},
+ {"cros_ec_sensorhub_data",
+ "cros_ec",
+ {
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "current_time", 1, ProtoSchemaType::kInt64,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "current_timestamp", 2, ProtoSchemaType::kInt64,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "delta", 3, ProtoSchemaType::kInt64,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "ec_fifo_timestamp", 4, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "ec_sensor_num", 5, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "fifo_timestamp", 6, ProtoSchemaType::kInt64,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ },
+ kUnsetFtraceId,
+ 364,
+ kUnsetSize},
{"dma_heap_stat",
"dmabuf_heap",
{
@@ -5745,6 +5770,80 @@
kUnsetFtraceId,
361,
kUnsetSize},
+ {"napi_gro_receive_entry",
+ "net",
+ {
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "data_len", 1, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "gso_size", 2, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "gso_type", 3, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "hash", 4, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "ip_summed", 5, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "l4_hash", 6, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "len", 7, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "mac_header", 8, ProtoSchemaType::kInt32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "mac_header_valid", 9, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "name", 10, ProtoSchemaType::kString,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "napi_id", 11, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "nr_frags", 12, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "protocol", 13, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "queue_mapping", 14, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "skbaddr", 15, ProtoSchemaType::kUint64,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "truesize", 16, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "vlan_proto", 17, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "vlan_tagged", 18, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "vlan_tci", 19, ProtoSchemaType::kUint32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ },
+ kUnsetFtraceId,
+ 365,
+ kUnsetSize},
+ {"napi_gro_receive_exit",
+ "net",
+ {
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "ret", 1, ProtoSchemaType::kInt32,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ },
+ kUnsetFtraceId,
+ 366,
+ kUnsetSize},
{"oom_score_adj_update",
"oom",
{
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/cros_ec/cros_ec_sensorhub_data/format b/src/traced/probes/ftrace/test/data/synthetic/events/cros_ec/cros_ec_sensorhub_data/format
new file mode 100644
index 0000000..d578512
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/synthetic/events/cros_ec/cros_ec_sensorhub_data/format
@@ -0,0 +1,17 @@
+name: cros_ec_sensorhub_data
+ID: 1195
+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:u32 ec_sensor_num; offset:8; size:4; signed:0;
+ field:u32 ec_fifo_timestamp; offset:12; size:4; signed:0;
+ field:s64 fifo_timestamp; offset:16; size:8; signed:1;
+ field:s64 current_timestamp; offset:24; size:8; signed:1;
+ field:s64 current_time; offset:32; size:8; signed:1;
+ field:s64 delta; offset:40; size:8; signed:1;
+
+print fmt: "ec_num: %4u, ec_fifo_ts: %9u, fifo_ts: %12lld, curr_ts: %12lld, curr_time: %12lld, delta %12lld", REC->ec_sensor_num, REC->ec_fifo_timestamp, REC->fifo_timestamp, REC->current_timestamp, REC->current_time, REC->delta
+
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/net/napi_gro_receive_entry/format b/src/traced/probes/ftrace/test/data/synthetic/events/net/napi_gro_receive_entry/format
new file mode 100644
index 0000000..1d8d557
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/synthetic/events/net/napi_gro_receive_entry/format
@@ -0,0 +1,29 @@
+name: napi_gro_receive_entry
+ID: 928
+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:__data_loc char[] name; offset:8; size:4; signed:0;
+ field:unsigned int napi_id; offset:12; size:4; signed:0;
+ field:u16 queue_mapping; offset:16; size:2; signed:0;
+ field:const void * skbaddr; offset:24; size:8; signed:0;
+ field:bool vlan_tagged; offset:32; size:1; signed:0;
+ field:u16 vlan_proto; offset:34; size:2; signed:0;
+ field:u16 vlan_tci; offset:36; size:2; signed:0;
+ field:u16 protocol; offset:38; size:2; signed:0;
+ field:u8 ip_summed; offset:40; size:1; signed:0;
+ field:u32 hash; offset:44; size:4; signed:0;
+ field:bool l4_hash; offset:48; size:1; signed:0;
+ field:unsigned int len; offset:52; size:4; signed:0;
+ field:unsigned int data_len; offset:56; size:4; signed:0;
+ field:unsigned int truesize; offset:60; size:4; signed:0;
+ field:bool mac_header_valid; offset:64; size:1; signed:0;
+ field:int mac_header; offset:68; size:4; signed:1;
+ field:unsigned char nr_frags; offset:72; size:1; signed:0;
+ field:u16 gso_size; offset:74; size:2; signed:0;
+ field:u16 gso_type; offset:76; size:2; signed:0;
+
+print fmt: "dev=%s napi_id=%#x queue_mapping=%u skbaddr=%p vlan_tagged=%d vlan_proto=0x%04x vlan_tci=0x%04x protocol=0x%04x ip_summed=%d hash=0x%08x l4_hash=%d len=%u data_len=%u truesize=%u mac_header_valid=%d mac_header=%d nr_frags=%d gso_size=%d gso_type=%#x", __get_str(name), REC->napi_id, REC->queue_mapping, REC->skbaddr, REC->vlan_tagged, REC->vlan_proto, REC->vlan_tci, REC->protocol, REC->ip_summed, REC->hash, REC->l4_hash, REC->len, REC->data_len, REC->truesize, REC->mac_header_valid, REC->mac_header, REC->nr_frags, REC->gso_size, REC->gso_type
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/net/napi_gro_receive_exit/format b/src/traced/probes/ftrace/test/data/synthetic/events/net/napi_gro_receive_exit/format
new file mode 100644
index 0000000..2eb347d
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/synthetic/events/net/napi_gro_receive_exit/format
@@ -0,0 +1,11 @@
+name: napi_gro_receive_exit
+ID: 929
+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:int ret; offset:8; size:4; signed:1;
+
+print fmt: "ret=%d", REC->ret
diff --git a/src/traced/probes/ps/process_stats_data_source.cc b/src/traced/probes/ps/process_stats_data_source.cc
index 22e0cdb..76e8ccc 100644
--- a/src/traced/probes/ps/process_stats_data_source.cc
+++ b/src/traced/probes/ps/process_stats_data_source.cc
@@ -227,10 +227,16 @@
if (proc_status.empty())
return;
int tgid = ToInt(ReadProcStatusEntry(proc_status, "Tgid:"));
- if (tgid <= 0)
+ int tid = ToInt(ReadProcStatusEntry(proc_status, "Pid:"));
+ if (tgid <= 0 || tid <= 0)
return;
- if (!seen_pids_.count(tgid))
- WriteProcess(tgid, proc_status);
+
+ if (!seen_pids_.count(tgid)) {
+ // We need to read the status file if |pid| is non-main thread.
+ const std::string& proc_status_tgid =
+ (tgid == tid ? proc_status : ReadProcPidFile(tgid, "status"));
+ WriteProcess(tgid, proc_status_tgid);
+ }
if (pid != tgid) {
PERFETTO_DCHECK(!seen_pids_.count(pid));
std::string thread_name;
@@ -273,6 +279,8 @@
void ProcessStatsDataSource::WriteProcess(int32_t pid,
const std::string& proc_status) {
PERFETTO_DCHECK(ToInt(ReadProcStatusEntry(proc_status, "Tgid:")) == pid);
+ // Assert that |proc_status| is not for a non-main thread.
+ PERFETTO_DCHECK(ToInt(ReadProcStatusEntry(proc_status, "Pid:")) == pid);
auto* proc = GetOrCreatePsTree()->add_processes();
proc->set_pid(pid);
proc->set_ppid(ToInt(ReadProcStatusEntry(proc_status, "PPid:")));
diff --git a/src/traced/probes/ps/process_stats_data_source_unittest.cc b/src/traced/probes/ps/process_stats_data_source_unittest.cc
index 62ec0dc..0fa7d54 100644
--- a/src/traced/probes/ps/process_stats_data_source_unittest.cc
+++ b/src/traced/probes/ps/process_stats_data_source_unittest.cc
@@ -665,7 +665,11 @@
.WillOnce(Return(
"Name: foo\nTgid:\t42\nPid: 43\nPPid: 17\nNSpid:\t43\t3\n"));
- data_source->OnPids({42, 43});
+ // It's possible that OnPids() is called with a non-main thread is seen before
+ // the main thread for a process. When this happens, the data source
+ // will WriteProcess(42) first and then WriteThread(43).
+ data_source->OnPids({43});
+ data_source->OnPids({42}); // This will be a no-op.
auto trace = writer_raw_->GetAllTracePackets();
ASSERT_EQ(trace.size(), 1u);
diff --git a/src/traced/service/builtin_producer.cc b/src/traced/service/builtin_producer.cc
index 20d9849..a2007be 100644
--- a/src/traced/service/builtin_producer.cc
+++ b/src/traced/service/builtin_producer.cc
@@ -67,8 +67,16 @@
}
void BuiltinProducer::ConnectInProcess(TracingService* svc) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ // TODO(primiano): ConnectProducer should take a base::PlatformProcessId not
+ // pid_t, as they are different on Windows. But that is a larger refactoring
+ // and not worth given this is the only use case where it clashes.
+ const pid_t cur_proc_id = 0;
+#else
+ const pid_t cur_proc_id = base::GetProcessId();
+#endif
endpoint_ = svc->ConnectProducer(
- this, base::GetCurrentUserId(), base::GetProcessId(), "traced",
+ this, base::GetCurrentUserId(), cur_proc_id, "traced",
/*shared_memory_size_hint_bytes=*/16 * 1024, /*in_process=*/true,
TracingService::ProducerSMBScrapingMode::kDisabled,
/*shared_memory_page_size_hint_bytes=*/4096);
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index 696732e..18f6e69 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -1656,6 +1656,7 @@
return;
}
+ ++tracing_session->flushes_requested;
FlushRequestID flush_request_id = ++last_flush_request_id_;
PendingFlush& pending_flush =
tracing_session->pending_flushes
@@ -1734,7 +1735,6 @@
// If there were no producers to flush, consider it a success.
bool success = it->second.producers.empty();
-
auto callback = std::move(it->second.callback);
tracing_session->pending_flushes.erase(it);
CompleteFlush(tsid, std::move(callback), success);
@@ -1758,6 +1758,9 @@
tracing_session,
protos::pbzero::TracingServiceEvent::kAllDataSourcesFlushedFieldNumber,
true /* snapshot_clocks */);
+
+ tracing_session->flushes_succeeded += success ? 1 : 0;
+ tracing_session->flushes_failed += success ? 0 : 1;
callback(success);
}
@@ -1889,6 +1892,8 @@
if (!weak_this)
return;
TracingSession* session = weak_this->GetTracingSession(tsid);
+ session->final_flush_outcome = success ? TraceStats::FINAL_FLUSH_SUCCEEDED
+ : TraceStats::FINAL_FLUSH_FAILED;
if (session->consumer_maybe_null) {
// If the consumer is still attached, just disable the session but give it
// a chance to read the contents.
@@ -2068,12 +2073,6 @@
IsWaitingForTrigger(tracing_session))
return false;
- // Speculative fix for the memory watchdog crash in b/195145848. This function
- // uses the heap extensively and might need a M_PURGE. window.gc() is back.
- // TODO(primiano): if this fixes the crash we might want to coalesce the purge
- // and throttle it.
- auto on_ret = base::OnScopeExit([] { base::MaybeReleaseAllocatorMemToOS(); });
-
// ReadBuffers() can allocate memory internally, for filtering. By limiting
// the data that ReadBuffers() reads to kWriteIntoChunksSize per iteration,
// we limit the amount of memory used on each iteration.
@@ -2271,6 +2270,13 @@
MaybeFilterPackets(tracing_session, &packets);
+ if (!*has_more) {
+ // We've observed some extremely high memory usage by scudo after
+ // MaybeFilterPackets in the past. The original bug (b/195145848) is fixed
+ // now, but this code asks scudo to release memory just in case.
+ base::MaybeReleaseAllocatorMemToOS();
+ }
+
return packets;
}
@@ -3187,6 +3193,10 @@
trace_stats.set_chunks_discarded(chunks_discarded_);
trace_stats.set_patches_discarded(patches_discarded_);
trace_stats.set_invalid_packets(tracing_session->invalid_packets);
+ trace_stats.set_flushes_requested(tracing_session->flushes_requested);
+ trace_stats.set_flushes_succeeded(tracing_session->flushes_succeeded);
+ trace_stats.set_flushes_failed(tracing_session->flushes_failed);
+ trace_stats.set_final_flush_outcome(tracing_session->final_flush_outcome);
if (tracing_session->trace_filter) {
auto* filt_stats = trace_stats.mutable_filter_stats();
diff --git a/src/tracing/core/tracing_service_impl.h b/src/tracing/core/tracing_service_impl.h
index 99ee6ea..d0df0a6 100644
--- a/src/tracing/core/tracing_service_impl.h
+++ b/src/tracing/core/tracing_service_impl.h
@@ -57,6 +57,12 @@
class TaskRunner;
} // namespace base
+namespace protos {
+namespace gen {
+enum TraceStats_FinalFlushOutcome : int;
+}
+} // namespace protos
+
class Consumer;
class Producer;
class SharedMemory;
@@ -558,6 +564,14 @@
// Packets that failed validation of the TrustedPacket.
uint64_t invalid_packets = 0;
+ // Flush() stats. See comments in trace_stats.proto for more.
+ uint64_t flushes_requested = 0;
+ uint64_t flushes_succeeded = 0;
+ uint64_t flushes_failed = 0;
+
+ // Outcome of the final Flush() done by FlushAndDisableTracing().
+ protos::gen::TraceStats_FinalFlushOutcome final_flush_outcome{};
+
// Set to true on the first call to MaybeNotifyAllDataSourcesStarted().
bool did_notify_all_data_source_started = false;
diff --git a/src/tracing/internal/track_event_internal.cc b/src/tracing/internal/track_event_internal.cc
index 0c27e4a..3717fb2 100644
--- a/src/tracing/internal/track_event_internal.cc
+++ b/src/tracing/internal/track_event_internal.cc
@@ -26,14 +26,11 @@
#include "perfetto/tracing/track_event_interned_data_index.h"
#include "protos/perfetto/common/data_source_descriptor.gen.h"
#include "protos/perfetto/common/track_event_descriptor.pbzero.h"
-#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
#include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
-using perfetto::protos::pbzero::ClockSnapshot;
-
namespace perfetto {
TrackEventSessionObserver::~TrackEventSessionObserver() = default;
@@ -51,13 +48,6 @@
static constexpr const char kLegacySlowPrefix[] = "disabled-by-default-";
static constexpr const char kSlowTag[] = "slow";
static constexpr const char kDebugTag[] = "debug";
-// Allows to specify a custom unit different than the default (ns) for
-// the incremental clock.
-// A multiplier of 1000 means that a timestamp = 3 should be
-// interpreted as 3000 ns = 3 us.
-// TODO(mohitms): Move it to TrackEventConfig.
-constexpr uint64_t kIncrementalTimestampUnitMultiplier = 1;
-static_assert(kIncrementalTimestampUnitMultiplier >= 1, "");
void ForEachObserver(
std::function<bool(TrackEventSessionObserver*&)> callback) {
@@ -313,94 +303,50 @@
}
// static
-TraceTimestamp TrackEventInternal::GetTraceTime() {
- return {TrackEventIncrementalState::kClockIdIncremental, GetTimeNs()};
-}
-
-// static
int TrackEventInternal::GetSessionCount() {
return session_count_.load();
}
// static
-void TrackEventInternal::ResetIncrementalState(
- TraceWriterBase* trace_writer,
- TrackEventIncrementalState* incr_state,
- const TraceTimestamp& timestamp) {
- auto sequence_timestamp = timestamp;
- if (timestamp.clock_id != TrackEventInternal::GetClockId() &&
- timestamp.clock_id != TrackEventIncrementalState::kClockIdIncremental) {
- sequence_timestamp = TrackEventInternal::GetTraceTime();
- }
-
- incr_state->last_timestamp_ns = sequence_timestamp.value;
+void TrackEventInternal::ResetIncrementalState(TraceWriterBase* trace_writer,
+ TraceTimestamp timestamp) {
auto default_track = ThreadTrack::Current();
{
// Mark any incremental state before this point invalid. Also set up
// defaults so that we don't need to repeat constant data for each packet.
auto packet = NewTracePacket(
- trace_writer, incr_state, timestamp,
+ trace_writer, timestamp,
protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED);
auto defaults = packet->set_trace_packet_defaults();
- defaults->set_timestamp_clock_id(
- TrackEventIncrementalState::kClockIdIncremental);
+ defaults->set_timestamp_clock_id(GetClockId());
// Establish the default track for this event sequence.
auto track_defaults = defaults->set_track_event_defaults();
track_defaults->set_track_uuid(default_track.uuid);
-
- ClockSnapshot* clocks = packet->set_clock_snapshot();
- // Trace clock.
- ClockSnapshot::Clock* trace_clock = clocks->add_clocks();
- trace_clock->set_clock_id(GetClockId());
- trace_clock->set_timestamp(sequence_timestamp.value);
- // Delta-encoded incremental clock in nano seconds.
- // TODO(b/168311581): Make the unit of this clock configurable to allow
- // trade-off between precision and encoded trace size.
- ClockSnapshot::Clock* clock_incremental = clocks->add_clocks();
- clock_incremental->set_clock_id(
- TrackEventIncrementalState::kClockIdIncremental);
- auto ts_unit_multiplier = kIncrementalTimestampUnitMultiplier;
- clock_incremental->set_timestamp(sequence_timestamp.value /
- ts_unit_multiplier);
- clock_incremental->set_is_incremental(true);
- clock_incremental->set_unit_multiplier_ns(ts_unit_multiplier);
}
// Every thread should write a descriptor for its default track, because most
// trace points won't explicitly reference it. We also write the process
// descriptor from every thread that writes trace events to ensure it gets
// emitted at least once.
- WriteTrackDescriptor(default_track, trace_writer, incr_state,
- sequence_timestamp);
-
- WriteTrackDescriptor(ProcessTrack::Current(), trace_writer, incr_state,
- sequence_timestamp);
+ WriteTrackDescriptor(default_track, trace_writer);
+ WriteTrackDescriptor(ProcessTrack::Current(), trace_writer);
}
// static
protozero::MessageHandle<protos::pbzero::TracePacket>
TrackEventInternal::NewTracePacket(TraceWriterBase* trace_writer,
- TrackEventIncrementalState* incr_state,
- const TraceTimestamp& timestamp,
+ TraceTimestamp timestamp,
uint32_t seq_flags) {
auto packet = trace_writer->NewTracePacket();
- if (timestamp.clock_id == TrackEventIncrementalState::kClockIdIncremental) {
- if (incr_state->last_timestamp_ns <= timestamp.value) {
- // No need to set the clock id here, since kClockIdIncremental is the
- // clock id assumed by default.
- auto ts_unit_multiplier = kIncrementalTimestampUnitMultiplier;
- auto time_diff_ns = timestamp.value - incr_state->last_timestamp_ns;
- packet->set_timestamp(time_diff_ns / ts_unit_multiplier);
- incr_state->last_timestamp_ns = timestamp.value;
- } else {
- // TODO(mohitms): Consider using kIncrementalTimestampUnitMultiplier.
- packet->set_timestamp(timestamp.value);
- packet->set_timestamp_clock_id(GetClockId());
- }
- } else {
- packet->set_timestamp(timestamp.value);
- packet->set_timestamp_clock_id(timestamp.clock_id);
+ packet->set_timestamp(timestamp.nanoseconds);
+ if (timestamp.clock_id != GetClockId()) {
+ packet->set_timestamp_clock_id(static_cast<uint32_t>(timestamp.clock_id));
+ } else if (GetClockId() != protos::pbzero::BUILTIN_CLOCK_BOOTTIME) {
+ // TODO(skyostil): Stop emitting the clock id for the default trace clock
+ // for every event once the trace processor understands trace packet
+ // defaults.
+ packet->set_timestamp_clock_id(GetClockId());
}
packet->set_sequence_flags(seq_flags);
return packet;
@@ -413,10 +359,11 @@
const Category* category,
const char* name,
perfetto::protos::pbzero::TrackEvent::Type type,
- const TraceTimestamp& timestamp) {
+ TraceTimestamp timestamp) {
PERFETTO_DCHECK(g_main_thread);
PERFETTO_DCHECK(!incr_state->was_cleared);
- auto packet = NewTracePacket(trace_writer, incr_state, timestamp);
+
+ auto packet = NewTracePacket(trace_writer, timestamp);
EventContext ctx(std::move(packet), incr_state);
auto track_event = ctx.event();
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index 8aa589c..26d8a03 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -59,7 +59,6 @@
#include "protos/perfetto/common/track_event_descriptor.pbzero.h"
#include "protos/perfetto/config/interceptor_config.gen.h"
#include "protos/perfetto/config/track_event/track_event_config.gen.h"
-#include "protos/perfetto/trace/clock_snapshot.gen.h"
#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
#include "protos/perfetto/trace/gpu/gpu_render_stage_event.gen.h"
#include "protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h"
@@ -73,7 +72,6 @@
#include "protos/perfetto/trace/trace.pbzero.h"
#include "protos/perfetto/trace/trace_packet.gen.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "protos/perfetto/trace/trace_packet_defaults.gen.h"
#include "protos/perfetto/trace/track_event/chrome_process_descriptor.gen.h"
#include "protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h"
#include "protos/perfetto/trace/track_event/counter_descriptor.gen.h"
@@ -970,11 +968,6 @@
bool process_descriptor_found = false;
uint32_t sequence_id = 0;
int32_t cur_pid = perfetto::test::GetCurrentProcessId();
- uint64_t recent_absolute_time_ns = 0;
- bool found_incremental_clock = false;
- constexpr auto kClockIdIncremental =
- perfetto::internal::TrackEventIncrementalState::kClockIdIncremental;
-
for (const auto& packet : trace.packet()) {
if (packet.has_track_descriptor()) {
const auto& desc = packet.track_descriptor();
@@ -991,17 +984,6 @@
incremental_state_was_cleared = true;
categories.clear();
event_names.clear();
- EXPECT_EQ(kClockIdIncremental,
- packet.trace_packet_defaults().timestamp_clock_id());
- }
- if (packet.has_clock_snapshot()) {
- for (auto& clock : packet.clock_snapshot().clocks()) {
- if (clock.is_incremental()) {
- found_incremental_clock = true;
- recent_absolute_time_ns = clock.timestamp();
- EXPECT_EQ(kClockIdIncremental, clock.clock_id());
- }
- }
}
if (!packet.has_track_event())
@@ -1031,13 +1013,18 @@
event_names[it.iid()] = it.name();
}
}
- EXPECT_TRUE(found_incremental_clock);
- uint64_t absolute_timestamp = packet.timestamp() + recent_absolute_time_ns;
- recent_absolute_time_ns = absolute_timestamp;
- EXPECT_GT(absolute_timestamp, 0u);
- EXPECT_LE(absolute_timestamp, now);
- // Packet uses default (incremental) clock.
+
+ EXPECT_GT(packet.timestamp(), 0u);
+ EXPECT_LE(packet.timestamp(), now);
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
EXPECT_FALSE(packet.has_timestamp_clock_id());
+#else
+ constexpr auto kClockMonotonic =
+ perfetto::protos::pbzero::ClockSnapshot::Clock::MONOTONIC;
+ EXPECT_EQ(packet.timestamp_clock_id(),
+ static_cast<uint32_t>(kClockMonotonic));
+#endif
if (track_event.type() ==
perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN) {
EXPECT_FALSE(begin_found);
@@ -1064,84 +1051,6 @@
TestCategoryAsTemplateParameter<kTestCategory>();
}
-TEST_P(PerfettoApiTest, TrackEventWithIncrementalTimestamp) {
- // Create a new trace session.
- auto* tracing_session = NewTraceWithCategories({"bar"});
- constexpr auto kClockIdIncremental =
- perfetto::internal::TrackEventIncrementalState::kClockIdIncremental;
- tracing_session->get()->StartBlocking();
-
- std::map<uint64_t, std::string> event_names;
-
- auto empty_lambda = [](perfetto::EventContext) {};
-
- constexpr uint64_t kInstantEvent1Time = 92718891479583;
- TRACE_EVENT_INSTANT(
- "bar", "InstantEvent1",
- perfetto::TraceTimestamp{kClockIdIncremental, kInstantEvent1Time},
- empty_lambda);
-
- constexpr uint64_t kInstantEvent2Time = 92718891618959;
- TRACE_EVENT_INSTANT(
- "bar", "InstantEvent2",
- perfetto::TraceTimestamp{kClockIdIncremental, kInstantEvent2Time},
- empty_lambda);
-
- perfetto::TrackEvent::Flush();
- tracing_session->get()->StopBlocking();
-
- std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
- perfetto::protos::gen::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
-
- uint64_t absolute_timestamp = 0;
- int event_count = 0;
- // Go through the packets and add the timestamps of those packets that use the
- // incremental clock - in order to get the absolute timestamps of the track
- // events.
- for (const auto& packet : trace.packet()) {
- if (packet.has_clock_snapshot()) {
- for (auto& clock : packet.clock_snapshot().clocks()) {
- if (clock.is_incremental()) {
- absolute_timestamp = clock.timestamp();
- EXPECT_EQ(clock.clock_id(), kClockIdIncremental);
- }
- }
- } else if (!packet.has_timestamp_clock_id()) {
- // Packets that don't have a timestamp_clock_id default to the incremental
- // clock.
- absolute_timestamp += packet.timestamp();
- }
-
- if (packet.sequence_flags() &
- perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
- event_names.clear();
- }
-
- if (!packet.has_track_event())
- continue;
-
- // Update incremental state.
- if (packet.has_interned_data()) {
- const auto& interned_data = packet.interned_data();
- for (const auto& it : interned_data.event_names()) {
- EXPECT_EQ(event_names.find(it.iid()), event_names.end());
- event_names[it.iid()] = it.name();
- }
- }
-
- if (event_names[packet.track_event().name_iid()] == "InstantEvent1") {
- event_count++;
- ASSERT_EQ(absolute_timestamp, kInstantEvent1Time);
- } else if (event_names[packet.track_event().name_iid()] ==
- "InstantEvent2") {
- event_count++;
- ASSERT_EQ(absolute_timestamp, kInstantEvent2Time);
- }
- }
- ASSERT_EQ(event_count, 2);
-}
-
TEST_P(PerfettoApiTest, TrackEventCategories) {
// Create a new trace session.
auto* tracing_session = NewTraceWithCategories({"bar"});
@@ -1845,9 +1754,6 @@
for (const auto& packet : trace.packet()) {
if (!packet.has_track_event())
continue;
-
- EXPECT_EQ(packet.timestamp_clock_id(),
- static_cast<uint32_t>(perfetto::TrackEvent::GetTraceClockId()));
event_count++;
switch (packet.track_event().type()) {
case perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN:
diff --git a/src/tracing/track_event_state_tracker.cc b/src/tracing/track_event_state_tracker.cc
index 7ff50ac..7cb1b09 100644
--- a/src/tracing/track_event_state_tracker.cc
+++ b/src/tracing/track_event_state_tracker.cc
@@ -17,10 +17,8 @@
#include "perfetto/tracing/track_event_state_tracker.h"
#include "perfetto/ext/base/hash.h"
-#include "perfetto/tracing/internal/track_event_internal.h"
#include "protos/perfetto/common/interceptor_descriptor.gen.h"
-#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
#include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
@@ -32,8 +30,6 @@
namespace perfetto {
-using internal::TrackEventIncrementalState;
-
TrackEventStateTracker::~TrackEventStateTracker() = default;
TrackEventStateTracker::Delegate::~Delegate() = default;
@@ -49,15 +45,8 @@
perfetto::protos::pbzero::TrackEvent::Decoder track_event(
packet.track_event());
- auto clock_id = packet.timestamp_clock_id();
- if (!packet.has_timestamp_clock_id())
- clock_id = sequence_state.default_clock_id;
+ // TODO(skyostil): Support incremental timestamps.
uint64_t timestamp = packet.timestamp();
- // TODO(mohitms): Incorporate unit multiplier as well.
- if (clock_id == TrackEventIncrementalState::kClockIdIncremental) {
- timestamp += sequence_state.most_recent_absolute_time_ns;
- sequence_state.most_recent_absolute_time_ns = timestamp;
- }
Track* track = &sequence_state.track;
if (track_event.has_track_uuid()) {
@@ -174,19 +163,6 @@
}
#endif
- perfetto::protos::pbzero::ClockSnapshot::Decoder snapshot(
- packet.clock_snapshot());
- for (auto it = snapshot.clocks(); it; ++it) {
- perfetto::protos::pbzero::ClockSnapshot::Clock::Decoder clock(*it);
- // TODO(mohitms) : Handle the incremental clock other than default one.
- if (clock.is_incremental() &&
- clock.clock_id() == TrackEventIncrementalState::kClockIdIncremental) {
- sequence_state.most_recent_absolute_time_ns =
- clock.timestamp() * clock.unit_multiplier_ns();
- break;
- }
- }
-
if (packet.sequence_flags() &
perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
// Convert any existing event names and categories on the stack to
@@ -232,8 +208,6 @@
perfetto::protos::pbzero::TrackEventDefaults::Decoder
track_event_defaults(defaults.track_event_defaults());
sequence_state.track.uuid = track_event_defaults.track_uuid();
- if (defaults.has_timestamp_clock_id())
- sequence_state.default_clock_id = defaults.timestamp_clock_id();
}
}
if (packet.has_track_descriptor()) {
diff --git a/test/configs/BUILD.gn b/test/configs/BUILD.gn
index 4c93db1..b57b9aa 100644
--- a/test/configs/BUILD.gn
+++ b/test/configs/BUILD.gn
@@ -21,8 +21,8 @@
script = "../../tools/protoc_helper.py"
deps = [
- "../../protos/perfetto/config:merged_config",
- "../../protos/perfetto/trace:merged_trace",
+ "../../protos/perfetto/config:merged_config_source_set",
+ "../../protos/perfetto/trace:merged_trace_source_set",
protoc_target,
]
diff --git a/test/test_helper.h b/test/test_helper.h
index 8407f20..778f88a 100644
--- a/test/test_helper.h
+++ b/test/test_helper.h
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/scoped_file.h"
@@ -317,6 +318,8 @@
std::unique_ptr<TracingService::ConsumerEndpoint> endpoint_; // Keep last.
};
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
// This class is a reference to a child process that has in essence been execv
// to the requested binary. The process will start and then wait for Run()
// before proceeding. We use this to fork new processes before starting any
@@ -414,6 +417,8 @@
base::Pipe sync_pipe_;
};
+#endif // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
} // namespace perfetto
#endif // TEST_TEST_HELPER_H_
diff --git a/test/trace_processor/chrome/scroll_jank.out b/test/trace_processor/chrome/scroll_jank.out
index baaa642..163727e 100644
--- a/test/trace_processor/chrome/scroll_jank.out
+++ b/test/trace_processor/chrome/scroll_jank.out
@@ -1,141 +1,141 @@
-"gesture_scroll_id","trace_id","jank","ts","dur"
-2708,2709,0,544958000403,19009426
-2708,2711,0,544966000403,22609426
-2708,2715,0,544983000403,28089426
-2708,2717,0,544991000403,30714426
-2708,2719,0,544999000403,34740426
-2708,2721,0,545007000403,37462426
-2708,2725,0,545024000403,31889426
-2708,2727,0,545032000403,23876426
-2708,2729,0,545040000403,28316426
-2708,2733,0,545056000403,22620426
-2708,2735,0,545065000403,23642426
-2708,2739,0,545081000403,19016426
-2708,2741,0,545089000403,22491426
-2708,2743,0,545098000403,24940426
-2708,2747,0,545114000403,19365426
-2708,2749,0,545122000403,22629426
-2708,2753,0,545139000403,17669426
-2708,2755,0,545147000403,20941426
-2708,2757,0,545155000403,23321426
-2708,2761,0,545172000403,18585426
-2708,2763,0,545180000403,22430426
-2708,2765,0,545188000403,23545426
-2708,2769,0,545204000403,19115426
-2708,2771,0,545213000403,21107426
-2708,2773,0,545221000403,25065426
-2708,2777,0,545237000403,20064426
-2708,2779,0,545246000403,22190426
-2708,2783,0,545262000403,16635426
-2708,2785,0,545270000403,19926426
-2708,2787,0,545278000403,23003426
-2708,2791,0,545295000403,17169426
-2708,2793,0,545303000403,20626426
-2708,2795,0,545311000403,23560426
-2708,2799,0,545328000403,18191426
-2708,2801,0,545336000403,20911426
-2708,2803,0,545344000403,24228426
-2708,2807,0,545361000403,18189426
-2708,2809,0,545369000403,21379426
-2708,2811,0,545377000403,24913426
-2708,2815,0,545394000403,18671426
-2708,2817,0,545402000403,21928426
-2708,2821,0,545418000403,17254426
-2708,2823,0,545426000403,20407426
-2708,2825,0,545435000403,22633426
-2708,2827,0,545443000403,27179426
-2708,2831,0,545459000403,20575426
-2708,2833,0,545468000403,23489426
-2708,2837,0,545484000403,18277426
-2708,2839,0,545492000403,21649426
-2708,2841,0,545500000403,24734426
-2708,2845,0,545517000403,18824426
-2708,2847,0,545525000403,22343426
-2708,2849,0,545533000403,25222426
-2708,2853,0,545550000403,19151426
-2708,2855,0,545558000403,22660426
-2708,2859,0,545574000403,17603426
-2708,2861,0,545583000403,19608426
-2708,2863,0,545591000403,22822426
-2708,2867,0,545607000403,18005426
-2708,2869,0,545615000403,21063426
-2708,2871,0,545624000403,23894426
-2708,2875,0,545640000403,18611426
-2708,2877,0,545648000403,21759426
-2708,2879,0,545656000403,25004426
-2708,2881,0,545671000403,32742426
-2708,2884,0,545681794403,32652426
-2708,2885,0,545691182403,34488426
-2708,2886,0,545702355403,34887426
-2708,2887,0,545713526403,34615426
-2708,2888,0,545724697403,36799426
-2708,2889,0,545735867403,35326426
-2708,2890,0,545747040403,35047426
-2708,2891,0,545758211403,34990426
-2708,2892,0,545769381403,39529426
-2708,2893,0,545780550403,35967426
-2708,2894,1,545791721403,45468426
-2708,2895,1,545802892403,45651426
-2708,2897,0,545825234403,34662426
-2917,2918,0,546027000403,24672426
-2917,2920,0,546035000403,27274426
-2917,2922,0,546044000403,28587426
-2917,2924,1,546052000403,41821426
-2917,2926,1,546060000403,44914426
-2917,2930,0,546076000403,28902426
-2917,2932,0,546085000403,31881426
-2917,2934,0,546093000403,34989426
-2917,2938,1,546109000403,41953426
-2917,2940,0,546118000403,32872426
-2917,2942,0,546126000403,35348426
-2917,2946,0,546142000403,42106426
-2917,2948,1,546150000403,45005426
-2917,2950,0,546159000403,35994426
-2917,2954,0,546175000403,30970426
-2917,2956,1,546183000403,45256426
-2917,2960,0,546200000403,40097426
-2917,2962,0,546208000403,32086426
-2917,2964,0,546216000403,34686426
-2917,2968,0,546233000403,28852426
-2917,2970,0,546241000403,32494426
-2917,2972,0,546249000403,37304426
-2917,2976,0,546265000403,32101426
-2917,2978,0,546273000403,34156426
-2917,2982,0,546290000403,27915426
-2917,2984,0,546298000403,30723426
-2917,2986,0,546307000403,32918426
-2917,2990,0,546323000403,29800426
-2917,2992,0,546331000403,31314426
-2917,2994,0,546339000403,35092426
-2917,2998,0,546356000403,28702426
-2917,3000,0,546364000403,32457426
-2917,3002,0,546372000403,35043426
-2917,3006,0,546389000403,29285426
-2917,3008,0,546397000403,32831426
-2917,3010,0,546405000403,35630426
-2917,3014,0,546422000403,30119426
-2917,3016,0,546430000403,33185426
-2917,3020,0,546446000403,28386426
-2917,3022,0,546455000403,30102426
-2917,3024,0,546463000403,33512426
-2917,3028,0,546479000403,28455426
-2917,3030,0,546488000403,30791426
-2917,3032,0,546496000403,34105426
-2917,3036,0,546512000403,29329426
-2917,3038,0,546520000403,32321426
-2917,3040,0,546529000403,34457426
-2917,3044,0,546545000403,29668426
-2917,3046,0,546553000403,32830426
-2917,3048,0,546561000403,35849426
-2917,3052,0,546578000403,30365426
-2917,3054,0,546586000403,33666426
-2917,3056,0,546594000403,36913426
-2917,3060,0,546611000403,30855426
-2917,3062,0,546619000403,33897426
-2917,3064,0,546627000403,36941426
-2917,3068,0,546644000403,31194426
-2917,3070,0,546652000403,34276426
-2917,3074,0,546676000403,32746426
-2917,3077,0,546701627403,29680426
-2917,3079,0,546718977403,34597426
+"gesture_scroll_id","trace_id","jank","ts","dur","jank_budget"
+2708,2709,0,544958000403,19009426,-11933333.350000
+2708,2711,0,544966000403,22609426,-4733333.350000
+2708,2715,0,544983000403,28089426,-2853333.350000
+2708,2717,0,544991000403,30714426,-5708333.350000
+2708,2719,0,544999000403,34740426,-4307333.350000
+2708,2721,0,545007000403,37462426,-2760333.350000
+2708,2725,0,545024000403,31889426,-320333.350000
+2708,2727,0,545032000403,23876426,-12773333.350000
+2708,2729,0,545040000403,28316426,-2637333.350000
+2708,2733,0,545056000403,22620426,-9355333.350000
+2708,2735,0,545065000403,23642426,-3707333.350000
+2708,2739,0,545081000403,19016426,-11808333.350000
+2708,2741,0,545089000403,22491426,-4858333.350000
+2708,2743,0,545098000403,24940426,-2758333.350000
+2708,2747,0,545114000403,19365426,-11597333.350000
+2708,2749,0,545122000403,22629426,-3373333.350000
+2708,2753,0,545139000403,17669426,-11605333.350000
+2708,2755,0,545147000403,20941426,-5061333.350000
+2708,2757,0,545155000403,23321426,-3597333.350000
+2708,2761,0,545172000403,18585426,-12178333.350000
+2708,2763,0,545180000403,22430426,-4488333.350000
+2708,2765,0,545188000403,23545426,-3903333.350000
+2708,2769,0,545204000403,19115426,-10325333.350000
+2708,2771,0,545213000403,21107426,-6341333.350000
+2708,2773,0,545221000403,25065426,-3332333.350000
+2708,2777,0,545237000403,20064426,-10459333.350000
+2708,2779,0,545246000403,22190426,-2778333.350000
+2708,2783,0,545262000403,16635426,-11624333.350000
+2708,2785,0,545270000403,19926426,-5042333.350000
+2708,2787,0,545278000403,23003426,-2499333.350000
+2708,2791,0,545295000403,17169426,-11790333.350000
+2708,2793,0,545303000403,20626426,-4876333.350000
+2708,2795,0,545311000403,23560426,-2964333.350000
+2708,2799,0,545328000403,18191426,-11053333.350000
+2708,2801,0,545336000403,20911426,-5613333.350000
+2708,2803,0,545344000403,24228426,-2294333.350000
+2708,2807,0,545361000403,18189426,-11523333.350000
+2708,2809,0,545369000403,21379426,-5143333.350000
+2708,2811,0,545377000403,24913426,-2091333.350000
+2708,2815,0,545394000403,18671426,-11590333.350000
+2708,2817,0,545402000403,21928426,-3659333.350000
+2708,2821,0,545418000403,17254426,-11486333.350000
+2708,2823,0,545426000403,20407426,-5180333.350000
+2708,2825,0,545435000403,22633426,-6107333.350000
+2708,2827,0,545443000403,27179426,-1729333.350000
+2708,2831,0,545459000403,20575426,-11247333.350000
+2708,2833,0,545468000403,23489426,-3121333.350000
+2708,2837,0,545484000403,18277426,-11705333.350000
+2708,2839,0,545492000403,21649426,-4961333.350000
+2708,2841,0,545500000403,24734426,-2423333.350000
+2708,2845,0,545517000403,18824426,-11852333.350000
+2708,2847,0,545525000403,22343426,-4814333.350000
+2708,2849,0,545533000403,25222426,-2262333.350000
+2708,2853,0,545550000403,19151426,-11842333.350000
+2708,2855,0,545558000403,22660426,-3276333.350000
+2708,2859,0,545574000403,17603426,-10338333.350000
+2708,2861,0,545583000403,19608426,-6328333.350000
+2708,2863,0,545591000403,22822426,-3516333.350000
+2708,2867,0,545607000403,18005426,-11391333.350000
+2708,2869,0,545615000403,21063426,-5275333.350000
+2708,2871,0,545624000403,23894426,-3050333.350000
+2708,2875,0,545640000403,18611426,-11481333.350000
+2708,2877,0,545648000403,21759426,-5185333.350000
+2708,2879,0,545656000403,25004426,-5088333.350000
+2708,2881,0,545671000403,32742426,-595333.350000
+2708,2884,0,545681794403,32652426,-8423333.350000
+2708,2885,0,545691182403,34488426,-6497333.350000
+2708,2886,0,545702355403,34887426,-7934333.350000
+2708,2887,0,545713526403,34615426,-8605333.350000
+2708,2888,0,545724697403,36799426,-6149333.350000
+2708,2889,0,545735867403,35326426,-8054333.350000
+2708,2890,0,545747040403,35047426,-8276333.350000
+2708,2891,0,545758211403,34990426,-8390333.350000
+2708,2892,0,545769381403,39529426,-3794333.350000
+2708,2893,0,545780550403,35967426,-11895333.350000
+2708,2894,1,545791721403,45468426,1167666.650000
+2708,2895,1,545802892403,45651426,2655666.650000
+2708,2897,0,545825234403,34662426,1656666.650000
+2917,2918,0,546027000403,24672426,-10935333.350000
+2917,2920,0,546035000403,27274426,-5731333.350000
+2917,2922,0,546044000403,28587426,-7020333.350000
+2917,2924,1,546052000403,41821426,4900666.650000
+2917,2926,1,546060000403,44914426,7678666.650000
+2917,2930,0,546076000403,28902426,-11312333.350000
+2917,2932,0,546085000403,31881426,-5354333.350000
+2917,2934,0,546093000403,34989426,-5225333.350000
+2917,2938,1,546109000403,41953426,747666.650000
+2917,2940,0,546118000403,32872426,-10809333.350000
+2917,2942,0,546126000403,35348426,-5857333.350000
+2917,2946,0,546142000403,42106426,-1575333.350000
+2917,2948,1,546150000403,45005426,677666.650000
+2917,2950,0,546159000403,35994426,-3309333.350000
+2917,2954,0,546175000403,30970426,-13357333.350000
+2917,2956,1,546183000403,45256426,5952666.650000
+2917,2960,0,546200000403,40097426,-322333.350000
+2917,2962,0,546208000403,32086426,-10933333.350000
+2917,2964,0,546216000403,34686426,-2499333.350000
+2917,2968,0,546233000403,28852426,-11975333.350000
+2917,2970,0,546241000403,32494426,-4691333.350000
+2917,2972,0,546249000403,37304426,-3130333.350000
+2917,2976,0,546265000403,32101426,-10388333.350000
+2917,2978,0,546273000403,34156426,-2092333.350000
+2917,2982,0,546290000403,27915426,-11141333.350000
+2917,2984,0,546298000403,30723426,-5525333.350000
+2917,2986,0,546307000403,32918426,-5215333.350000
+2917,2990,0,546323000403,29800426,-9847333.350000
+2917,2992,0,546331000403,31314426,-6819333.350000
+2917,2994,0,546339000403,35092426,-1943333.350000
+2917,2998,0,546356000403,28702426,-12088333.350000
+2917,3000,0,546364000403,32457426,-4578333.350000
+2917,3002,0,546372000403,35043426,-2575333.350000
+2917,3006,0,546389000403,29285426,-11879333.350000
+2917,3008,0,546397000403,32831426,-4787333.350000
+2917,3010,0,546405000403,35630426,-2822333.350000
+2917,3014,0,546422000403,30119426,-11399333.350000
+2917,3016,0,546430000403,33185426,-3534333.350000
+2917,3020,0,546446000403,28386426,-10049333.350000
+2917,3022,0,546455000403,30102426,-6617333.350000
+2917,3024,0,546463000403,33512426,-3276333.350000
+2917,3028,0,546479000403,28455426,-10669333.350000
+2917,3030,0,546488000403,30791426,-5997333.350000
+2917,3032,0,546496000403,34105426,-3557333.350000
+2917,3036,0,546512000403,29329426,-11325333.350000
+2917,3038,0,546520000403,32321426,-5341333.350000
+2917,3040,0,546529000403,34457426,-3544333.350000
+2917,3044,0,546545000403,29668426,-11495333.350000
+2917,3046,0,546553000403,32830426,-5171333.350000
+2917,3048,0,546561000403,35849426,-2849333.350000
+2917,3052,0,546578000403,30365426,-11634333.350000
+2917,3054,0,546586000403,33666426,-5032333.350000
+2917,3056,0,546594000403,36913426,-2275333.350000
+2917,3060,0,546611000403,30855426,-11375333.350000
+2917,3062,0,546619000403,33897426,-5291333.350000
+2917,3064,0,546627000403,36941426,-2586333.350000
+2917,3068,0,546644000403,31194426,-11415333.350000
+2917,3070,0,546652000403,34276426,-5251333.350000
+2917,3074,0,546676000403,32746426,-5267333.350000
+2917,3077,0,546701627403,29680426,-11399333.350000
+2917,3079,0,546718977403,34597426,-3416333.350000
diff --git a/test/trace_processor/chrome/scroll_jank.sql b/test/trace_processor/chrome/scroll_jank.sql
index 2a502c1..9aaa99b 100644
--- a/test/trace_processor/chrome/scroll_jank.sql
+++ b/test/trace_processor/chrome/scroll_jank.sql
@@ -20,5 +20,6 @@
trace_id,
jank,
ts,
- dur
+ dur,
+ jank_budget
FROM scroll_jank;
diff --git a/test/trace_processor/chrome/touch_jank.out b/test/trace_processor/chrome/touch_jank.out
index 9f55ea8..18edb3f 100644
--- a/test/trace_processor/chrome/touch_jank.out
+++ b/test/trace_processor/chrome/touch_jank.out
@@ -1,16 +1,16 @@
-"touch_id","trace_id","jank","ts","dur"
-6280,6288,1,1383122421558418,226350000
-6280,6312,0,1383122543558418,185244000
-6318,6328,1,1383123604558418,207945000
-6318,6414,0,1383124088558418,173233000
-6420,6552,0,1383125521558418,161901000
-6586,6602,0,1383126581558418,87964000
-6586,6693,1,1383127076558418,140115000
-6697,6698,1,1383127670558418,301236000
-6697,6723,0,1383127837558418,134236000
-6788,6802,0,1383129053558418,163272000
-6788,6877,1,1383129492558418,370407000
-6906,6911,1,1383130519558418,198057000
-6906,6915,0,1383130553558418,164057000
-6906,6940,0,1383130681558418,167758000
+"touch_id","trace_id","jank","ts","dur","jank_budget"
+6280,6288,1,1383122421558418,226350000,32772666.650000
+6280,6312,0,1383122543558418,185244000,-31034333.350000
+6318,6328,1,1383123604558418,207945000,26378666.650000
+6318,6414,0,1383124088558418,173233000,2998666.650000
+6420,6552,0,1383125521558418,161901000,65603666.650000
+6586,6602,0,1383126581558418,87964000,-60484333.350000
+6586,6693,1,1383127076558418,140115000,43817666.650000
+6697,6698,1,1383127670558418,301236000,158666666.650000
+6697,6723,0,1383127837558418,134236000,-37369333.350000
+6788,6802,0,1383129053558418,163272000,20702666.650000
+6788,6877,1,1383129492558418,370407000,198801666.650000
+6906,6911,1,1383130519558418,198057000,25666666.650000
+6906,6915,0,1383130553558418,164057000,-12034333.350000
+6906,6940,0,1383130681558418,167758000,-4632333.350000
diff --git a/test/trace_processor/chrome/touch_jank.sql b/test/trace_processor/chrome/touch_jank.sql
index 723b146..d601148 100644
--- a/test/trace_processor/chrome/touch_jank.sql
+++ b/test/trace_processor/chrome/touch_jank.sql
@@ -20,5 +20,6 @@
trace_id,
jank,
ts,
- dur
+ dur,
+ jank_budget
FROM touch_jank;
diff --git a/test/trace_processor/chrome/touch_jank_synth.out b/test/trace_processor/chrome/touch_jank_synth.out
index 0c6f96f..44758af 100644
--- a/test/trace_processor/chrome/touch_jank_synth.out
+++ b/test/trace_processor/chrome/touch_jank_synth.out
@@ -1,5 +1,5 @@
-"touch_id","trace_id","jank","ts","dur"
-87654,34577,0,0,10000000
-87654,34578,1,16000000,33000000
-87654,34579,0,55000000,33000000
+"touch_id","trace_id","jank","ts","dur","jank_budget"
+87654,34577,0,0,10000000,-31333333.350000
+87654,34578,1,16000000,33000000,14666666.650000
+87654,34579,0,55000000,33000000,-8333333.350000
diff --git a/test/trace_processor/fuchsia/fuchsia_smoke_instants.out b/test/trace_processor/fuchsia/fuchsia_smoke_instants.out
index 6e2dd9d..87964ab 100644
--- a/test/trace_processor/fuchsia/fuchsia_smoke_instants.out
+++ b/test/trace_processor/fuchsia/fuchsia_smoke_instants.out
@@ -1,11 +1,11 @@
-"ts","name","value"
-21442756010,"task_start",0.000000
-21446583438,"task_end",0.000000
-21448366538,"task_start",0.000000
-21450363277,"task_end",0.000000
-21454255741,"task_start",0.000000
-21457834528,"task_end",0.000000
-21459006408,"task_start",0.000000
-21460601866,"task_end",0.000000
-21461282720,"task_start",0.000000
-21462998487,"task_end",0.000000
+"ts","name"
+21442756010,"task_start"
+21446583438,"task_end"
+21448366538,"task_start"
+21450363277,"task_end"
+21454255741,"task_start"
+21457834528,"task_end"
+21459006408,"task_start"
+21460601866,"task_end"
+21461282720,"task_start"
+21462998487,"task_end"
diff --git a/test/trace_processor/fuchsia/fuchsia_smoke_slices.out b/test/trace_processor/fuchsia/fuchsia_smoke_slices.out
index e437aa4..39c37a0 100644
--- a/test/trace_processor/fuchsia/fuchsia_smoke_slices.out
+++ b/test/trace_processor/fuchsia/fuchsia_smoke_slices.out
@@ -1,3 +1,3 @@
"type","depth","count"
-"thread_track",0,1153
-"thread_track",1,5
+"thread_track",0,2153
+"thread_track",1,1004
diff --git a/test/trace_processor/fuchsia/fuchsia_workstation_smoke_slices.out b/test/trace_processor/fuchsia/fuchsia_workstation_smoke_slices.out
index daab85f..68945e2 100644
--- a/test/trace_processor/fuchsia/fuchsia_workstation_smoke_slices.out
+++ b/test/trace_processor/fuchsia/fuchsia_workstation_smoke_slices.out
@@ -2,8 +2,8 @@
"process_track",0,85
"process_track",1,14
"process_track",2,1
-"thread_track",0,13379
-"thread_track",1,11548
+"thread_track",0,15198
+"thread_track",1,11607
"thread_track",2,10181
"thread_track",3,1927
"thread_track",4,4001
diff --git a/test/trace_processor/fuchsia/smoke_instants.sql b/test/trace_processor/fuchsia/smoke_instants.sql
index b57a531..cc5c40e 100644
--- a/test/trace_processor/fuchsia/smoke_instants.sql
+++ b/test/trace_processor/fuchsia/smoke_instants.sql
@@ -15,7 +15,8 @@
--
select
ts,
- name,
- value
-from instants
+ name
+from slice
+where
+ dur = 0
limit 10;
diff --git a/test/trace_processor/graphics/android_sysui_cuj.out b/test/trace_processor/graphics/android_sysui_cuj.out
index 9d81d7b..b82ae3b 100644
--- a/test/trace_processor/graphics/android_sysui_cuj.out
+++ b/test/trace_processor/graphics/android_sysui_cuj.out
@@ -61,6 +61,12 @@
}
frames {
number: 8
+ ts: 300000000
+ dur: 4000000
+ vsync: 110
+ }
+ frames {
+ number: 9
ts: 400000000
dur: 10000000
vsync: 120
diff --git a/test/trace_processor/graphics/android_sysui_cuj.py b/test/trace_processor/graphics/android_sysui_cuj.py
index a3a8254..dbbf47c 100644
--- a/test/trace_processor/graphics/android_sysui_cuj.py
+++ b/test/trace_processor/graphics/android_sysui_cuj.py
@@ -28,11 +28,19 @@
trace.add_atrace_end(ts=ts_end, tid=PID, pid=PID)
-def add_render_thread_atrace(trace, ts, ts_end, buf):
+def add_render_thread_atrace_begin(trace, ts, buf):
trace.add_atrace_begin(ts=ts, tid=RTID, pid=PID, buf=buf)
+
+
+def add_render_thread_atrace_end(trace, ts_end):
trace.add_atrace_end(ts=ts_end, tid=RTID, pid=PID)
+def add_render_thread_atrace(trace, ts, ts_end, buf):
+ add_render_thread_atrace_begin(trace, ts, buf)
+ add_render_thread_atrace_end(trace, ts_end)
+
+
def add_gpu_thread_atrace(trace, ts, ts_end, buf):
trace.add_atrace_begin(ts=ts, tid=1666, pid=PID, buf=buf)
trace.add_atrace_end(ts=ts_end, tid=1666, pid=PID)
@@ -43,14 +51,30 @@
trace.add_atrace_end(ts=ts_end, tid=JITID, pid=PID)
-def add_frame(trace, vsync, ts_do_frame, ts_end_do_frame, ts_draw_frame,
- ts_end_draw_frame, ts_gpu, ts_end_gpu):
+def add_frame(trace,
+ vsync,
+ ts_do_frame,
+ ts_end_do_frame,
+ ts_draw_frame,
+ ts_end_draw_frame,
+ ts_gpu=None,
+ ts_end_gpu=None):
add_main_thread_atrace(trace, ts_do_frame, ts_end_do_frame,
"Choreographer#doFrame %d" % vsync)
- add_render_thread_atrace(trace, ts_draw_frame, ts_end_draw_frame,
- "DrawFrames %d" % vsync)
- add_gpu_thread_atrace(trace, ts_gpu, ts_end_gpu,
- "waiting for GPU completion 123")
+
+ gpu_idx = 1000 + vsync * 10 + 1
+ if ts_gpu is None:
+ gpu_fence_message = "GPU completion fence %d has signaled"
+ else:
+ gpu_fence_message = "Trace GPU completion fence %d"
+ add_render_thread_atrace_begin(trace, ts_draw_frame, "DrawFrames %d" % vsync)
+ add_render_thread_atrace(trace, ts_end_draw_frame - 100,
+ ts_end_draw_frame - 1, gpu_fence_message % gpu_idx)
+ add_render_thread_atrace_end(trace, ts_end_draw_frame)
+
+ if ts_gpu is not None:
+ add_gpu_thread_atrace(trace, ts_gpu, ts_end_gpu,
+ "waiting for GPU completion %d" % gpu_idx)
def add_display_frame_events(ts,
@@ -248,13 +272,19 @@
ts_gpu=108_000_000,
ts_end_gpu=115_600_000)
+add_render_thread_atrace_begin(trace, ts=108_000_000, buf="DrawFrames 90")
add_render_thread_atrace(
- trace, ts=108_000_000, ts_end=114_000_000, buf="DrawFrames 90")
+ trace,
+ ts=113_000_000,
+ ts_end=113_500_000,
+ buf="Trace GPU completion fence 1902")
+add_render_thread_atrace_end(trace, ts_end=114_000_000)
+
add_gpu_thread_atrace(
trace,
ts=121_500_000,
ts_end=122_000_000,
- buf="waiting for GPU completion 123")
+ buf="waiting for GPU completion 1902")
add_frame(
trace,
@@ -276,8 +306,8 @@
ts_end_do_frame=315_000_000,
ts_draw_frame=302_000_000,
ts_end_draw_frame=304_000_000,
- ts_gpu=308_000_000,
- ts_end_gpu=310_000_000)
+ ts_gpu=None,
+ ts_end_gpu=None)
add_render_thread_atrace(
trace, ts=305_000_000, ts_end=308_000_000, buf="dispatchFrameCallbacks")
diff --git a/test/trace_processor/network/index b/test/trace_processor/network/index
index 51ce794..3f8fa33 100644
--- a/test/trace_processor/network/index
+++ b/test/trace_processor/network/index
@@ -4,3 +4,4 @@
netperf_metric.textproto android_netperf netperf_metric.out
inet_sock_set_state.textproto inet_sock_set_state.sql inet_sock_set_state.out
tcp_retransmit_skb.textproto tcp_retransmit_skb.sql tcp_retransmit_skb.out
+napi_gro_receive.textproto napi_gro_receive.sql napi_gro_receive.out
diff --git a/test/trace_processor/network/napi_gro_receive.out b/test/trace_processor/network/napi_gro_receive.out
new file mode 100644
index 0000000..0648e41
--- /dev/null
+++ b/test/trace_processor/network/napi_gro_receive.out
@@ -0,0 +1,4 @@
+"ts","name","dur","cat","name","ret","len"
+10000,"rmnet0",20,"napi_gro","Napi Gro Cpu 2",2,1000
+20000,"rmnet0",20,"napi_gro","Napi Gro Cpu 2",1,1000
+30000,"wlan",20,"napi_gro","Napi Gro Cpu 4",3,500
diff --git a/test/trace_processor/network/napi_gro_receive.sql b/test/trace_processor/network/napi_gro_receive.sql
new file mode 100644
index 0000000..48ee38f
--- /dev/null
+++ b/test/trace_processor/network/napi_gro_receive.sql
@@ -0,0 +1,16 @@
+SELECT
+ ts,
+ s.name,
+ dur,
+ cat,
+ t.name,
+ EXTRACT_ARG(arg_set_id, 'ret') AS ret,
+ EXTRACT_ARG(arg_set_id, 'len') AS len
+FROM
+ slice AS s
+LEFT JOIN
+ track AS t
+ ON s.track_id = t.id
+WHERE
+ t.name GLOB "Napi Gro Cpu *"
+ORDER BY ts;
diff --git a/test/trace_processor/network/napi_gro_receive.textproto b/test/trace_processor/network/napi_gro_receive.textproto
new file mode 100644
index 0000000..ee202f8
--- /dev/null
+++ b/test/trace_processor/network/napi_gro_receive.textproto
@@ -0,0 +1,75 @@
+packet {
+ ftrace_events {
+ cpu: 2
+ event {
+ timestamp: 10000
+ pid: 200
+ napi_gro_receive_entry {
+ name: "rmnet0"
+ len: 1000
+ }
+ }
+ }
+}
+packet {
+ ftrace_events {
+ cpu: 2
+ event {
+ timestamp: 10020
+ pid: 300
+ napi_gro_receive_exit {
+ ret: 2
+ }
+ }
+ }
+}
+packet {
+ ftrace_events {
+ cpu: 2
+ event {
+ timestamp: 20000
+ pid: 200
+ napi_gro_receive_entry {
+ name: "rmnet0"
+ len: 1000
+ }
+ }
+ }
+}
+packet {
+ ftrace_events {
+ cpu: 2
+ event {
+ timestamp: 20020
+ pid: 300
+ napi_gro_receive_exit {
+ ret: 1
+ }
+ }
+ }
+}
+packet {
+ ftrace_events {
+ cpu: 4
+ event {
+ timestamp: 30000
+ pid: 200
+ napi_gro_receive_entry {
+ name: "wlan"
+ len: 500
+ }
+ }
+ }
+}
+packet {
+ ftrace_events {
+ cpu: 4
+ event {
+ timestamp: 30020
+ pid: 300
+ napi_gro_receive_exit {
+ ret: 3
+ }
+ }
+ }
+}
diff --git a/test/trace_processor/network/netperf_metric.out b/test/trace_processor/network/netperf_metric.out
index 24c8aac..0077d53 100644
--- a/test/trace_processor/network/netperf_metric.out
+++ b/test/trace_processor/network/netperf_metric.out
@@ -32,6 +32,7 @@
data_rate_kbps: 800.0
}
}
+ gro_aggregation_ratio: '1:1.75'
}
tx {
total {
@@ -141,4 +142,5 @@
}
avg_interstack_latency_ms: 0.4
}
+ retransmission_rate: 20.0
}
diff --git a/test/trace_processor/network/netperf_metric.textproto b/test/trace_processor/network/netperf_metric.textproto
index 1684df9..0e478a9 100644
--- a/test/trace_processor/network/netperf_metric.textproto
+++ b/test/trace_processor/network/netperf_metric.textproto
@@ -2,6 +2,36 @@
ftrace_events {
cpu: 0
event {
+ timestamp: 99999900
+ pid: 200
+ napi_gro_receive_entry {
+ name: "rmnet0"
+ len: 512
+ }
+ }
+ event {
+ timestamp: 99999920
+ pid: 300
+ napi_gro_receive_exit {
+ ret: 1
+ }
+ }
+ event {
+ timestamp: 99999930
+ pid: 200
+ napi_gro_receive_entry {
+ name: "rmnet0"
+ len: 512
+ }
+ }
+ event {
+ timestamp: 99999940
+ pid: 300
+ napi_gro_receive_exit {
+ ret: 2
+ }
+ }
+ event {
timestamp: 100000000
pid: 200
cpu_frequency {
@@ -25,6 +55,18 @@
}
}
event {
+ timestamp: 100090000
+ pid: 234
+ tcp_retransmit_skb {
+ daddr: 19216801
+ saddr: 127001
+ dport: 5001
+ sport: 56789
+ state: 1
+ skaddr: 77889900
+ }
+ }
+ event {
timestamp: 100100000
pid: 200
net_dev_xmit {
@@ -46,6 +88,36 @@
ftrace_events {
cpu: 1
event {
+ timestamp: 119999900
+ pid: 200
+ napi_gro_receive_entry {
+ name: "rmnet0"
+ len: 512
+ }
+ }
+ event {
+ timestamp: 119999920
+ pid: 300
+ napi_gro_receive_exit {
+ ret: 1
+ }
+ }
+ event {
+ timestamp: 119999930
+ pid: 200
+ napi_gro_receive_entry {
+ name: "rmnet0"
+ len: 512
+ }
+ }
+ event {
+ timestamp: 119999940
+ pid: 300
+ napi_gro_receive_exit {
+ ret: 2
+ }
+ }
+ event {
timestamp: 120000000
pid: 200
cpu_frequency {
@@ -90,6 +162,36 @@
ftrace_events {
cpu: 0
event {
+ timestamp: 139999900
+ pid: 200
+ napi_gro_receive_entry {
+ name: "rmnet0"
+ len: 512
+ }
+ }
+ event {
+ timestamp: 139999920
+ pid: 300
+ napi_gro_receive_exit {
+ ret: 1
+ }
+ }
+ event {
+ timestamp: 139999930
+ pid: 200
+ napi_gro_receive_entry {
+ name: "rmnet0"
+ len: 512
+ }
+ }
+ event {
+ timestamp: 139999940
+ pid: 300
+ napi_gro_receive_exit {
+ ret: 2
+ }
+ }
+ event {
timestamp: 140000000
pid: 200
cpu_frequency {
@@ -134,6 +236,21 @@
ftrace_events {
cpu: 1
event {
+ timestamp: 139999900
+ pid: 200
+ napi_gro_receive_entry {
+ name: "rmnet0"
+ len: 1024
+ }
+ }
+ event {
+ timestamp: 139999920
+ pid: 300
+ napi_gro_receive_exit {
+ ret: 3
+ }
+ }
+ event {
timestamp: 140000000
pid: 200
cpu_frequency {
diff --git a/test/trace_processor/profiling/heap_graph_deobfuscate_pkg.textproto b/test/trace_processor/profiling/heap_graph_deobfuscate_pkg.textproto
new file mode 100644
index 0000000..4697548
--- /dev/null
+++ b/test/trace_processor/profiling/heap_graph_deobfuscate_pkg.textproto
@@ -0,0 +1,141 @@
+packet {
+ process_tree {
+ processes {
+ pid: 2
+ ppid: 1
+ cmdline: "<ignored>"
+ uid: 10001
+ }
+ }
+}
+packet {
+ packages_list {
+ packages {
+ name: "com.google.android.gm"
+ uid: 10001
+ }
+ }
+}
+packet {
+ trusted_packet_sequence_id: 999
+ timestamp: 10
+ heap_graph {
+ pid: 2
+ roots {
+ root_type: ROOT_JAVA_FRAME
+ object_ids: 0x01
+ object_ids: 0x05
+ }
+ objects {
+ id: 0x01
+ type_id: 1
+ self_size: 64
+ reference_field_id: 1
+ reference_object_id: 0x02
+ reference_field_id: 4
+ reference_object_id: 0x00
+ reference_field_id: 3
+ reference_object_id: 0x02
+ }
+ objects {
+ id: 0x02
+ type_id: 2
+ self_size: 32
+ }
+ objects {
+ id: 0x03
+ type_id: 2
+ self_size: 128
+ }
+ objects {
+ id: 0x04
+ type_id: 3
+ self_size: 1024
+ reference_field_id: 2
+ reference_object_id: 0x01
+ }
+ objects {
+ id: 0x05
+ type_id: 4
+ self_size: 256
+ }
+ objects {
+ id: 0x06
+ type_id: 5
+ self_size: 256
+ }
+ continued: true
+ index: 0
+ }
+}
+packet {
+ trusted_packet_sequence_id: 999
+ timestamp: 10
+ heap_graph {
+ pid: 2
+ location_names {
+ iid: 1
+ str: "base.apk!classes.dex"
+ }
+ types {
+ id: 1
+ class_name: "FactoryProducerDelegateImplActor"
+ location_id: 1
+ }
+ types {
+ id: 2
+ class_name: "Foo"
+ location_id: 1
+ }
+ types {
+ id: 3
+ class_name: "a"
+ location_id: 1
+ }
+ types {
+ id: 4
+ class_name: "a[]"
+ location_id: 1
+ }
+ types {
+ id: 5
+ class_name: "java.lang.Class<a[]>"
+ location_id: 1
+ }
+ field_names {
+ iid: 1
+ str: "FactoryProducerDelegateImplActor.foo"
+ }
+ field_names {
+ iid: 2
+ str: "int a.a"
+ }
+ field_names {
+ iid: 3
+ str: "a.b"
+ }
+ field_names {
+ iid: 4
+ str: "FactoryProducerDelegateImplActor.setToNULL"
+ }
+ continued: true
+ index: 1
+ }
+}
+packet {
+ deobfuscation_mapping {
+ package_name: "com.google.android.gm"
+ obfuscated_classes {
+ obfuscated_name: "a"
+ deobfuscated_name: "DeobfuscatedA"
+ obfuscated_members {
+ obfuscated_name: "a"
+ deobfuscated_name: "deobfuscatedA"
+ }
+ obfuscated_members {
+ obfuscated_name: "b"
+ deobfuscated_name: "Other.deobfuscatedA"
+ }
+ }
+ }
+}
diff --git a/test/trace_processor/profiling/index b/test/trace_processor/profiling/index
index 07a9340..1099a51 100644
--- a/test/trace_processor/profiling/index
+++ b/test/trace_processor/profiling/index
@@ -13,6 +13,7 @@
heap_graph_baseapk.textproto heap_graph_flamegraph.sql heap_graph_flamegraph.out
heap_graph_baseapk.textproto heap_graph_object.sql heap_graph_object.out
heap_graph_baseapk.textproto heap_graph_reference.sql heap_graph_reference.out
+heap_graph_deobfuscate_pkg.textproto heap_graph_object.sql heap_graph_object.out
heap_graph_duplicate.textproto heap_graph_flamegraph.sql heap_graph_duplicate_flamegraph.out
diff --git a/tools/ftrace_proto_gen/event_list b/tools/ftrace_proto_gen/event_list
index 0535103..948eb11 100644
--- a/tools/ftrace_proto_gen/event_list
+++ b/tools/ftrace_proto_gen/event_list
@@ -358,3 +358,6 @@
net/net_dev_xmit
sock/inet_sock_set_state
tcp/tcp_retransmit_skb
+cros_ec/cros_ec_sensorhub_data
+net/napi_gro_receive_entry
+net/napi_gro_receive_exit
diff --git a/tools/gen_bazel b/tools/gen_bazel
index 73b4e45..e5c7f82 100755
--- a/tools/gen_bazel
+++ b/tools/gen_bazel
@@ -64,12 +64,12 @@
# These targets are required by internal build rules but don't need to be
# exported publicly.
default_targets = [
- '//test:client_api_example',
'//src/ipc:perfetto_ipc',
'//src/ipc/protoc_plugin:ipc_plugin',
'//src/protozero:protozero',
'//src/protozero/protoc_plugin:protozero_plugin',
'//src/protozero/protoc_plugin:cppgen_plugin',
+ '//test:client_api_example',
'//tools/proto_filter:proto_filter',
'//tools/proto_merger:proto_merger',
] + public_targets
@@ -77,14 +77,18 @@
# Root proto targets (to force discovery of intermediate proto targets).
# These targets are marked public.
proto_targets = [
- '//protos/perfetto/trace:merged_trace',
+ '//protos/perfetto/trace:merged_trace_source_set',
'//protos/perfetto/trace:non_minimal_lite',
- '//protos/perfetto/config:merged_config',
+ '//protos/perfetto/trace:non_minimal_source_set',
+ '//protos/perfetto/config:merged_config_source_set',
'//protos/perfetto/metrics:lite',
+ '//protos/perfetto/metrics:source_set',
'//protos/perfetto/metrics/android:lite',
- '//protos/perfetto/trace:lite',
- '//protos/perfetto/config:lite',
+ '//protos/perfetto/metrics/android:source_set',
+ '//protos/perfetto/trace:source_set',
+ '//protos/perfetto/config:source_set',
'//protos/third_party/chromium:lite',
+ '//protos/third_party/chromium:source_set',
]
# Path for the protobuf sources in the standalone build.
@@ -143,7 +147,8 @@
custom_actions = {
- gn_utils.GEN_VERSION_TARGET: gen_version_header,
+ gn_utils.GEN_VERSION_TARGET:
+ gen_version_header,
'//src/trace_processor/metrics/sql:gen_amalgamated_sql_metrics':
gen_amalgamated_sql_metrics,
}
@@ -171,12 +176,14 @@
self.tools = []
self.exec_tools = []
self.outs = []
+ self.exports = []
def __lt__(self, other):
if isinstance(other, self.__class__):
return self.name < other.name
- raise TypeError('\'<\' not supported between instances of \'%s\' and \'%s\''
- % (type(self).__name__, type(other).__name__))
+ raise TypeError(
+ '\'<\' not supported between instances of \'%s\' and \'%s\'' %
+ (type(self).__name__, type(other).__name__))
def __str__(self):
"""Converts the object into a Bazel Starlark label."""
@@ -185,8 +192,8 @@
res += '%s(\n' % self.type
any_deps = len(self.deps) + len(self.external_deps) > 0
ORD = [
- 'name','srcs', 'hdrs', 'visibility', 'deps', 'outs', 'cmd', 'tools',
- 'exec_tools'
+ 'name', 'srcs', 'hdrs', 'visibility', 'deps', 'outs', 'cmd', 'tools',
+ 'exec_tools', 'exports'
]
hasher = lambda x: sum((99,) + tuple(ord(c) for c in x))
key_sorter = lambda kv: ORD.index(kv[0]) if kv[0] in ORD else hasher(kv[0])
@@ -250,15 +257,8 @@
return gn_utils.label_to_target_name_with_path(gn_name)
-def gen_proto_labels(target):
- """ Generates the xx_proto_library label for proto targets.
-
- Bazel requires that each protobuf-related target is modeled with two labels:
- 1. A plugin-agnostic target that defines only the .proto sources and their
- dependencies.
- 2. A plugin-dependent target (e.g. cc_library, cc_protozero_library) that has
- only a dependency on 1 and does NOT refer to any .proto sources.
- """
+def gen_proto_label(target):
+ """ Generates the xx_proto_library label for proto targets."""
assert (target.type == 'proto_library')
def get_sources_label(target_name):
@@ -267,46 +267,39 @@
sources_label_name = get_sources_label(target.name)
- # Generates 1.
- sources_label = BazelLabel(sources_label_name, 'perfetto_proto_library')
- sources_label.comment = target.name
- assert (all(x.startswith('//') for x in target.sources))
- assert (all(x.endswith('.proto') for x in target.sources))
- sources_label.srcs = sorted([x[2:] for x in target.sources]) # Strip //.
-
- deps = [
- ':' + get_sources_label(x)
- for x in target.proto_deps
-
- # This is to avoid a dependency-on-self in the case where
- # protos/perfetto/ipc:ipc depends on protos/perfetto/ipc:cpp and both
- # targets resolve to "protos_perfetto_ipc_protos".
- if get_sources_label(x) != sources_label_name
- ]
- sources_label.deps = sorted(deps)
-
- # In Bazel, proto_paths are not a supported concept becauase strong dependency
- # checking is enabled. Instead, we need to depend on the target which includes
- # the proto we want to depend on.
- # For example, we include the proto_path |buildtools_protobuf_src| because we
- # want to depend on the "google/protobuf/descriptor.proto" proto file. This
- # will be exposed by the |protobuf_descriptor_proto| dep.
- if buildtools_protobuf_src in target.proto_paths:
- sources_label.external_deps = [
- 'PERFETTO_CONFIG.deps.protobuf_descriptor_proto'
- ]
-
- if target.name in proto_targets:
- sources_label.visibility = PUBLIC_VISIBILITY
- else:
- sources_label.visibility = ['PERFETTO_CONFIG.proto_library_visibility']
-
# For 'source_set' plugins, we don't want to generate any plugin-dependent
# targets so just return the label of the proto sources only.
if target.proto_plugin == 'source_set':
- return [sources_label]
+ sources_label = BazelLabel(sources_label_name, 'perfetto_proto_library')
+ sources_label.comment = target.name
+ assert (all(x.startswith('//') for x in target.sources))
+ assert (all(x.endswith('.proto') for x in target.sources))
+ sources_label.srcs = sorted([x[2:] for x in target.sources]) # Strip //.
+ sources_label.deps = sorted(
+ [':' + get_sources_label(x) for x in target.proto_deps])
- # Generates 2.
+ # In Bazel, proto_paths are not a supported concept becauase strong
+ # dependency checking is enabled. Instead, we need to depend on the target
+ # which includes the proto we want to depend on.
+ # For example, we include the proto_path |buildtools_protobuf_src| because
+ # we want to depend on the "google/protobuf/descriptor.proto" proto file.
+ # This will be exposed by the |protobuf_descriptor_proto| dep.
+ if buildtools_protobuf_src in target.proto_paths:
+ sources_label.external_deps = [
+ 'PERFETTO_CONFIG.deps.protobuf_descriptor_proto'
+ ]
+
+ if target.name in proto_targets:
+ sources_label.visibility = PUBLIC_VISIBILITY
+ else:
+ sources_label.visibility = ['PERFETTO_CONFIG.proto_library_visibility']
+
+ sources_label.exports = sorted([
+ ':' + get_sources_label(d) for d in target.proto_exports
+ ])
+ return sources_label
+
+ # For all other types of plugins, we need to generate
if target.proto_plugin == 'proto':
plugin_label_type = 'perfetto_cc_proto_library'
elif target.proto_plugin == 'protozero':
@@ -322,28 +315,39 @@
plugin_label_name = get_bazel_label_name(target.name)
plugin_label = BazelLabel(plugin_label_name, plugin_label_type)
plugin_label.comment = target.name
- plugin_label.deps += [':' + sources_label_name]
# When using the plugins we need to pass down also the transitive deps.
# For instance consider foo.proto including common.proto. The generated
# foo.cc will #include "common.gen.h". Hence the generated cc_protocpp_library
# rule need to pass down the dependency on the target that generates
# common.gen.{cc,h}.
- if target.proto_deps and target.proto_plugin in (
- 'cppgen', 'ipc', 'protozero'):
+ if target.proto_plugin in ('cppgen', 'ipc', 'protozero'):
plugin_label.deps += [
':' + get_bazel_label_name(x) for x in target.proto_deps
]
+ # Add any dependencies on source_set targets (i.e. targets containing proto
+ # files). For descriptors, we will have an explicit edge between the
+ # descriptor and source set wheras for other plugin types, this edge is
+ # implicit.
+ if target.proto_plugin == 'descriptor':
+ plugin_label.deps += [
+ ':' + get_sources_label(x) for x in target.proto_deps
+ ]
+ else:
+ plugin_label.deps += [':' + sources_label_name]
+
+ # Since the descriptor generates an explicit output file which can be
+ # referenced by other targets, we specify a name for it.
if target.proto_plugin == 'descriptor':
plugin_label.outs = [plugin_label_name + '.bin']
- return [sources_label, plugin_label]
+ return plugin_label
def gen_target(gn_target):
if gn_target.type == 'proto_library':
- return gen_proto_labels(gn_target)
+ return [gen_proto_label(gn_target)]
elif gn_target.type == 'action':
if gn_target.name in custom_actions:
return custom_actions[gn_target.name](gn_target)
@@ -374,7 +378,7 @@
label.hdrs += [x[2:] for x in gn_target.public_headers]
else:
raise Error('%s: \'public\' currently supported only for cc_library' %
- gn_target.name)
+ gn_target.name)
raw_srcs = [x[2:] for x in gn_target.sources]
if bazel_type == 'perfetto_cc_library':
@@ -511,20 +515,20 @@
for target_name in sorted(proto_targets):
gn.get_target(target_name)
- # Generate targets for the transitive set of proto targets.
- # TODO explain deduping here.
- labels = {}
- for target in sorted(itervalues(gn.proto_libs)):
- for label in gen_target(target):
- # Ensure that if the existing target has public visibility, we preserve
- # that in the new label; this ensures that we don't accidentaly reduce
- # the visibility of targets which are meant to be public.
- existing_label = labels.get(label.name)
- if existing_label and existing_label.visibility == PUBLIC_VISIBILITY:
- label.visibility = PUBLIC_VISIBILITY
- labels[label.name] = label
+ # For any non-source set and non-descriptor targets, ensure the source set
+ # associated to that target is discovered.
+ for target in sorted(itervalues(gn.all_targets)):
+ plugin = target.proto_plugin
+ if plugin is None or plugin == 'source_set' or plugin == 'descriptor':
+ continue
+ gn.get_target(re.sub('(lite|zero|cpp|ipc)$', 'source_set', target.name))
- res += ''.join(str(x) for x in sorted(itervalues(labels)))
+ # Generate targets for the transitive set of proto targets.
+ labels = [
+ l for target in sorted(itervalues(gn.proto_libs))
+ for l in gen_target(target)
+ ]
+ res += ''.join(str(x) for x in sorted(labels))
res += '''
# ##############################################################################
@@ -542,6 +546,7 @@
return res
+
def main():
parser = argparse.ArgumentParser(
description='Generate BUILD from a GN description.')
diff --git a/tools/gn_utils.py b/tools/gn_utils.py
index 2a0f8c6..771d16e 100644
--- a/tools/gn_utils.py
+++ b/tools/gn_utils.py
@@ -310,6 +310,7 @@
# This is typically: 'proto', 'protozero', 'ipc'.
self.proto_plugin = None
self.proto_paths = set()
+ self.proto_exports = set()
self.sources = set()
# TODO(primiano): consider whether the public section should be part of
@@ -395,12 +396,13 @@
target.is_third_party_dep_ = True
return target
- proto_target_type, proto_desc = self.get_proto_target_type_(target)
+ proto_target_type, proto_desc = self.get_proto_target_type(target)
if proto_target_type is not None:
self.proto_libs[target.name] = target
target.type = 'proto_library'
target.proto_plugin = proto_target_type
target.proto_paths.update(self.get_proto_paths(proto_desc))
+ target.proto_exports.update(self.get_proto_exports(proto_desc))
target.sources.update(proto_desc.get('sources', []))
assert (all(x.endswith('.proto') for x in target.sources))
elif target.type == 'source_set':
@@ -444,7 +446,7 @@
target.proto_paths.update(dep.proto_paths)
# Don't bubble deps for action targets
- if target.type != 'action':
+ if target.type != 'action' and proto_target_type != 'descriptor':
target.proto_deps.update(dep.proto_deps) # Bubble up deps.
elif dep.type == 'source_set':
target.source_set_deps.add(dep_name)
@@ -459,24 +461,17 @@
return target
+ def get_proto_exports(self, proto_desc):
+ # exports in metadata will be available for source_set targets.
+ metadata = proto_desc.get('metadata', {})
+ return metadata.get('exports', [])
+
def get_proto_paths(self, proto_desc):
# import_dirs in metadata will be available for source_set targets.
metadata = proto_desc.get('metadata', {})
- import_dirs = metadata.get('import_dirs', [])
- if import_dirs:
- return import_dirs
+ return metadata.get('import_dirs', [])
- # For all non-source-set targets, we need to parse the command line
- # of the protoc invocation.
- proto_paths = []
- args = proto_desc.get('args', [])
- for i, arg in enumerate(args):
- if arg != '--proto_path':
- continue
- proto_paths.append(re.sub('^../../', '//', args[i + 1]))
- return proto_paths
-
- def get_proto_target_type_(self, target):
+ def get_proto_target_type(self, target):
""" Checks if the target is a proto library and return the plugin.
Returns:
@@ -497,7 +492,7 @@
return 'descriptor', desc
# Source set proto targets have a non-empty proto_library_sources in the
- # metadata of the descirption.
+ # metadata of the description.
metadata = desc.get('metadata', {})
if 'proto_library_sources' in metadata:
return 'source_set', desc
diff --git a/tools/heap_profile b/tools/heap_profile
index 6eaaa47..4539dc1 100755
--- a/tools/heap_profile
+++ b/tools/heap_profile
@@ -576,7 +576,7 @@
# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
-# Revision: v23.0
+# Revision: v24.1
PERFETTO_PREBUILT_MANIFEST = [{
'tool':
'trace_to_text',
@@ -585,11 +585,11 @@
'file_name':
'trace_to_text',
'file_size':
- 6939864,
+ 6972736,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/mac-amd64/trace_to_text',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/mac-amd64/trace_to_text',
'sha256':
- '1626880d1fbec8efc9702583b6c22d617079a08226df414d65888a6b3c7572c8',
+ 'cd963e3f63b23977302fcbcb19a9fe64e98aeb2f419ce4212cfafa4e52b8faec',
'platform':
'darwin',
'machine': ['x86_64']
@@ -601,11 +601,11 @@
'file_name':
'trace_to_text.exe',
'file_size':
- 6658560,
+ 6685696,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/windows-amd64/trace_to_text.exe',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/windows-amd64/trace_to_text.exe',
'sha256':
- '14334fc93ecb0498201bf2ad72ebe69938c43cb6641cf94cfd7ad646603039ed',
+ 'bc951b12148338ff151f33af87e79926d18b7ea3180419a7e6c6c150b604fe25',
'platform':
'win32',
'machine': ['amd64']
@@ -617,11 +617,11 @@
'file_name':
'trace_to_text',
'file_size':
- 7513024,
+ 7539312,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/linux-amd64/trace_to_text',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/linux-amd64/trace_to_text',
'sha256':
- 'e19163f152717d9922e1926489b64c50b30ea772ebb0f21f6abb6e8cd25615b3',
+ 'e40fbf44fca2673be1e6aedbc3159ce3cd4f6f33911f9dd1298471bd5b4a05ab',
'platform':
'linux',
'machine': ['x86_64']
diff --git a/tools/record_android_trace b/tools/record_android_trace
index db0cffe..1134a06 100755
--- a/tools/record_android_trace
+++ b/tools/record_android_trace
@@ -226,7 +226,12 @@
if api_level < 24:
# adb shell does not redirect stdin. Push the config on a temporary file
# on the device.
- mktmp = adb('shell', 'mktemp', '--tmpdir', '/data/local/tmp', stdout=subprocess.PIPE)
+ mktmp = adb(
+ 'shell',
+ 'mktemp',
+ '--tmpdir',
+ '/data/local/tmp',
+ stdout=subprocess.PIPE)
on_device_config = mktmp.communicate()[0].decode().strip().strip()
if mktmp.returncode != 0:
prt('Failed to create config on device', ANSI.RED)
@@ -399,7 +404,7 @@
# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
-# Revision: v23.0
+# Revision: v24.1
PERFETTO_PREBUILT_MANIFEST = [{
'tool':
'tracebox',
@@ -408,11 +413,11 @@
'file_name':
'tracebox',
'file_size':
- 1038732,
+ 1046604,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/android-arm/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/android-arm/tracebox',
'sha256':
- 'b37507c28e8eade93fa9f0da86d6b9779f69aadea9d7e33cd3b85866c7b755fc'
+ 'a6ab413ef1aecbe93a73d9e3c9d6f00eb06b4c9886c0627a979a9acbf071a4a3'
}, {
'tool':
'tracebox',
@@ -421,11 +426,11 @@
'file_name':
'tracebox',
'file_size':
- 1572032,
+ 1588032,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/android-arm64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/android-arm64/tracebox',
'sha256':
- '83306c567da4f1b3eb910a0407abf88fcc099d22a191ceb096837381b2ebff79'
+ 'a0da06d2df7106712f90a5475ab8ef994ae844f4fee7bf4f38aaacc8260062cd'
}, {
'tool':
'tracebox',
@@ -434,11 +439,11 @@
'file_name':
'tracebox',
'file_size':
- 1595748,
+ 1615908,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/android-x86/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/android-x86/tracebox',
'sha256':
- '527c2ff54350fe73197b5164e6f7ed21f3d10c38a667e57781222d679dca4707'
+ 'a56591c10f29c00b425ade21d1c61086584166fb00236b9744e3cb06b777fbc8'
}, {
'tool':
'tracebox',
@@ -447,11 +452,11 @@
'file_name':
'tracebox',
'file_size':
- 1821888,
+ 1841984,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/android-x64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/android-x64/tracebox',
'sha256':
- '99cfbb37e7c3ae4ea70fc51811601c409fcd81589d4311a4b805a67f4760203b'
+ '21db734c29f96436685c2a65086e231e03425e35bfdb6fd25a4af729c55c6619'
}]
diff --git a/tools/trace_processor b/tools/trace_processor
index 69e8a91..8bbab28 100755
--- a/tools/trace_processor
+++ b/tools/trace_processor
@@ -27,7 +27,7 @@
TOOL_NAME = 'trace_processor_shell'
# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
-# Revision: v23.0
+# Revision: v24.1
PERFETTO_PREBUILT_MANIFEST = [{
'tool':
'trace_processor_shell',
@@ -36,11 +36,11 @@
'file_name':
'trace_processor_shell',
'file_size':
- 6924224,
+ 6940768,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/mac-amd64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/mac-amd64/trace_processor_shell',
'sha256':
- '08bde02f5920fa1af8dc64b857db9c000ac6940f2bb49030742d62adf04e3ff3',
+ '2d553933fdaba7080ff207094c0ed514a2f5573e525a653417b656b9c9c90e16',
'platform':
'darwin',
'machine': ['x86_64']
@@ -52,11 +52,11 @@
'file_name':
'trace_processor_shell.exe',
'file_size':
- 6656512,
+ 6681600,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/windows-amd64/trace_processor_shell.exe',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/windows-amd64/trace_processor_shell.exe',
'sha256':
- '8151996f74ad7b3e6fb8c04c5acd351a74fe24e939902cc74380e9789c203309',
+ '1f4cb1a8a1726ebbada1f928c7d856a04fd57994077cead0b65c7b32225ba48b',
'platform':
'win32',
'machine': ['amd64']
@@ -68,11 +68,11 @@
'file_name':
'trace_processor_shell',
'file_size':
- 7495496,
+ 7520208,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/linux-amd64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/linux-amd64/trace_processor_shell',
'sha256':
- 'e71bf3c16224a8ecbfb2485864dd3762f642fb052acf560d0631ef6c18a740fd',
+ '232acef777f0b0206d023bf705d1abfd64503a7762e50e813c693dd8bafd91bd',
'platform':
'linux',
'machine': ['x86_64']
@@ -84,11 +84,11 @@
'file_name':
'trace_processor_shell',
'file_size':
- 4867252,
+ 4887472,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/linux-arm/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/linux-arm/trace_processor_shell',
'sha256':
- 'e909add14c46bcc5a2ed1736169886696867cebc17c5218cb9c143caced886f5',
+ 'b03ae322ed90ee7746f5cb33c9a92a82cec34540f3fb1997b343d8cad18db158',
'platform':
'linux',
'machine': ['armv6l', 'armv7l', 'armv8l']
@@ -100,11 +100,11 @@
'file_name':
'trace_processor_shell',
'file_size':
- 6742056,
+ 6765656,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/linux-arm64/trace_processor_shell',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/linux-arm64/trace_processor_shell',
'sha256':
- 'b2cad70adbb139a8878d69999e0dfad40ca24e94f001b7bd67dcbbedcdb6c6dc',
+ '222240d00ca2ae3eac6908df275ca79e2b72ff6a0c934594d2744a2399a58dcc',
'platform':
'linux',
'machine': ['aarch64']
diff --git a/tools/trace_to_text/BUILD.gn b/tools/trace_to_text/BUILD.gn
index 1abb0a8..aa770a8 100644
--- a/tools/trace_to_text/BUILD.gn
+++ b/tools/trace_to_text/BUILD.gn
@@ -15,6 +15,7 @@
import("../../gn/perfetto.gni")
import("../../gn/perfetto_cc_proto_descriptor.gni")
import("../../gn/perfetto_host_executable.gni")
+import("../../gn/test.gni")
import("../../gn/wasm.gni")
perfetto_host_executable("trace_to_text") {
@@ -83,6 +84,23 @@
public_deps = [ ":pprofbuilder" ]
}
+source_set("trace_to_text_lib") {
+ deps = [
+ ":gen_cc_trace_descriptor",
+ ":utils",
+ "../../gn:default_deps",
+ "../../include/perfetto/base",
+ "../../src/protozero:proto_ring_buffer",
+ "../../src/trace_processor:storage_minimal",
+ "../../src/trace_processor/util:gzip",
+ ]
+ sources = [
+ "proto_full_utils.h",
+ "trace_to_text.cc",
+ "trace_to_text.h",
+ ]
+}
+
# The core source files that are used both by the "full" version (the host
# executable) and by the "lite" version (the WASM module for the UI).
source_set("common") {
@@ -132,12 +150,11 @@
testonly = true
deps = [
":common",
- ":gen_cc_trace_descriptor",
+ ":trace_to_text_lib",
":utils",
"../../gn:default_deps",
"../../gn:protobuf_full",
"../../protos/perfetto/trace:zero",
- "../../src/protozero:proto_ring_buffer",
]
if (enable_perfetto_zlib) {
deps += [ "../../gn:zlib" ]
@@ -145,7 +162,6 @@
sources = [
"proto_full_utils.cc",
"proto_full_utils.h",
- "trace_to_text.cc",
]
}
@@ -163,3 +179,16 @@
descriptor_name = "trace.descriptor"
descriptor_target = "../../protos/perfetto/trace:descriptor"
}
+
+perfetto_unittest_source_set("unittests") {
+ testonly = true
+ deps = [
+ ":trace_to_text_lib",
+ "../../gn:default_deps",
+ "../../gn:gtest_and_gmock",
+ "../../gn:protobuf_full",
+ "../../include/perfetto/base",
+ "../../include/perfetto/ext/base:base",
+ ]
+ sources = [ "trace_to_text_unittest.cc" ]
+}
diff --git a/tools/trace_to_text/lite_fallbacks.cc b/tools/trace_to_text/lite_fallbacks.cc
index 82e09ff..e208a12 100644
--- a/tools/trace_to_text/lite_fallbacks.cc
+++ b/tools/trace_to_text/lite_fallbacks.cc
@@ -24,7 +24,7 @@
namespace perfetto {
namespace trace_to_text {
-int TraceToText(std::istream*, std::ostream*) {
+bool TraceToText(std::istream*, std::ostream*) {
PERFETTO_FATAL(
"The 'text' command is not available in lite builds of trace_to_text");
}
diff --git a/tools/trace_to_text/main.cc b/tools/trace_to_text/main.cc
index e4a9f1d..dfd75b6 100644
--- a/tools/trace_to_text/main.cc
+++ b/tools/trace_to_text/main.cc
@@ -187,8 +187,9 @@
return 1;
}
- if (format == "text")
- return TraceToText(input_stream, output_stream);
+ if (format == "text") {
+ return TraceToText(input_stream, output_stream) ? 0 : 1;
+ }
if (format == "profile") {
return perf_profile
diff --git a/tools/trace_to_text/trace_to_text.cc b/tools/trace_to_text/trace_to_text.cc
index 7507c75..2ddf713 100644
--- a/tools/trace_to_text/trace_to_text.cc
+++ b/tools/trace_to_text/trace_to_text.cc
@@ -31,9 +31,8 @@
#include "protos/perfetto/trace/trace.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
-#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
-#include <zlib.h>
-#endif
+#include "src/trace_processor/forwarding_trace_parser.h"
+#include "src/trace_processor/util/gzip_utils.h"
namespace perfetto {
namespace trace_to_text {
@@ -50,6 +49,8 @@
using google::protobuf::TextFormat;
using google::protobuf::io::OstreamOutputStream;
using google::protobuf::io::ZeroCopyOutputStream;
+using trace_processor::TraceType;
+using trace_processor::util::GzipDecompressor;
inline void WriteToZeroCopyOutput(ZeroCopyOutputStream* output,
const char* str,
@@ -83,34 +84,9 @@
Message* compressed_msg_scratch,
ZeroCopyOutputStream* output) {
#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
- uint8_t out[4096];
- std::vector<uint8_t> data;
-
- z_stream stream{};
- stream.next_in =
- const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(packets.data()));
- stream.avail_in = static_cast<unsigned int>(packets.length());
-
- if (inflateInit(&stream) != Z_OK) {
- PERFETTO_ELOG("Error when initiliazing zlib to decompress packets");
- return;
- }
-
- int ret;
- do {
- stream.next_out = out;
- stream.avail_out = sizeof(out);
- ret = inflate(&stream, Z_NO_FLUSH);
- if (ret != Z_STREAM_END && ret != Z_OK) {
- PERFETTO_ELOG("Error when decompressing packets: %s",
- (stream.msg ? stream.msg : ""));
- return;
- }
- data.insert(data.end(), out, out + (sizeof(out) - stream.avail_out));
- } while (ret != Z_STREAM_END);
- inflateEnd(&stream);
-
- protos::pbzero::Trace::Decoder decoder(data.data(), data.size());
+ std::vector<uint8_t> whole_data = GzipDecompressor::DecompressFully(
+ reinterpret_cast<const uint8_t*>(packets.data()), packets.size());
+ protos::pbzero::Trace::Decoder decoder(whole_data.data(), whole_data.size());
WriteToZeroCopyOutput(output, kCompressedPacketsPrefix,
sizeof(kCompressedPacketsPrefix) - 1);
TextFormat::Printer printer;
@@ -146,90 +122,171 @@
#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
}
-} // namespace
-
-int TraceToText(std::istream* input, std::ostream* output) {
- DescriptorPool pool;
+// TracePacket descriptor and metadata, used to print a TracePacket proto as a
+// text proto.
+struct TracePacketProtoDescInfo {
+ TracePacketProtoDescInfo();
FileDescriptorSet desc_set;
+ DescriptorPool pool;
+ std::unique_ptr<DynamicMessageFactory> factory;
+ const Descriptor* trace_descriptor;
+ const Message* prototype;
+ const FieldDescriptor* compressed_desc;
+};
+
+TracePacketProtoDescInfo::TracePacketProtoDescInfo() {
desc_set.ParseFromArray(kTraceDescriptor.data(), kTraceDescriptor.size());
for (const auto& desc : desc_set.file()) {
pool.BuildFile(desc);
}
-
- DynamicMessageFactory factory(&pool);
- const Descriptor* trace_descriptor =
- pool.FindMessageTypeByName("perfetto.protos.TracePacket");
- const Message* prototype = factory.GetPrototype(trace_descriptor);
- std::unique_ptr<Message> msg(prototype->New());
-
- OstreamOutputStream zero_copy_output(output);
- OstreamOutputStream* zero_copy_output_ptr = &zero_copy_output;
-
- const Reflection* reflect = msg->GetReflection();
- const FieldDescriptor* compressed_desc = trace_descriptor->FindFieldByNumber(
+ factory.reset(new DynamicMessageFactory(&pool));
+ trace_descriptor = pool.FindMessageTypeByName("perfetto.protos.TracePacket");
+ prototype = factory->GetPrototype(trace_descriptor);
+ compressed_desc = trace_descriptor->FindFieldByNumber(
protos::pbzero::TracePacket::kCompressedPacketsFieldNumber);
+}
- std::unique_ptr<Message> compressed_packets_msg(prototype->New());
- std::string compressed_packets;
+// Online algorithm to covert trace binary to text format.
+// Usage:
+// - Feed the trace-binary in a sequence of memblock, and it will continue to
+// write the output in given std::ostream*.
+class OnlineTraceToText {
+ public:
+ OnlineTraceToText(std::ostream* output)
+ : zero_copy_out_stream_(output),
+ msg_(pb_desc_info_.prototype->New()),
+ compressed_packets_msg_(pb_desc_info_.prototype->New()),
+ reflect_(msg_->GetReflection()) {
+ printer_.SetInitialIndentLevel(1);
+ }
+ OnlineTraceToText(const OnlineTraceToText&) = delete;
+ OnlineTraceToText& operator=(const OnlineTraceToText&) = delete;
+ void Feed(const uint8_t* data, size_t len);
+ bool ok() const { return ok_; }
- TextFormat::Printer printer;
- printer.SetInitialIndentLevel(1);
+ private:
+ bool ok_ = true;
+ OstreamOutputStream zero_copy_out_stream_;
+ protozero::ProtoRingBuffer ring_buffer_;
+ TextFormat::Printer printer_;
+ TracePacketProtoDescInfo pb_desc_info_;
+ std::unique_ptr<Message> msg_;
+ std::unique_ptr<Message> compressed_packets_msg_;
+ const Reflection* reflect_;
+ std::string compressed_packets_;
+ size_t bytes_processed_ = 0;
+ size_t packet_ = 0;
+};
- static constexpr size_t kMaxMsgSize = protozero::ProtoRingBuffer::kMaxMsgSize;
- std::unique_ptr<char[]> data(new char[kMaxMsgSize]);
- protozero::ProtoRingBuffer ring_buffer;
-
- uint32_t packet = 0;
- size_t bytes_processed = 0;
- while (!input->eof()) {
- input->read(data.get(), kMaxMsgSize);
- if (input->bad() || (input->fail() && !input->eof())) {
- PERFETTO_ELOG("Failed while reading trace");
- return 1;
+void OnlineTraceToText::Feed(const uint8_t* data, size_t len) {
+ ring_buffer_.Append(data, static_cast<size_t>(len));
+ while (true) {
+ auto token = ring_buffer_.ReadMessage();
+ if (token.fatal_framing_error) {
+ PERFETTO_ELOG("Failed to tokenize trace packet");
+ ok_ = false;
+ return;
}
- ring_buffer.Append(data.get(), static_cast<size_t>(input->gcount()));
+ if (!token.valid()) {
+ // no need to set `ok_ = false` here because this just means
+ // we've run out of packets in the ring buffer.
+ break;
+ }
- for (;;) {
- auto token = ring_buffer.ReadMessage();
- if (token.fatal_framing_error) {
- PERFETTO_ELOG("Failed to tokenize trace packet");
- return 1;
- }
- if (!token.valid())
- break;
- bytes_processed += token.len;
-
- if (token.field_id != protos::pbzero::Trace::kPacketFieldNumber) {
- PERFETTO_ELOG("Skipping invalid field");
- continue;
- }
-
- if ((packet++ & 0x3f) == 0) {
- fprintf(stderr, "Processing trace: %8zu KB%c", bytes_processed / 1024,
- kProgressChar);
- fflush(stderr);
- }
-
- if (!msg->ParseFromArray(token.start, static_cast<int>(token.len))) {
- PERFETTO_ELOG("Skipping invalid packet");
- continue;
- }
-
- if (reflect->HasField(*msg, compressed_desc)) {
- compressed_packets = reflect->GetStringReference(*msg, compressed_desc,
- &compressed_packets);
- PrintCompressedPackets(compressed_packets, compressed_packets_msg.get(),
- zero_copy_output_ptr);
- } else {
- WriteToZeroCopyOutput(zero_copy_output_ptr, kPacketPrefix,
- sizeof(kPacketPrefix) - 1);
- printer.Print(*msg, zero_copy_output_ptr);
- WriteToZeroCopyOutput(zero_copy_output_ptr, kPacketSuffix,
- sizeof(kPacketSuffix) - 1);
- }
+ if (token.field_id != protos::pbzero::Trace::kPacketFieldNumber) {
+ PERFETTO_ELOG("Skipping invalid field");
+ continue;
+ }
+ if (!msg_->ParseFromArray(token.start, static_cast<int>(token.len))) {
+ PERFETTO_ELOG("Skipping invalid packet");
+ continue;
+ }
+ bytes_processed_ += token.len;
+ if ((packet_++ & 0x3f) == 0) {
+ fprintf(stderr, "Processing trace: %8zu KB%c", bytes_processed_ / 1024,
+ kProgressChar);
+ fflush(stderr);
+ }
+ if (reflect_->HasField(*msg_, pb_desc_info_.compressed_desc)) {
+ // TODO(mohitms): GetStringReference ignores third argument. Why are we
+ // passing ?
+ compressed_packets_ = reflect_->GetStringReference(
+ *msg_, pb_desc_info_.compressed_desc, &compressed_packets_);
+ PrintCompressedPackets(compressed_packets_, compressed_packets_msg_.get(),
+ &zero_copy_out_stream_);
+ } else {
+ WriteToZeroCopyOutput(&zero_copy_out_stream_, kPacketPrefix,
+ sizeof(kPacketPrefix) - 1);
+ printer_.Print(*msg_, &zero_copy_out_stream_);
+ WriteToZeroCopyOutput(&zero_copy_out_stream_, kPacketSuffix,
+ sizeof(kPacketSuffix) - 1);
}
}
- return 0;
+}
+
+class InputReader {
+ public:
+ InputReader(std::istream* input) : input_(input) {}
+ // Request the input-stream to read next |len_limit| bytes and load
+ // it in |data|. It also updates the |len| with actual number of bytes loaded
+ // in |data|. This can be less than requested |len_limit| if we have reached
+ // at the end of the file.
+ bool Read(uint8_t* data, uint32_t* len, uint32_t len_limit) {
+ if (input_->eof())
+ return false;
+ input_->read(reinterpret_cast<char*>(data), std::streamsize(len_limit));
+ if (input_->bad() || (input_->fail() && !input_->eof())) {
+ PERFETTO_ELOG("Failed while reading trace");
+ ok_ = false;
+ return false;
+ }
+ *len = uint32_t(input_->gcount());
+ return true;
+ }
+ bool ok() const { return ok_; }
+
+ private:
+ std::istream* input_;
+ bool ok_ = true;
+};
+
+} // namespace
+
+bool TraceToText(std::istream* input, std::ostream* output) {
+ constexpr size_t kMaxMsgSize = protozero::ProtoRingBuffer::kMaxMsgSize;
+ std::unique_ptr<uint8_t[]> buffer(new uint8_t[kMaxMsgSize]);
+ uint32_t buffer_len = 0;
+
+ InputReader input_reader(input);
+ OnlineTraceToText online_trace_to_text(output);
+
+ input_reader.Read(buffer.get(), &buffer_len, kMaxMsgSize);
+ TraceType type = trace_processor::GuessTraceType(buffer.get(), buffer_len);
+
+ if (type == TraceType::kGzipTraceType) {
+ GzipDecompressor decompressor;
+ auto consumer = [&](const uint8_t* data, size_t len) {
+ online_trace_to_text.Feed(data, len);
+ };
+ using ResultCode = GzipDecompressor::ResultCode;
+ do {
+ ResultCode code =
+ decompressor.FeedAndExtract(buffer.get(), buffer_len, consumer);
+ if (code == ResultCode::kError || !online_trace_to_text.ok())
+ return false;
+ } while (input_reader.Read(buffer.get(), &buffer_len, kMaxMsgSize));
+ return input_reader.ok();
+ } else if (type == TraceType::kProtoTraceType) {
+ do {
+ online_trace_to_text.Feed(buffer.get(), buffer_len);
+ if (!online_trace_to_text.ok())
+ return false;
+ } while (input_reader.Read(buffer.get(), &buffer_len, kMaxMsgSize));
+ return input_reader.ok();
+ } else {
+ PERFETTO_ELOG("Unrecognised file.");
+ return false;
+ }
}
} // namespace trace_to_text
diff --git a/tools/trace_to_text/trace_to_text.h b/tools/trace_to_text/trace_to_text.h
index 2be24ad..d0f35e0 100644
--- a/tools/trace_to_text/trace_to_text.h
+++ b/tools/trace_to_text/trace_to_text.h
@@ -22,7 +22,8 @@
namespace perfetto {
namespace trace_to_text {
-int TraceToText(std::istream* input, std::ostream* output);
+// Returns true in case of success.
+bool TraceToText(std::istream* input, std::ostream* output);
} // namespace trace_to_text
} // namespace perfetto
diff --git a/tools/trace_to_text/trace_to_text_unittest.cc b/tools/trace_to_text/trace_to_text_unittest.cc
new file mode 100644
index 0000000..0066c0c
--- /dev/null
+++ b/tools/trace_to_text/trace_to_text_unittest.cc
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "tools/trace_to_text/trace_to_text.h"
+
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/hash.h"
+#include "test/gtest_and_gmock.h"
+
+#include <fstream>
+
+using std::string;
+
+namespace perfetto {
+namespace trace_to_text {
+
+// Given a file, compute the checksum/hash of file.
+// Learn more @ base::Hash.
+// Precondition: File should exist and be accessible.
+static uint64_t FileHash(const string& filename) {
+ base::Hash hash;
+ std::ifstream input_f(filename, std::ios::binary);
+ PERFETTO_DCHECK(input_f.good());
+ char buffer[4096];
+ while (!input_f.eof()) {
+ input_f.read(buffer, sizeof(buffer));
+ if (input_f.gcount() > 0) {
+ hash.Update(buffer, size_t(input_f.gcount()));
+ }
+ }
+ return hash.digest();
+}
+
+TEST(TraceToText, DISABLED_Basic) {
+ auto tmp_file = "/tmp/trace_" + std::to_string(rand()) + ".txt";
+ auto input_file_names = {"test/data/example_android_trace_30s.pb.gz",
+ "test/data/example_android_trace_30s.pb"};
+ PERFETTO_LOG("tmp_file = %s.", tmp_file.c_str());
+ for (auto filename : input_file_names) {
+ {
+ std::ifstream input_f(filename, std::ios::binary);
+ std::ofstream output_f(tmp_file, std::ios::out | std::ios::binary);
+ EXPECT_TRUE(TraceToText(&input_f, &output_f));
+ PERFETTO_LOG("Processed %s", filename);
+ }
+ EXPECT_EQ(0xCD794377594BC7DCull, FileHash(tmp_file));
+ remove(tmp_file.c_str());
+ }
+}
+
+} // namespace trace_to_text
+} // namespace perfetto
diff --git a/tools/tracebox b/tools/tracebox
index ece2014..e7b1253 100755
--- a/tools/tracebox
+++ b/tools/tracebox
@@ -27,7 +27,7 @@
TOOL_NAME = 'tracebox'
# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
-# Revision: v23.0
+# Revision: v24.1
PERFETTO_PREBUILT_MANIFEST = [{
'tool':
'tracebox',
@@ -36,11 +36,11 @@
'file_name':
'tracebox',
'file_size':
- 1316192,
+ 1332696,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/mac-amd64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/mac-amd64/tracebox',
'sha256':
- '54101d81876ceed8c2d24701835fd11cd0edc4d43af655ed0420013809138951',
+ 'be14a9040e8d0143d5b0838560cf20afb0be2d1971f6df4c79d7b4c46aa5852e',
'platform':
'darwin',
'machine': ['x86_64']
@@ -52,11 +52,11 @@
'file_name':
'tracebox',
'file_size':
- 1739352,
+ 1756264,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/linux-amd64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/linux-amd64/tracebox',
'sha256':
- 'b42cfaadf4dd35c5c540775a0d909dcbfa5338d1c022767db3a4b1324c19e58b',
+ '2fde750c982826f6a7c3e49b2d6ee7ec72c956170b4bba07e2989f2b81f26269',
'platform':
'linux',
'machine': ['x86_64']
@@ -68,11 +68,11 @@
'file_name':
'tracebox',
'file_size':
- 1739352,
+ 1756264,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/linux-amd64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/linux-amd64/tracebox',
'sha256':
- 'b42cfaadf4dd35c5c540775a0d909dcbfa5338d1c022767db3a4b1324c19e58b',
+ '2fde750c982826f6a7c3e49b2d6ee7ec72c956170b4bba07e2989f2b81f26269',
'platform':
'linux',
'machine': ['x86_64']
@@ -84,11 +84,11 @@
'file_name':
'tracebox',
'file_size':
- 1002132,
+ 1012940,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/linux-arm/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/linux-arm/tracebox',
'sha256':
- '65351d250c3c52f8a69afa78069d9a87931c45cf3bf415c207e93de6eb75dbbe',
+ 'a6f964b1b155c309fda0fb0b765f9fbf3d030d8c4bd6f9f03dad173ee689668e',
'platform':
'linux',
'machine': ['armv6l', 'armv7l', 'armv8l']
@@ -100,11 +100,11 @@
'file_name':
'tracebox',
'file_size':
- 1619248,
+ 1635160,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/linux-arm64/tracebox',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/linux-arm64/tracebox',
'sha256':
- '2cb0be71da6b46167a8dd4a9d8af5229dba89b8e508554c16cde20b81f175d3d',
+ 'ed998b18606a6cffb490336990220e6290faa4544e52a5c77273f69507f80e89',
'platform':
'linux',
'machine': ['aarch64']
diff --git a/tools/traceconv b/tools/traceconv
index 4754a87..663ad5a 100755
--- a/tools/traceconv
+++ b/tools/traceconv
@@ -27,7 +27,7 @@
TOOL_NAME = 'trace_to_text'
# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
-# Revision: v23.0
+# Revision: v24.1
PERFETTO_PREBUILT_MANIFEST = [{
'tool':
'trace_to_text',
@@ -36,11 +36,11 @@
'file_name':
'trace_to_text',
'file_size':
- 6939864,
+ 6972736,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/mac-amd64/trace_to_text',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/mac-amd64/trace_to_text',
'sha256':
- '1626880d1fbec8efc9702583b6c22d617079a08226df414d65888a6b3c7572c8',
+ 'cd963e3f63b23977302fcbcb19a9fe64e98aeb2f419ce4212cfafa4e52b8faec',
'platform':
'darwin',
'machine': ['x86_64']
@@ -52,11 +52,11 @@
'file_name':
'trace_to_text',
'file_size':
- 7513024,
+ 7539312,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/linux-amd64/trace_to_text',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/linux-amd64/trace_to_text',
'sha256':
- 'e19163f152717d9922e1926489b64c50b30ea772ebb0f21f6abb6e8cd25615b3',
+ 'e40fbf44fca2673be1e6aedbc3159ce3cd4f6f33911f9dd1298471bd5b4a05ab',
'platform':
'linux',
'machine': ['x86_64']
@@ -68,11 +68,11 @@
'file_name':
'trace_to_text.exe',
'file_size':
- 6658560,
+ 6685696,
'url':
- 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v23.0/windows-amd64/trace_to_text.exe',
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v24.1/windows-amd64/trace_to_text.exe',
'sha256':
- '14334fc93ecb0498201bf2ad72ebe69938c43cb6641cf94cfd7ad646603039ed',
+ 'bc951b12148338ff151f33af87e79926d18b7ea3180419a7e6c6c150b604fe25',
'platform':
'win32',
'machine': ['amd64']
diff --git a/ui/src/assets/common.scss b/ui/src/assets/common.scss
index c98a6a1..4aeb978 100644
--- a/ui/src/assets/common.scss
+++ b/ui/src/assets/common.scss
@@ -606,6 +606,9 @@
.track-button {
color: white;
}
+ span.chip {
+ color: #121212;
+ }
}
.shell {
padding: 4px 4px;
@@ -720,6 +723,15 @@
&.query-error {
color: red;
}
+
+ .total-values {
+ text-align: right;
+ padding-right: 10px;
+ }
+
+ .empty-result {
+ padding: 10px;
+ }
}
.pivot-table-editor-container {
diff --git a/ui/src/assets/details.scss b/ui/src/assets/details.scss
index a191ffa..ab9a458 100644
--- a/ui/src/assets/details.scss
+++ b/ui/src/assets/details.scss
@@ -21,6 +21,9 @@
border: 1px solid rgba(0,0,0,0.1);
border-bottom: none;
cursor: row-resize;
+ // Disable user selection since this handle is draggable to resize the
+ // bottom panels.
+ user-select: none;
height: 28px;
min-height: 28px;
display: grid;
diff --git a/ui/src/base/string_utils.ts b/ui/src/base/string_utils.ts
index 019de9e..27e2614 100644
--- a/ui/src/base/string_utils.ts
+++ b/ui/src/base/string_utils.ts
@@ -96,3 +96,14 @@
}
return buf;
}
+
+// A function used to interpolate strings into SQL query. The only replacement
+// is done is that single quote replaced with two single quotes, according to
+// SQLite documentation:
+// https://www.sqlite.org/lang_expr.html#literal_values_constants_
+//
+// The purpose of this function is to use in simple comparisons, to escape
+// strings used in GLOB clauses see escapeQuery function.
+export function sqliteString(str: string): string {
+ return `'${str.replace('\'', '\'\'')}'`;
+}
diff --git a/ui/src/base/string_utils_unittest.ts b/ui/src/base/string_utils_unittest.ts
index c8dce8e..4265a62 100644
--- a/ui/src/base/string_utils_unittest.ts
+++ b/ui/src/base/string_utils_unittest.ts
@@ -17,6 +17,7 @@
base64Encode,
binaryDecode,
binaryEncode,
+ sqliteString,
utf8Decode,
utf8Encode,
} from './string_utils';
@@ -73,3 +74,8 @@
expect(binaryDecode(encodedStr)).toEqual(buf);
expect(binaryDecode(encodedThroughJson)).toEqual(buf);
});
+
+test('string_utils.sqliteString', () => {
+ expect(sqliteString('that\'s it')).toEqual('\'that\'\'s it\'');
+ expect(sqliteString('no quotes')).toEqual('\'no quotes\'');
+});
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index 768493a..76d2dd3 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -917,8 +917,8 @@
}
},
- togglePivotTableRedux(state: StateDraft, args: {enabled: boolean}) {
- state.pivotTableRedux.enabled = args.enabled;
+ togglePivotTableRedux(state: StateDraft, args: {selectionArea: Area|null}) {
+ state.pivotTableRedux.selectionArea = args.selectionArea;
},
addNewPivotTable(state: StateDraft, args: {
@@ -946,7 +946,9 @@
resetPivotTableRequest(state: StateDraft, args: {pivotTableId: string}):
void {
- state.pivotTable[args.pivotTableId].requestedAction = undefined;
+ if (state.pivotTable[args.pivotTableId] !== undefined) {
+ state.pivotTable[args.pivotTableId].requestedAction = undefined;
+ }
},
setPivotTableRequest(
diff --git a/ui/src/common/empty_state.ts b/ui/src/common/empty_state.ts
index 2b9396e..cc57df5 100644
--- a/ui/src/common/empty_state.ts
+++ b/ui/src/common/empty_state.ts
@@ -103,6 +103,6 @@
fetchChromeCategories: false,
chromeCategories: undefined,
pivotTableRedux:
- {enabled: false, query: null, queryId: 0, queryResult: null},
+ {selectionArea: null, query: null, queryId: 0, queryResult: null},
};
}
\ No newline at end of file
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index db5e9c6..19f6a2e 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -335,6 +335,7 @@
// correctly. Generated together with the text of query and passed without the
// change to the query response.
export interface PivotTableReduxQueryMetadata {
+ tableName: string;
pivotColumns: string[];
aggregationColumns: string[];
}
@@ -355,8 +356,8 @@
}
export interface PivotTableReduxState {
- // Whether the panel should be visible
- enabled: boolean;
+ // Currently selected area, if null, pivot table is not going to be visible.
+ selectionArea: Area|null;
// Increasing identifier of the query request, used to avoid performing the
// same query more than once.
queryId: number;
diff --git a/ui/src/controller/aggregation/slice_aggregation_controller.ts b/ui/src/controller/aggregation/slice_aggregation_controller.ts
index 8646c45..313e0ce 100644
--- a/ui/src/controller/aggregation/slice_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/slice_aggregation_controller.ts
@@ -57,26 +57,31 @@
{pivotTableId: SLICE_AGGREGATION_PIVOT_TABLE_ID, action: 'QUERY'}));
}
+export function getSelectedTrackIds(area: Area): number[] {
+ const selectedTrackIds = [];
+ for (const trackId of area.tracks) {
+ const track = globals.state.tracks[trackId];
+ // Track will be undefined for track groups.
+ if (track !== undefined) {
+ if (track.kind === SLICE_TRACK_KIND) {
+ selectedTrackIds.push((track.config as SliceConfig).trackId);
+ }
+ if (track.kind === ASYNC_SLICE_TRACK_KIND) {
+ const config = track.config as AsyncSliceConfig;
+ for (const id of config.trackIds) {
+ selectedTrackIds.push(id);
+ }
+ }
+ }
+ }
+ return selectedTrackIds;
+}
+
export class SliceAggregationController extends AggregationController {
async createAggregateView(engine: Engine, area: Area) {
await engine.query(`drop view if exists ${this.kind};`);
- const selectedTrackIds = [];
- for (const trackId of area.tracks) {
- const track = globals.state.tracks[trackId];
- // Track will be undefined for track groups.
- if (track !== undefined) {
- if (track.kind === SLICE_TRACK_KIND) {
- selectedTrackIds.push((track.config as SliceConfig).trackId);
- }
- if (track.kind === ASYNC_SLICE_TRACK_KIND) {
- const config = track.config as AsyncSliceConfig;
- for (const id of config.trackIds) {
- selectedTrackIds.push(id);
- }
- }
- }
- }
+ const selectedTrackIds = getSelectedTrackIds(area);
if (selectedTrackIds.length === 0) return false;
diff --git a/ui/src/controller/pivot_table_redux_controller.ts b/ui/src/controller/pivot_table_redux_controller.ts
index 59a4c1b..5e37e52 100644
--- a/ui/src/controller/pivot_table_redux_controller.ts
+++ b/ui/src/controller/pivot_table_redux_controller.ts
@@ -2,6 +2,10 @@
import {Engine} from '../common/engine';
import {featureFlags} from '../common/feature_flags';
import {ColumnType} from '../common/query_result';
+import {
+ PivotTableReduxQueryMetadata,
+ PivotTableReduxResult
+} from '../common/state';
import {aggregationIndex} from '../frontend/pivot_table_redux_query_generator';
import {Controller} from './controller';
@@ -98,6 +102,20 @@
}
}
+function createEmptyQueryResult(metadata: PivotTableReduxQueryMetadata):
+ PivotTableReduxResult {
+ return {
+ tree: {
+ aggregates: [],
+ isCollapsed: false,
+ children: new Map(),
+ rows: [],
+ },
+ metadata
+ };
+}
+
+
// Controller responsible for showing the panel with pivot table, as well as
// executing its queries and post-processing query results.
export class PivotTableReduxController extends Controller<{}> {
@@ -115,9 +133,6 @@
return;
}
- const selection = globals.state.currentSelection;
- const hasSelection = selection !== null;
-
const pivotTableState = globals.state.pivotTableRedux;
if (pivotTableState.queryId > this.lastStartedQueryId &&
pivotTableState.query !== null) {
@@ -143,6 +158,21 @@
it.next();
return row;
}
+
+ if (!it.valid()) {
+ // Iterator is invalid after creation; means that there are no rows
+ // satisfying filtering criteria. Return an empty tree.
+ globals.dispatch(Actions.setPivotStateReduxState({
+ pivotTableState: {
+ queryId: this.lastStartedQueryId,
+ query: null,
+ queryResult: createEmptyQueryResult(query.metadata),
+ selectionArea: pivotTableState.selectionArea
+ }
+ }));
+ return;
+ }
+
const treeBuilder = new TreeBuilder(
query.metadata.pivotColumns.length,
query.metadata.aggregationColumns.length,
@@ -159,12 +189,19 @@
tree: treeBuilder.build(),
metadata: query.metadata,
},
- enabled: true
+ selectionArea: pivotTableState.selectionArea
}
}));
});
}
- globals.dispatch(Actions.togglePivotTableRedux({enabled: hasSelection}));
+ const selection = globals.state.currentSelection;
+ if (selection !== null && selection.kind === 'AREA') {
+ const enabledArea = globals.state.areas[selection.areaId];
+ globals.dispatch(
+ Actions.togglePivotTableRedux({selectionArea: enabledArea}));
+ } else {
+ globals.dispatch(Actions.togglePivotTableRedux({selectionArea: null}));
+ }
}
}
\ No newline at end of file
diff --git a/ui/src/frontend/details_panel.ts b/ui/src/frontend/details_panel.ts
index 0088e33..9c8969a 100644
--- a/ui/src/frontend/details_panel.ts
+++ b/ui/src/frontend/details_panel.ts
@@ -327,11 +327,13 @@
});
}
- if (globals.state.pivotTableRedux.enabled) {
+ if (globals.state.pivotTableRedux.selectionArea !== null) {
detailsPanels.push({
key: 'pivot_table_redux',
name: 'Pivot Table',
- vnode: m(PivotTableRedux)
+ vnode:
+ m(PivotTableRedux,
+ {selectionArea: globals.state.pivotTableRedux.selectionArea})
});
}
diff --git a/ui/src/frontend/pivot_table_redux.ts b/ui/src/frontend/pivot_table_redux.ts
index c2c129a..ea2b7d3 100644
--- a/ui/src/frontend/pivot_table_redux.ts
+++ b/ui/src/frontend/pivot_table_redux.ts
@@ -1,14 +1,20 @@
import * as m from 'mithril';
+import {sqliteString} from '../base/string_utils';
import {Actions} from '../common/actions';
import {ColumnType} from '../common/query_result';
-import {PivotTableReduxQuery, PivotTableReduxResult} from '../common/state';
+import {
+ Area,
+ PivotTableReduxQuery,
+ PivotTableReduxResult
+} from '../common/state';
import {PivotTree} from '../controller/pivot_table_redux_controller';
import {globals} from './globals';
import {Panel} from './panel';
import {
aggregationIndex,
+ areaFilter,
ColumnSet,
generateQuery,
QueryGeneratorError,
@@ -48,26 +54,50 @@
}
}
-export class PivotTableRedux extends Panel {
+interface PivotTableReduxAttrs {
+ selectionArea: Area;
+}
+
+interface DrillFilter {
+ column: string;
+ value: ColumnType;
+}
+
+// Convert DrillFilter to SQL condition to be used in WHERE clause.
+function renderDrillFilter(filter: DrillFilter): string {
+ if (filter.value === null) {
+ return `${filter.column} IS NULL`;
+ } else if (typeof filter.value === 'number') {
+ return `${filter.column} = ${filter.value}`;
+ }
+ return `${filter.column} = ${sqliteString(filter.value)}`;
+}
+
+export class PivotTableRedux extends Panel<PivotTableReduxAttrs> {
selectedPivotsMap = new ColumnSet();
selectedAggregations = new ColumnSet();
+ constrainToArea = true;
editMode = true;
renderCanvas(): void {}
- generateQuery(): PivotTableReduxQuery {
- return generateQuery(this.selectedPivotsMap, this.selectedAggregations);
+ generateQuery(attrs: PivotTableReduxAttrs): PivotTableReduxQuery {
+ return generateQuery(
+ this.selectedPivotsMap,
+ this.selectedAggregations,
+ attrs.selectionArea,
+ this.constrainToArea);
}
- runQuery() {
+ runQuery(attrs: PivotTableReduxAttrs) {
try {
- const query = this.generateQuery();
+ const query = this.generateQuery(attrs);
const lastPivotTableState = globals.state.pivotTableRedux;
globals.dispatch(Actions.setPivotStateReduxState({
pivotTableState: {
query,
queryId: lastPivotTableState.queryId + 1,
- enabled: true,
+ selectionArea: lastPivotTableState.selectionArea,
queryResult: null
}
}));
@@ -91,7 +121,7 @@
col))));
}
- renderResultsView() {
+ renderResultsView(attrs: PivotTableReduxAttrs) {
return m(
'.pivot-table-redux',
m('button.mode-button',
@@ -102,11 +132,39 @@
}
},
'Edit'),
- this.renderResultsTable());
+ this.renderResultsTable(attrs));
+ }
+
+ renderDrillDownCell(
+ area: Area, result: PivotTableReduxResult, filters: DrillFilter[]) {
+ return m(
+ 'td',
+ m('button',
+ {
+ title: 'All corresponding slices',
+ onclick: () => {
+ const queryFilters = filters.map(renderDrillFilter);
+ if (this.constrainToArea) {
+ queryFilters.push(areaFilter(area));
+ }
+ const query = `
+ select * from ${result.metadata.tableName}
+ where ${queryFilters.join(' and \n')}
+ `;
+ // TODO(ddrone): the UI of running query as if it was a canned or
+ // custom query is a temporary one, replace with a proper UI.
+ globals.dispatch(Actions.executeQuery({
+ engineId: '0',
+ queryId: 'command',
+ query,
+ }));
+ }
+ },
+ m('i.material-icons', 'arrow_right')));
}
renderSectionRow(
- path: PathItem[], tree: PivotTree,
+ area: Area, path: PathItem[], tree: PivotTree,
result: PivotTableReduxResult): m.Vnode {
const renderedCells = [];
for (let j = 0; j + 1 < path.length; j++) {
@@ -133,25 +191,34 @@
renderedCells.push(m('td', `${value}`));
}
+ const drillFilters: DrillFilter[] = [];
+ for (let i = 0; i < path.length; i++) {
+ drillFilters.push({
+ value: `${path[i].nextKey}`,
+ column: result.metadata.pivotColumns[i]
+ });
+ }
+
+ renderedCells.push(this.renderDrillDownCell(area, result, drillFilters));
return m('tr', renderedCells);
}
renderTree(
- path: PathItem[], tree: PivotTree, result: PivotTableReduxResult,
- sink: m.Vnode[]) {
+ area: Area, path: PathItem[], tree: PivotTree,
+ result: PivotTableReduxResult, sink: m.Vnode[]) {
if (tree.isCollapsed) {
- sink.push(this.renderSectionRow(path, tree, result));
+ sink.push(this.renderSectionRow(area, path, tree, result));
return;
}
if (tree.children.size > 0) {
// Avoid rendering the intermediate results row for the root of tree
// and in case there's only one child subtree.
if (!tree.isCollapsed && path.length > 0 && tree.children.size !== 1) {
- sink.push(this.renderSectionRow(path, tree, result));
+ sink.push(this.renderSectionRow(area, path, tree, result));
}
for (const [key, childTree] of tree.children.entries()) {
path.push({tree: childTree, nextKey: key});
- this.renderTree(path, childTree, result, sink);
+ this.renderTree(area, path, childTree, result, sink);
path.pop();
}
return;
@@ -159,11 +226,12 @@
// Avoid rendering the intermediate results row if it has only one leaf
// row.
- if (!tree.isCollapsed && tree.rows.length > 1) {
- sink.push(this.renderSectionRow(path, tree, result));
+ if (!tree.isCollapsed && path.length > 0 && tree.rows.length > 1) {
+ sink.push(this.renderSectionRow(area, path, tree, result));
}
for (const row of tree.rows) {
const renderedCells = [];
+ const drillFilters: DrillFilter[] = [];
const treeDepth = result.metadata.pivotColumns.length;
for (let j = 0; j < treeDepth; j++) {
if (j < path.length) {
@@ -171,62 +239,105 @@
} else {
renderedCells.push(m(`td`, `${row[j]}`));
}
+ drillFilters.push(
+ {column: result.metadata.pivotColumns[j], value: row[j]});
}
for (let j = 0; j < result.metadata.aggregationColumns.length; j++) {
const value = row[aggregationIndex(treeDepth, j, treeDepth)];
renderedCells.push(m('td', `${value}`));
}
+ renderedCells.push(this.renderDrillDownCell(area, result, drillFilters));
sink.push(m('tr', renderedCells));
}
}
- renderResultsTable() {
+ renderTotalsRow(queryResult: PivotTableReduxResult) {
+ const overallValuesRow =
+ [m('td.total-values',
+ {'colspan': queryResult.metadata.pivotColumns.length},
+ m('strong', 'Total values:'))];
+ for (const aggValue of queryResult.tree.aggregates) {
+ overallValuesRow.push(m('td', `${aggValue}`));
+ }
+ overallValuesRow.push(m('td'));
+ return m('tr', overallValuesRow);
+ }
+
+ renderResultsTable(attrs: PivotTableReduxAttrs) {
const state = globals.state.pivotTableRedux;
if (state.query !== null || state.queryResult === null) {
return m('div', 'Loading...');
}
const renderedRows: m.Vnode[] = [];
+ const tree = state.queryResult.tree;
+
+ if (tree.children.size === 0 && tree.rows.length === 0) {
+ // Empty result, render a special message
+ return m('.empty-result', 'No slices in the current selection.');
+ }
+
this.renderTree(
- [], state.queryResult.tree, state.queryResult, renderedRows);
+ attrs.selectionArea, [], tree, state.queryResult, renderedRows);
const allColumns = state.queryResult.metadata.pivotColumns.concat(
state.queryResult.metadata.aggregationColumns);
return m(
'table.query-table.pivot-table',
- m('thead', m('tr', allColumns.map(column => m('td', column)))),
- m('tbody', renderedRows));
+ m('thead', m('tr', allColumns.map(column => m('td', column)), m('td'))),
+ m('tbody', this.renderTotalsRow(state.queryResult), renderedRows));
}
- renderQuery(): m.Vnode {
+ renderQuery(attrs: PivotTableReduxAttrs): m.Vnode {
+ // Prepare a button to switch to results mode.
+ let innerElement =
+ m('button.mode-button',
+ {
+ onclick: () => {
+ this.editMode = false;
+ this.runQuery(attrs);
+ globals.rafScheduler.scheduleFullRedraw();
+ }
+ },
+ 'Execute');
try {
- return m(
- 'div',
- m('pre', this.generateQuery()),
- m('button.mode-button',
- {
- onclick: () => {
- this.editMode = false;
- this.runQuery();
- globals.rafScheduler.scheduleFullRedraw();
- }
- },
- 'Execute'));
+ this.generateQuery(attrs);
} catch (e) {
if (e instanceof QueryGeneratorError) {
- return m('div.query-error', e.message);
+ // If query generation fails, show an error message instead of a button.
+ innerElement = m('div.query-error', e.message);
} else {
throw e;
}
}
+
+ return m(
+ 'div',
+ m('div',
+ m('input', {
+ type: 'checkbox',
+ id: 'constrain-to-selection',
+ checked: this.constrainToArea,
+ onclick: (e: InputEvent) => {
+ const checkbox = e.target as HTMLInputElement;
+ this.constrainToArea = checkbox.checked;
+ }
+ }),
+ m('label',
+ {
+ 'for': 'constrain-to-selection',
+ },
+ 'Constrain to current time range')),
+ innerElement);
}
- view() {
- return this.editMode ? this.renderEditView() : this.renderResultsView();
+ view({attrs}: m.Vnode<PivotTableReduxAttrs>) {
+ return this.editMode ? this.renderEditView(attrs) :
+ this.renderResultsView(attrs);
}
- renderEditView() {
+ renderEditView(attrs: PivotTableReduxAttrs) {
return m(
'.pivot-table-redux.edit',
m('div',
@@ -254,6 +365,6 @@
setKey: ['thread_slice', t],
}),
`thread_slice.${t}`)))),
- this.renderQuery());
+ this.renderQuery(attrs));
}
}
\ No newline at end of file
diff --git a/ui/src/frontend/pivot_table_redux_query_generator.ts b/ui/src/frontend/pivot_table_redux_query_generator.ts
index 9bd62fc..8e9586b 100644
--- a/ui/src/frontend/pivot_table_redux_query_generator.ts
+++ b/ui/src/frontend/pivot_table_redux_query_generator.ts
@@ -1,4 +1,8 @@
-import {PivotTableReduxQuery} from '../common/state';
+import {Area, PivotTableReduxQuery} from '../common/state';
+import {toNs} from '../common/time';
+import {
+ getSelectedTrackIds
+} from '../controller/aggregation/slice_aggregation_controller';
export interface Table {
name: string;
@@ -86,11 +90,21 @@
return `agg_${aggregationIndex}_level_${rolloverLevel}`;
}
+export function areaFilter(area: Area): string {
+ return `
+ ts > ${toNs(area.startSec)}
+ and ts < ${toNs(area.endSec)}
+ and track_id in (${getSelectedTrackIds(area).join(', ')})
+ `;
+}
+
function generateInnerQuery(
pivots: string[],
aggregations: string[],
table: string,
- includeTrack: boolean): string {
+ includeTrack: boolean,
+ area: Area,
+ constrainToArea: boolean): string {
const pivotColumns = pivots.concat(includeTrack ? ['track_id'] : []);
const aggregationColumns: string[] = [];
@@ -99,10 +113,13 @@
aggregationColumns.push(`SUM(${agg}) as ${aggregationAlias(i, 0)}`);
}
+ // The condition is inverted because flipped order of literals makes JS
+ // formatter insert huge amounts of whitespace for no good reason.
return `
select
${pivotColumns.concat(aggregationColumns).join(',\n')}
from ${table}
+ ${(constrainToArea ? `where ${areaFilter(area)}` : '')}
group by ${pivotColumns.join(', ')}
`;
}
@@ -138,7 +155,9 @@
export function generateQuery(
selectedPivots: ColumnSet,
- selectedAggregations: ColumnSet): PivotTableReduxQuery {
+ selectedAggregations: ColumnSet,
+ area: Area,
+ constrainToArea: boolean): PivotTableReduxQuery {
const sliceTableAggregations =
computeSliceTableAggregations(selectedAggregations);
const slicePivots: string[] = [];
@@ -203,7 +222,9 @@
slicePivots,
sliceTableAggregations.flatAggregations,
sliceTableAggregations.tableName,
- nonSlicePivots.length > 0)}
+ nonSlicePivots.length > 0,
+ area,
+ constrainToArea)}
) preaggregated
${nonSlicePivots.length > 0 ? joins : ''}
group by ${nonSlicePivots.concat(prefixedSlicePivots).join(', ')}
@@ -212,6 +233,7 @@
return {
text,
metadata: {
+ tableName: sliceTableAggregations.tableName,
pivotColumns: nonSlicePivots.concat(slicePivots.map(
column => `${sliceTableAggregations.tableName}.${column}`)),
aggregationColumns: sliceTableAggregations.flatAggregations.map(