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

Unified Diff: third_party/WebKit/Source/core/frame/PerformanceMonitor.cpp

Issue 2484213003: Convert performance monitor to the subscription model. (Closed)
Patch Set: core export Created 4 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/frame/PerformanceMonitor.cpp
diff --git a/third_party/WebKit/Source/core/frame/PerformanceMonitor.cpp b/third_party/WebKit/Source/core/frame/PerformanceMonitor.cpp
index 79c29beb4a2fbddbb550923788613bd85b9981c0..b4949cedf9d84b798ab425346c4a523a3b09e2b6 100644
--- a/third_party/WebKit/Source/core/frame/PerformanceMonitor.cpp
+++ b/third_party/WebKit/Source/core/frame/PerformanceMonitor.cpp
@@ -5,63 +5,15 @@
#include "core/frame/PerformanceMonitor.h"
#include "bindings/core/v8/SourceLocation.h"
-#include "core/InstrumentingAgents.h"
#include "core/dom/Document.h"
#include "core/dom/ExecutionContext.h"
-#include "core/frame/DOMWindow.h"
#include "core/frame/Frame.h"
-#include "core/frame/FrameConsole.h"
#include "core/frame/LocalFrame.h"
-#include "core/frame/UseCounter.h"
-#include "core/inspector/ConsoleMessage.h"
-#include "core/timing/DOMWindowPerformance.h"
-#include "core/timing/Performance.h"
#include "public/platform/Platform.h"
#include "wtf/CurrentTime.h"
namespace blink {
-namespace {
-static const double kLongTaskThresholdMillis = 50.0;
-static const double kLongTaskWarningThresholdMillis = 150.0;
-
-static const double kSyncLayoutThresholdMillis = 30.0;
-static const double kSyncLayoutWarningThresholdMillis = 60.0;
-
-static const char kUnknownAttribution[] = "unknown";
-static const char kAmbugiousAttribution[] = "multiple-contexts";
-static const char kSameOriginAttribution[] = "same-origin";
-static const char kAncestorAttribution[] = "cross-origin-ancestor";
-static const char kDescendantAttribution[] = "cross-origin-descendant";
-static const char kCrossOriginAttribution[] = "cross-origin-unreachable";
-
-bool canAccessOrigin(Frame* frame1, Frame* frame2) {
- SecurityOrigin* securityOrigin1 =
- frame1->securityContext()->getSecurityOrigin();
- SecurityOrigin* securityOrigin2 =
- frame2->securityContext()->getSecurityOrigin();
- return securityOrigin1->canAccess(securityOrigin2);
-}
-
-} // namespace
-
-// static
-void PerformanceMonitor::performanceObserverAdded(Performance* performance) {
- LocalFrame* frame = performance->frame();
- PerformanceMonitor* monitor = frame->performanceMonitor();
- monitor->m_webPerformanceObservers.add(performance);
- monitor->updateInstrumentation();
-}
-
-// static
-void PerformanceMonitor::performanceObserverRemoved(Performance* performance) {
- LocalFrame* frame = performance->frame();
- DCHECK(frame);
- PerformanceMonitor* monitor = frame->performanceMonitor();
- monitor->m_webPerformanceObservers.remove(performance);
- monitor->updateInstrumentation();
-}
-
// static
void PerformanceMonitor::willExecuteScript(ExecutionContext* context) {
PerformanceMonitor* performanceMonitor =
@@ -111,71 +63,105 @@ void PerformanceMonitor::didRecalculateStyle(Document* document) {
}
// static
-bool PerformanceMonitor::enabled(ExecutionContext* context) {
- return PerformanceMonitor::instrumentingMonitor(context);
-}
-
-// static
-void PerformanceMonitor::logViolation(MessageLevel level,
- ExecutionContext* context,
- const String& messageText) {
- PerformanceMonitor* performanceMonitor =
+double PerformanceMonitor::threshold(ExecutionContext* context,
+ Violation violation) {
+ PerformanceMonitor* monitor =
PerformanceMonitor::instrumentingMonitor(context);
- if (performanceMonitor)
- performanceMonitor->logViolation(level, messageText);
+ return monitor ? monitor->m_thresholds[violation] : 0;
}
// static
-void PerformanceMonitor::logViolation(
- MessageLevel level,
- ExecutionContext* context,
- const String& messageText,
- std::unique_ptr<SourceLocation> location) {
- PerformanceMonitor* performanceMonitor =
+void PerformanceMonitor::reportGenericViolation(ExecutionContext* context,
+ Violation violation,
+ const String& text,
+ double time,
+ SourceLocation* location) {
+ PerformanceMonitor* monitor =
PerformanceMonitor::instrumentingMonitor(context);
- if (performanceMonitor)
- performanceMonitor->logViolation(level, messageText, std::move(location));
+ if (!monitor)
+ return;
+ ClientThresholds* clientThresholds = monitor->m_subscriptions.get(violation);
+ if (!clientThresholds)
+ return;
+ for (const auto& it : *clientThresholds) {
+ if (it.value < time)
+ it.key->reportGenericViolation(violation, text, time, location);
+ }
}
// static
-PerformanceMonitor* PerformanceMonitor::instrumentingMonitor(
- ExecutionContext* context) {
+PerformanceMonitor* PerformanceMonitor::monitor(
+ const ExecutionContext* context) {
if (!context->isDocument())
return nullptr;
LocalFrame* frame = toDocument(context)->frame();
if (!frame)
return nullptr;
- PerformanceMonitor* monitor = frame->performanceMonitor();
- return monitor->m_enabled ? monitor : nullptr;
+ return frame->performanceMonitor();
+}
+
+// static
+PerformanceMonitor* PerformanceMonitor::instrumentingMonitor(
+ const ExecutionContext* context) {
+ PerformanceMonitor* monitor = PerformanceMonitor::monitor(context);
+ return monitor && monitor->m_enabled ? monitor : nullptr;
}
PerformanceMonitor::PerformanceMonitor(LocalFrame* localRoot)
- : m_localRoot(localRoot) {}
+ : m_localRoot(localRoot) {
+ std::fill(std::begin(m_thresholds), std::end(m_thresholds), 0);
+}
PerformanceMonitor::~PerformanceMonitor() {
- m_webPerformanceObservers.clear();
- m_loggingEnabled = false;
+ m_subscriptions.clear();
+ updateInstrumentation();
+}
+
+void PerformanceMonitor::subscribe(Violation violation,
+ double threshold,
+ Client* client) {
+ DCHECK(violation < kAfterLast);
+ ClientThresholds* clientThresholds = m_subscriptions.get(violation);
+ if (!clientThresholds) {
+ clientThresholds = new ClientThresholds();
+ m_subscriptions.set(violation, clientThresholds);
+ }
+ clientThresholds->set(client, threshold);
updateInstrumentation();
}
-void PerformanceMonitor::setLoggingEnabled(bool enabled) {
- m_loggingEnabled = enabled;
+void PerformanceMonitor::unsubscribeAll(Client* client) {
+ for (const auto& it : m_subscriptions)
+ it.value->remove(client);
updateInstrumentation();
}
void PerformanceMonitor::updateInstrumentation() {
- bool shouldEnable = m_loggingEnabled || m_webPerformanceObservers.size();
- if (shouldEnable == m_enabled)
- return;
- if (shouldEnable) {
- UseCounter::count(m_localRoot, UseCounter::LongTaskObserver);
- Platform::current()->currentThread()->addTaskTimeObserver(this);
- Platform::current()->currentThread()->addTaskObserver(this);
- } else {
- Platform::current()->currentThread()->removeTaskTimeObserver(this);
- Platform::current()->currentThread()->removeTaskObserver(this);
+ bool longTaskObserverEnabled = !!m_thresholds[kLongTask];
+ std::fill(std::begin(m_thresholds), std::end(m_thresholds), 0);
+
+ for (const auto& it : m_subscriptions) {
+ Violation violation = static_cast<Violation>(it.key);
+ ClientThresholds* clientThresholds = it.value;
+ for (const auto& clientThreshold : *clientThresholds) {
+ if (!m_thresholds[violation] ||
+ m_thresholds[violation] > clientThreshold.value)
+ m_thresholds[violation] = clientThreshold.value;
+ }
+ }
+
+ if (!m_thresholds[kLongTask] != !longTaskObserverEnabled) {
+ if (m_thresholds[kLongTask]) {
+ Platform::current()->currentThread()->addTaskTimeObserver(this);
+ Platform::current()->currentThread()->addTaskObserver(this);
+ } else {
+ Platform::current()->currentThread()->removeTaskTimeObserver(this);
+ Platform::current()->currentThread()->removeTaskObserver(this);
+ }
}
- m_enabled = shouldEnable;
+
+ m_enabled = std::count(std::begin(m_thresholds), std::end(m_thresholds), 0) <
+ static_cast<int>(kAfterLast);
}
void PerformanceMonitor::innerWillExecuteScript(ExecutionContext* context) {
@@ -227,110 +213,36 @@ void PerformanceMonitor::willProcessTask() {
}
void PerformanceMonitor::didProcessTask() {
- if (m_perTaskStyleAndLayoutTime * 1000 < kSyncLayoutThresholdMillis)
+ double threshold = m_thresholds[kLongLayout];
+ if (!threshold || m_perTaskStyleAndLayoutTime < threshold)
return;
- if (m_loggingEnabled) {
- logViolation(
- m_perTaskStyleAndLayoutTime * 1000 < kSyncLayoutWarningThresholdMillis
- ? InfoMessageLevel
- : WarningMessageLevel,
- String::format("Forced reflow while executing JavaScript took %ldms.",
- lround(m_perTaskStyleAndLayoutTime * 1000)));
+ ClientThresholds* clientThresholds = m_subscriptions.get(kLongLayout);
+ DCHECK(clientThresholds);
+ for (const auto& it : *clientThresholds) {
+ if (it.value < m_perTaskStyleAndLayoutTime)
+ it.key->reportLongLayout(m_perTaskStyleAndLayoutTime);
}
}
void PerformanceMonitor::ReportTaskTime(scheduler::TaskQueue*,
double startTime,
double endTime) {
- double taskTimeMs = (endTime - startTime) * 1000;
- if (taskTimeMs < kLongTaskThresholdMillis)
+ double taskTime = endTime - startTime;
+ if (!m_thresholds[kLongTask] || taskTime < m_thresholds[kLongTask])
return;
- for (Performance* performance : m_webPerformanceObservers) {
- if (!performance->frame())
- continue;
- std::pair<String, DOMWindow*> attribution =
- sanitizedAttribution(m_frameContexts, performance->frame());
- performance->addLongTaskTiming(startTime, endTime, attribution.first,
- attribution.second);
- }
- if (m_loggingEnabled) {
- logViolation(taskTimeMs < kLongTaskWarningThresholdMillis
- ? InfoMessageLevel
- : WarningMessageLevel,
- String::format("Long running JavaScript task took %ldms.",
- lround(taskTimeMs)));
- }
-}
-
-void PerformanceMonitor::logViolation(MessageLevel level,
- const String& messageText) {
- ConsoleMessage* message =
- ConsoleMessage::create(ViolationMessageSource, level, messageText);
- m_localRoot->console().addMessage(message);
-}
-
-void PerformanceMonitor::logViolation(
- MessageLevel level,
- const String& messageText,
- std::unique_ptr<SourceLocation> location) {
- ConsoleMessage* message = ConsoleMessage::create(
- ViolationMessageSource, level, messageText, std::move(location));
- m_localRoot->console().addMessage(message);
-}
-
-/**
- * Report sanitized name based on cross-origin policy.
- * See detailed Security doc here: http://bit.ly/2duD3F7
- */
-std::pair<String, DOMWindow*> PerformanceMonitor::sanitizedAttribution(
- const HeapHashSet<Member<Frame>>& frames,
- Frame* observerFrame) {
- if (frames.size() == 0) {
- // Unable to attribute as no script was involved.
- return std::make_pair(kUnknownAttribution, nullptr);
- }
- if (frames.size() > 1) {
- // Unable to attribute, multiple script execution contents were involved.
- return std::make_pair(kAmbugiousAttribution, nullptr);
- }
- // Exactly one culprit location, attribute based on origin boundary.
- DCHECK_EQ(1u, frames.size());
- Frame* culpritFrame = *frames.begin();
- DCHECK(culpritFrame);
- if (canAccessOrigin(observerFrame, culpritFrame)) {
- // From accessible frames or same origin, return culprit location URL.
- return std::make_pair(kSameOriginAttribution, culpritFrame->domWindow());
- }
- // For cross-origin, if the culprit is the descendant or ancestor of
- // observer then indicate the *closest* cross-origin frame between
- // the observer and the culprit, in the corresponding direction.
- if (culpritFrame->tree().isDescendantOf(observerFrame)) {
- // If the culprit is a descendant of the observer, then walk up the tree
- // from culprit to observer, and report the *last* cross-origin (from
- // observer) frame. If no intermediate cross-origin frame is found, then
- // report the culprit directly.
- Frame* lastCrossOriginFrame = culpritFrame;
- for (Frame* frame = culpritFrame; frame != observerFrame;
- frame = frame->tree().parent()) {
- if (!canAccessOrigin(observerFrame, frame)) {
- lastCrossOriginFrame = frame;
- }
- }
- return std::make_pair(kDescendantAttribution,
- lastCrossOriginFrame->domWindow());
- }
- if (observerFrame->tree().isDescendantOf(culpritFrame)) {
- return std::make_pair(kAncestorAttribution, nullptr);
+ ClientThresholds* clientThresholds = m_subscriptions.get(kLongTask);
+ for (const auto& it : *clientThresholds) {
+ if (it.value < taskTime)
+ it.key->reportLongTask(startTime, endTime, m_frameContexts);
}
- return std::make_pair(kCrossOriginAttribution, nullptr);
}
DEFINE_TRACE(PerformanceMonitor) {
visitor->trace(m_localRoot);
visitor->trace(m_frameContexts);
- visitor->trace(m_webPerformanceObservers);
+ visitor->trace(m_subscriptions);
}
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698