| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "core/frame/PerformanceMonitor.h" | 5 #include "core/frame/PerformanceMonitor.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/ScheduledAction.h" | 7 #include "bindings/core/v8/ScheduledAction.h" |
| 8 #include "bindings/core/v8/ScriptEventListener.h" | 8 #include "bindings/core/v8/ScriptEventListener.h" |
| 9 #include "bindings/core/v8/SourceLocation.h" | 9 #include "bindings/core/v8/SourceLocation.h" |
| 10 #include "core/InstrumentingAgents.h" |
| 10 #include "core/dom/Document.h" | 11 #include "core/dom/Document.h" |
| 11 #include "core/dom/ExecutionContext.h" | 12 #include "core/dom/ExecutionContext.h" |
| 12 #include "core/events/EventListener.h" | 13 #include "core/events/EventListener.h" |
| 13 #include "core/frame/Frame.h" | 14 #include "core/frame/Frame.h" |
| 14 #include "core/frame/LocalFrame.h" | 15 #include "core/frame/LocalFrame.h" |
| 15 #include "core/html/parser/HTMLDocumentParser.h" | 16 #include "core/html/parser/HTMLDocumentParser.h" |
| 16 #include "public/platform/Platform.h" | 17 #include "public/platform/Platform.h" |
| 17 #include "wtf/CurrentTime.h" | 18 #include "wtf/CurrentTime.h" |
| 18 | 19 |
| 19 namespace blink { | 20 namespace blink { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 return; | 55 return; |
| 55 --m_performanceMonitor->m_handlerDepth; | 56 --m_performanceMonitor->m_handlerDepth; |
| 56 if (!m_performanceMonitor->m_handlerDepth) { | 57 if (!m_performanceMonitor->m_handlerDepth) { |
| 57 m_performanceMonitor->m_handlerType = PerformanceMonitor::kAfterLast; | 58 m_performanceMonitor->m_handlerType = PerformanceMonitor::kAfterLast; |
| 58 m_performanceMonitor->m_handlerName = nullptr; | 59 m_performanceMonitor->m_handlerName = nullptr; |
| 59 m_performanceMonitor->m_handlerAtomicName = AtomicString(); | 60 m_performanceMonitor->m_handlerAtomicName = AtomicString(); |
| 60 } | 61 } |
| 61 } | 62 } |
| 62 | 63 |
| 63 // static | 64 // static |
| 64 void PerformanceMonitor::willExecuteScript(ExecutionContext* context) { | |
| 65 PerformanceMonitor* performanceMonitor = PerformanceMonitor::monitor(context); | |
| 66 if (performanceMonitor) | |
| 67 performanceMonitor->alwaysWillExecuteScript(context); | |
| 68 } | |
| 69 | |
| 70 // static | |
| 71 void PerformanceMonitor::didExecuteScript(ExecutionContext* context) { | |
| 72 PerformanceMonitor* performanceMonitor = PerformanceMonitor::monitor(context); | |
| 73 if (performanceMonitor) | |
| 74 performanceMonitor->alwaysDidExecuteScript(); | |
| 75 } | |
| 76 | |
| 77 // static | |
| 78 void PerformanceMonitor::willCallFunction(ExecutionContext* context) { | |
| 79 PerformanceMonitor* performanceMonitor = PerformanceMonitor::monitor(context); | |
| 80 if (performanceMonitor) | |
| 81 performanceMonitor->alwaysWillCallFunction(context); | |
| 82 } | |
| 83 | |
| 84 // static | |
| 85 void PerformanceMonitor::didCallFunction(ExecutionContext* context, | |
| 86 v8::Local<v8::Function> function) { | |
| 87 PerformanceMonitor* performanceMonitor = PerformanceMonitor::monitor(context); | |
| 88 if (performanceMonitor) | |
| 89 performanceMonitor->alwaysDidCallFunction(context, function); | |
| 90 } | |
| 91 | |
| 92 // static | |
| 93 void PerformanceMonitor::willUpdateLayout(Document* document) { | |
| 94 PerformanceMonitor* performanceMonitor = | |
| 95 PerformanceMonitor::instrumentingMonitor(document); | |
| 96 if (performanceMonitor) | |
| 97 performanceMonitor->willUpdateLayout(); | |
| 98 } | |
| 99 | |
| 100 // static | |
| 101 void PerformanceMonitor::didUpdateLayout(Document* document) { | |
| 102 PerformanceMonitor* performanceMonitor = | |
| 103 PerformanceMonitor::instrumentingMonitor(document); | |
| 104 if (performanceMonitor) | |
| 105 performanceMonitor->didUpdateLayout(); | |
| 106 } | |
| 107 | |
| 108 // static | |
| 109 void PerformanceMonitor::willRecalculateStyle(Document* document) { | |
| 110 PerformanceMonitor* performanceMonitor = | |
| 111 PerformanceMonitor::instrumentingMonitor(document); | |
| 112 if (performanceMonitor) | |
| 113 performanceMonitor->willRecalculateStyle(); | |
| 114 } | |
| 115 | |
| 116 // static | |
| 117 void PerformanceMonitor::didRecalculateStyle(Document* document) { | |
| 118 PerformanceMonitor* performanceMonitor = | |
| 119 PerformanceMonitor::instrumentingMonitor(document); | |
| 120 if (performanceMonitor) | |
| 121 performanceMonitor->didRecalculateStyle(); | |
| 122 } | |
| 123 | |
| 124 // static | |
| 125 void PerformanceMonitor::documentWriteFetchScript(Document* document) { | |
| 126 PerformanceMonitor* performanceMonitor = | |
| 127 PerformanceMonitor::instrumentingMonitor(document); | |
| 128 if (!performanceMonitor) | |
| 129 return; | |
| 130 String text = "Parser was blocked due to document.write(<script>)"; | |
| 131 performanceMonitor->innerReportGenericViolation(document, kBlockedParser, | |
| 132 text, 0, nullptr); | |
| 133 } | |
| 134 | |
| 135 // static | |
| 136 double PerformanceMonitor::threshold(ExecutionContext* context, | 65 double PerformanceMonitor::threshold(ExecutionContext* context, |
| 137 Violation violation) { | 66 Violation violation) { |
| 138 PerformanceMonitor* monitor = | 67 PerformanceMonitor* monitor = |
| 139 PerformanceMonitor::instrumentingMonitor(context); | 68 PerformanceMonitor::instrumentingMonitor(context); |
| 140 return monitor ? monitor->m_thresholds[violation] : 0; | 69 return monitor ? monitor->m_thresholds[violation] : 0; |
| 141 } | 70 } |
| 142 | 71 |
| 143 // static | 72 // static |
| 144 void PerformanceMonitor::reportGenericViolation( | 73 void PerformanceMonitor::reportGenericViolation( |
| 145 ExecutionContext* context, | 74 ExecutionContext* context, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 170 PerformanceMonitor* PerformanceMonitor::instrumentingMonitor( | 99 PerformanceMonitor* PerformanceMonitor::instrumentingMonitor( |
| 171 const ExecutionContext* context) { | 100 const ExecutionContext* context) { |
| 172 PerformanceMonitor* monitor = PerformanceMonitor::monitor(context); | 101 PerformanceMonitor* monitor = PerformanceMonitor::monitor(context); |
| 173 return monitor && monitor->m_enabled ? monitor : nullptr; | 102 return monitor && monitor->m_enabled ? monitor : nullptr; |
| 174 } | 103 } |
| 175 | 104 |
| 176 PerformanceMonitor::PerformanceMonitor(LocalFrame* localRoot) | 105 PerformanceMonitor::PerformanceMonitor(LocalFrame* localRoot) |
| 177 : m_localRoot(localRoot) { | 106 : m_localRoot(localRoot) { |
| 178 std::fill(std::begin(m_thresholds), std::end(m_thresholds), 0); | 107 std::fill(std::begin(m_thresholds), std::end(m_thresholds), 0); |
| 179 Platform::current()->currentThread()->addTaskTimeObserver(this); | 108 Platform::current()->currentThread()->addTaskTimeObserver(this); |
| 109 m_localRoot->instrumentingAgents()->addPerformanceMonitor(this); |
| 180 } | 110 } |
| 181 | 111 |
| 182 PerformanceMonitor::~PerformanceMonitor() { | 112 PerformanceMonitor::~PerformanceMonitor() { |
| 183 shutdown(); | 113 DCHECK(!m_localRoot); |
| 184 } | 114 } |
| 185 | 115 |
| 186 void PerformanceMonitor::subscribe(Violation violation, | 116 void PerformanceMonitor::subscribe(Violation violation, |
| 187 double threshold, | 117 double threshold, |
| 188 Client* client) { | 118 Client* client) { |
| 189 DCHECK(violation < kAfterLast); | 119 DCHECK(violation < kAfterLast); |
| 190 ClientThresholds* clientThresholds = m_subscriptions.at(violation); | 120 ClientThresholds* clientThresholds = m_subscriptions.at(violation); |
| 191 if (!clientThresholds) { | 121 if (!clientThresholds) { |
| 192 clientThresholds = new ClientThresholds(); | 122 clientThresholds = new ClientThresholds(); |
| 193 m_subscriptions.set(violation, clientThresholds); | 123 m_subscriptions.set(violation, clientThresholds); |
| 194 } | 124 } |
| 195 clientThresholds->set(client, threshold); | 125 clientThresholds->set(client, threshold); |
| 196 updateInstrumentation(); | 126 updateInstrumentation(); |
| 197 } | 127 } |
| 198 | 128 |
| 199 void PerformanceMonitor::unsubscribeAll(Client* client) { | 129 void PerformanceMonitor::unsubscribeAll(Client* client) { |
| 200 for (const auto& it : m_subscriptions) | 130 for (const auto& it : m_subscriptions) |
| 201 it.value->erase(client); | 131 it.value->erase(client); |
| 202 updateInstrumentation(); | 132 updateInstrumentation(); |
| 203 } | 133 } |
| 204 | 134 |
| 205 void PerformanceMonitor::shutdown() { | 135 void PerformanceMonitor::shutdown() { |
| 136 if (!m_localRoot) |
| 137 return; |
| 206 m_subscriptions.clear(); | 138 m_subscriptions.clear(); |
| 207 updateInstrumentation(); | 139 updateInstrumentation(); |
| 208 Platform::current()->currentThread()->removeTaskTimeObserver(this); | 140 Platform::current()->currentThread()->removeTaskTimeObserver(this); |
| 141 m_localRoot->instrumentingAgents()->removePerformanceMonitor(this); |
| 142 m_localRoot = nullptr; |
| 209 } | 143 } |
| 210 | 144 |
| 211 void PerformanceMonitor::updateInstrumentation() { | 145 void PerformanceMonitor::updateInstrumentation() { |
| 212 std::fill(std::begin(m_thresholds), std::end(m_thresholds), 0); | 146 std::fill(std::begin(m_thresholds), std::end(m_thresholds), 0); |
| 213 | 147 |
| 214 for (const auto& it : m_subscriptions) { | 148 for (const auto& it : m_subscriptions) { |
| 215 Violation violation = static_cast<Violation>(it.key); | 149 Violation violation = static_cast<Violation>(it.key); |
| 216 ClientThresholds* clientThresholds = it.value; | 150 ClientThresholds* clientThresholds = it.value; |
| 217 for (const auto& clientThreshold : *clientThresholds) { | 151 for (const auto& clientThreshold : *clientThresholds) { |
| 218 if (!m_thresholds[violation] || | 152 if (!m_thresholds[violation] || |
| 219 m_thresholds[violation] > clientThreshold.value) | 153 m_thresholds[violation] > clientThreshold.value) |
| 220 m_thresholds[violation] = clientThreshold.value; | 154 m_thresholds[violation] = clientThreshold.value; |
| 221 } | 155 } |
| 222 } | 156 } |
| 223 | 157 |
| 224 m_enabled = std::count(std::begin(m_thresholds), std::end(m_thresholds), 0) < | 158 m_enabled = std::count(std::begin(m_thresholds), std::end(m_thresholds), 0) < |
| 225 static_cast<int>(kAfterLast); | 159 static_cast<int>(kAfterLast); |
| 226 } | 160 } |
| 227 | 161 |
| 228 void PerformanceMonitor::alwaysWillExecuteScript(ExecutionContext* context) { | 162 void PerformanceMonitor::willExecuteScript(ExecutionContext* context) { |
| 229 // Heuristic for minimal frame context attribution: note the frame context | 163 // Heuristic for minimal frame context attribution: note the frame context |
| 230 // for each script execution. When a long task is encountered, | 164 // for each script execution. When a long task is encountered, |
| 231 // if there is only one frame context involved, then report it. | 165 // if there is only one frame context involved, then report it. |
| 232 // Otherwise don't report frame context. | 166 // Otherwise don't report frame context. |
| 233 // NOTE: This heuristic is imperfect and will be improved in V2 API. | 167 // NOTE: This heuristic is imperfect and will be improved in V2 API. |
| 234 // In V2, timing of script execution along with style & layout updates will be | 168 // In V2, timing of script execution along with style & layout updates will be |
| 235 // accounted for detailed and more accurate attribution. | 169 // accounted for detailed and more accurate attribution. |
| 236 ++m_scriptDepth; | 170 ++m_scriptDepth; |
| 237 if (!m_taskExecutionContext) | 171 if (!m_taskExecutionContext) |
| 238 m_taskExecutionContext = context; | 172 m_taskExecutionContext = context; |
| 239 else if (m_taskExecutionContext != context) | 173 else if (m_taskExecutionContext != context) |
| 240 m_taskHasMultipleContexts = true; | 174 m_taskHasMultipleContexts = true; |
| 241 } | 175 } |
| 242 | 176 |
| 243 void PerformanceMonitor::alwaysDidExecuteScript() { | 177 void PerformanceMonitor::didExecuteScript() { |
| 244 --m_scriptDepth; | 178 --m_scriptDepth; |
| 245 } | 179 } |
| 246 | 180 |
| 247 void PerformanceMonitor::alwaysWillCallFunction(ExecutionContext* context) { | 181 void PerformanceMonitor::willCallFunction(ExecutionContext* context) { |
| 248 alwaysWillExecuteScript(context); | 182 willExecuteScript(context); |
| 249 if (!m_enabled) | 183 if (!m_enabled) |
| 250 return; | 184 return; |
| 251 if (m_scriptDepth == 1 && m_thresholds[m_handlerType]) | 185 if (m_scriptDepth == 1 && m_thresholds[m_handlerType]) |
| 252 m_scriptStartTime = WTF::monotonicallyIncreasingTime(); | 186 m_scriptStartTime = WTF::monotonicallyIncreasingTime(); |
| 253 } | 187 } |
| 254 | 188 |
| 255 void PerformanceMonitor::alwaysDidCallFunction( | 189 void PerformanceMonitor::didCallFunction(ExecutionContext* context, |
| 256 ExecutionContext* context, | 190 v8::Local<v8::Function> function) { |
| 257 v8::Local<v8::Function> function) { | 191 didExecuteScript(); |
| 258 alwaysDidExecuteScript(); | |
| 259 if (!m_enabled) | 192 if (!m_enabled) |
| 260 return; | 193 return; |
| 261 if (m_scriptDepth) | 194 if (m_scriptDepth) |
| 262 return; | 195 return; |
| 263 if (m_handlerType == kAfterLast) | 196 if (m_handlerType == kAfterLast) |
| 264 return; | 197 return; |
| 265 double threshold = m_thresholds[m_handlerType]; | 198 double threshold = m_thresholds[m_handlerType]; |
| 266 if (!threshold) | 199 if (!threshold) |
| 267 return; | 200 return; |
| 268 | 201 |
| 269 double time = WTF::monotonicallyIncreasingTime() - m_scriptStartTime; | 202 double time = WTF::monotonicallyIncreasingTime() - m_scriptStartTime; |
| 270 if (time < threshold) | 203 if (time < threshold) |
| 271 return; | 204 return; |
| 272 String name = m_handlerName ? m_handlerName : m_handlerAtomicName; | 205 String name = m_handlerName ? m_handlerName : m_handlerAtomicName; |
| 273 String text = String::format("'%s' handler took %ldms", name.utf8().data(), | 206 String text = String::format("'%s' handler took %ldms", name.utf8().data(), |
| 274 lround(time * 1000)); | 207 lround(time * 1000)); |
| 275 innerReportGenericViolation(context, m_handlerType, text, time, | 208 innerReportGenericViolation(context, m_handlerType, text, time, |
| 276 SourceLocation::fromFunction(function)); | 209 SourceLocation::fromFunction(function)); |
| 277 } | 210 } |
| 278 | 211 |
| 279 void PerformanceMonitor::willUpdateLayout() { | 212 void PerformanceMonitor::willUpdateLayout() { |
| 213 if (!m_enabled) |
| 214 return; |
| 280 if (m_thresholds[kLongLayout] && m_scriptDepth && !m_layoutDepth) | 215 if (m_thresholds[kLongLayout] && m_scriptDepth && !m_layoutDepth) |
| 281 m_layoutStartTime = WTF::monotonicallyIncreasingTime(); | 216 m_layoutStartTime = WTF::monotonicallyIncreasingTime(); |
| 282 ++m_layoutDepth; | 217 ++m_layoutDepth; |
| 283 } | 218 } |
| 284 | 219 |
| 285 void PerformanceMonitor::didUpdateLayout() { | 220 void PerformanceMonitor::didUpdateLayout() { |
| 221 if (!m_enabled) |
| 222 return; |
| 286 --m_layoutDepth; | 223 --m_layoutDepth; |
| 287 if (m_thresholds[kLongLayout] && m_scriptDepth && !m_layoutDepth) { | 224 if (m_thresholds[kLongLayout] && m_scriptDepth && !m_layoutDepth) { |
| 288 m_perTaskStyleAndLayoutTime += | 225 m_perTaskStyleAndLayoutTime += |
| 289 WTF::monotonicallyIncreasingTime() - m_layoutStartTime; | 226 WTF::monotonicallyIncreasingTime() - m_layoutStartTime; |
| 290 } | 227 } |
| 291 } | 228 } |
| 292 | 229 |
| 293 void PerformanceMonitor::willRecalculateStyle() { | 230 void PerformanceMonitor::willRecalculateStyle(Document*) { |
| 231 if (!m_enabled) |
| 232 return; |
| 233 |
| 294 if (m_thresholds[kLongLayout] && m_scriptDepth) | 234 if (m_thresholds[kLongLayout] && m_scriptDepth) |
| 295 m_styleStartTime = WTF::monotonicallyIncreasingTime(); | 235 m_styleStartTime = WTF::monotonicallyIncreasingTime(); |
| 296 } | 236 } |
| 297 | 237 |
| 298 void PerformanceMonitor::didRecalculateStyle() { | 238 void PerformanceMonitor::didRecalculateStyle() { |
| 239 if (!m_enabled) |
| 240 return; |
| 299 if (m_thresholds[kLongLayout] && m_scriptDepth) { | 241 if (m_thresholds[kLongLayout] && m_scriptDepth) { |
| 300 m_perTaskStyleAndLayoutTime += | 242 m_perTaskStyleAndLayoutTime += |
| 301 WTF::monotonicallyIncreasingTime() - m_styleStartTime; | 243 WTF::monotonicallyIncreasingTime() - m_styleStartTime; |
| 302 } | 244 } |
| 303 } | 245 } |
| 304 | 246 |
| 247 void PerformanceMonitor::documentWriteFetchScript(Document* document) { |
| 248 if (!m_enabled) |
| 249 return; |
| 250 String text = "Parser was blocked due to document.write(<script>)"; |
| 251 innerReportGenericViolation(document, kBlockedParser, text, 0, nullptr); |
| 252 } |
| 253 |
| 305 void PerformanceMonitor::willProcessTask(scheduler::TaskQueue*, | 254 void PerformanceMonitor::willProcessTask(scheduler::TaskQueue*, |
| 306 double startTime) { | 255 double startTime) { |
| 307 // Reset m_taskExecutionContext. We don't clear this in didProcessTask | 256 // Reset m_taskExecutionContext. We don't clear this in didProcessTask |
| 308 // as it is needed in ReportTaskTime which occurs after didProcessTask. | 257 // as it is needed in ReportTaskTime which occurs after didProcessTask. |
| 309 m_taskExecutionContext = nullptr; | 258 m_taskExecutionContext = nullptr; |
| 310 m_taskHasMultipleContexts = false; | 259 m_taskHasMultipleContexts = false; |
| 311 | 260 |
| 312 if (!m_enabled) | 261 if (!m_enabled) |
| 313 return; | 262 return; |
| 314 m_scriptDepth = 0; | 263 m_scriptDepth = 0; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 } | 319 } |
| 371 } | 320 } |
| 372 | 321 |
| 373 DEFINE_TRACE(PerformanceMonitor) { | 322 DEFINE_TRACE(PerformanceMonitor) { |
| 374 visitor->trace(m_localRoot); | 323 visitor->trace(m_localRoot); |
| 375 visitor->trace(m_taskExecutionContext); | 324 visitor->trace(m_taskExecutionContext); |
| 376 visitor->trace(m_subscriptions); | 325 visitor->trace(m_subscriptions); |
| 377 } | 326 } |
| 378 | 327 |
| 379 } // namespace blink | 328 } // namespace blink |
| OLD | NEW |