Merge "perfetto-ui: Add origin trial"
diff --git a/Android.bp b/Android.bp
index 7a622db..19675b8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -979,9 +979,9 @@
name: "perfetto_include_perfetto_profiling_normalize",
}
-// GN: //include/perfetto/profiling:symbolizer
+// GN: //include/perfetto/profiling:pprof_builder
filegroup {
- name: "perfetto_include_perfetto_profiling_symbolizer",
+ name: "perfetto_include_perfetto_profiling_pprof_builder",
}
// GN: //include/perfetto/protozero:protozero
@@ -5416,6 +5416,31 @@
],
}
+// GN: //src/profiling/perf:unwind_support
+filegroup {
+ name: "perfetto_src_profiling_perf_unwind_support",
+ srcs: [
+ "src/profiling/perf/unwind_support.cc",
+ ],
+}
+
+// GN: //src/profiling/symbolizer:symbolize_database
+filegroup {
+ name: "perfetto_src_profiling_symbolizer_symbolize_database",
+ srcs: [
+ "src/profiling/symbolizer/symbolize_database.cc",
+ ],
+}
+
+// GN: //src/profiling/symbolizer:symbolizer
+filegroup {
+ name: "perfetto_src_profiling_symbolizer_symbolizer",
+ srcs: [
+ "src/profiling/symbolizer/local_symbolizer.cc",
+ "src/profiling/symbolizer/symbolizer.cc",
+ ],
+}
+
// GN: //src/profiling:unittests
filegroup {
name: "perfetto_src_profiling_unittests",
@@ -5620,11 +5645,26 @@
],
}
-// GN: //src/trace_processor:common
+// GN: //src/trace_processor/containers:containers
filegroup {
- name: "perfetto_src_trace_processor_common",
+ name: "perfetto_src_trace_processor_containers_containers",
srcs: [
- "src/trace_processor/string_pool.cc",
+ "src/trace_processor/containers/bit_vector.cc",
+ "src/trace_processor/containers/bit_vector_iterators.cc",
+ "src/trace_processor/containers/row_map.cc",
+ "src/trace_processor/containers/string_pool.cc",
+ ],
+}
+
+// GN: //src/trace_processor/containers:unittests
+filegroup {
+ name: "perfetto_src_trace_processor_containers_unittests",
+ srcs: [
+ "src/trace_processor/containers/bit_vector_unittest.cc",
+ "src/trace_processor/containers/null_term_string_view_unittest.cc",
+ "src/trace_processor/containers/row_map_unittest.cc",
+ "src/trace_processor/containers/sparse_vector_unittest.cc",
+ "src/trace_processor/containers/string_pool_unittest.cc",
],
}
@@ -5632,10 +5672,7 @@
filegroup {
name: "perfetto_src_trace_processor_db_lib",
srcs: [
- "src/trace_processor/db/bit_vector.cc",
- "src/trace_processor/db/bit_vector_iterators.cc",
"src/trace_processor/db/column.cc",
- "src/trace_processor/db/row_map.cc",
"src/trace_processor/db/table.cc",
],
}
@@ -5644,10 +5681,7 @@
filegroup {
name: "perfetto_src_trace_processor_db_unittests",
srcs: [
- "src/trace_processor/db/bit_vector_unittest.cc",
"src/trace_processor/db/compare_unittest.cc",
- "src/trace_processor/db/row_map_unittest.cc",
- "src/trace_processor/db/sparse_vector_unittest.cc",
],
}
@@ -5668,7 +5702,6 @@
"src/trace_processor/cpu_profile_stack_sample_table.cc",
"src/trace_processor/filtered_row_index.cc",
"src/trace_processor/gfp_flags.cc",
- "src/trace_processor/heap_profile_allocation_table.cc",
"src/trace_processor/instants_table.cc",
"src/trace_processor/metadata_table.cc",
"src/trace_processor/process_table.cc",
@@ -5740,8 +5773,15 @@
filegroup {
name: "perfetto_src_trace_processor_storage_full",
srcs: [
+ "src/trace_processor/importers/proto/android_probes_module.cc",
+ "src/trace_processor/importers/proto/android_probes_parser.cc",
"src/trace_processor/importers/proto/graphics_event_module.cc",
"src/trace_processor/importers/proto/graphics_event_parser.cc",
+ "src/trace_processor/importers/proto/heap_graph_module.cc",
+ "src/trace_processor/importers/proto/heap_graph_tracker.cc",
+ "src/trace_processor/importers/proto/heap_graph_walker.cc",
+ "src/trace_processor/importers/proto/system_probes_module.cc",
+ "src/trace_processor/importers/proto/system_probes_parser.cc",
"src/trace_processor/importers/proto/vulkan_memory_tracker.cc",
"src/trace_processor/register_additional_modules.cc",
],
@@ -5752,13 +5792,14 @@
name: "perfetto_src_trace_processor_storage_minimal",
srcs: [
"src/trace_processor/args_tracker.cc",
- "src/trace_processor/binder_tracker.cc",
"src/trace_processor/clock_tracker.cc",
+ "src/trace_processor/destructible.cc",
"src/trace_processor/event_tracker.cc",
"src/trace_processor/forwarding_trace_parser.cc",
"src/trace_processor/ftrace_utils.cc",
"src/trace_processor/gzip_trace_parser.cc",
"src/trace_processor/heap_profile_tracker.cc",
+ "src/trace_processor/importers/ftrace/binder_tracker.cc",
"src/trace_processor/importers/ftrace/ftrace_descriptors.cc",
"src/trace_processor/importers/ftrace/ftrace_module.cc",
"src/trace_processor/importers/ftrace/ftrace_module_impl.cc",
@@ -5769,17 +5810,10 @@
"src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc",
"src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc",
"src/trace_processor/importers/fuchsia/fuchsia_trace_utils.cc",
- "src/trace_processor/importers/proto/android_probes_module.cc",
- "src/trace_processor/importers/proto/android_probes_parser.cc",
"src/trace_processor/importers/proto/args_table_utils.cc",
- "src/trace_processor/importers/proto/heap_graph_module.cc",
- "src/trace_processor/importers/proto/heap_graph_tracker.cc",
- "src/trace_processor/importers/proto/heap_graph_walker.cc",
"src/trace_processor/importers/proto/proto_importer_module.cc",
"src/trace_processor/importers/proto/proto_trace_parser.cc",
"src/trace_processor/importers/proto/proto_trace_tokenizer.cc",
- "src/trace_processor/importers/proto/system_probes_module.cc",
- "src/trace_processor/importers/proto/system_probes_parser.cc",
"src/trace_processor/importers/proto/track_event_module.cc",
"src/trace_processor/importers/proto/track_event_parser.cc",
"src/trace_processor/importers/proto/track_event_tokenizer.cc",
@@ -5829,14 +5863,12 @@
"src/trace_processor/importers/proto/proto_trace_parser_unittest.cc",
"src/trace_processor/importers/systrace/systrace_parser_unittest.cc",
"src/trace_processor/metadata_table_unittest.cc",
- "src/trace_processor/null_term_string_view_unittest.cc",
"src/trace_processor/process_table_unittest.cc",
"src/trace_processor/process_tracker_unittest.cc",
"src/trace_processor/protozero_to_text_unittests.cc",
"src/trace_processor/sched_slice_table_unittest.cc",
"src/trace_processor/slice_tracker_unittest.cc",
"src/trace_processor/span_join_operator_table_unittest.cc",
- "src/trace_processor/string_pool_unittest.cc",
"src/trace_processor/syscall_tracker_unittest.cc",
"src/trace_processor/thread_table_unittest.cc",
"src/trace_processor/trace_sorter_unittest.cc",
@@ -6352,14 +6384,6 @@
],
}
-// GN: //tools/trace_to_text:local_symbolizer
-filegroup {
- name: "perfetto_tools_trace_to_text_local_symbolizer",
- srcs: [
- "tools/trace_to_text/local_symbolizer.cc",
- ],
-}
-
// GN: //tools/trace_to_text:pprofbuilder
filegroup {
name: "perfetto_tools_trace_to_text_pprofbuilder",
@@ -6368,14 +6392,6 @@
],
}
-// GN: //tools/trace_to_text:symbolizer
-filegroup {
- name: "perfetto_tools_trace_to_text_symbolizer",
- srcs: [
- "tools/trace_to_text/symbolizer.cc",
- ],
-}
-
// GN: //tools/trace_to_text:utils
filegroup {
name: "perfetto_tools_trace_to_text_utils",
@@ -6582,13 +6598,15 @@
":perfetto_src_profiling_memory_wire_protocol",
":perfetto_src_profiling_perf_producer",
":perfetto_src_profiling_perf_producer_unittests",
+ ":perfetto_src_profiling_perf_unwind_support",
":perfetto_src_profiling_unittests",
":perfetto_src_protozero_protozero",
":perfetto_src_protozero_testing_messages_cpp_gen",
":perfetto_src_protozero_testing_messages_lite_gen",
":perfetto_src_protozero_testing_messages_zero_gen",
":perfetto_src_protozero_unittests",
- ":perfetto_src_trace_processor_common",
+ ":perfetto_src_trace_processor_containers_containers",
+ ":perfetto_src_trace_processor_containers_unittests",
":perfetto_src_trace_processor_db_lib",
":perfetto_src_trace_processor_db_unittests",
":perfetto_src_trace_processor_descriptors",
@@ -6720,6 +6738,9 @@
"-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
"-DHAVE_HIDDEN",
],
+ include_dirs: [
+ "bionic/libc/kernel",
+ ],
data: [
"src/traced/probes/filesystem/testdata/**/*",
"src/traced/probes/ftrace/test/data/**/*",
@@ -6802,7 +6823,7 @@
":perfetto_protos_perfetto_trace_track_event_zero_gen",
":perfetto_src_base_base",
":perfetto_src_protozero_protozero",
- ":perfetto_src_trace_processor_common",
+ ":perfetto_src_trace_processor_containers_containers",
":perfetto_src_trace_processor_db_lib",
":perfetto_src_trace_processor_descriptors",
":perfetto_src_trace_processor_lib",
@@ -6873,7 +6894,7 @@
":perfetto_include_perfetto_ext_base_base",
":perfetto_include_perfetto_ext_traced_sys_stats_counters",
":perfetto_include_perfetto_profiling_deobfuscator",
- ":perfetto_include_perfetto_profiling_symbolizer",
+ ":perfetto_include_perfetto_profiling_pprof_builder",
":perfetto_include_perfetto_protozero_protozero",
":perfetto_include_perfetto_trace_processor_basic_types",
":perfetto_include_perfetto_trace_processor_storage",
@@ -6908,8 +6929,10 @@
":perfetto_protos_third_party_pprof_zero_gen",
":perfetto_src_base_base",
":perfetto_src_profiling_deobfuscator",
+ ":perfetto_src_profiling_symbolizer_symbolize_database",
+ ":perfetto_src_profiling_symbolizer_symbolizer",
":perfetto_src_protozero_protozero",
- ":perfetto_src_trace_processor_common",
+ ":perfetto_src_trace_processor_containers_containers",
":perfetto_src_trace_processor_db_lib",
":perfetto_src_trace_processor_descriptors",
":perfetto_src_trace_processor_lib",
@@ -6920,9 +6943,7 @@
":perfetto_src_trace_processor_tables_tables",
":perfetto_tools_trace_to_text_common",
":perfetto_tools_trace_to_text_full",
- ":perfetto_tools_trace_to_text_local_symbolizer",
":perfetto_tools_trace_to_text_pprofbuilder",
- ":perfetto_tools_trace_to_text_symbolizer",
":perfetto_tools_trace_to_text_utils",
],
shared_libs: [
@@ -7047,6 +7068,7 @@
":perfetto_src_ipc_ipc",
":perfetto_src_profiling_perf_producer",
":perfetto_src_profiling_perf_traced_perf_main",
+ ":perfetto_src_profiling_perf_unwind_support",
":perfetto_src_protozero_protozero",
":perfetto_src_tracing_common",
":perfetto_src_tracing_ipc",
@@ -7054,7 +7076,10 @@
"src/profiling/perf/main.cc",
],
shared_libs: [
+ "libbase",
"liblog",
+ "libprocinfo",
+ "libunwindstack",
],
generated_headers: [
"perfetto_protos_perfetto_common_cpp_gen_headers",
@@ -7102,6 +7127,9 @@
"-DGOOGLE_PROTOBUF_NO_RTTI",
"-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
],
+ include_dirs: [
+ "bionic/libc/kernel",
+ ],
}
// GN: //src/traced/probes:traced_probes
diff --git a/BUILD b/BUILD
index 1dde88e..4d01126 100644
--- a/BUILD
+++ b/BUILD
@@ -332,12 +332,11 @@
],
)
-# GN target: //include/perfetto/profiling:symbolizer
+# GN target: //include/perfetto/profiling:pprof_builder
filegroup(
- name = "include_perfetto_profiling_symbolizer",
+ name = "include_perfetto_profiling_pprof_builder",
srcs = [
"include/perfetto/profiling/pprof_builder.h",
- "include/perfetto/profiling/symbolizer.h",
],
)
@@ -547,6 +546,26 @@
],
)
+# GN target: //src/profiling/symbolizer:symbolize_database
+filegroup(
+ name = "src_profiling_symbolizer_symbolize_database",
+ srcs = [
+ "src/profiling/symbolizer/symbolize_database.cc",
+ "src/profiling/symbolizer/symbolize_database.h",
+ ],
+)
+
+# GN target: //src/profiling/symbolizer:symbolizer
+filegroup(
+ name = "src_profiling_symbolizer_symbolizer",
+ srcs = [
+ "src/profiling/symbolizer/local_symbolizer.cc",
+ "src/profiling/symbolizer/local_symbolizer.h",
+ "src/profiling/symbolizer/symbolizer.cc",
+ "src/profiling/symbolizer/symbolizer.h",
+ ],
+)
+
# GN target: //src/profiling:deobfuscator
filegroup(
name = "src_profiling_deobfuscator",
@@ -572,20 +591,30 @@
],
)
+# GN target: //src/trace_processor/containers:containers
+filegroup(
+ name = "src_trace_processor_containers_containers",
+ srcs = [
+ "src/trace_processor/containers/bit_vector.cc",
+ "src/trace_processor/containers/bit_vector.h",
+ "src/trace_processor/containers/bit_vector_iterators.cc",
+ "src/trace_processor/containers/bit_vector_iterators.h",
+ "src/trace_processor/containers/null_term_string_view.h",
+ "src/trace_processor/containers/row_map.cc",
+ "src/trace_processor/containers/row_map.h",
+ "src/trace_processor/containers/sparse_vector.h",
+ "src/trace_processor/containers/string_pool.cc",
+ "src/trace_processor/containers/string_pool.h",
+ ],
+)
+
# GN target: //src/trace_processor/db:lib
filegroup(
name = "src_trace_processor_db_lib",
srcs = [
- "src/trace_processor/db/bit_vector.cc",
- "src/trace_processor/db/bit_vector.h",
- "src/trace_processor/db/bit_vector_iterators.cc",
- "src/trace_processor/db/bit_vector_iterators.h",
"src/trace_processor/db/column.cc",
"src/trace_processor/db/column.h",
"src/trace_processor/db/compare.h",
- "src/trace_processor/db/row_map.cc",
- "src/trace_processor/db/row_map.h",
- "src/trace_processor/db/sparse_vector.h",
"src/trace_processor/db/table.cc",
"src/trace_processor/db/table.h",
"src/trace_processor/db/typed_column.h",
@@ -688,16 +717,6 @@
],
)
-# GN target: //src/trace_processor:common
-filegroup(
- name = "src_trace_processor_common",
- srcs = [
- "src/trace_processor/null_term_string_view.h",
- "src/trace_processor/string_pool.cc",
- "src/trace_processor/string_pool.h",
- ],
-)
-
# GN target: //src/trace_processor:descriptors
filegroup(
name = "src_trace_processor_descriptors",
@@ -730,8 +749,6 @@
"src/trace_processor/filtered_row_index.h",
"src/trace_processor/gfp_flags.cc",
"src/trace_processor/gfp_flags.h",
- "src/trace_processor/heap_profile_allocation_table.cc",
- "src/trace_processor/heap_profile_allocation_table.h",
"src/trace_processor/instants_table.cc",
"src/trace_processor/instants_table.h",
"src/trace_processor/metadata_table.cc",
@@ -775,10 +792,24 @@
filegroup(
name = "src_trace_processor_storage_full",
srcs = [
+ "src/trace_processor/importers/proto/android_probes_module.cc",
+ "src/trace_processor/importers/proto/android_probes_module.h",
+ "src/trace_processor/importers/proto/android_probes_parser.cc",
+ "src/trace_processor/importers/proto/android_probes_parser.h",
"src/trace_processor/importers/proto/graphics_event_module.cc",
"src/trace_processor/importers/proto/graphics_event_module.h",
"src/trace_processor/importers/proto/graphics_event_parser.cc",
"src/trace_processor/importers/proto/graphics_event_parser.h",
+ "src/trace_processor/importers/proto/heap_graph_module.cc",
+ "src/trace_processor/importers/proto/heap_graph_module.h",
+ "src/trace_processor/importers/proto/heap_graph_tracker.cc",
+ "src/trace_processor/importers/proto/heap_graph_tracker.h",
+ "src/trace_processor/importers/proto/heap_graph_walker.cc",
+ "src/trace_processor/importers/proto/heap_graph_walker.h",
+ "src/trace_processor/importers/proto/system_probes_module.cc",
+ "src/trace_processor/importers/proto/system_probes_module.h",
+ "src/trace_processor/importers/proto/system_probes_parser.cc",
+ "src/trace_processor/importers/proto/system_probes_parser.h",
"src/trace_processor/importers/proto/vulkan_memory_tracker.cc",
"src/trace_processor/importers/proto/vulkan_memory_tracker.h",
"src/trace_processor/register_additional_modules.cc",
@@ -792,11 +823,11 @@
srcs = [
"src/trace_processor/args_tracker.cc",
"src/trace_processor/args_tracker.h",
- "src/trace_processor/binder_tracker.cc",
- "src/trace_processor/binder_tracker.h",
"src/trace_processor/chunked_trace_reader.h",
"src/trace_processor/clock_tracker.cc",
"src/trace_processor/clock_tracker.h",
+ "src/trace_processor/destructible.cc",
+ "src/trace_processor/destructible.h",
"src/trace_processor/event_tracker.cc",
"src/trace_processor/event_tracker.h",
"src/trace_processor/forwarding_trace_parser.cc",
@@ -807,6 +838,8 @@
"src/trace_processor/gzip_trace_parser.h",
"src/trace_processor/heap_profile_tracker.cc",
"src/trace_processor/heap_profile_tracker.h",
+ "src/trace_processor/importers/ftrace/binder_tracker.cc",
+ "src/trace_processor/importers/ftrace/binder_tracker.h",
"src/trace_processor/importers/ftrace/ftrace_descriptors.cc",
"src/trace_processor/importers/ftrace/ftrace_descriptors.h",
"src/trace_processor/importers/ftrace/ftrace_module.cc",
@@ -832,19 +865,9 @@
"src/trace_processor/importers/json/json_trace_tokenizer.h",
"src/trace_processor/importers/json/json_trace_utils.cc",
"src/trace_processor/importers/json/json_trace_utils.h",
- "src/trace_processor/importers/proto/android_probes_module.cc",
- "src/trace_processor/importers/proto/android_probes_module.h",
- "src/trace_processor/importers/proto/android_probes_parser.cc",
- "src/trace_processor/importers/proto/android_probes_parser.h",
"src/trace_processor/importers/proto/args_table_utils.cc",
"src/trace_processor/importers/proto/args_table_utils.h",
"src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h",
- "src/trace_processor/importers/proto/heap_graph_module.cc",
- "src/trace_processor/importers/proto/heap_graph_module.h",
- "src/trace_processor/importers/proto/heap_graph_tracker.cc",
- "src/trace_processor/importers/proto/heap_graph_tracker.h",
- "src/trace_processor/importers/proto/heap_graph_walker.cc",
- "src/trace_processor/importers/proto/heap_graph_walker.h",
"src/trace_processor/importers/proto/packet_sequence_state.h",
"src/trace_processor/importers/proto/proto_importer_module.cc",
"src/trace_processor/importers/proto/proto_importer_module.h",
@@ -853,10 +876,6 @@
"src/trace_processor/importers/proto/proto_trace_parser.h",
"src/trace_processor/importers/proto/proto_trace_tokenizer.cc",
"src/trace_processor/importers/proto/proto_trace_tokenizer.h",
- "src/trace_processor/importers/proto/system_probes_module.cc",
- "src/trace_processor/importers/proto/system_probes_module.h",
- "src/trace_processor/importers/proto/system_probes_parser.cc",
- "src/trace_processor/importers/proto/system_probes_parser.h",
"src/trace_processor/importers/proto/track_event_module.cc",
"src/trace_processor/importers/proto/track_event_module.h",
"src/trace_processor/importers/proto/track_event_parser.cc",
@@ -1177,15 +1196,6 @@
],
)
-# GN target: //tools/trace_to_text:local_symbolizer
-filegroup(
- name = "tools_trace_to_text_local_symbolizer",
- srcs = [
- "tools/trace_to_text/local_symbolizer.cc",
- "tools/trace_to_text/local_symbolizer.h",
- ],
-)
-
# GN target: //tools/trace_to_text:pprofbuilder
filegroup(
name = "tools_trace_to_text_pprofbuilder",
@@ -1194,14 +1204,6 @@
],
)
-# GN target: //tools/trace_to_text:symbolizer
-filegroup(
- name = "tools_trace_to_text_symbolizer",
- srcs = [
- "tools/trace_to_text/symbolizer.cc",
- ],
-)
-
# GN target: //tools/trace_to_text:utils
filegroup(
name = "tools_trace_to_text_utils",
@@ -2518,7 +2520,7 @@
srcs = [
":src_base_base",
":src_protozero_protozero",
- ":src_trace_processor_common",
+ ":src_trace_processor_containers_containers",
":src_trace_processor_db_lib",
":src_trace_processor_descriptors",
":src_trace_processor_export_json",
@@ -2596,7 +2598,7 @@
":src_base_base",
":src_base_unix_socket",
":src_protozero_protozero",
- ":src_trace_processor_common",
+ ":src_trace_processor_containers_containers",
":src_trace_processor_db_lib",
":src_trace_processor_descriptors",
":src_trace_processor_export_json",
@@ -2686,15 +2688,16 @@
name = "libpprofbuilder",
srcs = [
":src_profiling_deobfuscator",
+ ":src_profiling_symbolizer_symbolize_database",
+ ":src_profiling_symbolizer_symbolizer",
":tools_trace_to_text_pprofbuilder",
- ":tools_trace_to_text_symbolizer",
":tools_trace_to_text_utils",
],
hdrs = [
":include_perfetto_base_base",
":include_perfetto_ext_base_base",
":include_perfetto_profiling_deobfuscator",
- ":include_perfetto_profiling_symbolizer",
+ ":include_perfetto_profiling_pprof_builder",
":include_perfetto_protozero_protozero",
":include_perfetto_trace_processor_basic_types",
":include_perfetto_trace_processor_storage",
@@ -2741,15 +2744,17 @@
":include_perfetto_ext_trace_processor_export_json",
":include_perfetto_ext_traced_sys_stats_counters",
":include_perfetto_profiling_deobfuscator",
- ":include_perfetto_profiling_symbolizer",
+ ":include_perfetto_profiling_pprof_builder",
":include_perfetto_protozero_protozero",
":include_perfetto_trace_processor_basic_types",
":include_perfetto_trace_processor_storage",
":include_perfetto_trace_processor_trace_processor",
":src_base_base",
":src_profiling_deobfuscator",
+ ":src_profiling_symbolizer_symbolize_database",
+ ":src_profiling_symbolizer_symbolizer",
":src_protozero_protozero",
- ":src_trace_processor_common",
+ ":src_trace_processor_containers_containers",
":src_trace_processor_db_lib",
":src_trace_processor_descriptors",
":src_trace_processor_export_json",
@@ -2761,9 +2766,7 @@
":src_trace_processor_tables_tables",
":tools_trace_to_text_common",
":tools_trace_to_text_full",
- ":tools_trace_to_text_local_symbolizer",
":tools_trace_to_text_pprofbuilder",
- ":tools_trace_to_text_symbolizer",
":tools_trace_to_text_utils",
],
visibility = [
diff --git a/BUILD.gn b/BUILD.gn
index 30f269d..4fdd937 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -82,6 +82,17 @@
]
}
+if (enable_perfetto_trace_processor_json) {
+ executable("trace_processor_minimal_smoke_tests") {
+ testonly = true
+ deps = [
+ "gn:default_deps",
+ "src/trace_processor:storage_minimal_smoke_tests",
+ ]
+ }
+ all_targets += [ ":trace_processor_minimal_smoke_tests" ]
+}
+
if (enable_perfetto_benchmarks) {
import("gn/perfetto_benchmarks.gni")
executable("perfetto_benchmarks") {
diff --git a/docs/heapprofd.md b/docs/heapprofd.md
index 9096993..50ae55f 100644
--- a/docs/heapprofd.md
+++ b/docs/heapprofd.md
@@ -47,9 +47,6 @@
moment the dump was created.
* **alloc\_space**: how many bytes were allocated (including ones freed at the
moment of the dump) at this callstack
-* **idle\_space**: if [idle page tracking](#idle-page-tracking) is being used,
- the number of bytes that were allocated at this callstack and are on pages
- that have not been touched since the last dump.
* **objects**: how many allocations without matching frees were done at this
callstack.
* **alloc\_objects**: how many allocations (including ones with matching frees)
@@ -179,45 +176,6 @@
You can save the symbolized version by issuing the `proto` command in pprof.
-## Idle page tracking
-This is only available in Android versions newer than 10.
-
-Idle page tracking allows you to analyze which allocations made by your
-program are being used by a workload. This can be useful for finding leaks
-as well as unused cached values.
-
-**Do not follow these instructions on devices containing valuable data.**
-They require you turn off SELinux on your device, significantly lowering
-your device's security level.
-
-Use the following command to profile the next startup of your program with idle
-tracking enabled.
-
-1. `$ adb root`
-2. `$ tools/heap_profile -n ${NAME} --no-running --disable-selinux
---idle-allocations`
-
-Then run the following commands in a separate shell.
-
-1. `$ adb shell killall ${ROOT}` to restart your program.
-2. Wait for your program to finish starting.
-3. `adb shell killall -USR1 heapprofd` to trigger the first dump (see
-[Manual Dumping](#manual-dumping) above). This will mark all allocations as
-idle.
-4. Interact with your program.
-
-Once you are done interacting, `Ctrl-C` the invokation of
-`tools/heap_profile`, and upload the `heap_dump.2.*.pb.gz` file to pprof.
-You can then see the memory that was idle in the `idle_space` tab.
-
-This will show allocations that are on pages that have not been touched since
-the last dump. Small allocations that are not touched might not show up, as
-they might share a page with an allocation that was.
-
-If heapprofd is operating in sampling mode (i.e. `--interval` is larger than 1),
-the values in `idle_space` will not correct for the sampling, so they are not
-comparable to values in `space` and `alloc_space`, which do.
-
## Troubleshooting
### Buffer overrun
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index ab87bc9..4e86d3b 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -84,9 +84,6 @@
"PERFETTO_TP_METRICS=$enable_perfetto_trace_processor_metrics",
"PERFETTO_TP_FTRACE=$enable_perfetto_trace_processor_ftrace",
"PERFETTO_TP_HTTPD=$perfetto_tp_httpd",
- "PERFETTO_TP_SYSTEM_PROBES=$enable_perfetto_trace_processor_system_probes",
- "PERFETTO_TP_ANDROID_PROBES=$enable_perfetto_trace_processor_android_probes",
- "PERFETTO_TP_HEAP_GRAPHS=$enable_perfetto_trace_processor_heap_graphs",
"PERFETTO_TP_JSON=$enable_perfetto_trace_processor_json",
"PERFETTO_TP_JSON_IMPORT=$enable_perfetto_trace_processor_json_import",
"PERFETTO_TP_FUCHSIA=$enable_perfetto_trace_processor_fuchsia",
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index 4aba7e1..cc1232f 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -149,9 +149,7 @@
# Build the perf event profiler (traced_perf).
# TODO(b/144281346): under development.
- enable_perfetto_traced_perf =
- perfetto_build_with_android ||
- (perfetto_build_standalone && (is_linux || is_android))
+ enable_perfetto_traced_perf = perfetto_build_with_android
# The Trace Processor: offline analytical engine to process traces and compute
# metrics using a SQL engine.
@@ -219,18 +217,6 @@
enable_perfetto_trace_processor_ftrace =
enable_perfetto_trace_processor && !(build_with_chromium && is_android)
- # Enables parsing support for system probes in trace processor.
- enable_perfetto_trace_processor_system_probes =
- enable_perfetto_trace_processor && !(build_with_chromium && is_android)
-
- # Enables parsing support for android system probes in trace processor.
- enable_perfetto_trace_processor_android_probes =
- enable_perfetto_trace_processor && !(build_with_chromium && is_android)
-
- # Enables parsing support for heap graphs in trace processor.
- enable_perfetto_trace_processor_heap_graphs =
- enable_perfetto_trace_processor && !(build_with_chromium && is_android)
-
# Enables JSON support in the trace processor. Required for JSON trace import
# and export. Importer support can also be disabled using
# |enable_perfetto_trace_processor_json_import|.
@@ -256,9 +242,7 @@
# Enables syscall support in trace processor. Required for ftrace, system
# probes, and android probes support.
enable_perfetto_trace_processor_syscalls =
- enable_perfetto_trace_processor_ftrace ||
- enable_perfetto_trace_processor_system_probes ||
- enable_perfetto_trace_processor_android_probes
+ enable_perfetto_trace_processor_ftrace
# Enables metrics support in the trace processor, which require SQL support.
enable_perfetto_trace_processor_metrics =
@@ -318,6 +302,4 @@
# Syscall support is required for ftrace, system probes, and android probes.
assert(enable_perfetto_trace_processor_syscalls ||
- (!enable_perfetto_trace_processor_ftrace &&
- !enable_perfetto_trace_processor_system_probes &&
- !enable_perfetto_trace_processor_android_probes))
+ !enable_perfetto_trace_processor_ftrace)
diff --git a/gn/perfetto_benchmarks.gni b/gn/perfetto_benchmarks.gni
index 4b0f331..122c6ff 100644
--- a/gn/perfetto_benchmarks.gni
+++ b/gn/perfetto_benchmarks.gni
@@ -18,7 +18,7 @@
"gn:default_deps",
"src/base:benchmarks",
"src/traced/probes/ftrace:benchmarks",
- "src/trace_processor/db:benchmarks",
+ "src/trace_processor/containers:benchmarks",
"src/trace_processor/tables:benchmarks",
"src/tracing:benchmarks",
"test:benchmark_main",
diff --git a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
index 41c3c05..e9cae4f 100644
--- a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
@@ -38,9 +38,6 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_METRICS() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_FTRACE() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HTTPD() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_SYSTEM_PROBES() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_ANDROID_PROBES() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HEAP_GRAPHS() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON_IMPORT() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_FUCHSIA() (1)
diff --git a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
index 04c4e7d..baa1056 100644
--- a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
@@ -38,9 +38,6 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_METRICS() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_FTRACE() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HTTPD() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() || PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() || PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX())
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_SYSTEM_PROBES() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_ANDROID_PROBES() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HEAP_GRAPHS() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON_IMPORT() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_FUCHSIA() (1)
diff --git a/include/perfetto/profiling/BUILD.gn b/include/perfetto/profiling/BUILD.gn
index 03f8350..ce7c188 100644
--- a/include/perfetto/profiling/BUILD.gn
+++ b/include/perfetto/profiling/BUILD.gn
@@ -12,13 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# TODO(135923303): as part of fixing b/135923303, symbolizer.h will be removed
-# and namespacing of pprof_builder.h will be changed so do not depend on this
-# target.
-source_set("symbolizer") {
+source_set("pprof_builder") {
sources = [
"pprof_builder.h",
- "symbolizer.h",
]
}
diff --git a/include/perfetto/profiling/pprof_builder.h b/include/perfetto/profiling/pprof_builder.h
index 4227a8c..7e26f51 100644
--- a/include/perfetto/profiling/pprof_builder.h
+++ b/include/perfetto/profiling/pprof_builder.h
@@ -27,9 +27,11 @@
class TraceProcessor;
}
-namespace trace_to_text {
-
+namespace profiling {
class Symbolizer;
+}
+
+namespace trace_to_text {
struct SerializedProfile {
uint64_t pid;
@@ -38,13 +40,13 @@
bool TraceToPprof(trace_processor::TraceProcessor*,
std::vector<SerializedProfile>* output,
- Symbolizer* symbolizer,
+ profiling::Symbolizer* symbolizer,
uint64_t pid = 0,
const std::vector<uint64_t>& timestamps = {});
bool TraceToPprof(std::istream* input,
std::vector<SerializedProfile>* output,
- Symbolizer* symbolizer,
+ profiling::Symbolizer* symbolizer,
uint64_t pid = 0,
const std::vector<uint64_t>& timestamps = {});
diff --git a/src/profiling/perf/BUILD.gn b/src/profiling/perf/BUILD.gn
index dba1ca2..b864674 100644
--- a/src/profiling/perf/BUILD.gn
+++ b/src/profiling/perf/BUILD.gn
@@ -18,6 +18,9 @@
assert(enable_perfetto_traced_perf)
+# TODO(rsavitski): only building in-tree at the moment (so this build file is
+# only used for gen_android_bp, expect bitrot).
+
executable("traced_perf") {
deps = [
":traced_perf_main",
@@ -43,6 +46,7 @@
source_set("producer") {
deps = [
+ ":unwind_support",
"../../../gn:default_deps",
"../../../protos/perfetto/config:cpp",
"../../../protos/perfetto/config/profiling:zero",
@@ -63,6 +67,17 @@
]
}
+source_set("unwind_support") {
+ deps = [
+ "../../../gn:default_deps",
+ "../../../gn:libunwindstack",
+ "../../../src/base",
+ ]
+ sources = [
+ "unwind_support.cc",
+ "unwind_support.h",
+ ]
+}
source_set("producer_unittests") {
testonly = true
deps = [
diff --git a/src/profiling/perf/event_config.h b/src/profiling/perf/event_config.h
index da53a0b..cc750ff 100644
--- a/src/profiling/perf/event_config.h
+++ b/src/profiling/perf/event_config.h
@@ -23,6 +23,7 @@
#include "perfetto/ext/base/optional.h"
#include "perfetto/tracing/core/data_source_config.h"
+#include "src/profiling/perf/unwind_support.h"
#include "protos/perfetto/config/profiling/perf_event_config.pbzero.h"
@@ -42,21 +43,17 @@
protos::pbzero::PerfEventConfig::Decoder pb_config(
ds_config.perf_event_config_raw());
- if (!pb_config.has_tid())
- return base::nullopt;
-
return EventConfig(pb_config);
}
- int32_t target_tid() const { return target_tid_; }
+ uint32_t target_cpu() const { return target_cpu_; }
perf_event_attr* perf_attr() const {
return const_cast<perf_event_attr*>(&perf_event_attr_);
}
private:
- EventConfig(const protos::pbzero::PerfEventConfig::Decoder& pb_config)
- : target_tid_(pb_config.tid()) {
+ EventConfig(const protos::pbzero::PerfEventConfig::Decoder&) {
auto& pe = perf_event_attr_;
memset(&pe, 0, sizeof(perf_event_attr));
pe.size = sizeof(perf_event_attr);
@@ -70,18 +67,20 @@
pe.sample_freq = 100;
pe.freq = true;
- pe.sample_type = PERF_SAMPLE_TID | PERF_SAMPLE_STACK_USER;
+ pe.sample_type =
+ PERF_SAMPLE_TID | PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER;
// Needs to be < ((u16)(~0u)), and have bottom 8 bits clear.
pe.sample_stack_user = (1u << 15);
-
- // Note: can't use inherit with task-scoped event mmap
- pe.inherit = false;
+ pe.sample_regs_user = PerfUserRegsMaskForCurrentArch();
}
- // TODO(rsavitski): this will have to represent entire event groups, thus this
- // class will represent N events. So we'll need N cpus/tids, but likely still
- // a single perf_event_attr.
- int32_t target_tid_ = 0;
+ // TODO(rsavitski): for now hardcode each session to be for a single cpu's
+ // scope. In general a config will correspond to N cpus and/or tids.
+ uint32_t target_cpu_ = 0;
+
+ // TODO(rsavitski): if we allow for event groups containing multiple sampled
+ // counters, we'll need to vary the .type & .config fields per
+ // perf_event_open.
perf_event_attr perf_event_attr_;
};
diff --git a/src/profiling/perf/event_config_unittest.cc b/src/profiling/perf/event_config_unittest.cc
index 6598eb4..0d7fa52 100644
--- a/src/profiling/perf/event_config_unittest.cc
+++ b/src/profiling/perf/event_config_unittest.cc
@@ -32,9 +32,8 @@
namespace profiling {
namespace {
-static DataSourceConfig ConfigForTid(int32_t tid) {
+static DataSourceConfig CreateEmptyConfig() {
protozero::HeapBuffered<protos::pbzero::PerfEventConfig> pb_config;
- pb_config->set_tid(tid);
protozero::HeapBuffered<protos::pbzero::DataSourceConfig> ds_config;
ds_config->set_perf_event_config_raw(pb_config.SerializeAsString());
DataSourceConfig cfg;
@@ -42,17 +41,8 @@
return cfg;
}
-TEST(EventConfigTest, TidRequired) {
- // Doesn't pass validation without a TID
- DataSourceConfig cfg;
- ASSERT_TRUE(cfg.ParseFromString(""));
-
- base::Optional<EventConfig> event_config = EventConfig::Create(cfg);
- ASSERT_FALSE(event_config.has_value());
-}
-
TEST(EventConfigTest, AttrStructConstructed) {
- auto cfg = ConfigForTid(42);
+ auto cfg = CreateEmptyConfig();
base::Optional<EventConfig> event_config = EventConfig::Create(cfg);
ASSERT_TRUE(event_config.has_value());
diff --git a/src/profiling/perf/event_reader.cc b/src/profiling/perf/event_reader.cc
index 7bc5ccf..a2d0e87 100644
--- a/src/profiling/perf/event_reader.cc
+++ b/src/profiling/perf/event_reader.cc
@@ -23,6 +23,7 @@
#include <unistd.h>
#include "perfetto/ext/base/utils.h"
+#include "src/profiling/perf/unwind_support.h"
namespace perfetto {
namespace profiling {
@@ -48,10 +49,15 @@
syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags));
}
+// TODO(rsavitski): one EventConfig will correspond to N perf_event_open calls
+// in the general case. Does it make sense to keep a single function which does
+// the N calls, and then returns the group leader's fd? What about cases where
+// we have >1 pid or >1 cpu to open for? Should the entire EventReader be
+// cpu-scoped?
base::ScopedFile PerfEventOpen(const EventConfig& event_cfg) {
base::ScopedFile perf_fd{
- perf_event_open(event_cfg.perf_attr(), event_cfg.target_tid(),
- /*cpu=*/-1, /*group_fd=*/-1, PERF_FLAG_FD_CLOEXEC)};
+ perf_event_open(event_cfg.perf_attr(), /*pid=*/-1, event_cfg.target_cpu(),
+ /*group_fd=*/-1, PERF_FLAG_FD_CLOEXEC)};
return perf_fd;
}
@@ -195,7 +201,7 @@
void EventReader::ParseNextSampleBatch() {
std::vector<char> data = ring_buffer_.ReadAvailable();
if (data.size() == 0) {
- PERFETTO_LOG("WIP: no samples");
+ PERFETTO_LOG("no samples (work in progress)");
return;
}
@@ -217,7 +223,7 @@
if (event_hdr->type == PERF_RECORD_SAMPLE) {
ParsePerfRecordSample(sample_start, event_hdr->size);
} else {
- PERFETTO_ELOG("WIP: unsupported event type");
+ PERFETTO_ELOG("Unsupported event type (work in progress)");
}
*ptr = sample_start + event_hdr->size;
@@ -229,9 +235,9 @@
size_t sample_size) {
const perf_event_attr* cfg = event_cfg_.perf_attr();
- if (cfg->sample_type &
- (~uint64_t(PERF_SAMPLE_TID | PERF_SAMPLE_STACK_USER))) {
- PERFETTO_ELOG("WIP: unsupported sampling option.");
+ if (cfg->sample_type & (~uint64_t(PERF_SAMPLE_TID | PERF_SAMPLE_STACK_USER |
+ PERF_SAMPLE_REGS_USER))) {
+ PERFETTO_ELOG("Unsupported sampling option (work in progress)");
return;
}
@@ -249,6 +255,16 @@
PERFETTO_LOG("tid: %" PRIu32 "", tid);
}
+ if (cfg->sample_type & PERF_SAMPLE_REGS_USER) {
+ auto parsed_regs = ReadPerfUserRegsData(&parse_pos);
+
+ if (parsed_regs) {
+ parsed_regs->IterateRegisters([](const char* name, uint64_t value) {
+ PERFETTO_LOG("reg[%s]: %" PRIx64 "", name, value);
+ });
+ }
+ }
+
if (cfg->sample_type & PERF_SAMPLE_STACK_USER) {
uint64_t max_stack_size; // the requested size
parse_pos = ReadValue(&max_stack_size, parse_pos);
diff --git a/src/profiling/perf/event_reader.h b/src/profiling/perf/event_reader.h
index 537f489..fa9b96b 100644
--- a/src/profiling/perf/event_reader.h
+++ b/src/profiling/perf/event_reader.h
@@ -86,7 +86,7 @@
EventReader(EventReader&&) noexcept;
EventReader& operator=(EventReader&&) noexcept;
- // TODO(rsavitski): temporary.
+ // TODO(rsavitski): temporary one-shot parser for development purposes.
void ParseNextSampleBatch();
private:
diff --git a/src/profiling/perf/perf_producer.cc b/src/profiling/perf/perf_producer.cc
index dd5d642..e544f86 100644
--- a/src/profiling/perf/perf_producer.cc
+++ b/src/profiling/perf/perf_producer.cc
@@ -66,20 +66,6 @@
return;
}
- std::string maps_path = std::string("/proc/") +
- std::to_string(event_config->target_tid()) +
- std::string("/maps");
- auto maps_fd = base::OpenFile(maps_path, O_RDONLY);
- if (!maps_fd)
- PERFETTO_PLOG("failed /proc/pid/maps open (proceeding)");
-
- std::string mem_path = std::string("/proc/") +
- std::to_string(event_config->target_tid()) +
- std::string("/mem");
- auto mem_fd = base::OpenFile(mem_path, O_RDONLY);
- if (!mem_fd)
- PERFETTO_PLOG("failed /proc/pid/mem open (proceeding)");
-
base::Optional<EventReader> event_reader =
EventReader::ConfigureEvents(event_config.value());
if (!event_reader.has_value()) {
@@ -90,8 +76,7 @@
// Build the DataSource instance.
auto it_inserted = data_sources_.emplace(
std::piecewise_construct, std::forward_as_tuple(instance_id),
- std::forward_as_tuple(std::move(event_reader.value()), std::move(maps_fd),
- std::move(mem_fd)));
+ std::forward_as_tuple(std::move(event_reader.value())));
PERFETTO_DCHECK(it_inserted.second);
}
diff --git a/src/profiling/perf/perf_producer.h b/src/profiling/perf/perf_producer.h
index d028c75..e373836 100644
--- a/src/profiling/perf/perf_producer.h
+++ b/src/profiling/perf/perf_producer.h
@@ -66,22 +66,13 @@
kConnected,
};
- // TODO(rsavitski): proc-fds need to live elsewhere, as they can be shared
- // across data sources. We might also have arbitrarily many tasks handled
- // by one data source (if scoping events to a cpu).
struct DataSource {
- DataSource(EventReader _event_reader,
- base::ScopedFile _maps_fd,
- base::ScopedFile _mem_fd)
- : event_reader(std::move(_event_reader)),
- maps_fd(std::move(_maps_fd)),
- mem_fd(std::move(_mem_fd)) {}
+ DataSource(EventReader _event_reader)
+ : event_reader(std::move(_event_reader)) {}
+ // TODO(rsavitski): current thinking is an EventReader per cpu-scoped ring
+ // buffer. And a central bookkeeper.
EventReader event_reader;
-
- // note: currently populated, but unused.
- base::ScopedFile maps_fd;
- base::ScopedFile mem_fd;
};
void ConnectService();
diff --git a/src/profiling/perf/unwind_support.cc b/src/profiling/perf/unwind_support.cc
new file mode 100644
index 0000000..47dc3c0
--- /dev/null
+++ b/src/profiling/perf/unwind_support.cc
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/profiling/perf/unwind_support.h"
+
+#include <inttypes.h>
+#include <linux/perf_event.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <memory>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/MachineArm.h>
+#include <unwindstack/MachineArm64.h>
+#include <unwindstack/Regs.h>
+#include <unwindstack/RegsArm.h>
+#include <unwindstack/RegsArm64.h>
+#include <unwindstack/UserArm.h>
+#include <unwindstack/UserArm64.h>
+
+// TODO(rsavitski): this includes the kernel uapi constant definitions (for
+// register sampling). For now hardcoded for in-tree builds (specifically,
+// bionic/include/kernel/). Standalone builds will need to source the headers
+// from elsewhere (without depending on the host machine's system headers).
+#include <uapi/asm-arm/asm/perf_regs.h>
+#include <uapi/asm-x86/asm/perf_regs.h>
+#define perf_event_arm_regs perf_event_arm64_regs
+#include <uapi/asm-arm64/asm/perf_regs.h>
+#undef perf_event_arm_regs
+
+namespace perfetto {
+namespace profiling {
+
+namespace {
+
+template <typename T>
+const char* ReadValue(T* value_out, const char* ptr) {
+ memcpy(value_out, reinterpret_cast<const void*>(ptr), sizeof(T));
+ return ptr + sizeof(T);
+}
+
+// Supported configurations:
+// * 32 bit daemon, 32 bit userspace
+// * 64 bit daemon, mixed bitness userspace
+// Therefore give the kernel the mask corresponding to our build architecture.
+// Register parsing handles the mixed userspace ABI cases.
+// TODO(rsavitski): cleanly detect 32 bit builds being side-loaded onto a system
+// with 64 bit userspace processes.
+uint64_t PerfUserRegsMask(unwindstack::ArchEnum arch) {
+ // TODO(rsavitski): support the rest of the architectures.
+ switch (arch) {
+ case unwindstack::ARCH_ARM64:
+ return (1ULL << PERF_REG_ARM64_MAX) - 1;
+ case unwindstack::ARCH_ARM:
+ return ((1ULL << PERF_REG_ARM_MAX) - 1);
+ default:
+ PERFETTO_FATAL("Unsupported architecture (work in progress)");
+ }
+}
+
+// Adjusts the given architecture enum based on the ABI (as recorded in the perf
+// sample). Note: we do not support 64 bit samples on a 32 bit daemon build, so
+// this only converts from 64 bit to 32 bit architectures.
+unwindstack::ArchEnum ArchForAbi(unwindstack::ArchEnum arch, uint64_t abi) {
+ if (arch == unwindstack::ARCH_ARM64 && abi == PERF_SAMPLE_REGS_ABI_32) {
+ return unwindstack::ARCH_ARM;
+ }
+ if (arch == unwindstack::ARCH_X86_64 && abi == PERF_SAMPLE_REGS_ABI_32) {
+ return unwindstack::ARCH_X86;
+ }
+ return arch;
+}
+
+// Register values as an array, indexed using the kernel uapi perf_events.h enum
+// values. Unsampled values will be left as zeroes.
+// TODO(rsavitski): support all relevant architectures (allocate enough space
+// for the widest register bank).
+struct RawRegisterData {
+ static constexpr uint64_t kMaxSize = PERF_REG_ARM64_MAX;
+ uint64_t regs[kMaxSize] = {};
+};
+
+std::unique_ptr<unwindstack::Regs> ToLibUnwindstackRegs(
+ const RawRegisterData& raw_regs,
+ unwindstack::ArchEnum arch) {
+ // First converts the |RawRegisterData| array to libunwindstack's raw register
+ // format, then constructs the relevant unwindstack::Regs subclass out of the
+ // latter.
+ if (arch == unwindstack::ARCH_ARM64) {
+ static_assert(static_cast<int>(unwindstack::ARM64_REG_R0) ==
+ static_cast<int>(PERF_REG_ARM64_X0),
+ "register layout mismatch");
+ static_assert(static_cast<int>(unwindstack::ARM64_REG_R30) ==
+ static_cast<int>(PERF_REG_ARM64_LR),
+ "register layout mismatch");
+
+ unwindstack::arm64_user_regs arm64_user_regs;
+ memset(&arm64_user_regs, 0, sizeof(arm64_user_regs));
+ memcpy(&arm64_user_regs.regs[unwindstack::ARM64_REG_R0],
+ &raw_regs.regs[PERF_REG_ARM64_X0],
+ sizeof(uint64_t) * (PERF_REG_ARM64_LR - PERF_REG_ARM64_X0 + 1));
+ arm64_user_regs.sp = raw_regs.regs[PERF_REG_ARM64_SP];
+ arm64_user_regs.pc = raw_regs.regs[PERF_REG_ARM64_PC];
+
+ return std::unique_ptr<unwindstack::Regs>(
+ unwindstack::RegsArm64::Read(&arm64_user_regs));
+ }
+
+ if (arch == unwindstack::ARCH_ARM) {
+ static_assert(static_cast<int>(unwindstack::ARM_REG_R0) ==
+ static_cast<int>(PERF_REG_ARM_R0),
+ "register layout mismatch");
+ static_assert(static_cast<int>(unwindstack::ARM_REG_LAST) ==
+ static_cast<int>(PERF_REG_ARM_MAX),
+ "register layout mismatch");
+
+ unwindstack::arm_user_regs arm_user_regs;
+ memset(&arm_user_regs, 0, sizeof(arm_user_regs));
+ for (size_t i = unwindstack::ARM_REG_R0; i < unwindstack::ARM_REG_LAST;
+ i++) {
+ arm_user_regs.regs[i] = static_cast<uint32_t>(raw_regs.regs[i]);
+ }
+
+ return std::unique_ptr<unwindstack::Regs>(
+ unwindstack::RegsArm::Read(&arm_user_regs));
+ }
+
+ PERFETTO_FATAL("Unsupported architecture (work in progress)");
+}
+
+} // namespace
+
+uint64_t PerfUserRegsMaskForCurrentArch() {
+ return PerfUserRegsMask(unwindstack::Regs::CurrentArch());
+}
+
+// Assumes that the sampling was configured with
+// |PerfUserRegsMaskForCurrentArch|.
+std::unique_ptr<unwindstack::Regs> ReadPerfUserRegsData(const char** data) {
+ unwindstack::ArchEnum requested_arch = unwindstack::Regs::CurrentArch();
+
+ // Layout, assuming a sparse bitmask requesting r1 and r15:
+ // [u64 abi] [u64 r1] [u64 r15]
+ const char* parse_pos = *data;
+ uint64_t sampled_abi;
+ parse_pos = ReadValue(&sampled_abi, parse_pos);
+ PERFETTO_LOG("WIP: abi: %" PRIu64 "", sampled_abi);
+
+ // Unpack the densely-packed register values into |RawRegisterData|, which has
+ // a value for every register (unsampled registers will be left at zero).
+ RawRegisterData raw_regs{};
+ uint64_t regs_mask = PerfUserRegsMaskForCurrentArch();
+ for (size_t i = 0; regs_mask && (i < RawRegisterData::kMaxSize); i++) {
+ if (regs_mask & (1u << i)) {
+ parse_pos = ReadValue(&raw_regs.regs[i], parse_pos);
+ }
+ }
+
+ // Special case: we've requested arm64 registers from a 64 bit kernel, but
+ // ended up sampling a 32 bit arm userspace process. The 32 bit execution
+ // state of the target process was saved by the exception entry in an
+ // ISA-specific way. The userspace R0-R14 end up saved as arm64 W0-W14, but
+ // the program counter (R15 on arm32) is still in PERF_REG_ARM64_PC (the 33rd
+ // register). So we can take the kernel-dumped 64 bit register state, reassign
+ // the PC into the R15 slot, and treat the resulting RawRegisterData as an
+ // arm32 register bank. See "Fundamentals of ARMv8-A" (ARM DOC
+ // 100878_0100_en), page 28.
+ if (requested_arch == unwindstack::ARCH_ARM64 &&
+ sampled_abi == PERF_SAMPLE_REGS_ABI_32) {
+ raw_regs.regs[PERF_REG_ARM_PC] = raw_regs.regs[PERF_REG_ARM64_PC];
+ }
+
+ // Adjust caller's parsing position.
+ *data = parse_pos;
+
+ // ABI_NONE means there were no registers (e.g. we've sampled a kernel thread,
+ // which doesn't have userspace registers). We still walk over the empty data
+ // above, but return an empty result to the caller.
+ if (sampled_abi == PERF_SAMPLE_REGS_ABI_NONE) {
+ return nullptr;
+ } else {
+ unwindstack::ArchEnum sampled_arch =
+ ArchForAbi(requested_arch, sampled_abi);
+ return ToLibUnwindstackRegs(raw_regs, sampled_arch);
+ }
+}
+
+} // namespace profiling
+} // namespace perfetto
diff --git a/src/profiling/perf/unwind_support.h b/src/profiling/perf/unwind_support.h
new file mode 100644
index 0000000..f0764d2
--- /dev/null
+++ b/src/profiling/perf/unwind_support.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_PROFILING_PERF_UNWIND_SUPPORT_H_
+#define SRC_PROFILING_PERF_UNWIND_SUPPORT_H_
+
+#include <stdint.h>
+#include <unwindstack/Regs.h>
+
+#include <memory>
+
+#include "perfetto/ext/base/scoped_file.h"
+
+namespace perfetto {
+namespace profiling {
+
+// Returns a bitmask for sampling the userspace register set, used when
+// configuring perf events.
+uint64_t PerfUserRegsMaskForCurrentArch();
+
+// Converts the raw sampled register bytes to libunwindstack's representation
+// (correct arch-dependent subclass). Advances |data| pointer to past the
+// register data. The unique_ptr can be empty, if there were no userspace
+// registers to sample (i.e. we've sampled a kernel thread).
+// TODO(rsavitski): come up with a better signature (also consider how much to
+// isolate libunwindstack types).
+std::unique_ptr<unwindstack::Regs> ReadPerfUserRegsData(const char** data);
+
+} // namespace profiling
+} // namespace perfetto
+
+#endif // SRC_PROFILING_PERF_UNWIND_SUPPORT_H_
diff --git a/src/profiling/symbolizer/BUILD.gn b/src/profiling/symbolizer/BUILD.gn
new file mode 100644
index 0000000..3bbc385
--- /dev/null
+++ b/src/profiling/symbolizer/BUILD.gn
@@ -0,0 +1,48 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("../../../gn/perfetto.gni")
+
+source_set("symbolizer") {
+ public_deps = [
+ "../../../include/perfetto/ext/base",
+ ]
+ deps = [
+ "../../../gn:default_deps",
+ ]
+ sources = [
+ "local_symbolizer.cc",
+ "local_symbolizer.h",
+ "symbolizer.cc",
+ "symbolizer.h",
+ ]
+}
+
+source_set("symbolize_database") {
+ public_deps = [
+ ":symbolizer",
+ "../../../include/perfetto/ext/base",
+ ]
+ deps = [
+ "../../../gn:default_deps",
+ "../../../include/perfetto/protozero",
+ "../../../include/perfetto/trace_processor:trace_processor",
+ "../../../protos/perfetto/trace:zero",
+ "../../../protos/perfetto/trace/profiling:zero",
+ ]
+ sources = [
+ "symbolize_database.cc",
+ "symbolize_database.h",
+ ]
+}
diff --git a/tools/trace_to_text/local_symbolizer.cc b/src/profiling/symbolizer/local_symbolizer.cc
similarity index 98%
rename from tools/trace_to_text/local_symbolizer.cc
rename to src/profiling/symbolizer/local_symbolizer.cc
index 3daa0be..1874df1 100644
--- a/tools/trace_to_text/local_symbolizer.cc
+++ b/src/profiling/symbolizer/local_symbolizer.cc
@@ -20,7 +20,7 @@
// This translation unit is built only on Linux. See //gn/BUILD.gn.
#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
-#include "tools/trace_to_text/local_symbolizer.h"
+#include "src/profiling/symbolizer/local_symbolizer.h"
#include "perfetto/ext/base/string_splitter.h"
#include "perfetto/ext/base/string_utils.h"
@@ -35,7 +35,7 @@
#include <unistd.h>
namespace perfetto {
-namespace trace_to_text {
+namespace profiling {
namespace {
@@ -60,7 +60,6 @@
return lines;
}
-
struct Elf32 {
using Ehdr = Elf32_Ehdr;
using Shdr = Elf32_Shdr;
@@ -402,7 +401,7 @@
LocalSymbolizer::~LocalSymbolizer() = default;
-} // namespace trace_to_text
+} // namespace profiling
} // namespace perfetto
#endif // PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
diff --git a/tools/trace_to_text/local_symbolizer.h b/src/profiling/symbolizer/local_symbolizer.h
similarity index 90%
rename from tools/trace_to_text/local_symbolizer.h
rename to src/profiling/symbolizer/local_symbolizer.h
index e1eef9e..eb3a717 100644
--- a/tools/trace_to_text/local_symbolizer.h
+++ b/src/profiling/symbolizer/local_symbolizer.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef TOOLS_TRACE_TO_TEXT_LOCAL_SYMBOLIZER_H_
-#define TOOLS_TRACE_TO_TEXT_LOCAL_SYMBOLIZER_H_
+#ifndef SRC_PROFILING_SYMBOLIZER_LOCAL_SYMBOLIZER_H_
+#define SRC_PROFILING_SYMBOLIZER_LOCAL_SYMBOLIZER_H_
#include <map>
#include <string>
@@ -23,10 +23,10 @@
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/pipe.h"
-#include "perfetto/profiling/symbolizer.h"
+#include "src/profiling/symbolizer/symbolizer.h"
namespace perfetto {
-namespace trace_to_text {
+namespace profiling {
class LocalBinaryFinder {
public:
@@ -93,7 +93,7 @@
LocalBinaryFinder finder_;
};
-} // namespace trace_to_text
+} // namespace profiling
} // namespace perfetto
-#endif // TOOLS_TRACE_TO_TEXT_LOCAL_SYMBOLIZER_H_
+#endif // SRC_PROFILING_SYMBOLIZER_LOCAL_SYMBOLIZER_H_
diff --git a/src/profiling/symbolizer/symbolize_database.cc b/src/profiling/symbolizer/symbolize_database.cc
new file mode 100644
index 0000000..39e09a4
--- /dev/null
+++ b/src/profiling/symbolizer/symbolize_database.cc
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/profiling/symbolizer/symbolize_database.h"
+
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "perfetto/base/logging.h"
+
+#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "perfetto/trace_processor/trace_processor.h"
+
+#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+namespace profiling {
+
+namespace {
+using Iterator = trace_processor::TraceProcessor::Iterator;
+
+constexpr const char* kQueryUnsymbolized =
+ "select spm.name, spm.build_id, spf.rel_pc "
+ "from stack_profile_frame spf "
+ "join stack_profile_mapping spm "
+ "on spf.mapping = spm.id "
+ "where spm.build_id != '' and spf.symbol_set_id == 0";
+
+using NameAndBuildIdPair = std::pair<std::string, std::string>;
+
+std::string FromHex(const char* str, size_t size) {
+ if (size % 2) {
+ PERFETTO_DFATAL_OR_ELOG("Failed to parse hex %s", str);
+ return "";
+ }
+ std::string result(size / 2, '\0');
+ for (size_t i = 0; i < size; i += 2) {
+ char hex_byte[3];
+ hex_byte[0] = str[i];
+ hex_byte[1] = str[i + 1];
+ hex_byte[2] = '\0';
+ char* end;
+ long int byte = strtol(hex_byte, &end, 16);
+ if (*end != '\0') {
+ PERFETTO_DFATAL_OR_ELOG("Failed to parse hex %s", str);
+ return "";
+ }
+ result[i / 2] = static_cast<char>(byte);
+ }
+ return result;
+}
+
+std::string FromHex(const std::string& str) {
+ return FromHex(str.c_str(), str.size());
+}
+
+std::map<NameAndBuildIdPair, std::vector<uint64_t>> GetUnsymbolizedFrames(
+ trace_processor::TraceProcessor* tp) {
+ std::map<std::pair<std::string, std::string>, std::vector<uint64_t>> res;
+ Iterator it = tp->ExecuteQuery(kQueryUnsymbolized);
+ while (it.Next()) {
+ auto name_and_buildid =
+ std::make_pair(it.Get(0).string_value, FromHex(it.Get(1).string_value));
+ int64_t rel_pc = it.Get(2).long_value;
+ res[name_and_buildid].emplace_back(rel_pc);
+ }
+ if (!it.Status().ok()) {
+ PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
+ it.Status().message().c_str());
+ return {};
+ }
+ return res;
+}
+} // namespace
+
+void SymbolizeDatabase(trace_processor::TraceProcessor* tp,
+ Symbolizer* symbolizer,
+ std::function<void(const std::string&)> callback) {
+ PERFETTO_CHECK(symbolizer);
+ auto unsymbolized = GetUnsymbolizedFrames(tp);
+ for (auto it = unsymbolized.cbegin(); it != unsymbolized.cend(); ++it) {
+ const auto& name_and_buildid = it->first;
+ const std::vector<uint64_t>& rel_pcs = it->second;
+ auto res = symbolizer->Symbolize(name_and_buildid.first,
+ name_and_buildid.second, rel_pcs);
+ if (res.empty())
+ continue;
+
+ protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket> packet;
+ auto* module_symbols = packet->set_module_symbols();
+ module_symbols->set_path(name_and_buildid.first);
+ module_symbols->set_build_id(name_and_buildid.second);
+ PERFETTO_DCHECK(res.size() == rel_pcs.size());
+ for (size_t i = 0; i < res.size(); ++i) {
+ auto* address_symbols = module_symbols->add_address_symbols();
+ address_symbols->set_address(rel_pcs[i]);
+ for (const SymbolizedFrame& frame : res[i]) {
+ auto* line = address_symbols->add_lines();
+ line->set_function_name(frame.function_name);
+ line->set_source_file_name(frame.file_name);
+ line->set_line_number(frame.line);
+ }
+ }
+ callback(packet.SerializeAsString());
+ }
+}
+
+} // namespace profiling
+} // namespace perfetto
diff --git a/src/profiling/symbolizer/symbolize_database.h b/src/profiling/symbolizer/symbolize_database.h
new file mode 100644
index 0000000..6c9ab1b
--- /dev/null
+++ b/src/profiling/symbolizer/symbolize_database.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_PROFILING_SYMBOLIZER_SYMBOLIZE_DATABASE_H_
+#define SRC_PROFILING_SYMBOLIZER_SYMBOLIZE_DATABASE_H_
+
+#include "src/profiling/symbolizer/symbolizer.h"
+
+#include <functional>
+#include <string>
+
+namespace perfetto {
+namespace trace_processor {
+class TraceProcessor;
+}
+namespace profiling {
+// Generate ModuleSymbol protos for all unsymbolized frames in the database.
+// Wrap them in proto-encoded TracePackets messages and call callback.
+void SymbolizeDatabase(trace_processor::TraceProcessor* tp,
+ Symbolizer* symbolizer,
+ std::function<void(const std::string&)> callback);
+} // namespace profiling
+} // namespace perfetto
+
+#endif // SRC_PROFILING_SYMBOLIZER_SYMBOLIZE_DATABASE_H_
diff --git a/tools/trace_to_text/symbolizer.cc b/src/profiling/symbolizer/symbolizer.cc
similarity index 87%
rename from tools/trace_to_text/symbolizer.cc
rename to src/profiling/symbolizer/symbolizer.cc
index 1cd83cb..0aa5d8b 100644
--- a/tools/trace_to_text/symbolizer.cc
+++ b/src/profiling/symbolizer/symbolizer.cc
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include "perfetto/profiling/symbolizer.h"
+#include "src/profiling/symbolizer/symbolizer.h"
namespace perfetto {
-namespace trace_to_text {
+namespace profiling {
Symbolizer::~Symbolizer() = default;
-} // namespace trace_to_text
+} // namespace profiling
} // namespace perfetto
diff --git a/include/perfetto/profiling/symbolizer.h b/src/profiling/symbolizer/symbolizer.h
similarity index 80%
rename from include/perfetto/profiling/symbolizer.h
rename to src/profiling/symbolizer/symbolizer.h
index 2a5a79e..ff4ee50 100644
--- a/include/perfetto/profiling/symbolizer.h
+++ b/src/profiling/symbolizer/symbolizer.h
@@ -14,17 +14,15 @@
* limitations under the License.
*/
-#ifndef INCLUDE_PERFETTO_PROFILING_SYMBOLIZER_H_
-#define INCLUDE_PERFETTO_PROFILING_SYMBOLIZER_H_
+#ifndef SRC_PROFILING_SYMBOLIZER_SYMBOLIZER_H_
+#define SRC_PROFILING_SYMBOLIZER_SYMBOLIZER_H_
#include <map>
#include <string>
#include <vector>
-// TODO(135923303): do not depend on anything in this file as it will be
-// removed as part of fixing b/135923303.
namespace perfetto {
-namespace trace_to_text {
+namespace profiling {
struct SymbolizedFrame {
std::string function_name;
@@ -46,7 +44,7 @@
virtual ~Symbolizer();
};
-} // namespace trace_to_text
+} // namespace profiling
} // namespace perfetto
-#endif // INCLUDE_PERFETTO_PROFILING_SYMBOLIZER_H_
+#endif // SRC_PROFILING_SYMBOLIZER_SYMBOLIZER_H_
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index df2329f..cb2f5cf 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -78,11 +78,11 @@
sources = [
"args_tracker.cc",
"args_tracker.h",
- "binder_tracker.cc",
- "binder_tracker.h",
"chunked_trace_reader.h",
"clock_tracker.cc",
"clock_tracker.h",
+ "destructible.cc",
+ "destructible.h",
"event_tracker.cc",
"event_tracker.h",
"forwarding_trace_parser.cc",
@@ -99,14 +99,9 @@
"importers/ftrace/ftrace_tokenizer.h",
"importers/ftrace/sched_event_tracker.h",
"importers/fuchsia/fuchsia_provider_view.h",
- "importers/proto/android_probes_module.h",
- "importers/proto/android_probes_parser.h",
"importers/proto/args_table_utils.cc",
"importers/proto/args_table_utils.h",
"importers/proto/chrome_compositor_scheduler_state.descriptor.h",
- "importers/proto/heap_graph_module.h",
- "importers/proto/heap_graph_tracker.h",
- "importers/proto/heap_graph_walker.h",
"importers/proto/packet_sequence_state.h",
"importers/proto/proto_importer_module.cc",
"importers/proto/proto_importer_module.h",
@@ -115,8 +110,6 @@
"importers/proto/proto_trace_parser.h",
"importers/proto/proto_trace_tokenizer.cc",
"importers/proto/proto_trace_tokenizer.h",
- "importers/proto/system_probes_module.h",
- "importers/proto/system_probes_parser.h",
"importers/proto/track_event_module.cc",
"importers/proto/track_event_module.h",
"importers/proto/track_event_parser.cc",
@@ -153,12 +146,12 @@
]
deps = [
- ":common",
":descriptors",
"../../gn:default_deps",
"../../gn:zlib",
"../base",
"../protozero",
+ "containers",
"tables",
]
public_deps = [
@@ -190,6 +183,8 @@
}
if (enable_perfetto_trace_processor_ftrace) {
sources += [
+ "importers/ftrace/binder_tracker.cc",
+ "importers/ftrace/binder_tracker.h",
"importers/ftrace/ftrace_descriptors.cc",
"importers/ftrace/ftrace_module_impl.cc",
"importers/ftrace/ftrace_parser.cc",
@@ -203,26 +198,6 @@
enable_perfetto_trace_processor_fuchsia) {
sources += [ "ftrace_utils.cc" ]
}
- if (enable_perfetto_trace_processor_system_probes) {
- sources += [
- "importers/proto/system_probes_module.cc",
- "importers/proto/system_probes_parser.cc",
- ]
- deps += [ "../../include/perfetto/ext/traced:sys_stats_counters" ]
- }
- if (enable_perfetto_trace_processor_android_probes) {
- sources += [
- "importers/proto/android_probes_module.cc",
- "importers/proto/android_probes_parser.cc",
- ]
- }
- if (enable_perfetto_trace_processor_heap_graphs) {
- sources += [
- "importers/proto/heap_graph_module.cc",
- "importers/proto/heap_graph_tracker.cc",
- "importers/proto/heap_graph_walker.cc",
- ]
- }
if (enable_perfetto_trace_processor_fuchsia) {
sources += [
"importers/fuchsia/fuchsia_provider_view.cc",
@@ -247,10 +222,24 @@
source_set("storage_full") {
sources = [
+ "importers/proto/android_probes_module.cc",
+ "importers/proto/android_probes_module.h",
+ "importers/proto/android_probes_parser.cc",
+ "importers/proto/android_probes_parser.h",
"importers/proto/graphics_event_module.cc",
"importers/proto/graphics_event_module.h",
"importers/proto/graphics_event_parser.cc",
"importers/proto/graphics_event_parser.h",
+ "importers/proto/heap_graph_module.cc",
+ "importers/proto/heap_graph_module.h",
+ "importers/proto/heap_graph_tracker.cc",
+ "importers/proto/heap_graph_tracker.h",
+ "importers/proto/heap_graph_walker.cc",
+ "importers/proto/heap_graph_walker.h",
+ "importers/proto/system_probes_module.cc",
+ "importers/proto/system_probes_module.h",
+ "importers/proto/system_probes_parser.cc",
+ "importers/proto/system_probes_parser.h",
"importers/proto/vulkan_memory_tracker.cc",
"importers/proto/vulkan_memory_tracker.h",
"register_additional_modules.cc",
@@ -260,6 +249,7 @@
":storage_minimal",
]
deps = [
+ "../../include/perfetto/ext/traced:sys_stats_counters",
"../../protos/perfetto/common:zero",
"../../protos/perfetto/trace:zero",
"../../protos/perfetto/trace/android:zero",
@@ -270,6 +260,20 @@
if (enable_perfetto_trace_processor_json) {
public_deps += [ "../../gn:jsoncpp" ]
}
+
+ # Include these sources only if they are not already included in
+ # storage_minimal.
+ # TODO(khokhlov): Remove this 'if' when modules that use this tracker are
+ # migrated to storage_full.
+ if (!enable_perfetto_trace_processor_syscalls) {
+ sources += [
+ "syscall_tracker.cc",
+ "syscalls_aarch32.h",
+ "syscalls_aarch64.h",
+ "syscalls_armeabi.h",
+ "syscalls_x86_64.h",
+ ]
+ }
}
if (enable_perfetto_trace_processor_json) {
@@ -303,8 +307,6 @@
"filtered_row_index.h",
"gfp_flags.cc",
"gfp_flags.h",
- "heap_profile_allocation_table.cc",
- "heap_profile_allocation_table.h",
"instants_table.cc",
"instants_table.h",
"metadata_table.cc",
@@ -343,7 +345,6 @@
]
deps = [
- ":common",
":storage_full",
"../../gn:default_deps",
"../../gn:sqlite",
@@ -372,21 +373,6 @@
}
}
-# TODO(lalitm): we need to find a better home for the classes here.
-source_set("common") {
- sources = [
- "null_term_string_view.h",
- "string_pool.cc",
- "string_pool.h",
- ]
-
- deps = [
- "../../gn:default_deps",
- "../base",
- "../protozero",
- ]
-}
-
if (enable_perfetto_trace_processor_metrics) { # shell requires metrics.
perfetto_host_executable("trace_processor_shell") {
deps = [
@@ -421,17 +407,15 @@
"forwarding_trace_parser_unittest.cc",
"heap_profile_tracker_unittest.cc",
"importers/proto/args_table_utils_unittest.cc",
+ "importers/proto/heap_graph_walker_unittest.cc",
"importers/proto/proto_trace_parser_unittest.cc",
"importers/systrace/systrace_parser_unittest.cc",
- "null_term_string_view_unittest.cc",
"process_tracker_unittest.cc",
"protozero_to_text_unittests.cc",
"slice_tracker_unittest.cc",
- "string_pool_unittest.cc",
"trace_sorter_unittest.cc",
]
deps = [
- ":common",
":descriptors",
":protozero_to_text",
":storage_full",
@@ -452,6 +436,7 @@
"../base",
"../protozero",
"../protozero:testing_messages_zero",
+ "containers:unittests",
"db:unittests",
"tables:unittests",
]
@@ -496,9 +481,6 @@
"thread_table_unittest.cc",
]
}
- if (enable_perfetto_trace_processor_heap_graphs) {
- sources += [ "importers/proto/heap_graph_walker_unittest.cc" ]
- }
if (enable_perfetto_trace_processor_fuchsia) {
sources += [ "importers/fuchsia/fuchsia_trace_utils_unittest.cc" ]
}
@@ -529,6 +511,24 @@
}
}
+if (enable_perfetto_trace_processor_json) {
+ source_set("storage_minimal_smoke_tests") {
+ testonly = true
+ sources = [
+ "storage_minimal_smoke_test.cc",
+ ]
+ deps = [
+ ":export_json",
+ ":storage_minimal",
+ "../../gn:default_deps",
+ "../../gn:gtest_and_gmock",
+ "../../gn:gtest_main",
+ "../../gn:jsoncpp",
+ "../base:test_support",
+ ]
+ }
+}
+
perfetto_fuzzer_test("trace_processor_fuzzer") {
testonly = true
sources = [
diff --git a/src/trace_processor/containers/BUILD.gn b/src/trace_processor/containers/BUILD.gn
new file mode 100644
index 0000000..32e0d28
--- /dev/null
+++ b/src/trace_processor/containers/BUILD.gn
@@ -0,0 +1,68 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("../../../gn/test.gni")
+
+source_set("containers") {
+ sources = [
+ "bit_vector.cc",
+ "bit_vector.h",
+ "bit_vector_iterators.cc",
+ "bit_vector_iterators.h",
+ "null_term_string_view.h",
+ "row_map.cc",
+ "row_map.h",
+ "sparse_vector.h",
+ "string_pool.cc",
+ "string_pool.h",
+ ]
+ deps = [
+ "../../../gn:default_deps",
+ "../../../include/perfetto/base",
+ "../../../include/perfetto/ext/base",
+ "../../../include/perfetto/protozero",
+ ]
+}
+
+perfetto_unittest_source_set("unittests") {
+ testonly = true
+ sources = [
+ "bit_vector_unittest.cc",
+ "null_term_string_view_unittest.cc",
+ "row_map_unittest.cc",
+ "sparse_vector_unittest.cc",
+ "string_pool_unittest.cc",
+ ]
+ deps = [
+ ":containers",
+ "../../../gn:default_deps",
+ "../../../gn:gtest_and_gmock",
+ ]
+}
+
+if (enable_perfetto_benchmarks) {
+ source_set("benchmarks") {
+ testonly = true
+ deps = [
+ ":containers",
+ "../../../gn:benchmark",
+ "../../../gn:default_deps",
+ ]
+ sources = [
+ "bit_vector_benchmark.cc",
+ "row_map_benchmark.cc",
+ "sparse_vector_benchmark.cc",
+ ]
+ }
+}
diff --git a/src/trace_processor/db/bit_vector.cc b/src/trace_processor/containers/bit_vector.cc
similarity index 94%
rename from src/trace_processor/db/bit_vector.cc
rename to src/trace_processor/containers/bit_vector.cc
index 0d2f3d8..0ec5bcc 100644
--- a/src/trace_processor/db/bit_vector.cc
+++ b/src/trace_processor/containers/bit_vector.cc
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#include "src/trace_processor/db/bit_vector.h"
+#include "src/trace_processor/containers/bit_vector.h"
-#include "src/trace_processor/db/bit_vector_iterators.h"
+#include "src/trace_processor/containers/bit_vector_iterators.h"
namespace perfetto {
namespace trace_processor {
diff --git a/src/trace_processor/db/bit_vector.h b/src/trace_processor/containers/bit_vector.h
similarity index 98%
rename from src/trace_processor/db/bit_vector.h
rename to src/trace_processor/containers/bit_vector.h
index bed71a6..58b9e23 100644
--- a/src/trace_processor/db/bit_vector.h
+++ b/src/trace_processor/containers/bit_vector.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef SRC_TRACE_PROCESSOR_DB_BIT_VECTOR_H_
-#define SRC_TRACE_PROCESSOR_DB_BIT_VECTOR_H_
+#ifndef SRC_TRACE_PROCESSOR_CONTAINERS_BIT_VECTOR_H_
+#define SRC_TRACE_PROCESSOR_CONTAINERS_BIT_VECTOR_H_
#include <stddef.h>
#include <stdint.h>
@@ -655,4 +655,4 @@
} // namespace trace_processor
} // namespace perfetto
-#endif // SRC_TRACE_PROCESSOR_DB_BIT_VECTOR_H_
+#endif // SRC_TRACE_PROCESSOR_CONTAINERS_BIT_VECTOR_H_
diff --git a/src/trace_processor/db/bit_vector_benchmark.cc b/src/trace_processor/containers/bit_vector_benchmark.cc
similarity index 98%
rename from src/trace_processor/db/bit_vector_benchmark.cc
rename to src/trace_processor/containers/bit_vector_benchmark.cc
index 54c00f9..b4a0c27 100644
--- a/src/trace_processor/db/bit_vector_benchmark.cc
+++ b/src/trace_processor/containers/bit_vector_benchmark.cc
@@ -16,7 +16,7 @@
#include <benchmark/benchmark.h>
-#include "src/trace_processor/db/bit_vector.h"
+#include "src/trace_processor/containers/bit_vector.h"
namespace {
@@ -36,7 +36,7 @@
b->Arg(1234567);
}
}
-}
+} // namespace
static void BM_BitVectorAppendTrue(benchmark::State& state) {
BitVector bv;
diff --git a/src/trace_processor/db/bit_vector_iterators.cc b/src/trace_processor/containers/bit_vector_iterators.cc
similarity index 98%
rename from src/trace_processor/db/bit_vector_iterators.cc
rename to src/trace_processor/containers/bit_vector_iterators.cc
index 281384c..5424365 100644
--- a/src/trace_processor/db/bit_vector_iterators.cc
+++ b/src/trace_processor/containers/bit_vector_iterators.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "src/trace_processor/db/bit_vector_iterators.h"
+#include "src/trace_processor/containers/bit_vector_iterators.h"
namespace perfetto {
namespace trace_processor {
diff --git a/src/trace_processor/db/bit_vector_iterators.h b/src/trace_processor/containers/bit_vector_iterators.h
similarity index 95%
rename from src/trace_processor/db/bit_vector_iterators.h
rename to src/trace_processor/containers/bit_vector_iterators.h
index 365e8ef..0047812 100644
--- a/src/trace_processor/db/bit_vector_iterators.h
+++ b/src/trace_processor/containers/bit_vector_iterators.h
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#ifndef SRC_TRACE_PROCESSOR_DB_BIT_VECTOR_ITERATORS_H_
-#define SRC_TRACE_PROCESSOR_DB_BIT_VECTOR_ITERATORS_H_
+#ifndef SRC_TRACE_PROCESSOR_CONTAINERS_BIT_VECTOR_ITERATORS_H_
+#define SRC_TRACE_PROCESSOR_CONTAINERS_BIT_VECTOR_ITERATORS_H_
-#include "src/trace_processor/db/bit_vector.h"
+#include "src/trace_processor/containers/bit_vector.h"
namespace perfetto {
namespace trace_processor {
@@ -187,4 +187,4 @@
} // namespace trace_processor
} // namespace perfetto
-#endif // SRC_TRACE_PROCESSOR_DB_BIT_VECTOR_ITERATORS_H_
+#endif // SRC_TRACE_PROCESSOR_CONTAINERS_BIT_VECTOR_ITERATORS_H_
diff --git a/src/trace_processor/db/bit_vector_unittest.cc b/src/trace_processor/containers/bit_vector_unittest.cc
similarity index 98%
rename from src/trace_processor/db/bit_vector_unittest.cc
rename to src/trace_processor/containers/bit_vector_unittest.cc
index 7b5aad7..e185afd 100644
--- a/src/trace_processor/db/bit_vector_unittest.cc
+++ b/src/trace_processor/containers/bit_vector_unittest.cc
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-#include "src/trace_processor/db/bit_vector.h"
+#include "src/trace_processor/containers/bit_vector.h"
#include <random>
-#include "src/trace_processor/db/bit_vector_iterators.h"
+#include "src/trace_processor/containers/bit_vector_iterators.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
diff --git a/src/trace_processor/null_term_string_view.h b/src/trace_processor/containers/null_term_string_view.h
similarity index 91%
rename from src/trace_processor/null_term_string_view.h
rename to src/trace_processor/containers/null_term_string_view.h
index f576006..5ae5a29 100644
--- a/src/trace_processor/null_term_string_view.h
+++ b/src/trace_processor/containers/null_term_string_view.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef SRC_TRACE_PROCESSOR_NULL_TERM_STRING_VIEW_H_
-#define SRC_TRACE_PROCESSOR_NULL_TERM_STRING_VIEW_H_
+#ifndef SRC_TRACE_PROCESSOR_CONTAINERS_NULL_TERM_STRING_VIEW_H_
+#define SRC_TRACE_PROCESSOR_CONTAINERS_NULL_TERM_STRING_VIEW_H_
#include "perfetto/ext/base/string_view.h"
@@ -57,4 +57,4 @@
} // namespace trace_processor
} // namespace perfetto
-#endif // SRC_TRACE_PROCESSOR_NULL_TERM_STRING_VIEW_H_
+#endif // SRC_TRACE_PROCESSOR_CONTAINERS_NULL_TERM_STRING_VIEW_H_
diff --git a/src/trace_processor/null_term_string_view_unittest.cc b/src/trace_processor/containers/null_term_string_view_unittest.cc
similarity index 97%
rename from src/trace_processor/null_term_string_view_unittest.cc
rename to src/trace_processor/containers/null_term_string_view_unittest.cc
index c8cc29e..eb4d23f 100644
--- a/src/trace_processor/null_term_string_view_unittest.cc
+++ b/src/trace_processor/containers/null_term_string_view_unittest.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "src/trace_processor/null_term_string_view.h"
+#include "src/trace_processor/containers/null_term_string_view.h"
#include "test/gtest_and_gmock.h"
diff --git a/src/trace_processor/db/row_map.cc b/src/trace_processor/containers/row_map.cc
similarity index 98%
rename from src/trace_processor/db/row_map.cc
rename to src/trace_processor/containers/row_map.cc
index cb16e4d..b10d0cb 100644
--- a/src/trace_processor/db/row_map.cc
+++ b/src/trace_processor/containers/row_map.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "src/trace_processor/db/row_map.h"
+#include "src/trace_processor/containers/row_map.h"
namespace perfetto {
namespace trace_processor {
diff --git a/src/trace_processor/db/row_map.h b/src/trace_processor/containers/row_map.h
similarity index 95%
rename from src/trace_processor/db/row_map.h
rename to src/trace_processor/containers/row_map.h
index 9b2805e..00ad7d2 100644
--- a/src/trace_processor/db/row_map.h
+++ b/src/trace_processor/containers/row_map.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef SRC_TRACE_PROCESSOR_DB_ROW_MAP_H_
-#define SRC_TRACE_PROCESSOR_DB_ROW_MAP_H_
+#ifndef SRC_TRACE_PROCESSOR_CONTAINERS_ROW_MAP_H_
+#define SRC_TRACE_PROCESSOR_CONTAINERS_ROW_MAP_H_
#include <stdint.h>
@@ -24,8 +24,8 @@
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/optional.h"
-#include "src/trace_processor/db/bit_vector.h"
-#include "src/trace_processor/db/bit_vector_iterators.h"
+#include "src/trace_processor/containers/bit_vector.h"
+#include "src/trace_processor/containers/bit_vector_iterators.h"
namespace perfetto {
namespace trace_processor {
@@ -381,31 +381,13 @@
// if (!other.Contains(idx))
// Remove(idx)
void Intersect(const RowMap& other) {
- uint32_t size = other.size();
-
- if (size == 0u) {
- // If other is empty, then we will also end up being empty.
- *this = RowMap();
- return;
- }
-
- if (size == 1u) {
- // If other just has a single row, see if we also have that row. If we
- // do, then just return that row. Otherwise, make ourselves empty.
- uint32_t row = other.Get(0);
- *this = Contains(row) ? RowMap::SingleRow(row) : RowMap();
- return;
- }
-
if (mode_ == Mode::kRange && other.mode_ == Mode::kRange) {
// If both RowMaps have ranges, we can just take the smallest intersection
// of them as the new RowMap.
- // This case is important to optimize as it comes up with sorted columns.
+ // We have this as an explicit fast path as this is very common for
+ // constraints on id and sorted columns to satisfy this condition.
start_idx_ = std::max(start_idx_, other.start_idx_);
- end_idx_ = std::min(end_idx_, other.end_idx_);
-
- if (end_idx_ <= start_idx_)
- *this = RowMap();
+ end_idx_ = std::max(start_idx_, std::min(end_idx_, other.end_idx_));
return;
}
@@ -634,4 +616,4 @@
} // namespace trace_processor
} // namespace perfetto
-#endif // SRC_TRACE_PROCESSOR_DB_ROW_MAP_H_
+#endif // SRC_TRACE_PROCESSOR_CONTAINERS_ROW_MAP_H_
diff --git a/src/trace_processor/db/row_map_benchmark.cc b/src/trace_processor/containers/row_map_benchmark.cc
similarity index 99%
rename from src/trace_processor/db/row_map_benchmark.cc
rename to src/trace_processor/containers/row_map_benchmark.cc
index 1d6892e..47d66cd 100644
--- a/src/trace_processor/db/row_map_benchmark.cc
+++ b/src/trace_processor/containers/row_map_benchmark.cc
@@ -16,7 +16,7 @@
#include <benchmark/benchmark.h>
-#include "src/trace_processor/db/row_map.h"
+#include "src/trace_processor/containers/row_map.h"
using perfetto::trace_processor::BitVector;
using perfetto::trace_processor::RowMap;
diff --git a/src/trace_processor/db/row_map_unittest.cc b/src/trace_processor/containers/row_map_unittest.cc
similarity index 99%
rename from src/trace_processor/db/row_map_unittest.cc
rename to src/trace_processor/containers/row_map_unittest.cc
index 042154d..c85b5fe 100644
--- a/src/trace_processor/db/row_map_unittest.cc
+++ b/src/trace_processor/containers/row_map_unittest.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "src/trace_processor/db/row_map.h"
+#include "src/trace_processor/containers/row_map.h"
#include <memory>
diff --git a/src/trace_processor/db/sparse_vector.h b/src/trace_processor/containers/sparse_vector.h
similarity index 93%
rename from src/trace_processor/db/sparse_vector.h
rename to src/trace_processor/containers/sparse_vector.h
index 7fb0d87..5c803d3 100644
--- a/src/trace_processor/db/sparse_vector.h
+++ b/src/trace_processor/containers/sparse_vector.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef SRC_TRACE_PROCESSOR_DB_SPARSE_VECTOR_H_
-#define SRC_TRACE_PROCESSOR_DB_SPARSE_VECTOR_H_
+#ifndef SRC_TRACE_PROCESSOR_CONTAINERS_SPARSE_VECTOR_H_
+#define SRC_TRACE_PROCESSOR_CONTAINERS_SPARSE_VECTOR_H_
#include <stdint.h>
@@ -23,7 +23,7 @@
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/optional.h"
-#include "src/trace_processor/db/row_map.h"
+#include "src/trace_processor/containers/row_map.h"
namespace perfetto {
namespace trace_processor {
@@ -115,4 +115,4 @@
} // namespace trace_processor
} // namespace perfetto
-#endif // SRC_TRACE_PROCESSOR_DB_SPARSE_VECTOR_H_
+#endif // SRC_TRACE_PROCESSOR_CONTAINERS_SPARSE_VECTOR_H_
diff --git a/src/trace_processor/db/sparse_vector_benchmark.cc b/src/trace_processor/containers/sparse_vector_benchmark.cc
similarity index 96%
rename from src/trace_processor/db/sparse_vector_benchmark.cc
rename to src/trace_processor/containers/sparse_vector_benchmark.cc
index ed1bed2..626b738 100644
--- a/src/trace_processor/db/sparse_vector_benchmark.cc
+++ b/src/trace_processor/containers/sparse_vector_benchmark.cc
@@ -16,7 +16,7 @@
#include <benchmark/benchmark.h>
-#include "src/trace_processor/db/sparse_vector.h"
+#include "src/trace_processor/containers/sparse_vector.h"
namespace {
diff --git a/src/trace_processor/db/sparse_vector_unittest.cc b/src/trace_processor/containers/sparse_vector_unittest.cc
similarity index 96%
rename from src/trace_processor/db/sparse_vector_unittest.cc
rename to src/trace_processor/containers/sparse_vector_unittest.cc
index cd8e43a..6e81b0b 100644
--- a/src/trace_processor/db/sparse_vector_unittest.cc
+++ b/src/trace_processor/containers/sparse_vector_unittest.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "src/trace_processor/db/sparse_vector.h"
+#include "src/trace_processor/containers/sparse_vector.h"
#include "test/gtest_and_gmock.h"
diff --git a/src/trace_processor/string_pool.cc b/src/trace_processor/containers/string_pool.cc
similarity index 98%
rename from src/trace_processor/string_pool.cc
rename to src/trace_processor/containers/string_pool.cc
index 1a45e27..020de1c 100644
--- a/src/trace_processor/string_pool.cc
+++ b/src/trace_processor/containers/string_pool.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "src/trace_processor/string_pool.h"
+#include "src/trace_processor/containers/string_pool.h"
#include <limits>
diff --git a/src/trace_processor/string_pool.h b/src/trace_processor/containers/string_pool.h
similarity index 96%
rename from src/trace_processor/string_pool.h
rename to src/trace_processor/containers/string_pool.h
index d632764..bdfc39f 100644
--- a/src/trace_processor/string_pool.h
+++ b/src/trace_processor/containers/string_pool.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef SRC_TRACE_PROCESSOR_STRING_POOL_H_
-#define SRC_TRACE_PROCESSOR_STRING_POOL_H_
+#ifndef SRC_TRACE_PROCESSOR_CONTAINERS_STRING_POOL_H_
+#define SRC_TRACE_PROCESSOR_CONTAINERS_STRING_POOL_H_
#include <stddef.h>
#include <stdint.h>
@@ -26,7 +26,7 @@
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/paged_memory.h"
#include "perfetto/protozero/proto_utils.h"
-#include "src/trace_processor/null_term_string_view.h"
+#include "src/trace_processor/containers/null_term_string_view.h"
namespace perfetto {
namespace trace_processor {
@@ -250,4 +250,4 @@
} // namespace std
-#endif // SRC_TRACE_PROCESSOR_STRING_POOL_H_
+#endif // SRC_TRACE_PROCESSOR_CONTAINERS_STRING_POOL_H_
diff --git a/src/trace_processor/string_pool_unittest.cc b/src/trace_processor/containers/string_pool_unittest.cc
similarity index 98%
rename from src/trace_processor/string_pool_unittest.cc
rename to src/trace_processor/containers/string_pool_unittest.cc
index 9021f01..0144d7c 100644
--- a/src/trace_processor/string_pool_unittest.cc
+++ b/src/trace_processor/containers/string_pool_unittest.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "src/trace_processor/string_pool.h"
+#include "src/trace_processor/containers/string_pool.h"
#include <random>
diff --git a/src/trace_processor/db/BUILD.gn b/src/trace_processor/db/BUILD.gn
index 30e2518..be92403 100644
--- a/src/trace_processor/db/BUILD.gn
+++ b/src/trace_processor/db/BUILD.gn
@@ -16,36 +16,26 @@
source_set("lib") {
sources = [
- "bit_vector.cc",
- "bit_vector.h",
- "bit_vector_iterators.cc",
- "bit_vector_iterators.h",
"column.cc",
"column.h",
"compare.h",
- "row_map.cc",
- "row_map.h",
- "sparse_vector.h",
"table.cc",
"table.h",
"typed_column.h",
]
deps = [
- "../:common",
"../../../gn:default_deps",
"../../../include/perfetto/base",
"../../../include/perfetto/ext/base",
"../../../include/perfetto/trace_processor",
+ "../containers",
]
}
perfetto_unittest_source_set("unittests") {
testonly = true
sources = [
- "bit_vector_unittest.cc",
"compare_unittest.cc",
- "row_map_unittest.cc",
- "sparse_vector_unittest.cc",
]
deps = [
":lib",
@@ -53,19 +43,3 @@
"../../../gn:gtest_and_gmock",
]
}
-
-if (enable_perfetto_benchmarks) {
- source_set("benchmarks") {
- testonly = true
- deps = [
- ":lib",
- "../../../gn:benchmark",
- "../../../gn:default_deps",
- ]
- sources = [
- "bit_vector_benchmark.cc",
- "row_map_benchmark.cc",
- "sparse_vector_benchmark.cc",
- ]
- }
-}
diff --git a/src/trace_processor/db/column.h b/src/trace_processor/db/column.h
index 0e3d927..0c411dd 100644
--- a/src/trace_processor/db/column.h
+++ b/src/trace_processor/db/column.h
@@ -22,10 +22,10 @@
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/optional.h"
#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/containers/row_map.h"
+#include "src/trace_processor/containers/sparse_vector.h"
+#include "src/trace_processor/containers/string_pool.h"
#include "src/trace_processor/db/compare.h"
-#include "src/trace_processor/db/row_map.h"
-#include "src/trace_processor/db/sparse_vector.h"
-#include "src/trace_processor/string_pool.h"
namespace perfetto {
namespace trace_processor {
diff --git a/src/trace_processor/db/table.cc b/src/trace_processor/db/table.cc
index 823f57f..6fa723c 100644
--- a/src/trace_processor/db/table.cc
+++ b/src/trace_processor/db/table.cc
@@ -32,7 +32,7 @@
}
Table& Table::operator=(Table&& other) noexcept {
- size_ = other.size_;
+ row_count_ = other.row_count_;
string_pool_ = other.string_pool_;
row_maps_ = std::move(other.row_maps_);
@@ -53,7 +53,7 @@
Table Table::CopyExceptRowMaps() const {
Table table(string_pool_, nullptr);
- table.size_ = size_;
+ table.row_count_ = row_count_;
for (const Column& col : columns_) {
table.columns_.emplace_back(col, &table, col.index_in_table(),
col.row_map_idx_);
@@ -66,7 +66,7 @@
return Copy();
// Build an index vector with all the indices for the first |size_| rows.
- std::vector<uint32_t> idx(size_);
+ std::vector<uint32_t> idx(row_count_);
std::iota(idx.begin(), idx.end(), 0);
// As our data is columnar, it's always more efficient to sort one column
@@ -108,7 +108,7 @@
RowMap rm(std::move(idx));
for (const RowMap& map : row_maps_) {
table.row_maps_.emplace_back(map.SelectRows(rm));
- PERFETTO_DCHECK(table.row_maps_.back().size() == table.size());
+ PERFETTO_DCHECK(table.row_maps_.back().size() == table.row_count());
}
// Remove the sorted flag from all the columns.
@@ -126,7 +126,7 @@
// 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.size_ = size_;
+ table.row_count_ = row_count_;
for (const RowMap& rm : row_maps_) {
table.row_maps_.emplace_back(rm.Copy());
}
@@ -146,8 +146,8 @@
// 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(size_);
- for (uint32_t i = 0; i < size_; ++i) {
+ 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();
diff --git a/src/trace_processor/db/table.h b/src/trace_processor/db/table.h
index cc3a3d8..058dac7 100644
--- a/src/trace_processor/db/table.h
+++ b/src/trace_processor/db/table.h
@@ -25,8 +25,8 @@
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/optional.h"
+#include "src/trace_processor/containers/string_pool.h"
#include "src/trace_processor/db/column.h"
-#include "src/trace_processor/string_pool.h"
namespace perfetto {
namespace trace_processor {
@@ -84,7 +84,7 @@
// Returns a RowMap which, if applied to the table, would contain the rows
// post filter.
RowMap FilterToRowMap(const std::vector<Constraint>& cs) const {
- RowMap rm(0, size_);
+ RowMap rm(0, row_count_);
for (const Constraint& c : cs) {
columns_[c.col_idx].FilterInto(c.op, c.value, &rm);
}
@@ -97,10 +97,10 @@
// passed RowMap is generated using |FilterToRowMap|.
Table Apply(RowMap rm) const {
Table table = CopyExceptRowMaps();
- table.size_ = rm.size();
+ table.row_count_ = rm.size();
for (const RowMap& map : row_maps_) {
table.row_maps_.emplace_back(map.SelectRows(rm));
- PERFETTO_DCHECK(table.row_maps_.back().size() == table.size());
+ PERFETTO_DCHECK(table.row_maps_.back().size() == table.row_count());
}
return table;
}
@@ -145,7 +145,7 @@
// Returns an iterator into the Table.
Iterator IterateRows() const { return Iterator(this); }
- uint32_t size() const { return size_; }
+ uint32_t row_count() const { return row_count_; }
const std::vector<RowMap>& row_maps() const { return row_maps_; }
protected:
@@ -153,7 +153,7 @@
std::vector<RowMap> row_maps_;
std::vector<Column> columns_;
- uint32_t size_ = 0;
+ uint32_t row_count_ = 0;
StringPool* string_pool_ = nullptr;
diff --git a/tools/trace_to_text/symbolizer.cc b/src/trace_processor/destructible.cc
similarity index 81%
copy from tools/trace_to_text/symbolizer.cc
copy to src/trace_processor/destructible.cc
index 1cd83cb..22bcf6a 100644
--- a/tools/trace_to_text/symbolizer.cc
+++ b/src/trace_processor/destructible.cc
@@ -13,13 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#include "perfetto/profiling/symbolizer.h"
+#include "src/trace_processor/destructible.h"
namespace perfetto {
-namespace trace_to_text {
+namespace trace_processor {
-Symbolizer::~Symbolizer() = default;
+Destructible::~Destructible() = default;
-} // namespace trace_to_text
+} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/destructible.h b/src/trace_processor/destructible.h
new file mode 100644
index 0000000..9b9c20f
--- /dev/null
+++ b/src/trace_processor/destructible.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_DESTRUCTIBLE_H_
+#define SRC_TRACE_PROCESSOR_DESTRUCTIBLE_H_
+
+namespace perfetto {
+namespace trace_processor {
+
+// To reduce Chrome binary size, we exclude the source code of several
+// trackers from the storage_minimal build target. So the trace processor
+// context can't always know the exact types of the tracker classes, but
+// it still needs to destruct them. To solve this, we subclass all trackers
+// from this Desctructible class.
+class Destructible {
+ public:
+ virtual ~Destructible();
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_DESTRUCTIBLE_H_
diff --git a/src/trace_processor/event_tracker_unittest.cc b/src/trace_processor/event_tracker_unittest.cc
index bebd42d..61968ab 100644
--- a/src/trace_processor/event_tracker_unittest.cc
+++ b/src/trace_processor/event_tracker_unittest.cc
@@ -40,12 +40,13 @@
context.event_tracker.reset(new EventTracker(&context));
context.track_tracker.reset(new TrackTracker(&context));
#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
- context.sched_tracker.reset(new SchedEventTracker(&context));
+ sched_tracker = SchedEventTracker::GetOrCreate(&context);
#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
}
protected:
TraceProcessorContext context;
+ SchedEventTracker* sched_tracker;
};
#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
@@ -60,14 +61,12 @@
int32_t prio = 1024;
const auto& timestamps = context.storage->slices().start_ns();
- context.sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, kCommProc2,
- prio, prev_state, pid_2, kCommProc1,
- prio);
+ sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, kCommProc2, prio,
+ prev_state, pid_2, kCommProc1, prio);
ASSERT_EQ(timestamps.size(), 1u);
- context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, pid_2, kCommProc1,
- prio, prev_state, pid_1, kCommProc2,
- prio);
+ sched_tracker->PushSchedSwitch(cpu, timestamp + 1, pid_2, kCommProc1, prio,
+ prev_state, pid_1, kCommProc2, prio);
ASSERT_EQ(timestamps.size(), 2ul);
ASSERT_EQ(timestamps[0], timestamp);
@@ -88,20 +87,20 @@
int32_t prio = 1024;
const auto& timestamps = context.storage->slices().start_ns();
- context.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/4, kCommProc2,
- prio, prev_state,
- /*tid=*/2, kCommProc1, prio);
+ sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/4, kCommProc2, prio,
+ prev_state,
+ /*tid=*/2, kCommProc1, prio);
ASSERT_EQ(timestamps.size(), 1u);
- context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/2,
- kCommProc1, prio, prev_state,
- /*tid=*/4, kCommProc2, prio);
- context.sched_tracker->PushSchedSwitch(cpu, timestamp + 11, /*tid=*/4,
- kCommProc2, prio, prev_state,
- /*tid=*/2, kCommProc1, prio);
- context.sched_tracker->PushSchedSwitch(cpu, timestamp + 31, /*tid=*/2,
- kCommProc1, prio, prev_state,
- /*tid=*/4, kCommProc2, prio);
+ sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/2, kCommProc1,
+ prio, prev_state,
+ /*tid=*/4, kCommProc2, prio);
+ sched_tracker->PushSchedSwitch(cpu, timestamp + 11, /*tid=*/4, kCommProc2,
+ prio, prev_state,
+ /*tid=*/2, kCommProc1, prio);
+ sched_tracker->PushSchedSwitch(cpu, timestamp + 31, /*tid=*/2, kCommProc1,
+ prio, prev_state,
+ /*tid=*/4, kCommProc2, prio);
ASSERT_EQ(timestamps.size(), 4ul);
ASSERT_EQ(timestamps[0], timestamp);
@@ -125,9 +124,9 @@
context.event_tracker->PushCounter(timestamp + 3, 5000, track);
context.event_tracker->PushCounter(timestamp + 9, 1000, track);
- ASSERT_EQ(context.storage->counter_track_table().size(), 1ul);
+ ASSERT_EQ(context.storage->counter_track_table().row_count(), 1ul);
- ASSERT_EQ(context.storage->counter_table().size(), 4ul);
+ ASSERT_EQ(context.storage->counter_table().row_count(), 4ul);
ASSERT_EQ(context.storage->counter_table().ts()[0], timestamp);
ASSERT_DOUBLE_EQ(context.storage->counter_table().value()[0], 1000);
diff --git a/src/trace_processor/export_json.cc b/src/trace_processor/export_json.cc
index df5f2b5..9ac286e 100644
--- a/src/trace_processor/export_json.cc
+++ b/src/trace_processor/export_json.cc
@@ -458,7 +458,7 @@
const ArgsBuilder& args_builder,
TraceFormatWriter* writer) {
const auto& slices = storage->slice_table();
- for (uint32_t i = 0; i < slices.size(); ++i) {
+ for (uint32_t i = 0; i < slices.row_count(); ++i) {
Json::Value event;
event["ts"] = Json::Int64(slices.ts()[i] / 1000);
event["cat"] = GetNonNullString(storage, slices.category()[i]);
@@ -845,7 +845,7 @@
const auto& callsites = storage->stack_profile_callsite_table();
int64_t maybe_callsite_id = samples.callsite_ids()[i];
PERFETTO_DCHECK(maybe_callsite_id >= 0 &&
- maybe_callsite_id < callsites.size());
+ maybe_callsite_id < callsites.row_count());
while (maybe_callsite_id >= 0) {
uint32_t callsite_id = static_cast<uint32_t>(maybe_callsite_id);
diff --git a/src/trace_processor/export_json_unittest.cc b/src/trace_processor/export_json_unittest.cc
index 02fe44d..4d72fcc 100644
--- a/src/trace_processor/export_json_unittest.cc
+++ b/src/trace_processor/export_json_unittest.cc
@@ -1150,7 +1150,7 @@
uint32_t frame_row_id_1 = storage->mutable_stack_profile_frames()->Insert(
{/*name_id=*/0, module_row_id_1, 0x42});
- uint32_t symbol_set_id = storage->symbol_table().size();
+ uint32_t symbol_set_id = storage->symbol_table().row_count();
storage->mutable_symbol_table()->Insert(
{symbol_set_id, storage->InternString("foo_func"),
storage->InternString("foo_file"), 66});
@@ -1159,7 +1159,7 @@
uint32_t frame_row_id_2 = storage->mutable_stack_profile_frames()->Insert(
{/*name_id=*/0, module_row_id_2, 0x4242});
- symbol_set_id = storage->symbol_table().size();
+ symbol_set_id = storage->symbol_table().row_count();
storage->mutable_symbol_table()->Insert(
{symbol_set_id, storage->InternString("bar_func"),
storage->InternString("bar_file"), 77});
diff --git a/src/trace_processor/heap_profile_allocation_table.cc b/src/trace_processor/heap_profile_allocation_table.cc
deleted file mode 100644
index dcdb825..0000000
--- a/src/trace_processor/heap_profile_allocation_table.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/heap_profile_allocation_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-HeapProfileAllocationTable::HeapProfileAllocationTable(
- sqlite3*,
- const TraceStorage* storage)
- : storage_(storage) {}
-
-void HeapProfileAllocationTable::RegisterTable(sqlite3* db,
- const TraceStorage* storage) {
- SqliteTable::Register<HeapProfileAllocationTable>(db, storage,
- "heap_profile_allocation");
-}
-
-StorageSchema HeapProfileAllocationTable::CreateStorageSchema() {
- const auto& allocs = storage_->heap_profile_allocations();
- return StorageSchema::Builder()
- .AddGenericNumericColumn("id", RowAccessor())
- .AddOrderedNumericColumn("ts", &allocs.timestamps())
- .AddNumericColumn("upid", &allocs.upids())
- .AddNumericColumn("callsite_id", &allocs.callsite_ids())
- .AddNumericColumn("count", &allocs.counts())
- .AddNumericColumn("size", &allocs.sizes())
- .Build({"id"});
-}
-
-uint32_t HeapProfileAllocationTable::RowCount() {
- return storage_->heap_profile_allocations().size();
-}
-
-int HeapProfileAllocationTable::BestIndex(const QueryConstraints& qc,
- BestIndexInfo* info) {
- info->sqlite_omit_order_by = true;
- info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
- return SQLITE_OK;
-}
-
-} // namespace trace_processor
-} // namespace perfetto
diff --git a/src/trace_processor/heap_profile_allocation_table.h b/src/trace_processor/heap_profile_allocation_table.h
deleted file mode 100644
index 9f7fd44..0000000
--- a/src/trace_processor/heap_profile_allocation_table.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_HEAP_PROFILE_ALLOCATION_TABLE_H_
-#define SRC_TRACE_PROCESSOR_HEAP_PROFILE_ALLOCATION_TABLE_H_
-
-#include "src/trace_processor/storage_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class HeapProfileAllocationTable : public StorageTable {
- public:
- static void RegisterTable(sqlite3* db, const TraceStorage* storage);
-
- HeapProfileAllocationTable(sqlite3*, const TraceStorage*);
-
- // StorageTable implementation.
- StorageSchema CreateStorageSchema() override;
- uint32_t RowCount() override;
- int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
-
- private:
- const TraceStorage* const storage_;
-};
-
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_HEAP_PROFILE_ALLOCATION_TABLE_H_
diff --git a/src/trace_processor/heap_profile_tracker.cc b/src/trace_processor/heap_profile_tracker.cc
index dc637c9..a666dad 100644
--- a/src/trace_processor/heap_profile_tracker.cc
+++ b/src/trace_processor/heap_profile_tracker.cc
@@ -55,27 +55,27 @@
UniquePid upid = context_->process_tracker->GetOrCreateProcess(
static_cast<uint32_t>(alloc.pid));
- TraceStorage::HeapProfileAllocations::Row alloc_row{
+ tables::HeapProfileAllocationTable::Row alloc_row{
alloc.timestamp, upid, callstack_id,
static_cast<int64_t>(alloc.alloc_count),
static_cast<int64_t>(alloc.self_allocated)};
- TraceStorage::HeapProfileAllocations::Row free_row{
+ tables::HeapProfileAllocationTable::Row free_row{
alloc.timestamp, upid, callstack_id,
-static_cast<int64_t>(alloc.free_count),
-static_cast<int64_t>(alloc.self_freed)};
- TraceStorage::HeapProfileAllocations::Row alloc_delta = alloc_row;
- TraceStorage::HeapProfileAllocations::Row free_delta = free_row;
+ tables::HeapProfileAllocationTable::Row alloc_delta = alloc_row;
+ tables::HeapProfileAllocationTable::Row free_delta = free_row;
auto prev_alloc_it = sequence_state.prev_alloc.find({upid, callstack_id});
if (prev_alloc_it == sequence_state.prev_alloc.end()) {
std::tie(prev_alloc_it, std::ignore) = sequence_state.prev_alloc.emplace(
std::make_pair(upid, callstack_id),
- TraceStorage::HeapProfileAllocations::Row{});
+ tables::HeapProfileAllocationTable::Row{});
}
- TraceStorage::HeapProfileAllocations::Row& prev_alloc = prev_alloc_it->second;
+ tables::HeapProfileAllocationTable::Row& prev_alloc = prev_alloc_it->second;
alloc_delta.count -= prev_alloc.count;
alloc_delta.size -= prev_alloc.size;
@@ -83,17 +83,19 @@
if (prev_free_it == sequence_state.prev_free.end()) {
std::tie(prev_free_it, std::ignore) = sequence_state.prev_free.emplace(
std::make_pair(upid, callstack_id),
- TraceStorage::HeapProfileAllocations::Row{});
+ tables::HeapProfileAllocationTable::Row{});
}
- TraceStorage::HeapProfileAllocations::Row& prev_free = prev_free_it->second;
+ tables::HeapProfileAllocationTable::Row& prev_free = prev_free_it->second;
free_delta.count -= prev_free.count;
free_delta.size -= prev_free.size;
if (alloc_delta.count)
- context_->storage->mutable_heap_profile_allocations()->Insert(alloc_delta);
+ context_->storage->mutable_heap_profile_allocation_table()->Insert(
+ alloc_delta);
if (free_delta.count)
- context_->storage->mutable_heap_profile_allocations()->Insert(free_delta);
+ context_->storage->mutable_heap_profile_allocation_table()->Insert(
+ free_delta);
prev_alloc = alloc_row;
prev_free = free_row;
diff --git a/src/trace_processor/heap_profile_tracker.h b/src/trace_processor/heap_profile_tracker.h
index 30629b5..1d121aa 100644
--- a/src/trace_processor/heap_profile_tracker.h
+++ b/src/trace_processor/heap_profile_tracker.h
@@ -78,10 +78,10 @@
std::vector<SourceAllocation> pending_allocs;
std::unordered_map<std::pair<UniquePid, int64_t>,
- TraceStorage::HeapProfileAllocations::Row>
+ tables::HeapProfileAllocationTable::Row>
prev_alloc;
std::unordered_map<std::pair<UniquePid, int64_t>,
- TraceStorage::HeapProfileAllocations::Row>
+ tables::HeapProfileAllocationTable::Row>
prev_free;
uint64_t last_profile_packet_index = 0;
diff --git a/src/trace_processor/heap_profile_tracker_unittest.cc b/src/trace_processor/heap_profile_tracker_unittest.cc
index ce978bf..f7c3734 100644
--- a/src/trace_processor/heap_profile_tracker_unittest.cc
+++ b/src/trace_processor/heap_profile_tracker_unittest.cc
@@ -185,7 +185,7 @@
int64_t parent,
int64_t frame_id) {
const auto& callsites = storage.stack_profile_callsite_table();
- for (uint32_t i = 0; i < callsites.size(); ++i) {
+ for (uint32_t i = 0; i < callsites.row_count(); ++i) {
if (callsites.depth()[i] == depth && callsites.parent_id()[i] == parent &&
callsites.frame_id()[i] == frame_id) {
return static_cast<int64_t>(i);
diff --git a/src/trace_processor/binder_tracker.cc b/src/trace_processor/importers/ftrace/binder_tracker.cc
similarity index 95%
rename from src/trace_processor/binder_tracker.cc
rename to src/trace_processor/importers/ftrace/binder_tracker.cc
index 2bc3953..10bab08 100644
--- a/src/trace_processor/binder_tracker.cc
+++ b/src/trace_processor/importers/ftrace/binder_tracker.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "src/trace_processor/binder_tracker.h"
+#include "src/trace_processor/importers/ftrace/binder_tracker.h"
#include "perfetto/base/compiler.h"
diff --git a/src/trace_processor/binder_tracker.h b/src/trace_processor/importers/ftrace/binder_tracker.h
similarity index 86%
rename from src/trace_processor/binder_tracker.h
rename to src/trace_processor/importers/ftrace/binder_tracker.h
index c3f1994..6b50fe2 100644
--- a/src/trace_processor/binder_tracker.h
+++ b/src/trace_processor/importers/ftrace/binder_tracker.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef SRC_TRACE_PROCESSOR_BINDER_TRACKER_H_
-#define SRC_TRACE_PROCESSOR_BINDER_TRACKER_H_
+#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_BINDER_TRACKER_H_
+#define SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_BINDER_TRACKER_H_
#include <stdint.h>
@@ -45,4 +45,4 @@
} // namespace trace_processor
} // namespace perfetto
-#endif // SRC_TRACE_PROCESSOR_BINDER_TRACKER_H_
+#endif // SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_BINDER_TRACKER_H_
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index c07fd8d..4335a84 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -19,7 +19,7 @@
#include "perfetto/base/logging.h"
#include "perfetto/protozero/proto_decoder.h"
#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/binder_tracker.h"
+#include "src/trace_processor/importers/ftrace/binder_tracker.h"
#include "src/trace_processor/importers/systrace/systrace_parser.h"
#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/stats.h"
@@ -60,6 +60,7 @@
FtraceParser::FtraceParser(TraceProcessorContext* context)
: context_(context),
+ binder_tracker_(context),
sched_wakeup_name_id_(context->storage->InternString("sched_wakeup")),
sched_waking_name_id_(context->storage->InternString("sched_waking")),
cpu_freq_name_id_(context->storage->InternString("cpufreq")),
@@ -188,20 +189,21 @@
const TimestampedTracePiece& ttp) {
using protos::pbzero::FtraceEvent;
int64_t ts = ttp.timestamp;
+ SchedEventTracker* sched_tracker = SchedEventTracker::GetOrCreate(context_);
// Handle the (optional) alternative encoding format for sched_switch.
if (ttp.inline_event.type == InlineEvent::Type::kSchedSwitch) {
const auto& event = ttp.inline_event.sched_switch;
- context_->sched_tracker->PushSchedSwitchCompact(
- cpu, ts, event.prev_state, static_cast<uint32_t>(event.next_pid),
- event.next_prio, event.next_comm);
+ sched_tracker->PushSchedSwitchCompact(cpu, ts, event.prev_state,
+ static_cast<uint32_t>(event.next_pid),
+ event.next_prio, event.next_comm);
return util::OkStatus();
}
// Handle the (optional) alternative encoding format for sched_waking.
if (ttp.inline_event.type == InlineEvent::Type::kSchedWaking) {
const auto& event = ttp.inline_event.sched_waking;
- context_->sched_tracker->PushSchedWakingCompact(
+ sched_tracker->PushSchedWakingCompact(
cpu, ts, static_cast<uint32_t>(event.pid), event.target_cpu, event.prio,
event.comm);
return util::OkStatus();
@@ -465,7 +467,7 @@
protos::pbzero::SchedSwitchFtraceEvent::Decoder ss(blob.data, blob.size);
uint32_t prev_pid = static_cast<uint32_t>(ss.prev_pid());
uint32_t next_pid = static_cast<uint32_t>(ss.next_pid());
- context_->sched_tracker->PushSchedSwitch(
+ SchedEventTracker::GetOrCreate(context_)->PushSchedSwitch(
cpu, ts, prev_pid, ss.prev_comm(), ss.prev_prio(), ss.prev_state(),
next_pid, ss.next_comm(), ss.next_prio());
}
@@ -523,14 +525,14 @@
void FtraceParser::ParsePrint(int64_t ts, uint32_t pid, ConstBytes blob) {
protos::pbzero::PrintFtraceEvent::Decoder evt(blob.data, blob.size);
- context_->systrace_parser->ParsePrintEvent(ts, pid, evt.buf());
+ SystraceParser::GetOrCreate(context_)->ParsePrintEvent(ts, pid, evt.buf());
}
void FtraceParser::ParseZero(int64_t ts, uint32_t pid, ConstBytes blob) {
protos::pbzero::ZeroFtraceEvent::Decoder evt(blob.data, blob.size);
uint32_t tgid = static_cast<uint32_t>(evt.pid());
- context_->systrace_parser->ParseZeroEvent(ts, pid, evt.flag(), evt.name(),
- tgid, evt.value());
+ SystraceParser::GetOrCreate(context_)->ParseZeroEvent(
+ ts, pid, evt.flag(), evt.name(), tgid, evt.value());
}
void FtraceParser::ParseSdeTracingMarkWrite(int64_t ts,
@@ -544,7 +546,7 @@
}
uint32_t tgid = static_cast<uint32_t>(evt.pid());
- context_->systrace_parser->ParseSdeTracingMarkWrite(
+ SystraceParser::GetOrCreate(context_)->ParseSdeTracingMarkWrite(
ts, pid, static_cast<char>(evt.trace_type()), evt.trace_begin(),
evt.trace_name(), tgid, evt.value());
}
@@ -707,10 +709,11 @@
uint32_t syscall_num = static_cast<uint32_t>(evt.id());
UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
+ SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(context_);
if (is_enter) {
- context_->syscall_tracker->Enter(ts, utid, syscall_num);
+ syscall_tracker->Enter(ts, utid, syscall_num);
} else {
- context_->syscall_tracker->Exit(ts, utid, syscall_num);
+ syscall_tracker->Exit(ts, utid, syscall_num);
}
// We are reusing the same function for sys_enter and sys_exit.
@@ -768,7 +771,7 @@
ConstBytes blob) {
protos::pbzero::BinderTransactionFtraceEvent::Decoder evt(blob.data,
blob.size);
- context_->binder_tracker->Transaction(timestamp, pid);
+ binder_tracker_.Transaction(timestamp, pid);
}
void FtraceParser::ParseBinderTransactionReceived(int64_t timestamp,
@@ -776,7 +779,7 @@
ConstBytes blob) {
protos::pbzero::BinderTransactionReceivedFtraceEvent::Decoder evt(blob.data,
blob.size);
- context_->binder_tracker->TransactionReceived(timestamp, pid);
+ binder_tracker_.TransactionReceived(timestamp, pid);
}
void FtraceParser::ParseBinderTransactionAllocBuf(int64_t timestamp,
@@ -784,28 +787,28 @@
ConstBytes blob) {
protos::pbzero::BinderTransactionAllocBufFtraceEvent::Decoder evt(blob.data,
blob.size);
- context_->binder_tracker->TransactionAllocBuf(timestamp, pid);
+ binder_tracker_.TransactionAllocBuf(timestamp, pid);
}
void FtraceParser::ParseBinderLocked(int64_t timestamp,
uint32_t pid,
ConstBytes blob) {
protos::pbzero::BinderLockedFtraceEvent::Decoder evt(blob.data, blob.size);
- context_->binder_tracker->Locked(timestamp, pid);
+ binder_tracker_.Locked(timestamp, pid);
}
void FtraceParser::ParseBinderLock(int64_t timestamp,
uint32_t pid,
ConstBytes blob) {
protos::pbzero::BinderLockFtraceEvent::Decoder evt(blob.data, blob.size);
- context_->binder_tracker->Lock(timestamp, pid);
+ binder_tracker_.Lock(timestamp, pid);
}
void FtraceParser::ParseBinderUnlock(int64_t timestamp,
uint32_t pid,
ConstBytes blob) {
protos::pbzero::BinderUnlockFtraceEvent::Decoder evt(blob.data, blob.size);
- context_->binder_tracker->Unlock(timestamp, pid);
+ binder_tracker_.Unlock(timestamp, pid);
}
} // namespace trace_processor
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.h b/src/trace_processor/importers/ftrace/ftrace_parser.h
index 15bc2ef..6dfdfb7 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.h
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.h
@@ -19,6 +19,7 @@
#include "perfetto/trace_processor/status.h"
#include "src/trace_processor/event_tracker.h"
+#include "src/trace_processor/importers/ftrace/binder_tracker.h"
#include "src/trace_processor/importers/ftrace/ftrace_descriptors.h"
#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
#include "src/trace_processor/timestamped_trace_piece.h"
@@ -94,6 +95,7 @@
protozero::ConstBytes);
TraceProcessorContext* context_;
+ BinderTracker binder_tracker_;
const StringId sched_wakeup_name_id_;
const StringId sched_waking_name_id_;
diff --git a/src/trace_processor/importers/ftrace/sched_event_tracker.h b/src/trace_processor/importers/ftrace/sched_event_tracker.h
index 84ebd53..7a141ff 100644
--- a/src/trace_processor/importers/ftrace/sched_event_tracker.h
+++ b/src/trace_processor/importers/ftrace/sched_event_tracker.h
@@ -22,21 +22,29 @@
#include "perfetto/ext/base/string_view.h"
#include "perfetto/ext/base/utils.h"
+#include "src/trace_processor/destructible.h"
+#include "src/trace_processor/trace_processor_context.h"
#include "src/trace_processor/trace_storage.h"
namespace perfetto {
namespace trace_processor {
-class TraceProcessorContext;
class EventTracker;
// Tracks sched events and stores them into the storage as sched slices.
-class SchedEventTracker {
+class SchedEventTracker : public Destructible {
public:
+ // Declared public for testing only.
explicit SchedEventTracker(TraceProcessorContext*);
SchedEventTracker(const SchedEventTracker&) = delete;
SchedEventTracker& operator=(const SchedEventTracker&) = delete;
- virtual ~SchedEventTracker();
+ ~SchedEventTracker() override;
+ static SchedEventTracker* GetOrCreate(TraceProcessorContext* context) {
+ if (!context->sched_tracker) {
+ context->sched_tracker.reset(new SchedEventTracker(context));
+ }
+ return static_cast<SchedEventTracker*>(context->sched_tracker.get());
+ }
// This method is called when a sched_switch event is seen in the trace.
// Virtual for testing.
diff --git a/src/trace_processor/importers/proto/heap_graph_module.cc b/src/trace_processor/importers/proto/heap_graph_module.cc
index 3004131..49d2f02 100644
--- a/src/trace_processor/importers/proto/heap_graph_module.cc
+++ b/src/trace_processor/importers/proto/heap_graph_module.cc
@@ -92,8 +92,7 @@
using perfetto::protos::pbzero::TracePacket;
HeapGraphModule::HeapGraphModule(TraceProcessorContext* context)
- : context_(context) {
- context_->heap_graph_tracker.reset(new HeapGraphTracker(context_));
+ : context_(context), heap_graph_tracker_(context) {
RegisterForField(TracePacket::kHeapGraphFieldNumber, context);
RegisterForField(TracePacket::kDeobfuscationMappingFieldNumber, context);
}
@@ -119,7 +118,7 @@
protos::pbzero::HeapGraph::Decoder heap_graph(blob.data, blob.size);
UniquePid upid = context_->process_tracker->GetOrCreateProcess(
static_cast<uint32_t>(heap_graph.pid()));
- context_->heap_graph_tracker->SetPacketIndex(seq_id, heap_graph.index());
+ heap_graph_tracker_.SetPacketIndex(seq_id, heap_graph.index());
for (auto it = heap_graph.objects(); it; ++it) {
protos::pbzero::HeapGraphObject::Decoder object(*it);
HeapGraphTracker::SourceObject obj;
@@ -157,14 +156,14 @@
ref.owned_object_id = object_ids[i];
obj.references.emplace_back(std::move(ref));
}
- context_->heap_graph_tracker->AddObject(seq_id, upid, ts, std::move(obj));
+ heap_graph_tracker_.AddObject(seq_id, upid, ts, std::move(obj));
}
for (auto it = heap_graph.type_names(); it; ++it) {
protos::pbzero::InternedString::Decoder entry(*it);
const char* str = reinterpret_cast<const char*>(entry.str().data);
auto str_view = base::StringView(str, entry.str().size);
- context_->heap_graph_tracker->AddInternedTypeName(
+ heap_graph_tracker_.AddInternedTypeName(
seq_id, entry.iid(), context_->storage->InternString(str_view));
}
for (auto it = heap_graph.field_names(); it; ++it) {
@@ -172,7 +171,7 @@
const char* str = reinterpret_cast<const char*>(entry.str().data);
auto str_view = base::StringView(str, entry.str().size);
- context_->heap_graph_tracker->AddInternedFieldName(
+ heap_graph_tracker_.AddInternedFieldName(
seq_id, entry.iid(), context_->storage->InternString(str_view));
}
for (auto it = heap_graph.roots(); it; ++it) {
@@ -192,11 +191,10 @@
stats::heap_graph_malformed_packet, static_cast<int>(upid));
break;
}
- context_->heap_graph_tracker->AddRoot(seq_id, upid, ts,
- std::move(src_root));
+ heap_graph_tracker_.AddRoot(seq_id, upid, ts, std::move(src_root));
}
if (!heap_graph.continued()) {
- context_->heap_graph_tracker->FinalizeProfile(seq_id);
+ heap_graph_tracker_.FinalizeProfile(seq_id);
}
}
@@ -214,7 +212,7 @@
cls.obfuscated_name().ToStdString().c_str());
} else {
const std::vector<int64_t>* cls_objects =
- context_->heap_graph_tracker->RowsForType(*obfuscated_class_name_id);
+ heap_graph_tracker_.RowsForType(*obfuscated_class_name_id);
if (cls_objects) {
auto interned_deobfuscated_name =
@@ -247,7 +245,7 @@
}
const std::vector<int64_t>* field_references =
- context_->heap_graph_tracker->RowsForField(*obfuscated_field_name_id);
+ heap_graph_tracker_.RowsForField(*obfuscated_field_name_id);
if (field_references) {
auto interned_deobfuscated_name = context_->storage->InternString(
base::StringView(merged_deobfuscated));
diff --git a/src/trace_processor/importers/proto/heap_graph_module.h b/src/trace_processor/importers/proto/heap_graph_module.h
index 2fde80e..492ba60 100644
--- a/src/trace_processor/importers/proto/heap_graph_module.h
+++ b/src/trace_processor/importers/proto/heap_graph_module.h
@@ -40,6 +40,7 @@
void ParseDeobfuscationMapping(protozero::ConstBytes);
TraceProcessorContext* context_;
+ HeapGraphTracker heap_graph_tracker_;
};
} // 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 930528d..7e8ca92 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker.cc
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.cc
@@ -117,10 +117,11 @@
/*reachable=*/0, /*type_name=*/type_name,
/*deobfuscated_type_name=*/base::nullopt,
/*root_type=*/base::nullopt});
- int64_t row = context_->storage->heap_graph_object_table().size() - 1;
+ int64_t row = context_->storage->heap_graph_object_table().row_count() - 1;
sequence_state.object_id_to_row.emplace(obj.object_id, row);
class_to_rows_[type_name].emplace_back(row);
- sequence_state.walker.AddNode(row, obj.self_size);
+ sequence_state.walker.AddNode(row, obj.self_size,
+ static_cast<int32_t>(type_name.id));
}
for (const SourceObject& obj : sequence_state.current_objects) {
@@ -130,7 +131,7 @@
int64_t owner_row = it->second;
int64_t reference_set_id =
- context_->storage->heap_graph_reference_table().size();
+ context_->storage->heap_graph_reference_table().row_count();
std::set<int64_t> seen_owned;
for (const SourceObject::Reference& ref : obj.references) {
// This is true for unset reference fields.
@@ -161,7 +162,8 @@
context_->storage->mutable_heap_graph_reference_table()->Insert(
{reference_set_id, owner_row, owned_row, field_name,
/*deobfuscated_field_name=*/base::nullopt});
- int64_t row = context_->storage->heap_graph_reference_table().size() - 1;
+ int64_t row =
+ context_->storage->heap_graph_reference_table().row_count() - 1;
field_to_rows_[field_name].emplace_back(row);
}
context_->storage->mutable_heap_graph_object_table()
@@ -185,10 +187,46 @@
}
}
- sequence_state.walker.CalculateRetained();
+ TraceStorage::StackProfileMappings::Row mapping_row{};
+ mapping_row.name_id = context_->storage->InternString("JAVA");
+ uint32_t mapping_id =
+ context_->storage->mutable_stack_profile_mappings()->Insert(mapping_row);
+
+ auto paths = sequence_state.walker.FindPathsFromRoot();
+ for (const auto& p : paths.children)
+ WriteFlamegraph(sequence_state, p.second, -1, 0, mapping_id);
+
sequence_state_.erase(seq_id);
}
+void HeapGraphTracker::WriteFlamegraph(
+ const SequenceState& sequence_state,
+ const HeapGraphWalker::PathFromRoot& path,
+ int32_t parent_id,
+ uint32_t depth,
+ uint32_t mapping_id) {
+ TraceStorage::StackProfileFrames::Row row{};
+ row.name_id = StringId(static_cast<uint32_t>(path.class_name));
+ row.mapping_row = mapping_id;
+ int32_t frame_id = static_cast<int32_t>(
+ context_->storage->mutable_stack_profile_frames()->Insert(row));
+
+ parent_id = static_cast<int32_t>(
+ context_->storage->mutable_stack_profile_callsite_table()->Insert(
+ {depth, parent_id, frame_id}));
+ depth++;
+
+ tables::HeapProfileAllocationTable::Row alloc_row{
+ sequence_state.current_ts, sequence_state.current_upid, parent_id,
+ static_cast<int64_t>(path.count), static_cast<int64_t>(path.size)};
+ // TODO(fmayer): Maybe add a separate table for heap graph flamegraphs.
+ context_->storage->mutable_heap_profile_allocation_table()->Insert(alloc_row);
+ for (const auto& p : path.children) {
+ const HeapGraphWalker::PathFromRoot& child = p.second;
+ WriteFlamegraph(sequence_state, child, parent_id, depth, mapping_id);
+ }
+}
+
void HeapGraphTracker::MarkReachable(int64_t row) {
context_->storage->mutable_heap_graph_object_table()
->mutable_reachable()
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.h b/src/trace_processor/importers/proto/heap_graph_tracker.h
index 86ca98d..219059b 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker.h
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.h
@@ -104,6 +104,12 @@
SequenceState& GetOrCreateSequence(uint32_t seq_id);
bool SetPidAndTimestamp(SequenceState* seq, UniquePid upid, int64_t ts);
+ void WriteFlamegraph(const SequenceState& sequence_state,
+ const HeapGraphWalker::PathFromRoot& path,
+ int32_t parent_id,
+ uint32_t depth,
+ uint32_t mapping_id);
+
TraceProcessorContext* const context_;
std::map<uint32_t, SequenceState> sequence_state_;
diff --git a/src/trace_processor/importers/proto/heap_graph_walker.cc b/src/trace_processor/importers/proto/heap_graph_walker.cc
index 020d3b4..90fd398 100644
--- a/src/trace_processor/importers/proto/heap_graph_walker.cc
+++ b/src/trace_processor/importers/proto/heap_graph_walker.cc
@@ -17,6 +17,8 @@
#include "src/trace_processor/importers/proto/heap_graph_walker.h"
#include "perfetto/base/logging.h"
+#include <deque>
+
namespace perfetto {
namespace trace_processor {
namespace {
@@ -57,12 +59,13 @@
HeapGraphWalker::Delegate::~Delegate() = default;
-void HeapGraphWalker::AddNode(int64_t row, uint64_t size) {
+void HeapGraphWalker::AddNode(int64_t row, uint64_t size, int32_t class_name) {
if (static_cast<size_t>(row) >= nodes_.size())
nodes_.resize(static_cast<size_t>(row) + 1);
Node& node = GetNode(row);
node.self_size = size;
node.row = row;
+ node.class_name = class_name;
}
void HeapGraphWalker::AddEdge(int64_t owner_row, int64_t owned_row) {
@@ -74,14 +77,33 @@
}
void HeapGraphWalker::MarkRoot(int64_t row) {
- Node& n = GetNode(row);
- n.root = true;
- ReachableNode(&n);
+ Node* node = &GetNode(row);
+ roots_.emplace_back(node);
+
+ // Calculate shortest distance to a GC root.
+ std::deque<std::pair<int32_t, Node*>> reachable_nodes{{0, node}};
+ while (!reachable_nodes.empty()) {
+ Node* cur_node;
+ int32_t distance;
+ std::tie(distance, cur_node) = reachable_nodes.front();
+ reachable_nodes.pop_front();
+ if (cur_node->distance_to_root == -1 ||
+ cur_node->distance_to_root > distance) {
+ if (cur_node->distance_to_root == -1)
+ delegate_->MarkReachable(cur_node->row);
+ cur_node->distance_to_root = distance;
+ for (Node* child_node : cur_node->children) {
+ if (child_node->distance_to_root == -1 ||
+ child_node->distance_to_root > distance + 1)
+ reachable_nodes.emplace_back(distance + 1, child_node);
+ }
+ }
+ }
}
void HeapGraphWalker::CalculateRetained() {
for (Node& n : nodes_) {
- if (n.reachable && n.node_index == 0)
+ if (n.reachable() && n.node_index == 0)
FindSCC(&n);
}
@@ -90,22 +112,6 @@
PERFETTO_CHECK(c.incoming_edges == 0);
}
-void HeapGraphWalker::ReachableNode(Node* node) {
- if (node->reachable)
- return;
- std::vector<Node*> reachable_nodes{node};
- while (!reachable_nodes.empty()) {
- Node* cur_node = reachable_nodes.back();
- reachable_nodes.pop_back();
- if (!cur_node->reachable) {
- delegate_->MarkReachable(cur_node->row);
- cur_node->reachable = true;
- reachable_nodes.insert(reachable_nodes.end(), cur_node->children.cbegin(),
- cur_node->children.cend());
- }
- }
-}
-
int64_t HeapGraphWalker::RetainedSize(const Component& component) {
int64_t retained_size =
static_cast<int64_t>(component.unique_retained_size) +
@@ -163,7 +169,7 @@
// A node can never be part of two components.
PERFETTO_CHECK(stack_elem->component == -1);
stack_elem->component = component_id;
- if (stack_elem->root)
+ if (stack_elem->root())
component.root = true;
} while (stack_elem != node);
@@ -171,7 +177,7 @@
component.unique_retained_size += elem->self_size;
for (Node* parent : elem->parents) {
// We do not count intra-component edges.
- if (parent->reachable && parent->component != component_id)
+ if (parent->reachable() && parent->component != component_id)
component.incoming_edges++;
}
component.orig_incoming_edges = component.incoming_edges;
@@ -306,7 +312,7 @@
walk_child.pop_back();
} else {
Node* child = node->children[child_idx++];
- PERFETTO_CHECK(child->reachable);
+ PERFETTO_CHECK(child->reachable());
if (child->node_index == 0) {
walk_stack.emplace_back(child);
walk_child.emplace_back(0);
@@ -317,5 +323,31 @@
}
}
+HeapGraphWalker::PathFromRoot HeapGraphWalker::FindPathsFromRoot() {
+ for (Node* root : roots_)
+ FindPathFromRoot(root, &path_);
+ for (Node& node : nodes_)
+ node.find_paths_from_root_visited = false;
+ return std::move(path_);
+}
+
+// TODO(fmayer): Teach this to handle field names.
+void HeapGraphWalker::FindPathFromRoot(Node* n, PathFromRoot* parent) {
+ PathFromRoot& cur = parent->children[n->class_name];
+ cur.size += n->self_size;
+ cur.count++;
+ cur.parent = parent;
+ cur.class_name = n->class_name;
+ for (Node* child : n->children) {
+ if (child->distance_to_root == n->distance_to_root + 1 &&
+ !child->find_paths_from_root_visited) {
+ // Mark as visited in case there is another path with the same distance
+ // from a root.
+ child->find_paths_from_root_visited = true;
+ FindPathFromRoot(child, &cur);
+ }
+ }
+}
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/heap_graph_walker.h b/src/trace_processor/importers/proto/heap_graph_walker.h
index c05c6df..4ec3dc8 100644
--- a/src/trace_processor/importers/proto/heap_graph_walker.h
+++ b/src/trace_processor/importers/proto/heap_graph_walker.h
@@ -97,6 +97,14 @@
class HeapGraphWalker {
public:
+ struct PathFromRoot {
+ uint64_t size = 0;
+ uint64_t count = 0;
+ int32_t class_name = -1;
+ std::map<int32_t, PathFromRoot> children;
+ PathFromRoot* parent = nullptr;
+ };
+
class Delegate {
public:
virtual ~Delegate();
@@ -109,7 +117,8 @@
HeapGraphWalker(Delegate* delegate) : delegate_(delegate) {}
void AddEdge(int64_t owner_row, int64_t owned_row);
- void AddNode(int64_t row, uint64_t size);
+ void AddNode(int64_t row, uint64_t size) { AddNode(row, size, -1); }
+ void AddNode(int64_t row, uint64_t size, int32_t class_name);
// Mark a a node as root. This marks all the nodes reachable from it as
// reachable.
@@ -118,6 +127,8 @@
// includes nodes not reachable from roots.
void CalculateRetained();
+ PathFromRoot FindPathsFromRoot();
+
private:
struct Node {
std::vector<Node*> children;
@@ -130,9 +141,14 @@
uint64_t lowlink = 0;
int64_t component = -1;
- bool reachable = false;
+ int32_t class_name = -1;
+ int32_t distance_to_root = -1;
+
bool on_stack = false;
- bool root = false;
+ bool find_paths_from_root_visited = false;
+
+ bool root() { return distance_to_root == 0; }
+ bool reachable() { return distance_to_root >= 0; }
};
struct Component {
@@ -154,14 +170,16 @@
void FoundSCC(Node*);
int64_t RetainedSize(const Component&);
- // Make node and all transitive children as reachable.
- void ReachableNode(Node*);
+ void FindPathFromRoot(Node* n, PathFromRoot* parent);
std::vector<Component> components_;
std::vector<Node*> node_stack_;
uint64_t next_node_index_ = 1;
std::vector<Node> nodes_;
+ PathFromRoot path_;
+ std::vector<Node*> roots_;
+
Delegate* delegate_;
};
diff --git a/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc b/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
index 7ec9c09..4b1b586 100644
--- a/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
+++ b/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
@@ -583,6 +583,76 @@
});
}
+bool HasPath(const HeapGraphWalker::PathFromRoot& path,
+ std::vector<int32_t> class_names) {
+ if (class_names.empty())
+ return true;
+ auto it = path.children.find(class_names[0]);
+ if (it == path.children.end())
+ return false;
+ class_names.erase(class_names.begin());
+ return HasPath(it->second, class_names);
+}
+
+// 1 |
+// ^^ |
+// / \ |
+// 2<-> 3 |
+// ^ |
+// | |
+// 4R |
+TEST(HeapGraphWalkeTest, ShortestPath) {
+ HeapGraphWalkerTestDelegate delegate;
+ HeapGraphWalker walker(&delegate);
+ walker.AddNode(1, 1, 1);
+ walker.AddNode(2, 2, 2);
+ walker.AddNode(3, 3, 3);
+ walker.AddNode(4, 4, 4);
+
+ walker.AddEdge(2, 1);
+ walker.AddEdge(2, 3);
+ walker.AddEdge(3, 1);
+ walker.AddEdge(3, 2);
+ walker.AddEdge(4, 2);
+
+ walker.MarkRoot(4);
+ auto path = walker.FindPathsFromRoot();
+
+ EXPECT_TRUE(HasPath(path, {4, 2, 1}));
+ EXPECT_TRUE(HasPath(path, {4, 2, 3}));
+ EXPECT_FALSE(HasPath(path, {4, 2, 3, 1}));
+}
+
+// 1 |
+// ^^ |
+// / \ |
+// 2R<->3 |
+// ^ |
+// | |
+// 4R |
+TEST(HeapGraphWalkeTest, ShortestPathMultipleRoots) {
+ HeapGraphWalkerTestDelegate delegate;
+ HeapGraphWalker walker(&delegate);
+ walker.AddNode(1, 1, 1);
+ walker.AddNode(2, 2, 2);
+ walker.AddNode(3, 3, 3);
+ walker.AddNode(4, 4, 4);
+
+ walker.AddEdge(2, 1);
+ walker.AddEdge(2, 3);
+ walker.AddEdge(3, 1);
+ walker.AddEdge(3, 2);
+ walker.AddEdge(4, 2);
+
+ walker.MarkRoot(4);
+ walker.MarkRoot(2);
+ auto path = walker.FindPathsFromRoot();
+
+ EXPECT_TRUE(HasPath(path, {2, 1}));
+ EXPECT_TRUE(HasPath(path, {2, 3}));
+ EXPECT_FALSE(HasPath(path, {4, 2, 3}));
+}
+
} // namespace
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/packet_sequence_state.h b/src/trace_processor/importers/proto/packet_sequence_state.h
index b6bc5a6..c020758 100644
--- a/src/trace_processor/importers/proto/packet_sequence_state.h
+++ b/src/trace_processor/importers/proto/packet_sequence_state.h
@@ -29,6 +29,8 @@
#include "src/trace_processor/trace_processor_context.h"
#include "src/trace_processor/trace_storage.h"
+#include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
+
namespace perfetto {
namespace trace_processor {
@@ -43,51 +45,124 @@
class PacketSequenceState {
public:
// Entry in an interning index, refers to the interned message.
- struct InternedMessageView {
- InternedMessageView(TraceBlobView msg) : message(std::move(msg)) {}
+ class InternedMessageView {
+ public:
+ InternedMessageView(TraceBlobView msg) : message_(std::move(msg)) {}
+ InternedMessageView(InternedMessageView&&) noexcept = default;
+ InternedMessageView& operator=(InternedMessageView&&) = default;
+
+ // Allow copy by cloning the TraceBlobView. This is required for
+ // UpdateTracePacketDefaults().
+ InternedMessageView(const InternedMessageView& view)
+ : message_(view.message_.slice(0, view.message_.length())) {}
+ InternedMessageView& operator=(const InternedMessageView& view) {
+ this->message_ = view.message_.slice(0, view.message_.length());
+ this->decoder_ = nullptr;
+ this->decoder_type_ = nullptr;
+ this->submessages_.clear();
+ return *this;
+ }
+
+ // Lazily initializes and returns the decoder object for the message. The
+ // decoder is stored in the InternedMessageView to avoid having to parse the
+ // message multiple times.
template <typename MessageType>
typename MessageType::Decoder* GetOrCreateDecoder() {
- if (!decoder) {
+ if (!decoder_) {
// Lazy init the decoder and save it away, so that we don't have to
// reparse the message every time we access the interning entry.
- decoder = std::unique_ptr<void, std::function<void(void*)>>(
- new typename MessageType::Decoder(message.data(), message.length()),
+ decoder_ = std::unique_ptr<void, std::function<void(void*)>>(
+ new
+ typename MessageType::Decoder(message_.data(), message_.length()),
[](void* obj) {
delete reinterpret_cast<typename MessageType::Decoder*>(obj);
});
- decoder_type = PERFETTO_TYPE_IDENTIFIER;
+ decoder_type_ = PERFETTO_TYPE_IDENTIFIER;
}
// Verify that the type of the decoder didn't change.
if (PERFETTO_TYPE_IDENTIFIER &&
- strcmp(decoder_type,
+ strcmp(decoder_type_,
// GCC complains if this arg can be null.
PERFETTO_TYPE_IDENTIFIER ? PERFETTO_TYPE_IDENTIFIER : "") !=
0) {
PERFETTO_FATAL(
"Interning entry accessed under different types! previous type: "
"%s. new type: %s.",
- decoder_type, __PRETTY_FUNCTION__);
+ decoder_type_, __PRETTY_FUNCTION__);
}
- return reinterpret_cast<typename MessageType::Decoder*>(decoder.get());
+ return reinterpret_cast<typename MessageType::Decoder*>(decoder_.get());
}
- TraceBlobView message;
- std::unique_ptr<void, std::function<void(void*)>> decoder;
+ // Lookup a submessage of the interned message, which is then itself stored
+ // as InternedMessageView, so that we only need to parse it once. Returns
+ // nullptr if the field isn't set.
+ // TODO(eseckler): Support repeated fields.
+ template <typename MessageType, uint32_t FieldId>
+ InternedMessageView* GetOrCreateSubmessageView() {
+ auto it = submessages_.find(FieldId);
+ if (it != submessages_.end())
+ return it->second.get();
+ auto* decoder = GetOrCreateDecoder<MessageType>();
+ // Calls the at() template method on the decoder.
+ auto field = decoder->template at<FieldId>().as_bytes();
+ if (!field.data)
+ return nullptr;
+ const size_t offset = message_.offset_of(field.data);
+ TraceBlobView submessage = message_.slice(offset, field.size);
+ InternedMessageView* submessage_view =
+ new InternedMessageView(std::move(submessage));
+ submessages_.emplace_hint(
+ it, FieldId, std::unique_ptr<InternedMessageView>(submessage_view));
+ return submessage_view;
+ }
+
+ const TraceBlobView& message() { return message_; }
private:
- const char* decoder_type = nullptr;
+ using SubMessageViewMap =
+ std::unordered_map<uint32_t /*field_id*/,
+ std::unique_ptr<InternedMessageView>>;
+
+ TraceBlobView message_;
+
+ // Stores the decoder for the message_, so that the message does not have to
+ // be re-decoded every time the interned message is looked up. Lazily
+ // initialized in GetOrCreateDecoder(). Since we don't know the type of the
+ // decoder until GetOrCreateDecoder() is called, we store the decoder as a
+ // void* unique_pointer with a destructor function that's supplied in
+ // GetOrCreateDecoder() when the decoder is created.
+ std::unique_ptr<void, std::function<void(void*)>> decoder_;
+
+ // Type identifier for the decoder. Only valid in debug builds and on
+ // supported platforms. Used to verify that GetOrCreateDecoder() is always
+ // called with the same template argument.
+ const char* decoder_type_ = nullptr;
+
+ // Views of submessages of the interned message. Submessages are lazily
+ // added by GetOrCreateSubmessageView(). By storing submessages and their
+ // decoders, we avoid having to decode submessages multiple times if they
+ // looked up often.
+ SubMessageViewMap submessages_;
};
using InternedMessageMap =
std::unordered_map<uint64_t /*iid*/, InternedMessageView>;
using InternedFieldMap =
std::unordered_map<uint32_t /*field_id*/, InternedMessageMap>;
- using InternedDataGenerationList = std::vector<InternedFieldMap>;
+
+ struct GenerationData {
+ InternedFieldMap interned_data;
+ base::Optional<InternedMessageView> trace_packet_defaults;
+ };
+
+ // TODO(eseckler): Reference count the generations so that we can get rid of
+ // past generations once all packets referring to them have been parsed.
+ using GenerationList = std::vector<GenerationData>;
PacketSequenceState(TraceProcessorContext* context)
: context_(context), stack_profile_tracker_(context) {
- interned_data_.emplace_back();
+ generations_.emplace_back();
}
int64_t IncrementAndGetTrackEventTimeNs(int64_t delta_ns) {
@@ -115,7 +190,7 @@
void OnIncrementalStateCleared() {
packet_loss_ = false;
- interned_data_.emplace_back(); // Bump generation number
+ generations_.emplace_back(); // Bump generation number
}
void SetThreadDescriptor(int32_t pid,
@@ -138,9 +213,8 @@
return stack_profile_tracker_;
}
- // Returns the index of the current generation in the
- // InternedDataGenerationList.
- size_t current_generation() const { return interned_data_.size() - 1; }
+ // Returns the index of the current generation in the GenerationList.
+ size_t current_generation() const { return generations_.size() - 1; }
bool track_event_timestamps_valid() const {
return track_event_timestamps_valid_;
@@ -167,7 +241,7 @@
}
iid = field.as_uint64();
- auto* map = &interned_data_.back()[field_id];
+ auto* map = &generations_.back().interned_data[field_id];
auto res = map->emplace(iid, InternedMessageView(std::move(message)));
// If a message with this ID is already interned in the same generation,
@@ -176,16 +250,18 @@
// TODO(eseckler): This DCHECK assumes that the message is encoded the
// same way if it is re-emitted.
PERFETTO_DCHECK(res.second ||
- (res.first->second.message.length() == message_size &&
- memcmp(res.first->second.message.data(), message_start,
+ (res.first->second.message().length() == message_size &&
+ memcmp(res.first->second.message().data(), message_start,
message_size) == 0));
}
+ // Returns |nullptr| if the message with the given |iid| was not found (also
+ // records a stat in this case).
template <uint32_t FieldId, typename MessageType>
typename MessageType::Decoder* LookupInternedMessage(size_t generation,
uint64_t iid) {
- PERFETTO_CHECK(generation <= interned_data_.size());
- auto* field_map = &interned_data_[generation];
+ PERFETTO_CHECK(generation <= generations_.size());
+ auto* field_map = &generations_[generation].interned_data;
auto field_it = field_map->find(FieldId);
if (field_it != field_map->end()) {
auto* message_map = &field_it->second;
@@ -201,6 +277,37 @@
return nullptr;
}
+ void UpdateTracePacketDefaults(TraceBlobView trace_packet_defaults) {
+ if (generations_.back().trace_packet_defaults) {
+ // The new defaults should only apply to subsequent messages on the
+ // sequence. Add a new generation with the updated defaults but the
+ // current generation's interned data state.
+ const InternedFieldMap& current_interned_data =
+ generations_.back().interned_data;
+ generations_.emplace_back();
+ generations_.back().interned_data = current_interned_data;
+ }
+ generations_.back().trace_packet_defaults =
+ InternedMessageView(std::move(trace_packet_defaults));
+ }
+
+ // Returns |nullptr| if no defaults were set in the given generation.
+ InternedMessageView* GetTracePacketDefaultsView(size_t generation) {
+ PERFETTO_CHECK(generation <= generations_.size());
+ if (!generations_[generation].trace_packet_defaults)
+ return nullptr;
+ return &generations_[generation].trace_packet_defaults.value();
+ }
+
+ // Returns |nullptr| if no defaults were set in the given generation.
+ typename protos::pbzero::TracePacketDefaults::Decoder* GetTracePacketDefaults(
+ size_t generation) {
+ InternedMessageView* view = GetTracePacketDefaultsView(generation);
+ if (!view)
+ return nullptr;
+ return view->GetOrCreateDecoder<protos::pbzero::TracePacketDefaults>();
+ }
+
private:
TraceProcessorContext* context_;
@@ -229,7 +336,7 @@
int64_t track_event_thread_timestamp_ns_ = 0;
int64_t track_event_thread_instruction_count_ = 0;
- InternedDataGenerationList interned_data_;
+ GenerationList generations_;
StackProfileTracker stack_profile_tracker_;
};
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index c08b5e6..01c0156 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -623,7 +623,7 @@
for (auto addr_it = module_symbols.address_symbols(); addr_it; ++addr_it) {
protos::pbzero::AddressSymbols::Decoder address_symbols(*addr_it);
- uint32_t symbol_set_id = context_->storage->symbol_table().size();
+ uint32_t symbol_set_id = context_->storage->symbol_table().row_count();
bool frame_found = false;
for (int64_t mapping_row : mapping_rows) {
std::vector<int64_t> frame_rows =
diff --git a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
index 4d9150d..a2455ce 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
@@ -24,13 +24,9 @@
#include "src/trace_processor/event_tracker.h"
#include "src/trace_processor/importers/ftrace/ftrace_module.h"
#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
-#include "src/trace_processor/importers/proto/android_probes_module.h"
-#include "src/trace_processor/importers/proto/heap_graph_module.h"
#include "src/trace_processor/importers/proto/proto_importer_module.h"
#include "src/trace_processor/importers/proto/proto_trace_parser.h"
-#include "src/trace_processor/importers/proto/system_probes_module.h"
#include "src/trace_processor/importers/proto/track_event_module.h"
-#include "src/trace_processor/importers/systrace/systrace_parser.h"
#include "src/trace_processor/metadata.h"
#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/register_additional_modules.h"
@@ -84,8 +80,6 @@
using ::testing::Return;
using ::testing::UnorderedElementsAreArray;
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE) || \
- PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
namespace {
MATCHER_P(DoubleEq, exp, "Double matcher that satisfies -Wfloat-equal") {
// The IEEE standard says that any comparison operation involving
@@ -97,15 +91,12 @@
return fabs(d_arg - d_exp) < 1e-128;
}
} // namespace
-#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE) ||
- // PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
class MockSchedEventTracker : public SchedEventTracker {
public:
MockSchedEventTracker(TraceProcessorContext* context)
: SchedEventTracker(context) {}
- virtual ~MockSchedEventTracker() = default;
MOCK_METHOD9(PushSchedSwitch,
void(uint32_t cpu,
@@ -251,7 +242,6 @@
context_.sorter.reset(new TraceSorter(&context_, 0 /*window size*/));
context_.parser.reset(new ProtoTraceParser(&context_));
#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
- context_.systrace_parser.reset(new SystraceParser(&context_));
context_.modules.emplace_back(new FtraceModuleImpl(&context_));
#else
context_.modules.emplace_back(new FtraceModule());
@@ -259,15 +249,6 @@
context_.ftrace_module =
static_cast<FtraceModule*>(context_.modules.back().get());
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_HEAP_GRAPHS)
- context_.modules.emplace_back(new HeapGraphModule(&context_));
-#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_HEAP_GRAPHS)
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_ANDROID_PROBES)
- context_.modules.emplace_back(new AndroidProbesModule(&context_));
-#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_ANDROID_PROBES)
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
- context_.modules.emplace_back(new SystemProbesModule(&context_));
-#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
context_.modules.emplace_back(new TrackEventModule(&context_));
RegisterAdditionalModules(&context_);
@@ -383,9 +364,6 @@
static const char buf_value[] = "This is a print event";
print->set_buf(buf_value);
- EXPECT_CALL(*storage_, InternString(base::StringView(task_newtask)))
- .Times(AtLeast(1));
- EXPECT_CALL(*storage_, InternString(base::StringView(buf_value)));
EXPECT_CALL(*process_, UpdateThread(123, 123));
Tokenize();
@@ -611,8 +589,6 @@
#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
-
TEST_F(ProtoTraceParserTest, LoadMemInfo) {
auto* packet = trace_.add_packet();
uint64_t ts = 1000;
@@ -627,7 +603,7 @@
DoubleEq(value * 1024.0), 0u));
Tokenize();
- EXPECT_EQ(context_.storage->track_table().size(), 1u);
+ EXPECT_EQ(context_.storage->track_table().row_count(), 1u);
}
TEST_F(ProtoTraceParserTest, LoadVmStats) {
@@ -644,7 +620,7 @@
PushCounter(static_cast<int64_t>(ts), DoubleEq(value), 0u));
Tokenize();
- EXPECT_EQ(context_.storage->track_table().size(), 1u);
+ EXPECT_EQ(context_.storage->track_table().row_count(), 1u);
}
TEST_F(ProtoTraceParserTest, LoadProcessPacket) {
@@ -687,8 +663,6 @@
Tokenize();
}
-#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
-
TEST_F(ProtoTraceParserTest, ThreadNameFromThreadDescriptor) {
context_.sorter.reset(new TraceSorter(
&context_, std::numeric_limits<int64_t>::max() /*window size*/));
@@ -1254,12 +1228,12 @@
context_.sorter->ExtractEventsForced();
// First track is for the thread; others are the async event tracks.
- EXPECT_EQ(storage_->track_table().size(), 4u);
+ EXPECT_EQ(storage_->track_table().row_count(), 4u);
EXPECT_EQ(storage_->track_table().name()[1], 2u);
EXPECT_EQ(storage_->track_table().name()[2], 4u);
EXPECT_EQ(storage_->track_table().name()[3], 4u);
- EXPECT_EQ(storage_->process_track_table().size(), 3u);
+ EXPECT_EQ(storage_->process_track_table().row_count(), 3u);
EXPECT_EQ(storage_->process_track_table().upid()[0], 1u);
EXPECT_EQ(storage_->process_track_table().upid()[1], 1u);
EXPECT_EQ(storage_->process_track_table().upid()[2], 1u);
@@ -1419,11 +1393,11 @@
// First track is "Thread track 1"; second is "Async track 1", third is
// "Thread track 2".
- EXPECT_EQ(storage_->track_table().size(), 3u);
+ EXPECT_EQ(storage_->track_table().row_count(), 3u);
EXPECT_EQ(storage_->track_table().name()[0], 10u); // "Thread track 1"
EXPECT_EQ(storage_->track_table().name()[1], 11u); // "Async track 1"
EXPECT_EQ(storage_->track_table().name()[2], 12u); // "Thread track 2"
- EXPECT_EQ(storage_->thread_track_table().size(), 2u);
+ EXPECT_EQ(storage_->thread_track_table().row_count(), 2u);
EXPECT_EQ(storage_->thread_track_table().utid()[0], 1u);
EXPECT_EQ(storage_->thread_track_table().utid()[1], 2u);
@@ -1456,8 +1430,8 @@
context_.sorter->ExtractEventsForced();
// Track tables shouldn't have changed.
- EXPECT_EQ(storage_->track_table().size(), 3u);
- EXPECT_EQ(storage_->thread_track_table().size(), 2u);
+ EXPECT_EQ(storage_->track_table().row_count(), 3u);
+ EXPECT_EQ(storage_->thread_track_table().row_count(), 2u);
EXPECT_EQ(storage_->virtual_track_slices().slice_count(), 1u);
EXPECT_EQ(storage_->virtual_track_slices().slice_ids()[0], 0u);
@@ -2462,7 +2436,6 @@
Variadic::String(3))}));
}
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_ANDROID_PROBES)
TEST_F(ProtoTraceParserTest, AndroidPackagesList) {
auto* packet = trace_.add_packet();
auto* pkg_list = packet->set_packages_list();
@@ -2543,7 +2516,6 @@
false);
EXPECT_EQ(find_arg(second_set_id, "version_code").int_value, 43);
}
-#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_ANDROID_PROBES)
TEST_F(ProtoTraceParserTest, ParseCPUProfileSamplesIntoTable) {
{
diff --git a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
index 97d7689..8ac2b36 100644
--- a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
+++ b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
@@ -186,63 +186,8 @@
return util::ErrStatus(
"Failed to parse proto packet fully; the trace is probably corrupt.");
- auto timestamp =
- decoder.has_timestamp()
- ? static_cast<int64_t>(decoder.timestamp())
- : std::max(latest_timestamp_, context_->sorter->max_timestamp());
-
const uint32_t seq_id = decoder.trusted_packet_sequence_id();
-
- if ((decoder.has_chrome_events() || decoder.has_chrome_metadata()) &&
- (!decoder.timestamp_clock_id() ||
- decoder.timestamp_clock_id() ==
- protos::pbzero::ClockSnapshot::Clock::MONOTONIC)) {
- // Chrome event timestamps are in MONOTONIC domain, but may occur in traces
- // where (a) no clock snapshots exist or (b) no clock_id is specified for
- // their timestamps. Adjust to trace time if we have a clock snapshot.
- // TODO(eseckler): Set timestamp_clock_id and emit ClockSnapshots in chrome
- // and then remove this.
- auto trace_ts = context_->clock_tracker->ToTraceTime(
- protos::pbzero::ClockSnapshot::Clock::MONOTONIC, timestamp);
- if (trace_ts.has_value())
- timestamp = trace_ts.value();
- } else if (decoder.timestamp_clock_id()) {
- // If the TracePacket specifies a non-zero clock-id, translate the timestamp
- // into the trace-time clock domain.
- PERFETTO_DCHECK(decoder.has_timestamp());
- ClockTracker::ClockId clock_id = decoder.timestamp_clock_id();
- bool is_seq_scoped = ClockTracker::IsReservedSeqScopedClockId(clock_id);
- if (is_seq_scoped) {
- if (!seq_id) {
- return util::ErrStatus(
- "TracePacket specified a sequence-local clock id (%" PRIu32
- ") but the TraceWriter's sequence_id is zero (the service is "
- "probably too old)",
- decoder.timestamp_clock_id());
- }
- clock_id = ClockTracker::SeqScopedClockIdToGlobal(
- seq_id, decoder.timestamp_clock_id());
- }
- auto trace_ts = context_->clock_tracker->ToTraceTime(clock_id, timestamp);
- if (!trace_ts.has_value()) {
- // ToTraceTime() will increase the |clock_sync_failure| stat on failure.
- static const char seq_extra_err[] =
- " Because the clock id is sequence-scoped, the ClockSnapshot must be "
- "emitted on the same TraceWriter sequence of the packet that refers "
- "to that clock id.";
- return util::ErrStatus(
- "Failed to convert TracePacket's timestamp from clock_id=%" PRIu32
- " seq_id=%" PRIu32
- ". This is usually due to the lack of a prior ClockSnapshot proto.%s",
- decoder.timestamp_clock_id(), seq_id,
- is_seq_scoped ? seq_extra_err : "");
- }
- timestamp = trace_ts.value();
- }
- latest_timestamp_ = std::max(timestamp, latest_timestamp_);
-
- auto* state = GetIncrementalStateForPacketSequence(
- decoder.trusted_packet_sequence_id());
+ auto* state = GetIncrementalStateForPacketSequence(seq_id);
uint32_t sequence_flags = decoder.sequence_flags();
@@ -254,6 +199,25 @@
HandlePreviousPacketDropped(decoder);
}
+ // It is important that we parse defaults before parsing other fields such as
+ // the timestamp, since the defaults could affect them.
+ if (decoder.has_trace_packet_defaults()) {
+ auto field = decoder.trace_packet_defaults();
+ const size_t offset = packet.offset_of(field.data);
+ ParseTracePacketDefaults(decoder, packet.slice(offset, field.size));
+ }
+
+ if (decoder.has_interned_data()) {
+ auto field = decoder.interned_data();
+ const size_t offset = packet.offset_of(field.data);
+ ParseInternedData(decoder, packet.slice(offset, field.size));
+ }
+
+ if (decoder.has_clock_snapshot()) {
+ return ParseClockSnapshot(decoder.clock_snapshot(),
+ decoder.trusted_packet_sequence_id());
+ }
+
if (decoder.sequence_flags() &
protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE) {
if (!seq_id) {
@@ -269,18 +233,70 @@
}
}
- if (decoder.has_clock_snapshot()) {
- return ParseClockSnapshot(decoder.clock_snapshot(),
- decoder.trusted_packet_sequence_id());
- }
+ protos::pbzero::TracePacketDefaults::Decoder* defaults =
+ state->GetTracePacketDefaults(state->current_generation());
- // TODO(eseckler): Parse TracePacketDefaults.
+ int64_t timestamp;
+ if (decoder.has_timestamp()) {
+ timestamp = static_cast<int64_t>(decoder.timestamp());
- if (decoder.has_interned_data()) {
- auto field = decoder.interned_data();
- const size_t offset = packet.offset_of(field.data);
- ParseInternedData(decoder, packet.slice(offset, field.size));
+ uint32_t timestamp_clock_id =
+ decoder.has_timestamp_clock_id()
+ ? decoder.timestamp_clock_id()
+ : (defaults ? defaults->timestamp_clock_id() : 0);
+
+ if ((decoder.has_chrome_events() || decoder.has_chrome_metadata()) &&
+ (!timestamp_clock_id ||
+ timestamp_clock_id ==
+ protos::pbzero::ClockSnapshot::Clock::MONOTONIC)) {
+ // Chrome event timestamps are in MONOTONIC domain, but may occur in
+ // traces where (a) no clock snapshots exist or (b) no clock_id is
+ // specified for their timestamps. Adjust to trace time if we have a clock
+ // snapshot.
+ // TODO(eseckler): Set timestamp_clock_id and emit ClockSnapshots in
+ // chrome and then remove this.
+ auto trace_ts = context_->clock_tracker->ToTraceTime(
+ protos::pbzero::ClockSnapshot::Clock::MONOTONIC, timestamp);
+ if (trace_ts.has_value())
+ timestamp = trace_ts.value();
+ } else if (timestamp_clock_id) {
+ // If the TracePacket specifies a non-zero clock-id, translate the
+ // timestamp into the trace-time clock domain.
+ ClockTracker::ClockId converted_clock_id = timestamp_clock_id;
+ bool is_seq_scoped =
+ ClockTracker::IsReservedSeqScopedClockId(converted_clock_id);
+ if (is_seq_scoped) {
+ if (!seq_id) {
+ return util::ErrStatus(
+ "TracePacket specified a sequence-local clock id (%" PRIu32
+ ") but the TraceWriter's sequence_id is zero (the service is "
+ "probably too old)",
+ timestamp_clock_id);
+ }
+ converted_clock_id =
+ ClockTracker::SeqScopedClockIdToGlobal(seq_id, timestamp_clock_id);
+ }
+ auto trace_ts =
+ context_->clock_tracker->ToTraceTime(converted_clock_id, timestamp);
+ if (!trace_ts.has_value()) {
+ // ToTraceTime() will increase the |clock_sync_failure| stat on failure.
+ static const char seq_extra_err[] =
+ " Because the clock id is sequence-scoped, the ClockSnapshot must "
+ "be emitted on the same TraceWriter sequence of the packet that "
+ "refers to that clock id.";
+ return util::ErrStatus(
+ "Failed to convert TracePacket's timestamp from clock_id=%" PRIu32
+ " seq_id=%" PRIu32
+ ". This is usually due to the lack of a prior ClockSnapshot "
+ "proto.%s",
+ timestamp_clock_id, seq_id, is_seq_scoped ? seq_extra_err : "");
+ }
+ timestamp = trace_ts.value();
+ }
+ } else {
+ timestamp = std::max(latest_timestamp_, context_->sorter->max_timestamp());
}
+ latest_timestamp_ = std::max(timestamp, latest_timestamp_);
auto& modules = context_->modules_by_field;
for (uint32_t field_id = 1; field_id < modules.size(); ++field_id) {
@@ -380,6 +396,21 @@
->OnPacketLoss();
}
+void ProtoTraceTokenizer::ParseTracePacketDefaults(
+ const protos::pbzero::TracePacket_Decoder& packet_decoder,
+ TraceBlobView trace_packet_defaults) {
+ if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
+ PERFETTO_ELOG(
+ "TracePacketDefaults packet without trusted_packet_sequence_id");
+ context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
+ return;
+ }
+
+ auto* state = GetIncrementalStateForPacketSequence(
+ packet_decoder.trusted_packet_sequence_id());
+ state->UpdateTracePacketDefaults(std::move(trace_packet_defaults));
+}
+
void ProtoTraceTokenizer::ParseInternedData(
const protos::pbzero::TracePacket::Decoder& packet_decoder,
TraceBlobView interned_data) {
diff --git a/src/trace_processor/importers/proto/proto_trace_tokenizer.h b/src/trace_processor/importers/proto/proto_trace_tokenizer.h
index bdefa2e..0612068 100644
--- a/src/trace_processor/importers/proto/proto_trace_tokenizer.h
+++ b/src/trace_processor/importers/proto/proto_trace_tokenizer.h
@@ -67,6 +67,8 @@
void HandleIncrementalStateCleared(
const protos::pbzero::TracePacket_Decoder&);
void HandlePreviousPacketDropped(const protos::pbzero::TracePacket_Decoder&);
+ void ParseTracePacketDefaults(const protos::pbzero::TracePacket_Decoder&,
+ TraceBlobView trace_packet_defaults);
void ParseInternedData(const protos::pbzero::TracePacket_Decoder&,
TraceBlobView interned_data);
PacketSequenceState* GetIncrementalStateForPacketSequence(
diff --git a/src/trace_processor/importers/proto/system_probes_parser.cc b/src/trace_processor/importers/proto/system_probes_parser.cc
index 8fb1281..5beed38 100644
--- a/src/trace_processor/importers/proto/system_probes_parser.cc
+++ b/src/trace_processor/importers/proto/system_probes_parser.cc
@@ -290,10 +290,11 @@
protos::pbzero::Utsname::Decoder utsname(utsname_blob.data,
utsname_blob.size);
base::StringView machine = utsname.machine();
+ SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(context_);
if (machine == "aarch64" || machine == "armv8l") {
- context_->syscall_tracker->SetArchitecture(kAarch64);
+ syscall_tracker->SetArchitecture(kAarch64);
} else if (machine == "x86_64") {
- context_->syscall_tracker->SetArchitecture(kX86_64);
+ syscall_tracker->SetArchitecture(kX86_64);
} else {
PERFETTO_ELOG("Unknown architecture %s", machine.ToStdString().c_str());
}
diff --git a/src/trace_processor/importers/proto/track_event_parser.cc b/src/trace_processor/importers/proto/track_event_parser.cc
index 85507b3..a044ea7 100644
--- a/src/trace_processor/importers/proto/track_event_parser.cc
+++ b/src/trace_processor/importers/proto/track_event_parser.cc
@@ -28,6 +28,7 @@
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h"
+#include "protos/perfetto/trace/track_event/chrome_histogram_sample.pbzero.h"
#include "protos/perfetto/trace/track_event/chrome_keyed_service.pbzero.h"
#include "protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h"
#include "protos/perfetto/trace/track_event/chrome_user_event.pbzero.h"
@@ -145,6 +146,12 @@
context->storage->InternString("legacy_ipc.line")),
chrome_keyed_service_name_args_key_id_(
context->storage->InternString("keyed_service.name")),
+ chrome_histogram_sample_name_hash_args_key_id_(
+ context->storage->InternString("histogram_sample.name_hash")),
+ chrome_histogram_sample_name_args_key_id_(
+ context->storage->InternString("histogram_sample.name")),
+ chrome_histogram_sample_sample_args_key_id_(
+ context->storage->InternString("histogram_sample.sample")),
chrome_legacy_ipc_class_ids_{
{context->storage->InternString("UNSPECIFIED"),
context->storage->InternString("AUTOMATION"),
@@ -193,6 +200,21 @@
ConstBytes blob) {
using LegacyEvent = protos::pbzero::TrackEvent::LegacyEvent;
+ protos::pbzero::TrackEventDefaults::Decoder* defaults = nullptr;
+ auto* packet_defaults_view =
+ sequence_state->GetTracePacketDefaultsView(sequence_state_generation);
+ if (packet_defaults_view) {
+ auto* track_event_defaults_view =
+ packet_defaults_view
+ ->GetOrCreateSubmessageView<protos::pbzero::TracePacketDefaults,
+ protos::pbzero::TracePacketDefaults::
+ kTrackEventDefaultsFieldNumber>();
+ if (track_event_defaults_view) {
+ defaults = track_event_defaults_view
+ ->GetOrCreateDecoder<protos::pbzero::TrackEventDefaults>();
+ }
+ }
+
protos::pbzero::TrackEvent::Decoder event(blob.data, blob.size);
const auto legacy_event_blob = event.legacy_event();
@@ -275,9 +297,14 @@
name_id = storage->InternString(event.name());
}
- // TODO(eseckler): Also consider track_uuid from TrackEventDefaults.
- // Fall back to the default descriptor track (uuid 0).
- uint64_t track_uuid = event.has_track_uuid() ? event.track_uuid() : 0u;
+ // Consider track_uuid from the packet and TrackEventDefaults, fall back to
+ // the default descriptor track (uuid 0).
+ uint64_t track_uuid =
+ event.has_track_uuid()
+ ? event.track_uuid()
+ : (defaults && defaults->has_track_uuid() ? defaults->track_uuid()
+ : 0u);
+
TrackId track_id;
base::Optional<UniqueTid> utid;
base::Optional<UniqueTid> upid;
@@ -470,6 +497,10 @@
ParseChromeKeyedService(event.chrome_keyed_service(), args_tracker,
row_id);
}
+ if (event.has_chrome_histogram_sample()) {
+ ParseChromeHistogramSample(event.chrome_histogram_sample(), args_tracker,
+ row_id);
+ }
if (legacy_tid) {
args_tracker->AddArg(row_id, legacy_event_original_tid_id_,
@@ -1100,5 +1131,31 @@
}
}
+void TrackEventParser::ParseChromeHistogramSample(
+ protozero::ConstBytes chrome_histogram_sample,
+ ArgsTracker* args_tracker,
+ RowId row) {
+ protos::pbzero::ChromeHistogramSample::Decoder event(
+ chrome_histogram_sample.data, chrome_histogram_sample.size);
+ if (event.has_name_hash()) {
+ uint64_t name_hash = static_cast<uint64_t>(event.name_hash());
+ args_tracker->AddArg(row, chrome_histogram_sample_name_hash_args_key_id_,
+ chrome_histogram_sample_name_hash_args_key_id_,
+ Variadic::UnsignedInteger(name_hash));
+ }
+ if (event.has_name()) {
+ StringId name = context_->storage->InternString(event.name());
+ args_tracker->AddArg(row, chrome_keyed_service_name_args_key_id_,
+ chrome_keyed_service_name_args_key_id_,
+ Variadic::String(name));
+ }
+ if (event.has_sample()) {
+ int64_t sample = static_cast<int64_t>(event.sample());
+ args_tracker->AddArg(row, chrome_histogram_sample_sample_args_key_id_,
+ chrome_histogram_sample_sample_args_key_id_,
+ Variadic::Integer(sample));
+ }
+}
+
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/track_event_parser.h b/src/trace_processor/importers/proto/track_event_parser.h
index e44b76d..6b23187 100644
--- a/src/trace_processor/importers/proto/track_event_parser.h
+++ b/src/trace_processor/importers/proto/track_event_parser.h
@@ -89,6 +89,9 @@
void ParseChromeKeyedService(protozero::ConstBytes chrome_keyed_service,
ArgsTracker*,
RowId);
+ void ParseChromeHistogramSample(protozero::ConstBytes chrome_keyed_service,
+ ArgsTracker*,
+ RowId);
private:
TraceProcessorContext* context_;
@@ -122,6 +125,9 @@
const StringId chrome_legacy_ipc_class_args_key_id_;
const StringId chrome_legacy_ipc_line_args_key_id_;
const StringId chrome_keyed_service_name_args_key_id_;
+ const StringId chrome_histogram_sample_name_hash_args_key_id_;
+ const StringId chrome_histogram_sample_name_args_key_id_;
+ const StringId chrome_histogram_sample_sample_args_key_id_;
std::array<StringId, 38> chrome_legacy_ipc_class_ids_;
};
diff --git a/src/trace_processor/importers/systrace/systrace_parser.cc b/src/trace_processor/importers/systrace/systrace_parser.cc
index 41237d2..a22adeb 100644
--- a/src/trace_processor/importers/systrace/systrace_parser.cc
+++ b/src/trace_processor/importers/systrace/systrace_parser.cc
@@ -28,6 +28,8 @@
SystraceParser::SystraceParser(TraceProcessorContext* ctx)
: context_(ctx), lmk_id_(ctx->storage->InternString("mem.lmk")) {}
+SystraceParser::~SystraceParser() = default;
+
void SystraceParser::ParsePrintEvent(int64_t ts,
uint32_t pid,
base::StringView event) {
@@ -71,7 +73,7 @@
context_->storage->IncrementStats(stats::systrace_parse_failure);
return;
}
- context_->systrace_parser->ParseSystracePoint(ts, pid, point);
+ ParseSystracePoint(ts, pid, point);
}
void SystraceParser::ParseSdeTracingMarkWrite(int64_t ts,
@@ -95,7 +97,7 @@
return;
}
- context_->systrace_parser->ParseSystracePoint(ts, pid, point);
+ ParseSystracePoint(ts, pid, point);
}
void SystraceParser::ParseSystracePoint(
diff --git a/src/trace_processor/importers/systrace/systrace_parser.h b/src/trace_processor/importers/systrace/systrace_parser.h
index ef39bd3..97fd337 100644
--- a/src/trace_processor/importers/systrace/systrace_parser.h
+++ b/src/trace_processor/importers/systrace/systrace_parser.h
@@ -187,9 +187,15 @@
} // namespace systrace_utils
-class SystraceParser {
+class SystraceParser : public Destructible {
public:
- explicit SystraceParser(TraceProcessorContext*);
+ static SystraceParser* GetOrCreate(TraceProcessorContext* context) {
+ if (!context->systrace_parser) {
+ context->systrace_parser.reset(new SystraceParser(context));
+ }
+ return static_cast<SystraceParser*>(context->systrace_parser.get());
+ }
+ ~SystraceParser() override;
void ParsePrintEvent(int64_t ts, uint32_t pid, base::StringView event);
@@ -209,6 +215,7 @@
int64_t value);
private:
+ explicit SystraceParser(TraceProcessorContext*);
void ParseSystracePoint(int64_t ts,
uint32_t pid,
systrace_utils::SystraceTracePoint event);
diff --git a/src/trace_processor/importers/systrace/systrace_trace_parser.cc b/src/trace_processor/importers/systrace/systrace_trace_parser.cc
index 33d5cb1..734c566 100644
--- a/src/trace_processor/importers/systrace/systrace_trace_parser.cc
+++ b/src/trace_processor/importers/systrace/systrace_trace_parser.cc
@@ -195,12 +195,13 @@
return util::Status("Could not parse sched_switch");
}
- context_->sched_tracker->PushSchedSwitch(
+ SchedEventTracker::GetOrCreate(context_)->PushSchedSwitch(
cpu, ts, prev_pid.value(), prev_comm, prev_prio.value(), prev_state,
next_pid.value(), next_comm, next_prio.value());
} else if (event_name == "tracing_mark_write" || event_name == "0" ||
event_name == "print") {
- context_->systrace_parser->ParsePrintEvent(ts, pid, args_str.c_str());
+ SystraceParser::GetOrCreate(context_)->ParsePrintEvent(ts, pid,
+ args_str.c_str());
} else if (event_name == "sched_wakeup") {
auto comm = args["comm"];
base::Optional<uint32_t> wakee_pid = base::StringToUInt32(args["pid"]);
diff --git a/src/trace_processor/metadata.h b/src/trace_processor/metadata.h
index 8965052..aad028f 100644
--- a/src/trace_processor/metadata.h
+++ b/src/trace_processor/metadata.h
@@ -19,7 +19,7 @@
#include <stddef.h>
-#include "src/trace_processor/string_pool.h"
+#include "src/trace_processor/containers/string_pool.h"
#include "src/trace_processor/variadic.h"
namespace perfetto {
diff --git a/src/trace_processor/process_tracker_unittest.cc b/src/trace_processor/process_tracker_unittest.cc
index ad971a5..1122a99 100644
--- a/src/trace_processor/process_tracker_unittest.cc
+++ b/src/trace_processor/process_tracker_unittest.cc
@@ -37,9 +37,6 @@
context.args_tracker.reset(new ArgsTracker(&context));
context.process_tracker.reset(new ProcessTracker(&context));
context.event_tracker.reset(new EventTracker(&context));
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
- context.sched_tracker.reset(new SchedEventTracker(&context));
-#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
}
protected:
@@ -97,13 +94,14 @@
static const char kCommProc1[] = "process1";
static const char kCommProc2[] = "process2";
int32_t prio = 1024;
+ SchedEventTracker* sched_tracker = SchedEventTracker::GetOrCreate(&context);
- context.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, kCommProc2,
- prio, prev_state,
- /*tid=*/4, kCommProc1, prio);
- context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
- kCommProc1, prio, prev_state,
- /*tid=*/1, kCommProc2, prio);
+ sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, kCommProc2, prio,
+ prev_state,
+ /*tid=*/4, kCommProc1, prio);
+ sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4, kCommProc1,
+ prio, prev_state,
+ /*tid=*/1, kCommProc2, prio);
context.process_tracker->SetProcessMetadata(2, base::nullopt, "test");
context.process_tracker->UpdateThread(4, 2);
diff --git a/src/trace_processor/register_additional_modules.cc b/src/trace_processor/register_additional_modules.cc
index cb2b68b..bc9d6ef 100644
--- a/src/trace_processor/register_additional_modules.cc
+++ b/src/trace_processor/register_additional_modules.cc
@@ -15,13 +15,19 @@
*/
#include "src/trace_processor/register_additional_modules.h"
+#include "src/trace_processor/importers/proto/android_probes_module.h"
#include "src/trace_processor/importers/proto/graphics_event_module.h"
+#include "src/trace_processor/importers/proto/heap_graph_module.h"
+#include "src/trace_processor/importers/proto/system_probes_module.h"
namespace perfetto {
namespace trace_processor {
void RegisterAdditionalModules(TraceProcessorContext* context) {
+ context->modules.emplace_back(new AndroidProbesModule(context));
context->modules.emplace_back(new GraphicsEventModule(context));
+ context->modules.emplace_back(new HeapGraphModule(context));
+ context->modules.emplace_back(new SystemProbesModule(context));
}
} // namespace trace_processor
diff --git a/src/trace_processor/sched_slice_table_unittest.cc b/src/trace_processor/sched_slice_table_unittest.cc
index 655033a..f9131ae 100644
--- a/src/trace_processor/sched_slice_table_unittest.cc
+++ b/src/trace_processor/sched_slice_table_unittest.cc
@@ -44,7 +44,7 @@
context_.args_tracker.reset(new ArgsTracker(&context_));
context_.process_tracker.reset(new ProcessTracker(&context_));
context_.event_tracker.reset(new EventTracker(&context_));
- context_.sched_tracker.reset(new SchedEventTracker(&context_));
+ sched_tracker_ = SchedEventTracker::GetOrCreate(&context_);
SchedSliceTable::RegisterTable(db_.get(), context_.storage.get());
}
@@ -61,6 +61,7 @@
TraceProcessorContext context_;
ScopedDb db_;
ScopedStmt stmt_;
+ SchedEventTracker* sched_tracker_;
};
TEST_F(SchedSliceTableTest, RowsReturnedInCorrectOrderWithinCpu) {
@@ -72,18 +73,14 @@
static const char kCommProc2[] = "process2";
uint32_t pid_2 = 4;
int32_t prio = 1024;
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, kCommProc2,
- prio, prev_state, pid_2, kCommProc1,
- prio);
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 3, pid_2, kCommProc1,
- prio, prev_state, pid_1, kCommProc2,
- prio);
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 4, pid_1, kCommProc2,
- prio, prev_state, pid_2, kCommProc1,
- prio);
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 10, pid_2,
- kCommProc1, prio, prev_state, pid_1,
- kCommProc2, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp, pid_1, kCommProc2, prio,
+ prev_state, pid_2, kCommProc1, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp + 3, pid_2, kCommProc1, prio,
+ prev_state, pid_1, kCommProc2, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp + 4, pid_1, kCommProc2, prio,
+ prev_state, pid_2, kCommProc1, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp + 10, pid_2, kCommProc1, prio,
+ prev_state, pid_1, kCommProc2, prio);
PrepareValidStatement(
"SELECT dur, ts, cpu FROM sched where dur != 0 ORDER BY dur");
@@ -117,24 +114,18 @@
static const char kCommProc2[] = "process2";
uint32_t pid_2 = 4;
int32_t prio = 1024;
- context_.sched_tracker->PushSchedSwitch(cpu_3, timestamp - 2, pid_1,
- kCommProc2, prio, prev_state, pid_2,
- kCommProc1, prio);
- context_.sched_tracker->PushSchedSwitch(cpu_3, timestamp - 1, pid_2,
- kCommProc1, prio, prev_state, pid_1,
- kCommProc2, prio);
- context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp, pid_1, kCommProc2,
- prio, prev_state, pid_2, kCommProc1,
- prio);
- context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 3, pid_2,
- kCommProc1, prio, prev_state, pid_1,
- kCommProc2, prio);
- context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp + 4, pid_2,
- kCommProc1, prio, prev_state, pid_1,
- kCommProc2, prio);
- context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 10, pid_1,
- kCommProc2, prio, prev_state, pid_2,
- kCommProc1, prio);
+ sched_tracker_->PushSchedSwitch(cpu_3, timestamp - 2, pid_1, kCommProc2, prio,
+ prev_state, pid_2, kCommProc1, prio);
+ sched_tracker_->PushSchedSwitch(cpu_3, timestamp - 1, pid_2, kCommProc1, prio,
+ prev_state, pid_1, kCommProc2, prio);
+ sched_tracker_->PushSchedSwitch(cpu_1, timestamp, pid_1, kCommProc2, prio,
+ prev_state, pid_2, kCommProc1, prio);
+ sched_tracker_->PushSchedSwitch(cpu_2, timestamp + 3, pid_2, kCommProc1, prio,
+ prev_state, pid_1, kCommProc2, prio);
+ sched_tracker_->PushSchedSwitch(cpu_1, timestamp + 4, pid_2, kCommProc1, prio,
+ prev_state, pid_1, kCommProc2, prio);
+ sched_tracker_->PushSchedSwitch(cpu_2, timestamp + 10, pid_1, kCommProc2,
+ prio, prev_state, pid_2, kCommProc1, prio);
PrepareValidStatement(
"SELECT dur, ts, cpu FROM sched where dur != 0 ORDER BY dur desc");
@@ -167,18 +158,14 @@
static const char kCommProc2[] = "process2";
uint32_t pid_2 = 4;
int32_t prio = 1024;
- context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp, pid_1, kCommProc2,
- prio, prev_state, pid_2, kCommProc1,
- prio);
- context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 3, pid_2,
- kCommProc1, prio, prev_state, pid_1,
- kCommProc2, prio);
- context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp + 4, pid_2,
- kCommProc1, prio, prev_state, pid_1,
- kCommProc2, prio);
- context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 10, pid_1,
- kCommProc2, prio, prev_state, pid_2,
- kCommProc1, prio);
+ sched_tracker_->PushSchedSwitch(cpu_1, timestamp, pid_1, kCommProc2, prio,
+ prev_state, pid_2, kCommProc1, prio);
+ sched_tracker_->PushSchedSwitch(cpu_2, timestamp + 3, pid_2, kCommProc1, prio,
+ prev_state, pid_1, kCommProc2, prio);
+ sched_tracker_->PushSchedSwitch(cpu_1, timestamp + 4, pid_2, kCommProc1, prio,
+ prev_state, pid_1, kCommProc2, prio);
+ sched_tracker_->PushSchedSwitch(cpu_2, timestamp + 10, pid_1, kCommProc2,
+ prio, prev_state, pid_2, kCommProc1, prio);
PrepareValidStatement(
"SELECT dur, ts, cpu FROM sched WHERE dur != 0 and cpu = 3");
@@ -200,18 +187,14 @@
static const char kCommProc2[] = "process2";
uint32_t pid_2 = 4;
int32_t prio = 1024;
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, kCommProc2,
- prio, prev_state, pid_2, kCommProc1,
- prio);
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 3, pid_2, kCommProc1,
- prio, prev_state, pid_1, kCommProc2,
- prio);
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 4, pid_1, kCommProc2,
- prio, prev_state, pid_2, kCommProc1,
- prio);
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 10, pid_2,
- kCommProc1, prio, prev_state, pid_1,
- kCommProc2, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp, pid_1, kCommProc2, prio,
+ prev_state, pid_2, kCommProc1, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp + 3, pid_2, kCommProc1, prio,
+ prev_state, pid_1, kCommProc2, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp + 4, pid_1, kCommProc2, prio,
+ prev_state, pid_2, kCommProc1, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp + 10, pid_2, kCommProc1, prio,
+ prev_state, pid_1, kCommProc2, prio);
PrepareValidStatement("SELECT utid FROM sched where dur != 0 ORDER BY utid");
@@ -238,12 +221,12 @@
// Fill |cpu_5| and |cpu_7) with one sched switch per time unit starting,
// respectively, @ T=50 and T=70.
for (int64_t i = 0; i <= 11; i++) {
- context_.sched_tracker->PushSchedSwitch(cpu_5, 50 + i, pid_1, "pid_1", prio,
- prev_state, pid_1, "pid_1", prio);
+ sched_tracker_->PushSchedSwitch(cpu_5, 50 + i, pid_1, "pid_1", prio,
+ prev_state, pid_1, "pid_1", prio);
}
for (int64_t i = 0; i <= 11; i++) {
- context_.sched_tracker->PushSchedSwitch(cpu_7, 70 + i, pid_2, "pid_2", prio,
- prev_state, pid_2, "pid_2", prio);
+ sched_tracker_->PushSchedSwitch(cpu_7, 70 + i, pid_2, "pid_2", prio,
+ prev_state, pid_2, "pid_2", prio);
}
auto query = [this](const std::string& where_clauses) {
diff --git a/src/trace_processor/slice_tracker_unittest.cc b/src/trace_processor/slice_tracker_unittest.cc
index f4f3c64..386a15c 100644
--- a/src/trace_processor/slice_tracker_unittest.cc
+++ b/src/trace_processor/slice_tracker_unittest.cc
@@ -44,7 +44,7 @@
std::vector<SliceInfo> ToSliceInfo(const tables::SliceTable& slices) {
std::vector<SliceInfo> infos;
- for (uint32_t i = 0; i < slices.size(); i++) {
+ for (uint32_t i = 0; i < slices.row_count(); i++) {
infos.emplace_back(SliceInfo{slices.ts()[i], slices.dur()[i]});
}
return infos;
@@ -60,7 +60,7 @@
tracker.End(10 /*ts*/, track, 0 /*cat*/, 1 /*name*/);
const auto& slices = context.storage->slice_table();
- EXPECT_EQ(slices.size(), 1u);
+ EXPECT_EQ(slices.row_count(), 1u);
EXPECT_EQ(slices.ts()[0], 2);
EXPECT_EQ(slices.dur()[0], 8);
EXPECT_EQ(slices.track_id()[0], track);
@@ -88,7 +88,7 @@
});
const auto& slices = context.storage->slice_table();
- EXPECT_EQ(slices.size(), 1u);
+ EXPECT_EQ(slices.row_count(), 1u);
EXPECT_EQ(slices.ts()[0], 2);
EXPECT_EQ(slices.dur()[0], 8);
EXPECT_EQ(slices.track_id()[0], track);
@@ -121,7 +121,7 @@
const auto& slices = context.storage->slice_table();
- EXPECT_EQ(slices.size(), 2u);
+ EXPECT_EQ(slices.row_count(), 2u);
uint32_t idx = 0;
EXPECT_EQ(slices.ts()[idx], 2);
diff --git a/src/trace_processor/sqlite/db_sqlite_table.cc b/src/trace_processor/sqlite/db_sqlite_table.cc
index a531b92..6e0df8b 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table.cc
@@ -192,7 +192,7 @@
// end of filtering. Note that |current_row_count| should always be at least 1
// unless we are absolutely certain that we will return no rows as otherwise
// SQLite can make some bad choices.
- uint32_t current_row_count = table.size();
+ uint32_t current_row_count = table.row_count();
// If the table is empty, any constraint set only pays the fixed cost. Also we
// can return 0 as the row count as we are certain that we will return no
diff --git a/src/trace_processor/sqlite/db_sqlite_table_unittest.cc b/src/trace_processor/sqlite/db_sqlite_table_unittest.cc
index d88a046..4f39839 100644
--- a/src/trace_processor/sqlite/db_sqlite_table_unittest.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table_unittest.cc
@@ -24,9 +24,9 @@
class TestTable : public Table {
public:
- TestTable(uint32_t size) : Table(&pool_, nullptr) {
- row_maps_.emplace_back(RowMap(0, size));
- size_ = size;
+ TestTable(uint32_t row_count) : Table(&pool_, nullptr) {
+ row_maps_.emplace_back(RowMap(0, row_count));
+ row_count_ = row_count;
columns_.emplace_back(Column::IdColumn(this, 0u, 0u));
columns_.emplace_back(
diff --git a/src/trace_processor/storage_minimal_smoke_test.cc b/src/trace_processor/storage_minimal_smoke_test.cc
new file mode 100644
index 0000000..1aa037d
--- /dev/null
+++ b/src/trace_processor/storage_minimal_smoke_test.cc
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdio>
+#include <string>
+
+#include <json/reader.h>
+#include <json/value.h>
+
+#include "perfetto/ext/trace_processor/export_json.h"
+#include "perfetto/trace_processor/basic_types.h"
+#include "perfetto/trace_processor/trace_processor_storage.h"
+#include "src/base/test/utils.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+class JsonStringOutputWriter : public json::OutputWriter {
+ public:
+ util::Status AppendString(const std::string& string) override {
+ buffer += string;
+ return util::OkStatus();
+ }
+ std::string buffer;
+};
+
+class StorageMinimalSmokeTest : public ::testing::Test {
+ public:
+ StorageMinimalSmokeTest()
+ : storage_(TraceProcessorStorage::CreateInstance(Config())) {}
+
+ protected:
+ std::unique_ptr<TraceProcessorStorage> storage_;
+};
+
+TEST_F(StorageMinimalSmokeTest, GraphicEventsIgnored) {
+ const size_t MAX_SIZE = 1 << 20;
+ auto f = fopen(base::GetTestDataPath("test/data/gpu_trace.pb").c_str(), "rb");
+ std::unique_ptr<uint8_t[]> buf(new uint8_t[MAX_SIZE]);
+ auto rsize = fread(reinterpret_cast<char*>(buf.get()), 1, MAX_SIZE, f);
+ storage_->Parse(std::move(buf), rsize);
+ storage_->NotifyEndOfFile();
+
+ JsonStringOutputWriter output_writer;
+ auto status = json::ExportJson(storage_.get(), &output_writer);
+ Json::Reader reader;
+ Json::Value result;
+ reader.parse(output_writer.buffer, result);
+
+ ASSERT_EQ(result["traceEvents"].size(), 0u);
+}
+
+TEST_F(StorageMinimalSmokeTest, TrackEventsImported) {
+ const size_t MAX_SIZE = 1 << 20;
+ auto f = fopen("test/trace_processor/track_event_typed_args.pb", "rb");
+ std::unique_ptr<uint8_t[]> buf(new uint8_t[MAX_SIZE]);
+ auto rsize = fread(reinterpret_cast<char*>(buf.get()), 1, MAX_SIZE, f);
+ storage_->Parse(std::move(buf), rsize);
+ storage_->NotifyEndOfFile();
+
+ JsonStringOutputWriter output_writer;
+ auto status = json::ExportJson(storage_.get(), &output_writer);
+ Json::Reader reader;
+ Json::Value result;
+ reader.parse(output_writer.buffer, result);
+
+ ASSERT_EQ(result["traceEvents"].size(), 4u);
+}
+
+} // namespace
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/syscall_tracker.h b/src/trace_processor/syscall_tracker.h
index 09cf772..1dba57d 100644
--- a/src/trace_processor/syscall_tracker.h
+++ b/src/trace_processor/syscall_tracker.h
@@ -21,6 +21,7 @@
#include <tuple>
#include "perfetto/ext/base/string_view.h"
+#include "src/trace_processor/destructible.h"
#include "src/trace_processor/slice_tracker.h"
#include "src/trace_processor/trace_processor_context.h"
#include "src/trace_processor/trace_storage.h"
@@ -39,12 +40,17 @@
kX86_64,
};
-class SyscallTracker {
+class SyscallTracker : public Destructible {
public:
- explicit SyscallTracker(TraceProcessorContext*);
SyscallTracker(const SyscallTracker&) = delete;
SyscallTracker& operator=(const SyscallTracker&) = delete;
virtual ~SyscallTracker();
+ static SyscallTracker* GetOrCreate(TraceProcessorContext* context) {
+ if (!context->syscall_tracker) {
+ context->syscall_tracker.reset(new SyscallTracker(context));
+ }
+ return static_cast<SyscallTracker*>(context->syscall_tracker.get());
+ }
void SetArchitecture(Architecture architecture);
@@ -65,6 +71,8 @@
}
private:
+ explicit SyscallTracker(TraceProcessorContext*);
+
TraceProcessorContext* const context_;
inline StringId SyscallNumberToStringId(uint32_t syscall_num) {
diff --git a/src/trace_processor/syscall_tracker_unittest.cc b/src/trace_processor/syscall_tracker_unittest.cc
index a659a64..1d9f513 100644
--- a/src/trace_processor/syscall_tracker_unittest.cc
+++ b/src/trace_processor/syscall_tracker_unittest.cc
@@ -54,7 +54,6 @@
context.track_tracker.reset(track_tracker);
slice_tracker = new MockSliceTracker(&context);
context.slice_tracker.reset(slice_tracker);
- context.syscall_tracker.reset(new SyscallTracker(&context));
}
protected:
@@ -72,19 +71,21 @@
EXPECT_CALL(*slice_tracker, End(110, track, kNullStringId, _, _))
.WillOnce(DoAll(SaveArg<3>(&end_name), Return(base::nullopt)));
- context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 57 /*sys_read*/);
- context.syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 57 /*sys_read*/);
+ SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(&context);
+ syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 57 /*sys_read*/);
+ syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 57 /*sys_read*/);
EXPECT_EQ(context.storage->GetString(begin_name), "sys_57");
EXPECT_EQ(context.storage->GetString(end_name), "sys_57");
}
TEST_F(SyscallTrackerTest, IgnoreWriteSyscalls) {
- context.syscall_tracker->SetArchitecture(kAarch64);
+ SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(&context);
+ syscall_tracker->SetArchitecture(kAarch64);
EXPECT_CALL(*slice_tracker, Begin(_, _, _, _, _)).Times(0);
EXPECT_CALL(*slice_tracker, End(_, _, _, _, _)).Times(0);
- context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 64 /*sys_write*/);
- context.syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 64 /*sys_write*/);
+ syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 64 /*sys_write*/);
+ syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 64 /*sys_write*/);
}
TEST_F(SyscallTrackerTest, Aarch64) {
@@ -96,9 +97,10 @@
EXPECT_CALL(*slice_tracker, End(110, track, kNullStringId, _, _))
.WillOnce(DoAll(SaveArg<3>(&end_name), Return(base::nullopt)));
- context.syscall_tracker->SetArchitecture(kAarch64);
- context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 63 /*sys_read*/);
- context.syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 63 /*sys_read*/);
+ SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(&context);
+ syscall_tracker->SetArchitecture(kAarch64);
+ syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 63 /*sys_read*/);
+ syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 63 /*sys_read*/);
EXPECT_EQ(context.storage->GetString(begin_name), "sys_read");
EXPECT_EQ(context.storage->GetString(end_name), "sys_read");
}
@@ -112,9 +114,10 @@
EXPECT_CALL(*slice_tracker, End(110, track, kNullStringId, _, _))
.WillOnce(DoAll(SaveArg<3>(&end_name), Return(base::nullopt)));
- context.syscall_tracker->SetArchitecture(kX86_64);
- context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 0 /*sys_read*/);
- context.syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 0 /*sys_read*/);
+ SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(&context);
+ syscall_tracker->SetArchitecture(kX86_64);
+ syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 0 /*sys_read*/);
+ syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 0 /*sys_read*/);
EXPECT_EQ(context.storage->GetString(begin_name), "sys_read");
EXPECT_EQ(context.storage->GetString(end_name), "sys_read");
}
@@ -122,9 +125,11 @@
TEST_F(SyscallTrackerTest, SyscallNumberTooLarge) {
EXPECT_CALL(*slice_tracker, Begin(_, _, _, _, _)).Times(0);
EXPECT_CALL(*slice_tracker, End(_, _, _, _, _)).Times(0);
- context.syscall_tracker->SetArchitecture(kAarch64);
- context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 9999);
- context.syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 9999);
+
+ SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(&context);
+ syscall_tracker->SetArchitecture(kAarch64);
+ syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 9999);
+ syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 9999);
}
} // namespace
diff --git a/src/trace_processor/tables/BUILD.gn b/src/trace_processor/tables/BUILD.gn
index 3b9fa44..b87d011 100644
--- a/src/trace_processor/tables/BUILD.gn
+++ b/src/trace_processor/tables/BUILD.gn
@@ -24,7 +24,6 @@
"track_tables.h",
]
deps = [
- "..:common",
"../../../gn:default_deps",
"../db:lib",
]
diff --git a/src/trace_processor/tables/macros_benchmark.cc b/src/trace_processor/tables/macros_benchmark.cc
index 008bcab..2e7bfbb 100644
--- a/src/trace_processor/tables/macros_benchmark.cc
+++ b/src/trace_processor/tables/macros_benchmark.cc
@@ -108,7 +108,7 @@
}
BENCHMARK(BM_TableIteratorChild)->Apply(TableFilterArgs);
-static void BM_TableFilterIdColumn(benchmark::State& state) {
+static void BM_TableFilterRootId(benchmark::State& state) {
StringPool pool;
RootTestTable root(&pool, nullptr);
@@ -120,7 +120,66 @@
benchmark::DoNotOptimize(root.Filter({root.id().eq(30)}));
}
}
-BENCHMARK(BM_TableFilterIdColumn)->Apply(TableFilterArgs);
+BENCHMARK(BM_TableFilterRootId)->Apply(TableFilterArgs);
+
+static void BM_TableFilterRootIdAndOther(benchmark::State& state) {
+ StringPool pool;
+ RootTestTable root(&pool, nullptr);
+
+ uint32_t size = static_cast<uint32_t>(state.range(0));
+
+ for (uint32_t i = 0; i < size; ++i) {
+ RootTestTable::Row root_row;
+ root_row.root_non_null = i * 4;
+ root.Insert(root_row);
+ }
+
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(root.Filter(
+ {root.id().eq(root.row_count() - 1), root.root_non_null().gt(100)}));
+ }
+}
+BENCHMARK(BM_TableFilterRootIdAndOther)->Apply(TableFilterArgs);
+
+static void BM_TableFilterChildId(benchmark::State& state) {
+ StringPool pool;
+ RootTestTable root(&pool, nullptr);
+ ChildTestTable child(&pool, &root);
+
+ uint32_t size = static_cast<uint32_t>(state.range(0));
+ for (uint32_t i = 0; i < size; ++i) {
+ root.Insert({});
+ child.Insert({});
+ }
+
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(child.Filter({child.id().eq(30)}));
+ }
+}
+BENCHMARK(BM_TableFilterChildId)->Apply(TableFilterArgs);
+
+static void BM_TableFilterChildIdAndSortedInRoot(benchmark::State& state) {
+ StringPool pool;
+ RootTestTable root(&pool, nullptr);
+ ChildTestTable child(&pool, &root);
+
+ uint32_t size = static_cast<uint32_t>(state.range(0));
+ for (uint32_t i = 0; i < size; ++i) {
+ RootTestTable::Row root_row;
+ root_row.root_sorted = i * 2;
+ root.Insert(root_row);
+
+ ChildTestTable::Row child_row;
+ child_row.root_sorted = i * 2 + 1;
+ child.Insert(child_row);
+ }
+
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(
+ child.Filter({child.id().eq(30), child.root_sorted().gt(1024)}));
+ }
+}
+BENCHMARK(BM_TableFilterChildIdAndSortedInRoot)->Apply(TableFilterArgs);
static void BM_TableFilterRootNonNullEqMatchMany(benchmark::State& state) {
StringPool pool;
@@ -320,25 +379,6 @@
}
BENCHMARK(BM_TableFilterChildSortedEqInParent)->Apply(TableFilterArgs);
-static void BM_TableFilterIdAndOtherParent(benchmark::State& state) {
- StringPool pool;
- RootTestTable root(&pool, nullptr);
-
- uint32_t size = static_cast<uint32_t>(state.range(0));
-
- for (uint32_t i = 0; i < size; ++i) {
- RootTestTable::Row root_row;
- root_row.root_non_null = i * 4;
- root.Insert(root_row);
- }
-
- for (auto _ : state) {
- benchmark::DoNotOptimize(root.Filter(
- {root.id().eq(root.size() - 1), root.root_non_null().gt(100)}));
- }
-}
-BENCHMARK(BM_TableFilterIdAndOtherParent)->Apply(TableFilterArgs);
-
static void BM_TableSortRootNonNull(benchmark::State& state) {
StringPool pool;
RootTestTable root(&pool, nullptr);
diff --git a/src/trace_processor/tables/macros_internal.h b/src/trace_processor/tables/macros_internal.h
index 1f65ec7..ff172e7 100644
--- a/src/trace_processor/tables/macros_internal.h
+++ b/src/trace_processor/tables/macros_internal.h
@@ -76,7 +76,7 @@
}
// Also add the index of the new row to the identity row map and increment
// the size.
- row_maps_.back().Insert(size_++);
+ row_maps_.back().Insert(row_count_++);
}
// Stores the most specific "derived" type of this row in the table.
@@ -267,7 +267,7 @@
uint32_t Insert(const Row& row) { \
uint32_t id; \
if (parent_ == nullptr) { \
- id = size(); \
+ id = row_count(); \
type_.Append(string_pool_->InternString(row.type())); \
} else { \
id = parent_->Insert(row); \
diff --git a/src/trace_processor/tables/macros_unittest.cc b/src/trace_processor/tables/macros_unittest.cc
index 46e03da..c7c7e82 100644
--- a/src/trace_processor/tables/macros_unittest.cc
+++ b/src/trace_processor/tables/macros_unittest.cc
@@ -144,47 +144,47 @@
Table out = slice_.Filter({slice_.dur().is_null()});
const auto* dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.size(), 2u);
+ ASSERT_EQ(out.row_count(), 2u);
ASSERT_EQ(dur->Get(0).type, SqlValue::kNull);
ASSERT_EQ(dur->Get(1).type, SqlValue::kNull);
out = slice_.Filter({slice_.dur().is_not_null()});
dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.size(), 3u);
+ ASSERT_EQ(out.row_count(), 3u);
ASSERT_EQ(dur->Get(0).long_value, 100);
ASSERT_EQ(dur->Get(1).long_value, 101);
ASSERT_EQ(dur->Get(2).long_value, 200);
out = slice_.Filter({slice_.dur().lt(101)});
dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_EQ(dur->Get(0).long_value, 100);
out = slice_.Filter({slice_.dur().eq(101)});
dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_EQ(dur->Get(0).long_value, 101);
out = slice_.Filter({slice_.dur().gt(101)});
dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_EQ(dur->Get(0).long_value, 200);
out = slice_.Filter({slice_.dur().ne(100)});
dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.size(), 2u);
+ ASSERT_EQ(out.row_count(), 2u);
ASSERT_EQ(dur->Get(0).long_value, 101);
ASSERT_EQ(dur->Get(1).long_value, 200);
out = slice_.Filter({slice_.dur().le(101)});
dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.size(), 2u);
+ ASSERT_EQ(out.row_count(), 2u);
ASSERT_EQ(dur->Get(0).long_value, 100);
ASSERT_EQ(dur->Get(1).long_value, 101);
out = slice_.Filter({slice_.dur().ge(101)});
dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.size(), 2u);
+ ASSERT_EQ(out.row_count(), 2u);
ASSERT_EQ(dur->Get(0).long_value, 101);
ASSERT_EQ(dur->Get(1).long_value, 200);
}
@@ -204,24 +204,24 @@
Table out = slice_.Filter({slice_.dur().eq_value(SqlValue::Double(100.0))});
const Column* dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_EQ(dur->Get(0).long_value, 100);
out = slice_.Filter({slice_.dur().le_value(SqlValue::Double(99.9999))});
dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_EQ(dur->Get(0).long_value, std::numeric_limits<int64_t>::min());
out = slice_.Filter({slice_.dur().ge_value(SqlValue::Double(99.9999))});
dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.size(), 2u);
+ ASSERT_EQ(out.row_count(), 2u);
ASSERT_EQ(dur->Get(0).long_value, 100);
ASSERT_EQ(dur->Get(1).long_value, std::numeric_limits<int64_t>::max());
out = slice_.Filter({slice_.dur().eq_value(
SqlValue::Double(std::numeric_limits<int64_t>::min()))});
dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_EQ(dur->Get(0).long_value, std::numeric_limits<int64_t>::min());
}
@@ -241,10 +241,10 @@
slice_.Insert({});
Table out = slice_.Filter({slice_.dur().ne_value(SqlValue())});
- ASSERT_EQ(out.size(), 0u);
+ ASSERT_EQ(out.row_count(), 0u);
out = slice_.Filter({slice_.dur().eq_value(SqlValue::String("100"))});
- ASSERT_EQ(out.size(), 0u);
+ ASSERT_EQ(out.row_count(), 0u);
}
TEST_F(TableMacrosUnittest, NullableDoubleComparision) {
@@ -264,47 +264,47 @@
Table out = counter_.Filter({counter_.value().is_null()});
const auto* value = out.GetColumnByName("value");
- ASSERT_EQ(out.size(), 2u);
+ ASSERT_EQ(out.row_count(), 2u);
ASSERT_EQ(value->Get(0).type, SqlValue::kNull);
ASSERT_EQ(value->Get(1).type, SqlValue::kNull);
out = counter_.Filter({counter_.value().is_not_null()});
value = out.GetColumnByName("value");
- ASSERT_EQ(out.size(), 3u);
+ ASSERT_EQ(out.row_count(), 3u);
ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
ASSERT_DOUBLE_EQ(value->Get(1).double_value, 101);
ASSERT_DOUBLE_EQ(value->Get(2).double_value, 200);
out = counter_.Filter({counter_.value().lt(101)});
value = out.GetColumnByName("value");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
out = counter_.Filter({counter_.value().eq(101)});
value = out.GetColumnByName("value");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
out = counter_.Filter({counter_.value().gt(101)});
value = out.GetColumnByName("value");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_DOUBLE_EQ(value->Get(0).double_value, 200);
out = counter_.Filter({counter_.value().ne(100)});
value = out.GetColumnByName("value");
- ASSERT_EQ(out.size(), 2u);
+ ASSERT_EQ(out.row_count(), 2u);
ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
ASSERT_DOUBLE_EQ(value->Get(1).double_value, 200);
out = counter_.Filter({counter_.value().le(101)});
value = out.GetColumnByName("value");
- ASSERT_EQ(out.size(), 2u);
+ ASSERT_EQ(out.row_count(), 2u);
ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
ASSERT_DOUBLE_EQ(value->Get(1).double_value, 101);
out = counter_.Filter({counter_.value().ge(101)});
value = out.GetColumnByName("value");
- ASSERT_EQ(out.size(), 2u);
+ ASSERT_EQ(out.row_count(), 2u);
ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
ASSERT_DOUBLE_EQ(value->Get(1).double_value, 200);
}
@@ -324,12 +324,12 @@
Table out = counter_.Filter({counter_.value().eq_value(SqlValue::Long(100))});
const Column* value = out.GetColumnByName("value");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100.0);
out = counter_.Filter({counter_.value().lt_value(SqlValue::Long(100))});
value = out.GetColumnByName("value");
- ASSERT_EQ(out.size(), 2u);
+ ASSERT_EQ(out.row_count(), 2u);
ASSERT_DOUBLE_EQ(value->Get(0).double_value, 99.9999);
ASSERT_DOUBLE_EQ(value->Get(1).double_value,
std::numeric_limits<int64_t>::min());
@@ -337,7 +337,7 @@
out = counter_.Filter({counter_.value().eq_value(
SqlValue::Long(std::numeric_limits<int64_t>::min()))});
value = out.GetColumnByName("value");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_DOUBLE_EQ(value->Get(0).double_value,
std::numeric_limits<int64_t>::min());
}
@@ -356,45 +356,45 @@
Table out = cpu_slice_.Filter({cpu_slice_.end_state().is_null()});
const auto* end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.size(), 2u);
+ ASSERT_EQ(out.row_count(), 2u);
ASSERT_EQ(end_state->Get(0).type, SqlValue::kNull);
ASSERT_EQ(end_state->Get(1).type, SqlValue::kNull);
out = cpu_slice_.Filter({cpu_slice_.end_state().is_not_null()});
end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.size(), 2u);
+ ASSERT_EQ(out.row_count(), 2u);
ASSERT_STREQ(end_state->Get(0).string_value, "R");
ASSERT_STREQ(end_state->Get(1).string_value, "D");
out = cpu_slice_.Filter({cpu_slice_.end_state().lt("R")});
end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_STREQ(end_state->Get(0).string_value, "D");
out = cpu_slice_.Filter({cpu_slice_.end_state().eq("D")});
end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_STREQ(end_state->Get(0).string_value, "D");
out = cpu_slice_.Filter({cpu_slice_.end_state().gt("D")});
end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_STREQ(end_state->Get(0).string_value, "R");
out = cpu_slice_.Filter({cpu_slice_.end_state().ne("D")});
end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_STREQ(end_state->Get(0).string_value, "R");
out = cpu_slice_.Filter({cpu_slice_.end_state().le("R")});
end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.size(), 2u);
+ ASSERT_EQ(out.row_count(), 2u);
ASSERT_STREQ(end_state->Get(0).string_value, "R");
ASSERT_STREQ(end_state->Get(1).string_value, "D");
out = cpu_slice_.Filter({cpu_slice_.end_state().ge("D")});
end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.size(), 2u);
+ ASSERT_EQ(out.row_count(), 2u);
ASSERT_STREQ(end_state->Get(0).string_value, "R");
ASSERT_STREQ(end_state->Get(1).string_value, "D");
}
@@ -414,7 +414,7 @@
const auto* end_state = out.GetColumnByName("end_state");
const auto* cpu = out.GetColumnByName("cpu");
- ASSERT_EQ(out.size(), 1u);
+ ASSERT_EQ(out.row_count(), 1u);
ASSERT_EQ(cpu->Get(0).long_value, 1u);
ASSERT_STREQ(end_state->Get(0).string_value, "D");
}
diff --git a/src/trace_processor/tables/profiler_tables.h b/src/trace_processor/tables/profiler_tables.h
index 13f3330..d00c5e7 100644
--- a/src/trace_processor/tables/profiler_tables.h
+++ b/src/trace_processor/tables/profiler_tables.h
@@ -42,6 +42,17 @@
PERFETTO_TP_TABLE(PERFETTO_TP_SYMBOL_DEF);
+#define PERFETTO_TP_HEAP_PROFILE_ALLOCATION_DEF(NAME, PARENT, C) \
+ NAME(HeapProfileAllocationTable, "heap_profile_allocation") \
+ PERFETTO_TP_ROOT_TABLE(PARENT, C) \
+ C(int64_t, ts, Column::Flag::kSorted) \
+ C(uint32_t, upid) \
+ C(int64_t, callsite_id) \
+ C(int64_t, count) \
+ C(int64_t, size)
+
+PERFETTO_TP_TABLE(PERFETTO_TP_HEAP_PROFILE_ALLOCATION_DEF);
+
#define PERFETTO_TP_HEAP_GRAPH_OBJECT_DEF(NAME, PARENT, C) \
NAME(HeapGraphObjectTable, "heap_graph_object") \
PERFETTO_TP_ROOT_TABLE(PARENT, C) \
diff --git a/src/trace_processor/tables/track_tables.h b/src/trace_processor/tables/track_tables.h
index 9048d66..29c3041 100644
--- a/src/trace_processor/tables/track_tables.h
+++ b/src/trace_processor/tables/track_tables.h
@@ -17,7 +17,6 @@
#ifndef SRC_TRACE_PROCESSOR_TABLES_TRACK_TABLES_H_
#define SRC_TRACE_PROCESSOR_TABLES_TRACK_TABLES_H_
-#include "src/trace_processor/string_pool.h"
#include "src/trace_processor/tables/macros.h"
namespace perfetto {
diff --git a/src/trace_processor/thread_table_unittest.cc b/src/trace_processor/thread_table_unittest.cc
index 6d5427c..03c6647 100644
--- a/src/trace_processor/thread_table_unittest.cc
+++ b/src/trace_processor/thread_table_unittest.cc
@@ -41,7 +41,7 @@
context_.args_tracker.reset(new ArgsTracker(&context_));
context_.process_tracker.reset(new ProcessTracker(&context_));
context_.event_tracker.reset(new EventTracker(&context_));
- context_.sched_tracker.reset(new SchedEventTracker(&context_));
+ sched_tracker_ = SchedEventTracker::GetOrCreate(&context_);
ThreadTable::RegisterTable(db_.get(), context_.storage.get());
ProcessTable::RegisterTable(db_.get(), context_.storage.get());
@@ -63,6 +63,7 @@
TraceProcessorContext context_;
ScopedDb db_;
ScopedStmt stmt_;
+ SchedEventTracker* sched_tracker_;
};
TEST_F(ThreadTableUnittest, Select) {
@@ -73,12 +74,12 @@
static const char kThreadName2[] = "thread2";
int32_t prio = 1024;
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1,
- kThreadName2, prio, prev_state,
- /*tid=*/4, kThreadName1, prio);
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
- kThreadName1, prio, prev_state,
- /*tid=*/1, kThreadName2, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp, /*tid=*/1, kThreadName2, prio,
+ prev_state,
+ /*tid=*/4, kThreadName1, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4, kThreadName1,
+ prio, prev_state,
+ /*tid=*/1, kThreadName2, prio);
context_.process_tracker->SetProcessMetadata(2, base::nullopt, "test");
context_.process_tracker->UpdateThread(4 /*tid*/, 2 /*pid*/);
@@ -101,15 +102,15 @@
static const char kThreadName2[] = "thread2";
int32_t prio = 1024;
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1,
- kThreadName2, prio, prev_state,
- /*tid=*/4, kThreadName1, prio);
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
- kThreadName1, prio, prev_state,
- /*tid=*/1, kThreadName2, prio);
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 2, /*tid=*/1,
- kThreadName2, prio, prev_state,
- /*tid=*/4, kThreadName1, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp, /*tid=*/1, kThreadName2, prio,
+ prev_state,
+ /*tid=*/4, kThreadName1, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4, kThreadName1,
+ prio, prev_state,
+ /*tid=*/1, kThreadName2, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp + 2, /*tid=*/1, kThreadName2,
+ prio, prev_state,
+ /*tid=*/4, kThreadName1, prio);
context_.process_tracker->SetProcessMetadata(2, base::nullopt, "test");
context_.process_tracker->UpdateThread(4 /*tid*/, 2 /*pid*/);
@@ -134,12 +135,12 @@
static const char kThreadName2[] = "thread2";
int32_t prio = 1024;
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1,
- kThreadName2, prio, prev_state,
- /*tid=*/4, kThreadName1, prio);
- context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
- kThreadName1, prio, prev_state,
- /*tid=*/1, kThreadName2, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp, /*tid=*/1, kThreadName2, prio,
+ prev_state,
+ /*tid=*/4, kThreadName1, prio);
+ sched_tracker_->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4, kThreadName1,
+ prio, prev_state,
+ /*tid=*/1, kThreadName2, prio);
// Also create a process for which we haven't seen any thread.
context_.process_tracker->SetProcessMetadata(7, base::nullopt, "pid7");
diff --git a/src/trace_processor/trace_blob_view.h b/src/trace_processor/trace_blob_view.h
index 46cc424..7a7889b 100644
--- a/src/trace_processor/trace_blob_view.h
+++ b/src/trace_processor/trace_blob_view.h
@@ -51,7 +51,7 @@
TraceBlobView(const TraceBlobView&) = delete;
TraceBlobView& operator=(const TraceBlobView&) = delete;
- TraceBlobView slice(size_t offset, size_t length) {
+ TraceBlobView slice(size_t offset, size_t length) const {
PERFETTO_DCHECK(offset + length <= offset_ + length_);
return TraceBlobView(shbuf_, offset, length);
}
diff --git a/src/trace_processor/trace_processor_context.cc b/src/trace_processor/trace_processor_context.cc
index a6b1c03..dbefd62 100644
--- a/src/trace_processor/trace_processor_context.cc
+++ b/src/trace_processor/trace_processor_context.cc
@@ -17,25 +17,17 @@
#include "src/trace_processor/trace_processor_context.h"
#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/binder_tracker.h"
#include "src/trace_processor/chunked_trace_reader.h"
#include "src/trace_processor/clock_tracker.h"
#include "src/trace_processor/event_tracker.h"
#include "src/trace_processor/heap_profile_tracker.h"
#include "src/trace_processor/importers/ftrace/ftrace_module.h"
-#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
#include "src/trace_processor/importers/json/json_trace_parser.h"
-#include "src/trace_processor/importers/proto/android_probes_module.h"
-#include "src/trace_processor/importers/proto/heap_graph_module.h"
-#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
#include "src/trace_processor/importers/proto/proto_trace_parser.h"
-#include "src/trace_processor/importers/proto/system_probes_module.h"
#include "src/trace_processor/importers/proto/track_event_module.h"
-#include "src/trace_processor/importers/systrace/systrace_parser.h"
#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/slice_tracker.h"
#include "src/trace_processor/stack_profile_tracker.h"
-#include "src/trace_processor/syscall_tracker.h"
#include "src/trace_processor/trace_sorter.h"
#include "src/trace_processor/track_tracker.h"
diff --git a/src/trace_processor/trace_processor_context.h b/src/trace_processor/trace_processor_context.h
index 3eab980..6d5b75c 100644
--- a/src/trace_processor/trace_processor_context.h
+++ b/src/trace_processor/trace_processor_context.h
@@ -21,13 +21,13 @@
#include <vector>
#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/destructible.h"
#include "src/trace_processor/importers/proto/proto_importer_module.h"
namespace perfetto {
namespace trace_processor {
class ArgsTracker;
-class BinderTracker;
class ChunkedTraceReader;
class ClockTracker;
class EventTracker;
@@ -35,10 +35,7 @@
class HeapGraphTracker;
class HeapProfileTracker;
class ProcessTracker;
-class SchedEventTracker;
class SliceTracker;
-class SyscallTracker;
-class SystraceParser;
class TraceParser;
class TraceSorter;
class TraceStorage;
@@ -56,17 +53,21 @@
std::unique_ptr<ArgsTracker> args_tracker;
std::unique_ptr<SliceTracker> slice_tracker;
std::unique_ptr<ProcessTracker> process_tracker;
- std::unique_ptr<SyscallTracker> syscall_tracker;
std::unique_ptr<EventTracker> event_tracker;
- std::unique_ptr<SchedEventTracker> sched_tracker;
std::unique_ptr<ClockTracker> clock_tracker;
std::unique_ptr<TraceParser> parser;
std::unique_ptr<TraceSorter> sorter;
std::unique_ptr<ChunkedTraceReader> chunk_reader;
std::unique_ptr<HeapProfileTracker> heap_profile_tracker;
- std::unique_ptr<SystraceParser> systrace_parser;
- std::unique_ptr<HeapGraphTracker> heap_graph_tracker;
- std::unique_ptr<BinderTracker> binder_tracker;
+
+ // These fields are stored as pointers to Destructible objects rather than
+ // their actual type (a subclass of Destructible), as the concrete subclass
+ // type is only available in the storage_full target. To access these fields,
+ // use the GetOrCreate() method on their subclass type,
+ // e.g. SyscallTracker::GetOrCreate(context).
+ std::unique_ptr<Destructible> syscall_tracker; // SyscallTracker
+ std::unique_ptr<Destructible> sched_tracker; // SchedEventTracker
+ std::unique_ptr<Destructible> systrace_parser; // SystraceParser
// The module at the index N is registered to handle field id N in
// TracePacket.
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index e47806d..039b1bd 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -26,7 +26,6 @@
#include "src/trace_processor/android_logs_table.h"
#include "src/trace_processor/args_table.h"
#include "src/trace_processor/cpu_profile_stack_sample_table.h"
-#include "src/trace_processor/heap_profile_allocation_table.h"
#include "src/trace_processor/instants_table.h"
#include "src/trace_processor/metadata_table.h"
#include "src/trace_processor/process_table.h"
@@ -382,7 +381,6 @@
StatsTable::RegisterTable(*db_, context_.storage.get());
AndroidLogsTable::RegisterTable(*db_, context_.storage.get());
RawTable::RegisterTable(*db_, context_.storage.get());
- HeapProfileAllocationTable::RegisterTable(*db_, context_.storage.get());
CpuProfileStackSampleTable::RegisterTable(*db_, context_.storage.get());
StackProfileFrameTable::RegisterTable(*db_, context_.storage.get());
StackProfileMappingTable::RegisterTable(*db_, context_.storage.get());
@@ -435,6 +433,9 @@
DbSqliteTable::RegisterTable(*db_, &storage->symbol_table(),
storage->symbol_table().table_name());
DbSqliteTable::RegisterTable(
+ *db_, &storage->heap_profile_allocation_table(),
+ storage->heap_profile_allocation_table().table_name());
+ DbSqliteTable::RegisterTable(
*db_, &storage->stack_profile_callsite_table(),
storage->stack_profile_callsite_table().table_name());
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index 50877fa..54855c5 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -127,34 +127,34 @@
}
}
-void FreeLine(char* line) {
- linenoiseHistoryAdd(line);
- linenoiseHistorySave(GetHistoryPath().c_str());
- linenoiseFree(line);
-}
+struct LineDeleter {
+ void operator()(char* p) const {
+ linenoiseHistoryAdd(p);
+ linenoiseHistorySave(GetHistoryPath().c_str());
+ linenoiseFree(p);
+ }
+};
-char* GetLine(const char* prompt) {
- return linenoise(prompt);
+using ScopedLine = std::unique_ptr<char, LineDeleter>;
+
+ScopedLine GetLine(const char* prompt) {
+ return ScopedLine(linenoise(prompt));
}
#else
void SetupLineEditor() {}
-void FreeLine(char* line) {
- delete[] line;
-}
+using ScopedLine = std::unique_ptr<char>;
-char* GetLine(const char* prompt) {
+ScopedLine GetLine(const char* prompt) {
printf("\r%80s\r%s", "", prompt);
fflush(stdout);
- char* line = new char[1024];
- if (!fgets(line, 1024 - 1, stdin)) {
- FreeLine(line);
+ ScopedLine line(new char[1024]);
+ if (!fgets(line.get(), 1024 - 1, stdin))
return nullptr;
- }
- if (strlen(line) > 0)
- line[strlen(line) - 1] = 0;
+ if (strlen(line.get()) > 0)
+ line.get()[strlen(line.get()) - 1] = 0;
return line;
}
@@ -452,15 +452,15 @@
SetupLineEditor();
for (;;) {
- char* line = GetLine("> ");
+ ScopedLine line = GetLine("> ");
if (!line)
break;
- if (strcmp(line, "") == 0)
+ if (strcmp(line.get(), "") == 0)
continue;
- if (line[0] == '.') {
+ if (line.get()[0] == '.') {
char command[32] = {};
char arg[1024] = {};
- sscanf(line + 1, "%31s %1023s", command, arg);
+ sscanf(line.get() + 1, "%31s %1023s", command, arg);
if (strcmp(command, "quit") == 0 || strcmp(command, "q") == 0) {
break;
} else if (strcmp(command, "help") == 0) {
@@ -477,10 +477,8 @@
}
base::TimeNanos t_start = base::GetWallTimeNs();
- auto it = g_tp->ExecuteQuery(line);
+ auto it = g_tp->ExecuteQuery(line.get());
PrintQueryResultInteractively(&it, t_start, column_width);
-
- FreeLine(line);
}
return 0;
}
diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc
index 2ceb370..46aefbf 100644
--- a/src/trace_processor/trace_processor_storage_impl.cc
+++ b/src/trace_processor/trace_processor_storage_impl.cc
@@ -18,26 +18,18 @@
#include "perfetto/base/logging.h"
#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/binder_tracker.h"
#include "src/trace_processor/clock_tracker.h"
#include "src/trace_processor/event_tracker.h"
#include "src/trace_processor/forwarding_trace_parser.h"
#include "src/trace_processor/heap_profile_tracker.h"
#include "src/trace_processor/importers/ftrace/ftrace_module.h"
-#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
-#include "src/trace_processor/importers/proto/android_probes_module.h"
-#include "src/trace_processor/importers/proto/heap_graph_module.h"
-#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
#include "src/trace_processor/importers/proto/proto_importer_module.h"
#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
-#include "src/trace_processor/importers/proto/system_probes_module.h"
#include "src/trace_processor/importers/proto/track_event_module.h"
-#include "src/trace_processor/importers/systrace/systrace_parser.h"
#include "src/trace_processor/importers/systrace/systrace_trace_parser.h"
#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/slice_tracker.h"
#include "src/trace_processor/stack_profile_tracker.h"
-#include "src/trace_processor/syscall_tracker.h"
#include "src/trace_processor/trace_blob_view.h"
#include "src/trace_processor/trace_sorter.h"
#include "src/trace_processor/track_tracker.h"
@@ -53,16 +45,8 @@
context_.slice_tracker.reset(new SliceTracker(&context_));
context_.event_tracker.reset(new EventTracker(&context_));
context_.process_tracker.reset(new ProcessTracker(&context_));
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_SYSCALLS)
- context_.syscall_tracker.reset(new SyscallTracker(&context_));
-#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_SYSCALLS)
context_.clock_tracker.reset(new ClockTracker(&context_));
context_.heap_profile_tracker.reset(new HeapProfileTracker(&context_));
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
- context_.sched_tracker.reset(new SchedEventTracker(&context_));
- context_.systrace_parser.reset(new SystraceParser(&context_));
- context_.binder_tracker.reset(new BinderTracker(&context_));
-#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
context_.modules.emplace_back(new FtraceModuleImpl(&context_));
@@ -74,15 +58,6 @@
context_.ftrace_module =
static_cast<FtraceModule*>(context_.modules.back().get());
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_HEAP_GRAPHS)
- context_.modules.emplace_back(new HeapGraphModule(&context_));
-#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_HEAP_GRAPHS)
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_ANDROID_PROBES)
- context_.modules.emplace_back(new AndroidProbesModule(&context_));
-#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_ANDROID_PROBES)
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
- context_.modules.emplace_back(new SystemProbesModule(&context_));
-#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
context_.modules.emplace_back(new TrackEventModule(&context_));
}
@@ -112,7 +87,7 @@
if (context_.sorter)
context_.sorter->ExtractEventsForced();
#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
- context_.sched_tracker->FlushPendingEvents();
+ SchedEventTracker::GetOrCreate(&context_)->FlushPendingEvents();
#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
context_.event_tracker->FlushPendingEvents();
context_.slice_tracker->FlushPendingSlices();
diff --git a/src/trace_processor/trace_storage.cc b/src/trace_processor/trace_storage.cc
index 2f4e872..c3c4077 100644
--- a/src/trace_processor/trace_storage.cc
+++ b/src/trace_processor/trace_storage.cc
@@ -132,12 +132,11 @@
android_log_.timestamps().end(), &start_ns, &end_ns);
MaybeUpdateMinMax(raw_events_.timestamps().begin(),
raw_events_.timestamps().end(), &start_ns, &end_ns);
- MaybeUpdateMinMax(heap_profile_allocations_.timestamps().begin(),
- heap_profile_allocations_.timestamps().end(), &start_ns,
- &end_ns);
DbTableMaybeUpdateMinMax(counter_table_.ts(), &start_ns, &end_ns);
DbTableMaybeUpdateMinMax(slice_table_.ts(), &start_ns, &end_ns);
+ DbTableMaybeUpdateMinMax(heap_profile_allocation_table_.ts(), &start_ns,
+ &end_ns);
if (start_ns == std::numeric_limits<int64_t>::max()) {
return std::make_pair(0, 0);
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 56c92a0..b27d5f1 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -32,10 +32,10 @@
#include "perfetto/ext/base/string_view.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/containers/string_pool.h"
#include "src/trace_processor/ftrace_utils.h"
#include "src/trace_processor/metadata.h"
#include "src/trace_processor/stats.h"
-#include "src/trace_processor/string_pool.h"
#include "src/trace_processor/tables/counter_tables.h"
#include "src/trace_processor/tables/profiler_tables.h"
#include "src/trace_processor/tables/slice_tables.h"
@@ -773,40 +773,6 @@
index_;
};
- class HeapProfileAllocations {
- public:
- struct Row {
- int64_t timestamp;
- UniquePid upid;
- int64_t callsite_id;
- int64_t count;
- int64_t size;
- };
-
- uint32_t size() const { return static_cast<uint32_t>(timestamps_.size()); }
-
- void Insert(const Row& row) {
- timestamps_.emplace_back(row.timestamp);
- upids_.emplace_back(row.upid);
- callsite_ids_.emplace_back(row.callsite_id);
- counts_.emplace_back(row.count);
- sizes_.emplace_back(row.size);
- }
-
- const std::deque<int64_t>& timestamps() const { return timestamps_; }
- const std::deque<UniquePid>& upids() const { return upids_; }
- const std::deque<int64_t>& callsite_ids() const { return callsite_ids_; }
- const std::deque<int64_t>& counts() const { return counts_; }
- const std::deque<int64_t>& sizes() const { return sizes_; }
-
- private:
- std::deque<int64_t> timestamps_;
- std::deque<UniquePid> upids_;
- std::deque<int64_t> callsite_ids_;
- std::deque<int64_t> counts_;
- std::deque<int64_t> sizes_;
- };
-
class CpuProfileStackSamples {
public:
struct Row {
@@ -1106,11 +1072,12 @@
return &stack_profile_callsite_table_;
}
- const HeapProfileAllocations& heap_profile_allocations() const {
- return heap_profile_allocations_;
+ const tables::HeapProfileAllocationTable& heap_profile_allocation_table()
+ const {
+ return heap_profile_allocation_table_;
}
- HeapProfileAllocations* mutable_heap_profile_allocations() {
- return &heap_profile_allocations_;
+ tables::HeapProfileAllocationTable* mutable_heap_profile_allocation_table() {
+ return &heap_profile_allocation_table_;
}
const CpuProfileStackSamples& cpu_profile_stack_samples() const {
return cpu_profile_stack_samples_;
@@ -1267,7 +1234,8 @@
StackProfileFrames stack_profile_frames_;
tables::StackProfileCallsiteTable stack_profile_callsite_table_{&string_pool_,
nullptr};
- HeapProfileAllocations heap_profile_allocations_;
+ tables::HeapProfileAllocationTable heap_profile_allocation_table_{
+ &string_pool_, nullptr};
CpuProfileStackSamples cpu_profile_stack_samples_;
// Symbol tables (mappings from frames to symbol names)
diff --git a/src/trace_processor/variadic.h b/src/trace_processor/variadic.h
index 6df011e..0444721 100644
--- a/src/trace_processor/variadic.h
+++ b/src/trace_processor/variadic.h
@@ -17,7 +17,7 @@
#ifndef SRC_TRACE_PROCESSOR_VARIADIC_H_
#define SRC_TRACE_PROCESSOR_VARIADIC_H_
-#include "src/trace_processor/string_pool.h"
+#include "src/trace_processor/containers/string_pool.h"
namespace perfetto {
namespace trace_processor {
diff --git a/test/ci/linux_tests.sh b/test/ci/linux_tests.sh
index 11f60a0..62bf1c7 100755
--- a/test/ci/linux_tests.sh
+++ b/test/ci/linux_tests.sh
@@ -23,6 +23,7 @@
${OUT_PATH}/perfetto_unittests
${OUT_PATH}/perfetto_integrationtests
+${OUT_PATH}/trace_processor_minimal_smoke_tests
# If this is a split host+target build, use the trace_processoer_shell binary
# from the host directory. In some cases (e.g. lsan x86 builds) the host binary
diff --git a/test/trace_processor/clock_sync.out b/test/trace_processor/clock_sync.out
index 77ee53f..aca328a 100644
--- a/test/trace_processor/clock_sync.out
+++ b/test/trace_processor/clock_sync.out
@@ -4,4 +4,7 @@
1003,7
1005,9
2006,11
-3007,13
+2010,12
+2013,13
+3007,14
+3010,15
diff --git a/test/trace_processor/clock_sync.py b/test/trace_processor/clock_sync.py
index 9dded25..e097024 100644
--- a/test/trace_processor/clock_sync.py
+++ b/test/trace_processor/clock_sync.py
@@ -68,10 +68,25 @@
# This counter should be translated @ BOOTTIME : 3000 + 7
trace.add_gpu_counter(
- ts=7, clock_id=SEQ_CLOCK1, counter_id=42, value=13, seq_id=3)
+ ts=7, clock_id=SEQ_CLOCK1, counter_id=42, value=14, seq_id=3)
# This counter should be translated @ BOOTTIME : 2000 + 6
trace.add_gpu_counter(
ts=6, clock_id=SEQ_CLOCK1, seq_id=2, counter_id=42, value=11)
+# Set default clock for sequence 2.
+defaults_packet = trace.add_packet()
+defaults_packet.trusted_packet_sequence_id = 2
+defaults_packet.trace_packet_defaults.timestamp_clock_id = SEQ_CLOCK1
+
+# This counter should be translated @ BOOTTIME : 2000 + 10
+trace.add_gpu_counter(ts=10, seq_id=2, counter_id=42, value=12)
+
+# Manually specified clock_id overrides the default clock.
+trace.add_gpu_counter(
+ ts=2013, clock_id=CLOCK_BOOTTIME, seq_id=2, counter_id=42, value=13)
+
+# Other sequence's default clock isn't changed, so this should be in BOOTTIME.
+trace.add_gpu_counter(ts=3010, counter_id=42, value=15, seq_id=3)
+
print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/heap_graph_interleaved_object.out b/test/trace_processor/heap_graph_interleaved_object.out
index c64ab68..82dc981 100644
--- a/test/trace_processor/heap_graph_interleaved_object.out
+++ b/test/trace_processor/heap_graph_interleaved_object.out
@@ -1,6 +1,6 @@
"id","type","upid","graph_sample_ts","object_id","self_size","retained_size","unique_retained_size","reference_set_id","reachable","type_name","deobfuscated_type_name","root_type"
-0,"heap_graph_object",3,10,1,64,64,64,0,1,"FactoryProducerDelegateImplActor","[NULL]","ROOT_JAVA_FRAME"
-1,"heap_graph_object",2,10,1,64,96,96,0,1,"FactoryProducerDelegateImplActor","[NULL]","ROOT_JAVA_FRAME"
-2,"heap_graph_object",2,10,2,32,32,32,1,1,"Foo","[NULL]","[NULL]"
+0,"heap_graph_object",3,10,1,64,-1,-1,0,1,"FactoryProducerDelegateImplActor","[NULL]","ROOT_JAVA_FRAME"
+1,"heap_graph_object",2,10,1,64,-1,-1,0,1,"FactoryProducerDelegateImplActor","[NULL]","ROOT_JAVA_FRAME"
+2,"heap_graph_object",2,10,2,32,-1,-1,1,1,"Foo","[NULL]","[NULL]"
3,"heap_graph_object",2,10,3,128,-1,-1,1,0,"Foo","[NULL]","[NULL]"
4,"heap_graph_object",2,10,4,256,-1,-1,1,0,"a","DeobfuscatedA","[NULL]"
diff --git a/test/trace_processor/heap_graph_object.out b/test/trace_processor/heap_graph_object.out
index 70e31f1..a25b67b 100644
--- a/test/trace_processor/heap_graph_object.out
+++ b/test/trace_processor/heap_graph_object.out
@@ -1,5 +1,5 @@
"id","type","upid","graph_sample_ts","object_id","self_size","retained_size","unique_retained_size","reference_set_id","reachable","type_name","deobfuscated_type_name","root_type"
-0,"heap_graph_object",2,10,1,64,96,96,0,1,"FactoryProducerDelegateImplActor","[NULL]","ROOT_JAVA_FRAME"
-1,"heap_graph_object",2,10,2,32,32,32,1,1,"Foo","[NULL]","[NULL]"
+0,"heap_graph_object",2,10,1,64,-1,-1,0,1,"FactoryProducerDelegateImplActor","[NULL]","ROOT_JAVA_FRAME"
+1,"heap_graph_object",2,10,2,32,-1,-1,1,1,"Foo","[NULL]","[NULL]"
2,"heap_graph_object",2,10,3,128,-1,-1,1,0,"Foo","[NULL]","[NULL]"
3,"heap_graph_object",2,10,4,256,-1,-1,1,0,"a","DeobfuscatedA","[NULL]"
diff --git a/test/trace_processor/index b/test/trace_processor/index
index 6793acd..1d6dee0 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -151,6 +151,7 @@
track_event_same_tids.textproto track_event_slices.sql track_event_same_tids_slices.out
track_event_typed_args.textproto track_event_slices.sql track_event_typed_args_slices.out
track_event_typed_args.textproto track_event_args.sql track_event_typed_args_args.out
+track_event_tracks.textproto track_event_slices.sql track_event_tracks_slices.out
# Parsing of an html file with systrace data inside
../data/systrace.html systrace_html.sql systrace_html.out
diff --git a/test/trace_processor/track_event_same_tids_slices.out b/test/trace_processor/track_event_same_tids_slices.out
index 350acf9..48fa77b 100644
--- a/test/trace_processor/track_event_same_tids_slices.out
+++ b/test/trace_processor/track_event_same_tids_slices.out
@@ -1,3 +1,3 @@
-"ts","dur","category","name","arg_set_id"
-1000,0,"cat","name1",0
-2000,0,"cat","name2",0
+"thread","ts","dur","category","name","arg_set_id"
+"t1",1000,0,"cat","name1",0
+"t2",2000,0,"cat","name2",0
diff --git a/test/trace_processor/track_event_slices.sql b/test/trace_processor/track_event_slices.sql
index 68772b4..42f7b69 100644
--- a/test/trace_processor/track_event_slices.sql
+++ b/test/trace_processor/track_event_slices.sql
@@ -13,4 +13,14 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-select ts, dur, category, name, arg_set_id from slice order by ts asc;
\ No newline at end of file
+select
+ thread.name as thread,
+ slice.ts,
+ slice.dur,
+ slice.category,
+ slice.name,
+ slice.arg_set_id
+from slice
+left join thread_track on slice.track_id = thread_track.id
+left join thread on thread_track.utid = thread.utid
+order by ts asc;
diff --git a/test/trace_processor/track_event_tracks.textproto b/test/trace_processor/track_event_tracks.textproto
new file mode 100644
index 0000000..fd8cdc8
--- /dev/null
+++ b/test/trace_processor/track_event_tracks.textproto
@@ -0,0 +1,69 @@
+# Sequence 1 defaults to track for "t1".
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ incremental_state_cleared: true
+ track_descriptor {
+ uuid: 1
+ thread {
+ pid: 5
+ tid: 1
+ thread_name: "t1"
+ }
+ }
+ trace_packet_defaults {
+ track_event_defaults {
+ track_uuid: 1
+ }
+ }
+}
+# Sequence 2 defaults to track for "t2".
+packet {
+ trusted_packet_sequence_id: 2
+ timestamp: 0
+ incremental_state_cleared: true
+ track_descriptor {
+ uuid: 2
+ thread {
+ pid: 5
+ tid: 2
+ thread_name: "t2"
+ }
+ }
+ trace_packet_defaults {
+ track_event_defaults {
+ track_uuid: 2
+ }
+ }
+}
+# Should appear on default track "t1".
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 1000
+ track_event {
+ categories: "cat"
+ name: "name1"
+ type: 3
+ }
+}
+# Should appear on default track "t2".
+packet {
+ trusted_packet_sequence_id: 2
+ timestamp: 2000
+ track_event {
+ categories: "cat"
+ name: "name2"
+ type: 3
+ }
+}
+# Should appear on overridden track "t2".
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 3000
+ track_event {
+ track_uuid: 2
+ categories: "cat"
+ name: "name3"
+ type: 3
+ }
+}
diff --git a/test/trace_processor/track_event_tracks_slices.out b/test/trace_processor/track_event_tracks_slices.out
new file mode 100644
index 0000000..93c7186
--- /dev/null
+++ b/test/trace_processor/track_event_tracks_slices.out
@@ -0,0 +1,4 @@
+"thread","ts","dur","category","name","arg_set_id"
+"t1",1000,0,"cat","name1",0
+"t2",2000,0,"cat","name2",0
+"t2",3000,0,"cat","name3",0
diff --git a/test/trace_processor/track_event_typed_args.pb b/test/trace_processor/track_event_typed_args.pb
new file mode 100644
index 0000000..c478cb0
--- /dev/null
+++ b/test/trace_processor/track_event_typed_args.pb
Binary files differ
diff --git a/test/trace_processor/track_event_typed_args_slices.out b/test/trace_processor/track_event_typed_args_slices.out
index d280266..6a9a969 100644
--- a/test/trace_processor/track_event_typed_args_slices.out
+++ b/test/trace_processor/track_event_typed_args_slices.out
@@ -1,4 +1,4 @@
-"ts","dur","category","name","arg_set_id"
-1000,0,"cat","name1",2
-2000,0,"cat","name2",3
-3000,0,"cat","name3",4
+"thread","ts","dur","category","name","arg_set_id"
+"t1",1000,0,"cat","name1",2
+"t1",2000,0,"cat","name2",3
+"t1",3000,0,"cat","name3",4
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index c00e697..ebc440a 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -158,11 +158,17 @@
('static_libs', {'libasync_safe'}),
('header_libs', {'bionic_libc_platform_headers'}),
],
- 'perfetto_unittests': [('data', set(enumerate_data_deps())),],
+ 'perfetto_unittests': [
+ ('data', set(enumerate_data_deps())),
+ ('include_dirs', {'bionic/libc/kernel'}),
+ ],
'traced_probes': [
('required', {'libperfetto_android_internal', 'trigger_perfetto'}),
],
'libperfetto_android_internal': [('static_libs', {'libhealthhalutils'}),],
+ 'traced_perf': [
+ ('include_dirs', {'bionic/libc/kernel'}),
+ ],
'trace_processor_shell': [
('dist', {'targets': ['sdk_repo']}),
('stl', 'libc++_static'),
diff --git a/tools/heap_profile b/tools/heap_profile
index 967299e..735fc58 100755
--- a/tools/heap_profile
+++ b/tools/heap_profile
@@ -167,12 +167,12 @@
parser.add_argument(
"--no-running",
action="store_true",
- help="Do not target already running processes.")
+ help="Do not target already running processes. Requires Android 11.")
parser.add_argument(
"--no-startup",
action="store_true",
help="Do not target processes that start during "
- "the profile.")
+ "the profile. Requires Android 11.")
parser.add_argument(
"--shmem-size",
help="Size of buffer between client and "
diff --git a/tools/trace_to_text/BUILD.gn b/tools/trace_to_text/BUILD.gn
index 4b2044c..41c844d 100644
--- a/tools/trace_to_text/BUILD.gn
+++ b/tools/trace_to_text/BUILD.gn
@@ -38,7 +38,6 @@
source_set("utils") {
deps = [
- ":symbolizer",
"../../gn:default_deps",
"../../include/perfetto/profiling:deobfuscator",
"../../include/perfetto/protozero",
@@ -47,12 +46,13 @@
"../../protos/perfetto/trace/interned_data:zero",
"../../protos/perfetto/trace/profiling:zero",
"../../src/profiling:deobfuscator",
+ "../../src/profiling/symbolizer",
+ "../../src/profiling/symbolizer:symbolize_database",
]
public_deps = [
"../../gn:zlib",
"../../include/perfetto/ext/base",
"../../include/perfetto/profiling:deobfuscator",
- "../../include/perfetto/profiling:symbolizer",
]
sources = [
"utils.cc",
@@ -60,45 +60,21 @@
]
}
-source_set("local_symbolizer") {
- public_deps = [
- "../../include/perfetto/ext/base",
- "../../include/perfetto/profiling:symbolizer",
- ]
- deps = [
- ":symbolizer",
- ":utils",
- "../../gn:default_deps",
- "../../include/perfetto/protozero",
- ]
- sources = [
- "local_symbolizer.cc",
- "local_symbolizer.h",
- ]
-}
-
-source_set("symbolizer") {
- deps = [
- "../../gn:default_deps",
- "../../include/perfetto/profiling:symbolizer",
- ]
- sources = [
- "symbolizer.cc",
- ]
-}
-
source_set("pprofbuilder") {
+ public_deps = [
+ "../../include/perfetto/profiling:pprof_builder",
+ ]
deps = [
- ":symbolizer",
":utils",
"../../gn:default_deps",
"../../include/perfetto/base",
- "../../include/perfetto/profiling:symbolizer",
"../../include/perfetto/protozero",
"../../include/perfetto/trace_processor",
"../../protos/perfetto/trace:zero",
"../../protos/perfetto/trace/profiling:zero",
"../../protos/third_party/pprof:zero",
+ "../../src/profiling/symbolizer",
+ "../../src/profiling/symbolizer:symbolize_database",
]
sources = [
"pprof_builder.cc",
@@ -117,7 +93,6 @@
# executable) and by the "lite" version (the WASM module for the UI).
source_set("common") {
deps = [
- ":local_symbolizer",
":pprofbuilder",
":utils",
"../../gn:default_deps",
@@ -126,6 +101,8 @@
"../../include/perfetto/profiling:deobfuscator",
"../../include/perfetto/protozero",
"../../protos/perfetto/trace:zero",
+ "../../src/profiling/symbolizer",
+ "../../src/profiling/symbolizer:symbolize_database",
"../../src/trace_processor:lib",
]
sources = [
diff --git a/tools/trace_to_text/pprof_builder.cc b/tools/trace_to_text/pprof_builder.cc
index 77dc8615..1b1014d 100644
--- a/tools/trace_to_text/pprof_builder.cc
+++ b/tools/trace_to_text/pprof_builder.cc
@@ -31,11 +31,13 @@
#include "perfetto/base/time.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/utils.h"
-#include "perfetto/profiling/symbolizer.h"
#include "perfetto/protozero/packed_repeated_fields.h"
#include "perfetto/protozero/scattered_heap_buffer.h"
#include "perfetto/trace_processor/trace_processor.h"
+#include "src/profiling/symbolizer/symbolize_database.h"
+#include "src/profiling/symbolizer/symbolizer.h"
+
#include "protos/perfetto/trace/trace.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
#include "protos/third_party/pprof/profile.pbzero.h"
@@ -497,7 +499,7 @@
bool TraceToPprof(std::istream* input,
std::vector<SerializedProfile>* output,
- Symbolizer* symbolizer,
+ profiling::Symbolizer* symbolizer,
uint64_t pid,
const std::vector<uint64_t>& timestamps) {
trace_processor::Config config;
@@ -513,26 +515,27 @@
bool TraceToPprof(trace_processor::TraceProcessor* tp,
std::vector<SerializedProfile>* output,
- Symbolizer* symbolizer,
+ profiling::Symbolizer* symbolizer,
uint64_t pid,
const std::vector<uint64_t>& timestamps) {
if (symbolizer) {
- SymbolizeDatabase(tp, symbolizer, [&tp](const std::string& packet_proto) {
- std::unique_ptr<uint8_t[]> buf(new uint8_t[11 + packet_proto.size()]);
- uint8_t* wptr = &buf[0];
- *(wptr++) =
- MakeTagLengthDelimited(protos::pbzero::Trace::kPacketFieldNumber);
- wptr = WriteVarInt(packet_proto.size(), wptr);
- memcpy(wptr, packet_proto.data(), packet_proto.size());
- wptr += packet_proto.size();
- size_t buf_size = static_cast<size_t>(wptr - &buf[0]);
- auto status = tp->Parse(std::move(buf), buf_size);
- if (!status.ok()) {
- PERFETTO_DFATAL_OR_ELOG("Failed to parse: %s",
- status.message().c_str());
- return;
- }
- });
+ profiling::SymbolizeDatabase(
+ tp, symbolizer, [&tp](const std::string& packet_proto) {
+ std::unique_ptr<uint8_t[]> buf(new uint8_t[11 + packet_proto.size()]);
+ uint8_t* wptr = &buf[0];
+ *(wptr++) =
+ MakeTagLengthDelimited(protos::pbzero::Trace::kPacketFieldNumber);
+ wptr = WriteVarInt(packet_proto.size(), wptr);
+ memcpy(wptr, packet_proto.data(), packet_proto.size());
+ wptr += packet_proto.size();
+ size_t buf_size = static_cast<size_t>(wptr - &buf[0]);
+ auto status = tp->Parse(std::move(buf), buf_size);
+ if (!status.ok()) {
+ PERFETTO_DFATAL_OR_ELOG("Failed to parse: %s",
+ status.message().c_str());
+ return;
+ }
+ });
}
tp->NotifyEndOfFile();
diff --git a/tools/trace_to_text/symbolize_profile.cc b/tools/trace_to_text/symbolize_profile.cc
index b354572..7cf1e10 100644
--- a/tools/trace_to_text/symbolize_profile.cc
+++ b/tools/trace_to_text/symbolize_profile.cc
@@ -19,11 +19,13 @@
#include <vector>
#include "perfetto/base/logging.h"
-#include "perfetto/profiling/symbolizer.h"
#include "perfetto/trace_processor/trace_processor.h"
+#include "src/profiling/symbolizer/symbolize_database.h"
+#include "src/profiling/symbolizer/symbolizer.h"
+
#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
-#include "tools/trace_to_text/local_symbolizer.h"
+#include "src/profiling/symbolizer/local_symbolizer.h"
#endif
#include "protos/perfetto/trace/trace.pbzero.h"
@@ -36,11 +38,11 @@
// Ingest profile, and emit a symbolization table for each sequence. This can
// be prepended to the profile to attach the symbol information.
int SymbolizeProfile(std::istream* input, std::ostream* output) {
- std::unique_ptr<Symbolizer> symbolizer;
+ std::unique_ptr<profiling::Symbolizer> symbolizer;
auto binary_path = GetPerfettoBinaryPath();
if (!binary_path.empty()) {
#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
- symbolizer.reset(new LocalSymbolizer(GetPerfettoBinaryPath()));
+ symbolizer.reset(new profiling::LocalSymbolizer(GetPerfettoBinaryPath()));
#else
PERFETTO_FATAL("This build does not support local symbolization.");
#endif
diff --git a/tools/trace_to_text/trace_to_profile.cc b/tools/trace_to_text/trace_to_profile.cc
index 4f5f1ec..ae9a2a5 100644
--- a/tools/trace_to_text/trace_to_profile.cc
+++ b/tools/trace_to_text/trace_to_profile.cc
@@ -22,7 +22,7 @@
#include "perfetto/base/build_config.h"
#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
-#include "tools/trace_to_text/local_symbolizer.h"
+#include "src/profiling/symbolizer/local_symbolizer.h"
#endif
#include "tools/trace_to_text/utils.h"
@@ -31,7 +31,7 @@
#include "perfetto/ext/base/temp_file.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/profiling/pprof_builder.h"
-#include "perfetto/profiling/symbolizer.h"
+#include "src/profiling/symbolizer/symbolizer.h"
namespace {
@@ -53,11 +53,11 @@
std::ostream* output,
uint64_t pid,
std::vector<uint64_t> timestamps) {
- std::unique_ptr<Symbolizer> symbolizer;
+ std::unique_ptr<profiling::Symbolizer> symbolizer;
auto binary_path = GetPerfettoBinaryPath();
if (!binary_path.empty()) {
#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
- symbolizer.reset(new LocalSymbolizer(GetPerfettoBinaryPath()));
+ symbolizer.reset(new profiling::LocalSymbolizer(GetPerfettoBinaryPath()));
#else
PERFETTO_ELOG(
"This build does not support local symbolization. "
diff --git a/tools/trace_to_text/utils.cc b/tools/trace_to_text/utils.cc
index 7b9b358..efc05f5 100644
--- a/tools/trace_to_text/utils.cc
+++ b/tools/trace_to_text/utils.cc
@@ -40,61 +40,9 @@
using Iterator = trace_processor::TraceProcessor::Iterator;
-constexpr const char* kQueryUnsymbolized =
- "select spm.name, spm.build_id, spf.rel_pc "
- "from stack_profile_frame spf "
- "join stack_profile_mapping spm "
- "on spf.mapping = spm.id "
- "where spm.build_id != '' and spf.symbol_set_id == 0";
constexpr size_t kCompressionBufferSize = 500 * 1024;
-std::string FromHex(const char* str, size_t size) {
- if (size % 2) {
- PERFETTO_DFATAL_OR_ELOG("Failed to parse hex %s", str);
- return "";
- }
- std::string result(size / 2, '\0');
- for (size_t i = 0; i < size; i += 2) {
- char hex_byte[3];
- hex_byte[0] = str[i];
- hex_byte[1] = str[i + 1];
- hex_byte[2] = '\0';
- char* end;
- long int byte = strtol(hex_byte, &end, 16);
- if (*end != '\0') {
- PERFETTO_DFATAL_OR_ELOG("Failed to parse hex %s", str);
- return "";
- }
- result[i / 2] = static_cast<char>(byte);
- }
- return result;
-}
-
-std::string FromHex(const std::string& str) {
- return FromHex(str.c_str(), str.size());
-}
-
-using NameAndBuildIdPair = std::pair<std::string, std::string>;
-
-std::map<NameAndBuildIdPair, std::vector<uint64_t>> GetUnsymbolizedFrames(
- trace_processor::TraceProcessor* tp) {
- std::map<std::pair<std::string, std::string>, std::vector<uint64_t>> res;
- Iterator it = tp->ExecuteQuery(kQueryUnsymbolized);
- while (it.Next()) {
- auto name_and_buildid =
- std::make_pair(it.Get(0).string_value, FromHex(it.Get(1).string_value));
- int64_t rel_pc = it.Get(2).long_value;
- res[name_and_buildid].emplace_back(rel_pc);
- }
- if (!it.Status().ok()) {
- PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
- it.Status().message().c_str());
- return {};
- }
- return res;
-}
-
std::map<std::string, std::set<std::string>> GetHeapGraphClasses(
trace_processor::TraceProcessor* tp) {
std::map<std::string, std::set<std::string>> res;
@@ -242,37 +190,6 @@
return true;
}
-void SymbolizeDatabase(trace_processor::TraceProcessor* tp,
- Symbolizer* symbolizer,
- std::function<void(const std::string&)> callback) {
- PERFETTO_CHECK(symbolizer);
- auto unsymbolized = GetUnsymbolizedFrames(tp);
- for (auto it = unsymbolized.cbegin(); it != unsymbolized.cend(); ++it) {
- const auto& name_and_buildid = it->first;
- const std::vector<uint64_t>& rel_pcs = it->second;
- auto res = symbolizer->Symbolize(name_and_buildid.first,
- name_and_buildid.second, rel_pcs);
- if (res.empty())
- continue;
-
- protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket> packet;
- auto* module_symbols = packet->set_module_symbols();
- module_symbols->set_path(name_and_buildid.first);
- module_symbols->set_build_id(name_and_buildid.second);
- PERFETTO_DCHECK(res.size() == rel_pcs.size());
- for (size_t i = 0; i < res.size(); ++i) {
- auto* address_symbols = module_symbols->add_address_symbols();
- address_symbols->set_address(rel_pcs[i]);
- for (const SymbolizedFrame& frame : res[i]) {
- auto* line = address_symbols->add_lines();
- line->set_function_name(frame.function_name);
- line->set_source_file_name(frame.file_name);
- line->set_line_number(frame.line);
- }
- }
- callback(packet.SerializeAsString());
- }
-}
void DeobfuscateDatabase(
trace_processor::TraceProcessor* tp,
diff --git a/tools/trace_to_text/utils.h b/tools/trace_to_text/utils.h
index b2e2c0d..46c86f9 100644
--- a/tools/trace_to_text/utils.h
+++ b/tools/trace_to_text/utils.h
@@ -32,7 +32,6 @@
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/paged_memory.h"
#include "perfetto/profiling/deobfuscator.h"
-#include "perfetto/profiling/symbolizer.h"
namespace perfetto {
@@ -65,12 +64,6 @@
void WriteTracePacket(const std::string& str, std::ostream* output);
-// Generate ModuleSymbol protos for all unsymbolized frames in the database.
-// Wrap them in proto-encoded TracePackets messages and call callback.
-void SymbolizeDatabase(trace_processor::TraceProcessor* tp,
- Symbolizer* symbolizer,
- std::function<void(const std::string&)> callback);
-
// Generate ObfuscationMapping protos for all obfuscated java names in the
// database.
// Wrap them in proto-encoded TracePackets messages and call callback.
diff --git a/ui/src/frontend/legacy_trace_viewer.ts b/ui/src/frontend/legacy_trace_viewer.ts
index 4dafe4c..c55451d 100644
--- a/ui/src/frontend/legacy_trace_viewer.ts
+++ b/ui/src/frontend/legacy_trace_viewer.ts
@@ -22,7 +22,8 @@
fileName = fileName.toLowerCase();
return (
fileName.endsWith('.json') || fileName.endsWith('.json.gz') ||
- fileName.endsWith('.zip') || fileName.endsWith('.ctrace'));
+ fileName.endsWith('.zip') || fileName.endsWith('.ctrace') ||
+ fileName.endsWith('.html'));
}
export function openFileWithLegacyTraceViewer(file: File) {