Commit 0b9d2b69 authored by Etienne Bergeron's avatar Etienne Bergeron Committed by Commit Bot

Add windows performance counters

This CL is adding the system performance counters on Windows.

A way to compute the system IO activity is to sum IO counters for
every processes. On windows, the GetIoCounters(...) call returns
counters by process. Using this technique has two drawbacks
  1) an expensive processes enumeration is required
  2) processes may disappear during the sample slice, which
     is leading to inaccurate metric.

We are proposing to call a ntdll API which returns system wide
counters. The operating system is keeping system wide counters
for IO accesses through ZwReadFile and ZwWriteFile.

see:
https://docs.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntquerysysteminformation

  "Returns an opaque SYSTEM_PERFORMANCE_INFORMATION structure that can be used to generate an
   unpredictable seed for a random number generator. "

Layout:
  https://cs.chromium.org/chromium/src/third_party/perl/c/i686-w64-mingw32/include/winternl.h?type=cs&l=609
  https://processhacker.sourceforge.io/doc/struct___s_y_s_t_e_m___p_e_r_f_o_r_m_a_n_c_e___i_n_f_o_r_m_a_t_i_o_n.html


To see these metrics, you can activate "system_stats" category and grab a trace.
A sample is collected every two seconds and will be displayed in the tracing UI.

Next step is to modify catapult to convert these tracing tracks as rate instead than raw counters.

see:
  catapult/tracing/tracing/ui/extras/system_stats/system_stats_instance_track.html
Change-Id: I45b6b04192c78dd5a0dc95eca0c2d357e74ca285


R=fdoray, gab

Bug: 872900
Change-Id: I45b6b04192c78dd5a0dc95eca0c2d357e74ca285
Reviewed-on: https://chromium-review.googlesource.com/1169871Reviewed-by: default avatarBruce Dawson <brucedawson@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Reviewed-by: default avatarGabriel Charette <gab@chromium.org>
Commit-Queue: Etienne Bergeron <etienneb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#583374}
parent edcd53a1
......@@ -67,7 +67,9 @@ SystemMetrics SystemMetrics::Sample() {
#if defined(OS_CHROMEOS)
GetSwapInfo(&system_metrics.swap_info_);
#endif
#if defined(OS_WIN)
GetSystemPerformanceInfo(&system_metrics.performance_);
#endif
return system_metrics;
}
......@@ -85,6 +87,9 @@ std::unique_ptr<Value> SystemMetrics::ToValue() const {
#if defined(OS_CHROMEOS)
res->Set("swapinfo", swap_info_.ToValue());
#endif
#if defined(OS_WIN)
res->Set("perfinfo", performance_.ToValue());
#endif
return std::move(res);
}
......
......@@ -475,6 +475,37 @@ BASE_EXPORT bool ParseZramStat(StringPiece stat_data, SwapInfo* swap_info);
BASE_EXPORT bool GetSwapInfo(SwapInfo* swap_info);
#endif // defined(OS_CHROMEOS)
struct BASE_EXPORT SystemPerformanceInfo {
SystemPerformanceInfo();
SystemPerformanceInfo(const SystemPerformanceInfo& other);
// Serializes the platform specific fields to value.
std::unique_ptr<Value> ToValue() const;
// Total idle time of all processes in the system (units of 100 ns).
uint64_t idle_time = 0;
// Number of bytes read.
uint64_t read_transfer_count = 0;
// Number of bytes written.
uint64_t write_transfer_count = 0;
// Number of bytes transferred (e.g. DeviceIoControlFile)
uint64_t other_transfer_count = 0;
// The amount of read operations.
uint64_t read_operation_count = 0;
// The amount of write operations.
uint64_t write_operation_count = 0;
// The amount of other operations.
uint64_t other_operation_count = 0;
// The number of pages written to the system's pagefiles.
uint64_t pagefile_pages_written = 0;
// The number of write operations performed on the system's pagefiles.
uint64_t pagefile_pages_write_ios = 0;
};
// Retrieves performance counters from the operating system.
// Fills in the provided |info| structure. Returns true on success.
BASE_EXPORT bool GetSystemPerformanceInfo(SystemPerformanceInfo* info);
// Collects and holds performance metrics for system memory and disk.
// Provides functionality to retrieve the data on various platforms and
// to serialize the stored data.
......@@ -499,6 +530,9 @@ class SystemMetrics {
#if defined(OS_CHROMEOS)
SwapInfo swap_info_;
#endif
#if defined(OS_WIN)
SystemPerformanceInfo performance_;
#endif
};
#if defined(OS_MACOSX) && !defined(OS_IOS)
......
......@@ -25,11 +25,96 @@ namespace {
// System pagesize. This value remains constant on x86/64 architectures.
const int PAGESIZE_KB = 4;
typedef NTSTATUS(WINAPI* NTQUERYSYSTEMINFORMATION)(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength);
// ntstatus.h conflicts with windows.h so define this locally.
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
// Definition of this struct is taken from the book:
// Windows NT/200, Native API reference, Gary Nebbett
struct SYSTEM_PERFORMANCE_INFORMATION {
// Total idle time of all processes in the system (units of 100 ns).
LARGE_INTEGER IdleTime;
// Number of bytes read (by all call to ZwReadFile).
LARGE_INTEGER ReadTransferCount;
// Number of bytes written (by all call to ZwWriteFile).
LARGE_INTEGER WriteTransferCount;
// Number of bytes transferred (e.g. DeviceIoControlFile)
LARGE_INTEGER OtherTransferCount;
// The amount of read operations.
ULONG ReadOperationCount;
// The amount of write operations.
ULONG WriteOperationCount;
// The amount of other operations.
ULONG OtherOperationCount;
ULONG AvailablePages;
ULONG TotalCommittedPages;
ULONG TotalCommitLimit;
ULONG PeakCommitment;
ULONG PageFaults;
ULONG WriteCopyFaults;
ULONG TransitionFaults;
ULONG CacheTransitionFaults;
ULONG DemandZeroFaults;
ULONG PagesRead;
ULONG PageReadIos;
ULONG CacheReads;
ULONG CacheIos;
// The number of pages written to the system's pagefiles.
ULONG PagefilePagesWritten;
// The number of write operations performed on the system's pagefiles.
ULONG PagefilePageWriteIos;
ULONG MappedFilePagesWritten;
ULONG MappedFilePageWriteIos;
ULONG PagedPoolUsage;
ULONG NonPagedPoolUsage;
ULONG PagedPoolAllocs;
ULONG PagedPoolFrees;
ULONG NonPagedPoolAllocs;
ULONG NonPagedPoolFrees;
ULONG TotalFreeSystemPtes;
ULONG SystemCodePage;
ULONG TotalSystemDriverPages;
ULONG TotalSystemCodePages;
ULONG SmallNonPagedLookasideListAllocateHits;
ULONG SmallPagedLookasideListAllocateHits;
ULONG Reserved3;
ULONG MmSystemCachePage;
ULONG PagedPoolPage;
ULONG SystemDriverPage;
ULONG FastReadNoWait;
ULONG FastReadWait;
ULONG FastReadResourceMiss;
ULONG FastReadNotPossible;
ULONG FastMdlReadNoWait;
ULONG FastMdlReadWait;
ULONG FastMdlReadResourceMiss;
ULONG FastMdlReadNotPossible;
ULONG MapDataNoWait;
ULONG MapDataWait;
ULONG MapDataNoWaitMiss;
ULONG MapDataWaitMiss;
ULONG PinMappedDataCount;
ULONG PinReadNoWait;
ULONG PinReadWait;
ULONG PinReadNoWaitMiss;
ULONG PinReadWaitMiss;
ULONG CopyReadNoWait;
ULONG CopyReadWait;
ULONG CopyReadNoWaitMiss;
ULONG CopyReadWaitMiss;
ULONG MdlReadNoWait;
ULONG MdlReadWait;
ULONG MdlReadNoWaitMiss;
ULONG MdlReadWaitMiss;
ULONG ReadAheadIos;
ULONG LazyWriteIos;
ULONG LazyWritePages;
ULONG DataFlushes;
ULONG DataPages;
ULONG ContextSwitches;
ULONG FirstLevelTbFills;
ULONG SecondLevelTbFills;
ULONG SystemCalls;
};
} // namespace
......@@ -204,4 +289,64 @@ size_t ProcessMetrics::GetMallocUsage() {
return 0;
}
SystemPerformanceInfo::SystemPerformanceInfo() = default;
SystemPerformanceInfo::SystemPerformanceInfo(
const SystemPerformanceInfo& other) = default;
std::unique_ptr<Value> SystemPerformanceInfo::ToValue() const {
std::unique_ptr<DictionaryValue> result(new DictionaryValue());
// Write out uint64_t variables as doubles.
// Note: this may discard some precision, but for JS there's no other option.
result->SetDouble("idle_time", static_cast<double>(idle_time));
result->SetDouble("read_transfer_count",
static_cast<double>(read_transfer_count));
result->SetDouble("write_transfer_count",
static_cast<double>(write_transfer_count));
result->SetDouble("other_transfer_count",
static_cast<double>(other_transfer_count));
result->SetDouble("read_operation_count",
static_cast<double>(read_operation_count));
result->SetDouble("write_operation_count",
static_cast<double>(write_operation_count));
result->SetDouble("other_operation_count",
static_cast<double>(other_operation_count));
result->SetDouble("pagefile_pages_written",
static_cast<double>(pagefile_pages_written));
result->SetDouble("pagefile_pages_write_ios",
static_cast<double>(pagefile_pages_write_ios));
return result;
}
// Retrieves performance counters from the operating system.
// Fills in the provided |info| structure. Returns true on success.
BASE_EXPORT bool GetSystemPerformanceInfo(SystemPerformanceInfo* info) {
static const auto query_system_information_ptr =
reinterpret_cast<decltype(&::NtQuerySystemInformation)>(GetProcAddress(
GetModuleHandle(L"ntdll.dll"), "NtQuerySystemInformation"));
if (!query_system_information_ptr)
return false;
SYSTEM_PERFORMANCE_INFORMATION counters = {};
const NTSTATUS status = query_system_information_ptr(
::SystemPerformanceInformation, &counters,
sizeof(SYSTEM_PERFORMANCE_INFORMATION), nullptr);
if (status != STATUS_SUCCESS)
return false;
info->idle_time = counters.IdleTime.QuadPart;
info->read_transfer_count = counters.ReadTransferCount.QuadPart;
info->write_transfer_count = counters.WriteTransferCount.QuadPart;
info->other_transfer_count = counters.OtherTransferCount.QuadPart;
info->read_operation_count = counters.ReadOperationCount;
info->write_operation_count = counters.WriteOperationCount;
info->other_operation_count = counters.OtherOperationCount;
info->pagefile_pages_written = counters.PagefilePagesWritten;
info->pagefile_pages_write_ios = counters.PagefilePageWriteIos;
return true;
}
} // namespace base
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