Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(267)

Side by Side Diff: ui/events/latency_info.cc

Issue 25022003: Report LatencyInfo through trace buffer (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: address sadrul's comments Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/debug/trace_event.h"
6 #include "base/json/json_writer.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/stringprintf.h"
5 #include "ui/events/latency_info.h" 9 #include "ui/events/latency_info.h"
6 10
7 #include <algorithm> 11 #include <algorithm>
8 12
13 namespace {
14 const char* GetComponentName(ui::LatencyComponentType type) {
15 #define CASE_TYPE(t) case ui::t: return #t
16 switch (type) {
17 CASE_TYPE(INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT);
18 CASE_TYPE(INPUT_EVENT_LATENCY_SCROLL_UPDATE_RWH_COMPONENT);
19 CASE_TYPE(INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT);
20 CASE_TYPE(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT);
21 CASE_TYPE(INPUT_EVENT_LATENCY_UI_COMPONENT);
22 CASE_TYPE(INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT);
23 CASE_TYPE(INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT);
24 CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT);
25 CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT);
26 CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT);
27 CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT);
28 default:
29 DLOG(WARNING) << "Unhandled LatencyComponentType.\n";
30 break;
31 }
32 #undef CASE_TYPE
33 return "unknown";
34 }
35
36 bool IsTerminalComponent(ui::LatencyComponentType type) {
37 switch (type) {
38 case ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT:
39 case ui::INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT:
40 case ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT:
41 case ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT:
42 return true;
43 default:
44 return false;
45 }
46 }
47
48 bool IsBeginComponent(ui::LatencyComponentType type) {
49 return (type == ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT);
50 }
51
52 // This class is for converting latency info to trace buffer friendly format.
53 class LatencyInfoTracedValue : public base::debug::ConvertableToTraceFormat {
54 public:
55 static scoped_ptr<ConvertableToTraceFormat> FromValue(
56 scoped_ptr<base::Value> value);
57
58 virtual ~LatencyInfoTracedValue();
59
60 virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE;
61
62 private:
63 explicit LatencyInfoTracedValue(base::Value* value);
64
65 scoped_ptr<base::Value> value_;
66
67 DISALLOW_COPY_AND_ASSIGN(LatencyInfoTracedValue);
68 };
69
70 scoped_ptr<base::debug::ConvertableToTraceFormat>
71 LatencyInfoTracedValue::FromValue(scoped_ptr<base::Value> value) {
72 return scoped_ptr<base::debug::ConvertableToTraceFormat>(
73 new LatencyInfoTracedValue(value.release()));
74 }
75
76 LatencyInfoTracedValue::~LatencyInfoTracedValue() {
77 }
78
79 void LatencyInfoTracedValue::AppendAsTraceFormat(std::string* out) const {
80 std::string tmp;
81 base::JSONWriter::Write(value_.get(), &tmp);
82 *out += tmp;
83 }
84
85 LatencyInfoTracedValue::LatencyInfoTracedValue(base::Value* value)
86 : value_(value) {
87 }
88
89 // Converts latencyinfo into format that can be dumped into trace buffer.
90 scoped_ptr<base::debug::ConvertableToTraceFormat> AsTraceableData(
91 const ui::LatencyInfo& latency) {
92 scoped_ptr<base::DictionaryValue> record_data(new base::DictionaryValue());
93 for (ui::LatencyInfo::LatencyMap::const_iterator it =
94 latency.latency_components.begin();
95 it != latency.latency_components.end(); ++it) {
96 base::DictionaryValue* component_info = new base::DictionaryValue();
97 component_info->SetDouble("comp_id", it->first.second);
98 component_info->SetDouble("time", it->second.event_time.ToInternalValue());
99 component_info->SetDouble("count", it->second.event_count);
100 record_data->Set(GetComponentName(it->first.first), component_info);
101 }
102 return LatencyInfoTracedValue::FromValue(record_data.PassAs<base::Value>());
103 }
104
105 } // namespace
106
9 namespace ui { 107 namespace ui {
10 108
11 LatencyInfo::LatencyInfo() { 109 LatencyInfo::LatencyInfo() : trace_id(-1), terminated(false) {
12 } 110 }
13 111
14 LatencyInfo::~LatencyInfo() { 112 LatencyInfo::~LatencyInfo() {
15 } 113 }
16 114
17 void LatencyInfo::MergeWith(const LatencyInfo& other) { 115 void LatencyInfo::MergeWith(const LatencyInfo& other) {
18 for (LatencyMap::const_iterator it = other.latency_components.begin(); 116 for (LatencyMap::const_iterator it = other.latency_components.begin();
19 it != other.latency_components.end(); 117 it != other.latency_components.end();
20 ++it) { 118 ++it) {
21 AddLatencyNumberWithTimestamp(it->first.first, 119 AddLatencyNumberWithTimestamp(it->first.first,
22 it->first.second, 120 it->first.second,
23 it->second.sequence_number, 121 it->second.sequence_number,
24 it->second.event_time, 122 it->second.event_time,
25 it->second.event_count); 123 it->second.event_count,
124 false);
26 } 125 }
27 } 126 }
28 127
29 void LatencyInfo::AddNewLatencyFrom(const LatencyInfo& other) { 128 void LatencyInfo::AddNewLatencyFrom(const LatencyInfo& other) {
30 for (LatencyMap::const_iterator it = other.latency_components.begin(); 129 for (LatencyMap::const_iterator it = other.latency_components.begin();
31 it != other.latency_components.end(); 130 it != other.latency_components.end();
32 ++it) { 131 ++it) {
33 if (!FindLatency(it->first.first, it->first.second, NULL)) { 132 if (!FindLatency(it->first.first, it->first.second, NULL)) {
34 AddLatencyNumberWithTimestamp(it->first.first, 133 AddLatencyNumberWithTimestamp(it->first.first,
35 it->first.second, 134 it->first.second,
36 it->second.sequence_number, 135 it->second.sequence_number,
37 it->second.event_time, 136 it->second.event_time,
38 it->second.event_count); 137 it->second.event_count,
138 false);
39 } 139 }
40 } 140 }
41 } 141 }
42 142
43 void LatencyInfo::AddLatencyNumber(LatencyComponentType component, 143 void LatencyInfo::AddLatencyNumber(LatencyComponentType component,
44 int64 id, 144 int64 id,
45 int64 component_sequence_number) { 145 int64 component_sequence_number) {
46 AddLatencyNumberWithTimestamp(component, id, component_sequence_number, 146 AddLatencyNumberWithTimestamp(component, id, component_sequence_number,
47 base::TimeTicks::HighResNow(), 1); 147 base::TimeTicks::HighResNow(), 1, true);
48 } 148 }
49 149
50 void LatencyInfo::AddLatencyNumberWithTimestamp(LatencyComponentType component, 150 void LatencyInfo::AddLatencyNumberWithTimestamp(LatencyComponentType component,
51 int64 id, 151 int64 id,
52 int64 component_sequence_number, 152 int64 component_sequence_number,
53 base::TimeTicks time, 153 base::TimeTicks time,
54 uint32 event_count) { 154 uint32 event_count,
155 bool dump_to_trace) {
156 if (dump_to_trace && IsBeginComponent(component)) {
157 // Should only ever add begin component once.
158 CHECK_EQ(-1, trace_id);
159 trace_id = component_sequence_number;
160 TRACE_EVENT_ASYNC_BEGIN0("benchmark",
161 "InputLatency",
162 TRACE_ID_DONT_MANGLE(trace_id));
163 }
164
55 LatencyMap::key_type key = std::make_pair(component, id); 165 LatencyMap::key_type key = std::make_pair(component, id);
56 LatencyMap::iterator it = latency_components.find(key); 166 LatencyMap::iterator it = latency_components.find(key);
57 if (it == latency_components.end()) { 167 if (it == latency_components.end()) {
58 LatencyComponent info = {component_sequence_number, time, event_count}; 168 LatencyComponent info = {component_sequence_number, time, event_count};
59 latency_components[key] = info; 169 latency_components[key] = info;
60 return; 170 } else {
171 it->second.sequence_number = std::max(component_sequence_number,
172 it->second.sequence_number);
173 uint32 new_count = event_count + it->second.event_count;
174 if (event_count > 0 && new_count != 0) {
175 // Do a weighted average, so that the new event_time is the average of
176 // the times of events currently in this structure with the time passed
177 // into this method.
178 it->second.event_time += (time - it->second.event_time) * event_count /
179 new_count;
180 it->second.event_count = new_count;
181 }
61 } 182 }
62 it->second.sequence_number = std::max(component_sequence_number, 183
63 it->second.sequence_number); 184 if (dump_to_trace && IsTerminalComponent(component) && trace_id != -1) {
64 uint32 new_count = event_count + it->second.event_count; 185 // Should only ever add terminal component once.
65 if (event_count > 0 && new_count != 0) { 186 CHECK(!terminated);
66 // Do a weighted average, so that the new event_time is the average of 187 terminated = true;
67 // the times of events currently in this structure with the time passed 188 TRACE_EVENT_ASYNC_END1("benchmark",
68 // into this method. 189 "InputLatency",
69 it->second.event_time += (time - it->second.event_time) * event_count / 190 TRACE_ID_DONT_MANGLE(trace_id),
70 new_count; 191 "data", AsTraceableData(*this));
71 it->second.event_count = new_count;
72 } 192 }
73 } 193 }
74 194
75 bool LatencyInfo::FindLatency(LatencyComponentType type, 195 bool LatencyInfo::FindLatency(LatencyComponentType type,
76 int64 id, 196 int64 id,
77 LatencyComponent* output) const { 197 LatencyComponent* output) const {
78 LatencyMap::const_iterator it = latency_components.find( 198 LatencyMap::const_iterator it = latency_components.find(
79 std::make_pair(type, id)); 199 std::make_pair(type, id));
80 if (it == latency_components.end()) 200 if (it == latency_components.end())
81 return false; 201 return false;
82 if (output) 202 if (output)
83 *output = it->second; 203 *output = it->second;
84 return true; 204 return true;
85 } 205 }
86 206
87 void LatencyInfo::Clear() { 207 void LatencyInfo::Clear() {
88 latency_components.clear(); 208 latency_components.clear();
89 } 209 }
90 210
91 } // namespace ui 211 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698