Commit 699ed793 authored by Nicolas Pena's avatar Nicolas Pena Committed by Commit Bot

Add QueueingTimeEstimatorPerfTest

This CL adds a microbenchmark for QueueingTimeEstimator that runs lots
of tasks and computes ExpectedQueueingTime on them. The test is DISABLED
as it takes 6 seconds to run and will only be used manually to compute
improvements.

Bug: 860246
Change-Id: I50d5471ed4628bf144b3da35b66d597ce6eac3c3
Reviewed-on: https://chromium-review.googlesource.com/1126444
Commit-Queue: Nicolás Peña Moreno <npm@chromium.org>
Reviewed-by: default avatarAlexander Timin <altimin@chromium.org>
Reviewed-by: default avatarTimothy Dresser <tdresser@chromium.org>
Cr-Commit-Position: refs/heads/master@{#573012}
parent a294b090
......@@ -151,6 +151,8 @@ jumbo_source_set("test_support") {
"test/lazy_thread_controller_for_test.cc",
"test/lazy_thread_controller_for_test.h",
"test/renderer_scheduler_test_support.cc",
"test/test_queueing_time_estimator_client.cc",
"test/test_queueing_time_estimator_client.h",
]
deps = [
......@@ -218,6 +220,7 @@ source_set("perf_tests") {
sources = [
"base/sequence_manager_perftest.cc",
"test/queueing_time_estimator_perf_test.cc",
]
deps = [
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "testing/gmock/include/gmock/gmock.h"
......@@ -10,6 +11,7 @@
#include "third_party/blink/public/common/page/launching_process_state.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/test/fake_frame_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.h"
#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
#include <map>
......@@ -19,82 +21,13 @@
namespace blink {
namespace scheduler {
using QueueType = MainThreadTaskQueue::QueueType;
namespace {
class TestQueueingTimeEstimatorClient : public QueueingTimeEstimator::Client {
public:
void OnQueueingTimeForWindowEstimated(base::TimeDelta queueing_time,
bool is_disjoint_window) override {
expected_queueing_times_.push_back(queueing_time);
// Mimic RendererSchedulerImpl::OnQueueingTimeForWindowEstimated.
if (is_disjoint_window) {
UMA_HISTOGRAM_TIMES("RendererScheduler.ExpectedTaskQueueingDuration",
queueing_time);
UMA_HISTOGRAM_CUSTOM_COUNTS(
"RendererScheduler.ExpectedTaskQueueingDuration3",
queueing_time.InMicroseconds(),
MainThreadSchedulerImpl::kMinExpectedQueueingTimeBucket,
MainThreadSchedulerImpl::kMaxExpectedQueueingTimeBucket,
MainThreadSchedulerImpl::kNumberExpectedQueueingTimeBuckets);
}
}
void OnReportFineGrainedExpectedQueueingTime(
const char* split_description,
base::TimeDelta queueing_time) override {
if (split_eqts_.find(split_description) == split_eqts_.end())
split_eqts_[split_description] = std::vector<base::TimeDelta>();
split_eqts_[split_description].push_back(queueing_time);
// Mimic MainThreadSchedulerImpl::OnReportFineGrainedExpectedQueueingTime.
base::UmaHistogramCustomCounts(
split_description, queueing_time.InMicroseconds(),
MainThreadSchedulerImpl::kMinExpectedQueueingTimeBucket,
MainThreadSchedulerImpl::kMaxExpectedQueueingTimeBucket,
MainThreadSchedulerImpl::kNumberExpectedQueueingTimeBuckets);
}
const std::vector<base::TimeDelta>& expected_queueing_times() {
return expected_queueing_times_;
}
const std::map<const char*, std::vector<base::TimeDelta>>& split_eqts() {
return split_eqts_;
}
const std::vector<base::TimeDelta>& QueueTypeValues(QueueType queue_type) {
return split_eqts_[QueueingTimeEstimator::Calculator::
GetReportingMessageFromQueueType(queue_type)];
}
const std::vector<base::TimeDelta>& FrameStatusValues(
FrameStatus frame_status) {
return split_eqts_[QueueingTimeEstimator::Calculator::
GetReportingMessageFromFrameStatus(frame_status)];
}
private:
std::vector<base::TimeDelta> expected_queueing_times_;
std::map<const char*, std::vector<base::TimeDelta>> split_eqts_;
};
class QueueingTimeEstimatorForTest : public QueueingTimeEstimator {
public:
QueueingTimeEstimatorForTest(TestQueueingTimeEstimatorClient* client,
base::TimeDelta window_duration,
int steps_per_window,
base::TimeTicks time)
: QueueingTimeEstimator(client, window_duration, steps_per_window) {
// If initial state is not foregrounded, foreground.
if (kLaunchingProcessIsBackgrounded) {
this->OnRendererStateChanged(false, time);
}
}
};
struct BucketExpectation {
int sample;
int count;
};
} // namespace
class QueueingTimeEstimatorTest : public testing::Test {
protected:
static std::vector<BucketExpectation> GetFineGrained(
......@@ -139,6 +72,8 @@ class QueueingTimeEstimatorTest : public testing::Test {
TestQueueingTimeEstimatorClient client;
};
} // namespace
// Three tasks of one second each, all within a 5 second window. Expected
// queueing time is the probability of falling into one of these tasks (3/5),
// multiplied by the expected queueing time within a task (0.5 seconds). Thus we
......
include_rules = [
"+cc/base/lap_timer.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 "cc/base/lap_timer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"
#include "third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.h"
namespace blink {
namespace scheduler {
namespace {
static constexpr base::TimeDelta kTimeLimit =
base::TimeDelta::FromMilliseconds(2000);
static const int kWarmupRuns = 50;
static const int kCheckInterval = 100;
class QueueingTimeEstimatorTestPerfTest : public testing::Test {
public:
QueueingTimeEstimatorTestPerfTest()
: timer_(kWarmupRuns, kTimeLimit, kCheckInterval) {}
cc::LapTimer timer_;
base::TimeTicks time;
TestQueueingTimeEstimatorClient client;
};
} // namespace
TEST_F(QueueingTimeEstimatorTestPerfTest, DISABLED_ManyTasks) {
const int num_tests = 3;
base::TimeDelta task_lengths[num_tests] = {
base::TimeDelta::FromSeconds(1), base::TimeDelta::FromMilliseconds(50),
base::TimeDelta::FromMilliseconds(1)};
std::string test_descriptions[num_tests] = {"OneSecondTasks", "FiftyMsTasks",
"OneMsTasks"};
for (int i = 0; i < num_tests; ++i) {
QueueingTimeEstimatorForTest estimator(
&client, base::TimeDelta::FromSeconds(1), 20, time);
time += base::TimeDelta::FromSeconds(1);
timer_.Reset();
do {
estimator.OnExecutionStarted(time, nullptr);
time += task_lengths[i];
estimator.OnExecutionStopped(time);
timer_.NextLap();
} while (!timer_.HasTimeLimitExpired());
perf_test::PrintResult("QueueingTimeEstimatorTestPerfTest", "ManyTasks",
test_descriptions[i], timer_.LapsPerSecond(),
"tasks/s", true);
}
}
} // namespace scheduler
} // namespace blink
// 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 "third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
namespace blink {
namespace scheduler {
void TestQueueingTimeEstimatorClient::OnQueueingTimeForWindowEstimated(
base::TimeDelta queueing_time,
bool is_disjoint_window) {
expected_queueing_times_.push_back(queueing_time);
// Mimic RendererSchedulerImpl::OnQueueingTimeForWindowEstimated.
if (is_disjoint_window) {
UMA_HISTOGRAM_TIMES("RendererScheduler.ExpectedTaskQueueingDuration",
queueing_time);
UMA_HISTOGRAM_CUSTOM_COUNTS(
"RendererScheduler.ExpectedTaskQueueingDuration3",
queueing_time.InMicroseconds(),
MainThreadSchedulerImpl::kMinExpectedQueueingTimeBucket,
MainThreadSchedulerImpl::kMaxExpectedQueueingTimeBucket,
MainThreadSchedulerImpl::kNumberExpectedQueueingTimeBuckets);
}
}
void TestQueueingTimeEstimatorClient::OnReportFineGrainedExpectedQueueingTime(
const char* split_description,
base::TimeDelta queueing_time) {
if (split_eqts_.find(split_description) == split_eqts_.end())
split_eqts_[split_description] = std::vector<base::TimeDelta>();
split_eqts_[split_description].push_back(queueing_time);
// Mimic MainThreadSchedulerImpl::OnReportFineGrainedExpectedQueueingTime.
base::UmaHistogramCustomCounts(
split_description, queueing_time.InMicroseconds(),
MainThreadSchedulerImpl::kMinExpectedQueueingTimeBucket,
MainThreadSchedulerImpl::kMaxExpectedQueueingTimeBucket,
MainThreadSchedulerImpl::kNumberExpectedQueueingTimeBuckets);
}
const std::vector<base::TimeDelta>&
TestQueueingTimeEstimatorClient::QueueTypeValues(QueueType queue_type) {
return split_eqts_[QueueingTimeEstimator::Calculator::
GetReportingMessageFromQueueType(queue_type)];
}
const std::vector<base::TimeDelta>&
TestQueueingTimeEstimatorClient::FrameStatusValues(FrameStatus frame_status) {
return split_eqts_[QueueingTimeEstimator::Calculator::
GetReportingMessageFromFrameStatus(frame_status)];
}
QueueingTimeEstimatorForTest::QueueingTimeEstimatorForTest(
TestQueueingTimeEstimatorClient* client,
base::TimeDelta window_duration,
int steps_per_window,
base::TimeTicks time)
: QueueingTimeEstimator(client, window_duration, steps_per_window) {
// If initial state is not foregrounded, foreground.
if (kLaunchingProcessIsBackgrounded) {
this->OnRendererStateChanged(false, time);
}
}
} // namespace scheduler
} // namespace blink
// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_TEST_TEST_QUEUEING_TIME_ESTIMATOR_CLIENT_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_TEST_TEST_QUEUEING_TIME_ESTIMATOR_CLIENT_H_
#include "third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h"
#include <map>
#include <vector>
namespace blink {
namespace scheduler {
using QueueType = MainThreadTaskQueue::QueueType;
class TestQueueingTimeEstimatorClient : public QueueingTimeEstimator::Client {
public:
// QueueingTimeEstimator::Client implementation:
void OnQueueingTimeForWindowEstimated(base::TimeDelta queueing_time,
bool is_disjoint_window) override;
void OnReportFineGrainedExpectedQueueingTime(
const char* split_description,
base::TimeDelta queueing_time) override;
const std::vector<base::TimeDelta>& expected_queueing_times() {
return expected_queueing_times_;
}
const std::map<const char*, std::vector<base::TimeDelta>>& split_eqts() {
return split_eqts_;
}
const std::vector<base::TimeDelta>& QueueTypeValues(QueueType queue_type);
const std::vector<base::TimeDelta>& FrameStatusValues(
FrameStatus frame_status);
private:
std::vector<base::TimeDelta> expected_queueing_times_;
std::map<const char*, std::vector<base::TimeDelta>> split_eqts_;
};
class QueueingTimeEstimatorForTest : public QueueingTimeEstimator {
public:
QueueingTimeEstimatorForTest(TestQueueingTimeEstimatorClient* client,
base::TimeDelta window_duration,
int steps_per_window,
base::TimeTicks time);
};
} // namespace scheduler
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_TEST_TEST_QUEUEING_TIME_ESTIMATOR_CLIENT_H_
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