> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/leonardo02lobo/Memory-Monitor/llms.txt
> Use this file to discover all available pages before exploring further.

# Process Analysis

> How Memory Monitor identifies memory-intensive processes by scanning /proc filesystem

## Overview

Memory Monitor identifies the process consuming the most memory by scanning the `/proc` filesystem and reading memory statistics from each running process. This allows you to quickly identify memory-intensive applications.

## Understanding VmRSS

**VmRSS (Virtual Memory Resident Set Size)** is the amount of memory that a process is actually using in physical RAM. This is the most important metric for understanding a process's real memory footprint.

<Info>
  VmRSS represents the portion of a process's memory that resides in RAM, excluding swapped-out pages. This is the "real" memory usage that impacts system performance.
</Info>

### VmRSS vs Other Memory Metrics

<Accordion title="VmRSS vs VmSize">
  * **VmSize**: Total virtual memory allocated to the process (includes swapped and unmapped memory)
  * **VmRSS**: Only the memory currently in physical RAM
  * **Why VmRSS matters**: A process can allocate gigabytes of virtual memory but only use megabytes of physical RAM. VmRSS shows the actual impact on your system.
</Accordion>

<Accordion title="VmRSS vs PSS (Proportional Set Size)">
  * **VmRSS**: Counts all resident memory, including shared libraries fully
  * **PSS**: Divides shared memory proportionally among processes
  * **Why use VmRSS**: It's simpler to calculate and available in `/proc/[pid]/status` without additional computation
</Accordion>

## Process Scanning Implementation

### Discovering Running Processes

The `/proc` directory contains numbered subdirectories for each running process. The `ListDirectory()` function scans these directories:

```python process_analyzer.py theme={null}
def ListDirectory() -> list[str, str] | None:
    list_directory: list[str] = os.listdir("/proc")
    pids = [pid for pid in list_directory if pid.isdigit()]
```

This approach:

* **Lists all entries** in `/proc` using `os.listdir()`
* **Filters for PIDs** by checking if each directory name is numeric using `isdigit()`
* **Creates a list** of valid process IDs to analyze

<Note>
  The `/proc` directory contains both process directories (named with PIDs) and system information files (like `meminfo`, `cpuinfo`). The `isdigit()` check ensures we only process actual process directories.
</Note>

### Tracking Maximum Memory Usage

The function maintains variables to track the process with the highest VmRSS:

```python process_analyzer.py theme={null}
max_vmrrs: int = 0
max_pid: str = ""
max_process_name: str = ""
```

### Reading Process Status Files

For each process, Memory Monitor reads the `/proc/[pid]/status` file, which contains detailed process information:

```python process_analyzer.py theme={null}
for pid in pids:
    status_path = os.path.join("/proc", pid, "status")
    try:
        with open(status_path, "r") as f:
            vmrrs = 0
            for line in f:
                if line.startswith("Name:"):
                    max_process_name = line.strip().split()[1]
                if line.startswith("VmRSS:"):
                    vmrrs = int(line.strip().split()[1])
                    if vmrrs > max_vmrrs:
                        max_vmrrs = vmrrs
                        max_pid = pid
```

The parser:

* **Opens each status file** using the constructed path `/proc/[pid]/status`
* **Reads line by line** to find the process name and VmRSS value
* **Extracts the process name** from lines starting with `Name:`
* **Extracts VmRSS value** from lines starting with `VmRSS:`
* **Compares and updates** the maximum VmRSS found so far

<Warning>
  VmRSS values in `/proc/[pid]/status` are in kilobytes (kB). Some processes may not have a VmRSS entry if they haven't allocated any resident memory yet.
</Warning>

## Error Handling

Process analysis requires robust error handling because the process list changes dynamically:

### FileNotFoundError

```python process_analyzer.py theme={null}
except FileNotFoundError:
    continue
```

**Why this happens**: Processes can terminate between when we list the `/proc` directory and when we try to read their status file. The process directory disappears, causing a `FileNotFoundError`.

**How it's handled**: The function simply continues to the next process. This is expected behavior and not an error condition.

<Accordion title="Example Scenario">
  1. Scanner lists `/proc` and finds PID 12345
  2. Process 12345 terminates
  3. Scanner tries to open `/proc/12345/status`
  4. File doesn't exist → `FileNotFoundError`
  5. Scanner continues to next process
</Accordion>

### PermissionError

```python process_analyzer.py theme={null}
except PermissionError:
    continue
```

**Why this happens**: Some processes (especially system processes) are owned by root or other users. Non-privileged users cannot read their status files.

**How it's handled**: The function skips processes it cannot access. To analyze all processes, Memory Monitor would need to run with elevated privileges (sudo).

<Note>
  Running Memory Monitor as a regular user will show memory usage for accessible processes. Running with `sudo` provides complete system-wide visibility.
</Note>

### Silent Failure vs Error Reporting

Both exceptions use `continue` rather than logging or reporting errors. This design choice:

* **Keeps output clean**: Expected conditions don't clutter results
* **Focuses on success**: Reports what it found rather than what it couldn't access
* **Maintains performance**: No overhead from logging frequent, expected conditions

## Output Format

The function returns detailed information about the highest memory-consuming process:

```python process_analyzer.py theme={null}
return [f"El proceso con mayor VmRSS es \n Name: {max_process_name}\n PID: {max_pid}\n VmRSS: {max_vmrrs} kB", max_pid]
```

The return value is a list containing:

1. **Formatted string** with process name, PID, and VmRSS value
2. **PID alone** for programmatic use

## Example /proc/\[pid]/status Output

Here's what a typical `/proc/[pid]/status` file contains:

```
Name:   firefox
State:  S (sleeping)
Pid:    12345
PPid:   1234
VmSize: 4096000 kB
VmRSS:  2048000 kB
VmData:  512000 kB
...
```

Memory Monitor extracts:

* **Name**: `firefox`
* **VmRSS**: `2048000` (in kB)

## Performance Considerations

<Accordion title="Why read line-by-line instead of reading the entire file?">
  The current implementation reads line-by-line but could be optimized by reading the entire file and then parsing. However, `/proc/[pid]/status` files are small (typically \< 2KB), so the performance difference is negligible.
</Accordion>

<Accordion title="Why scan all processes instead of sorting?">
  The function uses a single-pass algorithm with O(n) time complexity, tracking the maximum as it scans. This is efficient because:

  * Only one pass through the process list is needed
  * No additional memory for sorting
  * Early termination possible if needed
</Accordion>

<Accordion title="What about processes that spawn during scanning?">
  Processes that start after the initial `os.listdir("/proc")` call won't be included in this scan. For continuous monitoring, the scan would need to be repeated periodically.
</Accordion>

## Design Trade-offs

### Single Maximum vs Top N

Memory Monitor reports only the single highest memory consumer. To report multiple top processes, you would need to:

* Use a heap or sorted list structure
* Store top N processes during iteration
* Return a list of results

### VmRSS vs Other Metrics

The tool could track other memory metrics from `/proc/[pid]/status`:

* **VmSize**: Total virtual memory
* **VmData**: Size of data segment
* **VmStk**: Size of stack
* **VmExe**: Size of executable code

VmRSS was chosen because it represents actual RAM usage, the most actionable metric for system administrators.

## Next Steps

<Card title="Memory Monitoring" icon="gauge" href="/concepts/memory-monitoring">
  Learn how Memory Monitor tracks overall system memory usage
</Card>
