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

Unified Diff: services/resource_coordinator/coordination_unit/tab_cpu_usage_observer.cc

Issue 2925123002: NOCOMMIT PROTOTYPE [GRC] Tab CPU Usage Observer (Closed)
Patch Set: Rebase Created 3 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: services/resource_coordinator/coordination_unit/tab_cpu_usage_observer.cc
diff --git a/services/resource_coordinator/coordination_unit/tab_cpu_usage_observer.cc b/services/resource_coordinator/coordination_unit/tab_cpu_usage_observer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6310507fb4b38a692b800d214acae184873b2d74
--- /dev/null
+++ b/services/resource_coordinator/coordination_unit/tab_cpu_usage_observer.cc
@@ -0,0 +1,192 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/resource_coordinator/coordination_unit/tab_cpu_usage_observer.h"
+
+#include <stdint.h>
+
+#include <ostream>
+#include <utility>
+
+#include "base/values.h"
+#include "services/resource_coordinator/coordination_unit/coordination_unit_impl.h"
+#include "services/resource_coordinator/public/cpp/coordination_unit_id.h"
+#include "services/resource_coordinator/public/interfaces/coordination_unit.mojom.h"
+
+namespace resource_coordinator {
+
+const unsigned int TabObserver::kMaxCPUUsageMeasurementTicks = 3;
+
+TabObserver::TabObserver() : cpu_measurement_ticks_(0u) {}
+
+TabObserver::~TabObserver() = default;
+
+void TabObserver::AttributeCPUUsage(double cpu_usage) {
+ ++cpu_measurement_ticks_;
+}
+
+bool TabObserver::IsObserving() {
+ return !url_.empty() && cpu_measurement_ticks_ < kMaxCPUUsageMeasurementTicks;
+}
+
+void TabObserver::TabURLChanged(
+ const CoordinationUnitImpl* tab_coordination_unit,
+ mojom::PropertyType tab_url_property) {
+ DCHECK(tab_coordination_unit->id().type ==
+ CoordinationUnitType::kWebContents);
+ DCHECK(tab_url_property == mojom::PropertyType::kTabURL);
+
+ base::Value tab_url_value =
+ tab_coordination_unit->GetProperty(tab_url_property);
+ DCHECK(tab_url_value.is_string());
+ url_ = tab_url_value.GetString();
+
+ // Reset ticks
+ cpu_measurement_ticks_ = 0u;
+}
+
+ProcessObserver::ProcessObserver() = default;
+
+ProcessObserver::~ProcessObserver() = default;
+
+void ProcessObserver::RecalculateAttributableTabs(
+ const CoordinationUnitImpl* process_coordination_unit,
+ const CoordinationUnitImpl* frame_coordination_unit) {
+ DCHECK(process_coordination_unit->id().type ==
+ CoordinationUnitType::kProcess);
+ DCHECK(frame_coordination_unit->id().type == CoordinationUnitType::kFrame);
+
+ attributable_tabs_.clear();
+
+ DCHECK(tab_cpu_usage_observer_);
+ std::unordered_map<CoordinationUnitID, TabObserver>&
+ registered_tab_observers = tab_cpu_usage_observer_->tab_observers();
+ // Any WebContents CoordinationUnit that is a parent of any of the
+ // Process's child Frame CoordinationUnit is considered to attributable
+ // for the Process's CPU usage.
+ for (auto* child : process_coordination_unit->children()) {
+ if (child->id().type == CoordinationUnitType::kFrame) {
+ for (auto* frame_parent : child->parents()) {
+ if (frame_parent->id().type == CoordinationUnitType::kWebContents) {
+ // Another frame within a tab may have previously inserted its, so
+ // its acceptable to not check if the insertion was successful.
+ auto tab_observer_it =
+ registered_tab_observers.find(frame_parent->id());
+ DCHECK(tab_observer_it != registered_tab_observers.end());
+ attributable_tabs_.insert(
+ std::make_pair(frame_parent->id(), &tab_observer_it->second));
+ }
+ }
+ }
+ }
+}
+
+void ProcessObserver::NewCPUUsageMeasurement(
+ const CoordinationUnitImpl* process_coordination_unit,
+ mojom::PropertyType process_cpu_usage_property) {
+ DCHECK(process_coordination_unit->id().type ==
+ CoordinationUnitType::kProcess);
+ DCHECK(process_cpu_usage_property == mojom::PropertyType::kProcessCPUUsage);
+
+ if (attributable_tabs_.empty()) {
+ return;
+ }
+
+ base::Value process_cpu_usage_value =
+ process_coordination_unit->GetProperty(process_cpu_usage_property);
+ DCHECK(process_cpu_usage_value.is_double());
+
+ // CPU attribution for multiple tabs within a process is currently naive in
+ // that the measured process CPU utilization is attributed equally amongst the
+ // tabs.
+ double tab_cpu_usage = process_cpu_usage_value.GetDouble() /
+ static_cast<double>(attributable_tabs_.size());
+
+ for (auto& tab_observer : attributable_tabs_) {
+ if (tab_observer.second->IsObserving()) {
+ tab_observer.second->AttributeCPUUsage(tab_cpu_usage);
+ }
+ }
+}
+
+TabCPUUsageObserver::TabCPUUsageObserver() = default;
+
+TabCPUUsageObserver::~TabCPUUsageObserver() = default;
+
+void TabCPUUsageObserver::TabCoordinationUnitCreated(
+ CoordinationUnitImpl* tab_coordination_unit) {
+ DCHECK(!tab_observers_.count(tab_coordination_unit->id()));
+
+ auto& tab_observer = tab_observers_[tab_coordination_unit->id()];
+ tab_observer.SetTabCPUUsageObserver(this);
+
+ tab_coordination_unit->on_property_changed_event_listeners().AddListener(
+ base::Bind(&TabObserver::TabURLChanged, base::Unretained(&tab_observer)),
+ mojom::PropertyType::kTabURL);
+
+ tab_coordination_unit->on_will_be_destroyed_event_listeners().AddListener(
+ base::Bind(&TabCPUUsageObserver::RemoveTabObserver,
+ base::Unretained(this)));
+}
+
+void TabCPUUsageObserver::ProcessCoordinationUnitCreated(
+ CoordinationUnitImpl* process_coordination_unit) {
+ DCHECK(!process_observers_.count(process_coordination_unit->id()));
+ ProcessObserver& process_observer =
+ process_observers_[process_coordination_unit->id()];
+ process_observer.SetTabCPUUsageObserver(this);
+
+ process_coordination_unit->on_add_child_event_listeners().AddListener(
+ base::Bind(&ProcessObserver::RecalculateAttributableTabs,
+ base::Unretained(&process_observer)),
+ CoordinationUnitType::kFrame);
+
+ process_coordination_unit->on_remove_child_event_listeners().AddListener(
+ base::Bind(&ProcessObserver::RecalculateAttributableTabs,
+ base::Unretained(&process_observer)),
+ CoordinationUnitType::kFrame);
+
+ process_coordination_unit->on_property_changed_event_listeners().AddListener(
+ base::Bind(&ProcessObserver::NewCPUUsageMeasurement,
+ base::Unretained(&process_observer)),
+ mojom::PropertyType::kProcessCPUUsage);
Zhen Wang 2017/06/16 22:47:45 I see your point here that one may want to listen
+
+ process_coordination_unit->on_will_be_destroyed_event_listeners().AddListener(
+ base::Bind(&TabCPUUsageObserver::RemoveProcessObserver,
+ base::Unretained(this)));
+}
+
+void TabCPUUsageObserver::CoordinationUnitCreated(
+ CoordinationUnitImpl* coordination_unit) {
+ switch (coordination_unit->id().type) {
+ case CoordinationUnitType::kWebContents:
+ TabCoordinationUnitCreated(coordination_unit);
+ break;
+ case CoordinationUnitType::kProcess:
+ ProcessCoordinationUnitCreated(coordination_unit);
+ break;
+ case CoordinationUnitType::kFrame:
+ break;
+ default:
+ break;
+ }
+
+ if (coordination_unit->id().type != CoordinationUnitType::kProcess) {
+ return;
+ }
+}
+
+void TabCPUUsageObserver::RemoveProcessObserver(
+ const CoordinationUnitImpl* process_coordination_unit) {
+ DCHECK(process_observers_.count(process_coordination_unit->id()));
+ process_observers_.erase(process_coordination_unit->id());
+}
+
+void TabCPUUsageObserver::RemoveTabObserver(
+ const CoordinationUnitImpl* tab_coordination_unit) {
+ DCHECK(tab_observers_.count(tab_coordination_unit->id()));
+ tab_observers_.erase(tab_coordination_unit->id());
+}
+
+} // namespace resource_coordinator

Powered by Google App Engine
This is Rietveld 408576698