Commit cd540b30 authored by Joe Mason's avatar Joe Mason Committed by Commit Bot

[PM] Add a lazy mode to V8PerFrameMemoryRequest

R=chrisha

Bug: 1080672
Change-Id: I4b24d1e77e9dcc228d606f6d484127b04ca0dadc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2339219
Commit-Queue: Joe Mason <joenotcharles@chromium.org>
Reviewed-by: default avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: default avatarChris Hamilton <chrisha@chromium.org>
Cr-Commit-Position: refs/heads/master@{#798718}
parent 6695ffa6
......@@ -264,9 +264,8 @@ class V8PerFrameMemoryDecorator
base::Value DescribeFrameNodeData(const FrameNode* node) const override;
base::Value DescribeProcessNodeData(const ProcessNode* node) const override;
// Returns the amount of time to wait between requests for each process.
// Returns a zero TimeDelta if no requests should be made.
base::TimeDelta GetMinTimeBetweenRequestsPerProcess() const;
// Returns the next measurement request that should be scheduled.
V8PerFrameMemoryRequest* GetNextRequest() const;
// Implementation details below this point.
......@@ -288,7 +287,7 @@ class V8PerFrameMemoryDecorator
Graph* graph_ = nullptr;
// List of requests sorted by sample_frequency (lowest first).
// List of requests sorted by min_time_between_requests (lowest first).
std::vector<V8PerFrameMemoryRequest*> measurement_requests_;
SEQUENCE_CHECKER(sequence_checker_);
......@@ -296,25 +295,54 @@ class V8PerFrameMemoryDecorator
class V8PerFrameMemoryRequest {
public:
enum class MeasurementMode {
// Measurements will be taken at the next GC after a request is received.
// If no GC happens within a bounded time an extra GC will be scheduled.
kBounded,
// Measurements will only be taken at the next scheduled GC after a request
// is received.
kLazy,
kDefault = kBounded,
};
// Creates a request but does not start the measurements. Call
// StartMeasurement to add it to the request list.
explicit V8PerFrameMemoryRequest(const base::TimeDelta& sample_frequency);
//
// Measurement requests will be sent repeatedly to each process, with at
// least |min_time_between_requests| (which must be greater than 0) between
// each repetition. The next GC after each request is received will be
// instrumented, which adds some overhead. |mode| determines whether extra
// GC's can be scheduled, which would add even more overhead.
explicit V8PerFrameMemoryRequest(
const base::TimeDelta& min_time_between_requests,
MeasurementMode mode = MeasurementMode::kDefault);
// Creates a request and calls StartMeasurement with the given |graph| and
// |min_time_between_requests|, using the default measurement mode.
V8PerFrameMemoryRequest(const base::TimeDelta& min_time_between_requests,
Graph* graph);
// Creates a request and calls StartMeasurement. This will request
// measurements for all ProcessNode's in |graph| with frequency
// |sample_frequency|.
V8PerFrameMemoryRequest(const base::TimeDelta& sample_frequency,
// Creates a request and calls StartMeasurement with the given |graph|,
// |min_time_between_requests|, and |mode|.
V8PerFrameMemoryRequest(const base::TimeDelta& min_time_between_requests,
MeasurementMode mode,
Graph* graph);
~V8PerFrameMemoryRequest();
V8PerFrameMemoryRequest(const V8PerFrameMemoryRequest&) = delete;
V8PerFrameMemoryRequest& operator=(const V8PerFrameMemoryRequest&) = delete;
const base::TimeDelta& sample_frequency() const { return sample_frequency_; }
const base::TimeDelta& min_time_between_requests() const {
return min_time_between_requests_;
}
MeasurementMode mode() const { return mode_; }
// Requests measurements for all ProcessNode's in |graph| with this object's
// sample frequency. This must only be called once for each
// V8PerFrameMemoryRequest.
// Requests measurements for all ProcessNode's in |graph|. This must only be
// called once for each V8PerFrameMemoryRequest.
void StartMeasurement(Graph* graph);
// Adds/removes an observer.
......@@ -326,10 +354,11 @@ class V8PerFrameMemoryRequest {
// Private constructor for V8PerFrameMemoryRequestAnySeq. Saves
// |off_sequence_request| as a pointer to the off-sequence object that
// triggered the request and starts measurements with frequency
// |sample_frequency|.
// |min_time_between_requests|.
V8PerFrameMemoryRequest(
util::PassKey<V8PerFrameMemoryRequestAnySeq>,
const base::TimeDelta& sample_frequency,
const base::TimeDelta& min_time_between_requests,
MeasurementMode mode,
base::WeakPtr<V8PerFrameMemoryRequestAnySeq> off_sequence_request);
// V8PerFrameMemoryDecorator calls OnDecoratorUnregistered when it is removed
......@@ -343,7 +372,8 @@ class V8PerFrameMemoryRequest {
const ProcessNode* process_node) const;
private:
base::TimeDelta sample_frequency_;
base::TimeDelta min_time_between_requests_;
MeasurementMode mode_;
V8PerFrameMemoryDecorator* decorator_ = nullptr;
base::ObserverList<V8PerFrameMemoryObserver, /*check_empty=*/true> observers_;
......@@ -450,8 +480,11 @@ class V8PerFrameMemoryObserverAnySeq : public base::CheckedObserver {
// Wrapper that can instantiate a V8PerFrameMemoryRequest from any sequence.
class V8PerFrameMemoryRequestAnySeq {
public:
using MeasurementMode = V8PerFrameMemoryRequest::MeasurementMode;
explicit V8PerFrameMemoryRequestAnySeq(
const base::TimeDelta& sample_frequency);
const base::TimeDelta& min_time_between_requests,
MeasurementMode mode = MeasurementMode::kDefault);
~V8PerFrameMemoryRequestAnySeq();
V8PerFrameMemoryRequestAnySeq(const V8PerFrameMemoryRequestAnySeq&) = delete;
......
......@@ -48,6 +48,8 @@ class V8PerFrameMemoryDecorator::ObserverNotifier {
namespace {
using MeasurementMode = V8PerFrameMemoryRequest::MeasurementMode;
using PerFrameUsagePtr = blink::mojom::PerFrameV8MemoryUsageDataPtr;
// Comparator that generates a strict total order of PerFrameUsagePtr's when
......@@ -185,7 +187,7 @@ class NodeAttachedProcessData
void ScheduleNextMeasurement();
private:
void StartMeasurement();
void StartMeasurement(MeasurementMode mode);
void EnsureRemote();
void OnPerFrameV8MemoryUsageData(
blink::mojom::PerProcessV8MemoryUsageDataPtr result);
......@@ -228,10 +230,14 @@ void NodeAttachedProcessData::ScheduleNextMeasurement() {
return;
}
V8PerFrameMemoryRequest* next_request = nullptr;
auto* decorator =
V8PerFrameMemoryDecorator::GetFromGraph(process_node_->GetGraph());
if (!decorator ||
decorator->GetMinTimeBetweenRequestsPerProcess().is_zero()) {
if (decorator) {
next_request = decorator->GetNextRequest();
}
if (!next_request) {
// All measurements have been cancelled, or decorator was removed from
// graph.
state_ = State::kIdle;
......@@ -243,17 +249,20 @@ void NodeAttachedProcessData::ScheduleNextMeasurement() {
state_ = State::kWaiting;
if (last_request_time_.is_null()) {
// This is the first measurement. Perform it immediately.
StartMeasurement();
StartMeasurement(next_request->mode());
return;
}
// TODO(joenotcharles): Make sure kLazy requests can't starve kBounded
// requests.
base::TimeTicks next_request_time =
last_request_time_ + decorator->GetMinTimeBetweenRequestsPerProcess();
timer_.Start(FROM_HERE, next_request_time - base::TimeTicks::Now(), this,
&NodeAttachedProcessData::StartMeasurement);
last_request_time_ + next_request->min_time_between_requests();
timer_.Start(FROM_HERE, next_request_time - base::TimeTicks::Now(),
base::BindOnce(&NodeAttachedProcessData::StartMeasurement,
base::Unretained(this), next_request->mode()));
}
void NodeAttachedProcessData::StartMeasurement() {
void NodeAttachedProcessData::StartMeasurement(MeasurementMode mode) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(state_, State::kWaiting);
state_ = State::kMeasuring;
......@@ -268,7 +277,9 @@ void NodeAttachedProcessData::StartMeasurement() {
// NodeAttachedProcessData when the last V8PerFrameMemoryRequest is deleted,
// which could happen at any time.
resource_usage_reporter_->GetPerFrameV8MemoryUsageData(
blink::mojom::V8PerFrameMemoryReporter::Mode::DEFAULT,
mode == MeasurementMode::kLazy
? blink::mojom::V8PerFrameMemoryReporter::Mode::LAZY
: blink::mojom::V8PerFrameMemoryReporter::Mode::DEFAULT,
base::BindOnce(&NodeAttachedProcessData::OnPerFrameV8MemoryUsageData,
weak_factory_.GetWeakPtr()));
}
......@@ -371,16 +382,25 @@ void SetBindV8PerFrameMemoryReporterCallbackForTesting(
// V8PerFrameMemoryRequest
V8PerFrameMemoryRequest::V8PerFrameMemoryRequest(
const base::TimeDelta& sample_frequency)
: sample_frequency_(sample_frequency) {
DCHECK_GT(sample_frequency_, base::TimeDelta());
const base::TimeDelta& min_time_between_requests,
MeasurementMode mode)
: min_time_between_requests_(min_time_between_requests), mode_(mode) {
DCHECK_GT(min_time_between_requests_, base::TimeDelta());
}
V8PerFrameMemoryRequest::V8PerFrameMemoryRequest(
const base::TimeDelta& min_time_between_requests,
Graph* graph)
: V8PerFrameMemoryRequest(min_time_between_requests,
MeasurementMode::kDefault) {
StartMeasurement(graph);
}
V8PerFrameMemoryRequest::V8PerFrameMemoryRequest(
const base::TimeDelta& sample_frequency,
const base::TimeDelta& min_time_between_requests,
MeasurementMode mode,
Graph* graph)
: sample_frequency_(sample_frequency) {
DCHECK_GT(sample_frequency_, base::TimeDelta());
: V8PerFrameMemoryRequest(min_time_between_requests, mode) {
StartMeasurement(graph);
}
......@@ -388,12 +408,13 @@ V8PerFrameMemoryRequest::V8PerFrameMemoryRequest(
// sequence.
V8PerFrameMemoryRequest::V8PerFrameMemoryRequest(
util::PassKey<V8PerFrameMemoryRequestAnySeq>,
const base::TimeDelta& sample_frequency,
const base::TimeDelta& min_time_between_requests,
MeasurementMode mode,
base::WeakPtr<V8PerFrameMemoryRequestAnySeq> off_sequence_request)
: sample_frequency_(sample_frequency),
off_sequence_request_(std::move(off_sequence_request)),
off_sequence_request_sequence_(base::SequencedTaskRunnerHandle::Get()) {
: V8PerFrameMemoryRequest(min_time_between_requests, mode) {
DETACH_FROM_SEQUENCE(sequence_checker_);
off_sequence_request_ = std::move(off_sequence_request);
off_sequence_request_sequence_ = base::SequencedTaskRunnerHandle::Get();
// Unretained is safe since |this| will be destroyed on the graph sequence.
PerformanceManager::CallOnGraph(
FROM_HERE, base::BindOnce(&V8PerFrameMemoryRequest::StartMeasurement,
......@@ -586,12 +607,10 @@ base::Value V8PerFrameMemoryDecorator::DescribeProcessNodeData(
return dict;
}
base::TimeDelta V8PerFrameMemoryDecorator::GetMinTimeBetweenRequestsPerProcess()
const {
V8PerFrameMemoryRequest* V8PerFrameMemoryDecorator::GetNextRequest() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return measurement_requests_.empty()
? base::TimeDelta()
: measurement_requests_.front()->sample_frequency();
return measurement_requests_.empty() ? nullptr
: measurement_requests_.front();
}
void V8PerFrameMemoryDecorator::AddMeasurementRequest(
......@@ -607,7 +626,14 @@ void V8PerFrameMemoryDecorator::AddMeasurementRequest(
for (std::vector<V8PerFrameMemoryRequest*>::const_iterator it =
measurement_requests_.begin();
it != measurement_requests_.end(); ++it) {
if (request->sample_frequency() < (*it)->sample_frequency()) {
if (request->min_time_between_requests() <
(*it)->min_time_between_requests() ||
// Make sure bounded request sort before lazy requests so that they
// aren't starved.
(request->min_time_between_requests() ==
(*it)->min_time_between_requests() &&
request->mode() ==
V8PerFrameMemoryRequest::MeasurementMode::kBounded)) {
measurement_requests_.insert(it, request);
UpdateProcessMeasurementSchedules();
return;
......@@ -636,8 +662,8 @@ void V8PerFrameMemoryDecorator::UpdateProcessMeasurementSchedules() const {
for (size_t i = 1; i < measurement_requests_.size(); ++i) {
DCHECK(measurement_requests_[i - 1]);
DCHECK(measurement_requests_[i]);
DCHECK_LE(measurement_requests_[i - 1]->sample_frequency(),
measurement_requests_[i]->sample_frequency());
DCHECK_LE(measurement_requests_[i - 1]->min_time_between_requests(),
measurement_requests_[i]->min_time_between_requests());
}
#endif
for (const ProcessNode* node : graph_->GetAllProcessNodes()) {
......@@ -666,7 +692,8 @@ void V8PerFrameMemoryDecorator::NotifyObserversOnMeasurementAvailable(
// V8PerFrameMemoryRequestAnySeq
V8PerFrameMemoryRequestAnySeq::V8PerFrameMemoryRequestAnySeq(
const base::TimeDelta& sample_frequency) {
const base::TimeDelta& min_time_between_requests,
MeasurementMode mode) {
// |request_| must be initialized in the constructor body so that
// |weak_factory_| is completely constructed.
//
......@@ -674,8 +701,8 @@ V8PerFrameMemoryRequestAnySeq::V8PerFrameMemoryRequestAnySeq(
// constructor. After construction the V8PerFrameMemoryRequest must only be
// accessed on the graph sequence.
request_ = base::WrapUnique(new V8PerFrameMemoryRequest(
util::PassKey<V8PerFrameMemoryRequestAnySeq>(), sample_frequency,
weak_factory_.GetWeakPtr()));
util::PassKey<V8PerFrameMemoryRequestAnySeq>(), min_time_between_requests,
mode, weak_factory_.GetWeakPtr()));
}
V8PerFrameMemoryRequestAnySeq::~V8PerFrameMemoryRequestAnySeq() {
......
......@@ -142,8 +142,10 @@ class V8PerFrameMemoryDecoratorTestBase {
MockV8PerFrameMemoryReporter* mock_reporter,
base::RepeatingCallback<void(
MockV8PerFrameMemoryReporter::GetPerFrameV8MemoryUsageDataCallback
callback)> responder) {
EXPECT_CALL(*mock_reporter, GetPerFrameV8MemoryUsageData(_, _))
callback)> responder,
MockV8PerFrameMemoryReporter::Mode expected_mode =
MockV8PerFrameMemoryReporter::Mode::DEFAULT) {
EXPECT_CALL(*mock_reporter, GetPerFrameV8MemoryUsageData(expected_mode, _))
.WillOnce([this, responder](
MockV8PerFrameMemoryReporter::Mode mode,
MockV8PerFrameMemoryReporter::
......@@ -154,29 +156,37 @@ class V8PerFrameMemoryDecoratorTestBase {
}
void ExpectQueryAndReply(MockV8PerFrameMemoryReporter* mock_reporter,
blink::mojom::PerProcessV8MemoryUsageDataPtr data) {
blink::mojom::PerProcessV8MemoryUsageDataPtr data,
MockV8PerFrameMemoryReporter::Mode expected_mode =
MockV8PerFrameMemoryReporter::Mode::DEFAULT) {
ExpectQuery(
mock_reporter,
base::BindRepeating(&V8PerFrameMemoryDecoratorTestBase::ReplyWithData,
base::Unretained(this), base::Passed(&data)));
base::Unretained(this), base::Passed(&data)),
expected_mode);
}
void ExpectQueryAndDelayReply(
MockV8PerFrameMemoryReporter* mock_reporter,
const base::TimeDelta& delay,
blink::mojom::PerProcessV8MemoryUsageDataPtr data) {
blink::mojom::PerProcessV8MemoryUsageDataPtr data,
MockV8PerFrameMemoryReporter::Mode expected_mode =
MockV8PerFrameMemoryReporter::Mode::DEFAULT) {
ExpectQuery(mock_reporter,
base::BindRepeating(
&V8PerFrameMemoryDecoratorTestBase::DelayedReplyWithData,
base::Unretained(this), delay, base::Passed(&data)));
base::Unretained(this), delay, base::Passed(&data)),
expected_mode);
}
void ExpectBindAndRespondToQuery(
MockV8PerFrameMemoryReporter* mock_reporter,
blink::mojom::PerProcessV8MemoryUsageDataPtr data,
RenderProcessHostId expected_process_id = kTestProcessID) {
RenderProcessHostId expected_process_id = kTestProcessID,
MockV8PerFrameMemoryReporter::Mode expected_mode =
MockV8PerFrameMemoryReporter::Mode::DEFAULT) {
// Wrap the move-only |data| in a callback for the expectation below.
ExpectQueryAndReply(mock_reporter, std::move(data));
ExpectQueryAndReply(mock_reporter, std::move(data), expected_mode);
EXPECT_CALL(*this, BindReceiverWithProxyHost(_, _))
.WillOnce(
......@@ -560,6 +570,35 @@ TEST_F(V8PerFrameMemoryDecoratorTest, PerFrameDataIsDistributed) {
->unassociated_v8_bytes_used());
}
TEST_F(V8PerFrameMemoryDecoratorTest, LazyRequests) {
V8PerFrameMemoryRequest lazy_request(
kMinTimeBetweenRequests, V8PerFrameMemoryRequest::MeasurementMode::kLazy,
graph());
MockV8PerFrameMemoryReporter reporter;
{
auto data = blink::mojom::PerProcessV8MemoryUsageData::New();
ExpectBindAndRespondToQuery(&reporter, std::move(data), kTestProcessID,
MockV8PerFrameMemoryReporter::Mode::LAZY);
}
auto process = CreateNode<ProcessNodeImpl>(
content::PROCESS_TYPE_RENDERER,
RenderProcessHostProxy::CreateForTesting(kTestProcessID));
task_env().RunUntilIdle();
testing::Mock::VerifyAndClearExpectations(&reporter);
// Bounded requests should be preferred over lazy requests with the same
// min_time_between_requests.
V8PerFrameMemoryRequest bounded_request(kMinTimeBetweenRequests, graph());
auto* decorator = V8PerFrameMemoryDecorator::GetFromGraph(graph());
ASSERT_TRUE(decorator);
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(decorator->GetNextRequest()->mode(),
V8PerFrameMemoryRequest::MeasurementMode::kBounded);
}
TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsSorted) {
// Create some queries with different sample frequencies.
constexpr base::TimeDelta kShortInterval(kMinTimeBetweenRequests);
......@@ -602,7 +641,9 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsSorted) {
->unassociated_v8_bytes_used());
// Another measurement should be taken after the shortest interval.
EXPECT_EQ(kShortInterval, decorator->GetMinTimeBetweenRequestsPerProcess());
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(kShortInterval,
decorator->GetNextRequest()->min_time_between_requests());
{
auto data = blink::mojom::PerProcessV8MemoryUsageData::New();
data->unassociated_bytes_used = 2U;
......@@ -616,7 +657,9 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsSorted) {
// Remove the shortest request. Now a measurement should be taken after the
// medium interval, which is twice the short interval.
short_memory_request.reset();
EXPECT_EQ(kMediumInterval, decorator->GetMinTimeBetweenRequestsPerProcess());
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(kMediumInterval,
decorator->GetNextRequest()->min_time_between_requests());
{
auto data = blink::mojom::PerProcessV8MemoryUsageData::New();
data->unassociated_bytes_used = 3U;
......@@ -633,7 +676,9 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsSorted) {
// Remove the longest request. A measurement should still be taken after the
// medium interval.
long_memory_request.reset();
EXPECT_EQ(kMediumInterval, decorator->GetMinTimeBetweenRequestsPerProcess());
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(kMediumInterval,
decorator->GetNextRequest()->min_time_between_requests());
{
auto data = blink::mojom::PerProcessV8MemoryUsageData::New();
data->unassociated_bytes_used = 4U;
......@@ -646,7 +691,7 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsSorted) {
// Remove the medium request, making the queue empty.
medium_memory_request.reset();
EXPECT_TRUE(decorator->GetMinTimeBetweenRequestsPerProcess().is_zero());
EXPECT_FALSE(decorator->GetNextRequest());
{
auto data = blink::mojom::PerProcessV8MemoryUsageData::New();
data->unassociated_bytes_used = 5U;
......@@ -661,7 +706,9 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsSorted) {
// the measurement should be taken immediately.
long_memory_request =
std::make_unique<V8PerFrameMemoryRequest>(kLongInterval, graph());
EXPECT_EQ(kLongInterval, decorator->GetMinTimeBetweenRequestsPerProcess());
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(kLongInterval,
decorator->GetNextRequest()->min_time_between_requests());
task_env().FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(5U, V8PerFrameMemoryProcessData::ForProcessNode(process.get())
......@@ -682,7 +729,9 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsSorted) {
// measurement and the old interval should not).
medium_memory_request =
std::make_unique<V8PerFrameMemoryRequest>(kMediumInterval, graph());
EXPECT_EQ(kMediumInterval, decorator->GetMinTimeBetweenRequestsPerProcess());
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(kMediumInterval,
decorator->GetNextRequest()->min_time_between_requests());
{
auto data = blink::mojom::PerProcessV8MemoryUsageData::New();
......@@ -713,10 +762,14 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsSorted) {
// Remove the medium request and add it back. The measurement interval should
// not change.
medium_memory_request.reset();
EXPECT_EQ(kLongInterval, decorator->GetMinTimeBetweenRequestsPerProcess());
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(kLongInterval,
decorator->GetNextRequest()->min_time_between_requests());
medium_memory_request =
std::make_unique<V8PerFrameMemoryRequest>(kMediumInterval, graph());
EXPECT_EQ(kMediumInterval, decorator->GetMinTimeBetweenRequestsPerProcess());
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(kMediumInterval,
decorator->GetNextRequest()->min_time_between_requests());
{
auto data = blink::mojom::PerProcessV8MemoryUsageData::New();
......@@ -732,7 +785,9 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsSorted) {
// interval.
auto long_memory_request2 =
std::make_unique<V8PerFrameMemoryRequest>(kLongInterval, graph());
EXPECT_EQ(kMediumInterval, decorator->GetMinTimeBetweenRequestsPerProcess());
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(kMediumInterval,
decorator->GetNextRequest()->min_time_between_requests());
{
auto data = blink::mojom::PerProcessV8MemoryUsageData::New();
......@@ -747,7 +802,9 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsSorted) {
// Remove the medium request. Now there are 2 requests which should cause
// measurements at the same interval. Make sure only 1 measurement is taken.
medium_memory_request.reset();
EXPECT_EQ(kLongInterval, decorator->GetMinTimeBetweenRequestsPerProcess());
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(kLongInterval,
decorator->GetNextRequest()->min_time_between_requests());
{
auto data = blink::mojom::PerProcessV8MemoryUsageData::New();
......@@ -761,7 +818,9 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsSorted) {
// Remove 1 of the 2 long requests. Measurements should not change.
long_memory_request2.reset();
EXPECT_EQ(kLongInterval, decorator->GetMinTimeBetweenRequestsPerProcess());
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(kLongInterval,
decorator->GetNextRequest()->min_time_between_requests());
{
auto data = blink::mojom::PerProcessV8MemoryUsageData::New();
......@@ -806,8 +865,8 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsWithDelay) {
// measurement is expected.
// Advance to the middle of a measurement and create a new request. Should
// update GetMinTimeBetweenRequestsPerProcess but not start a new
// measurement until the existing measurement finishes.
// update min_time_between_requests but not start a new measurement until the
// existing measurement finishes.
{
auto data = blink::mojom::PerProcessV8MemoryUsageData::New();
data->unassociated_bytes_used = 1U;
......@@ -824,7 +883,9 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsWithDelay) {
auto medium_memory_request =
std::make_unique<V8PerFrameMemoryRequest>(kMediumInterval, graph());
EXPECT_EQ(kMediumInterval, decorator->GetMinTimeBetweenRequestsPerProcess());
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(kMediumInterval,
decorator->GetNextRequest()->min_time_between_requests());
task_env().FastForwardBy(kMeasurementLength);
ASSERT_EQ(1U, V8PerFrameMemoryProcessData::ForProcessNode(process.get())
->unassociated_v8_bytes_used())
......@@ -871,7 +932,9 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsWithDelay) {
auto short_memory_request =
std::make_unique<V8PerFrameMemoryRequest>(kShortInterval, graph());
EXPECT_EQ(kShortInterval, decorator->GetMinTimeBetweenRequestsPerProcess());
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(kShortInterval,
decorator->GetNextRequest()->min_time_between_requests());
EXPECT_EQ(last_query_time_, measurement_start_time);
{
......@@ -888,11 +951,12 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsWithDelay) {
<< "Measurement ended early";
measurement_start_time = last_query_time_;
// Delete the short request. Should update
// GetMinTimeBetweenRequestsPerProcess but not start a new measurement
// until the existing measurement finishes.
// Delete the short request. Should update min_time_between_requests but not
// start a new measurement until the existing measurement finishes.
short_memory_request.reset();
EXPECT_EQ(kMediumInterval, decorator->GetMinTimeBetweenRequestsPerProcess());
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(kMediumInterval,
decorator->GetNextRequest()->min_time_between_requests());
task_env().FastForwardBy(kMeasurementLength);
EXPECT_EQ(4U, V8PerFrameMemoryProcessData::ForProcessNode(process.get())
->unassociated_v8_bytes_used())
......@@ -917,7 +981,7 @@ TEST_F(V8PerFrameMemoryDecoratorTest, MeasurementRequestsWithDelay) {
medium_memory_request.reset();
long_memory_request.reset();
EXPECT_TRUE(decorator->GetMinTimeBetweenRequestsPerProcess().is_zero());
EXPECT_FALSE(decorator->GetNextRequest());
task_env().FastForwardBy(kMeasurementLength);
EXPECT_EQ(5U, V8PerFrameMemoryProcessData::ForProcessNode(process.get())
->unassociated_v8_bytes_used())
......@@ -1180,8 +1244,9 @@ TEST_F(V8PerFrameMemoryRequestAnySeqTest, RequestIsSequenceSafe) {
FROM_HERE, base::BindOnce([](Graph* graph) {
auto* decorator = V8PerFrameMemoryDecorator::GetFromGraph(graph);
ASSERT_TRUE(decorator);
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(V8PerFrameMemoryDecoratorTest::kMinTimeBetweenRequests,
decorator->GetMinTimeBetweenRequestsPerProcess());
decorator->GetNextRequest()->min_time_between_requests());
}));
// The observer should be invoked on the main sequence when a measurement is
......@@ -1216,9 +1281,11 @@ TEST_F(V8PerFrameMemoryRequestAnySeqTest, RequestIsSequenceSafe) {
// scheduled tasks, which resets the request frequency to zero.
PerformanceManager::CallOnGraph(
FROM_HERE, base::BindOnce([](Graph* graph) {
auto* decorator = V8PerFrameMemoryDecorator::GetFromGraph(graph);
ASSERT_TRUE(decorator);
ASSERT_TRUE(decorator->GetNextRequest());
EXPECT_EQ(V8PerFrameMemoryDecoratorTest::kMinTimeBetweenRequests,
V8PerFrameMemoryDecorator::GetFromGraph(graph)
->GetMinTimeBetweenRequestsPerProcess());
decorator->GetNextRequest()->min_time_between_requests());
}));
// Must remove the observer before destroying the request to avoid a DCHECK
......@@ -1228,9 +1295,9 @@ TEST_F(V8PerFrameMemoryRequestAnySeqTest, RequestIsSequenceSafe) {
PerformanceManager::CallOnGraph(
FROM_HERE, base::BindOnce([](Graph* graph) {
EXPECT_TRUE(V8PerFrameMemoryDecorator::GetFromGraph(graph)
->GetMinTimeBetweenRequestsPerProcess()
.is_zero());
auto* decorator = V8PerFrameMemoryDecorator::GetFromGraph(graph);
ASSERT_TRUE(decorator);
EXPECT_FALSE(decorator->GetNextRequest());
}));
// Execute the above tasks and exit.
......
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