Chromium Code Reviews| Index: chrome/browser/task_manager/sampling/shared_sampler_win.cc |
| diff --git a/chrome/browser/task_manager/sampling/shared_sampler_win.cc b/chrome/browser/task_manager/sampling/shared_sampler_win.cc |
| index e54e2f8295795c7be25563d0f41d3d330498eecf..a0986d5935768906276cbf25efb2e89e789c5bc4 100644 |
| --- a/chrome/browser/task_manager/sampling/shared_sampler_win.cc |
| +++ b/chrome/browser/task_manager/sampling/shared_sampler_win.cc |
| @@ -10,6 +10,7 @@ |
| #include <algorithm> |
| #include "base/bind.h" |
| +#include "base/bit_cast.h" |
| #include "base/command_line.h" |
| #include "base/path_service.h" |
| #include "base/time/time.h" |
| @@ -220,6 +221,8 @@ struct ProcessData { |
| ProcessData(ProcessData&&) = default; |
| int64_t physical_bytes; |
| + base::Time start_time; |
| + base::TimeDelta cpu_time; |
| std::vector<ThreadData> threads; |
| private: |
| @@ -313,7 +316,8 @@ SharedSampler::SharedSampler( |
| SharedSampler::~SharedSampler() {} |
| int64_t SharedSampler::GetSupportedFlags() const { |
| - return REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_PHYSICAL_MEMORY; |
| + return REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_PHYSICAL_MEMORY | |
| + REFRESH_TYPE_START_TIME | REFRESH_TYPE_CPU_TIME; |
| } |
| SharedSampler::Callbacks::Callbacks() {} |
| @@ -323,12 +327,16 @@ SharedSampler::Callbacks::~Callbacks() {} |
| SharedSampler::Callbacks::Callbacks(Callbacks&& other) { |
| on_idle_wakeups = std::move(other.on_idle_wakeups); |
| on_physical_memory = std::move(other.on_physical_memory); |
| + on_start_time = std::move(other.on_start_time); |
| + on_cpu_time = std::move(other.on_cpu_time); |
| } |
| void SharedSampler::RegisterCallbacks( |
| base::ProcessId process_id, |
| const OnIdleWakeupsCallback& on_idle_wakeups, |
| - const OnPhysicalMemoryCallback& on_physical_memory) { |
| + const OnPhysicalMemoryCallback& on_physical_memory, |
| + const OnStartTimeCallback& on_start_time, |
| + const OnCpuTimeCallback& on_cpu_time) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| if (process_id == 0) |
| @@ -337,6 +345,8 @@ void SharedSampler::RegisterCallbacks( |
| Callbacks callbacks; |
| callbacks.on_idle_wakeups = on_idle_wakeups; |
| callbacks.on_physical_memory = on_physical_memory; |
| + callbacks.on_start_time = on_start_time; |
| + callbacks.on_cpu_time = on_cpu_time; |
| bool result = callbacks_map_.insert( |
| std::make_pair(process_id, std::move(callbacks))).second; |
| DCHECK(result); |
| @@ -433,6 +443,19 @@ bool SharedSampler::IsSupportedImageName( |
| return false; |
| } |
| +namespace { |
|
afakhry
2017/01/09 21:03:42
Nit: Usually we have a single anonymous namespace
chengx
2017/01/10 00:39:27
I have moved these two functions to the existing a
|
| +// A wrapper function converting ticks (in units of 100 ns) to Time. |
| +base::Time ConvertTicksToTime(uint64_t ticks) { |
| + FILETIME ft = bit_cast<FILETIME, uint64_t>(ticks); |
| + return base::Time::FromFileTime(ft); |
| +} |
| + |
| +// A wrapper function converting ticks (in units of 100 ns) to TimeDelta. |
| +base::TimeDelta ConvertTicksToTimeDelta(uint64_t ticks) { |
| + return base::TimeDelta::FromMicroseconds(ticks / 10); |
| +} |
| +} |
|
afakhry
2017/01/09 21:03:42
Nit: } // namespace
chengx
2017/01/10 00:39:27
Done.
|
| + |
| std::unique_ptr<ProcessDataSnapshot> SharedSampler::CaptureSnapshot() { |
| DCHECK(worker_pool_sequenced_checker_.CalledOnValidSequence()); |
| @@ -487,6 +510,11 @@ std::unique_ptr<ProcessDataSnapshot> SharedSampler::CaptureSnapshot() { |
| process_data.physical_bytes = |
| static_cast<int64_t>(pi->WorkingSetPrivateSize); |
| + process_data.start_time = ConvertTicksToTime(pi->CreateTime); |
| + |
| + process_data.cpu_time = |
| + ConvertTicksToTimeDelta(pi->KernelTime + pi->UserTime); |
| + |
| // Iterate over threads and store each thread's ID and number of context |
| // switches. |
| for (ULONG thread_index = 0; thread_index < pi->NumberOfThreads; |
| @@ -564,6 +592,8 @@ void SharedSampler::MakeResultsFromTwoSnapshots( |
| result.idle_wakeups_per_second = |
| static_cast<int>(round(idle_wakeups_delta / time_delta)); |
| result.physical_bytes = process.physical_bytes; |
| + result.start_time = process.start_time; |
| + result.cpu_time = process.cpu_time; |
| results->push_back(result); |
| } |
| } |
| @@ -577,6 +607,8 @@ void SharedSampler::MakeResultsFromSnapshot(const ProcessDataSnapshot& snapshot, |
| // ProcessMetrics::CalculateIdleWakeupsPerSecond implementation. |
| result.idle_wakeups_per_second = 0; |
| result.physical_bytes = pair.second.physical_bytes; |
| + result.start_time = pair.second.start_time; |
| + result.cpu_time = pair.second.cpu_time; |
| results->push_back(result); |
| } |
| } |
| @@ -591,9 +623,11 @@ void SharedSampler::OnRefreshDone( |
| for (const auto& callback_entry : callbacks_map_) { |
| base::ProcessId process_id = callback_entry.first; |
| // A sentinel value of -1 is used when the result isn't available. |
| - // Task manager will use this to display 'N/A'. |
| + // Task manager will use this to display '-'. |
| int idle_wakeups_per_second = -1; |
| int64_t physical_bytes = -1; |
| + base::Time start_time; |
| + base::TimeDelta cpu_time; |
| // Match refresh result by |process_id|. |
| // This relies on refresh results being ordered by Process ID. |
| @@ -608,6 +642,8 @@ void SharedSampler::OnRefreshDone( |
| // Data matched in |refresh_results|. |
| idle_wakeups_per_second = result.idle_wakeups_per_second; |
| physical_bytes = result.physical_bytes; |
| + start_time = result.start_time; |
| + cpu_time = result.cpu_time; |
| ++result_index; |
| break; |
| } |
| @@ -629,6 +665,18 @@ void SharedSampler::OnRefreshDone( |
| DCHECK(callback_entry.second.on_physical_memory); |
| callback_entry.second.on_physical_memory.Run(physical_bytes); |
| } |
| + |
| + if (TaskManagerObserver::IsResourceRefreshEnabled(REFRESH_TYPE_START_TIME, |
| + refresh_flags_)) { |
| + DCHECK(callback_entry.second.on_start_time); |
| + callback_entry.second.on_start_time.Run(start_time); |
| + } |
| + |
| + if (TaskManagerObserver::IsResourceRefreshEnabled(REFRESH_TYPE_CPU_TIME, |
| + refresh_flags_)) { |
| + DCHECK(callback_entry.second.on_cpu_time); |
| + callback_entry.second.on_cpu_time.Run(cpu_time); |
| + } |
| } |
| // Reset refresh_results_ to trigger RefreshOnWorkerThread next time Refresh |