Commit 9fee530e authored by Chris Hamilton's avatar Chris Hamilton Committed by Commit Bot

Create SystemCoordinationUnit.

This acts as a "global" context for resource coordination signals that aren't appropriately aimed at any individual coordination unit. This will be required as part of the CPU and memory usage plumbing and aggregation.

BUG=829575

Change-Id: I5424351924a77c378c49c2d7aca892464a2d5064
Reviewed-on: https://chromium-review.googlesource.com/999017Reviewed-by: default avatarSigurður Ásgeirsson <siggi@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarFadi Meawad <fmeawad@chromium.org>
Commit-Queue: Chris Hamilton <chrisha@chromium.org>
Cr-Commit-Position: refs/heads/master@{#551703}
parent c0802868
...@@ -26,6 +26,8 @@ source_set("lib") { ...@@ -26,6 +26,8 @@ source_set("lib") {
"coordination_unit/page_coordination_unit_impl.h", "coordination_unit/page_coordination_unit_impl.h",
"coordination_unit/process_coordination_unit_impl.cc", "coordination_unit/process_coordination_unit_impl.cc",
"coordination_unit/process_coordination_unit_impl.h", "coordination_unit/process_coordination_unit_impl.h",
"coordination_unit/system_coordination_unit_impl.cc",
"coordination_unit/system_coordination_unit_impl.h",
"memory_instrumentation/coordinator_impl.cc", "memory_instrumentation/coordinator_impl.cc",
"memory_instrumentation/coordinator_impl.h", "memory_instrumentation/coordinator_impl.h",
"memory_instrumentation/graph.cc", "memory_instrumentation/graph.cc",
...@@ -94,6 +96,7 @@ source_set("tests") { ...@@ -94,6 +96,7 @@ source_set("tests") {
"coordination_unit/mock_coordination_unit_graphs.h", "coordination_unit/mock_coordination_unit_graphs.h",
"coordination_unit/page_coordination_unit_impl_unittest.cc", "coordination_unit/page_coordination_unit_impl_unittest.cc",
"coordination_unit/process_coordination_unit_impl_unittest.cc", "coordination_unit/process_coordination_unit_impl_unittest.cc",
"coordination_unit/system_coordination_unit_impl_unittest.cc",
"memory_instrumentation/coordinator_impl_unittest.cc", "memory_instrumentation/coordinator_impl_unittest.cc",
"memory_instrumentation/graph_processor_unittest.cc", "memory_instrumentation/graph_processor_unittest.cc",
"memory_instrumentation/graph_unittest.cc", "memory_instrumentation/graph_unittest.cc",
......
...@@ -6,9 +6,6 @@ ...@@ -6,9 +6,6 @@
#include <unordered_map> #include <unordered_map>
#include "services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h"
#include "services/resource_coordinator/coordination_unit/page_coordination_unit_impl.h"
#include "services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h"
#include "services/resource_coordinator/observers/coordination_unit_graph_observer.h" #include "services/resource_coordinator/observers/coordination_unit_graph_observer.h"
#include "services/resource_coordinator/public/cpp/coordination_unit_id.h" #include "services/resource_coordinator/public/cpp/coordination_unit_id.h"
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "services/resource_coordinator/coordination_unit/coordination_unit_base.h" #include "services/resource_coordinator/coordination_unit/coordination_unit_base.h"
#include "services/resource_coordinator/coordination_unit/coordination_unit_provider_impl.h" #include "services/resource_coordinator/coordination_unit/coordination_unit_provider_impl.h"
#include "services/resource_coordinator/coordination_unit/system_coordination_unit_impl.h"
#include "services/resource_coordinator/observers/coordination_unit_graph_observer.h" #include "services/resource_coordinator/observers/coordination_unit_graph_observer.h"
#include "services/resource_coordinator/public/cpp/coordination_unit_types.h" #include "services/resource_coordinator/public/cpp/coordination_unit_types.h"
#include "services/service_manager/public/cpp/bind_source_info.h" #include "services/service_manager/public/cpp/bind_source_info.h"
...@@ -37,11 +38,18 @@ void CoordinationUnitManager::OnStart( ...@@ -37,11 +38,18 @@ void CoordinationUnitManager::OnStart(
service_manager::BinderRegistryWithArgs< service_manager::BinderRegistryWithArgs<
const service_manager::BindSourceInfo&>* registry, const service_manager::BindSourceInfo&>* registry,
service_manager::ServiceContextRefFactory* service_ref_factory) { service_manager::ServiceContextRefFactory* service_ref_factory) {
// Create the singleton CoordinationUnitProvider.
provider_ = provider_ =
std::make_unique<CoordinationUnitProviderImpl>(service_ref_factory, this); std::make_unique<CoordinationUnitProviderImpl>(service_ref_factory, this);
registry->AddInterface(base::BindRepeating(
&CoordinationUnitProviderImpl::Bind, base::Unretained(provider_.get())));
registry->AddInterface(base::Bind(&CoordinationUnitProviderImpl::Bind, // Create a singleton SystemCU instance. Ownership is taken by
base::Unretained(provider_.get()))); // CoordinationUnitBase. This interface is not directly registered to the
// service, but rather clients can access it via CoordinationUnitProvider.
CoordinationUnitID system_cu_id(CoordinationUnitType::kSystem, std::string());
system_cu_ = SystemCoordinationUnitImpl::Create(
system_cu_id, service_ref_factory->CreateRef());
} }
void CoordinationUnitManager::RegisterObserver( void CoordinationUnitManager::RegisterObserver(
......
...@@ -26,6 +26,7 @@ namespace resource_coordinator { ...@@ -26,6 +26,7 @@ namespace resource_coordinator {
class CoordinationUnitBase; class CoordinationUnitBase;
class CoordinationUnitGraphObserver; class CoordinationUnitGraphObserver;
class CoordinationUnitProviderImpl; class CoordinationUnitProviderImpl;
class SystemCoordinationUnitImpl;
// The CoordinationUnitManager is a singleton that encapsulates all // The CoordinationUnitManager is a singleton that encapsulates all
// aspects of Coordination Units within the resource_coordinator service. // aspects of Coordination Units within the resource_coordinator service.
...@@ -50,6 +51,9 @@ class CoordinationUnitManager { ...@@ -50,6 +51,9 @@ class CoordinationUnitManager {
void OnBeforeCoordinationUnitDestroyed( void OnBeforeCoordinationUnitDestroyed(
CoordinationUnitBase* coordination_unit); CoordinationUnitBase* coordination_unit);
// Returns the singleton SystemCU.
SystemCoordinationUnitImpl* system_cu() const { return system_cu_; }
std::vector<std::unique_ptr<CoordinationUnitGraphObserver>>& std::vector<std::unique_ptr<CoordinationUnitGraphObserver>>&
observers_for_testing() { observers_for_testing() {
return observers_; return observers_;
...@@ -60,6 +64,9 @@ class CoordinationUnitManager { ...@@ -60,6 +64,9 @@ class CoordinationUnitManager {
ukm::UkmRecorder* ukm_recorder_ = nullptr; ukm::UkmRecorder* ukm_recorder_ = nullptr;
std::unique_ptr<CoordinationUnitProviderImpl> provider_; std::unique_ptr<CoordinationUnitProviderImpl> provider_;
// The singleton SystemCU associated with this manager.
SystemCoordinationUnitImpl* system_cu_ = nullptr;
static void Create( static void Create(
service_manager::ServiceContextRefFactory* service_ref_factory); service_manager::ServiceContextRefFactory* service_ref_factory);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h" #include "services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h"
#include "services/resource_coordinator/coordination_unit/page_coordination_unit_impl.h" #include "services/resource_coordinator/coordination_unit/page_coordination_unit_impl.h"
#include "services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h" #include "services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h"
#include "services/resource_coordinator/coordination_unit/system_coordination_unit_impl.h"
#include "services/service_manager/public/cpp/bind_source_info.h" #include "services/service_manager/public/cpp/bind_source_info.h"
#include "services/service_manager/public/cpp/service_context_ref.h" #include "services/service_manager/public/cpp/service_context_ref.h"
...@@ -79,6 +80,12 @@ void CoordinationUnitProviderImpl::CreateProcessCoordinationUnit( ...@@ -79,6 +80,12 @@ void CoordinationUnitProviderImpl::CreateProcessCoordinationUnit(
base::Unretained(this), process_cu)); base::Unretained(this), process_cu));
} }
void CoordinationUnitProviderImpl::GetSystemCoordinationUnit(
resource_coordinator::mojom::SystemCoordinationUnitRequest request) {
// Simply fetch the existing SystemCU and add an additional binding to it.
coordination_unit_manager_->system_cu()->AddBinding(std::move(request));
}
void CoordinationUnitProviderImpl::Bind( void CoordinationUnitProviderImpl::Bind(
resource_coordinator::mojom::CoordinationUnitProviderRequest request, resource_coordinator::mojom::CoordinationUnitProviderRequest request,
const service_manager::BindSourceInfo& source_info) { const service_manager::BindSourceInfo& source_info) {
......
...@@ -44,6 +44,9 @@ class CoordinationUnitProviderImpl : public mojom::CoordinationUnitProvider { ...@@ -44,6 +44,9 @@ class CoordinationUnitProviderImpl : public mojom::CoordinationUnitProvider {
void CreateProcessCoordinationUnit( void CreateProcessCoordinationUnit(
resource_coordinator::mojom::ProcessCoordinationUnitRequest request, resource_coordinator::mojom::ProcessCoordinationUnitRequest request,
const CoordinationUnitID& id) override; const CoordinationUnitID& id) override;
void GetSystemCoordinationUnit(
resource_coordinator::mojom::SystemCoordinationUnitRequest request)
override;
private: private:
service_manager::ServiceContextRefFactory* service_ref_factory_; service_manager::ServiceContextRefFactory* service_ref_factory_;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h" #include "services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h"
#include "services/resource_coordinator/coordination_unit/page_coordination_unit_impl.h" #include "services/resource_coordinator/coordination_unit/page_coordination_unit_impl.h"
#include "services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h" #include "services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h"
#include "services/resource_coordinator/coordination_unit/system_coordination_unit_impl.h"
#include "services/resource_coordinator/public/cpp/coordination_unit_id.h" #include "services/resource_coordinator/public/cpp/coordination_unit_id.h"
#include "services/resource_coordinator/public/cpp/coordination_unit_types.h" #include "services/resource_coordinator/public/cpp/coordination_unit_types.h"
...@@ -21,7 +22,8 @@ namespace resource_coordinator { ...@@ -21,7 +22,8 @@ namespace resource_coordinator {
MockSinglePageInSingleProcessCoordinationUnitGraph:: MockSinglePageInSingleProcessCoordinationUnitGraph::
MockSinglePageInSingleProcessCoordinationUnitGraph() MockSinglePageInSingleProcessCoordinationUnitGraph()
: frame(TestCoordinationUnitWrapper<FrameCoordinationUnitImpl>::Create()), : system(TestCoordinationUnitWrapper<SystemCoordinationUnitImpl>::Create()),
frame(TestCoordinationUnitWrapper<FrameCoordinationUnitImpl>::Create()),
process( process(
TestCoordinationUnitWrapper<ProcessCoordinationUnitImpl>::Create()), TestCoordinationUnitWrapper<ProcessCoordinationUnitImpl>::Create()),
page(TestCoordinationUnitWrapper<PageCoordinationUnitImpl>::Create()) { page(TestCoordinationUnitWrapper<PageCoordinationUnitImpl>::Create()) {
......
...@@ -12,21 +12,23 @@ namespace resource_coordinator { ...@@ -12,21 +12,23 @@ namespace resource_coordinator {
class FrameCoordinationUnitImpl; class FrameCoordinationUnitImpl;
class PageCoordinationUnitImpl; class PageCoordinationUnitImpl;
class ProcessCoordinationUnitImpl; class ProcessCoordinationUnitImpl;
class SystemCoordinationUnitImpl;
// The following coordination unit graph topology is created to emulate a // The following coordination unit graph topology is created to emulate a
// scenario when a single page executes in a single process: // scenario when a single page executes in a single process:
// //
// P' P // Pr Pg
// \ / // \ /
// F // F
// //
// Where: // Where:
// F: frame // F: frame
// P: process // Pr: process
// P': page // Pg: page
struct MockSinglePageInSingleProcessCoordinationUnitGraph { struct MockSinglePageInSingleProcessCoordinationUnitGraph {
MockSinglePageInSingleProcessCoordinationUnitGraph(); MockSinglePageInSingleProcessCoordinationUnitGraph();
~MockSinglePageInSingleProcessCoordinationUnitGraph(); ~MockSinglePageInSingleProcessCoordinationUnitGraph();
TestCoordinationUnitWrapper<SystemCoordinationUnitImpl> system;
TestCoordinationUnitWrapper<FrameCoordinationUnitImpl> frame; TestCoordinationUnitWrapper<FrameCoordinationUnitImpl> frame;
TestCoordinationUnitWrapper<ProcessCoordinationUnitImpl> process; TestCoordinationUnitWrapper<ProcessCoordinationUnitImpl> process;
TestCoordinationUnitWrapper<PageCoordinationUnitImpl> page; TestCoordinationUnitWrapper<PageCoordinationUnitImpl> page;
...@@ -35,16 +37,16 @@ struct MockSinglePageInSingleProcessCoordinationUnitGraph { ...@@ -35,16 +37,16 @@ struct MockSinglePageInSingleProcessCoordinationUnitGraph {
// The following coordination unit graph topology is created to emulate a // The following coordination unit graph topology is created to emulate a
// scenario where multiple pages are executing in a single process: // scenario where multiple pages are executing in a single process:
// //
// P' P OP' // Pg Pr OPg
// \ / \ / // \ / \ /
// F OF // F OF
// //
// Where: // Where:
// F: frame // F: frame
// OF: other_frame // OF: other_frame
// P': page // Pg: page
// OP': other_page // OPg: other_page
// P: process // Pr: process
struct MockMultiplePagesInSingleProcessCoordinationUnitGraph struct MockMultiplePagesInSingleProcessCoordinationUnitGraph
: public MockSinglePageInSingleProcessCoordinationUnitGraph { : public MockSinglePageInSingleProcessCoordinationUnitGraph {
MockMultiplePagesInSingleProcessCoordinationUnitGraph(); MockMultiplePagesInSingleProcessCoordinationUnitGraph();
...@@ -57,18 +59,18 @@ struct MockMultiplePagesInSingleProcessCoordinationUnitGraph ...@@ -57,18 +59,18 @@ struct MockMultiplePagesInSingleProcessCoordinationUnitGraph
// scenario where a single page that has frames is executing in different // scenario where a single page that has frames is executing in different
// processes (e.g. out-of-process iFrames): // processes (e.g. out-of-process iFrames):
// //
// P' P // Pg Pr
// |\ / // |\ /
// | F OP // | F OPr
// | \ / // | \ /
// |__CF // |__CF
// //
// Where: // Where:
// F: frame // F: frame
// CF: chid_frame // CF: child_frame
// P': page // Pg: page
// P: process // Pr: process
// OP: other_process // OPr: other_process
struct MockSinglePageWithMultipleProcessesCoordinationUnitGraph struct MockSinglePageWithMultipleProcessesCoordinationUnitGraph
: public MockSinglePageInSingleProcessCoordinationUnitGraph { : public MockSinglePageInSingleProcessCoordinationUnitGraph {
MockSinglePageWithMultipleProcessesCoordinationUnitGraph(); MockSinglePageWithMultipleProcessesCoordinationUnitGraph();
...@@ -81,9 +83,9 @@ struct MockSinglePageWithMultipleProcessesCoordinationUnitGraph ...@@ -81,9 +83,9 @@ struct MockSinglePageWithMultipleProcessesCoordinationUnitGraph
// scenario where multiple pages are utilizing multiple processes (e.g. // scenario where multiple pages are utilizing multiple processes (e.g.
// out-of-process iFrames and multiple pages in a process): // out-of-process iFrames and multiple pages in a process):
// //
// P' P OP'___ // Pg Pr OPg___
// \ / \ / | // \ / \ / |
// F OF OP | // F OF OPr |
// \ / | // \ / |
// CF___| // CF___|
// //
...@@ -91,10 +93,10 @@ struct MockSinglePageWithMultipleProcessesCoordinationUnitGraph ...@@ -91,10 +93,10 @@ struct MockSinglePageWithMultipleProcessesCoordinationUnitGraph
// F: frame_coordination_unit // F: frame_coordination_unit
// OF: other_frame_coordination_unit // OF: other_frame_coordination_unit
// CF: another_frame_coordination_unit // CF: another_frame_coordination_unit
// P': page_coordination_unit // Pg: page_coordination_unit
// OP': other_page_coordination_unit // OPg: other_page_coordination_unit
// P: process_coordination_unit // Pr: process_coordination_unit
// OP: other_process_coordination_unit // OPr: other_process_coordination_unit
struct MockMultiplePagesWithMultipleProcessesCoordinationUnitGraph struct MockMultiplePagesWithMultipleProcessesCoordinationUnitGraph
: public MockMultiplePagesInSingleProcessCoordinationUnitGraph { : public MockMultiplePagesInSingleProcessCoordinationUnitGraph {
MockMultiplePagesWithMultipleProcessesCoordinationUnitGraph(); MockMultiplePagesWithMultipleProcessesCoordinationUnitGraph();
......
// Copyright 2018 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/system_coordination_unit_impl.h"
#include "base/macros.h"
namespace resource_coordinator {
SystemCoordinationUnitImpl::SystemCoordinationUnitImpl(
const CoordinationUnitID& id,
std::unique_ptr<service_manager::ServiceContextRef> service_ref)
: CoordinationUnitInterface(id, std::move(service_ref)) {}
SystemCoordinationUnitImpl::~SystemCoordinationUnitImpl() = default;
void SystemCoordinationUnitImpl::OnProcessCPUUsageReady() {
SendEvent(mojom::Event::kProcessCPUUsageReady);
}
void SystemCoordinationUnitImpl::OnEventReceived(mojom::Event event) {
for (auto& observer : observers())
observer.OnSystemEventReceived(this, event);
}
void SystemCoordinationUnitImpl::OnPropertyChanged(
mojom::PropertyType property_type,
int64_t value) {
for (auto& observer : observers())
observer.OnSystemPropertyChanged(this, property_type, value);
}
} // namespace resource_coordinator
// Copyright 2018 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.
#ifndef SERVICES_RESOURCE_COORDINATOR_COORDINATION_UNIT_SYSTEM_COORDINATION_UNIT_IMPL_H_
#define SERVICES_RESOURCE_COORDINATOR_COORDINATION_UNIT_SYSTEM_COORDINATION_UNIT_IMPL_H_
#include "base/macros.h"
#include "services/resource_coordinator/coordination_unit/coordination_unit_base.h"
namespace resource_coordinator {
class SystemCoordinationUnitImpl
: public CoordinationUnitInterface<SystemCoordinationUnitImpl,
mojom::SystemCoordinationUnit,
mojom::SystemCoordinationUnitRequest> {
public:
static CoordinationUnitType Type() { return CoordinationUnitType::kSystem; }
SystemCoordinationUnitImpl(
const CoordinationUnitID& id,
std::unique_ptr<service_manager::ServiceContextRef> service_ref);
~SystemCoordinationUnitImpl() override;
// mojom::SystemCoordinationUnit implementation:
void OnProcessCPUUsageReady() override;
private:
// CoordinationUnitInterface implementation:
void OnEventReceived(mojom::Event event) override;
void OnPropertyChanged(mojom::PropertyType property_type,
int64_t value) override;
DISALLOW_COPY_AND_ASSIGN(SystemCoordinationUnitImpl);
};
} // namespace resource_coordinator
#endif // SERVICES_RESOURCE_COORDINATOR_COORDINATION_UNIT_SYSTEM_COORDINATION_UNIT_IMPL_H_
// Copyright 2018 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/system_coordination_unit_impl.h"
#include "base/test/simple_test_tick_clock.h"
#include "services/resource_coordinator/coordination_unit/coordination_unit_test_harness.h"
#include "services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h"
#include "services/resource_coordinator/coordination_unit/mock_coordination_unit_graphs.h"
#include "services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h"
#include "services/resource_coordinator/coordination_unit/system_coordination_unit_impl.h"
#include "services/resource_coordinator/observers/coordination_unit_graph_observer.h"
#include "services/resource_coordinator/resource_coordinator_clock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace resource_coordinator {
namespace {
// Observer used to make sure that signals are dispatched correctly.
class SystemObserver : public CoordinationUnitGraphObserver {
public:
// CoordinationUnitGraphObserver implementation:
bool ShouldObserve(const CoordinationUnitBase* coordination_unit) override {
auto cu_type = coordination_unit->id().type;
return cu_type == CoordinationUnitType::kSystem;
}
void OnSystemEventReceived(const SystemCoordinationUnitImpl* system_cu,
const mojom::Event event) override {
EXPECT_EQ(mojom::Event::kProcessCPUUsageReady, event);
++event_seen_count_;
}
size_t event_seen_count() const { return event_seen_count_; }
private:
size_t event_seen_count_ = 0;
};
class SystemCoordinationUnitImplTest : public CoordinationUnitTestHarness {
public:
void SetUp() override {
ResourceCoordinatorClock::SetClockForTesting(&clock_);
// Sets a valid starting time.
clock_.SetNowTicks(base::TimeTicks::Now());
}
void TearDown() override { ResourceCoordinatorClock::ResetClockForTesting(); }
protected:
void AdvanceClock(base::TimeDelta delta) { clock_.Advance(delta); }
private:
base::SimpleTestTickClock clock_;
};
} // namespace
TEST_F(SystemCoordinationUnitImplTest, OnProcessCPUUsageReady) {
MockSinglePageInSingleProcessCoordinationUnitGraph cu_graph;
SystemObserver observer;
cu_graph.system->AddObserver(&observer);
EXPECT_EQ(0u, observer.event_seen_count());
cu_graph.system->OnProcessCPUUsageReady();
EXPECT_EQ(1u, observer.event_seen_count());
}
} // namespace resource_coordinator
...@@ -15,6 +15,7 @@ class CoordinationUnitManager; ...@@ -15,6 +15,7 @@ class CoordinationUnitManager;
class FrameCoordinationUnitImpl; class FrameCoordinationUnitImpl;
class PageCoordinationUnitImpl; class PageCoordinationUnitImpl;
class ProcessCoordinationUnitImpl; class ProcessCoordinationUnitImpl;
class SystemCoordinationUnitImpl;
// An observer API for the coordination unit graph maintained by GRC. // An observer API for the coordination unit graph maintained by GRC.
// //
...@@ -69,6 +70,12 @@ class CoordinationUnitGraphObserver { ...@@ -69,6 +70,12 @@ class CoordinationUnitGraphObserver {
const mojom::PropertyType property_type, const mojom::PropertyType property_type,
int64_t value) {} int64_t value) {}
// Called whenever a property of the SystemCoordinationUnit is changed.
virtual void OnSystemPropertyChanged(
const SystemCoordinationUnitImpl* system_cu,
const mojom::PropertyType property_type,
int64_t value) {}
// Called whenever an event is received in |coordination_unit| if the // Called whenever an event is received in |coordination_unit| if the
// |coordination_unit| doesn't implement its own EventReceived handler. // |coordination_unit| doesn't implement its own EventReceived handler.
virtual void OnEventReceived(const CoordinationUnitBase* coordination_unit, virtual void OnEventReceived(const CoordinationUnitBase* coordination_unit,
...@@ -80,6 +87,9 @@ class CoordinationUnitGraphObserver { ...@@ -80,6 +87,9 @@ class CoordinationUnitGraphObserver {
virtual void OnProcessEventReceived( virtual void OnProcessEventReceived(
const ProcessCoordinationUnitImpl* process_cu, const ProcessCoordinationUnitImpl* process_cu,
const mojom::Event event) {} const mojom::Event event) {}
virtual void OnSystemEventReceived(
const SystemCoordinationUnitImpl* system_cu,
const mojom::Event event) {}
void set_coordination_unit_manager( void set_coordination_unit_manager(
CoordinationUnitManager* coordination_unit_manager) { CoordinationUnitManager* coordination_unit_manager) {
......
...@@ -42,6 +42,8 @@ component("resource_coordinator_cpp") { ...@@ -42,6 +42,8 @@ component("resource_coordinator_cpp") {
"resource_coordinator_features.cc", "resource_coordinator_features.cc",
"resource_coordinator_features.h", "resource_coordinator_features.h",
"resource_coordinator_interface.h", "resource_coordinator_interface.h",
"system_resource_coordinator.cc",
"system_resource_coordinator.h",
] ]
if (is_android) { if (is_android) {
......
...@@ -18,6 +18,8 @@ EnumTraits<resource_coordinator::mojom::CoordinationUnitType, ...@@ -18,6 +18,8 @@ EnumTraits<resource_coordinator::mojom::CoordinationUnitType,
return resource_coordinator::mojom::CoordinationUnitType::kFrame; return resource_coordinator::mojom::CoordinationUnitType::kFrame;
case resource_coordinator::CoordinationUnitType::kProcess: case resource_coordinator::CoordinationUnitType::kProcess:
return resource_coordinator::mojom::CoordinationUnitType::kProcess; return resource_coordinator::mojom::CoordinationUnitType::kProcess;
case resource_coordinator::CoordinationUnitType::kSystem:
return resource_coordinator::mojom::CoordinationUnitType::kSystem;
default: default:
NOTREACHED() << "Invalid type: " << static_cast<uint8_t>(type); NOTREACHED() << "Invalid type: " << static_cast<uint8_t>(type);
// This should not be reached. Just return a random value. // This should not be reached. Just return a random value.
...@@ -40,6 +42,9 @@ bool EnumTraits<resource_coordinator::mojom::CoordinationUnitType, ...@@ -40,6 +42,9 @@ bool EnumTraits<resource_coordinator::mojom::CoordinationUnitType,
case resource_coordinator::mojom::CoordinationUnitType::kProcess: case resource_coordinator::mojom::CoordinationUnitType::kProcess:
*out = resource_coordinator::CoordinationUnitType::kProcess; *out = resource_coordinator::CoordinationUnitType::kProcess;
break; break;
case resource_coordinator::mojom::CoordinationUnitType::kSystem:
*out = resource_coordinator::CoordinationUnitType::kSystem;
break;
default: default:
NOTREACHED() << "Invalid type: " << static_cast<uint8_t>(input); NOTREACHED() << "Invalid type: " << static_cast<uint8_t>(input);
return false; return false;
......
...@@ -9,13 +9,13 @@ ...@@ -9,13 +9,13 @@
namespace resource_coordinator { namespace resource_coordinator {
// Any new type here needs to be mirrored between coordination_unit_types.h and // Any new type here needs to be mirrored between coordination_unit_types.h and
// coordination_unit.mojom, and have mappings between the two defined in // coordination_unit.mojom.
// coordination_unit_struct_traits.h/.cc
enum class CoordinationUnitType : uint8_t { enum class CoordinationUnitType : uint8_t {
kInvalidType, kInvalidType,
kFrame, kFrame,
kPage, kPage,
kProcess, kProcess,
kSystem,
}; };
} // resource_coordinator } // resource_coordinator
......
...@@ -28,9 +28,21 @@ class ResourceCoordinatorInterface { ...@@ -28,9 +28,21 @@ class ResourceCoordinatorInterface {
service_->AddBinding(std::move(request)); service_->AddBinding(std::move(request));
} }
// Returns the ID. Note that this is meaningless for a singleton CU.
CoordinationUnitID id() const { return cu_id_; } CoordinationUnitID id() const { return cu_id_; }
// Returns the remote endpoint interface.
const CoordinationUnitMojoPtr& service() const { return service_; } const CoordinationUnitMojoPtr& service() const { return service_; }
// Expose the GetID function for testing.
using CoordinationUnitMojo = typename CoordinationUnitMojoPtr::InterfaceType;
using GetIDCallback = typename CoordinationUnitMojo::GetIDCallback;
void GetID(GetIDCallback callback) {
if (!service_)
std::move(callback).Run(cu_id_);
service_->GetID(std::move(callback));
}
protected: protected:
virtual void ConnectToService(mojom::CoordinationUnitProviderPtr& provider, virtual void ConnectToService(mojom::CoordinationUnitProviderPtr& provider,
const CoordinationUnitID& cu_id) = 0; const CoordinationUnitID& cu_id) = 0;
......
// Copyright 2018 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/public/cpp/system_resource_coordinator.h"
namespace resource_coordinator {
SystemResourceCoordinator::SystemResourceCoordinator(
service_manager::Connector* connector)
: ResourceCoordinatorInterface() {
CoordinationUnitID new_cu_id(CoordinationUnitType::kSystem, std::string());
ResourceCoordinatorInterface::ConnectToService(connector, new_cu_id);
}
SystemResourceCoordinator::~SystemResourceCoordinator() = default;
void SystemResourceCoordinator::OnProcessCPUUsageReady() {
if (!service_)
return;
service_->OnProcessCPUUsageReady();
}
void SystemResourceCoordinator::ConnectToService(
mojom::CoordinationUnitProviderPtr& provider,
const CoordinationUnitID& cu_id) {
provider->GetSystemCoordinationUnit(mojo::MakeRequest(&service_));
}
} // namespace resource_coordinator
// Copyright 2018 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.
#ifndef SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_SYSTEM_RESOURCE_COORDINATOR_H_
#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_SYSTEM_RESOURCE_COORDINATOR_H_
#include "services/resource_coordinator/public/cpp/resource_coordinator_interface.h"
#include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h"
namespace resource_coordinator {
class SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_EXPORT SystemResourceCoordinator
: public ResourceCoordinatorInterface<
mojom::SystemCoordinationUnitPtr,
mojom::SystemCoordinationUnitRequest> {
public:
SystemResourceCoordinator(service_manager::Connector* connector);
~SystemResourceCoordinator() override;
void OnProcessCPUUsageReady();
private:
void ConnectToService(mojom::CoordinationUnitProviderPtr& provider,
const CoordinationUnitID& cu_id) override;
DISALLOW_COPY_AND_ASSIGN(SystemResourceCoordinator);
};
} // namespace resource_coordinator
#endif // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_SYSTEM_RESOURCE_COORDINATOR_H_
...@@ -9,11 +9,12 @@ import "services/resource_coordinator/public/mojom/signals.mojom"; ...@@ -9,11 +9,12 @@ import "services/resource_coordinator/public/mojom/signals.mojom";
// Any new type here needs to be mirrored between coordination_unit_types.h and // Any new type here needs to be mirrored between coordination_unit_types.h and
// coordination_unit.mojom, and have mappings between the two defined in // coordination_unit.mojom, and have mappings between the two defined in
// coordination_unit_struct_traits.h/.cc (see comment in coordination_unit_id.h). // coordination_unit_mojom_traits.h/.cc (see comment in coordination_unit_id.h).
enum CoordinationUnitType { enum CoordinationUnitType {
kFrame, kFrame,
kPage, kPage,
kProcess, kProcess,
kSystem,
}; };
struct CoordinationUnitID { struct CoordinationUnitID {
...@@ -84,3 +85,19 @@ interface ProcessCoordinationUnit { ...@@ -84,3 +85,19 @@ interface ProcessCoordinationUnit {
SetMainThreadTaskLoadIsLow(bool main_thread_task_load_is_low); SetMainThreadTaskLoadIsLow(bool main_thread_task_load_is_low);
SetPID(int64 pid); SetPID(int64 pid);
}; };
// There is exactly one SystemCoordinationUnit at all times.
interface SystemCoordinationUnit {
// Gets the ID of this coordination unit.
GetID() => (CoordinationUnitID id);
// Add a new binding to an existing SystemCoordinationUnit.
AddBinding(SystemCoordinationUnit& request);
// Event signals.
// Fired when all ProcessCUs have been adorned with consistent CPU usage
// metrics. This allows for subsequent heuristics to propagate these
// measurements to PageCUs via a heuristic.
OnProcessCPUUsageReady();
};
...@@ -7,7 +7,11 @@ module resource_coordinator.mojom; ...@@ -7,7 +7,11 @@ module resource_coordinator.mojom;
import "services/resource_coordinator/public/mojom/coordination_unit.mojom"; import "services/resource_coordinator/public/mojom/coordination_unit.mojom";
interface CoordinationUnitProvider { interface CoordinationUnitProvider {
// CU factory functions.
CreateFrameCoordinationUnit(FrameCoordinationUnit& request, CoordinationUnitID id); CreateFrameCoordinationUnit(FrameCoordinationUnit& request, CoordinationUnitID id);
CreatePageCoordinationUnit(PageCoordinationUnit& request, CoordinationUnitID id); CreatePageCoordinationUnit(PageCoordinationUnit& request, CoordinationUnitID id);
CreateProcessCoordinationUnit(ProcessCoordinationUnit& request, CoordinationUnitID id); CreateProcessCoordinationUnit(ProcessCoordinationUnit& request, CoordinationUnitID id);
// Retrieves the always existing singleton SystemCU.
GetSystemCoordinationUnit(SystemCoordinationUnit& request);
}; };
...@@ -14,6 +14,9 @@ enum Event { ...@@ -14,6 +14,9 @@ enum Event {
// ServiceWorker are persistent and compatible with LifeCycle. // ServiceWorker are persistent and compatible with LifeCycle.
kNonPersistentNotificationCreated, kNonPersistentNotificationCreated,
kTitleUpdated, kTitleUpdated,
// This signal is sent to a SystemCU when all ProcessCU CPU usage estimates
// have been updated and are coherent.
kProcessCPUUsageReady,
}; };
// Defines the Storage property keys that can be get/set on the // Defines the Storage property keys that can be get/set on the
......
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding.h"
#include "services/resource_coordinator/public/cpp/frame_resource_coordinator.h"
#include "services/resource_coordinator/public/cpp/page_resource_coordinator.h"
#include "services/resource_coordinator/public/cpp/process_resource_coordinator.h"
#include "services/resource_coordinator/public/cpp/system_resource_coordinator.h"
#include "services/resource_coordinator/public/mojom/coordination_unit_provider.mojom.h" #include "services/resource_coordinator/public/mojom/coordination_unit_provider.mojom.h"
#include "services/resource_coordinator/public/mojom/service_constants.mojom.h" #include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
#include "services/service_manager/public/cpp/service.h" #include "services/service_manager/public/cpp/service.h"
...@@ -24,14 +28,37 @@ class ResourceCoordinatorTest : public service_manager::test::ServiceTest { ...@@ -24,14 +28,37 @@ class ResourceCoordinatorTest : public service_manager::test::ServiceTest {
loop_->Quit(); loop_->Quit();
} }
// Given a CU, tests that it works by invoking GetID and waiting for the
// response. This test will hang (and eventually fail) if the response does
// not come back from the remote endpoint.
template <typename CoordinationUnitPtrType>
void TestCUImpl(CoordinationUnitPtrType cu) {
base::RunLoop loop;
loop_ = &loop;
cu->GetID(base::BindOnce(&ResourceCoordinatorTest::GetIDCallback,
base::Unretained(this)));
loop.Run();
loop_ = nullptr;
}
// Variant that works with mojo interface pointers.
template <typename CoordinationUnitPtrType>
void TestCU(CoordinationUnitPtrType& cu) {
TestCUImpl<CoordinationUnitPtrType&>(cu);
}
// Variant that works with pointers to FooResourceCoordinator wrappers.
template <typename CoordinationUnitPtrType>
void TestCU(CoordinationUnitPtrType* cu) {
TestCUImpl<CoordinationUnitPtrType*>(cu);
}
protected: protected:
void SetUp() override { void SetUp() override {
service_manager::test::ServiceTest::SetUp(); service_manager::test::ServiceTest::SetUp();
connector()->StartService(mojom::kServiceName); connector()->StartService(mojom::kServiceName);
} }
void SetRunLoopToQuit(base::RunLoop* loop) { loop_ = loop; }
private: private:
base::RunLoop* loop_ = nullptr; base::RunLoop* loop_ = nullptr;
...@@ -39,20 +66,43 @@ class ResourceCoordinatorTest : public service_manager::test::ServiceTest { ...@@ -39,20 +66,43 @@ class ResourceCoordinatorTest : public service_manager::test::ServiceTest {
}; };
TEST_F(ResourceCoordinatorTest, ResourceCoordinatorInstantiate) { TEST_F(ResourceCoordinatorTest, ResourceCoordinatorInstantiate) {
// Get the CU provider interface.
mojom::CoordinationUnitProviderPtr provider; mojom::CoordinationUnitProviderPtr provider;
connector()->BindInterface(mojom::kServiceName, mojo::MakeRequest(&provider)); connector()->BindInterface(mojom::kServiceName, mojo::MakeRequest(&provider));
CoordinationUnitID new_id(CoordinationUnitType::kPage, "test_id"); // Create and test a dummy FrameCU.
mojom::PageCoordinationUnitPtr coordination_unit; CoordinationUnitID frame_id(CoordinationUnitType::kFrame, "");
provider->CreatePageCoordinationUnit(mojo::MakeRequest(&coordination_unit), mojom::FrameCoordinationUnitPtr frame_cu;
new_id); provider->CreateFrameCoordinationUnit(mojo::MakeRequest(&frame_cu), frame_id);
TestCU(frame_cu);
// Create and test a dummy PageCU.
CoordinationUnitID page_id(CoordinationUnitType::kPage, "");
mojom::PageCoordinationUnitPtr page_cu;
provider->CreatePageCoordinationUnit(mojo::MakeRequest(&page_cu), page_id);
TestCU(page_cu);
// Create and test a dummy SystemCU.
mojom::SystemCoordinationUnitPtr system_cu;
provider->GetSystemCoordinationUnit(mojo::MakeRequest(&system_cu));
TestCU(system_cu);
coordination_unit->GetID(base::BindOnce( // Create and test a dummy ProcessCU.
&ResourceCoordinatorTest::GetIDCallback, base::Unretained(this))); CoordinationUnitID process_id(CoordinationUnitType::kProcess, "");
mojom::ProcessCoordinationUnitPtr process_cu;
provider->CreateProcessCoordinationUnit(mojo::MakeRequest(&process_cu),
process_id);
TestCU(process_cu);
base::RunLoop loop; // Also test the convenience headers for creating and communicating with CUs.
SetRunLoopToQuit(&loop); FrameResourceCoordinator frame_rc(connector());
loop.Run(); TestCU(&frame_rc);
PageResourceCoordinator page_rc(connector());
TestCU(&page_rc);
ProcessResourceCoordinator process_rc(connector());
TestCU(&process_rc);
SystemResourceCoordinator system_rc(connector());
TestCU(&system_rc);
} }
} // namespace resource_coordinator } // namespace resource_coordinator
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment