# How witr Detects Memory Usage and RSS Across Different Platforms

> Discover how witr detects memory usage and RSS on Windows macOS and Linux. Learn about its platform specific implementations and data collection strategies.

- Repository: [Pranshu Parmar/witr](https://github.com/pranshuparmar/witr)
- Tags: deep-dive
- Published: 2026-08-09

---

**witr abstracts memory and RSS collection behind platform-specific implementations in `internal/proc`, using Win32 APIs on Windows, shelling out to `ps` on macOS, and currently omitting RSS metrics on Linux.**

The `witr` repository provides a cross-platform resource monitoring utility that detects **memory usage** and **RSS (Resident Set Size)** through specialized source files. Each platform implementation conforms to a unified interface while leveraging native operating system APIs or command-line tools. Understanding these internals reveals how the tool balances accuracy with portability across Windows, macOS, and Linux.

## Windows: Native Win32 API Implementation

On Windows, witr gathers memory metrics through direct system calls defined in [`internal/proc/resource_windows.go`](https://github.com/pranshuparmar/witr/blob/main/internal/proc/resource_windows.go). The implementation invokes the **Win32 API** function `GetProcessMemoryInfo` via the syscall wrapper `procGetProcessMemoryInfo` to retrieve process memory statistics.

The function `windowsProcMetrics` extracts the **WorkingSetSize** field from the `PROCESS_MEMORY_COUNTERS` structure, which represents the RSS in bytes. For private commit size reporting, it uses the **PrivateUsage** field, exposed as `MemoryUsage` in the resource context. To calculate RSS as a percentage of total system memory, the code calls `GlobalMemoryStatusEx` within the `windowsMemoryPercent` helper.

```go
// Windows – obtain RSS and memory usage
rss, cpu, cpuTime, started := windowsProcMetrics(pid)
// rss = WorkingSetSize (bytes)
// cpu  = lifetime-average CPU %
// cpuTime, started are also returned

```

## macOS: Parsing ps Command Output

For macOS (Darwin), witr implements detection in [`internal/proc/resource_darwin.go`](https://github.com/pranshuparmar/witr/blob/main/internal/proc/resource_darwin.go) using the standard `ps` command. The `getCPUAndMemoryUsage` function executes `ps -p <pid> -o %cpu=,rss=` and parses the tabular output to extract resource metrics.

The second column returned by `ps` represents RSS in **kilobytes**, which the code converts to bytes by multiplying by 1024. This value populates the `ctx.MemoryUsage` field in the returned resource context. The approach avoids complex cgo bindings while maintaining compatibility across macOS versions.

```go
// macOS – obtain RSS via ps
cpuPct, memBytes, err := getCPUAndMemoryUsage(pid)
// memBytes = rss (kilobytes) * 1024 → bytes

```

## Linux: CPU-Focused Detection Without RSS

The Linux implementation in [`internal/proc/resource_linux.go`](https://github.com/pranshuparmar/witr/blob/main/internal/proc/resource_linux.go) currently focuses exclusively on **CPU usage** and process state detection. The `GetCPUPercent` function parses `ps` output to calculate processor utilization, while `getAppNapped` reads `/proc/<pid>/stat` to determine if a process is stopped or suspended.

Notably, the Linux variant does **not** expose RSS or memory usage in the `ResourceContext` structure. The source contains logic to read process statistics from `/proc/<pid>/stat`, but it does not parse the 24th field (the RSS value) for reporting. Future implementations would likely extract this field or implement `ps`-style parsing to achieve parity with other platforms.

```go
// Linux – current implementation only fetches CPU %
cpuPct, err := GetCPUPercent(pid, true) // uses `ps -p … -o pcpu=`

```

## Summary

- **Windows**: Uses `GetProcessMemoryInfo` to read `WorkingSetSize` (RSS) and `PrivateUsage`, calculating percentages via `GlobalMemoryStatusEx` in [`resource_windows.go`](https://github.com/pranshuparmar/witr/blob/main/resource_windows.go).
- **macOS**: Executes `ps -p <pid> -o rss=` and converts kilobyte values to bytes in [`resource_darwin.go`](https://github.com/pranshuparmar/witr/blob/main/resource_darwin.go).
- **Linux**: Currently limited to CPU monitoring via `GetCPUPercent`; RSS detection is not implemented in the current version of [`resource_linux.go`](https://github.com/pranshuparmar/witr/blob/main/resource_linux.go).

## Frequently Asked Questions

### How does witr calculate RSS on Windows?

witr calls the Win32 API function `GetProcessMemoryInfo` through `procGetProcessMemoryInfo` in [`resource_windows.go`](https://github.com/pranshuparmar/witr/blob/main/resource_windows.go). It extracts the `WorkingSetSize` field from the `PROCESS_MEMORY_COUNTERS` structure, which provides the RSS in bytes. The percentage calculation uses `GlobalMemoryStatusEx` to determine total physical memory.

### Why does witr use the ps command on macOS instead of native APIs?

The macOS implementation in [`resource_darwin.go`](https://github.com/pranshuparmar/witr/blob/main/resource_darwin.go) uses the `ps` command to avoid cgo dependencies and complex Mach kernel interface bindings. Parsing the output of `ps -p <pid> -o %cpu=,rss=` provides reliable cross-version compatibility while minimizing external dependencies.

### Does witr support RSS monitoring on Linux?

No, the current Linux implementation in [`resource_linux.go`](https://github.com/pranshuparmar/witr/blob/main/resource_linux.go) does not expose RSS or memory usage metrics. It focuses on CPU percentage via `GetCPUPercent` and process state detection via `getAppNapped`. Future updates would need to parse the 24th field of `/proc/<pid>/stat` to add RSS support.

### What is the difference between WorkingSetSize and PrivateUsage in witr's Windows implementation?

In [`resource_windows.go`](https://github.com/pranshuparmar/witr/blob/main/resource_windows.go), `WorkingSetSize` represents the RSS (physical memory resident in RAM), while `PrivateUsage` indicates the process's private commit size (virtual memory allocated). witr reports `WorkingSetSize` as the RSS value and `PrivateUsage` as the general memory usage metric.