Memory Usage Discrepancy

Hi, I modeled a quarter-core reactor with x and y reflective conditions to simulate a full-core depletion, and I wanted to test for memory constraints between each integrator, so I used the following lines of code within my Jupyter Notebook,

import os
import subprocess

pid = os.getpid()
cmd = f"psrecord {pid} --include-children --interval 10 --duration 21600 --log openmc_performance.log"
subprocess.Popen(cmd.split())

model = openmc.Model(geometry, materials, settings)
chain = openmc.deplete.Chain.from_xml(“/home/smrcenter/openmc/endfb80/chain_casl_pwr.xml”)
chain.export_to_xml(“chain_mod_q.xml”)
operator = openmc.deplete.CoupledOperator(model, “chain_mod_q.xml”)
cecm = openmc.deplete.PredictorIntegrator(operator, time_steps, power, timestep_units=‘d’, solver=‘cram16’).integrate()

I then plotted the CPU, real memory, and virtual memory over the duration of the run,

This run was completed using 20 batches, 20 gens, 5 inactive, 10000 particles, with a memory allocation in WSL settings set to 30Gb, and 24 core processor (2400% max utilization). The timestep was 0.1d followed by a 1.0 day, with tallies of reaction rates for fuel materials. The CPU utilization seems correct to me, and it appears CPU is used for transport, but not as much for depletion, whereas the inverse is true for memory. I further plotted real and virtual memory here,

If anyone could explain how I could have a peak of approximately 286 GB of real memory, with only 30 GB of ram (which I was under the impression was the only real memory), and a max virtual memory of, 1764 GB, whereas only 8Gb was allocated to swap space (which is what I thought virtual memory was, for hard faults). This might be arising from my misunderstanding of how linux separates memory. Thank you for your assistance.

Plotting the

So I tried a different method of for a CECM integrator run recording the stats,

import time
import datetime
import csv
import psutil

def get_vmstat():
"""
Reads /proc/vmstat and returns a dictionary of values.
We'll use this to capture page fault counts.
"""
data = {}
try:
    with open("/proc/vmstat", "r") as f:
        for line in f:
            parts = line.split()
            if len(parts) == 2:
                key, value = parts
                data[key] = int(value)
except Exception as e:
    print("Error reading /proc/vmstat:", e)
return data

def main():
# Set sample interval (in seconds) and total duration (in seconds) 
interval = 10          
duration = 43200       
output_file = "system_usage.csv"
start_time = time.time()
end_time = start_time + duration

# Open the CSV file for writing log data
with open(output_file, "w", newline="") as csvfile:
    writer = csv.writer(csvfile)
    # Write header
    writer.writerow([
        "timestamp",
        "cpu_percent",
        "memory_used_MB",
        "memory_total_MB",
        "pgmajfault_delta",   
        "pgfault_delta"       
    ])

    # Read initial vmstat values
    last_vmstat = get_vmstat()
    
    while time.time() < end_time:
        # Get current timestamp
        timestamp = datetime.datetime.now().isoformat()

        # Get CPU usage (non-blocking)
        cpu_percent = psutil.cpu_percent(interval=None)

        # Get memory usage info
        mem = psutil.virtual_memory()

        # Get current /proc/vmstat values
        current_vmstat = get_vmstat()

        # Calculate differences (deltas) for page fault data
        # In /proc/vmstat:
        # - "pgmajfault" is the cumulative number of major page faults.
        # - "pgfault" is the cumulative number of page faults (mostly minor).
        pgmajfault_delta = current_vmstat.get("pgmajfault", 0) - last_vmstat.get("pgmajfault", 0)
        pgfault_delta = current_vmstat.get("pgfault", 0) - last_vmstat.get("pgfault", 0)
        last_vmstat = current_vmstat

        writer.writerow([
            timestamp,
            cpu_percent,
            mem.used / (1024 * 1024),
            mem.total / (1024 * 1024),
            pgmajfault_delta,
            pgfault_delta
        ])
        csvfile.flush()  # Ensure data is written to disk
        time.sleep(interval)

if __name__ == "__main__":
main()

which results in the following graphs,


These seem as to be expected, I will probably just ignore the previous measurements, though if people have an explanation to it I would appreciate it, furthermore if you see an issue with the new method please let me know.