Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CPU and Memory usage monitoring script for ROS #2467

Merged
merged 4 commits into from
Nov 18, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions engineering_tools/monitor-ros-cpu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/usr/bin/env python3

"""
CARMA Platform CPU Monitor Script

Requirements:
- Python 3.6 or higher
- psutil package (install with: pip3 install psutil)

Usage:
1. Open a new terminal before starting CARMA Platform
2. Navigate to the directory containing this script:
cd /path/to/script/

3. Run this script:
python3 monitor-ros-cpu.py

4. In a different terminal, start CARMA Platform:
./carma start all
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we have ../ for starting carma?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed


5. The script will automatically monitor and log CPU/memory usage
of all ROS2 nodes and related processes during CARMA operation

6. To stop monitoring:
- Press Ctrl+C in the monitoring terminal
- The CSV output file will be saved in the current directory as:
'cpu_usage_ros2_nodes.csv' or 'cpu_usage_ros2_nodes-N.csv'

Output:
- CSV file containing timestamp, process info, CPU and memory usage
- Data can be used to analyze CARMA Platform resource utilization
"""

import psutil
import subprocess
import time
import csv
import os
from datetime import datetime


# Function to create a unique filename by appending a number
def get_unique_filename(base_filename):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we follow the file naming convention of ROS bags and include the date/time? This would make it easier to correlate the script output with the ROS bag file.

counter = 1
filename, file_extension = os.path.splitext(base_filename)

# Loop until a file with a unique name is found
while os.path.isfile(base_filename):
base_filename = f"{filename}-{counter}{file_extension}"
counter += 1
return base_filename


# Base path to save the CSV file
base_output_file = "cpu_usage_ros2_nodes.csv"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you update the script so everything is saved in a folder? this way it would be easier to find/copy them after several runs.


# Get a unique filename
output_file = get_unique_filename(base_output_file)

# Open CSV file to store process usage data
with open(output_file, mode="a") as file:
writer = csv.writer(file)

# Write the header since it's a new file
writer.writerow(
[
"Timestamp",
"PID",
"Process Name",
"CPU (%)",
"Memory (%)",
"Command Line",
"Total CPU (%)",
]
)

while True:
# Get the current time with milliseconds
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]

# Get total CPU usage (overall system CPU usage)
total_cpu_percent = psutil.cpu_percent(interval=None) # Get immediate CPU usage

# Get list of running processes
for proc in psutil.process_iter(
["pid", "name", "cpu_percent", "memory_percent", "cmdline"]
):
try:
# Get CPU and memory usage of the process
cmdline = " ".join(proc.info["cmdline"]) # Convert list to string
if (
"ros" in proc.info["name"]
or "node" in proc.info["name"]
or "node" in cmdline
or "python3" in proc.info["name"]
or "ros" in cmdline
) and not ("code" in proc.info["name"]):
pid = proc.info["pid"]
name = proc.info["name"]
cpu_percent = proc.info["cpu_percent"]
memory_percent = proc.info["memory_percent"]

# Write process data to CSV, including the total CPU usage
writer.writerow(
[
timestamp,
pid,
name,
cpu_percent,
memory_percent,
cmdline,
total_cpu_percent,
]
)

except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
# Handle any processes that may have terminated or restricted access
continue

# Sleep for 1 second before the next iteration
time.sleep(1)
Loading