commit 7267ee8b9a4f4632607186ff33f711ba671ae5b1
parent bac754a046f857fada39f1a12adf3c8a7627a1d8
Author: Jens Stutte <jstutte@mozilla.com>
Date: Mon, 3 Nov 2025 14:08:41 +0000
Bug 1997924 - Avoid memory allocations in ProcessUpdatedPriorityModifier. r=bas
We can leverage std::set's extract / insert to avoid allocations when updating task priorities.
It is assumed that this is always better, also for a small number of tasks.
Differential Revision: https://phabricator.services.mozilla.com/D269142
Diffstat:
2 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/xpcom/threads/TaskController.cpp b/xpcom/threads/TaskController.cpp
@@ -1494,26 +1494,22 @@ void TaskController::ProcessUpdatedPriorityModifier(TaskManager* aManager) {
int32_t modifier = aManager->mCurrentPriorityModifier;
- std::vector<RefPtr<Task>> storedTasks;
- // Find all relevant tasks.
- for (auto iter = mMainThreadTasks.begin(); iter != mMainThreadTasks.end();) {
- if ((*iter)->mTaskManager == aManager) {
- storedTasks.push_back(*iter);
- iter = mMainThreadTasks.erase(iter);
- } else {
- iter++;
+ // Find all relevant task nodes and move them to a temporary set with the
+ // new priority modifier.
+ PrioritySortedTasks managerTasks;
+ auto cur = mMainThreadTasks.begin();
+ while (cur != mMainThreadTasks.end()) {
+ // Keep a valid iterator before potentially extracting the current task.
+ auto next = std::next(cur);
+ if (cur->get()->mTaskManager == aManager) {
+ auto task = mMainThreadTasks.extract(cur);
+ task.value()->mPriorityModifier = modifier;
+ managerTasks.insert(std::move(task));
}
+ cur = std::move(next);
}
-
- // Reinsert found tasks with their new priorities.
- for (RefPtr<Task>& ref : storedTasks) {
- // Kept alive at first by the vector and then by mMainThreadTasks.
- Task* task = ref;
- task->mPriorityModifier = modifier;
- auto insertion = mMainThreadTasks.insert(std::move(ref));
- MOZ_ASSERT(insertion.second);
- task->mIterator = insertion.first;
- }
+ // Merge the temporary set back to the main set.
+ mMainThreadTasks.merge(std::move(managerTasks));
}
} // namespace mozilla
diff --git a/xpcom/threads/TaskController.h b/xpcom/threads/TaskController.h
@@ -431,8 +431,9 @@ class TaskController {
std::stack<RefPtr<Task>> mCurrentTasksMT;
// A list of all tasks ordered by priority.
- std::set<RefPtr<Task>, Task::PriorityCompare> mThreadableTasks;
- std::set<RefPtr<Task>, Task::PriorityCompare> mMainThreadTasks;
+ using PrioritySortedTasks = std::set<RefPtr<Task>, Task::PriorityCompare>;
+ PrioritySortedTasks mThreadableTasks;
+ PrioritySortedTasks mMainThreadTasks;
// TaskManagers currently active.
// We can use a raw pointer since tasks always hold on to their TaskManager.