Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(679)

Side by Side Diff: chrome/browser/task_management/sampling/task_manager_impl.cc

Issue 2028753002: Make Task Manager sort more meaningful (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use a default argument instead of a second ctor. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "chrome/browser/task_management/sampling/task_manager_impl.h" 5 #include "chrome/browser/task_management/sampling/task_manager_impl.h"
6 6
7 #include <algorithm>
7 #include <string> 8 #include <string>
9 #include <unordered_map>
8 #include <vector> 10 #include <vector>
9 11
10 #include "base/command_line.h" 12 #include "base/command_line.h"
11 #include "base/stl_util.h" 13 #include "base/stl_util.h"
12 #include "build/build_config.h" 14 #include "build/build_config.h"
13 #include "chrome/browser/task_management/providers/browser_process_task_provider .h" 15 #include "chrome/browser/task_management/providers/browser_process_task_provider .h"
14 #include "chrome/browser/task_management/providers/child_process_task_provider.h " 16 #include "chrome/browser/task_management/providers/child_process_task_provider.h "
15 #include "chrome/browser/task_management/providers/web_contents/web_contents_tas k_provider.h" 17 #include "chrome/browser/task_management/providers/web_contents/web_contents_tas k_provider.h"
16 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/gpu_data_manager.h" 19 #include "content/public/browser/gpu_data_manager.h"
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 *stats = task->GetWebCacheStats(); 241 *stats = task->GetWebCacheStats();
240 242
241 return true; 243 return true;
242 } 244 }
243 245
244 const TaskIdList& TaskManagerImpl::GetTaskIdsList() const { 246 const TaskIdList& TaskManagerImpl::GetTaskIdsList() const {
245 DCHECK(is_running_) << "Task manager is not running. You must observe the " 247 DCHECK(is_running_) << "Task manager is not running. You must observe the "
246 "task manager for it to start running"; 248 "task manager for it to start running";
247 249
248 if (sorted_task_ids_.empty()) { 250 if (sorted_task_ids_.empty()) {
249 sorted_task_ids_.reserve(task_groups_by_task_id_.size()); 251 // |comparator| groups and sorts by subtask-ness (to push all subtasks to be
252 // last), then by process type (e.g. the browser process should be first;
253 // renderer processes should be together), then tab id (processes used by
254 // the same tab should be kept together, and a tab should have a stable
255 // position in the list as it cycles through processes, and tab creation
256 // order is meaningful), and finally by task id (when all else is equal, put
257 // the oldest tasks first).
258 auto comparator = [](const Task* a, const Task* b) -> bool {
259 return std::make_tuple(!!a->GetParentTask(), a->GetType(), a->GetTabId(),
afakhry 2016/06/06 18:11:59 First, using a tuple is brilliant. Second, how ab
ncarter (slow) 2016/06/20 17:40:00 Done.
260 a->task_id()) <
ncarter (slow) 2016/06/08 21:37:50 FYI using tuples for lexicographic comparison is a
afakhry 2016/06/09 13:33:53 Thanks for sharing! I liked the std::tie example.
261 std::make_tuple(!!b->GetParentTask(), b->GetType(), b->GetTabId(),
262 b->task_id());
263 };
250 264
251 // Ensure browser process group of task IDs are at the beginning of the 265 const size_t num_groups = task_groups_by_proc_id_.size();
252 // list. 266 const size_t num_tasks = task_groups_by_task_id_.size();
253 auto it = task_groups_by_proc_id_.find(base::GetCurrentProcId());
254 DCHECK(it != task_groups_by_proc_id_.end());
255 const TaskGroup* browser_group = it->second;
256 browser_group->AppendSortedTaskIds(&sorted_task_ids_);
257 267
268 // Populate |tasks_to_visit| with one task from each group.
269 std::vector<const Task*> tasks_to_visit;
270 tasks_to_visit.reserve(num_groups);
271 std::unordered_map<const Task*, std::vector<const Task*>> children;
afakhry 2016/06/06 18:11:59 Optional: Tracking the children here using a prior
ncarter (slow) 2016/06/08 21:37:50 Interesting idea. They're essentially the same und
afakhry 2016/06/09 13:33:53 Yes, they're definitely the same algorithm. The su
ncarter (slow) 2016/06/20 17:39:59 Thanks for this suggestion. My overall sense is th
afakhry 2016/06/22 13:49:46 Acknowledged.
258 for (const auto& groups_pair : task_groups_by_proc_id_) { 272 for (const auto& groups_pair : task_groups_by_proc_id_) {
259 if (groups_pair.second == browser_group) 273 // The first task in the group (per |comparator|) is the one used for
274 // sorting the group relative to other groups.
275 const std::vector<Task*>& tasks = groups_pair.second->tasks();
276 Task* group_task =
277 *std::min_element(tasks.begin(), tasks.end(), comparator);
278 tasks_to_visit.push_back(group_task);
279
280 // Build the parent-to-child map, for use later.
281 for (const Task* task : tasks) {
282 if (task->GetParentTask())
283 children[task->GetParentTask()].push_back(task);
284 else
285 DCHECK(group_task->GetParentTask() == nullptr);
286 }
287 }
288
289 // Now sort |tasks_to_visit| in reverse order (putting the browser process
290 // at back()). We will treat it as a stack from now on.
291 std::sort(tasks_to_visit.rbegin(), tasks_to_visit.rend(), comparator);
292 DCHECK_EQ(Task::BROWSER, tasks_to_visit.back()->GetType());
293
294 // Using |tasks_to_visit| as a stack, and |visited_groups| to track which
295 // groups we've already added, add groups to |sorted_task_ids_| until all
296 // groups have been added.
297 sorted_task_ids_.reserve(num_tasks);
298 std::unordered_set<TaskGroup*> visited_groups;
afakhry 2016/06/03 17:53:42 Do you need to #include <unordered_set>?
ncarter (slow) 2016/06/20 17:39:59 Done.
299 visited_groups.reserve(num_groups);
300 std::vector<Task*> current_group_tasks; // Outside loop for fewer mallocs.
301 while (visited_groups.size() < num_groups) {
302 CHECK(!tasks_to_visit.empty());
afakhry 2016/06/06 18:11:59 I think a DCHECK() is enough here.
ncarter (slow) 2016/06/20 17:40:00 Done.
303 TaskGroup* current_group =
304 GetTaskGroupByTaskId(tasks_to_visit.back()->task_id());
305 tasks_to_visit.pop_back();
306
307 // Mark |current_group| as visited. If this fails, we've already added
308 // the group, and should skip over it.
309 if (!visited_groups.insert(current_group).second)
260 continue; 310 continue;
261 311
262 groups_pair.second->AppendSortedTaskIds(&sorted_task_ids_); 312 // Make a copy of |current_group->tasks()|, sort it, and append the ids.
313 current_group_tasks = current_group->tasks();
314 std::sort(current_group_tasks.begin(), current_group_tasks.end(),
315 comparator);
316 for (Task* task : current_group_tasks) {
afakhry 2016/06/03 17:53:42 const auto& ?
afakhry 2016/06/03 17:53:42 Nit: Remove curly braces.
ncarter (slow) 2016/06/20 17:39:59 Done.
ncarter (slow) 2016/06/20 17:40:00 I prefer Task* here, since it makes it clearer to
afakhry 2016/06/22 13:49:46 It may or may not. const auto& is generally prefer
317 sorted_task_ids_.push_back(task->task_id());
318 }
319
320 // Find the children of the tasks we just added, and push them into
321 // |tasks_to_visit|, so that we visit them soon. Push in reverse order,
322 // so that we visit them in forward order.
323 for (auto parent_task = current_group_tasks.rbegin();
324 parent_task != current_group_tasks.rend(); ++parent_task) {
325 auto children_it = children.find(*parent_task);
326 if (children_it != children.end()) {
327 std::vector<const Task*>& children = children_it->second;
afakhry 2016/06/03 17:53:42 This children vector hides the outer children unor
ncarter (slow) 2016/06/08 21:37:50 YUCK. Thanks for pointing this out, it was an acci
afakhry 2016/06/09 13:33:53 I think you got lucky as you were only accessing |
ncarter (slow) 2016/06/20 17:40:00 Done.
328 std::sort(children.begin(), children.end(), comparator);
329 tasks_to_visit.insert(tasks_to_visit.end(), children.rbegin(),
330 children.rend());
331 }
332 }
263 } 333 }
334 DCHECK_EQ(num_tasks, sorted_task_ids_.size());
264 } 335 }
265 336
266 return sorted_task_ids_; 337 return sorted_task_ids_;
267 } 338 }
268 339
269 TaskIdList TaskManagerImpl::GetIdsOfTasksSharingSameProcess( 340 TaskIdList TaskManagerImpl::GetIdsOfTasksSharingSameProcess(
270 TaskId task_id) const { 341 TaskId task_id) const {
271 DCHECK(is_running_) << "Task manager is not running. You must observe the " 342 DCHECK(is_running_) << "Task manager is not running. You must observe the "
272 "task manager for it to start running"; 343 "task manager for it to start running";
273 344
274 TaskIdList result; 345 TaskIdList result;
275 GetTaskGroupByTaskId(task_id)->AppendSortedTaskIds(&result); 346 TaskGroup* group = GetTaskGroupByTaskId(task_id);
347 if (group) {
348 result.reserve(group->tasks().size());
349 for (Task* task : group->tasks()) {
afakhry 2016/06/03 17:53:42 Nit: the curly braces.
afakhry 2016/06/03 17:53:42 Also const auto& ?
ncarter (slow) 2016/06/20 17:39:59 I prefer 'Task*' to 'const auto&' here; it's is fe
ncarter (slow) 2016/06/20 17:40:00 Done.
afakhry 2016/06/22 13:49:46 Acknowledged.
350 result.push_back(task->task_id());
351 }
352 }
276 return result; 353 return result;
277 } 354 }
278 355
279 size_t TaskManagerImpl::GetNumberOfTasksOnSameProcess(TaskId task_id) const { 356 size_t TaskManagerImpl::GetNumberOfTasksOnSameProcess(TaskId task_id) const {
280 return GetTaskGroupByTaskId(task_id)->num_tasks(); 357 return GetTaskGroupByTaskId(task_id)->num_tasks();
281 } 358 }
282 359
283 void TaskManagerImpl::TaskAdded(Task* task) { 360 void TaskManagerImpl::TaskAdded(Task* task) {
284 DCHECK(task); 361 DCHECK(task);
285 362
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 groups_itr.second->AreBackgroundCalculationsDone(); 522 groups_itr.second->AreBackgroundCalculationsDone();
446 } 523 }
447 if (are_all_processes_data_ready) { 524 if (are_all_processes_data_ready) {
448 NotifyObserversOnRefreshWithBackgroundCalculations(GetTaskIdsList()); 525 NotifyObserversOnRefreshWithBackgroundCalculations(GetTaskIdsList());
449 for (const auto& groups_itr : task_groups_by_proc_id_) 526 for (const auto& groups_itr : task_groups_by_proc_id_)
450 groups_itr.second->ClearCurrentBackgroundCalculationsFlags(); 527 groups_itr.second->ClearCurrentBackgroundCalculationsFlags();
451 } 528 }
452 } 529 }
453 530
454 } // namespace task_management 531 } // namespace task_management
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698