Commit 44c11305 authored by Jesse McKenna's avatar Jesse McKenna Committed by Commit Bot

IdleWakeups: enable filtering by process ID

This change makes IdleWakeups interpret a numeric target process as
a process ID. When a process ID is provided as the target, IdleWakeups
will track that process and its child processes.

This is useful for measuring a particular version of Chrome, e.g., a
local Chromium build, without needing to close all other running
versions.

Example usage:
idlewakeups.exe 22612

The above makes IdleWakeups take measurements for process ID 22612,
plus all of its child processes.

Change-Id: I267bfc1dda8f5c0600f3fc677e40ca0f6bb26f22
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2490253
Commit-Queue: Jesse McKenna <jessemckenna@google.com>
Reviewed-by: default avatarAlex Gough <ajgo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#819883}
parent f43c8cea
...@@ -16,8 +16,11 @@ IdleWakeups.exe can then be found in src/tools/win/IdleWakeups/x64/Debug/. ...@@ -16,8 +16,11 @@ IdleWakeups.exe can then be found in src/tools/win/IdleWakeups/x64/Debug/.
`IdleWakeups.exe msedge` to match all Edge processes. `IdleWakeups.exe msedge` to match all Edge processes.
`IdleWakeups.exe 12345` to match process ID 12345 and its child processes.
The process matching the provided parameter is identified by case-sensitive The process matching the provided parameter is identified by case-sensitive
string prefix, e.g., `some_process` and `some_process.exe` would both work. string prefix, e.g., `some_process` and `some_process.exe` would both work. If
the parameter is numeric and a valid process ID, it is treated as a process ID.
When the tool starts it begins gathering and aggregating CPU usage, private When the tool starts it begins gathering and aggregating CPU usage, private
working set size, number of context switches / sec, and power usage for all working set size, number of context switches / sec, and power usage for all
......
...@@ -97,8 +97,8 @@ struct SYSTEM_PROCESS_INFORMATION { ...@@ -97,8 +97,8 @@ struct SYSTEM_PROCESS_INFORMATION {
ULONGLONG KernelTime; ULONGLONG KernelTime;
UNICODE_STRING ImageName; UNICODE_STRING ImageName;
KPRIORITY BasePriority; KPRIORITY BasePriority;
HANDLE ProcessId; HANDLE ProcessId; // Actually process ID, not a handle
HANDLE ParentProcessId; HANDLE ParentProcessId; // Actually parent process ID, not a handle
ULONG HandleCount; ULONG HandleCount;
ULONG Reserved2[2]; ULONG Reserved2[2];
// Padding here in 64-bit // Padding here in 64-bit
...@@ -215,6 +215,14 @@ SystemInformationSampler::SystemInformationSampler( ...@@ -215,6 +215,14 @@ SystemInformationSampler::SystemInformationSampler(
lstrcpyn(target_process_name_, process_name, lstrcpyn(target_process_name_, process_name,
sizeof(target_process_name_) / sizeof(wchar_t)); sizeof(target_process_name_) / sizeof(wchar_t));
// If |target_process_name_| is numeric, treat it as a process ID.
errno = 0;
wchar_t* end_ptr;
target_process_id_ = wcstoul(target_process_name_, &end_ptr, 10);
// Discard result if error occurred, or if negative or only partially numeric.
if (errno != 0 || target_process_id_ < 0 || *end_ptr != L'\0')
target_process_id_ = 0;
QueryPerformanceFrequency(&perf_frequency_); QueryPerformanceFrequency(&perf_frequency_);
QueryPerformanceCounter(&initial_counter_); QueryPerformanceCounter(&initial_counter_);
} }
...@@ -294,7 +302,16 @@ std::unique_ptr<ProcessDataSnapshot> SystemInformationSampler::TakeSnapshot() { ...@@ -294,7 +302,16 @@ std::unique_ptr<ProcessDataSnapshot> SystemInformationSampler::TakeSnapshot() {
break; break;
} }
if (pi->ImageName.Buffer) { if (target_process_id_ > 0) {
// If |pi| or its parent has the targeted process ID, add its data to
// the snapshot.
if (reinterpret_cast<DWORD>(pi->ProcessId) == target_process_id_ ||
reinterpret_cast<DWORD>(pi->ParentProcessId) ==
target_process_id_) {
snapshot->processes.insert(
std::make_pair(pi->ProcessId, GetProcessData(pi)));
}
} else if (pi->ImageName.Buffer) {
// Validate that the image name is within the buffer boundary. // Validate that the image name is within the buffer boundary.
// ImageName.Length seems to be in bytes rather than characters. // ImageName.Length seems to be in bytes rather than characters.
size_t image_name_offset = size_t image_name_offset =
...@@ -302,7 +319,7 @@ std::unique_ptr<ProcessDataSnapshot> SystemInformationSampler::TakeSnapshot() { ...@@ -302,7 +319,7 @@ std::unique_ptr<ProcessDataSnapshot> SystemInformationSampler::TakeSnapshot() {
if (image_name_offset + pi->ImageName.Length > data_buffer.size()) if (image_name_offset + pi->ImageName.Length > data_buffer.size())
break; break;
// If |pi| is the targeted process, add its data to the snapshot. // If |pi| has the targeted process name, add its data to the snapshot.
if (wcsncmp(target_process_name_filter(), pi->ImageName.Buffer, if (wcsncmp(target_process_name_filter(), pi->ImageName.Buffer,
lstrlen(target_process_name_filter())) == 0) { lstrlen(target_process_name_filter())) == 0) {
snapshot->processes.insert( snapshot->processes.insert(
......
...@@ -51,6 +51,10 @@ class SystemInformationSampler { ...@@ -51,6 +51,10 @@ class SystemInformationSampler {
private: private:
wchar_t target_process_name_[256] = {}; wchar_t target_process_name_[256] = {};
// Process ID of target process. If nonzero, |target_process_name| is a
// process ID, so filter to this ID and its child processes.
DWORD target_process_id_ = 0;
LARGE_INTEGER perf_frequency_; LARGE_INTEGER perf_frequency_;
LARGE_INTEGER initial_counter_; LARGE_INTEGER initial_counter_;
size_t previous_buffer_size_ = 0; size_t previous_buffer_size_ = 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