OLD | NEW |
---|---|
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/renderer/task_queue_throttler.h" | 5 #include "platform/scheduler/renderer/task_queue_throttler.h" |
6 | 6 |
7 #include <cstdint> | 7 #include <cstdint> |
8 | 8 |
9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
169 return find_it->second.throttling_ref_count > 0; | 169 return find_it->second.throttling_ref_count > 0; |
170 } | 170 } |
171 | 171 |
172 void TaskQueueThrottler::UnregisterTaskQueue(TaskQueue* task_queue) { | 172 void TaskQueueThrottler::UnregisterTaskQueue(TaskQueue* task_queue) { |
173 LazyNow lazy_now(tick_clock_); | 173 LazyNow lazy_now(tick_clock_); |
174 auto find_it = queue_details_.find(task_queue); | 174 auto find_it = queue_details_.find(task_queue); |
175 | 175 |
176 if (find_it == queue_details_.end()) | 176 if (find_it == queue_details_.end()) |
177 return; | 177 return; |
178 | 178 |
179 if (find_it->second.budget_pool) | 179 for (BudgetPool* budget_pool : find_it->second.budget_pools) { |
Sami
2017/03/17 11:18:39
budget_pools is being modified while we iterate it
altimin
2017/03/17 14:35:42
Very well spotted, thanks. (Bigger problem is that
| |
180 find_it->second.budget_pool->RemoveQueue(lazy_now.Now(), task_queue); | 180 budget_pool->RemoveQueue(lazy_now.Now(), task_queue); |
181 } | |
181 | 182 |
182 queue_details_.erase(find_it); | 183 queue_details_.erase(find_it); |
183 } | 184 } |
184 | 185 |
185 void TaskQueueThrottler::OnTimeDomainHasImmediateWork(TaskQueue* queue) { | 186 void TaskQueueThrottler::OnTimeDomainHasImmediateWork(TaskQueue* queue) { |
186 // Forward to the main thread if called from another thread | 187 // Forward to the main thread if called from another thread |
187 if (!task_runner_->RunsTasksOnCurrentThread()) { | 188 if (!task_runner_->RunsTasksOnCurrentThread()) { |
188 task_runner_->PostTask(FROM_HERE, | 189 task_runner_->PostTask(FROM_HERE, |
189 base::Bind(forward_immediate_work_callback_, queue)); | 190 base::Bind(forward_immediate_work_callback_, queue)); |
190 return; | 191 return; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
318 budget_pools_[time_budget_pool] = base::WrapUnique(time_budget_pool); | 319 budget_pools_[time_budget_pool] = base::WrapUnique(time_budget_pool); |
319 return time_budget_pool; | 320 return time_budget_pool; |
320 } | 321 } |
321 | 322 |
322 void TaskQueueThrottler::OnTaskRunTimeReported(TaskQueue* task_queue, | 323 void TaskQueueThrottler::OnTaskRunTimeReported(TaskQueue* task_queue, |
323 base::TimeTicks start_time, | 324 base::TimeTicks start_time, |
324 base::TimeTicks end_time) { | 325 base::TimeTicks end_time) { |
325 if (!IsThrottled(task_queue)) | 326 if (!IsThrottled(task_queue)) |
326 return; | 327 return; |
327 | 328 |
328 BudgetPool* budget_pool = GetBudgetPoolForQueue(task_queue); | 329 auto find_it = queue_details_.find(task_queue); |
alex clarke (OOO till 29th)
2017/03/16 19:12:01
I tend to write exactly that too but I wonder if t
altimin
2017/03/16 19:14:25
It's an iterator, copying them is cheap.
| |
329 if (!budget_pool) | 330 if (find_it == queue_details_.end()) |
330 return; | 331 return; |
331 | 332 |
332 budget_pool->RecordTaskRunTime(start_time, end_time); | 333 for (BudgetPool* budget_pool : find_it->second.budget_pools) { |
333 if (!budget_pool->HasEnoughBudgetToRun(end_time)) | 334 budget_pool->RecordTaskRunTime(start_time, end_time); |
334 budget_pool->BlockThrottledQueues(end_time); | 335 if (!budget_pool->HasEnoughBudgetToRun(end_time)) |
336 budget_pool->BlockThrottledQueues(end_time); | |
337 } | |
335 } | 338 } |
336 | 339 |
337 void TaskQueueThrottler::BlockQueue(base::TimeTicks now, TaskQueue* queue) { | 340 void TaskQueueThrottler::BlockQueue(base::TimeTicks now, TaskQueue* queue) { |
338 if (!IsThrottled(queue)) | 341 if (!IsThrottled(queue)) |
339 return; | 342 return; |
340 | 343 |
341 queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME); | 344 queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME); |
342 SchedulePumpQueue(FROM_HERE, now, queue); | 345 SchedulePumpQueue(FROM_HERE, now, queue); |
343 } | 346 } |
344 | 347 |
(...skipping 26 matching lines...) Expand all Loading... | |
371 state->EndDictionary(); | 374 state->EndDictionary(); |
372 } | 375 } |
373 | 376 |
374 void TaskQueueThrottler::AddQueueToBudgetPool(TaskQueue* queue, | 377 void TaskQueueThrottler::AddQueueToBudgetPool(TaskQueue* queue, |
375 BudgetPool* budget_pool) { | 378 BudgetPool* budget_pool) { |
376 std::pair<TaskQueueMap::iterator, bool> insert_result = | 379 std::pair<TaskQueueMap::iterator, bool> insert_result = |
377 queue_details_.insert(std::make_pair(queue, Metadata())); | 380 queue_details_.insert(std::make_pair(queue, Metadata())); |
378 | 381 |
379 Metadata& metadata = insert_result.first->second; | 382 Metadata& metadata = insert_result.first->second; |
380 | 383 |
381 DCHECK(!metadata.budget_pool); | 384 DCHECK(metadata.budget_pools.find(budget_pool) == |
382 metadata.budget_pool = budget_pool; | 385 metadata.budget_pools.end()); |
386 | |
387 metadata.budget_pools.insert(budget_pool); | |
383 } | 388 } |
384 | 389 |
385 void TaskQueueThrottler::RemoveQueueFromBudgetPool(TaskQueue* queue, | 390 void TaskQueueThrottler::RemoveQueueFromBudgetPool(TaskQueue* queue, |
386 BudgetPool* budget_pool) { | 391 BudgetPool* budget_pool) { |
387 auto find_it = queue_details_.find(queue); | 392 auto find_it = queue_details_.find(queue); |
388 DCHECK(find_it != queue_details_.end() && | 393 DCHECK(find_it != queue_details_.end() && |
389 find_it->second.budget_pool == budget_pool); | 394 find_it->second.budget_pools.find(budget_pool) != |
395 find_it->second.budget_pools.end()); | |
390 | 396 |
391 find_it->second.budget_pool = nullptr; | 397 find_it->second.budget_pools.erase(budget_pool); |
392 | 398 |
393 MaybeDeleteQueueMetadata(find_it); | 399 MaybeDeleteQueueMetadata(find_it); |
394 } | 400 } |
395 | 401 |
396 void TaskQueueThrottler::UnregisterBudgetPool(BudgetPool* budget_pool) { | 402 void TaskQueueThrottler::UnregisterBudgetPool(BudgetPool* budget_pool) { |
397 budget_pools_.erase(budget_pool); | 403 budget_pools_.erase(budget_pool); |
398 } | 404 } |
399 | 405 |
400 void TaskQueueThrottler::UnblockQueue(base::TimeTicks now, TaskQueue* queue) { | 406 void TaskQueueThrottler::UnblockQueue(base::TimeTicks now, TaskQueue* queue) { |
401 SchedulePumpQueue(FROM_HERE, now, queue); | 407 SchedulePumpQueue(FROM_HERE, now, queue); |
(...skipping 11 matching lines...) Expand all Loading... | |
413 NextTaskRunTime(&lazy_now, queue); | 419 NextTaskRunTime(&lazy_now, queue); |
414 if (!next_desired_run_time) | 420 if (!next_desired_run_time) |
415 return; | 421 return; |
416 | 422 |
417 base::Optional<base::TimeTicks> next_run_time = | 423 base::Optional<base::TimeTicks> next_run_time = |
418 Max(next_desired_run_time, GetNextAllowedRunTime(now, queue)); | 424 Max(next_desired_run_time, GetNextAllowedRunTime(now, queue)); |
419 | 425 |
420 MaybeSchedulePumpThrottledTasks(from_here, now, next_run_time.value()); | 426 MaybeSchedulePumpThrottledTasks(from_here, now, next_run_time.value()); |
421 } | 427 } |
422 | 428 |
423 BudgetPool* TaskQueueThrottler::GetBudgetPoolForQueue(TaskQueue* queue) { | |
424 auto find_it = queue_details_.find(queue); | |
425 if (find_it == queue_details_.end()) | |
426 return nullptr; | |
427 return find_it->second.budget_pool; | |
428 } | |
429 | |
430 base::TimeTicks TaskQueueThrottler::GetNextAllowedRunTime(base::TimeTicks now, | 429 base::TimeTicks TaskQueueThrottler::GetNextAllowedRunTime(base::TimeTicks now, |
431 TaskQueue* queue) { | 430 TaskQueue* queue) { |
432 BudgetPool* budget_pool = GetBudgetPoolForQueue(queue); | 431 base::TimeTicks next_run_time = now; |
433 if (!budget_pool) | 432 |
434 return now; | 433 auto find_it = queue_details_.find(queue); |
435 return std::max(now, budget_pool->GetNextAllowedRunTime()); | 434 if (find_it == queue_details_.end()) |
435 return next_run_time; | |
436 | |
437 for (BudgetPool* budget_pool : find_it->second.budget_pools) { | |
438 next_run_time = | |
439 std::max(next_run_time, budget_pool->GetNextAllowedRunTime()); | |
440 } | |
441 | |
442 return next_run_time; | |
436 } | 443 } |
437 | 444 |
438 void TaskQueueThrottler::MaybeDeleteQueueMetadata(TaskQueueMap::iterator it) { | 445 void TaskQueueThrottler::MaybeDeleteQueueMetadata(TaskQueueMap::iterator it) { |
439 if (it->second.throttling_ref_count == 0 && !it->second.budget_pool) | 446 if (it->second.throttling_ref_count == 0 && it->second.budget_pools.empty()) |
440 queue_details_.erase(it); | 447 queue_details_.erase(it); |
441 } | 448 } |
442 | 449 |
443 void TaskQueueThrottler::DisableThrottling() { | 450 void TaskQueueThrottler::DisableThrottling() { |
444 if (!allow_throttling_) | 451 if (!allow_throttling_) |
445 return; | 452 return; |
446 | 453 |
447 allow_throttling_ = false; | 454 allow_throttling_ = false; |
448 | 455 |
449 for (const auto& map_entry : queue_details_) { | 456 for (const auto& map_entry : queue_details_) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
482 queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME); | 489 queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME); |
483 queue->SetTimeDomain(time_domain_.get()); | 490 queue->SetTimeDomain(time_domain_.get()); |
484 SchedulePumpQueue(FROM_HERE, lazy_now.Now(), queue); | 491 SchedulePumpQueue(FROM_HERE, lazy_now.Now(), queue); |
485 } | 492 } |
486 | 493 |
487 TRACE_EVENT0(tracing_category_, "TaskQueueThrottler_EnableThrottling"); | 494 TRACE_EVENT0(tracing_category_, "TaskQueueThrottler_EnableThrottling"); |
488 } | 495 } |
489 | 496 |
490 } // namespace scheduler | 497 } // namespace scheduler |
491 } // namespace blink | 498 } // namespace blink |
OLD | NEW |