Chromium Code Reviews| 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 |