Commit afc23281 authored by Farah Charab's avatar Farah Charab Committed by Commit Bot

Scheduling: Add a metric to track the number of times the starvation

logic is triggered by the task queue selector.

Change-Id: I7944632f176a325505fb2e2c3ea4d1690c792092
Reviewed-on: https://chromium-review.googlesource.com/995774
Commit-Queue: Farah Charab <farahcharab@chromium.org>
Reviewed-by: default avatarBrian White <bcwhite@chromium.org>
Reviewed-by: default avatarAlexander Timin <altimin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#549297}
parent c6c0557b
...@@ -27,6 +27,7 @@ blink_platform_sources("scheduler") { ...@@ -27,6 +27,7 @@ blink_platform_sources("scheduler") {
"base/task_queue_manager_impl.h", "base/task_queue_manager_impl.h",
"base/task_queue_selector.cc", "base/task_queue_selector.cc",
"base/task_queue_selector.h", "base/task_queue_selector.h",
"base/task_queue_selector_logic.h",
"base/task_time_observer.h", "base/task_time_observer.h",
"base/thread_controller.h", "base/thread_controller.h",
"base/thread_controller_impl.cc", "base/thread_controller_impl.cc",
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h" #include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event_argument.h" #include "base/trace_event/trace_event_argument.h"
#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h" #include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
#include "third_party/blink/renderer/platform/scheduler/base/work_queue.h" #include "third_party/blink/renderer/platform/scheduler/base/work_queue.h"
...@@ -13,6 +14,38 @@ namespace blink { ...@@ -13,6 +14,38 @@ namespace blink {
namespace scheduler { namespace scheduler {
namespace internal { namespace internal {
namespace {
TaskQueueSelectorLogic QueuePriorityToSelectorLogic(
TaskQueue::QueuePriority priority) {
switch (priority) {
case TaskQueue::kControlPriority:
return TaskQueueSelectorLogic::kControlPriorityLogic;
case TaskQueue::kHighestPriority:
return TaskQueueSelectorLogic::kHighestPriorityLogic;
case TaskQueue::kHighPriority:
return TaskQueueSelectorLogic::kHighPriorityLogic;
case TaskQueue::kNormalPriority:
return TaskQueueSelectorLogic::kNormalPriorityLogic;
case TaskQueue::kLowPriority:
return TaskQueueSelectorLogic::kLowPriorityLogic;
case TaskQueue::kBestEffortPriority:
return TaskQueueSelectorLogic::kBestEffortPriorityLogic;
default:
NOTREACHED();
return TaskQueueSelectorLogic::kCount;
}
}
// Helper function used to report the number of times a selector logic is
// trigerred. This will create a histogram for the enumerated data.
void ReportTaskSelectionLogic(TaskQueueSelectorLogic selector_logic) {
UMA_HISTOGRAM_ENUMERATION("TaskQueueSelector.TaskServicedPerSelectorLogic",
selector_logic, TaskQueueSelectorLogic::kCount);
}
} // namespace
TaskQueueSelector::TaskQueueSelector() TaskQueueSelector::TaskQueueSelector()
: prioritizing_selector_(this, "enabled"), : prioritizing_selector_(this, "enabled"),
immediate_starvation_count_(0), immediate_starvation_count_(0),
...@@ -187,6 +220,7 @@ bool TaskQueueSelector::PrioritizingSelector::SelectWorkQueueToService( ...@@ -187,6 +220,7 @@ bool TaskQueueSelector::PrioritizingSelector::SelectWorkQueueToService(
ChooseOldestWithPriority(TaskQueue::kControlPriority, ChooseOldestWithPriority(TaskQueue::kControlPriority,
out_chose_delayed_over_immediate, out_chose_delayed_over_immediate,
out_work_queue)) { out_work_queue)) {
ReportTaskSelectionLogic(TaskQueueSelectorLogic::kControlPriorityLogic);
return true; return true;
} }
...@@ -197,6 +231,8 @@ bool TaskQueueSelector::PrioritizingSelector::SelectWorkQueueToService( ...@@ -197,6 +231,8 @@ bool TaskQueueSelector::PrioritizingSelector::SelectWorkQueueToService(
ChooseOldestWithPriority(TaskQueue::kLowPriority, ChooseOldestWithPriority(TaskQueue::kLowPriority,
out_chose_delayed_over_immediate, out_chose_delayed_over_immediate,
out_work_queue)) { out_work_queue)) {
ReportTaskSelectionLogic(
TaskQueueSelectorLogic::kLowPriorityStarvationLogic);
return true; return true;
} }
...@@ -207,6 +243,8 @@ bool TaskQueueSelector::PrioritizingSelector::SelectWorkQueueToService( ...@@ -207,6 +243,8 @@ bool TaskQueueSelector::PrioritizingSelector::SelectWorkQueueToService(
ChooseOldestWithPriority(TaskQueue::kNormalPriority, ChooseOldestWithPriority(TaskQueue::kNormalPriority,
out_chose_delayed_over_immediate, out_chose_delayed_over_immediate,
out_work_queue)) { out_work_queue)) {
ReportTaskSelectionLogic(
TaskQueueSelectorLogic::kNormalPriorityStarvationLogic);
return true; return true;
} }
...@@ -217,6 +255,8 @@ bool TaskQueueSelector::PrioritizingSelector::SelectWorkQueueToService( ...@@ -217,6 +255,8 @@ bool TaskQueueSelector::PrioritizingSelector::SelectWorkQueueToService(
ChooseOldestWithPriority(TaskQueue::kHighPriority, ChooseOldestWithPriority(TaskQueue::kHighPriority,
out_chose_delayed_over_immediate, out_chose_delayed_over_immediate,
out_work_queue)) { out_work_queue)) {
ReportTaskSelectionLogic(
TaskQueueSelectorLogic::kHighPriorityStarvationLogic);
return true; return true;
} }
...@@ -225,6 +265,7 @@ bool TaskQueueSelector::PrioritizingSelector::SelectWorkQueueToService( ...@@ -225,6 +265,7 @@ bool TaskQueueSelector::PrioritizingSelector::SelectWorkQueueToService(
priority < max_priority; priority = NextPriority(priority)) { priority < max_priority; priority = NextPriority(priority)) {
if (ChooseOldestWithPriority(priority, out_chose_delayed_over_immediate, if (ChooseOldestWithPriority(priority, out_chose_delayed_over_immediate,
out_work_queue)) { out_work_queue)) {
ReportTaskSelectionLogic(QueuePriorityToSelectorLogic(priority));
return true; return true;
} }
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/pending_task.h" #include "base/pending_task.h"
#include "base/threading/thread_checker.h" #include "base/threading/thread_checker.h"
#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector_logic.h"
#include "third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h" #include "third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h"
namespace blink { namespace blink {
......
// Copyright 2015 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_BASE_TASK_QUEUE_SELECTOR_LOGIC_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_SELECTOR_LOGIC_H_
namespace blink {
namespace scheduler {
// Used to describe the logic trigerred when a task queue is selected to
// service.
// This enum is used for histograms and should not be renumbered.
enum class TaskQueueSelectorLogic {
// Selected due to priority rules.
kControlPriorityLogic = 0,
kHighestPriorityLogic = 1,
kHighPriorityLogic = 2,
kNormalPriorityLogic = 3,
kLowPriorityLogic = 4,
kBestEffortPriorityLogic = 5,
// Selected due to starvation logic.
kHighPriorityStarvationLogic = 6,
kNormalPriorityStarvationLogic = 7,
kLowPriorityStarvationLogic = 8,
kCount = 9,
};
} // namespace scheduler
} // namespace blink
#endif
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/pending_task.h" #include "base/pending_task.h"
#include "base/test/histogram_tester.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h" #include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
...@@ -116,6 +117,7 @@ class TaskQueueSelectorTest : public testing::Test { ...@@ -116,6 +117,7 @@ class TaskQueueSelectorTest : public testing::Test {
<< i; << i;
queue_to_index_map_.insert(std::make_pair(task_queues_[i].get(), i)); queue_to_index_map_.insert(std::make_pair(task_queues_[i].get(), i));
} }
histogram_tester_.reset(new base::HistogramTester());
} }
void TearDown() final { void TearDown() final {
...@@ -139,12 +141,17 @@ class TaskQueueSelectorTest : public testing::Test { ...@@ -139,12 +141,17 @@ class TaskQueueSelectorTest : public testing::Test {
std::unique_ptr<VirtualTimeDomain> virtual_time_domain_; std::unique_ptr<VirtualTimeDomain> virtual_time_domain_;
std::vector<std::unique_ptr<TaskQueueImpl>> task_queues_; std::vector<std::unique_ptr<TaskQueueImpl>> task_queues_;
std::map<TaskQueueImpl*, size_t> queue_to_index_map_; std::map<TaskQueueImpl*, size_t> queue_to_index_map_;
std::unique_ptr<base::HistogramTester> histogram_tester_;
}; };
TEST_F(TaskQueueSelectorTest, TestDefaultPriority) { TEST_F(TaskQueueSelectorTest, TestDefaultPriority) {
size_t queue_order[] = {4, 3, 2, 1, 0}; size_t queue_order[] = {4, 3, 2, 1, 0};
PushTasks(queue_order, 5); PushTasks(queue_order, 5);
EXPECT_THAT(PopTasks(), testing::ElementsAre(4, 3, 2, 1, 0)); EXPECT_THAT(PopTasks(), testing::ElementsAre(4, 3, 2, 1, 0));
EXPECT_EQ(histogram_tester_->GetBucketCount(
"TaskQueueSelector.TaskServicedPerSelectorLogic",
static_cast<int>(TaskQueueSelectorLogic::kNormalPriorityLogic)),
5);
} }
TEST_F(TaskQueueSelectorTest, TestHighestPriority) { TEST_F(TaskQueueSelectorTest, TestHighestPriority) {
...@@ -153,6 +160,11 @@ TEST_F(TaskQueueSelectorTest, TestHighestPriority) { ...@@ -153,6 +160,11 @@ TEST_F(TaskQueueSelectorTest, TestHighestPriority) {
selector_.SetQueuePriority(task_queues_[2].get(), selector_.SetQueuePriority(task_queues_[2].get(),
TaskQueue::kHighestPriority); TaskQueue::kHighestPriority);
EXPECT_THAT(PopTasks(), ::testing::ElementsAre(2, 0, 1, 3, 4)); EXPECT_THAT(PopTasks(), ::testing::ElementsAre(2, 0, 1, 3, 4));
EXPECT_EQ(
histogram_tester_->GetBucketCount(
"TaskQueueSelector.TaskServicedPerSelectorLogic",
static_cast<int>(TaskQueueSelectorLogic::kHighestPriorityLogic)),
1);
} }
TEST_F(TaskQueueSelectorTest, TestHighPriority) { TEST_F(TaskQueueSelectorTest, TestHighPriority) {
...@@ -163,6 +175,10 @@ TEST_F(TaskQueueSelectorTest, TestHighPriority) { ...@@ -163,6 +175,10 @@ TEST_F(TaskQueueSelectorTest, TestHighPriority) {
selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::kHighPriority); selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::kHighPriority);
selector_.SetQueuePriority(task_queues_[0].get(), TaskQueue::kLowPriority); selector_.SetQueuePriority(task_queues_[0].get(), TaskQueue::kLowPriority);
EXPECT_THAT(PopTasks(), ::testing::ElementsAre(2, 1, 3, 4, 0)); EXPECT_THAT(PopTasks(), ::testing::ElementsAre(2, 1, 3, 4, 0));
EXPECT_EQ(histogram_tester_->GetBucketCount(
"TaskQueueSelector.TaskServicedPerSelectorLogic",
static_cast<int>(TaskQueueSelectorLogic::kHighPriorityLogic)),
1);
} }
TEST_F(TaskQueueSelectorTest, TestLowPriority) { TEST_F(TaskQueueSelectorTest, TestLowPriority) {
...@@ -170,6 +186,10 @@ TEST_F(TaskQueueSelectorTest, TestLowPriority) { ...@@ -170,6 +186,10 @@ TEST_F(TaskQueueSelectorTest, TestLowPriority) {
PushTasks(queue_order, 5); PushTasks(queue_order, 5);
selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::kLowPriority); selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::kLowPriority);
EXPECT_THAT(PopTasks(), testing::ElementsAre(0, 1, 3, 4, 2)); EXPECT_THAT(PopTasks(), testing::ElementsAre(0, 1, 3, 4, 2));
EXPECT_EQ(histogram_tester_->GetBucketCount(
"TaskQueueSelector.TaskServicedPerSelectorLogic",
static_cast<int>(TaskQueueSelectorLogic::kLowPriorityLogic)),
1);
} }
TEST_F(TaskQueueSelectorTest, TestBestEffortPriority) { TEST_F(TaskQueueSelectorTest, TestBestEffortPriority) {
...@@ -181,6 +201,11 @@ TEST_F(TaskQueueSelectorTest, TestBestEffortPriority) { ...@@ -181,6 +201,11 @@ TEST_F(TaskQueueSelectorTest, TestBestEffortPriority) {
selector_.SetQueuePriority(task_queues_[3].get(), selector_.SetQueuePriority(task_queues_[3].get(),
TaskQueue::kHighestPriority); TaskQueue::kHighestPriority);
EXPECT_THAT(PopTasks(), ::testing::ElementsAre(3, 1, 4, 2, 0)); EXPECT_THAT(PopTasks(), ::testing::ElementsAre(3, 1, 4, 2, 0));
EXPECT_EQ(
histogram_tester_->GetBucketCount(
"TaskQueueSelector.TaskServicedPerSelectorLogic",
static_cast<int>(TaskQueueSelectorLogic::kBestEffortPriorityLogic)),
1);
} }
TEST_F(TaskQueueSelectorTest, TestControlPriority) { TEST_F(TaskQueueSelectorTest, TestControlPriority) {
...@@ -193,6 +218,11 @@ TEST_F(TaskQueueSelectorTest, TestControlPriority) { ...@@ -193,6 +218,11 @@ TEST_F(TaskQueueSelectorTest, TestControlPriority) {
TaskQueue::kHighestPriority); TaskQueue::kHighestPriority);
EXPECT_EQ(TaskQueue::kHighestPriority, task_queues_[2]->GetQueuePriority()); EXPECT_EQ(TaskQueue::kHighestPriority, task_queues_[2]->GetQueuePriority());
EXPECT_THAT(PopTasks(), ::testing::ElementsAre(4, 2, 0, 1, 3)); EXPECT_THAT(PopTasks(), ::testing::ElementsAre(4, 2, 0, 1, 3));
EXPECT_EQ(
histogram_tester_->GetBucketCount(
"TaskQueueSelector.TaskServicedPerSelectorLogic",
static_cast<int>(TaskQueueSelectorLogic::kControlPriorityLogic)),
1);
} }
TEST_F(TaskQueueSelectorTest, TestObserverWithEnabledQueue) { TEST_F(TaskQueueSelectorTest, TestObserverWithEnabledQueue) {
......
...@@ -43446,6 +43446,21 @@ would be helpful to identify which type is being sent. ...@@ -43446,6 +43446,21 @@ would be helpful to identify which type is being sent.
<int value="5" label="Tapped Inside, Different Node"/> <int value="5" label="Tapped Inside, Different Node"/>
</enum> </enum>
<enum name="TaskQueueSelectorLogic">
<summary>
Used to record selector logic trigerred when servicing a task queue.
</summary>
<int value="0" label="Control Priority Logic"/>
<int value="1" label="Highest Priority Logic"/>
<int value="2" label="High Priority Logic"/>
<int value="3" label="Normal Priority Logic"/>
<int value="4" label="Low Priority Logic"/>
<int value="5" label="Best Effort Priority Logic"/>
<int value="6" label="High Priority Starvation Logic"/>
<int value="7" label="Normal Priority Starvation Logic"/>
<int value="8" label="Low Priority Starvation Logic"/>
</enum>
<enum name="TcpSocketStatus"> <enum name="TcpSocketStatus">
<int value="0" label="Unknown"/> <int value="0" label="Unknown"/>
<int value="1" label="Fast Connection Return"/> <int value="1" label="Fast Connection Return"/>
...@@ -94596,6 +94596,17 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. ...@@ -94596,6 +94596,17 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
</summary> </summary>
</histogram> </histogram>
<histogram name="TaskQueueSelector.TaskServicedPerSelectorLogic"
enum="TaskQueueSelectorLogic">
<owner>altimin@chromium.org</owner>
<owner>farahcharab@chromium.org</owner>
<summary>
Used to track the number of tasks serviced due to starvation versus the
number of tasks serviced due to priroity. Incremented whenever a task queue
is selected to service.
</summary>
</histogram>
<histogram name="TaskScheduler.BlockShutdownTasksPostedDuringShutdown" <histogram name="TaskScheduler.BlockShutdownTasksPostedDuringShutdown"
units="tasks"> units="tasks">
<owner>fdoray@chromium.org</owner> <owner>fdoray@chromium.org</owner>
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