Add CPU profiling to run_all.sh

- Added get_cpu_usage() function to sample CPU percentage
- Updated profile_resources() to profile both memory and CPU
- Modified run_program() to track CPU usage alongside memory
- Updated output format to show CPU statistics
- Summary now displays: Time, Memory (avg/peak), CPU (avg/peak)
- Both memory and CPU are sampled every 10ms during execution
This commit is contained in:
Ein Anderssono
2026-04-23 00:52:39 +02:00
parent cb9363dc26
commit f0516beadf
+53 -20
View File
@@ -48,24 +48,45 @@ get_memory_usage() {
fi fi
} }
# Function to profile memory during execution # Function to get CPU usage of a process (in percentage)
profile_memory() { get_cpu_usage() {
local pid=$1 local pid=$1
local output_file=$2 if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
# Use ps to get CPU percentage
ps -o %cpu= -p "$pid" 2>/dev/null | awk '{print int($1)}' || echo "0"
else
echo "0"
fi
}
# Function to profile memory and CPU during execution
profile_resources() {
local pid=$1
local mem_output_file=$2
local cpu_output_file=$3
local peak_mem=0 local peak_mem=0
local peak_cpu=0
local current_mem local current_mem
local current_cpu
# Sample memory every 10ms while process is running # Sample resources every 10ms while process is running
while kill -0 "$pid" 2>/dev/null; do while kill -0 "$pid" 2>/dev/null; do
current_mem=$(get_memory_usage "$pid") current_mem=$(get_memory_usage "$pid")
current_cpu=$(get_cpu_usage "$pid")
if [ "$current_mem" -gt "$peak_mem" ]; then if [ "$current_mem" -gt "$peak_mem" ]; then
peak_mem=$current_mem peak_mem=$current_mem
fi fi
echo "$current_mem" >> "$output_file" if [ "$current_cpu" -gt "$peak_cpu" ]; then
peak_cpu=$current_cpu
fi
echo "$current_mem" >> "$mem_output_file"
echo "$current_cpu" >> "$cpu_output_file"
sleep 0.01 2>/dev/null || sleep 0.1 sleep 0.01 2>/dev/null || sleep 0.1
done done
echo "$peak_mem" echo "$peak_mem $peak_cpu"
} }
echo "=== Pi-beräkning med $DECIMALS decimaler (4 körningar, genomsnitt av 3 efter warmup) ===" echo "=== Pi-beräkning med $DECIMALS decimaler (4 körningar, genomsnitt av 3 efter warmup) ==="
@@ -83,23 +104,28 @@ run_program() {
local total_time=0 local total_time=0
local total_memory=0 local total_memory=0
local total_cpu=0
local success_count=0 local success_count=0
local result local result
local peak_memory=0 local peak_memory=0
local peak_cpu=0
# Run 4 times, discard first run (warmup) # Run 4 times, discard first run (warmup)
for i in 1 2 3 4; do for i in 1 2 3 4; do
local mem_profile_file="/tmp/${name}_mem_$$_$i" local mem_profile_file="/tmp/${name}_mem_$$_$i"
local cpu_profile_file="/tmp/${name}_cpu_$$_$i"
local start=$(date +%s%N) local start=$(date +%s%N)
# Run program and capture PID for memory profiling # Run program and capture PID for resource profiling
if [ "$i" -gt 1 ]; then if [ "$i" -gt 1 ]; then
# For runs 2-4, profile memory # For runs 2-4, profile memory and CPU
"$@" 2>/dev/null & "$@" 2>/dev/null &
local pid=$! local pid=$!
# Profile memory in background # Profile resources in background
local peak_mem=$(profile_memory "$pid" "$mem_profile_file") local resources=$(profile_resources "$pid" "$mem_profile_file" "$cpu_profile_file")
local peak_mem=$(echo "$resources" | awk '{print $1}')
local peak_cpu_val=$(echo "$resources" | awk '{print $2}')
# Wait for process to complete # Wait for process to complete
wait "$pid" 2>/dev/null wait "$pid" 2>/dev/null
@@ -112,10 +138,14 @@ run_program() {
total_time=$((total_time + elapsed)) total_time=$((total_time + elapsed))
total_memory=$((total_memory + peak_mem)) total_memory=$((total_memory + peak_mem))
total_cpu=$((total_cpu + peak_cpu_val))
if [ "$peak_mem" -gt "$peak_memory" ]; then if [ "$peak_mem" -gt "$peak_memory" ]; then
peak_memory=$peak_mem peak_memory=$peak_mem
fi fi
if [ "$peak_cpu_val" -gt "$peak_cpu" ]; then
peak_cpu=$peak_cpu_val
fi
if verify "$result" "$DECIMALS"; then if verify "$result" "$DECIMALS"; then
((success_count++)) ((success_count++))
@@ -123,11 +153,11 @@ run_program() {
else else
echo -e "${RED}ERROR${NC}" echo -e "${RED}ERROR${NC}"
results+=("999999 $name ERROR") results+=("999999 $name ERROR")
rm -f "$mem_profile_file" rm -f "$mem_profile_file" "$cpu_profile_file"
return return
fi fi
rm -f "$mem_profile_file" rm -f "$mem_profile_file" "$cpu_profile_file"
else else
# First run (warmup) - just execute without profiling # First run (warmup) - just execute without profiling
if result=$("$@" 2>/dev/null); then if result=$("$@" 2>/dev/null); then
@@ -143,17 +173,18 @@ run_program() {
# Calculate averages # Calculate averages
local avg_time=$((total_time / 3)) local avg_time=$((total_time / 3))
local avg_memory=$((total_memory / 3)) local avg_memory=$((total_memory / 3))
local avg_cpu=$((total_cpu / 3))
# Convert memory to MB for display # Convert memory to MB for display
local avg_memory_mb=$((avg_memory / 1024)) local avg_memory_mb=$((avg_memory / 1024))
local peak_memory_mb=$((peak_memory / 1024)) local peak_memory_mb=$((peak_memory / 1024))
if [ $success_count -eq 3 ]; then if [ $success_count -eq 3 ]; then
echo -e "${GREEN}SUCCESS${NC} $avg_time ms (avg), ${BLUE}${avg_memory_mb}MB avg, ${YELLOW}${peak_memory_mb}MB peak${NC}" echo -e "${GREEN}SUCCESS${NC} $avg_time ms, ${BLUE}${avg_memory_mb}MB mem, ${YELLOW}${avg_cpu}% CPU avg, ${peak_cpu}% CPU peak${NC}"
results+=("$avg_time $name SUCCESS $avg_memory $peak_memory") results+=("$avg_time $name SUCCESS $avg_memory $peak_memory $avg_cpu $peak_cpu")
else else
echo -e "${RED}FAILED${NC} $avg_time ms (avg), ${BLUE}${avg_memory_mb}MB avg, ${YELLOW}${peak_memory_mb}MB peak${NC}" echo -e "${RED}FAILED${NC} $avg_time ms, ${BLUE}${avg_memory_mb}MB mem, ${YELLOW}${avg_cpu}% CPU avg, ${peak_cpu}% CPU peak${NC}"
results+=("$avg_time $name FAILED $avg_memory $peak_memory") results+=("$avg_time $name FAILED $avg_memory $peak_memory $avg_cpu $peak_cpu")
fi fi
} }
@@ -201,8 +232,8 @@ echo ""
IFS=$'\n' sorted=($(printf '%s\n' "${results[@]}" | sort -n)) IFS=$'\n' sorted=($(printf '%s\n' "${results[@]}" | sort -n))
unset IFS unset IFS
echo "Språk Status Tid (ms) Minne (MB)" echo "Språk Status Tid (ms) Minne (MB) CPU (%)"
echo "================================================" echo "================================================================"
for entry in "${sorted[@]}"; do for entry in "${sorted[@]}"; do
time_ms=$(echo "$entry" | awk '{print $1}') time_ms=$(echo "$entry" | awk '{print $1}')
@@ -210,6 +241,8 @@ for entry in "${sorted[@]}"; do
status=$(echo "$entry" | awk '{print $3}') status=$(echo "$entry" | awk '{print $3}')
avg_mem=$(echo "$entry" | awk '{print $4}') avg_mem=$(echo "$entry" | awk '{print $4}')
peak_mem=$(echo "$entry" | awk '{print $5}') peak_mem=$(echo "$entry" | awk '{print $5}')
avg_cpu=$(echo "$entry" | awk '{print $6}')
peak_cpu=$(echo "$entry" | awk '{print $7}')
# Convert to MB # Convert to MB
avg_mem_mb=$((avg_mem / 1024)) avg_mem_mb=$((avg_mem / 1024))
@@ -218,9 +251,9 @@ for entry in "${sorted[@]}"; do
printf "%-12s " "$name" printf "%-12s " "$name"
if [ "$status" = "SUCCESS" ]; then if [ "$status" = "SUCCESS" ]; then
echo -e "${GREEN}$status${NC} $time_ms ms ${BLUE}${avg_mem_mb}MB avg / ${YELLOW}${peak_mem_mb}MB peak${NC}" echo -e "${GREEN}$status${NC} $time_ms ms ${BLUE}${avg_mem_mb}MB avg / ${YELLOW}${peak_mem_mb}MB peak ${avg_cpu}% avg / ${peak_cpu}% peak${NC}"
else else
echo -e "${RED}$status${NC} $time_ms ms ${BLUE}${avg_mem_mb}MB avg / ${YELLOW}${peak_mem_mb}MB peak${NC}" echo -e "${RED}$status${NC} $time_ms ms ${BLUE}${avg_mem_mb}MB avg / ${YELLOW}${peak_mem_mb}MB peak ${avg_cpu}% avg / ${peak_cpu}% peak${NC}"
fi fi
done done