Skip to content

Commit 9049ff0

Browse files
committed
feature: Enable System Resource Tracker on Windows
Signed-off-by: Neil R. Spruit <neil.r.spruit@intel.com>
1 parent c47981f commit 9049ff0

5 files changed

Lines changed: 110 additions & 25 deletions

File tree

source/layers/validation/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ Currently checked things:
106106
- check whether created immediate command lists are using in order queues
107107
- check whether in order command lists are using copy offload
108108

109-
### `ZEL_ENABLE_SYSTEM_RESOURCE_TRACKER_CHECKER` (Linux Only)
109+
### `ZEL_ENABLE_SYSTEM_RESOURCE_TRACKER_CHECKER`
110110

111111
The System Resource Tracker monitors both Level Zero API resources and system resources in real-time. It tracks:
112112

@@ -137,7 +137,7 @@ export ZEL_LOADER_LOGGING_LEVEL=debug
137137
- Debugging and benchmarking
138138
- CI/CD integration for automated resource monitoring
139139

140-
**Platform Support:** This checker is Linux-only and uses `/proc/self/status` for system metrics. It is automatically excluded from Windows and macOS builds.
140+
**Platform Support:** This checker supports Linux and Windows. On Linux it reads `/proc/self/status`; on Windows it uses the Win32 `PSAPI` and `Toolhelp32` APIs. macOS is not supported.
141141

142142
See [System Resource Tracker documentation](checkers/system_resource_tracker/system_resource_tracker.md) for detailed usage and CSV format.
143143

source/layers/validation/checkers/CMakeLists.txt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,4 @@ add_subdirectory(events_checker)
44
add_subdirectory(performance)
55
add_subdirectory(parameter_validation)
66
add_subdirectory(template)
7-
8-
# System resource tracker is Linux-only (uses /proc/self/status)
9-
if(UNIX AND NOT APPLE)
10-
add_subdirectory(system_resource_tracker)
11-
endif()
7+
add_subdirectory(system_resource_tracker)
Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
# System resource tracker is Linux-only (uses /proc/self/status)
2-
if(UNIX AND NOT APPLE)
3-
target_sources(${TARGET_NAME}
4-
PRIVATE
5-
${CMAKE_CURRENT_LIST_DIR}/zel_system_resource_tracker_checker.h
6-
${CMAKE_CURRENT_LIST_DIR}/zel_system_resource_tracker_checker.cpp
7-
)
8-
endif()
1+
target_sources(${TARGET_NAME}
2+
PRIVATE
3+
${CMAKE_CURRENT_LIST_DIR}/zel_system_resource_tracker_checker.h
4+
${CMAKE_CURRENT_LIST_DIR}/zel_system_resource_tracker_checker.cpp
5+
)

source/layers/validation/checkers/system_resource_tracker/system_resource_tracker.md

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
The System Resource Tracker is a Level Zero validation layer checker that monitors both Level Zero API resources and system resources in real-time. It tracks resource allocation and deallocation across all Level Zero API calls that create or destroy resources, providing detailed insights into memory usage, resource lifecycles, and system-level metrics.
66

7-
**Platform Support:** Linux only. This checker uses `/proc/self/status` for system metrics and is not available on Windows or macOS.
7+
**Platform Support:** Linux and Windows. On Linux the checker reads `/proc/self/status` for system metrics; on Windows it uses the Win32 `GetProcessMemoryInfo`, `CreateToolhelp32Snapshot`, and `GetProcessHandleCount` APIs. macOS is not supported.
88

99
## Features
1010

@@ -14,13 +14,13 @@ The System Resource Tracker is a Level Zero validation layer checker that monito
1414
- Logs warnings when memory increases during destroy operations
1515
- Reports cumulative leaks per resource type at program exit
1616
- Provides detailed per-handle leak information
17-
- **System Resource Monitoring**: Tracks real system metrics via `/proc/self/status` including:
18-
- Virtual memory size (VmSize)
19-
- Resident set size (VmRSS)
20-
- Data segment size (VmData)
21-
- Peak virtual memory (VmPeak)
17+
- **System Resource Monitoring**: Tracks real system metrics including:
18+
- Virtual memory size (VmSize / PrivateUsage on Windows)
19+
- Resident set size (VmRSS / WorkingSetSize on Windows)
20+
- Data segment size (VmData / PrivateUsage on Windows)
21+
- Peak virtual memory (VmPeak / PeakWorkingSetSize on Windows)
2222
- Thread count
23-
- File descriptor count
23+
- File descriptor / handle count
2424
- **Signed Delta Tracking**: Calculates both positive and negative resource changes (deltas) for each API call with proper signed arithmetic
2525
- **Cumulative Summaries**: Maintains running totals of all resource types and leak totals
2626
- **CSV Export**: Optionally exports timestamped data for graphing and analysis
@@ -34,6 +34,7 @@ The System Resource Tracker is a Level Zero validation layer checker that monito
3434

3535
Enable the checker to log resource usage to the Level Zero debug log:
3636

37+
**Linux:**
3738
```bash
3839
export ZE_ENABLE_VALIDATION_LAYER=1
3940
export ZEL_ENABLE_SYSTEM_RESOURCE_TRACKER_CHECKER=1
@@ -44,10 +45,22 @@ export ZEL_LOADER_LOGGING_LEVEL=debug
4445
./my_level_zero_app
4546
```
4647

48+
**Windows (PowerShell):**
49+
```powershell
50+
$env:ZE_ENABLE_VALIDATION_LAYER=1
51+
$env:ZEL_ENABLE_SYSTEM_RESOURCE_TRACKER_CHECKER=1
52+
$env:ZEL_ENABLE_LOADER_LOGGING=1
53+
$env:ZEL_LOADER_LOGGING_LEVEL="debug"
54+
55+
# Run your Level Zero application
56+
.\my_level_zero_app.exe
57+
```
58+
4759
### CSV Output for Graphing
4860

4961
Set the `ZEL_SYSTEM_RESOURCE_TRACKER_CSV` environment variable to specify the output CSV file path, this path will be relative to the current working directory of the application:
5062

63+
**Linux:**
5164
```bash
5265
export ZE_ENABLE_VALIDATION_LAYER=1
5366
export ZEL_ENABLE_SYSTEM_RESOURCE_TRACKER_CHECKER=1
@@ -57,6 +70,16 @@ export ZEL_SYSTEM_RESOURCE_TRACKER_CSV=tracker_output.csv
5770
./my_level_zero_app
5871
```
5972

73+
**Windows (PowerShell):**
74+
```powershell
75+
$env:ZE_ENABLE_VALIDATION_LAYER=1
76+
$env:ZEL_ENABLE_SYSTEM_RESOURCE_TRACKER_CHECKER=1
77+
$env:ZEL_SYSTEM_RESOURCE_TRACKER_CSV="tracker_output.csv"
78+
79+
# Run your Level Zero application
80+
.\my_level_zero_app.exe
81+
```
82+
6083
**Note:** The actual output file will include the process ID (e.g., `tracker_output_pid12345.csv`) to ensure each process creates a unique file. This prevents conflicts when multiple processes use the tracker simultaneously.
6184

6285
## Tracked API Calls
@@ -317,7 +340,7 @@ The System Resource Tracker is implemented as a validation layer checker that us
317340
- Per-resource-type leak counters
318341
- Thread-local pre-call metrics storage for append operations
319342
- `getResourceTracker()`: Function-local static singleton accessor ensuring proper initialization order
320-
- `getSystemResourceMetrics()`: Parses `/proc/self/status` to read current system metrics
343+
- `getSystemResourceMetrics()`: Reads current system metrics — parses `/proc/self/status` on Linux; uses `GetProcessMemoryInfo`, `CreateToolhelp32Snapshot`, and `GetProcessHandleCount` on Windows
321344
- `checkForLeak()`: Compares creation metrics to destruction metrics and logs warnings if memory increased
322345
- `writeCsvData()`: Atomic CSV line writer using ostringstream with signed delta support
323346
- `logResourceSummary()`: Formats and logs cumulative resource usage
@@ -335,13 +358,20 @@ The tracker uses multiple mechanisms to ensure thread safety:
335358
### Performance Considerations
336359

337360
- Tracking overhead is approximately < 1ms per API call
338-
- System metrics are read by parsing a small text file (`/proc/self/status` on Linux)
361+
- System metrics are read from `/proc/self/status` on Linux or via Win32 `PSAPI` / `Toolhelp32` on Windows
339362
- CSV writes are buffered and flushed after each call to ensure crash safety
340363
- The tracker only runs when explicitly enabled via environment variable
341364

342365
### Platform Support
343366

344-
The System Resource Tracker is **Linux-only** and relies on `/proc/self/status` for system resource metrics. The checker is automatically excluded from builds on Windows and macOS.
367+
The System Resource Tracker supports **Linux and Windows**:
368+
369+
| Platform | Metrics source | VmSize | VmRSS | VmData | VmPeak | Threads | FDs/Handles |
370+
|----------|---------------|--------|-------|--------|--------|---------|-------------|
371+
| Linux | `/proc/self/status` | VmSize | VmRSS | VmData | VmPeak | Threads field | `getrlimit(RLIMIT_NOFILE)` |
372+
| Windows | Win32 PSAPI / Toolhelp32 | `PrivateUsage` | `WorkingSetSize` | `PrivateUsage` | `PeakWorkingSetSize` | thread snapshot | `GetProcessHandleCount` |
373+
374+
macOS is not supported.
345375

346376
## Troubleshooting
347377

source/layers/validation/checkers/system_resource_tracker/zel_system_resource_tracker_checker.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,15 @@
1212
#include <iomanip>
1313
#include <fstream>
1414
#include <sstream>
15+
#ifdef _WIN32
16+
#include <windows.h>
17+
#include <psapi.h>
18+
#include <tlhelp32.h>
19+
typedef ptrdiff_t ssize_t;
20+
#else
1521
#include <sys/resource.h>
1622
#include <unistd.h>
23+
#endif
1724
#include <cstring>
1825
#include <mutex>
1926
#include <chrono>
@@ -162,6 +169,50 @@ namespace validation_layer
162169
static SystemResourceMetrics getSystemResourceMetrics();
163170
static void writeCsvData(const std::string& apiCall, const SystemResourceMetrics& current, const SystemResourceMetrics& delta, bool checkLeak);
164171

172+
#ifdef _WIN32
173+
// Helper function to read system resource metrics (Windows)
174+
static SystemResourceMetrics getSystemResourceMetrics() {
175+
SystemResourceMetrics metrics;
176+
177+
PROCESS_MEMORY_COUNTERS_EX pmc;
178+
ZeroMemory(&pmc, sizeof(pmc));
179+
pmc.cb = sizeof(pmc);
180+
if (GetProcessMemoryInfo(GetCurrentProcess(),
181+
reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&pmc),
182+
sizeof(pmc))) {
183+
metrics.vmSize = static_cast<size_t>(pmc.PrivateUsage) / 1024;
184+
metrics.vmRSS = static_cast<size_t>(pmc.WorkingSetSize) / 1024;
185+
metrics.vmData = static_cast<size_t>(pmc.PrivateUsage) / 1024;
186+
metrics.vmPeak = static_cast<size_t>(pmc.PeakWorkingSetSize) / 1024;
187+
}
188+
189+
// Count threads belonging to this process
190+
DWORD currentPid = GetCurrentProcessId();
191+
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
192+
if (hSnapshot != INVALID_HANDLE_VALUE) {
193+
THREADENTRY32 te;
194+
te.dwSize = sizeof(THREADENTRY32);
195+
size_t threadCount = 0;
196+
if (Thread32First(hSnapshot, &te)) {
197+
do {
198+
if (te.th32OwnerProcessID == currentPid) {
199+
threadCount++;
200+
}
201+
} while (Thread32Next(hSnapshot, &te));
202+
}
203+
CloseHandle(hSnapshot);
204+
metrics.numThreads = threadCount;
205+
}
206+
207+
// Count open handles
208+
DWORD handleCount = 0;
209+
if (GetProcessHandleCount(GetCurrentProcess(), &handleCount)) {
210+
metrics.numFDs = static_cast<size_t>(handleCount);
211+
}
212+
213+
return metrics;
214+
}
215+
#else
165216
// Helper function to read system resource metrics from /proc/self/status
166217
static SystemResourceMetrics getSystemResourceMetrics() {
167218
SystemResourceMetrics metrics;
@@ -207,6 +258,7 @@ namespace validation_layer
207258

208259
return metrics;
209260
}
261+
#endif
210262

211263
// Helper function to write CSV data with signed deltas (assumes mutex is already held by caller)
212264
static void writeCsvData(const std::string& apiCall, const SystemResourceMetrics& current, const SystemResourceMetrics& delta, bool checkLeak = false) {
@@ -402,11 +454,21 @@ namespace validation_layer
402454
std::to_string(reinterpret_cast<uintptr_t>(&getResourceTracker())));
403455

404456
// Check if CSV output is requested
457+
#ifdef _WIN32
458+
char* csvPath = nullptr;
459+
size_t csvPathLen = 0;
460+
_dupenv_s(&csvPath, &csvPathLen, "ZEL_SYSTEM_RESOURCE_TRACKER_CSV");
461+
#else
405462
const char* csvPath = getenv("ZEL_SYSTEM_RESOURCE_TRACKER_CSV");
463+
#endif
406464
if (csvPath && csvPath[0] != '\0') {
407465
try {
408466
// Create unique filename per process by appending PID
467+
#ifdef _WIN32
468+
DWORD pid = GetCurrentProcessId();
469+
#else
409470
pid_t pid = getpid();
471+
#endif
410472
std::string uniquePath(csvPath);
411473

412474
// Insert PID before file extension or at end

0 commit comments

Comments
 (0)