| 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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 if (!allow_throttling_) | 163 if (!allow_throttling_) |
| 164 return false; | 164 return false; |
| 165 | 165 |
| 166 auto find_it = queue_details_.find(task_queue); | 166 auto find_it = queue_details_.find(task_queue); |
| 167 if (find_it == queue_details_.end()) | 167 if (find_it == queue_details_.end()) |
| 168 return false; | 168 return false; |
| 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_); | |
| 174 auto find_it = queue_details_.find(task_queue); | 173 auto find_it = queue_details_.find(task_queue); |
| 175 | |
| 176 if (find_it == queue_details_.end()) | 174 if (find_it == queue_details_.end()) |
| 177 return; | 175 return; |
| 178 | 176 |
| 179 if (find_it->second.budget_pool) | 177 LazyNow lazy_now(tick_clock_); |
| 180 find_it->second.budget_pool->RemoveQueue(lazy_now.Now(), task_queue); | 178 std::unordered_set<BudgetPool*> budget_pools = find_it->second.budget_pools; |
| 179 for (BudgetPool* budget_pool : budget_pools) { |
| 180 budget_pool->RemoveQueue(lazy_now.Now(), task_queue); |
| 181 } |
| 181 | 182 |
| 182 queue_details_.erase(find_it); | 183 // Iterator may have been deleted by BudgetPool::RemoveQueue, so don't |
| 184 // use it here. |
| 185 queue_details_.erase(task_queue); |
| 183 } | 186 } |
| 184 | 187 |
| 185 void TaskQueueThrottler::OnTimeDomainHasImmediateWork(TaskQueue* queue) { | 188 void TaskQueueThrottler::OnTimeDomainHasImmediateWork(TaskQueue* queue) { |
| 186 // Forward to the main thread if called from another thread | 189 // Forward to the main thread if called from another thread |
| 187 if (!task_runner_->RunsTasksOnCurrentThread()) { | 190 if (!task_runner_->RunsTasksOnCurrentThread()) { |
| 188 task_runner_->PostTask(FROM_HERE, | 191 task_runner_->PostTask(FROM_HERE, |
| 189 base::Bind(forward_immediate_work_callback_, queue)); | 192 base::Bind(forward_immediate_work_callback_, queue)); |
| 190 return; | 193 return; |
| 191 } | 194 } |
| 192 TRACE_EVENT0(tracing_category_, | 195 TRACE_EVENT0(tracing_category_, |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 budget_pools_[time_budget_pool] = base::WrapUnique(time_budget_pool); | 321 budget_pools_[time_budget_pool] = base::WrapUnique(time_budget_pool); |
| 319 return time_budget_pool; | 322 return time_budget_pool; |
| 320 } | 323 } |
| 321 | 324 |
| 322 void TaskQueueThrottler::OnTaskRunTimeReported(TaskQueue* task_queue, | 325 void TaskQueueThrottler::OnTaskRunTimeReported(TaskQueue* task_queue, |
| 323 base::TimeTicks start_time, | 326 base::TimeTicks start_time, |
| 324 base::TimeTicks end_time) { | 327 base::TimeTicks end_time) { |
| 325 if (!IsThrottled(task_queue)) | 328 if (!IsThrottled(task_queue)) |
| 326 return; | 329 return; |
| 327 | 330 |
| 328 BudgetPool* budget_pool = GetBudgetPoolForQueue(task_queue); | 331 auto find_it = queue_details_.find(task_queue); |
| 329 if (!budget_pool) | 332 if (find_it == queue_details_.end()) |
| 330 return; | 333 return; |
| 331 | 334 |
| 332 budget_pool->RecordTaskRunTime(start_time, end_time); | 335 for (BudgetPool* budget_pool : find_it->second.budget_pools) { |
| 333 if (!budget_pool->HasEnoughBudgetToRun(end_time)) | 336 budget_pool->RecordTaskRunTime(start_time, end_time); |
| 334 budget_pool->BlockThrottledQueues(end_time); | 337 if (!budget_pool->HasEnoughBudgetToRun(end_time)) |
| 338 budget_pool->BlockThrottledQueues(end_time); |
| 339 } |
| 335 } | 340 } |
| 336 | 341 |
| 337 void TaskQueueThrottler::BlockQueue(base::TimeTicks now, TaskQueue* queue) { | 342 void TaskQueueThrottler::BlockQueue(base::TimeTicks now, TaskQueue* queue) { |
| 338 if (!IsThrottled(queue)) | 343 if (!IsThrottled(queue)) |
| 339 return; | 344 return; |
| 340 | 345 |
| 341 queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME); | 346 queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME); |
| 342 SchedulePumpQueue(FROM_HERE, now, queue); | 347 SchedulePumpQueue(FROM_HERE, now, queue); |
| 343 } | 348 } |
| 344 | 349 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 371 state->EndDictionary(); | 376 state->EndDictionary(); |
| 372 } | 377 } |
| 373 | 378 |
| 374 void TaskQueueThrottler::AddQueueToBudgetPool(TaskQueue* queue, | 379 void TaskQueueThrottler::AddQueueToBudgetPool(TaskQueue* queue, |
| 375 BudgetPool* budget_pool) { | 380 BudgetPool* budget_pool) { |
| 376 std::pair<TaskQueueMap::iterator, bool> insert_result = | 381 std::pair<TaskQueueMap::iterator, bool> insert_result = |
| 377 queue_details_.insert(std::make_pair(queue, Metadata())); | 382 queue_details_.insert(std::make_pair(queue, Metadata())); |
| 378 | 383 |
| 379 Metadata& metadata = insert_result.first->second; | 384 Metadata& metadata = insert_result.first->second; |
| 380 | 385 |
| 381 DCHECK(!metadata.budget_pool); | 386 DCHECK(metadata.budget_pools.find(budget_pool) == |
| 382 metadata.budget_pool = budget_pool; | 387 metadata.budget_pools.end()); |
| 388 |
| 389 metadata.budget_pools.insert(budget_pool); |
| 383 } | 390 } |
| 384 | 391 |
| 385 void TaskQueueThrottler::RemoveQueueFromBudgetPool(TaskQueue* queue, | 392 void TaskQueueThrottler::RemoveQueueFromBudgetPool(TaskQueue* queue, |
| 386 BudgetPool* budget_pool) { | 393 BudgetPool* budget_pool) { |
| 387 auto find_it = queue_details_.find(queue); | 394 auto find_it = queue_details_.find(queue); |
| 388 DCHECK(find_it != queue_details_.end() && | 395 DCHECK(find_it != queue_details_.end() && |
| 389 find_it->second.budget_pool == budget_pool); | 396 find_it->second.budget_pools.find(budget_pool) != |
| 397 find_it->second.budget_pools.end()); |
| 390 | 398 |
| 391 find_it->second.budget_pool = nullptr; | 399 find_it->second.budget_pools.erase(budget_pool); |
| 392 | 400 |
| 393 MaybeDeleteQueueMetadata(find_it); | 401 MaybeDeleteQueueMetadata(find_it); |
| 394 } | 402 } |
| 395 | 403 |
| 396 void TaskQueueThrottler::UnregisterBudgetPool(BudgetPool* budget_pool) { | 404 void TaskQueueThrottler::UnregisterBudgetPool(BudgetPool* budget_pool) { |
| 397 budget_pools_.erase(budget_pool); | 405 budget_pools_.erase(budget_pool); |
| 398 } | 406 } |
| 399 | 407 |
| 400 void TaskQueueThrottler::UnblockQueue(base::TimeTicks now, TaskQueue* queue) { | 408 void TaskQueueThrottler::UnblockQueue(base::TimeTicks now, TaskQueue* queue) { |
| 401 SchedulePumpQueue(FROM_HERE, now, queue); | 409 SchedulePumpQueue(FROM_HERE, now, queue); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 413 NextTaskRunTime(&lazy_now, queue); | 421 NextTaskRunTime(&lazy_now, queue); |
| 414 if (!next_desired_run_time) | 422 if (!next_desired_run_time) |
| 415 return; | 423 return; |
| 416 | 424 |
| 417 base::Optional<base::TimeTicks> next_run_time = | 425 base::Optional<base::TimeTicks> next_run_time = |
| 418 Max(next_desired_run_time, GetNextAllowedRunTime(now, queue)); | 426 Max(next_desired_run_time, GetNextAllowedRunTime(now, queue)); |
| 419 | 427 |
| 420 MaybeSchedulePumpThrottledTasks(from_here, now, next_run_time.value()); | 428 MaybeSchedulePumpThrottledTasks(from_here, now, next_run_time.value()); |
| 421 } | 429 } |
| 422 | 430 |
| 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, | 431 base::TimeTicks TaskQueueThrottler::GetNextAllowedRunTime(base::TimeTicks now, |
| 431 TaskQueue* queue) { | 432 TaskQueue* queue) { |
| 432 BudgetPool* budget_pool = GetBudgetPoolForQueue(queue); | 433 base::TimeTicks next_run_time = now; |
| 433 if (!budget_pool) | 434 |
| 434 return now; | 435 auto find_it = queue_details_.find(queue); |
| 435 return std::max(now, budget_pool->GetNextAllowedRunTime()); | 436 if (find_it == queue_details_.end()) |
| 437 return next_run_time; |
| 438 |
| 439 for (BudgetPool* budget_pool : find_it->second.budget_pools) { |
| 440 next_run_time = |
| 441 std::max(next_run_time, budget_pool->GetNextAllowedRunTime()); |
| 442 } |
| 443 |
| 444 return next_run_time; |
| 436 } | 445 } |
| 437 | 446 |
| 438 void TaskQueueThrottler::MaybeDeleteQueueMetadata(TaskQueueMap::iterator it) { | 447 void TaskQueueThrottler::MaybeDeleteQueueMetadata(TaskQueueMap::iterator it) { |
| 439 if (it->second.throttling_ref_count == 0 && !it->second.budget_pool) | 448 if (it->second.throttling_ref_count == 0 && it->second.budget_pools.empty()) |
| 440 queue_details_.erase(it); | 449 queue_details_.erase(it); |
| 441 } | 450 } |
| 442 | 451 |
| 443 void TaskQueueThrottler::DisableThrottling() { | 452 void TaskQueueThrottler::DisableThrottling() { |
| 444 if (!allow_throttling_) | 453 if (!allow_throttling_) |
| 445 return; | 454 return; |
| 446 | 455 |
| 447 allow_throttling_ = false; | 456 allow_throttling_ = false; |
| 448 | 457 |
| 449 for (const auto& map_entry : queue_details_) { | 458 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); | 491 queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME); |
| 483 queue->SetTimeDomain(time_domain_.get()); | 492 queue->SetTimeDomain(time_domain_.get()); |
| 484 SchedulePumpQueue(FROM_HERE, lazy_now.Now(), queue); | 493 SchedulePumpQueue(FROM_HERE, lazy_now.Now(), queue); |
| 485 } | 494 } |
| 486 | 495 |
| 487 TRACE_EVENT0(tracing_category_, "TaskQueueThrottler_EnableThrottling"); | 496 TRACE_EVENT0(tracing_category_, "TaskQueueThrottler_EnableThrottling"); |
| 488 } | 497 } |
| 489 | 498 |
| 490 } // namespace scheduler | 499 } // namespace scheduler |
| 491 } // namespace blink | 500 } // namespace blink |
| OLD | NEW |