Commit 9bb9067b authored by Jesse McKenna's avatar Jesse McKenna Committed by Commit Bot

IdleWakeups: optionally show CPU time in seconds

This change adds command-line flag --cpu-seconds to IdleWakeups. This
option makes IdleWakeups print absolute CPU time in seconds, rather
than as a percentage.

Because average and median CPU time in seconds are not meaningful
measurements, this also adds a "Sum" row to the summary. This row
appears only when --cpu-seconds is enabled, and displays only CPU
time.

Change-Id: I9bd4efd8712da9ac976eeb8dc435232c63170827
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2441321Reviewed-by: default avatarAlex Gough <ajgo@chromium.org>
Commit-Queue: Jesse McKenna <jessemckenna@google.com>
Cr-Commit-Position: refs/heads/master@{#814030}
parent 0c251a15
...@@ -24,8 +24,11 @@ working set size, number of context switches / sec, and power usage for all ...@@ -24,8 +24,11 @@ working set size, number of context switches / sec, and power usage for all
matched processes. Hit Ctrl-C to stop the measurements and print average and matched processes. Hit Ctrl-C to stop the measurements and print average and
median values over the entire measurement interval. median values over the entire measurement interval.
CPU usage is normalized to one CPU core, with 100% meaning one CPU core is By default, CPU usage is normalized to one CPU core, with 100% meaning one CPU
fully utilized. core is fully utilized.
To view CPU time in seconds rather than by percentage, use command-line option
`--cpu-seconds`.
[Intel Power Gadget](https://software.intel.com/en-us/articles/intel-power-gadget-20) [Intel Power Gadget](https://software.intel.com/en-us/articles/intel-power-gadget-20)
is required to allow IdleWakeups tool to query power usage. is required to allow IdleWakeups tool to query power usage.
...@@ -11,12 +11,16 @@ ...@@ -11,12 +11,16 @@
#include "power_sampler.h" #include "power_sampler.h"
#include "system_information_sampler.h" #include "system_information_sampler.h"
// Unit for raw CPU usage data from Windows.
constexpr int kTicksPerSecond = 10000000;
// Result data structure contains a final set of values calculated based on // Result data structure contains a final set of values calculated based on
// comparison of two snapshots. These are the values that the tool prints // comparison of two snapshots. These are the values that the tool prints
// in the output. // in the output.
struct Result { struct Result {
ULONG idle_wakeups_per_sec; ULONG idle_wakeups_per_sec;
double cpu_usage; double cpu_usage_percent;
double cpu_usage_seconds;
ULONGLONG working_set; ULONGLONG working_set;
double power; double power;
}; };
...@@ -27,8 +31,11 @@ typedef std::vector<Result> ResultVector; ...@@ -27,8 +31,11 @@ typedef std::vector<Result> ResultVector;
ULONG GetIdleWakeupsPerSec(const Result& r) { ULONG GetIdleWakeupsPerSec(const Result& r) {
return r.idle_wakeups_per_sec; return r.idle_wakeups_per_sec;
} }
double GetCpuUsage(const Result& r) { double GetCpuUsagePercent(const Result& r) {
return r.cpu_usage; return r.cpu_usage_percent;
}
double GetCpuUsageSeconds(const Result& r) {
return r.cpu_usage_seconds;
} }
ULONGLONG GetWorkingSet(const Result& r) { ULONGLONG GetWorkingSet(const Result& r) {
return r.working_set; return r.working_set;
...@@ -238,11 +245,9 @@ Result IdleWakeups::DiffSnapshots(const ProcessDataSnapshot& prev_snapshot, ...@@ -238,11 +245,9 @@ Result IdleWakeups::DiffSnapshots(const ProcessDataSnapshot& prev_snapshot,
Result result; Result result;
result.idle_wakeups_per_sec = result.idle_wakeups_per_sec =
static_cast<ULONG>(idle_wakeups_delta / time_delta); static_cast<ULONG>(idle_wakeups_delta / time_delta);
// brucedawson: Don't divide by number of processors so that all numbers are result.cpu_usage_percent =
// percentage of a core (double)cpu_usage_delta * 100 / (time_delta * kTicksPerSecond);
// result.cpu_usage = (double)cpu_usage_delta * 100 / (time_delta * 10000000 * result.cpu_usage_seconds = (double)cpu_usage_delta / kTicksPerSecond;
// NumberOfprocessors());
result.cpu_usage = (double)cpu_usage_delta * 100 / (time_delta * 10000000);
result.working_set = total_working_set; result.working_set = total_working_set;
return result; return result;
...@@ -275,17 +280,32 @@ void PrintHeader() { ...@@ -275,17 +280,32 @@ void PrintHeader() {
"----------\n"); "----------\n");
} }
#define RESULT_FORMAT_STRING " %20lu %8.2f%c %6.2f MiB %4.2f W\n" #define RESULT_FORMAT_STRING " %20lu %8.2f%c %7.2f MiB %5.2f W\n"
int wmain(int argc, wchar_t* argv[]) { int wmain(int argc, wchar_t* argv[]) {
ctrl_c_pressed = CreateEvent(NULL, FALSE, FALSE, NULL); ctrl_c_pressed = CreateEvent(NULL, FALSE, FALSE, NULL);
SetConsoleCtrlHandler(HandlerFunction, TRUE); SetConsoleCtrlHandler(HandlerFunction, TRUE);
PowerSampler power_sampler; PowerSampler power_sampler;
SystemInformationSampler system_information_sampler(argc > 1 ? argv[1]
: L"chrome.exe");
IdleWakeups the_app; IdleWakeups the_app;
// Parse command line for target process name and optional --cpu-seconds flag.
wchar_t* target_process_name = nullptr;
bool cpu_usage_in_seconds = false;
for (int i = 1; i < argc; i++) {
if (wcscmp(argv[i], L"--cpu-seconds") == 0)
cpu_usage_in_seconds = true;
else if (!target_process_name)
target_process_name = argv[i];
// Stop parsing if all possible args have been found.
if (cpu_usage_in_seconds && target_process_name)
break;
}
const char cpu_usage_unit = cpu_usage_in_seconds ? 's' : '%';
SystemInformationSampler system_information_sampler(
target_process_name ? target_process_name : L"chrome.exe");
// Take the initial snapshot. // Take the initial snapshot.
std::unique_ptr<ProcessDataSnapshot> previous_snapshot = std::unique_ptr<ProcessDataSnapshot> previous_snapshot =
system_information_sampler.TakeSnapshot(); system_information_sampler.TakeSnapshot();
...@@ -296,7 +316,8 @@ int wmain(int argc, wchar_t* argv[]) { ...@@ -296,7 +316,8 @@ int wmain(int argc, wchar_t* argv[]) {
size_t final_number_of_processes = initial_number_of_processes; size_t final_number_of_processes = initial_number_of_processes;
ULONG cumulative_idle_wakeups_per_sec = 0; ULONG cumulative_idle_wakeups_per_sec = 0;
double cumulative_cpu_usage = 0.0; double cumulative_cpu_usage_percent = 0.0;
double cumulative_cpu_usage_seconds = 0.0;
ULONGLONG cumulative_working_set = 0; ULONGLONG cumulative_working_set = 0;
double cumulative_energy = 0.0; double cumulative_energy = 0.0;
size_t cumulative_processes_created = 0; size_t cumulative_processes_created = 0;
...@@ -329,12 +350,15 @@ int wmain(int argc, wchar_t* argv[]) { ...@@ -329,12 +350,15 @@ int wmain(int argc, wchar_t* argv[]) {
result.power = power_sampler.get_power(L"Processor"); result.power = power_sampler.get_power(L"Processor");
printf("%9u processes" RESULT_FORMAT_STRING, (DWORD)number_of_processes, printf("%9u processes" RESULT_FORMAT_STRING, (DWORD)number_of_processes,
result.idle_wakeups_per_sec, result.cpu_usage, '%', result.idle_wakeups_per_sec,
result.working_set / 1024.0, result.power); cpu_usage_in_seconds ? result.cpu_usage_seconds
: result.cpu_usage_percent,
cpu_usage_unit, result.working_set / 1024.0, result.power);
if (number_of_processes > 0) { if (number_of_processes > 0) {
cumulative_idle_wakeups_per_sec += result.idle_wakeups_per_sec; cumulative_idle_wakeups_per_sec += result.idle_wakeups_per_sec;
cumulative_cpu_usage += result.cpu_usage; cumulative_cpu_usage_percent += result.cpu_usage_percent;
cumulative_cpu_usage_seconds += result.cpu_usage_seconds;
cumulative_working_set += result.working_set; cumulative_working_set += result.working_set;
cumulative_energy += result.power; cumulative_energy += result.power;
results.push_back(result); results.push_back(result);
...@@ -353,21 +377,34 @@ int wmain(int argc, wchar_t* argv[]) { ...@@ -353,21 +377,34 @@ int wmain(int argc, wchar_t* argv[]) {
printf(" Average" RESULT_FORMAT_STRING, printf(" Average" RESULT_FORMAT_STRING,
cumulative_idle_wakeups_per_sec / sample_count, cumulative_idle_wakeups_per_sec / sample_count,
cumulative_cpu_usage / sample_count, '%', (cpu_usage_in_seconds ? cumulative_cpu_usage_seconds
(cumulative_working_set / 1024.0) / sample_count, : cumulative_cpu_usage_percent) /
sample_count,
cpu_usage_unit, (cumulative_working_set / 1024.0) / sample_count,
cumulative_energy / sample_count); cumulative_energy / sample_count);
Result median_result; Result median_result;
median_result.idle_wakeups_per_sec = median_result.idle_wakeups_per_sec =
GetMedian<ULONG>(&results, GetIdleWakeupsPerSec); GetMedian<ULONG>(&results, GetIdleWakeupsPerSec);
median_result.cpu_usage = GetMedian<double>(&results, GetCpuUsage); median_result.cpu_usage_percent =
GetMedian<double>(&results, GetCpuUsagePercent);
median_result.cpu_usage_seconds =
GetMedian<double>(&results, GetCpuUsageSeconds);
median_result.working_set = GetMedian<ULONGLONG>(&results, GetWorkingSet); median_result.working_set = GetMedian<ULONGLONG>(&results, GetWorkingSet);
median_result.power = GetMedian<double>(&results, GetPower); median_result.power = GetMedian<double>(&results, GetPower);
printf(" Median" RESULT_FORMAT_STRING, printf(" Median" RESULT_FORMAT_STRING,
median_result.idle_wakeups_per_sec, median_result.cpu_usage, '%', median_result.idle_wakeups_per_sec,
median_result.working_set / 1024.0, median_result.power); cpu_usage_in_seconds ? median_result.cpu_usage_seconds
: median_result.cpu_usage_percent,
cpu_usage_unit, median_result.working_set / 1024.0,
median_result.power);
if (cpu_usage_in_seconds) {
printf(" Sum %32.2f%c\n", cumulative_cpu_usage_seconds,
cpu_usage_unit);
}
printf("\n"); printf("\n");
if (num_idle_snapshots > 0) if (num_idle_snapshots > 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment