Reland "[fuchsia] Publish memory usage details to Inspect."
This reverts commit 85681bfa15eb915b1d3b1d93d5e26306001b2eeb.
Reason for revert: Original CL was reverted speculatively to address Linux test failures, despite only affecting Fuchsia.
Original change's description:
> Revert "[fuchsia] Publish memory usage details to Inspect."
>
> This reverts commit 3fa3172fdddfeff8de140b8b81c1d27d6c14e19e.
>
> Reason for revert: The CL likely caused service_unittests failures.
> https://ci.chromium.org/ui/p/chromium/builders/ci/Linux%20Chromium%20OS%20ASan%20LSan%20Tests%20(1)/40578/test-results
> [ RUN ] TracingObserverProtoTest.AddChromeDumpToTraceIfEnabled_When_TraceLog_Disabled
> FATAL services_unittests[31665:31712]: [sequence_checker.h(136)] Check failed: checker.CalledOnValidSequence(&bound_at).
> #0 0x557c6c97d3db in backtrace /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:4192:13
> #1 0x557c7761a0d9 in base::debug::CollectStackTrace(void**, unsigned long) ./../../base/debug/stack_trace_posix.cc:867:39
> #2 0x557c773a7583 in StackTrace ./../../base/debug/stack_trace.cc:200:12
> #3 0x557c773a7583 in base::debug::StackTrace::StackTrace() ./../../base/debug/stack_trace.cc:197:28
>
>
> Original change's description:
> > [fuchsia] Publish memory usage details to Inspect.
> >
> > Set up a "memory" node published by each web_instance, that will gather
> > details from the instance's processes regarding their memory usage, on-
> > demand.
> >
> > By default this reports the type and Private Memory Footprint of each
> > process. Additional detail can be included, from named allocator-dumps
> > specified in an |allocator-dump-names| argument in the web_instance's
> > config-data.
> >
> > Bug: 1238889
> > Change-Id: Id517c52650653e1a1dd681a721d845d6bd301545
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3094003
> > Commit-Queue: Wez <wez@chromium.org>
> > Auto-Submit: Wez <wez@chromium.org>
> > Reviewed-by: Chris Hamilton <chrisha@chromium.org>
> > Reviewed-by: David Dorwin <ddorwin@chromium.org>
> > Cr-Commit-Position: refs/heads/main@{#914113}
>
> Bug: 1238889
> Change-Id: I4dbc3d2bbc752709c105c4919f7df61ae55fb3cb
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3110459
> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> Owners-Override: Maxim Kolosovskiy <kolos@chromium.org>
> Auto-Submit: Maxim Kolosovskiy <kolos@chromium.org>
> Commit-Queue: Maxim Kolosovskiy <kolos@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#914261}
Bug: 1238889
Change-Id: I4052da8a2849379e24cea6bdc883249bbe579679
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3113669
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Auto-Submit: Wez <wez@chromium.org>
Commit-Queue: Maxim Kolosovskiy <kolos@chromium.org>
Reviewed-by: Maxim Kolosovskiy <kolos@chromium.org>
Owners-Override: Maxim Kolosovskiy <kolos@chromium.org>
Cr-Commit-Position: refs/heads/main@{#914285}
diff --git a/fuchsia/engine/BUILD.gn b/fuchsia/engine/BUILD.gn
index 73af0c3e..96900f8 100644
--- a/fuchsia/engine/BUILD.gn
+++ b/fuchsia/engine/BUILD.gn
@@ -240,6 +240,8 @@
"browser/web_engine_content_browser_client.h",
"browser/web_engine_devtools_controller.cc",
"browser/web_engine_devtools_controller.h",
+ "browser/web_engine_memory_inspector.cc",
+ "browser/web_engine_memory_inspector.h",
"browser/web_engine_net_log_observer.cc",
"browser/web_engine_net_log_observer.h",
"browser/web_engine_permission_delegate.cc",
diff --git a/fuchsia/engine/browser/DEPS b/fuchsia/engine/browser/DEPS
index 8ae2af5..549a52e 100644
--- a/fuchsia/engine/browser/DEPS
+++ b/fuchsia/engine/browser/DEPS
@@ -23,6 +23,7 @@
"+services/media_session/public/mojom",
"+services/metrics/public/cpp/ukm_source_id.h",
"+services/network/public/mojom",
+ "+services/resource_coordinator/public",
"+third_party/blink/public",
"+third_party/openscreen/src",
"+third_party/skia/include/core",
diff --git a/fuchsia/engine/browser/web_engine_browser_main_parts.cc b/fuchsia/engine/browser/web_engine_browser_main_parts.cc
index d04245ef..3b36107 100644
--- a/fuchsia/engine/browser/web_engine_browser_main_parts.cc
+++ b/fuchsia/engine/browser/web_engine_browser_main_parts.cc
@@ -37,6 +37,7 @@
#include "fuchsia/engine/browser/media_resource_provider_service.h"
#include "fuchsia/engine/browser/web_engine_browser_context.h"
#include "fuchsia/engine/browser/web_engine_devtools_controller.h"
+#include "fuchsia/engine/browser/web_engine_memory_inspector.h"
#include "fuchsia/engine/common/cast_streaming.h"
#include "fuchsia/engine/switches.h"
#include "gpu/command_buffer/service/gpu_switches.h"
@@ -127,6 +128,10 @@
base::ComponentContextForProcess());
cr_fuchsia::PublishVersionInfoToInspect(component_inspector_.get());
+ // Add a node providing memory details for this whole web instance.
+ memory_inspector_ =
+ std::make_unique<WebEngineMemoryInspector>(component_inspector_->root());
+
const auto* command_line = base::CommandLine::ForCurrentProcess();
// If Vulkan is not enabled then disable hardware acceleration. Otherwise gpu
diff --git a/fuchsia/engine/browser/web_engine_browser_main_parts.h b/fuchsia/engine/browser/web_engine_browser_main_parts.h
index 8f56326..5e2ff5c 100644
--- a/fuchsia/engine/browser/web_engine_browser_main_parts.h
+++ b/fuchsia/engine/browser/web_engine_browser_main_parts.h
@@ -38,6 +38,7 @@
}
class MediaResourceProviderService;
+class WebEngineMemoryInspector;
class WEB_ENGINE_EXPORT WebEngineBrowserMainParts
: public content::BrowserMainParts {
@@ -87,6 +88,7 @@
// Used to publish diagnostics including the active Contexts and FrameHosts.
std::unique_ptr<sys::ComponentInspector> component_inspector_;
+ std::unique_ptr<WebEngineMemoryInspector> memory_inspector_;
// Browsing contexts for the connected clients.
fidl::BindingSet<fuchsia::web::Context, std::unique_ptr<ContextImpl>>
diff --git a/fuchsia/engine/browser/web_engine_memory_inspector.cc b/fuchsia/engine/browser/web_engine_memory_inspector.cc
new file mode 100644
index 0000000..847e6ddb
--- /dev/null
+++ b/fuchsia/engine/browser/web_engine_memory_inspector.cc
@@ -0,0 +1,146 @@
+// Copyright 2021 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 "fuchsia/engine/browser/web_engine_memory_inspector.h"
+
+#include <lib/fpromise/promise.h>
+#include <lib/inspect/cpp/inspector.h>
+#include <sstream>
+
+#include "base/trace_event/memory_dump_request_args.h"
+#include "fuchsia/base/config_reader.h"
+#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
+
+namespace {
+
+std::vector<std::string> GetAllocatorDumpNamesFromConfig() {
+ const absl::optional<base::Value>& config = cr_fuchsia::LoadPackageConfig();
+ if (!config)
+ return {};
+
+ const base::Value* names_list = config->FindListPath("allocator-dump-names");
+ if (!names_list)
+ return {};
+
+ std::vector<std::string> names;
+ names.reserve(names_list->GetList().size());
+ for (auto& name : names_list->GetList()) {
+ names.push_back(name.GetString());
+ }
+ return names;
+}
+
+// List of allocator dump names to include.
+const std::vector<std::string>& AllocatorDumpNames() {
+ static base::NoDestructor<std::vector<std::string>> allocator_dump_names(
+ GetAllocatorDumpNamesFromConfig());
+ return *allocator_dump_names;
+}
+
+} // namespace
+
+WebEngineMemoryInspector::WebEngineMemoryInspector(inspect::Node& parent_node) {
+ // Loading the allocator dump names from the config involves blocking I/O so
+ // trigger it to be done during construction, before the prohibition on
+ // blocking the main thread is applied.
+ AllocatorDumpNames();
+
+ node_ = parent_node.CreateLazyNode("memory", [this]() {
+ return fpromise::make_promise(fit::bind_member(
+ this, &WebEngineMemoryInspector::ResolveMemoryDumpPromise));
+ });
+}
+
+WebEngineMemoryInspector::~WebEngineMemoryInspector() = default;
+
+fpromise::result<inspect::Inspector>
+WebEngineMemoryInspector::ResolveMemoryDumpPromise(fpromise::context& context) {
+ // If there is a |dump_results_| then resolve the promise with it.
+ if (dump_results_) {
+ auto memory_dump = std::move(dump_results_);
+ return fpromise::ok(*memory_dump);
+ }
+
+ // If MemoryInstrumentation is not initialized then resolve an error.
+ auto* memory_instrumentation =
+ memory_instrumentation::MemoryInstrumentation::GetInstance();
+ if (!memory_instrumentation)
+ return fpromise::error();
+
+ // Request memory usage summaries for all processes, including details for
+ // any configured allocator dumps.
+ auto* coordinator = memory_instrumentation->GetCoordinator();
+ DCHECK(coordinator);
+
+ coordinator->RequestGlobalMemoryDump(
+ base::trace_event::MemoryDumpType::SUMMARY_ONLY,
+ base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND,
+ base::trace_event::MemoryDumpDeterminism::NONE, AllocatorDumpNames(),
+ base::BindOnce(&WebEngineMemoryInspector::OnMemoryDumpComplete,
+ weak_this_.GetWeakPtr(), context.suspend_task()));
+
+ return fpromise::pending();
+}
+
+void WebEngineMemoryInspector::OnMemoryDumpComplete(
+ fpromise::suspended_task task,
+ bool success,
+ memory_instrumentation::mojom::GlobalMemoryDumpPtr raw_dump) {
+ DCHECK(!dump_results_);
+
+ dump_results_ = std::make_unique<inspect::Inspector>();
+
+ // If capture failed then there is no data to report.
+ if (!success || !raw_dump) {
+ task.resume_task();
+ return;
+ }
+
+ for (const auto& process_dump : raw_dump->process_dumps) {
+ auto node = dump_results_->GetRoot().CreateChild(
+ base::NumberToString(process_dump->pid));
+
+ // Include details of each process' role in the web instance.
+ std::ostringstream type;
+ type << process_dump->process_type;
+ node.CreateString("type", type.str(), dump_results_.get());
+
+ const auto service_name = process_dump->service_name;
+ if (service_name) {
+ node.CreateString("service", *service_name, dump_results_.get());
+ }
+
+ // Include the summary of the process' memory usage.
+ const auto& os_dump = process_dump->os_dump;
+ node.CreateUint("resident_kb", os_dump->resident_set_kb,
+ dump_results_.get());
+ node.CreateUint("private_kb", os_dump->private_footprint_kb,
+ dump_results_.get());
+ node.CreateUint("shared_kb", os_dump->shared_footprint_kb,
+ dump_results_.get());
+
+ // If provided, include detail from individual allocators.
+ auto detail_node = node.CreateChild("allocator_dump");
+ if (!process_dump->chrome_allocator_dumps.empty()) {
+ for (auto& it : process_dump->chrome_allocator_dumps) {
+ // Create a node using the allocator dump name.
+ auto allocator_node = detail_node.CreateChild(it.first);
+
+ // Publish the allocator-provided fields into the node.
+ for (auto& field : it.second->numeric_entries) {
+ allocator_node.CreateUint(field.first, field.second,
+ dump_results_.get());
+ }
+
+ dump_results_->emplace(std::move(allocator_node));
+ }
+
+ dump_results_->emplace(std::move(detail_node));
+ }
+
+ dump_results_->emplace(std::move(node));
+ }
+
+ task.resume_task();
+}
diff --git a/fuchsia/engine/browser/web_engine_memory_inspector.h b/fuchsia/engine/browser/web_engine_memory_inspector.h
new file mode 100644
index 0000000..d14523a
--- /dev/null
+++ b/fuchsia/engine/browser/web_engine_memory_inspector.h
@@ -0,0 +1,53 @@
+// Copyright 2021 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 FUCHSIA_ENGINE_BROWSER_WEB_ENGINE_MEMORY_INSPECTOR_H_
+#define FUCHSIA_ENGINE_BROWSER_WEB_ENGINE_MEMORY_INSPECTOR_H_
+
+#include <lib/inspect/cpp/vmo/types.h>
+#include <memory>
+
+#include "base/memory/weak_ptr.h"
+#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
+
+namespace fpromise {
+class context;
+}
+
+// Integrates with MemoryInstrumentation to publish memory details to Inspect
+// on-demand.
+class WebEngineMemoryInspector {
+ public:
+ // Creates a lazily-populated node called "memory" under |parent_node|.
+ explicit WebEngineMemoryInspector(inspect::Node& parent_node);
+ ~WebEngineMemoryInspector();
+
+ private:
+ // Returns the result of attempting to resolve the memory dump promise:
+ // - If the dump is available then the contents are serialized and returned.
+ // - Otherwise the |context| is suspended, a fresh dump requested, and a
+ // pending result returned. The |context| will be resumed only when the
+ // dump request completes.
+ // This is used as a continuation function for promises generated by the
+ // LazyNode's callback.
+ fpromise::result<inspect::Inspector> ResolveMemoryDumpPromise(
+ fpromise::context& context);
+
+ // Handles completion of a memory dump request.
+ void OnMemoryDumpComplete(
+ fpromise::suspended_task task,
+ bool success,
+ memory_instrumentation::mojom::GlobalMemoryDumpPtr raw_dump);
+
+ // Node holding memory usage information.
+ inspect::LazyNode node_;
+
+ // Holds an Inspector populated with data from the memory dump received by
+ // OnMemoryDumpComplete(), until the promise continuation is called.
+ std::unique_ptr<inspect::Inspector> dump_results_;
+
+ const base::WeakPtrFactory<WebEngineMemoryInspector> weak_this_{this};
+};
+
+#endif // FUCHSIA_ENGINE_BROWSER_WEB_ENGINE_MEMORY_INSPECTOR_H_