Merge "TracedValue: add dchecks that the scope is always correct."
diff --git a/Android.bp b/Android.bp
index a8a334e..7c34f7e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3559,6 +3559,7 @@
"protos/perfetto/metrics/android/display_metrics.proto",
"protos/perfetto/metrics/android/gpu_metric.proto",
"protos/perfetto/metrics/android/heap_profile_callsites.proto",
+ "protos/perfetto/metrics/android/hwcomposer.proto",
"protos/perfetto/metrics/android/hwui_metric.proto",
"protos/perfetto/metrics/android/ion_metric.proto",
"protos/perfetto/metrics/android/java_heap_histogram.proto",
@@ -3599,6 +3600,7 @@
"protos/perfetto/metrics/android/display_metrics.proto",
"protos/perfetto/metrics/android/gpu_metric.proto",
"protos/perfetto/metrics/android/heap_profile_callsites.proto",
+ "protos/perfetto/metrics/android/hwcomposer.proto",
"protos/perfetto/metrics/android/hwui_metric.proto",
"protos/perfetto/metrics/android/ion_metric.proto",
"protos/perfetto/metrics/android/java_heap_histogram.proto",
@@ -7517,6 +7519,7 @@
"src/trace_processor/metrics/android/android_cpu_agg.sql",
"src/trace_processor/metrics/android/android_cpu_raw_metrics_per_core.sql",
"src/trace_processor/metrics/android/android_gpu.sql",
+ "src/trace_processor/metrics/android/android_hwcomposer.sql",
"src/trace_processor/metrics/android/android_hwui_metric.sql",
"src/trace_processor/metrics/android/android_ion.sql",
"src/trace_processor/metrics/android/android_lmk.sql",
@@ -7533,6 +7536,7 @@
"src/trace_processor/metrics/android/android_task_names.sql",
"src/trace_processor/metrics/android/android_task_state.sql",
"src/trace_processor/metrics/android/android_thread_time_in_state.sql",
+ "src/trace_processor/metrics/android/composition_layers.sql",
"src/trace_processor/metrics/android/cpu_info.sql",
"src/trace_processor/metrics/android/display_metrics.sql",
"src/trace_processor/metrics/android/frame_missed.sql",
diff --git a/BUILD b/BUILD
index 256f5f5..19a8781 100644
--- a/BUILD
+++ b/BUILD
@@ -885,6 +885,7 @@
"src/trace_processor/metrics/android/android_cpu_agg.sql",
"src/trace_processor/metrics/android/android_cpu_raw_metrics_per_core.sql",
"src/trace_processor/metrics/android/android_gpu.sql",
+ "src/trace_processor/metrics/android/android_hwcomposer.sql",
"src/trace_processor/metrics/android/android_hwui_metric.sql",
"src/trace_processor/metrics/android/android_ion.sql",
"src/trace_processor/metrics/android/android_lmk.sql",
@@ -901,6 +902,7 @@
"src/trace_processor/metrics/android/android_task_names.sql",
"src/trace_processor/metrics/android/android_task_state.sql",
"src/trace_processor/metrics/android/android_thread_time_in_state.sql",
+ "src/trace_processor/metrics/android/composition_layers.sql",
"src/trace_processor/metrics/android/cpu_info.sql",
"src/trace_processor/metrics/android/display_metrics.sql",
"src/trace_processor/metrics/android/frame_missed.sql",
@@ -2281,6 +2283,7 @@
"protos/perfetto/metrics/android/display_metrics.proto",
"protos/perfetto/metrics/android/gpu_metric.proto",
"protos/perfetto/metrics/android/heap_profile_callsites.proto",
+ "protos/perfetto/metrics/android/hwcomposer.proto",
"protos/perfetto/metrics/android/hwui_metric.proto",
"protos/perfetto/metrics/android/ion_metric.proto",
"protos/perfetto/metrics/android/java_heap_histogram.proto",
diff --git a/BUILD.gn b/BUILD.gn
index 146ea00..278a678 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -135,8 +135,9 @@
"protos/perfetto/common:cpp",
# The diff testing framework depends on these descriptors.
- "protos/perfetto/metrics:descriptor($host_toolchain)",
- "protos/perfetto/trace:descriptor($host_toolchain)",
+ "protos/perfetto/metrics:descriptor",
+ "protos/perfetto/trace:descriptor",
+ "protos/perfetto/trace:test_extensions_descriptor",
# Used in the when updating the ftrace protos
"protos/perfetto/trace/ftrace:descriptor",
diff --git a/debian/changelog b/debian/changelog
index 40a8df5..fb48257 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,8 @@
+perfetto (11.0-1) unstable; urgency=medium
+ * Add the Perfetto perf sampling and profiling service.
+
+ -- Sami Kyostila <skyostil@google.com> Mon, 18 Jan 2021 12:10:00 +0000
+
perfetto (9.0-1) unstable; urgency=medium
* Run traced under a dedicated system user account and set socket
diff --git a/debian/perfetto.install b/debian/perfetto.install
index ded0fdc..1ae73aa 100644
--- a/debian/perfetto.install
+++ b/debian/perfetto.install
@@ -1,6 +1,8 @@
out/release/libperfetto.so usr/lib
out/release/traced usr/sbin
+out/release/traced_perf usr/sbin
out/release/traced_probes usr/sbin
out/release/perfetto usr/bin
debian/traced.service lib/systemd/system
+debian/traced-perf.service lib/systemd/system
debian/traced-probes.service lib/systemd/system
diff --git a/debian/traced-perf.service b/debian/traced-perf.service
new file mode 100644
index 0000000..b04463b
--- /dev/null
+++ b/debian/traced-perf.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Perfetto sampling and profiling data source
+
+[Service]
+ExecStart=/usr/sbin/traced_perf
+User=root
+Group=root
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index 82eb6cb..de8f70b 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -25,6 +25,7 @@
"display_metrics.proto",
"gpu_metric.proto",
"heap_profile_callsites.proto",
+ "hwcomposer.proto",
"hwui_metric.proto",
"ion_metric.proto",
"java_heap_histogram.proto",
diff --git a/protos/perfetto/metrics/android/hwcomposer.proto b/protos/perfetto/metrics/android/hwcomposer.proto
new file mode 100644
index 0000000..22644ce
--- /dev/null
+++ b/protos/perfetto/metrics/android/hwcomposer.proto
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package perfetto.protos;
+
+message AndroidHwcomposerMetrics {
+ // Counts the number of composition total layers in the trace. (non-weighted average)
+ optional double composition_total_layers = 1;
+
+ // Counts the number of composition dpu layers in the trace. (non-weighted average)
+ optional double composition_dpu_layers = 2;
+
+ // Counts the number of composition gpu layers in the trace. (non-weighted average)
+ optional double composition_gpu_layers = 3;
+
+ // Counts the number of composition dpu cached layers in the trace. (non-weighted average)
+ optional double composition_dpu_cached_layers = 4;
+}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index 244629c..8986b58 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -23,6 +23,7 @@
import "protos/perfetto/metrics/android/display_metrics.proto";
import "protos/perfetto/metrics/android/gpu_metric.proto";
import "protos/perfetto/metrics/android/heap_profile_callsites.proto";
+import "protos/perfetto/metrics/android/hwcomposer.proto";
import "protos/perfetto/metrics/android/hwui_metric.proto";
import "protos/perfetto/metrics/android/ion_metric.proto";
import "protos/perfetto/metrics/android/java_heap_histogram.proto";
@@ -55,7 +56,7 @@
// Root message for all Perfetto-based metrics.
//
-// Next id: 28
+// Next id: 29
message TraceMetrics {
reserved 4, 10, 13, 14, 19;
@@ -124,6 +125,9 @@
// Frame timing and jank root causes for system UI interactions.
optional AndroidSysUiCujMetrics android_sysui_cuj = 27;
+ // Metric associated with hwcomposer.
+ optional AndroidHwcomposerMetrics android_hwcomposer = 28;
+
// Demo extensions.
extensions 450 to 499;
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index 2d3e51f..36ac53a 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -251,6 +251,24 @@
// End of protos/perfetto/metrics/android/heap_profile_callsites.proto
+// Begin of protos/perfetto/metrics/android/hwcomposer.proto
+
+message AndroidHwcomposerMetrics {
+ // Counts the number of composition total layers in the trace. (non-weighted average)
+ optional double composition_total_layers = 1;
+
+ // Counts the number of composition dpu layers in the trace. (non-weighted average)
+ optional double composition_dpu_layers = 2;
+
+ // Counts the number of composition gpu layers in the trace. (non-weighted average)
+ optional double composition_gpu_layers = 3;
+
+ // Counts the number of composition dpu cached layers in the trace. (non-weighted average)
+ optional double composition_dpu_cached_layers = 4;
+}
+
+// End of protos/perfetto/metrics/android/hwcomposer.proto
+
// Begin of protos/perfetto/metrics/android/hwui_metric.proto
// Android HWUI graphics performance and graphics memory usage metrics.
@@ -811,7 +829,7 @@
// Root message for all Perfetto-based metrics.
//
-// Next id: 28
+// Next id: 29
message TraceMetrics {
reserved 4, 10, 13, 14, 19;
@@ -880,6 +898,9 @@
// Frame timing and jank root causes for system UI interactions.
optional AndroidSysUiCujMetrics android_sysui_cuj = 27;
+ // Metric associated with hwcomposer.
+ optional AndroidHwcomposerMetrics android_hwcomposer = 28;
+
// Demo extensions.
extensions 450 to 499;
diff --git a/protos/perfetto/trace/BUILD.gn b/protos/perfetto/trace/BUILD.gn
index 0c39d63..9c195e4 100644
--- a/protos/perfetto/trace/BUILD.gn
+++ b/protos/perfetto/trace/BUILD.gn
@@ -111,7 +111,7 @@
perfetto_proto_library("descriptor") {
proto_generators = [ "descriptor" ]
generate_descriptor = "trace.descriptor"
- sources = [ "perfetto_trace.proto" ]
+ sources = [ "trace.proto" ]
}
}
@@ -121,3 +121,10 @@
complete_static_lib = true
deps = [ ":lite" ]
}
+
+perfetto_proto_library("test_extensions_descriptor") {
+ proto_generators = [ "descriptor" ]
+ generate_descriptor = "test_extensions.descriptor"
+ sources = [ "test_extensions.proto" ]
+ deps = [ "track_event:source_set" ]
+}
diff --git a/protos/perfetto/trace/android/frame_timeline_event.proto b/protos/perfetto/trace/android/frame_timeline_event.proto
index c6c4482..86386a4 100644
--- a/protos/perfetto/trace/android/frame_timeline_event.proto
+++ b/protos/perfetto/trace/android/frame_timeline_event.proto
@@ -28,17 +28,19 @@
// This relationship can be reconstructed by using
// DisplayFrame.token = SurfaceFrame.display_frame_token
message FrameTimelineEvent {
- // Specifies which component was the main source for the jank.
+ // Specifies the reason(s) most likely to have caused the jank.
+ // Used as a bitmask.
enum JankType {
JANK_UNSPECIFIED = 0;
JANK_NONE = 1;
JANK_SF_SCHEDULING = 2;
- JANK_PREDICTION_ERROR = 3;
- JANK_DISPLAY_HAL = 4;
- JANK_SF_DEADLINE_MISSED = 5;
- JANK_APP_DEADLINE_MISSED = 6;
- JANK_BUFFER_STUFFING = 7;
- JANK_UNKNOWN = 8;
+ JANK_PREDICTION_ERROR = 4;
+ JANK_DISPLAY_HAL = 8;
+ JANK_SF_CPU_DEADLINE_MISSED = 16;
+ JANK_SF_GPU_DEADLINE_MISSED = 32;
+ JANK_APP_DEADLINE_MISSED = 64;
+ JANK_BUFFER_STUFFING = 128;
+ JANK_UNKNOWN = 256;
};
// Specifies how a frame was presented on screen w.r.t. timing.
@@ -102,7 +104,9 @@
optional PresentType present_type = 6;
optional bool on_time_finish = 7;
optional bool gpu_composition = 8;
- optional JankType jank_type = 9;
+ // A bitmask of JankType. More than one reason can be attributed to a janky
+ // frame.
+ optional int32 jank_type = 9;
};
// Indicates the start of expected timeline slice for DisplayFrames.
@@ -144,7 +148,9 @@
optional PresentType present_type = 4;
optional bool on_time_finish = 5;
optional bool gpu_composition = 6;
- optional JankType jank_type = 7;
+ // A bitmask of JankType. More than one reason can be attributed to a janky
+ // frame.
+ optional int32 jank_type = 7;
};
// FrameEnd just sends the cookie to indicate that the corresponding
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 134c682..7e30a40 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -1854,17 +1854,19 @@
// This relationship can be reconstructed by using
// DisplayFrame.token = SurfaceFrame.display_frame_token
message FrameTimelineEvent {
- // Specifies which component was the main source for the jank.
+ // Specifies the reason(s) most likely to have caused the jank.
+ // Used as a bitmask.
enum JankType {
JANK_UNSPECIFIED = 0;
JANK_NONE = 1;
JANK_SF_SCHEDULING = 2;
- JANK_PREDICTION_ERROR = 3;
- JANK_DISPLAY_HAL = 4;
- JANK_SF_DEADLINE_MISSED = 5;
- JANK_APP_DEADLINE_MISSED = 6;
- JANK_BUFFER_STUFFING = 7;
- JANK_UNKNOWN = 8;
+ JANK_PREDICTION_ERROR = 4;
+ JANK_DISPLAY_HAL = 8;
+ JANK_SF_CPU_DEADLINE_MISSED = 16;
+ JANK_SF_GPU_DEADLINE_MISSED = 32;
+ JANK_APP_DEADLINE_MISSED = 64;
+ JANK_BUFFER_STUFFING = 128;
+ JANK_UNKNOWN = 256;
};
// Specifies how a frame was presented on screen w.r.t. timing.
@@ -1928,7 +1930,9 @@
optional PresentType present_type = 6;
optional bool on_time_finish = 7;
optional bool gpu_composition = 8;
- optional JankType jank_type = 9;
+ // A bitmask of JankType. More than one reason can be attributed to a janky
+ // frame.
+ optional int32 jank_type = 9;
};
// Indicates the start of expected timeline slice for DisplayFrames.
@@ -1970,7 +1974,9 @@
optional PresentType present_type = 4;
optional bool on_time_finish = 5;
optional bool gpu_composition = 6;
- optional JankType jank_type = 7;
+ // A bitmask of JankType. More than one reason can be attributed to a janky
+ // frame.
+ optional int32 jank_type = 7;
};
// FrameEnd just sends the cookie to indicate that the corresponding
@@ -8386,24 +8392,3 @@
}
// End of protos/perfetto/trace/trace.proto
-
-// Begin of protos/perfetto/trace/test_extensions.proto
-
-// Extensions for TrackEvent used for integration testing. This proto file is
-// compiled to descriptor and is used in tools/diff_test_trace_processor.py.
-//
-// See docs/design-docs/extensions.md for more details.
-message TestExtension {
- extend TrackEvent {
- optional string string_extension_for_testing = 9900;
- repeated int32 int_extension_for_testing = 9901;
- optional string omitted_extension_for_testing = 9902;
- optional TestExtensionChild nested_message_extension_for_testing = 9903;
- }
-}
-
-message TestExtensionChild {
- optional string child_field_for_testing = 1;
-}
-
-// End of protos/perfetto/trace/test_extensions.proto
diff --git a/src/trace_processor/importers/proto/frame_timeline_event_parser.cc b/src/trace_processor/importers/proto/frame_timeline_event_parser.cc
index e1c9082..b98f940 100644
--- a/src/trace_processor/importers/proto/frame_timeline_event_parser.cc
+++ b/src/trace_processor/importers/proto/frame_timeline_event_parser.cc
@@ -44,25 +44,42 @@
using FrameEndDecoder = protos::pbzero::FrameTimelineEvent_FrameEnd_Decoder;
+static StringId JankTypeBitmaskToStringId(TraceProcessorContext* context,
+ int32_t jank_type) {
+ if (jank_type == FrameTimelineEvent::JANK_UNSPECIFIED)
+ return context->storage->InternString("Unspecified");
+ if (jank_type == FrameTimelineEvent::JANK_NONE)
+ return context->storage->InternString("None");
+
+ std::vector<std::string> jank_reasons;
+ if (jank_type & FrameTimelineEvent::JANK_SF_SCHEDULING)
+ jank_reasons.emplace_back("SurfaceFlinger Scheduling");
+ if (jank_type & FrameTimelineEvent::JANK_PREDICTION_ERROR)
+ jank_reasons.emplace_back("Prediction Error");
+ if (jank_type & FrameTimelineEvent::JANK_DISPLAY_HAL)
+ jank_reasons.emplace_back("Display HAL");
+ if (jank_type & FrameTimelineEvent::JANK_SF_CPU_DEADLINE_MISSED)
+ jank_reasons.emplace_back("SurfaceFlinger CPU Deadline Missed");
+ if (jank_type & FrameTimelineEvent::JANK_SF_GPU_DEADLINE_MISSED)
+ jank_reasons.emplace_back("SurfaceFlinger GPU Deadline Missed");
+ if (jank_type & FrameTimelineEvent::JANK_APP_DEADLINE_MISSED)
+ jank_reasons.emplace_back("App Deadline Missed");
+ if (jank_type & FrameTimelineEvent::JANK_BUFFER_STUFFING)
+ jank_reasons.emplace_back("Buffer Stuffing");
+ if (jank_type & FrameTimelineEvent::JANK_UNKNOWN)
+ jank_reasons.emplace_back("Unknown jank");
+
+ std::string jank_str(
+ std::accumulate(jank_reasons.begin(), jank_reasons.end(), std::string(),
+ [](const std::string& l, const std::string& r) {
+ return l.empty() ? r : l + ", " + r;
+ }));
+ return context->storage->InternString(base::StringView(jank_str));
+}
+
FrameTimelineEventParser::FrameTimelineEventParser(
TraceProcessorContext* context)
: context_(context),
- jank_type_ids_{
- {context->storage->InternString(
- "Unspecified Jank") /* JANK_UNSPECIFIED */,
- context->storage->InternString("No Jank") /* JANK_NONE */,
- context->storage->InternString(
- "SurfaceFlinger Scheduling") /* JANK_SF_SCHEDULING */,
- context->storage->InternString(
- "Prediction Error") /* JANK_PREDICTION_ERROR */,
- context->storage->InternString("Display HAL") /* JANK_DISPLAY_HAL */,
- context->storage->InternString(
- "SurfaceFlinger Deadline Missed") /*JANK_SF_DEADLINE_MISSED */,
- context->storage->InternString(
- "App Deadline Missed") /* JANK_APP_DEADLINE_MISSED */,
- context->storage->InternString(
- "Buffer Stuffing") /* JANK_BUFFER_STUFFING */,
- context->storage->InternString("Unknown Jank") /* JANK_UNKNOWN */}},
present_type_ids_{
{context->storage->InternString(
"Unspecified Present") /* PRESENT_UNSPECIFIED */,
@@ -167,7 +184,7 @@
present_type_ids_[static_cast<size_t>(event.present_type())];
actual_row.on_time_finish = event.on_time_finish();
actual_row.gpu_composition = event.gpu_composition();
- actual_row.jank_type = jank_type_ids_[static_cast<size_t>(event.jank_type())];
+ actual_row.jank_type = JankTypeBitmaskToStringId(context_, event.jank_type());
context_->slice_tracker->BeginFrameTimeline(actual_row);
}
@@ -289,7 +306,7 @@
present_type_ids_[static_cast<size_t>(event.present_type())];
actual_row.on_time_finish = event.on_time_finish();
actual_row.gpu_composition = event.gpu_composition();
- actual_row.jank_type = jank_type_ids_[static_cast<size_t>(event.jank_type())];
+ actual_row.jank_type = JankTypeBitmaskToStringId(context_, event.jank_type());
context_->slice_tracker->BeginFrameTimeline(actual_row);
}
diff --git a/src/trace_processor/importers/proto/frame_timeline_event_parser.h b/src/trace_processor/importers/proto/frame_timeline_event_parser.h
index 73affb8..fedfdb5 100644
--- a/src/trace_processor/importers/proto/frame_timeline_event_parser.h
+++ b/src/trace_processor/importers/proto/frame_timeline_event_parser.h
@@ -29,6 +29,9 @@
namespace trace_processor {
+using FrameTimelineEvent = protos::pbzero::FrameTimelineEvent;
+using FrameTimelineEventDecoder = protos::pbzero::FrameTimelineEvent_Decoder;
+
class TraceProcessorContext;
// Class for parsing graphics frame related events.
@@ -41,8 +44,6 @@
void ParseFrameTimelineEvent(int64_t timestamp, ConstBytes);
private:
- using FrameTimelineEvent = protos::pbzero::FrameTimelineEvent;
- using FrameTimelineEventDecoder = protos::pbzero::FrameTimelineEvent_Decoder;
void ParseExpectedDisplayFrameStart(int64_t timestamp, ConstBytes);
void ParseActualDisplayFrameStart(int64_t timestamp, ConstBytes);
@@ -59,7 +60,6 @@
// of the cookie makes it so that we can end a slice with just the cookie and
// the TrackSetId.
std::map<int64_t, TrackSetId> cookie_track_set_id_map_;
- std::array<StringId, 9> jank_type_ids_;
std::array<StringId, 5> present_type_ids_;
StringId expected_timeline_track_name_;
StringId actual_timeline_track_name_;
diff --git a/src/trace_processor/metrics/BUILD.gn b/src/trace_processor/metrics/BUILD.gn
index 0017914..b7bef7b 100644
--- a/src/trace_processor/metrics/BUILD.gn
+++ b/src/trace_processor/metrics/BUILD.gn
@@ -26,6 +26,7 @@
"android/android_mem.sql",
"android/android_mem_unagg.sql",
"android/android_ion.sql",
+ "android/composition_layers.sql",
"android/frame_missed.sql",
"android/android_lmk_reason.sql",
"android/android_lmk.sql",
@@ -41,6 +42,7 @@
"android/display_metrics.sql",
"android/heap_profile_callsites.sql",
"android/hsc_startups.sql",
+ "android/android_hwcomposer.sql",
"android/android_hwui_metric.sql",
"android/java_heap_histogram.sql",
"android/java_heap_stats.sql",
diff --git a/src/trace_processor/metrics/android/android_hwcomposer.sql b/src/trace_processor/metrics/android/android_hwcomposer.sql
new file mode 100644
index 0000000..769c659
--- /dev/null
+++ b/src/trace_processor/metrics/android/android_hwcomposer.sql
@@ -0,0 +1,50 @@
+--
+-- Copyright 2021 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+SELECT RUN_METRIC(
+ 'android/composition_layers.sql',
+ 'track_name', 'HWComposer: Total Layer',
+ 'output', 'total_layers'
+);
+
+SELECT RUN_METRIC(
+ 'android/composition_layers.sql',
+ 'track_name', 'HWComposer: DPU Layer',
+ 'output', 'dpu_layers'
+);
+
+SELECT RUN_METRIC(
+ 'android/composition_layers.sql',
+ 'track_name', 'HWComposer: GPU Layer',
+ 'output', 'gpu_layers'
+);
+
+SELECT RUN_METRIC(
+ 'android/composition_layers.sql',
+ 'track_name', 'HWComposer: Cached Layer',
+ 'output', 'cached_layers'
+);
+
+CREATE VIEW android_hwcomposer_output AS
+SELECT AndroidHwcomposerMetrics(
+ 'composition_total_layers', (SELECT AVG(value)
+ FROM total_layers),
+ 'composition_dpu_layers', (SELECT AVG(value)
+ FROM dpu_layers),
+ 'composition_gpu_layers', (SELECT AVG(value)
+ FROM gpu_layers),
+ 'composition_dpu_cached_layers', (SELECT AVG(value)
+ FROM cached_layers)
+);
diff --git a/src/trace_processor/metrics/android/composition_layers.sql b/src/trace_processor/metrics/android/composition_layers.sql
new file mode 100644
index 0000000..f63a6d3
--- /dev/null
+++ b/src/trace_processor/metrics/android/composition_layers.sql
@@ -0,0 +1,29 @@
+--
+-- Copyright 2021 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+CREATE VIEW IF NOT EXISTS {{output}} AS
+WITH composition_layer_counts AS (
+ SELECT
+ LAG(ts) OVER (ORDER BY ts) AS ts,
+ value
+ FROM counter c
+ JOIN process_counter_track t ON c.track_id = t.id
+ WHERE t.name = '{{track_name}}'
+)
+SELECT
+ ts,
+ value
+FROM composition_layer_counts
+WHERE value >= 0 AND ts IS NOT NULL;
diff --git a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
index c973e4c..659de3c 100644
--- a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
+++ b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor
Binary files differ
diff --git a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1 b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1
index 427c6ca..dd4358f 100644
--- a/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1
+++ b/src/trace_processor/python/perfetto/trace_processor/metrics.descriptor.sha1
@@ -2,4 +2,4 @@
// SHA1(tools/gen_binary_descriptors)
// 70978e4b6e0d773dd222715b1c7e74c25d344da0
// SHA1(protos/perfetto/metrics/metrics.proto)
-// 88089959b7be61227a18d46e91e635df4fca535c
+// e0033c91fc2ae9cd9730bbf5684f5661c16e4d5c
diff --git a/test/synth_common.py b/test/synth_common.py
index 222a338..baa4143 100644
--- a/test/synth_common.py
+++ b/test/synth_common.py
@@ -16,7 +16,7 @@
import argparse
from collections import namedtuple
-from google.protobuf import descriptor, descriptor_pb2, message_factory
+from google.protobuf import descriptor, descriptor_pb2, message_factory, descriptor_pool
CLONE_THREAD = 0x00010000
CLONE_VFORK = 0x00004000
@@ -672,34 +672,37 @@
event = packet.frame_timeline_event.frame_end
event.cookie = cookie
+
+def read_descriptor(file_name):
+ with open(file_name, 'rb') as f:
+ contents = f.read()
+
+ descriptor = descriptor_pb2.FileDescriptorSet()
+ descriptor.MergeFromString(contents)
+
+ return descriptor
+
+
+def create_pool(args):
+ trace_descriptor = read_descriptor(args.trace_descriptor)
+
+ pool = descriptor_pool.DescriptorPool()
+ for file in trace_descriptor.file:
+ pool.Add(file)
+
+ return pool
+
+
def create_trace():
parser = argparse.ArgumentParser()
parser.add_argument(
'trace_descriptor', type=str, help='location of trace descriptor')
args = parser.parse_args()
- with open(args.trace_descriptor, 'rb') as t:
- fileContent = t.read()
-
- file_desc_set_pb2 = descriptor_pb2.FileDescriptorSet()
- file_desc_set_pb2.MergeFromString(fileContent)
-
- desc_by_path = {}
- for f_desc_pb2 in file_desc_set_pb2.file:
- f_desc_pb2_encode = f_desc_pb2.SerializeToString()
- f_desc = descriptor.FileDescriptor(
- name=f_desc_pb2.name,
- package=f_desc_pb2.package,
- serialized_pb=f_desc_pb2_encode)
-
- for desc in f_desc.message_types_by_name.values():
- desc_by_path[desc.full_name] = desc
-
- for desc in f_desc.enum_types_by_name.values():
- desc_by_path[desc.full_name] = desc
-
- factory = message_factory.MessageFactory()
- ProtoTrace = factory.GetPrototype(desc_by_path['perfetto.protos.Trace'])
+ pool = create_pool(args)
+ factory = message_factory.MessageFactory(pool)
+ ProtoTrace = factory.GetPrototype(
+ pool.FindMessageTypeByName('perfetto.protos.Trace'))
class EnumPrototype(object):
@@ -719,14 +722,15 @@
])
prototypes = Prototypes(
TrackEvent=factory.GetPrototype(
- desc_by_path['perfetto.protos.TrackEvent']),
+ pool.FindMessageTypeByName('perfetto.protos.TrackEvent')),
ChromeRAILMode=EnumPrototype.from_descriptor(
- desc_by_path['perfetto.protos.ChromeRAILMode']),
+ pool.FindEnumTypeByName('perfetto.protos.ChromeRAILMode')),
ThreadDescriptor=factory.GetPrototype(
- desc_by_path['perfetto.protos.ThreadDescriptor']),
+ pool.FindMessageTypeByName('perfetto.protos.ThreadDescriptor')),
ChromeProcessDescriptor=factory.GetPrototype(
- desc_by_path['perfetto.protos.ChromeProcessDescriptor']),
+ pool.FindMessageTypeByName(
+ 'perfetto.protos.ChromeProcessDescriptor')),
CounterDescriptor=factory.GetPrototype(
- desc_by_path['perfetto.protos.CounterDescriptor']),
+ pool.FindMessageTypeByName('perfetto.protos.CounterDescriptor')),
)
return Trace(ProtoTrace(), prototypes)
diff --git a/test/trace_processor/graphics/actual_frame_timeline_events.out b/test/trace_processor/graphics/actual_frame_timeline_events.out
index 0776aa8..a28b3c4 100644
--- a/test/trace_processor/graphics/actual_frame_timeline_events.out
+++ b/test/trace_processor/graphics/actual_frame_timeline_events.out
@@ -1,8 +1,9 @@
"ts","dur","pid","display_frame_token","surface_frame_token","layer_name","present_type","on_time_finish","gpu_composition","jank_type"
-20,6,666,2,0,"[NULL]","On-time Present",1,0,"No Jank"
-21,16,1000,4,1,"Layer1","On-time Present",1,0,"No Jank"
+20,6,666,2,0,"[NULL]","On-time Present",1,0,"None"
+21,16,1000,4,1,"Layer1","On-time Present",1,0,"None"
41,33,1000,6,5,"Layer1","Late Present",0,0,"App Deadline Missed"
-42,5,666,4,0,"[NULL]","On-time Present",1,0,"No Jank"
-81,7,666,6,0,"[NULL]","On-time Present",1,0,"No Jank"
+42,5,666,4,0,"[NULL]","On-time Present",1,0,"None"
+81,7,666,6,0,"[NULL]","On-time Present",1,0,"None"
90,16,1000,8,7,"Layer1","Early Present",1,0,"SurfaceFlinger Scheduling"
108,4,666,8,0,"[NULL]","Early Present",1,0,"SurfaceFlinger Scheduling"
+148,8,666,12,0,"[NULL]","Late Present",0,0,"SurfaceFlinger Scheduling, SurfaceFlinger CPU Deadline Missed"
diff --git a/test/trace_processor/graphics/composition_layer.py b/test/trace_processor/graphics/composition_layer.py
new file mode 100644
index 0000000..f25aec6
--- /dev/null
+++ b/test/trace_processor/graphics/composition_layer.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+# Copyright (C) 2021 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.
+
+# This synthetic trace tests handling of the mm_id field in the rss_stat
+# event when mm_structs are reused on process death.
+
+from os import sys, path
+
+import synth_common
+
+trace = synth_common.create_trace()
+
+trace.add_packet(ts=1)
+trace.add_process(10, 1, "parent_process")
+trace.add_process(11, 10, "child_process")
+
+trace.add_ftrace_packet(1)
+
+trace.add_print(ts=99, tid=11, buf='C|10|HWComposer: Total Layer|7')
+trace.add_print(ts=100, tid=11, buf='C|10|HWComposer: Total Layer|5')
+trace.add_print(ts=101, tid=11, buf='C|10|HWComposer: Total Layer|6')
+trace.add_print(ts=102, tid=11, buf='C|10|HWComposer: Total Layer|0')
+trace.add_print(ts=103, tid=11, buf='C|10|HWComposer: Total Layer|4')
+trace.add_print(ts=104, tid=11, buf='C|10|HWComposer: Total Layer|6')
+trace.add_print(ts=105, tid=11, buf='C|10|HWComposer: Total Layer|0')
+trace.add_print(ts=106, tid=11, buf='C|10|HWComposer: Total Layer|4')
+trace.add_print(ts=107, tid=11, buf='C|10|HWComposer: Total Layer|5')
+trace.add_print(ts=108, tid=11, buf='C|10|HWComposer: Total Layer|0')
+trace.add_print(ts=108, tid=11, buf='C|10|HWComposer: Total Layer|3')
+trace.add_print(ts=108, tid=11, buf='C|10|HWComposer: Total Layer|0')
+
+sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/composition_layer_count.out b/test/trace_processor/graphics/composition_layer_count.out
new file mode 100644
index 0000000..6c47b9e
--- /dev/null
+++ b/test/trace_processor/graphics/composition_layer_count.out
@@ -0,0 +1,3 @@
+
+"AVG(value)"
+3.000000
diff --git a/test/trace_processor/graphics/composition_layer_count.sql b/test/trace_processor/graphics/composition_layer_count.sql
new file mode 100644
index 0000000..30a92e6
--- /dev/null
+++ b/test/trace_processor/graphics/composition_layer_count.sql
@@ -0,0 +1,19 @@
+--
+-- Copyright 2021 The Android Open Source Project
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- https://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+SELECT RUN_METRIC('android/android_hwcomposer.sql') AS suppress_query_output;
+
+SELECT AVG(value)
+FROM total_layers;
diff --git a/test/trace_processor/graphics/expected_frame_timeline_events.out b/test/trace_processor/graphics/expected_frame_timeline_events.out
index d695295..935d497 100644
--- a/test/trace_processor/graphics/expected_frame_timeline_events.out
+++ b/test/trace_processor/graphics/expected_frame_timeline_events.out
@@ -6,3 +6,4 @@
80,6,666,6,0,"[NULL]"
90,16,1000,8,7,"Layer1"
120,6,666,8,0,"[NULL]"
+140,6,666,12,0,"[NULL]"
diff --git a/test/trace_processor/graphics/frame_timeline_events.py b/test/trace_processor/graphics/frame_timeline_events.py
index 78496b9..0acb485 100644
--- a/test/trace_processor/graphics/frame_timeline_events.py
+++ b/test/trace_processor/graphics/frame_timeline_events.py
@@ -21,12 +21,13 @@
JANK_UNSPECIFIED = 0;
JANK_NONE = 1;
JANK_SF_SCHEDULING = 2;
- JANK_PREDICTION_ERROR = 3;
- JANK_DISPLAY_HAL = 4;
- JANK_SF_DEADLINE_MISSED = 5;
- JANK_APP_DEADLINE_MISSED = 6;
- JANK_BUFFER_STUFFING = 7;
- JANK_UNKNOWN = 8;
+ JANK_PREDICTION_ERROR = 4;
+ JANK_DISPLAY_HAL = 8;
+ JANK_SF_CPU_DEADLINE_MISSED = 16;
+ JANK_SF_GPU_DEADLINE_MISSED = 32;
+ JANK_APP_DEADLINE_MISSED = 64;
+ JANK_BUFFER_STUFFING = 128;
+ JANK_UNKNOWN = 256;
class PresentType:
PRESENT_UNSPECIFIED = 0;
@@ -75,4 +76,10 @@
trace.add_actual_surface_frame_start_event(ts=90, cookie=14, token=7, display_frame_token=8, pid=1000, layer_name="Layer1", present_type=PresentType.PRESENT_EARLY, on_time_finish=1, gpu_composition=0, jank_type=JankType.JANK_SF_SCHEDULING)
trace.add_frame_end_event(ts=106, cookie=14)
+# DisplayFrame with multiple jank reasons
+trace.add_expected_display_frame_start_event(ts=140, cookie=15, token=12, pid=666)
+trace.add_frame_end_event(ts=146, cookie=15)
+trace.add_actual_display_frame_start_event(ts=148, cookie=16, token=12, pid=666, present_type=PresentType.PRESENT_LATE, on_time_finish=0, gpu_composition=0, jank_type=JankType.JANK_SF_CPU_DEADLINE_MISSED | JankType.JANK_SF_SCHEDULING)
+trace.add_frame_end_event(ts=156, cookie=16)
+
sys.stdout.buffer.write(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics/index b/test/trace_processor/graphics/index
index c6e21c0..256e72d 100644
--- a/test/trace_processor/graphics/index
+++ b/test/trace_processor/graphics/index
@@ -29,3 +29,6 @@
# Frame Timeline event trace tests
frame_timeline_events.py expected_frame_timeline_events.sql expected_frame_timeline_events.out
frame_timeline_events.py actual_frame_timeline_events.sql actual_frame_timeline_events.out
+
+# Composition layer
+composition_layer.py composition_layer_count.sql composition_layer_count.out
diff --git a/test/trace_processor/track_event/track_event_typed_args.textproto b/test/trace_processor/track_event/track_event_typed_args.textproto
index fdbfe2b..471f16a 100644
--- a/test/trace_processor/track_event/track_event_typed_args.textproto
+++ b/test/trace_processor/track_event/track_event_typed_args.textproto
@@ -125,3 +125,14 @@
}
}
}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 6000
+ track_event {
+ track_uuid: 1
+ categories: "cat"
+ name: "name5"
+ type: 3
+ [perfetto.protos.ChromeTrackEvent.chrome_app_state]: APP_STATE_FOREGROUND
+ }
+}
diff --git a/test/trace_processor/track_event/track_event_typed_args_args.out b/test/trace_processor/track_event/track_event_typed_args_args.out
index 70411b2..229d3cd 100644
--- a/test/trace_processor/track_event/track_event_typed_args_args.out
+++ b/test/trace_processor/track_event/track_event_typed_args_args.out
@@ -15,3 +15,4 @@
"int_extension_for_testing","int_extension_for_testing[1]",1337,"[NULL]"
"nested_message_extension_for_testing.child_field_for_testing","nested_message_extension_for_testing.child_field_for_testing","[NULL]","nesting test"
"string_extension_for_testing","string_extension_for_testing","[NULL]","an extension string!"
+"chrome_app_state","chrome_app_state","[NULL]","APP_STATE_FOREGROUND"
diff --git a/test/trace_processor/track_event/track_event_typed_args_slices.out b/test/trace_processor/track_event/track_event_typed_args_slices.out
index 7259082..85b697a 100644
--- a/test/trace_processor/track_event/track_event_typed_args_slices.out
+++ b/test/trace_processor/track_event/track_event_typed_args_slices.out
@@ -3,3 +3,4 @@
"[NULL]","[NULL]","t1","[NULL]",2000,0,"cat","name2"
"[NULL]","[NULL]","t1","[NULL]",3000,0,"cat","name3"
"[NULL]","[NULL]","t1","[NULL]",4000,0,"cat","name4"
+"[NULL]","[NULL]","t1","[NULL]",6000,0,"cat","name5"
diff --git a/tools/diff_test_trace_processor.py b/tools/diff_test_trace_processor.py
index ccc3119..2565ca3 100755
--- a/tools/diff_test_trace_processor.py
+++ b/tools/diff_test_trace_processor.py
@@ -160,7 +160,8 @@
def run_all_tests(trace_processor, trace_descriptor_path,
- metrics_message_factory, tests, keep_input, rebase):
+ extension_descriptor_paths, metrics_message_factory, tests,
+ keep_input, rebase):
perf_data = []
test_failure = 0
rebased = 0
@@ -184,7 +185,8 @@
gen_trace_path = os.path.realpath(gen_trace_file.name)
elif trace_path.endswith('.textproto'):
gen_trace_file = tempfile.NamedTemporaryFile(delete=False)
- serialize_textproto_trace(trace_descriptor_path, trace_path,
+ serialize_textproto_trace(trace_descriptor_path,
+ extension_descriptor_paths, trace_path,
gen_trace_file)
gen_trace_path = os.path.realpath(gen_trace_file.name)
else:
@@ -375,11 +377,10 @@
tests = read_all_tests(query_metric_pattern, trace_pattern)
sys.stderr.write('[==========] Running {} tests.\n'.format(len(tests)))
+ out_path = os.path.dirname(args.trace_processor)
if args.trace_descriptor:
trace_descriptor_path = args.trace_descriptor
else:
- out_path = os.path.dirname(args.trace_processor)
-
def find_trace_descriptor(parent):
trace_protos_path = os.path.join(parent, 'gen', 'protos', 'perfetto',
'trace')
@@ -393,21 +394,24 @@
if args.metrics_descriptor:
metrics_descriptor_path = args.metrics_descriptor
else:
- out_path = os.path.dirname(args.trace_processor)
metrics_protos_path = os.path.join(out_path, 'gen', 'protos', 'perfetto',
'metrics')
metrics_descriptor_path = os.path.join(metrics_protos_path,
'metrics.descriptor')
+ chrome_extensions = os.path.join(out_path, 'gen', 'protos', 'third_party',
+ 'chromium', 'chrome_track_event.descriptor')
+ test_extensions = os.path.join(out_path, 'gen', 'protos', 'perfetto', 'trace',
+ 'test_extensions.descriptor')
+
metrics_message_factory = create_metrics_message_factory(
metrics_descriptor_path)
test_run_start = datetime.datetime.now()
- test_failure, perf_data, rebased = run_all_tests(args.trace_processor,
- trace_descriptor_path,
- metrics_message_factory,
- tests, args.keep_input,
- args.rebase)
+ test_failure, perf_data, rebased = run_all_tests(
+ args.trace_processor, trace_descriptor_path,
+ [chrome_extensions, test_extensions], metrics_message_factory, tests,
+ args.keep_input, args.rebase)
test_run_end = datetime.datetime.now()
sys.stderr.write('[==========] {} tests ran. ({} ms total)\n'.format(
diff --git a/tools/gen_merged_protos b/tools/gen_merged_protos
index 15b2ecb..07964b6 100755
--- a/tools/gen_merged_protos
+++ b/tools/gen_merged_protos
@@ -32,7 +32,6 @@
TRACE_PROTO_ROOTS = CONFIG_PROTO_ROOTS + [
'protos/perfetto/trace/trace.proto',
- 'protos/perfetto/trace/test_extensions.proto',
]
MERGED_TRACE_PROTO = 'protos/perfetto/trace/perfetto_trace.proto'
diff --git a/tools/print_descriptor.py b/tools/print_descriptor.py
new file mode 100755
index 0000000..e4c0a92
--- /dev/null
+++ b/tools/print_descriptor.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python3
+# Copyright (C) 2021 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 argparse
+from google.protobuf import descriptor_pb2
+
+
+# Take a path to file with binary protobuf descriptor as CLI argument and print
+# it in textproto format.
+#
+# Example usage:
+# tools/print_descriptor.py path/to/file.descriptor
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ 'input_file',
+ type=str,
+ help='File name with binary proto descriptor to print')
+ args = parser.parse_args()
+
+ descriptor = descriptor_pb2.FileDescriptorSet()
+ with open(args.input_file, 'rb') as f:
+ contents = f.read()
+ descriptor.MergeFromString(contents)
+
+ print(descriptor)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/proto_utils.py b/tools/proto_utils.py
index 455f15e..210b13c 100644
--- a/tools/proto_utils.py
+++ b/tools/proto_utils.py
@@ -18,7 +18,7 @@
import subprocess
import tempfile
-from google.protobuf import descriptor, descriptor_pb2, message_factory
+from google.protobuf import descriptor, descriptor_pb2, message_factory, descriptor_pool
from google.protobuf import reflection, text_format
@@ -46,11 +46,31 @@
return message_factory.MessageFactory().GetPrototype(desc_by_path[proto_type])
-def serialize_textproto_trace(trace_descriptor_path, text_proto_path,
- out_stream):
- trace_message_factory = create_message_factory(trace_descriptor_path,
- 'perfetto.protos.Trace')
- proto = trace_message_factory()
+def read_descriptor(file_name):
+ with open(file_name, 'rb') as f:
+ contents = f.read()
+
+ descriptor = descriptor_pb2.FileDescriptorSet()
+ descriptor.MergeFromString(contents)
+
+ return descriptor
+
+
+def serialize_textproto_trace(trace_descriptor_path, extension_descriptor_paths,
+ text_proto_path, out_stream):
+ pool = descriptor_pool.DescriptorPool()
+ trace_descriptor = read_descriptor(trace_descriptor_path)
+ for file in trace_descriptor.file:
+ pool.Add(file)
+
+ for path in extension_descriptor_paths:
+ descriptor = read_descriptor(path)
+ for file in descriptor.file:
+ pool.Add(file)
+
+ proto = message_factory.MessageFactory().GetPrototype(
+ pool.FindMessageTypeByName('perfetto.protos.Trace'))()
+
with open(text_proto_path, 'r') as text_proto_file:
text_format.Merge(text_proto_file.read(), proto)
out_stream.write(proto.SerializeToString())
@@ -59,7 +79,11 @@
def serialize_python_trace(trace_descriptor_path, python_trace_path,
out_stream):
- python_cmd = ['python3', python_trace_path, trace_descriptor_path]
+ python_cmd = [
+ 'python3',
+ python_trace_path,
+ trace_descriptor_path,
+ ]
# Add the test dir to the PYTHONPATH to allow synth_common to be found.
env = os.environ.copy()
diff --git a/tools/serialize_test_trace.py b/tools/serialize_test_trace.py
index cf8257f..5bb9080 100755
--- a/tools/serialize_test_trace.py
+++ b/tools/serialize_test_trace.py
@@ -21,7 +21,7 @@
import os
import sys
-from proto_utils import create_message_factory, serialize_python_trace, serialize_textproto_trace
+from proto_utils import serialize_python_trace, serialize_textproto_trace
def main():
@@ -38,19 +38,29 @@
if args.out and not args.descriptor:
trace_protos_path = os.path.join(args.out, 'gen', 'protos', 'perfetto',
'trace')
+ chrome_extension_descriptor_path = os.path.join(
+ args.out, 'gen', 'protos', 'third_party', 'chromium',
+ 'chrome_track_event.descriptor')
trace_descriptor_path = os.path.join(trace_protos_path, 'trace.descriptor')
+ test_extensions_descriptor_path = os.path.join(
+ trace_protos_path, 'test_extensions.descriptor')
+ extension_descriptors = [
+ chrome_extension_descriptor_path, test_extensions_descriptor_path
+ ]
elif args.descriptor and not args.out:
trace_descriptor_path = args.descriptor
+ extension_descriptors = []
else:
- raise RuntimeError('Exactly one of --out and --descriptor should be provided')
+ raise RuntimeError(
+ 'Exactly one of --out and --descriptor should be provided')
trace_path = args.trace_path
if trace_path.endswith('.py'):
serialize_python_trace(trace_descriptor_path, trace_path, sys.stdout.buffer)
elif trace_path.endswith('.textproto'):
- serialize_textproto_trace(trace_descriptor_path, trace_path,
- sys.stdout.buffer)
+ serialize_textproto_trace(trace_descriptor_path, extension_descriptors,
+ trace_path, sys.stdout.buffer)
else:
raise RuntimeError('Invalid extension for unserialized trace file')
diff --git a/tools/trace_to_text/trace_to_profile.cc b/tools/trace_to_text/trace_to_profile.cc
index 5a5d261..a394e2b 100644
--- a/tools/trace_to_text/trace_to_profile.cc
+++ b/tools/trace_to_text/trace_to_profile.cc
@@ -16,6 +16,7 @@
#include "tools/trace_to_text/trace_to_profile.h"
+#include <random>
#include <string>
#include <vector>
@@ -49,6 +50,17 @@
namespace trace_to_text {
namespace {
+std::string GetRandomString(size_t n) {
+ std::random_device r;
+ auto rng = std::default_random_engine(r());
+ std::uniform_int_distribution<char> dist('a', 'z');
+ std::string result(n, ' ');
+ for (size_t i = 0; i < n; ++i) {
+ result[i] = dist(rng);
+ }
+ return result;
+}
+
void MaybeSymbolize(trace_processor::TraceProcessor* tp) {
std::unique_ptr<profiling::Symbolizer> symbolizer =
profiling::LocalSymbolizerOrDie(profiling::GetPerfettoBinaryPath(),
@@ -99,8 +111,8 @@
return 0;
}
- std::string temp_dir =
- GetTemp() + "/" + dirname_prefix + base::GetTimeFmt("%y%m%d%H%M%S");
+ std::string temp_dir = GetTemp() + "/" + dirname_prefix +
+ base::GetTimeFmt("%y%m%d%H%M%S") + GetRandomString(5);
PERFETTO_CHECK(base::Mkdir(temp_dir));
for (const auto& profile : profiles) {
std::string filename = temp_dir + "/" + filename_fn(profile);
diff --git a/ui/src/controller/aggregation/cpu_aggregation_controller.ts b/ui/src/controller/aggregation/cpu_aggregation_controller.ts
index 70a643b..a8b1161 100644
--- a/ui/src/controller/aggregation/cpu_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/cpu_aggregation_controller.ts
@@ -54,7 +54,7 @@
}
getTabName() {
- return 'CPU Slices';
+ return 'CPU by thread';
}
async getExtra() {}
diff --git a/ui/src/controller/aggregation/cpu_by_process_aggregation_controller.ts b/ui/src/controller/aggregation/cpu_by_process_aggregation_controller.ts
new file mode 100644
index 0000000..baf9efe
--- /dev/null
+++ b/ui/src/controller/aggregation/cpu_by_process_aggregation_controller.ts
@@ -0,0 +1,101 @@
+// Copyright (C) 2021 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 {ColumnDef} from '../../common/aggregation_data';
+import {Engine} from '../../common/engine';
+import {Area, Sorting} from '../../common/state';
+import {toNs} from '../../common/time';
+import {Config, CPU_SLICE_TRACK_KIND} from '../../tracks/cpu_slices/common';
+import {globals} from '../globals';
+
+import {AggregationController} from './aggregation_controller';
+
+export class CpuByProcessAggregationController extends AggregationController {
+ async createAggregateView(engine: Engine, area: Area) {
+ await engine.query(`drop view if exists ${this.kind};`);
+
+ const selectedCpus = [];
+ for (const trackId of area.tracks) {
+ const track = globals.state.tracks[trackId];
+ // Track will be undefined for track groups.
+ if (track !== undefined && track.kind === CPU_SLICE_TRACK_KIND) {
+ selectedCpus.push((track.config as Config).cpu);
+ }
+ }
+ if (selectedCpus.length === 0) return false;
+
+ const query = `create view ${this.kind} as
+ SELECT process.name as process_name, pid,
+ sum(dur) AS total_dur,
+ sum(dur)/count(1) as avg_dur,
+ count(1) as occurrences
+ FROM process
+ JOIN thread USING(upid)
+ JOIN thread_state USING(utid)
+ WHERE cpu IN (${selectedCpus}) AND
+ state = "Running" AND
+ thread_state.ts + thread_state.dur > ${toNs(area.startSec)} AND
+ thread_state.ts < ${toNs(area.endSec)} group by upid`;
+
+ await engine.query(query);
+ return true;
+ }
+
+ getTabName() {
+ return 'CPU by process';
+ }
+
+ async getExtra() {}
+
+ getDefaultSorting(): Sorting {
+ return {column: 'total_dur', direction: 'DESC'};
+ }
+
+ getColumnDefinitions(): ColumnDef[] {
+ return [
+ {
+ title: 'Process',
+ kind: 'STRING',
+ columnConstructor: Uint16Array,
+ columnId: 'process_name',
+ },
+ {
+ title: 'PID',
+ kind: 'NUMBER',
+ columnConstructor: Uint16Array,
+ columnId: 'pid'
+ },
+ {
+ title: 'Wall duration (ms)',
+ kind: 'TIMESTAMP_NS',
+ columnConstructor: Float64Array,
+ columnId: 'total_dur',
+ sum: true
+ },
+ {
+ title: 'Avg Wall duration (ms)',
+ kind: 'TIMESTAMP_NS',
+ columnConstructor: Float64Array,
+ columnId: 'avg_dur'
+ },
+ {
+ title: 'Occurrences',
+ kind: 'NUMBER',
+ columnConstructor: Uint16Array,
+ columnId: 'occurrences',
+ sum: true
+ }
+ ];
+ }
+}
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 29f8709..ab061c7 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -39,6 +39,9 @@
CpuAggregationController
} from './aggregation/cpu_aggregation_controller';
import {
+ CpuByProcessAggregationController
+} from './aggregation/cpu_by_process_aggregation_controller';
+import {
SliceAggregationController
} from './aggregation/slice_aggregation_controller';
import {
@@ -173,6 +176,10 @@
ThreadAggregationController,
{engine, kind: 'thread_state_aggregation'}));
childControllers.push(Child(
+ 'cpu_process_aggregation',
+ CpuByProcessAggregationController,
+ {engine, kind: 'cpu_by_process_aggregation'}));
+ childControllers.push(Child(
'slice_aggregation',
SliceAggregationController,
{engine, kind: 'slice_aggregation'}));