Commit 9e46ab65 authored by Ulan Degenbaev's avatar Ulan Degenbaev Committed by Chromium LUCI CQ

Use WebMemoryAggregator in implementation of performance.measureMemory

Bug: chromium:1085129
Change-Id: Ia0d1968c97542a7ed0455b61aaf2558e9c81272c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2613024Reviewed-by: default avatarJoe Mason <joenotcharles@chromium.org>
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#841087}
parent b37a8e77
...@@ -117,6 +117,7 @@ class GraphFeaturesHelper { ...@@ -117,6 +117,7 @@ class GraphFeaturesHelper {
// browser to work. // browser to work.
constexpr GraphFeaturesHelper& EnableMinimal() { constexpr GraphFeaturesHelper& EnableMinimal() {
EnableExecutionContextRegistry(); EnableExecutionContextRegistry();
EnableV8ContextTracker();
return *this; return *this;
} }
......
...@@ -234,7 +234,7 @@ int WebMemoryTestHarness::GetNextUniqueId() { ...@@ -234,7 +234,7 @@ int WebMemoryTestHarness::GetNextUniqueId() {
} }
FrameNodeImpl* WebMemoryTestHarness::AddFrameNodeImpl( FrameNodeImpl* WebMemoryTestHarness::AddFrameNodeImpl(
std::string url, base::Optional<std::string> url,
int browsing_instance_id, int browsing_instance_id,
Bytes memory_usage, Bytes memory_usage,
FrameNodeImpl* parent, FrameNodeImpl* parent,
...@@ -255,7 +255,9 @@ FrameNodeImpl* WebMemoryTestHarness::AddFrameNodeImpl( ...@@ -255,7 +255,9 @@ FrameNodeImpl* WebMemoryTestHarness::AddFrameNodeImpl(
auto frame = CreateNode<FrameNodeImpl>(process_.get(), page, parent, auto frame = CreateNode<FrameNodeImpl>(process_.get(), page, parent,
frame_tree_node_id, frame_routing_id, frame_tree_node_id, frame_routing_id,
frame_token, browsing_instance_id); frame_token, browsing_instance_id);
frame->OnNavigationCommitted(GURL(url), /*same document*/ true); if (url) {
frame->OnNavigationCommitted(GURL(*url), /*same document*/ true);
}
V8DetailedMemoryExecutionContextData::CreateForTesting(frame.get()) V8DetailedMemoryExecutionContextData::CreateForTesting(frame.get())
->set_v8_bytes_used(memory_usage.bytes); ->set_v8_bytes_used(memory_usage.bytes);
frames_.push_back(std::move(frame)); frames_.push_back(std::move(frame));
......
...@@ -247,7 +247,7 @@ class WebMemoryTestHarness : public GraphTestHarness { ...@@ -247,7 +247,7 @@ class WebMemoryTestHarness : public GraphTestHarness {
} }
// Creates a frame node as if from window.open and adds it to the graph. // Creates a frame node as if from window.open and adds it to the graph.
FrameNodeImpl* AddFrameNodeFromOpener(std::string url, FrameNodeImpl* AddFrameNodeFromOpener(base::Optional<std::string> url,
Bytes bytes, Bytes bytes,
FrameNodeImpl* opener) { FrameNodeImpl* opener) {
return AddFrameNodeImpl(url, kDefaultBrowsingInstanceId, bytes, return AddFrameNodeImpl(url, kDefaultBrowsingInstanceId, bytes,
...@@ -283,7 +283,7 @@ class WebMemoryTestHarness : public GraphTestHarness { ...@@ -283,7 +283,7 @@ class WebMemoryTestHarness : public GraphTestHarness {
// Creates and adds a new frame node to the graph. // Creates and adds a new frame node to the graph.
FrameNodeImpl* AddFrameNodeImpl( FrameNodeImpl* AddFrameNodeImpl(
std::string url, base::Optional<std::string> url,
int browsing_instance_id, int browsing_instance_id,
Bytes bytes, Bytes bytes,
FrameNodeImpl* parent = nullptr, FrameNodeImpl* parent = nullptr,
......
...@@ -106,9 +106,11 @@ WebMemoryAggregator::FindNodeAggregationType(const FrameNode* frame_node) { ...@@ -106,9 +106,11 @@ WebMemoryAggregator::FindNodeAggregationType(const FrameNode* frame_node) {
return NodeAggregationType::kInvisible; return NodeAggregationType::kInvisible;
} }
auto frame_origin = GetOrigin(frame_node);
// If |frame_node| is same-origin to |start_node|, it's an aggregation point. // If |frame_node| is same-origin to |start_node|, it's an aggregation point.
// (This trivially includes the |start_node| itself.) // (This trivially includes the |start_node| itself.)
if (requesting_origin_.IsSameOriginWith(GetOrigin(frame_node))) if (requesting_origin_.IsSameOriginWith(frame_origin))
return NodeAggregationType::kSameOriginAggregationPoint; return NodeAggregationType::kSameOriginAggregationPoint;
DCHECK_NE(frame_node, aggregation_start_node_); DCHECK_NE(frame_node, aggregation_start_node_);
...@@ -116,8 +118,16 @@ WebMemoryAggregator::FindNodeAggregationType(const FrameNode* frame_node) { ...@@ -116,8 +118,16 @@ WebMemoryAggregator::FindNodeAggregationType(const FrameNode* frame_node) {
// a same-origin node, its existence is visible to |start_node| so it's an // a same-origin node, its existence is visible to |start_node| so it's an
// aggregation point. But its current url will be hidden from |start_node|. // aggregation point. But its current url will be hidden from |start_node|.
const FrameNode* parent_node = frame_node->GetParentFrameNode(); const FrameNode* parent_node = frame_node->GetParentFrameNode();
// |frame_node| is a child of |start_node| so must have a parent.
DCHECK(parent_node); if (!parent_node) {
// A cross-origin window opened via window.open gets its own browsing
// context group due to COOP. However, while the window is being loaded it
// belongs to the old browsing context group. In that case the origin is
// opaque.
DCHECK(frame_origin.opaque());
return NodeAggregationType::kInvisible;
}
if (requesting_origin_.IsSameOriginWith(GetOrigin(parent_node))) if (requesting_origin_.IsSameOriginWith(GetOrigin(parent_node)))
return NodeAggregationType::kCrossOriginAggregationPoint; return NodeAggregationType::kCrossOriginAggregationPoint;
......
...@@ -506,6 +506,28 @@ TEST_F(WebMemoryAggregatorTest, AggregateWindowOpener) { ...@@ -506,6 +506,28 @@ TEST_F(WebMemoryAggregatorTest, AggregateWindowOpener) {
} }
} }
TEST_F(WebMemoryAggregatorTest, AggregateProvisionalWindowOpener) {
FrameNodeImpl* main_frame = AddFrameNode("https://example.com/", Bytes{10});
// This creates an openee window with pending navigation which should be
// skipped because it may get its own browsing context group once the
// navigation completes.
FrameNodeImpl* pending_frame =
AddFrameNodeFromOpener(base::nullopt, Bytes{4}, main_frame);
WebMemoryAggregator aggregator(main_frame);
EXPECT_EQ(aggregator.FindNodeAggregationType(pending_frame),
NodeAggregationType::kInvisible);
auto expected_result = CreateExpectedMemoryMeasurement({
ExpectedMemoryBreakdown(10, AttributionScope::kWindow,
"https://example.com/"),
});
auto result = aggregator.AggregateMeasureMemoryResult();
EXPECT_EQ(MeasurementToJSON(result), MeasurementToJSON(expected_result));
}
} // namespace } // namespace
} // namespace v8_memory } // namespace v8_memory
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "components/performance_manager/public/performance_manager.h" #include "components/performance_manager/public/performance_manager.h"
#include "components/performance_manager/public/render_frame_host_proxy.h" #include "components/performance_manager/public/render_frame_host_proxy.h"
#include "components/performance_manager/public/v8_memory/web_memory.h" #include "components/performance_manager/public/v8_memory/web_memory.h"
#include "components/performance_manager/v8_memory/web_memory_aggregator.h"
#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
...@@ -36,46 +37,16 @@ mojom::WebMemoryMeasurementPtr BuildMemoryUsageResult( ...@@ -36,46 +37,16 @@ mojom::WebMemoryMeasurementPtr BuildMemoryUsageResult(
const blink::LocalFrameToken& frame_token, const blink::LocalFrameToken& frame_token,
const ProcessNode* process_node) { const ProcessNode* process_node) {
const auto& frame_nodes = process_node->GetFrameNodes(); const auto& frame_nodes = process_node->GetFrameNodes();
const auto it = std::find_if(frame_nodes.begin(), frame_nodes.end(),
[frame_token](const FrameNode* node) {
return node->GetFrameToken() == frame_token;
});
// Find the frame that made the request. if (it == frame_nodes.end()) {
const FrameNode* requesting_frame = nullptr;
for (auto* frame_node : frame_nodes) {
if (frame_node->GetFrameToken() == frame_token) {
requesting_frame = frame_node;
break;
}
}
if (!requesting_frame) {
// The frame no longer exists. // The frame no longer exists.
return mojom::WebMemoryMeasurement::New(); return mojom::WebMemoryMeasurement::New();
} }
return WebMemoryAggregator(*it).AggregateMeasureMemoryResult();
auto result = mojom::WebMemoryMeasurement::New();
for (const FrameNode* frame_node : frame_nodes) {
if (frame_node->GetBrowsingInstanceId() !=
requesting_frame->GetBrowsingInstanceId()) {
continue;
}
if (frame_node->GetURL().GetOrigin() !=
requesting_frame->GetURL().GetOrigin()) {
continue;
}
auto* data = v8_memory::V8DetailedMemoryExecutionContextData::ForFrameNode(
frame_node);
if (!data) {
continue;
}
auto attribution = mojom::WebMemoryAttribution::New();
attribution->url = frame_node->GetURL().spec();
attribution->scope = mojom::WebMemoryAttribution::Scope::kWindow;
auto entry = mojom::WebMemoryBreakdownEntry::New();
entry->bytes = data->v8_bytes_used();
entry->attribution.push_back(std::move(attribution));
result->breakdown.push_back(std::move(entry));
}
return result;
} }
v8_memory::V8DetailedMemoryRequest::MeasurementMode v8_memory::V8DetailedMemoryRequest::MeasurementMode
...@@ -160,8 +131,6 @@ void WebMemoryMeasurer::MeasureMemory(mojom::WebMemoryMeasurement::Mode mode, ...@@ -160,8 +131,6 @@ void WebMemoryMeasurer::MeasureMemory(mojom::WebMemoryMeasurement::Mode mode,
void WebMemoryMeasurer::MeasurementComplete( void WebMemoryMeasurer::MeasurementComplete(
const ProcessNode* process_node, const ProcessNode* process_node,
const V8DetailedMemoryProcessData*) { const V8DetailedMemoryProcessData*) {
// TODO(crbug.com/1085129): Use WebMemoryAggregator here instead of
// BuildMemoryUsageResult.
std::move(callback_).Run(BuildMemoryUsageResult(frame_token_, process_node)); std::move(callback_).Run(BuildMemoryUsageResult(frame_token_, process_node));
} }
......
...@@ -25,8 +25,6 @@ namespace v8_memory { ...@@ -25,8 +25,6 @@ namespace v8_memory {
// A helper class for implementing WebMeasureMemory(). This manages a request // A helper class for implementing WebMeasureMemory(). This manages a request
// object that sends a V8 detailed memory request to the renderer, and formats // object that sends a V8 detailed memory request to the renderer, and formats
// the result into a mojom::WebMemoryMeasurement. // the result into a mojom::WebMemoryMeasurement.
// TODO(crbug.com/1085129): Extend this to measure all renderers that are
// reachable from the requesting node.
class WebMemoryMeasurer { class WebMemoryMeasurer {
public: public:
using MeasurementCallback = using MeasurementCallback =
......
...@@ -70,9 +70,12 @@ void WebMemoryImplTest::MeasureAndVerify( ...@@ -70,9 +70,12 @@ void WebMemoryImplTest::MeasureAndVerify(
base::flat_map<std::string, Bytes> actual; base::flat_map<std::string, Bytes> actual;
for (const auto& entry : result->breakdown) { for (const auto& entry : result->breakdown) {
EXPECT_EQ(1u, entry->attribution.size()); EXPECT_EQ(1u, entry->attribution.size());
EXPECT_EQ(mojom::WebMemoryAttribution::Scope::kWindow, if (mojom::WebMemoryAttribution::Scope::kWindow ==
entry->attribution[0]->scope); entry->attribution[0]->scope) {
actual[*entry->attribution[0]->url] = Bytes{entry->bytes}; actual[*entry->attribution[0]->url] = Bytes{entry->bytes};
} else {
actual[*entry->attribution[0]->src] = Bytes{entry->bytes};
}
} }
EXPECT_EQ(expected, actual); EXPECT_EQ(expected, actual);
measurement_done = true; measurement_done = true;
...@@ -93,15 +96,17 @@ TEST_F(WebMemoryImplTest, MeasurerIncludesSameOriginRelatedFrames) { ...@@ -93,15 +96,17 @@ TEST_F(WebMemoryImplTest, MeasurerIncludesSameOriginRelatedFrames) {
}); });
} }
// TODO(b/1085129): Currently WebMemoryMeasurer only includes the results for a TEST_F(WebMemoryImplTest, MeasurerIncludesCrossOriginFrames) {
// single process. Once it invokes WebMemoryAggregator, update this test to
// expect cross-origin frames to be included in the aggregation.
TEST_F(WebMemoryImplTest, MeasurerSkipsCrossOriginFrames) {
auto* main = AddFrameNode("http://foo.com", Bytes{10u}); auto* main = AddFrameNode("http://foo.com", Bytes{10u});
AddFrameNode("http://bar.com/iframe", Bytes{20}, main); AddFrameNode("http://bar.com/iframe", Bytes{20}, main, "bar_id",
"http://bar.com/iframe_src");
MeasureAndVerify(main, {{"http://foo.com/", Bytes{10u}}}); MeasureAndVerify(main, {{"http://foo.com/", Bytes{10u}},
{
"http://bar.com/iframe_src",
Bytes{20},
}});
} }
TEST_F(WebMemoryImplTest, MeasurerSkipsCrossBrowserContextGroupFrames) { TEST_F(WebMemoryImplTest, MeasurerSkipsCrossBrowserContextGroupFrames) {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_memory_attribution.h" #include "third_party/blink/renderer/bindings/core/v8/v8_memory_attribution.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_memory_attribution_container.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_memory_breakdown_entry.h" #include "third_party/blink/renderer/bindings/core/v8/v8_memory_breakdown_entry.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_memory_measurement.h" #include "third_party/blink/renderer/bindings/core/v8/v8_memory_measurement.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h"
...@@ -138,12 +139,27 @@ WTF::String ConvertScope(WebMemoryAttribution::Scope scope) { ...@@ -138,12 +139,27 @@ WTF::String ConvertScope(WebMemoryAttribution::Scope scope) {
} }
} }
MemoryAttributionContainer* ConvertContainer(
const WebMemoryAttributionPtr& attribution) {
if (!attribution->src && !attribution->id) {
return nullptr;
}
auto* result = MemoryAttributionContainer::Create();
result->setSrc(attribution->src);
result->setId(attribution->id);
return result;
}
MemoryAttribution* ConvertAttribution( MemoryAttribution* ConvertAttribution(
const WebMemoryAttributionPtr& attribution) { const WebMemoryAttributionPtr& attribution) {
auto* result = MemoryAttribution::Create(); auto* result = MemoryAttribution::Create();
result->setUrl(attribution->url); if (attribution->url) {
result->setUrl(attribution->url);
} else {
result->setUrl("cross-origin-url");
}
result->setScope(ConvertScope(attribution->scope)); result->setScope(ConvertScope(attribution->scope));
result->setContainer(nullptr); result->setContainer(ConvertContainer(attribution));
return result; return result;
} }
......
...@@ -6,6 +6,6 @@ ...@@ -6,6 +6,6 @@
// The attributes of the container iframe element. // The attributes of the container iframe element.
dictionary MemoryAttributionContainer { dictionary MemoryAttributionContainer {
required DOMString id; DOMString id;
required USVString src; USVString src;
}; };
\ No newline at end of file
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