Skip to content

Instantly share code, notes, and snippets.

@creotiv
Last active May 1, 2025 10:48
Show Gist options
  • Save creotiv/63166cb1c3c6d0e5c14e678542306bdc to your computer and use it in GitHub Desktop.
Save creotiv/63166cb1c3c6d0e5c14e678542306bdc to your computer and use it in GitHub Desktop.
#!/bin/bash
# Script to monitor CPU throttling time and generate a plot
# Auto-install required packages
install_python_packages() {
for package in "$@"; do
if ! python3 -c "import $package" &> /dev/null; then
echo "Installing Python package: $package"
pip3 install "$package" || pip3 install --break-system-packages "$package" || python3 -m pip install "$package" ||{
echo "Failed to install $package. Please install it manually."
exit 1
}
fi
done
}
# Check if Python is installed
if ! command -v python3 &> /dev/null; then
echo "Python 3 is required but not installed. Please install Python 3."
exit 1
fi
# Auto-install required packages
echo "Checking and installing required Python packages..."
install_python_packages matplotlib numpy
# Create a temporary file for data
DATA_FILE=$(mktemp)
echo "Timestamp,CPU,ThrottleTime" > "$DATA_FILE"
# Function to clean up and create plot
cleanup_and_plot() {
echo -e "\nCreating plot from collected data..."
# Create the plot using Python
python3 - "$DATA_FILE" <<EOF
import sys
import matplotlib.pyplot as plt
import numpy as np
import csv
from datetime import datetime
import matplotlib.dates as mdates
import os
# Read the data file
data_file = sys.argv[1]
# Detect unique CPUs from the data
cpu_ids = set()
timestamps = []
csv_data = []
# Parse the CSV file to find all unique CPUs
with open(data_file, 'r') as f:
reader = csv.reader(f)
header = next(reader) # Skip header
for row in reader:
if len(row) == 3: # Ensure row is valid
timestamp_str, cpu, throttle_time = row
try:
cpu = int(cpu)
cpu_ids.add(cpu)
csv_data.append((timestamp_str, cpu, throttle_time))
except (ValueError, TypeError):
continue
# Sort CPUs for consistent colors
cpus = sorted(list(cpu_ids))
if not cpus:
print("No CPU data found. Exiting.")
sys.exit(1)
# Initialize data structures
cpu_data = {cpu: [] for cpu in cpus}
timestamps_dict = {}
# Parse the collected data
for row in csv_data:
timestamp_str, cpu, throttle_time = row
try:
timestamp = datetime.fromisoformat(timestamp_str)
throttle_time = float(throttle_time)
if timestamp not in timestamps:
timestamps.append(timestamp)
cpu_data[cpu].append(throttle_time)
except (ValueError, TypeError):
continue
# Sort timestamps
timestamps.sort()
# Create the plot
plt.figure(figsize=(12, 8))
for cpu in cpus:
if cpu_data[cpu]: # Only plot if we have data
plt.plot(timestamps[:len(cpu_data[cpu])], cpu_data[cpu], marker='o', linestyle='-', label=f'CPU {cpu}')
plt.title('CPU Throttling Time')
plt.xlabel('Time')
plt.ylabel('Throttle Time (ms)')
plt.grid(True)
plt.legend()
# Format x-axis to show time nicely
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))
plt.gcf().autofmt_xdate()
# Save the plot
output_file = 'cpu_throttle_data.png'
plt.savefig(output_file)
print(f"Plot saved as {output_file}")
# Also save a copy of the raw data as CSV
import shutil
shutil.copyfile(data_file, 'cpu_throttle_data.csv')
print(f"Raw data saved as cpu_throttle_data.csv")
EOF
# Clean up temp file
rm -f "$DATA_FILE"
echo "Done!"
exit 0
}
# Set trap for Ctrl+C
trap cleanup_and_plot SIGINT
# Detect number of CPUs
NUM_CPUS=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
echo "Detected $NUM_CPUS CPUs on this system"
echo "Monitoring CPU throttling data. Press Ctrl+C to stop and generate plot."
echo "Data will be collected every 5 seconds..."
# Main loop to collect data
while true; do
timestamp=$(date -Iseconds)
for cpu in $(seq 0 $((NUM_CPUS-1))); do
# Get throttle time using sudo
throttle_time=$(sudo cat /sys/devices/system/cpu/cpu${cpu}/thermal_throttle/core_throttle_total_time_ms 2>/dev/null || echo "0")
# Check if we got a valid number
if [[ "$throttle_time" =~ ^[0-9]+$ ]]; then
echo "$timestamp,$cpu,$throttle_time" >> "$DATA_FILE"
else
echo "$timestamp,$cpu,0" >> "$DATA_FILE"
fi
done
# Wait for 5 seconds
sleep 5
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment