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 |