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

Side by Side Diff: chrome/browser/task_manager/sampling/shared_sampler_win.cc

Issue 2573183002: Add process start time and CPU time columns to task manager (Closed)
Patch Set: Fix nits Created 4 years 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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_manager/sampling/shared_sampler.h" 5 #include "chrome/browser/task_manager/sampling/shared_sampler.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <winternl.h> 8 #include <winternl.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 ULONG context_switches; 213 ULONG context_switches;
214 }; 214 };
215 215
216 // Per-process data extracted from SYSTEM_PROCESS_INFORMATION and stored in a 216 // Per-process data extracted from SYSTEM_PROCESS_INFORMATION and stored in a
217 // snapshot. This structure is accessed only on the worker thread. 217 // snapshot. This structure is accessed only on the worker thread.
218 struct ProcessData { 218 struct ProcessData {
219 ProcessData() = default; 219 ProcessData() = default;
220 ProcessData(ProcessData&&) = default; 220 ProcessData(ProcessData&&) = default;
221 221
222 int64_t physical_bytes; 222 int64_t physical_bytes;
223 int64_t start_time;
224 int64_t cpu_time;
223 std::vector<ThreadData> threads; 225 std::vector<ThreadData> threads;
224 226
225 private: 227 private:
226 DISALLOW_COPY_AND_ASSIGN(ProcessData); 228 DISALLOW_COPY_AND_ASSIGN(ProcessData);
227 }; 229 };
228 230
229 typedef std::map<base::ProcessId, ProcessData> ProcessDataMap; 231 typedef std::map<base::ProcessId, ProcessData> ProcessDataMap;
230 232
231 ULONG CountContextSwitchesDelta(const ProcessData& prev_process_data, 233 ULONG CountContextSwitchesDelta(const ProcessData& prev_process_data,
232 const ProcessData& new_process_data) { 234 const ProcessData& new_process_data) {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 // This object will be created on the UI thread, however the sequenced checker 308 // This object will be created on the UI thread, however the sequenced checker
307 // will be used to assert we're running the expensive operations on one of the 309 // will be used to assert we're running the expensive operations on one of the
308 // blocking pool threads. 310 // blocking pool threads.
309 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 311 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
310 worker_pool_sequenced_checker_.DetachFromSequence(); 312 worker_pool_sequenced_checker_.DetachFromSequence();
311 } 313 }
312 314
313 SharedSampler::~SharedSampler() {} 315 SharedSampler::~SharedSampler() {}
314 316
315 int64_t SharedSampler::GetSupportedFlags() const { 317 int64_t SharedSampler::GetSupportedFlags() const {
316 return REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_PHYSICAL_MEMORY; 318 return REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_PHYSICAL_MEMORY |
319 REFRESH_TYPE_START_TIME | REFRESH_TYPE_CPU_TIME;
317 } 320 }
318 321
319 SharedSampler::Callbacks::Callbacks() {} 322 SharedSampler::Callbacks::Callbacks() {}
320 323
321 SharedSampler::Callbacks::~Callbacks() {} 324 SharedSampler::Callbacks::~Callbacks() {}
322 325
323 SharedSampler::Callbacks::Callbacks(Callbacks&& other) { 326 SharedSampler::Callbacks::Callbacks(Callbacks&& other) {
324 on_idle_wakeups = std::move(other.on_idle_wakeups); 327 on_idle_wakeups = std::move(other.on_idle_wakeups);
325 on_physical_memory = std::move(other.on_physical_memory); 328 on_physical_memory = std::move(other.on_physical_memory);
329 on_start_time = std::move(other.on_start_time);
330 on_cpu_time = std::move(other.on_cpu_time);
brucedawson 2016/12/19 21:51:05 Why is std::move being used here? It offers no val
326 } 331 }
327 332
328 void SharedSampler::RegisterCallbacks( 333 void SharedSampler::RegisterCallbacks(
329 base::ProcessId process_id, 334 base::ProcessId process_id,
330 const OnIdleWakeupsCallback& on_idle_wakeups, 335 const OnIdleWakeupsCallback& on_idle_wakeups,
331 const OnPhysicalMemoryCallback& on_physical_memory) { 336 const OnPhysicalMemoryCallback& on_physical_memory,
337 const OnStartTimeCallback& on_start_time,
338 const OnCpuTimeCallback& on_cpu_time) {
332 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 339 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
333 340
334 if (process_id == 0) 341 if (process_id == 0)
335 return; 342 return;
336 343
337 Callbacks callbacks; 344 Callbacks callbacks;
338 callbacks.on_idle_wakeups = on_idle_wakeups; 345 callbacks.on_idle_wakeups = on_idle_wakeups;
339 callbacks.on_physical_memory = on_physical_memory; 346 callbacks.on_physical_memory = on_physical_memory;
347 callbacks.on_start_time = on_start_time;
348 callbacks.on_cpu_time = on_cpu_time;
340 bool result = callbacks_map_.insert( 349 bool result = callbacks_map_.insert(
341 std::make_pair(process_id, std::move(callbacks))).second; 350 std::make_pair(process_id, std::move(callbacks))).second;
342 DCHECK(result); 351 DCHECK(result);
343 } 352 }
344 353
345 void SharedSampler::UnregisterCallbacks(base::ProcessId process_id) { 354 void SharedSampler::UnregisterCallbacks(base::ProcessId process_id) {
346 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 355 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
347 356
348 if (process_id == 0) 357 if (process_id == 0)
349 return; 358 return;
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 // terminated the total number of context switches for the process might 489 // terminated the total number of context switches for the process might
481 // go down and the delta would be negative. 490 // go down and the delta would be negative.
482 // To avoid that we need to compare thread IDs between two snapshots and 491 // To avoid that we need to compare thread IDs between two snapshots and
483 // not count context switches for threads that are missing in the most 492 // not count context switches for threads that are missing in the most
484 // recent snapshot. 493 // recent snapshot.
485 ProcessData process_data; 494 ProcessData process_data;
486 495
487 process_data.physical_bytes = 496 process_data.physical_bytes =
488 static_cast<int64_t>(pi->WorkingSetPrivateSize); 497 static_cast<int64_t>(pi->WorkingSetPrivateSize);
489 498
499 process_data.start_time = static_cast<int64_t>(pi->CreateTime);
brucedawson 2016/12/19 21:51:05 What happens if you use uint64_t for start_time an
chengx 2016/12/20 00:51:12 Done.
500
501 process_data.cpu_time =
502 static_cast<int64_t>(pi->KernelTime + pi->UserTime);
503
490 // Iterate over threads and store each thread's ID and number of context 504 // Iterate over threads and store each thread's ID and number of context
491 // switches. 505 // switches.
492 for (ULONG thread_index = 0; thread_index < pi->NumberOfThreads; 506 for (ULONG thread_index = 0; thread_index < pi->NumberOfThreads;
493 ++thread_index) { 507 ++thread_index) {
494 const SYSTEM_THREAD_INFORMATION* ti = &pi->Threads[thread_index]; 508 const SYSTEM_THREAD_INFORMATION* ti = &pi->Threads[thread_index];
495 if (ti->ClientId.UniqueProcess != pi->ProcessId) 509 if (ti->ClientId.UniqueProcess != pi->ProcessId)
496 continue; 510 continue;
497 511
498 ThreadData thread_data; 512 ThreadData thread_data;
499 thread_data.thread_id = static_cast<base::PlatformThreadId>( 513 thread_data.thread_id = static_cast<base::PlatformThreadId>(
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 // Process is missing in the previous snapshot. 571 // Process is missing in the previous snapshot.
558 // Use entire number of context switches of the current process. 572 // Use entire number of context switches of the current process.
559 idle_wakeups_delta = CountContextSwitchesDelta(ProcessData(), process); 573 idle_wakeups_delta = CountContextSwitchesDelta(ProcessData(), process);
560 } 574 }
561 575
562 RefreshResult result; 576 RefreshResult result;
563 result.process_id = process_id; 577 result.process_id = process_id;
564 result.idle_wakeups_per_second = 578 result.idle_wakeups_per_second =
565 static_cast<int>(round(idle_wakeups_delta / time_delta)); 579 static_cast<int>(round(idle_wakeups_delta / time_delta));
566 result.physical_bytes = process.physical_bytes; 580 result.physical_bytes = process.physical_bytes;
581 result.start_time = process.start_time;
582 result.cpu_time = process.cpu_time;
567 results->push_back(result); 583 results->push_back(result);
568 } 584 }
569 } 585 }
570 586
571 void SharedSampler::MakeResultsFromSnapshot(const ProcessDataSnapshot& snapshot, 587 void SharedSampler::MakeResultsFromSnapshot(const ProcessDataSnapshot& snapshot,
572 RefreshResults* results) { 588 RefreshResults* results) {
573 for (const auto& pair : snapshot.processes) { 589 for (const auto& pair : snapshot.processes) {
574 RefreshResult result; 590 RefreshResult result;
575 result.process_id = pair.first; 591 result.process_id = pair.first;
576 // Use 0 for Idle Wakeups / sec in this case. This is consistent with 592 // Use 0 for Idle Wakeups / sec in this case. This is consistent with
577 // ProcessMetrics::CalculateIdleWakeupsPerSecond implementation. 593 // ProcessMetrics::CalculateIdleWakeupsPerSecond implementation.
578 result.idle_wakeups_per_second = 0; 594 result.idle_wakeups_per_second = 0;
579 result.physical_bytes = pair.second.physical_bytes; 595 result.physical_bytes = pair.second.physical_bytes;
596 result.start_time = pair.second.start_time;
597 result.cpu_time = pair.second.cpu_time;
580 results->push_back(result); 598 results->push_back(result);
581 } 599 }
582 } 600 }
583 601
584 void SharedSampler::OnRefreshDone( 602 void SharedSampler::OnRefreshDone(
585 std::unique_ptr<RefreshResults> refresh_results) { 603 std::unique_ptr<RefreshResults> refresh_results) {
586 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 604 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
587 DCHECK_NE(0, refresh_flags_); 605 DCHECK_NE(0, refresh_flags_);
588 606
589 size_t result_index = 0; 607 size_t result_index = 0;
590 608
591 for (const auto& callback_entry : callbacks_map_) { 609 for (const auto& callback_entry : callbacks_map_) {
592 base::ProcessId process_id = callback_entry.first; 610 base::ProcessId process_id = callback_entry.first;
593 // A sentinel value of -1 is used when the result isn't available. 611 // A sentinel value of -1 is used when the result isn't available.
594 // Task manager will use this to display 'N/A'. 612 // Task manager will use this to display 'N/A'.
595 int idle_wakeups_per_second = -1; 613 int idle_wakeups_per_second = -1;
596 int64_t physical_bytes = -1; 614 int64_t physical_bytes = -1;
615 int64_t start_time = -1;
616 int64_t cpu_time = -1;
597 617
598 // Match refresh result by |process_id|. 618 // Match refresh result by |process_id|.
599 // This relies on refresh results being ordered by Process ID. 619 // This relies on refresh results being ordered by Process ID.
600 // Please note that |refresh_results| might contain some extra entries that 620 // Please note that |refresh_results| might contain some extra entries that
601 // don't exist in |callbacks_map_| if there is more than one instance of 621 // don't exist in |callbacks_map_| if there is more than one instance of
602 // Chrome. It might be missing some entries too if there is a race condition 622 // Chrome. It might be missing some entries too if there is a race condition
603 // between getting process information on the worker thread and adding a 623 // between getting process information on the worker thread and adding a
604 // corresponding TaskGroup to the task manager. 624 // corresponding TaskGroup to the task manager.
605 for (; result_index < refresh_results->size(); ++result_index) { 625 for (; result_index < refresh_results->size(); ++result_index) {
606 const auto& result = (*refresh_results)[result_index]; 626 const auto& result = (*refresh_results)[result_index];
607 if (result.process_id == process_id) { 627 if (result.process_id == process_id) {
608 // Data matched in |refresh_results|. 628 // Data matched in |refresh_results|.
609 idle_wakeups_per_second = result.idle_wakeups_per_second; 629 idle_wakeups_per_second = result.idle_wakeups_per_second;
610 physical_bytes = result.physical_bytes; 630 physical_bytes = result.physical_bytes;
631 start_time = result.start_time;
632 cpu_time = result.cpu_time;
611 ++result_index; 633 ++result_index;
612 break; 634 break;
613 } 635 }
614 636
615 if (result.process_id > process_id) { 637 if (result.process_id > process_id) {
616 // An entry corresponding to |process_id| is missing. See above. 638 // An entry corresponding to |process_id| is missing. See above.
617 break; 639 break;
618 } 640 }
619 } 641 }
620 642
621 if (TaskManagerObserver::IsResourceRefreshEnabled(REFRESH_TYPE_IDLE_WAKEUPS, 643 if (TaskManagerObserver::IsResourceRefreshEnabled(REFRESH_TYPE_IDLE_WAKEUPS,
622 refresh_flags_)) { 644 refresh_flags_)) {
623 DCHECK(callback_entry.second.on_idle_wakeups); 645 DCHECK(callback_entry.second.on_idle_wakeups);
624 callback_entry.second.on_idle_wakeups.Run(idle_wakeups_per_second); 646 callback_entry.second.on_idle_wakeups.Run(idle_wakeups_per_second);
625 } 647 }
626 648
627 if (TaskManagerObserver::IsResourceRefreshEnabled( 649 if (TaskManagerObserver::IsResourceRefreshEnabled(
628 REFRESH_TYPE_PHYSICAL_MEMORY, refresh_flags_)) { 650 REFRESH_TYPE_PHYSICAL_MEMORY, refresh_flags_)) {
629 DCHECK(callback_entry.second.on_physical_memory); 651 DCHECK(callback_entry.second.on_physical_memory);
630 callback_entry.second.on_physical_memory.Run(physical_bytes); 652 callback_entry.second.on_physical_memory.Run(physical_bytes);
631 } 653 }
654
655 if (TaskManagerObserver::IsResourceRefreshEnabled(REFRESH_TYPE_START_TIME,
656 refresh_flags_)) {
657 DCHECK(callback_entry.second.on_start_time);
658 callback_entry.second.on_start_time.Run(start_time);
659 }
660
661 if (TaskManagerObserver::IsResourceRefreshEnabled(REFRESH_TYPE_CPU_TIME,
662 refresh_flags_)) {
663 DCHECK(callback_entry.second.on_cpu_time);
664 callback_entry.second.on_cpu_time.Run(cpu_time);
665 }
632 } 666 }
633 667
634 // Reset refresh_results_ to trigger RefreshOnWorkerThread next time Refresh 668 // Reset refresh_results_ to trigger RefreshOnWorkerThread next time Refresh
635 // is called. 669 // is called.
636 refresh_flags_ = 0; 670 refresh_flags_ = 0;
637 } 671 }
638 672
639 } // namespace task_manager 673 } // namespace task_manager
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698