summaryrefslogtreecommitdiff
path: root/chromium/cc/metrics/frame_sequence_metrics.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/cc/metrics/frame_sequence_metrics.cc')
-rw-r--r--chromium/cc/metrics/frame_sequence_metrics.cc122
1 files changed, 108 insertions, 14 deletions
diff --git a/chromium/cc/metrics/frame_sequence_metrics.cc b/chromium/cc/metrics/frame_sequence_metrics.cc
index 0cefe55fd51..5933096b855 100644
--- a/chromium/cc/metrics/frame_sequence_metrics.cc
+++ b/chromium/cc/metrics/frame_sequence_metrics.cc
@@ -4,6 +4,10 @@
#include "cc/metrics/frame_sequence_metrics.h"
+#include <memory>
+#include <string>
+#include <utility>
+
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/strcat.h"
@@ -91,13 +95,20 @@ bool IsInteractionType(FrameSequenceTrackerType sequence_type) {
FrameSequenceMetrics::FrameSequenceMetrics(FrameSequenceTrackerType type,
ThroughputUkmReporter* ukm_reporter)
: type_(type), throughput_ukm_reporter_(ukm_reporter) {
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
- "cc,benchmark", "FrameSequenceTracker", TRACE_ID_LOCAL(this), "name",
- FrameSequenceTracker::GetFrameSequenceTrackerTypeName(type_));
}
-FrameSequenceMetrics::~FrameSequenceMetrics() {
+FrameSequenceMetrics::~FrameSequenceMetrics() = default;
+
+void FrameSequenceMetrics::ReportLeftoverData() {
if (HasDataLeftForReporting()) {
+ // Do this before ReportMetrics() which clears the throughput data.
+ // TODO(xidachen): Find a way to make ThroughputUkmReporter to directly talk
+ // to LayerTreeHostClient, and submit throughput data. Instead of storing
+ // the values in ThroughputUkmReporter.
+ if (type_ == FrameSequenceTrackerType::kUniversal &&
+ HasEnoughDataForReporting()) {
+ throughput_ukm_reporter_->ComputeUniversalThroughput(this);
+ }
ReportMetrics();
}
}
@@ -136,6 +147,8 @@ FrameSequenceMetrics::ThreadType FrameSequenceMetrics::GetEffectiveThread()
return ThreadType::kSlower;
case FrameSequenceTrackerType::kCustom:
+ return ThreadType::kMain;
+
case FrameSequenceTrackerType::kMaxType:
NOTREACHED();
}
@@ -144,6 +157,8 @@ FrameSequenceMetrics::ThreadType FrameSequenceMetrics::GetEffectiveThread()
void FrameSequenceMetrics::Merge(
std::unique_ptr<FrameSequenceMetrics> metrics) {
+ // Merging custom trackers are not supported.
+ DCHECK_NE(type_, FrameSequenceTrackerType::kCustom);
DCHECK_EQ(type_, metrics->type_);
DCHECK_EQ(GetEffectiveThread(), metrics->GetEffectiveThread());
impl_throughput_.Merge(metrics->impl_throughput_);
@@ -169,6 +184,16 @@ bool FrameSequenceMetrics::HasDataLeftForReporting() const {
main_throughput_.frames_expected > 0;
}
+void FrameSequenceMetrics::AdoptTrace(FrameSequenceMetrics* adopt_from) {
+ DCHECK(!trace_data_.trace_id);
+ trace_data_.trace_id = adopt_from->trace_data_.trace_id;
+ adopt_from->trace_data_.trace_id = nullptr;
+}
+
+void FrameSequenceMetrics::AdvanceTrace(base::TimeTicks timestamp) {
+ trace_data_.Advance(timestamp);
+}
+
void FrameSequenceMetrics::ComputeAggregatedThroughput() {
// Whenever we are expecting and producing main frames, we are expecting and
// producing impl frames as well. As an example, if we expect one main frame
@@ -183,10 +208,11 @@ void FrameSequenceMetrics::ComputeAggregatedThroughput() {
void FrameSequenceMetrics::ReportMetrics() {
DCHECK_LE(impl_throughput_.frames_produced, impl_throughput_.frames_expected);
DCHECK_LE(main_throughput_.frames_produced, main_throughput_.frames_expected);
- TRACE_EVENT_NESTABLE_ASYNC_END2(
- "cc,benchmark", "FrameSequenceTracker", TRACE_ID_LOCAL(this), "args",
- ThroughputData::ToTracedValue(impl_throughput_, main_throughput_),
- "checkerboard", frames_checkerboarded_);
+ DCHECK_LE(aggregated_throughput_.frames_produced,
+ aggregated_throughput_.frames_expected);
+
+ // Terminates |trace_data_| for all types of FrameSequenceTracker.
+ trace_data_.Terminate();
if (type_ == FrameSequenceTrackerType::kCustom) {
DCHECK(!custom_reporter_.is_null());
@@ -199,8 +225,6 @@ void FrameSequenceMetrics::ReportMetrics() {
return;
}
- ComputeAggregatedThroughput();
-
// Report the throughput metrics.
base::Optional<int> impl_throughput_percent = ThroughputData::ReportHistogram(
this, ThreadType::kCompositor,
@@ -220,7 +244,8 @@ void FrameSequenceMetrics::ReportMetrics() {
this, ThreadType::kSlower,
GetIndexForMetric(FrameSequenceMetrics::ThreadType::kSlower, type_),
aggregated_throughput_);
- if (aggregated_throughput_percent.has_value() && throughput_ukm_reporter_) {
+ if (aggregated_throughput_percent.has_value() && throughput_ukm_reporter_ &&
+ type_ != FrameSequenceTrackerType::kUniversal) {
throughput_ukm_reporter_->ReportThroughputUkm(
aggregated_throughput_percent, impl_throughput_percent,
main_throughput_percent, type_);
@@ -312,9 +337,7 @@ base::Optional<int> FrameSequenceMetrics::ThroughputData::ReportHistogram(
// Throughput means the percent of frames that was expected to show on the
// screen but didn't. In other words, the lower the throughput is, the
// smoother user experience.
- const int percent =
- std::ceil(100 * (data.frames_expected - data.frames_produced) /
- static_cast<double>(data.frames_expected));
+ const int percent = data.DroppedFramePercent();
const bool is_animation =
ShouldReportForAnimation(sequence_type, thread_type);
@@ -323,6 +346,11 @@ base::Optional<int> FrameSequenceMetrics::ThroughputData::ReportHistogram(
ThroughputUkmReporter* const ukm_reporter = metrics->ukm_reporter();
if (is_animation) {
+ TRACE_EVENT_INSTANT2("cc,benchmark", "PercentDroppedFrames.AllAnimations",
+ TRACE_EVENT_SCOPE_THREAD, "frames_expected",
+ data.frames_expected, "frames_produced",
+ data.frames_produced);
+
UMA_HISTOGRAM_PERCENTAGE(
"Graphics.Smoothness.PercentDroppedFrames.AllAnimations", percent);
if (ukm_reporter) {
@@ -332,6 +360,10 @@ base::Optional<int> FrameSequenceMetrics::ThroughputData::ReportHistogram(
}
if (is_interaction) {
+ TRACE_EVENT_INSTANT2("cc,benchmark", "PercentDroppedFrames.AllInteractions",
+ TRACE_EVENT_SCOPE_THREAD, "frames_expected",
+ data.frames_expected, "frames_produced",
+ data.frames_produced);
UMA_HISTOGRAM_PERCENTAGE(
"Graphics.Smoothness.PercentDroppedFrames.AllInteractions", percent);
if (ukm_reporter) {
@@ -341,6 +373,10 @@ base::Optional<int> FrameSequenceMetrics::ThroughputData::ReportHistogram(
}
if (is_animation || is_interaction) {
+ TRACE_EVENT_INSTANT2("cc,benchmark", "PercentDroppedFrames.AllSequences",
+ TRACE_EVENT_SCOPE_THREAD, "frames_expected",
+ data.frames_expected, "frames_produced",
+ data.frames_produced);
UMA_HISTOGRAM_PERCENTAGE(
"Graphics.Smoothness.PercentDroppedFrames.AllSequences", percent);
if (ukm_reporter) {
@@ -368,4 +404,62 @@ base::Optional<int> FrameSequenceMetrics::ThroughputData::ReportHistogram(
return percent;
}
+std::unique_ptr<base::trace_event::TracedValue>
+FrameSequenceMetrics::ThroughputData::ToTracedValue(
+ const ThroughputData& impl,
+ const ThroughputData& main,
+ ThreadType effective_thread) {
+ auto dict = std::make_unique<base::trace_event::TracedValue>();
+ if (effective_thread == ThreadType::kMain) {
+ dict->SetInteger("main-frames-produced", main.frames_produced);
+ dict->SetInteger("main-frames-expected", main.frames_expected);
+ } else {
+ dict->SetInteger("impl-frames-produced", impl.frames_produced);
+ dict->SetInteger("impl-frames-expected", impl.frames_expected);
+ }
+ return dict;
+}
+
+FrameSequenceMetrics::TraceData::TraceData(FrameSequenceMetrics* m)
+ : metrics(m) {
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED("cc,benchmark", &enabled);
+}
+
+FrameSequenceMetrics::TraceData::~TraceData() = default;
+
+void FrameSequenceMetrics::TraceData::Terminate() {
+ if (!enabled || !trace_id)
+ return;
+ TRACE_EVENT_NESTABLE_ASYNC_END2(
+ "cc,benchmark", "FrameSequenceTracker", TRACE_ID_LOCAL(trace_id), "args",
+ ThroughputData::ToTracedValue(metrics->impl_throughput(),
+ metrics->main_throughput(),
+ metrics->GetEffectiveThread()),
+ "checkerboard", metrics->frames_checkerboarded());
+ trace_id = nullptr;
+}
+
+void FrameSequenceMetrics::TraceData::Advance(base::TimeTicks new_timestamp) {
+ if (!enabled)
+ return;
+ if (!trace_id) {
+ trace_id = this;
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1(
+ "cc,benchmark", "FrameSequenceTracker", TRACE_ID_LOCAL(trace_id),
+ this->last_timestamp, "name",
+ FrameSequenceTracker::GetFrameSequenceTrackerTypeName(metrics->type()));
+ }
+ // Use different names, because otherwise the trace-viewer shows the slices in
+ // the same color, and that makes it difficult to tell the traces apart from
+ // each other.
+ const char* trace_names[] = {"Frame", "Frame ", "Frame "};
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
+ "cc,benchmark", trace_names[++this->frame_count % 3],
+ TRACE_ID_LOCAL(trace_id), this->last_timestamp);
+ TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
+ "cc,benchmark", trace_names[this->frame_count % 3],
+ TRACE_ID_LOCAL(trace_id), new_timestamp);
+ this->last_timestamp = new_timestamp;
+}
+
} // namespace cc