| 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 f87e71505f90a01957d12fc0c169061610bb7e58..277b909a4c692a5f47b8a02d4621e4f869d8821f 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:
|
| @@ -284,6 +287,17 @@ const ProcessData* SeekInPreviousSnapshot(
|
| return nullptr;
|
| }
|
|
|
| +// 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);
|
| +}
|
| +
|
| } // namespace
|
|
|
| // ProcessDataSnapshot gets created and accessed only on the worker thread.
|
| @@ -313,7 +327,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 +338,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 +356,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);
|
| @@ -493,6 +514,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;
|
| @@ -570,6 +596,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);
|
| }
|
| }
|
| @@ -583,6 +611,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);
|
| }
|
| }
|
| @@ -597,9 +627,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.
|
| @@ -614,6 +646,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;
|
| }
|
| @@ -635,6 +669,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
|
|
|