diff options
Diffstat (limited to 'chromium/content/renderer/performance_manager')
3 files changed, 159 insertions, 0 deletions
diff --git a/chromium/content/renderer/performance_manager/OWNERS b/chromium/content/renderer/performance_manager/OWNERS new file mode 100644 index 00000000000..6ef4e6df1e5 --- /dev/null +++ b/chromium/content/renderer/performance_manager/OWNERS @@ -0,0 +1 @@ +file://components/performance_manager/OWNERS diff --git a/chromium/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.cc b/chromium/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.cc new file mode 100644 index 00000000000..2cd2b9dea07 --- /dev/null +++ b/chromium/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.cc @@ -0,0 +1,134 @@ +// Copyright 2020 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 "content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.h" + +#include "base/containers/flat_map.h" +#include "content/public/common/isolated_world_ids.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" +#include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/web/web_local_frame_client.h" +#include "v8/include/v8.h" + +namespace performance_manager { + +namespace { + +class FrameAssociatedMeasurementDelegate : public v8::MeasureMemoryDelegate { + public: + using GetPerFrameV8MemoryUsageDataCallback = + mojom::V8PerFrameMemoryReporter::GetPerFrameV8MemoryUsageDataCallback; + + explicit FrameAssociatedMeasurementDelegate( + GetPerFrameV8MemoryUsageDataCallback&& callback) + : callback_(std::move(callback)) {} + + ~FrameAssociatedMeasurementDelegate() override { + if (callback_) { + std::move(callback_).Run(mojom::PerProcessV8MemoryUsageData::New()); + } + } + + private: + bool ShouldMeasure(v8::Local<v8::Context> context) override { + // Measure all contexts. + return true; + } + + void MeasurementComplete( + const std::vector<std::pair<v8::Local<v8::Context>, size_t>>& + context_sizes_in_bytes, + size_t unattributed_size_in_bytes) override { + mojom::PerProcessV8MemoryUsageDataPtr result = + mojom::PerProcessV8MemoryUsageData::New(); + + result->unassociated_bytes_used = unattributed_size_in_bytes; + + // Keep track of the per-frame data throughout this loop. + base::flat_map<blink::WebLocalFrame*, mojom::PerFrameV8MemoryUsageDataPtr> + frames; + for (const auto& context_and_size : context_sizes_in_bytes) { + const v8::Local<v8::Context>& context = context_and_size.first; + const size_t size = context_and_size.second; + + blink::WebLocalFrame* frame = + blink::WebLocalFrame::FrameForContext(context); + + if (!frame) { + // TODO(crbug.com/1080672): It would be prefereable to count the + // V8SchemaRegistry context's overhead with unassociated_bytes, but at + // present there isn't a public API that allows this distinction. + ++(result->num_unassociated_contexts); + result->unassociated_context_bytes_used += size; + } else { + mojom::PerFrameV8MemoryUsageData* per_frame_resources = + frames[frame].get(); + if (!per_frame_resources) { +#if DCHECK_IS_ON() + // Check that the frame token didn't already occur. + for (const auto& entry : frames) { + // This frame was already added to the map by frames[frame] above. + if (frame == entry.first) + continue; + DCHECK_NE(entry.first->GetFrameToken(), frame->GetFrameToken()); + } +#endif + auto new_resources = mojom::PerFrameV8MemoryUsageData::New(); + new_resources->frame_token = frame->GetFrameToken(); + per_frame_resources = new_resources.get(); + frames[frame] = std::move(new_resources); + } + + mojom::V8IsolatedWorldMemoryUsagePtr isolated_world_usage = + mojom::V8IsolatedWorldMemoryUsage::New(); + isolated_world_usage->bytes_used = size; + int32_t world_id = frame->GetScriptContextWorldId(context); + + if (world_id != content::ISOLATED_WORLD_ID_GLOBAL) { + isolated_world_usage->stable_id = + frame->GetIsolatedWorldStableId(context).Utf8(); + isolated_world_usage->human_readable_name = + frame->GetIsolatedWorldHumanReadableName(context).Utf8(); + } + + DCHECK( + !base::Contains(per_frame_resources->associated_bytes, world_id)); + per_frame_resources->associated_bytes[world_id] = + std::move(isolated_world_usage); + } + } + // Move the per-frame memory values to the result. + for (auto& entry : frames) + result->associated_memory.push_back(std::move(entry.second)); + + std::move(callback_).Run(std::move(result)); + } + + GetPerFrameV8MemoryUsageDataCallback callback_; +}; + +} // namespace + +// static +void V8PerFrameMemoryReporterImpl::Create( + mojo::PendingReceiver<mojom::V8PerFrameMemoryReporter> receiver) { + mojo::MakeSelfOwnedReceiver(std::make_unique<V8PerFrameMemoryReporterImpl>(), + std::move(receiver)); +} + +void V8PerFrameMemoryReporterImpl::GetPerFrameV8MemoryUsageData( + GetPerFrameV8MemoryUsageDataCallback callback) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + if (!isolate) { + std::move(callback).Run(mojom::PerProcessV8MemoryUsageData::New()); + } else { + std::unique_ptr<FrameAssociatedMeasurementDelegate> delegate = + std::make_unique<FrameAssociatedMeasurementDelegate>( + std::move(callback)); + + isolate->MeasureMemory(std::move(delegate)); + } +} + +} // namespace performance_manager diff --git a/chromium/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.h b/chromium/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.h new file mode 100644 index 00000000000..8b67670b5dc --- /dev/null +++ b/chromium/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.h @@ -0,0 +1,24 @@ +// Copyright 2020 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 CONTENT_RENDERER_PERFORMANCE_MANAGER_V8_PER_FRAME_MEMORY_REPORTER_IMPL_H_ +#define CONTENT_RENDERER_PERFORMANCE_MANAGER_V8_PER_FRAME_MEMORY_REPORTER_IMPL_H_ + +#include "content/public/common/performance_manager/v8_per_frame_memory.mojom.h" + +namespace performance_manager { + +// Exposes V8 per-frame associated memory metrics to the browser. +class V8PerFrameMemoryReporterImpl : public mojom::V8PerFrameMemoryReporter { + public: + static void Create( + mojo::PendingReceiver<mojom::V8PerFrameMemoryReporter> receiver); + + void GetPerFrameV8MemoryUsageData( + GetPerFrameV8MemoryUsageDataCallback callback) override; +}; + +} // namespace performance_manager + +#endif // CONTENT_RENDERER_PERFORMANCE_MANAGER_V8_PER_FRAME_MEMORY_REPORTER_IMPL_H_ |