Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/base/time_domain.cc

Issue 2640763003: Optimize away updatable_queue_set_ (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "platform/scheduler/base/time_domain.h" 5 #include "platform/scheduler/base/time_domain.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "platform/scheduler/base/task_queue_impl.h" 9 #include "platform/scheduler/base/task_queue_impl.h"
10 #include "platform/scheduler/base/task_queue_manager_delegate.h" 10 #include "platform/scheduler/base/task_queue_manager_delegate.h"
11 #include "platform/scheduler/base/work_queue.h" 11 #include "platform/scheduler/base/work_queue.h"
12 12
13 namespace blink { 13 namespace blink {
14 namespace scheduler { 14 namespace scheduler {
15 15
16 TimeDomain::TimeDomain(Observer* observer) : observer_(observer) {} 16 TimeDomain::TimeDomain(Observer* observer) : observer_(observer) {}
17 17
18 TimeDomain::~TimeDomain() { 18 TimeDomain::~TimeDomain() {
19 DCHECK(main_thread_checker_.CalledOnValidThread()); 19 DCHECK(main_thread_checker_.CalledOnValidThread());
20 } 20 }
21 21
22 void TimeDomain::RegisterQueue(internal::TaskQueueImpl* queue) { 22 void TimeDomain::RegisterQueue(internal::TaskQueueImpl* queue) {
23 DCHECK(main_thread_checker_.CalledOnValidThread()); 23 DCHECK(main_thread_checker_.CalledOnValidThread());
24 DCHECK_EQ(queue->GetTimeDomain(), this); 24 DCHECK_EQ(queue->GetTimeDomain(), this);
25 } 25 }
26 26
27 void TimeDomain::UnregisterQueue(internal::TaskQueueImpl* queue) { 27 void TimeDomain::UnregisterQueue(internal::TaskQueueImpl* queue) {
28 DCHECK(main_thread_checker_.CalledOnValidThread()); 28 DCHECK(main_thread_checker_.CalledOnValidThread());
29 DCHECK_EQ(queue->GetTimeDomain(), this); 29 DCHECK_EQ(queue->GetTimeDomain(), this);
30 UnregisterAsUpdatableTaskQueue(queue); 30
31 {
32 base::AutoLock lock(has_incoming_immediate_work_lock_);
33 has_incoming_immediate_work_.erase(queue);
34 }
31 35
32 // If no wakeup has been requested then bail out. 36 // If no wakeup has been requested then bail out.
33 if (!queue->heap_handle().IsValid()) 37 if (!queue->heap_handle().IsValid())
34 return; 38 return;
35 39
36 DCHECK_NE(queue->scheduled_time_domain_wakeup(), base::TimeTicks()); 40 DCHECK_NE(queue->scheduled_time_domain_wakeup(), base::TimeTicks());
37 41
38 // O(log n) 42 // O(log n)
39 delayed_wakeup_queue_.erase(queue->heap_handle()); 43 delayed_wakeup_queue_.erase(queue->heap_handle());
40 } 44 }
41 45
42 void TimeDomain::MigrateQueue(internal::TaskQueueImpl* queue, 46 void TimeDomain::MigrateQueue(internal::TaskQueueImpl* queue,
43 TimeDomain* destination_time_domain) { 47 TimeDomain* destination_time_domain) {
44 DCHECK(main_thread_checker_.CalledOnValidThread()); 48 DCHECK(main_thread_checker_.CalledOnValidThread());
45 DCHECK_EQ(queue->GetTimeDomain(), this); 49 DCHECK_EQ(queue->GetTimeDomain(), this);
46 DCHECK(destination_time_domain); 50 DCHECK(destination_time_domain);
47 51
48 // Make sure we remember to update |queue| if it's got incoming immediate 52 // Make sure we remember to update |queue| if it's got incoming immediate
49 // work. 53 // work.
50 if (UnregisterAsUpdatableTaskQueue(queue)) 54 {
51 destination_time_domain->updatable_queue_set_.insert(queue); 55 base::AutoLock lock(has_incoming_immediate_work_lock_);
56 if (has_incoming_immediate_work_.erase(queue)) {
57 destination_time_domain->has_incoming_immediate_work_.insert(queue);
Sami 2017/01/18 17:57:04 Looks like we need to grab the destination lock he
alex clarke (OOO till 29th) 2017/01/19 08:50:52 I'd like has_incoming_immediate_work_ to end up on
Sami 2017/01/19 11:57:38 That sounds fine, but for the time being don't we
alex clarke (OOO till 29th) 2017/01/19 12:34:31 Done.
58 }
59 }
52 60
53 // If no wakeup has been requested then bail out. 61 // If no wakeup has been requested then bail out.
54 if (!queue->heap_handle().IsValid()) 62 if (!queue->heap_handle().IsValid())
55 return; 63 return;
56 64
57 base::TimeTicks wake_up_time = queue->scheduled_time_domain_wakeup(); 65 base::TimeTicks wake_up_time = queue->scheduled_time_domain_wakeup();
58 DCHECK_NE(wake_up_time, base::TimeTicks()); 66 DCHECK_NE(wake_up_time, base::TimeTicks());
59 67
60 // O(log n) 68 // O(log n)
61 delayed_wakeup_queue_.erase(queue->heap_handle()); 69 delayed_wakeup_queue_.erase(queue->heap_handle());
(...skipping 25 matching lines...) Expand all
87 // If |queue| is the first wakeup then request the wakeup. 95 // If |queue| is the first wakeup then request the wakeup.
88 if (delayed_wakeup_queue_.min().queue == queue) { 96 if (delayed_wakeup_queue_.min().queue == queue) {
89 base::TimeDelta delay = std::max(base::TimeDelta(), delayed_run_time - now); 97 base::TimeDelta delay = std::max(base::TimeDelta(), delayed_run_time - now);
90 RequestWakeup(now, delay); 98 RequestWakeup(now, delay);
91 } 99 }
92 100
93 if (observer_) 101 if (observer_)
94 observer_->OnTimeDomainHasDelayedWork(queue); 102 observer_->OnTimeDomainHasDelayedWork(queue);
95 } 103 }
96 104
97 void TimeDomain::RegisterAsUpdatableTaskQueue(internal::TaskQueueImpl* queue) { 105 void TimeDomain::OnQueueHasIncomingImmediateWork(
106 internal::TaskQueueImpl* queue) {
98 { 107 {
99 base::AutoLock lock(newly_updatable_lock_); 108 base::AutoLock lock(has_incoming_immediate_work_lock_);
100 newly_updatable_.push_back(queue); 109 has_incoming_immediate_work_.insert(queue);
101 } 110 }
111
102 if (observer_) 112 if (observer_)
103 observer_->OnTimeDomainHasImmediateWork(queue); 113 observer_->OnTimeDomainHasImmediateWork(queue);
104 } 114 }
105 115
106 bool TimeDomain::UnregisterAsUpdatableTaskQueue(
107 internal::TaskQueueImpl* queue) {
108 DCHECK(main_thread_checker_.CalledOnValidThread());
109
110 bool was_updatable = updatable_queue_set_.erase(queue) != 0;
111
112 base::AutoLock lock(newly_updatable_lock_);
113 // Remove all copies of |queue| from |newly_updatable_|.
114 for (size_t i = 0; i < newly_updatable_.size();) {
115 if (newly_updatable_[i] == queue) {
116 // Move last element into slot #i and then compact.
117 newly_updatable_[i] = newly_updatable_.back();
118 newly_updatable_.pop_back();
119 was_updatable = true;
120 } else {
121 i++;
122 }
123 }
124 return was_updatable;
125 }
126
127 void TimeDomain::UpdateWorkQueues(LazyNow lazy_now) { 116 void TimeDomain::UpdateWorkQueues(LazyNow lazy_now) {
128 DCHECK(main_thread_checker_.CalledOnValidThread()); 117 DCHECK(main_thread_checker_.CalledOnValidThread());
129 118
130 // Move any ready delayed tasks into the Incoming queues. 119 // Move any ready delayed tasks into the Incoming queues.
131 WakeupReadyDelayedQueues(&lazy_now); 120 WakeupReadyDelayedQueues(&lazy_now);
132 121
133 MoveNewlyUpdatableQueuesIntoUpdatableQueueSet(); 122 std::set<internal::TaskQueueImpl*> queues_to_reload_if_empty;
134 123
135 std::set<internal::TaskQueueImpl*>::iterator iter = 124 {
136 updatable_queue_set_.begin(); 125 base::AutoLock lock(has_incoming_immediate_work_lock_);
137 while (iter != updatable_queue_set_.end()) { 126 std::swap(queues_to_reload_if_empty, has_incoming_immediate_work_);
138 std::set<internal::TaskQueueImpl*>::iterator queue_it = iter++; 127 }
139 internal::TaskQueueImpl* queue = *queue_it;
140 128
141 // Update the queue and remove from the set if subsequent updates are not 129 for (internal::TaskQueueImpl* queue : queues_to_reload_if_empty)
142 // required. 130 queue->ReloadImmediateWorkQueueIfEmpty();
143 if (!queue->MaybeUpdateImmediateWorkQueues())
144 updatable_queue_set_.erase(queue_it);
145 }
146 }
147
148 void TimeDomain::MoveNewlyUpdatableQueuesIntoUpdatableQueueSet() {
149 DCHECK(main_thread_checker_.CalledOnValidThread());
150 base::AutoLock lock(newly_updatable_lock_);
151 while (!newly_updatable_.empty()) {
152 updatable_queue_set_.insert(newly_updatable_.back());
153 newly_updatable_.pop_back();
154 }
155 } 131 }
156 132
157 void TimeDomain::WakeupReadyDelayedQueues(LazyNow* lazy_now) { 133 void TimeDomain::WakeupReadyDelayedQueues(LazyNow* lazy_now) {
158 DCHECK(main_thread_checker_.CalledOnValidThread()); 134 DCHECK(main_thread_checker_.CalledOnValidThread());
159 // Wake up any queues with pending delayed work. Note std::multipmap stores 135 // Wake up any queues with pending delayed work. Note std::multipmap stores
160 // the elements sorted by key, so the begin() iterator points to the earliest 136 // the elements sorted by key, so the begin() iterator points to the earliest
161 // queue to wakeup. 137 // queue to wakeup.
162 while (!delayed_wakeup_queue_.empty() && 138 while (!delayed_wakeup_queue_.empty() &&
163 delayed_wakeup_queue_.min().time <= lazy_now->Now()) { 139 delayed_wakeup_queue_.min().time <= lazy_now->Now()) {
164 internal::TaskQueueImpl* queue = delayed_wakeup_queue_.min().queue; 140 internal::TaskQueueImpl* queue = delayed_wakeup_queue_.min().queue;
(...skipping 18 matching lines...) Expand all
183 if (delayed_wakeup_queue_.empty()) 159 if (delayed_wakeup_queue_.empty())
184 return false; 160 return false;
185 161
186 *out_task_queue = delayed_wakeup_queue_.min().queue; 162 *out_task_queue = delayed_wakeup_queue_.min().queue;
187 return true; 163 return true;
188 } 164 }
189 165
190 void TimeDomain::AsValueInto(base::trace_event::TracedValue* state) const { 166 void TimeDomain::AsValueInto(base::trace_event::TracedValue* state) const {
191 state->BeginDictionary(); 167 state->BeginDictionary();
192 state->SetString("name", GetName()); 168 state->SetString("name", GetName());
193 state->BeginArray("updatable_queue_set"); 169 {
194 for (auto* queue : updatable_queue_set_) 170 base::AutoLock lock(has_incoming_immediate_work_lock_);
195 state->AppendString(queue->GetName()); 171 state->BeginArray("has_incoming_immediate_work");
196 state->EndArray(); 172 for (internal::TaskQueueImpl* queue : has_incoming_immediate_work_)
173 state->AppendString(queue->GetName());
174 state->EndArray();
175 }
197 state->SetInteger("registered_delay_count", delayed_wakeup_queue_.size()); 176 state->SetInteger("registered_delay_count", delayed_wakeup_queue_.size());
198 if (!delayed_wakeup_queue_.empty()) { 177 if (!delayed_wakeup_queue_.empty()) {
199 base::TimeDelta delay = delayed_wakeup_queue_.min().time - Now(); 178 base::TimeDelta delay = delayed_wakeup_queue_.min().time - Now();
200 state->SetDouble("next_delay_ms", delay.InMillisecondsF()); 179 state->SetDouble("next_delay_ms", delay.InMillisecondsF());
201 } 180 }
202 AsValueIntoInternal(state); 181 AsValueIntoInternal(state);
203 state->EndDictionary(); 182 state->EndDictionary();
204 } 183 }
205 184
206 } // namespace scheduler 185 } // namespace scheduler
207 } // namespace blink 186 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698