From 1813b159932d1963f41121a3b10a248c974f10b6 Mon Sep 17 00:00:00 2001 From: andreastaliad Date: Thu, 28 May 2026 23:30:28 +0300 Subject: [PATCH] Revert "added standalone run scripts for all tests and experiments" This reverts commit a54a29e4868b00c93a27e047bf9722a809e7c4c2. --- creation_time_experiment/run_creation_time.sh | 156 ------------ fork_bomb/run_fork_bomb.sh | 44 ---- .../run_pi_digits_benchmark.sh | 201 ++++------------ .../run_thread_recursive.sh | 222 ++++++++---------- 4 files changed, 145 insertions(+), 478 deletions(-) delete mode 100755 creation_time_experiment/run_creation_time.sh delete mode 100755 fork_bomb/run_fork_bomb.sh diff --git a/creation_time_experiment/run_creation_time.sh b/creation_time_experiment/run_creation_time.sh deleted file mode 100755 index 041ff54..0000000 --- a/creation_time_experiment/run_creation_time.sh +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -LC_ALL=C - -ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) -RUN_ID=$(date +"%Y%m%d_%H%M%S") -OUT_DIR="$ROOT_DIR/runs/$RUN_ID" -mkdir -p "$OUT_DIR" - -LOG_FILE="$OUT_DIR/activity.log" - -log() { - echo "[$(date -Iseconds)] $*" | tee -a "$LOG_FILE" -} - -count_processes() { - ls -d /proc/[0-9]* 2>/dev/null | wc -l -} - -count_threads_total() { - awk '/^Threads:/ {sum+=$2} END {print sum+0}' /proc/[0-9]*/status 2>/dev/null || echo 0 -} - -get_mem_kb() { - awk '/^MemTotal:/ {t=$2} /^MemAvailable:/ {a=$2} END {print t" "a}' /proc/meminfo -} - -sample_process_csv() { - local pid="$1" - local csv="$2" - local start_uptime="$3" - local max_seconds="$4" - - local have_pidstat=0 - if command -v pidstat >/dev/null 2>&1; then - have_pidstat=1 - else - log "pidstat not found; install sysstat for accurate CPU sampling" - fi - - local prev_cpu_total=0 - local prev_cpu_idle=0 - if [ -r /proc/stat ]; then - read -r _ c_user c_nice c_system c_idle c_iowait c_irq c_softirq c_steal _ _ < /proc/stat - prev_cpu_total=$((c_user + c_nice + c_system + c_idle + c_iowait + c_irq + c_softirq + c_steal)) - prev_cpu_idle=$((c_idle + c_iowait)) - fi - - while kill -0 "$pid" 2>/dev/null; do - local now_uptime elapsed_s - now_uptime=$(awk '{print $1}' /proc/uptime) - elapsed_s=$(awk -v s="$start_uptime" -v n="$now_uptime" 'BEGIN{printf "%.3f", (n-s)}') - - if [ "$max_seconds" -gt 0 ]; then - if awk -v e="$elapsed_s" -v m="$max_seconds" 'BEGIN{exit (e>m)?0:1}'; then - log "Timeout reached (${max_seconds}s), stopping PID=$pid" - kill -TERM "-$pid" 2>/dev/null || true - sleep 2 - kill -KILL "-$pid" 2>/dev/null || true - break - fi - fi - - local proc_count thread_total - proc_count=$(count_processes || echo 0) - thread_total=$(count_threads_total || echo 0) - - local load1 load5 load15 - read -r load1 load5 load15 _ < /proc/loadavg - - local mem_total mem_avail mem_used - read -r mem_total mem_avail < <(get_mem_kb || echo "0 0") - mem_used=$((mem_total - mem_avail)) - - local cpu rss vsz nlwp - rss=$(awk '/^VmRSS:/ {print $2}' "/proc/$pid/status" 2>/dev/null || echo 0) - vsz=$(awk '/^VmSize:/ {print $2}' "/proc/$pid/status" 2>/dev/null || echo 0) - nlwp=$(awk '/^Threads:/ {print $2}' "/proc/$pid/status" 2>/dev/null || echo 0) - if [ "$have_pidstat" -eq 1 ]; then - cpu=$(pidstat -p "$pid" 1 1 2>/dev/null | awk -v p="$pid" '$1 ~ /^[0-9]/ && $3==p {print $8; exit}') - cpu=${cpu:-0.00} - else - cpu=0.00 - fi - local stk=0 heap=0 - - local sys_cpu_pct=0.00 - if [ -r /proc/stat ]; then - read -r _ c_user c_nice c_system c_idle c_iowait c_irq c_softirq c_steal _ _ < /proc/stat - local cpu_total=$((c_user + c_nice + c_system + c_idle + c_iowait + c_irq + c_softirq + c_steal)) - local cpu_idle=$((c_idle + c_iowait)) - local dt_total=$((cpu_total - prev_cpu_total)) - local dt_idle=$((cpu_idle - prev_cpu_idle)) - sys_cpu_pct=$(awk -v t="$dt_total" -v i="$dt_idle" 'BEGIN{ if (t<=0) printf "0.00"; else printf "%.2f", (100.0*(t-i))/t }') - prev_cpu_total=$cpu_total - prev_cpu_idle=$cpu_idle - fi - - printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n" \ - "$(date -Iseconds)" "$elapsed_s" "$load1" "$load5" "$load15" \ - "$mem_total" "$mem_avail" "$mem_used" "$proc_count" "$thread_total" \ - "$pid" "$cpu" "$sys_cpu_pct" "${rss:-0}" "${vsz:-0}" "${stk:-0}" "${heap:-0}" "${nlwp:-0}" \ - >> "$csv" - - sleep 0.2 - done -} - -run_with_sampling() { - local name="$1" - local cmd="$2" - local csv="$3" - local max_seconds="$4" - - log "Starting $name: $cmd" - - echo "timestamp,elapsed_s,load1,load5,load15,mem_total_kb,mem_available_kb,mem_used_kb,proc_count,thread_count_total,pid,cpu_pct,sys_cpu_pct,rss_kb,vsz_kb,stack_kb,heap_kb,proc_threads" > "$csv" - - local start_uptime pid - start_uptime=$(awk '{print $1}' /proc/uptime) - - if command -v setsid >/dev/null 2>&1; then - setsid bash -c "$cmd" & - pid=$! - else - bash -c "$cmd" & - pid=$! - fi - - sample_process_csv "$pid" "$csv" "$start_uptime" "$max_seconds" - - set +e - wait "$pid" - local exit_code=$? - set -e - - log "Finished $name (exit_code=$exit_code)" -} - -log "Compiling creation_time" -gcc -O2 -pthread -o "$ROOT_DIR/creation_time" "$ROOT_DIR/creation_time.c" - -CREATION_TIME_ITERS=${CREATION_TIME_ITERS:-"100 1000 10000"} -CREATION_TIME_SECONDS=${CREATION_TIME_SECONDS:-60} - -STDOUT_LOG="$OUT_DIR/creation_time_stdout.log" -STDERR_LOG="$OUT_DIR/creation_time_stderr.log" - -run_with_sampling \ - "creation_time" \ - "cd '$ROOT_DIR' && { for n in $CREATION_TIME_ITERS; do echo \"=== iterations=\$n ===\"; ./creation_time -n \"\$n\"; done; } >'$STDOUT_LOG' 2>'$STDERR_LOG'" \ - "$OUT_DIR/creation_time.csv" \ - "$CREATION_TIME_SECONDS" - -log "Experiment finished" -log "Run directory: $OUT_DIR" diff --git a/fork_bomb/run_fork_bomb.sh b/fork_bomb/run_fork_bomb.sh deleted file mode 100755 index d0a2010..0000000 --- a/fork_bomb/run_fork_bomb.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -LC_ALL=C - -ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) -RUN_ID=$(date +"%Y%m%d_%H%M%S") -OUT_DIR="$ROOT_DIR/runs/$RUN_ID" -mkdir -p "$OUT_DIR" - -LOG_FILE="$OUT_DIR/activity.log" - -log() { - echo "[$(date -Iseconds)] $*" | tee -a "$LOG_FILE" -} - -log "Compiling fork_bomb" -gcc -O2 -o "$ROOT_DIR/fork_bomb" "$ROOT_DIR/fork_bomb.c" - -ALLOW_DANGEROUS=${ALLOW_DANGEROUS:-0} -FORK_BOMB_SECONDS=${FORK_BOMB_SECONDS:-5} -PROC_SAMPLE_STEP=${PROC_SAMPLE_STEP:-50} - -FORK_BOMB_CSV="$OUT_DIR/fork_bomb.csv" - -if [ "$ALLOW_DANGEROUS" -eq 1 ]; then - log "Starting fork_bomb (C-side logging)" - if command -v timeout >/dev/null 2>&1; then - timeout "$FORK_BOMB_SECONDS" sh -c "cd '$ROOT_DIR' && FORK_BOMB_CSV='$FORK_BOMB_CSV' PROC_SAMPLE_STEP='$PROC_SAMPLE_STEP' ./fork_bomb" || true - else - (cd "$ROOT_DIR" && FORK_BOMB_CSV="$FORK_BOMB_CSV" PROC_SAMPLE_STEP="$PROC_SAMPLE_STEP" ./fork_bomb) & - FB_PID=$! - sleep "$FORK_BOMB_SECONDS" || true - kill -TERM "-$FB_PID" 2>/dev/null || true - sleep 2 - kill -KILL "-$FB_PID" 2>/dev/null || true - fi - pkill -f "./fork_bomb" 2>/dev/null || true -else - log "Skipping fork_bomb (set ALLOW_DANGEROUS=1 to run)" - echo "timestamp,elapsed_s,load1,load5,load15,mem_total_kb,mem_available_kb,mem_used_kb,proc_count,thread_count_total,pid,cpu_pct,sys_cpu_pct,rss_kb,vsz_kb,stack_kb,heap_kb,proc_threads" > "$FORK_BOMB_CSV" -fi - -log "Experiment finished" -log "Run directory: $OUT_DIR" diff --git a/pi_digits_benchmark/run_pi_digits_benchmark.sh b/pi_digits_benchmark/run_pi_digits_benchmark.sh index 55d1d6b..ccc4017 100755 --- a/pi_digits_benchmark/run_pi_digits_benchmark.sh +++ b/pi_digits_benchmark/run_pi_digits_benchmark.sh @@ -2,167 +2,64 @@ set -euo pipefail LC_ALL=C -ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) -RUN_ID=$(date +"%Y%m%d_%H%M%S") -OUT_DIR="$ROOT_DIR/runs/$RUN_ID" -mkdir -p "$OUT_DIR" +DIR=$(cd "$(dirname "$0")" && pwd) +cd "$DIR" -LOG_FILE="$OUT_DIR/activity.log" +gcc -O2 -pthread -o pi_digits_benchmark pi_digits_benchmark.c -log() { - echo "[$(date -Iseconds)] $*" | tee -a "$LOG_FILE" -} - -count_processes() { - ls -d /proc/[0-9]* 2>/dev/null | wc -l -} - -count_threads_total() { - awk '/^Threads:/ {sum+=$2} END {print sum+0}' /proc/[0-9]*/status 2>/dev/null || echo 0 -} - -get_mem_kb() { - awk '/^MemTotal:/ {t=$2} /^MemAvailable:/ {a=$2} END {print t" "a}' /proc/meminfo -} - -sample_process_csv() { - local pid="$1" - local csv="$2" - local start_uptime="$3" - local max_seconds="$4" - - local have_pidstat=0 - if command -v pidstat >/dev/null 2>&1; then - have_pidstat=1 - else - log "pidstat not found; install sysstat for accurate CPU sampling" - fi - - local prev_cpu_total=0 - local prev_cpu_idle=0 - if [ -r /proc/stat ]; then - read -r _ c_user c_nice c_system c_idle c_iowait c_irq c_softirq c_steal _ _ < /proc/stat - prev_cpu_total=$((c_user + c_nice + c_system + c_idle + c_iowait + c_irq + c_softirq + c_steal)) - prev_cpu_idle=$((c_idle + c_iowait)) - fi - - while kill -0 "$pid" 2>/dev/null; do - local now_uptime elapsed_s - now_uptime=$(awk '{print $1}' /proc/uptime) - elapsed_s=$(awk -v s="$start_uptime" -v n="$now_uptime" 'BEGIN{printf "%.3f", (n-s)}') - - if [ "$max_seconds" -gt 0 ]; then - if awk -v e="$elapsed_s" -v m="$max_seconds" 'BEGIN{exit (e>m)?0:1}'; then - log "Timeout reached (${max_seconds}s), stopping PID=$pid" - kill -TERM "-$pid" 2>/dev/null || true - sleep 2 - kill -KILL "-$pid" 2>/dev/null || true - break - fi - fi - - local proc_count thread_total - proc_count=$(count_processes || echo 0) - thread_total=$(count_threads_total || echo 0) - - local load1 load5 load15 - read -r load1 load5 load15 _ < /proc/loadavg - - local mem_total mem_avail mem_used - read -r mem_total mem_avail < <(get_mem_kb || echo "0 0") - mem_used=$((mem_total - mem_avail)) - - local cpu rss vsz nlwp - rss=$(awk '/^VmRSS:/ {print $2}' "/proc/$pid/status" 2>/dev/null || echo 0) - vsz=$(awk '/^VmSize:/ {print $2}' "/proc/$pid/status" 2>/dev/null || echo 0) - nlwp=$(awk '/^Threads:/ {print $2}' "/proc/$pid/status" 2>/dev/null || echo 0) - if [ "$have_pidstat" -eq 1 ]; then - cpu=$(pidstat -p "$pid" 1 1 2>/dev/null | awk -v p="$pid" '$1 ~ /^[0-9]/ && $3==p {print $8; exit}') - cpu=${cpu:-0.00} - else - cpu=0.00 - fi - local stk=0 heap=0 - - local sys_cpu_pct=0.00 - if [ -r /proc/stat ]; then - read -r _ c_user c_nice c_system c_idle c_iowait c_irq c_softirq c_steal _ _ < /proc/stat - local cpu_total=$((c_user + c_nice + c_system + c_idle + c_iowait + c_irq + c_softirq + c_steal)) - local cpu_idle=$((c_idle + c_iowait)) - local dt_total=$((cpu_total - prev_cpu_total)) - local dt_idle=$((cpu_idle - prev_cpu_idle)) - sys_cpu_pct=$(awk -v t="$dt_total" -v i="$dt_idle" 'BEGIN{ if (t<=0) printf "0.00"; else printf "%.2f", (100.0*(t-i))/t }') - prev_cpu_total=$cpu_total - prev_cpu_idle=$cpu_idle - fi - - printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n" \ - "$(date -Iseconds)" "$elapsed_s" "$load1" "$load5" "$load15" \ - "$mem_total" "$mem_avail" "$mem_used" "$proc_count" "$thread_total" \ - "$pid" "$cpu" "$sys_cpu_pct" "${rss:-0}" "${vsz:-0}" "${stk:-0}" "${heap:-0}" "${nlwp:-0}" \ - >> "$csv" - - sleep 0.2 - done -} - -run_with_sampling() { - local name="$1" - local cmd="$2" - local csv="$3" - local max_seconds="$4" - - log "Starting $name: $cmd" - - echo "timestamp,elapsed_s,load1,load5,load15,mem_total_kb,mem_available_kb,mem_used_kb,proc_count,thread_count_total,pid,cpu_pct,sys_cpu_pct,rss_kb,vsz_kb,stack_kb,heap_kb,proc_threads" > "$csv" - - local start_uptime pid - start_uptime=$(awk '{print $1}' /proc/uptime) - - if command -v setsid >/dev/null 2>&1; then - setsid bash -c "$cmd" & - pid=$! - else - bash -c "$cmd" & - pid=$! - fi - - sample_process_csv "$pid" "$csv" "$start_uptime" "$max_seconds" - - set +e - wait "$pid" - local exit_code=$? - set -e - - log "Finished $name (exit_code=$exit_code)" -} - -log "Compiling pi_digits_benchmark" -gcc -O2 -pthread -o "$ROOT_DIR/pi_digits_benchmark" "$ROOT_DIR/pi_digits_benchmark.c" +echo "Compiled pi_digits_benchmark" THREAD_COUNT=${THREAD_COUNT:-4} PROCESS_COUNT=${PROCESS_COUNT:-4} PI_DIGITS=${PI_DIGITS:-2000} CHUNK_SIZE=${CHUNK_SIZE:-500} -PI_BENCH_OUT_BASE="$OUT_DIR/pi_digits_benchmark" +RUNS_DIR="$DIR/runs" +mkdir -p "$RUNS_DIR" +RUN_ID=$(date +"%Y%m%d_%H%M%S") -PI_THREAD_STDOUT="$OUT_DIR/pi_digits_thread_stdout.log" -PI_THREAD_STDERR="$OUT_DIR/pi_digits_thread_stderr.log" -PI_PROC_STDOUT="$OUT_DIR/pi_digits_process_stdout.log" -PI_PROC_STDERR="$OUT_DIR/pi_digits_process_stderr.log" +RESULTS_CSV="$DIR/results.csv" +if [ ! -f "$RESULTS_CSV" ]; then + echo "run_id,timestamp,host,kernel,mode,worker_count,pi_digits,chunk_size,exit_code,wall_s,cpu_user_s,cpu_sys_s,cpu_pct,max_rss_kb,max_vsz_kb,agg_rss_kb,agg_vsz_kb,agg_pss_kb,mem_snapshot_s,final_output_bytes" > "$RESULTS_CSV" +fi -run_with_sampling \ - "pi_digits_benchmark_thread" \ - "cd '$ROOT_DIR' && THREAD_COUNT='$THREAD_COUNT' PROCESS_COUNT='$PROCESS_COUNT' PI_DIGITS='$PI_DIGITS' CHUNK_SIZE='$CHUNK_SIZE' ./pi_digits_benchmark --mode thread --out-dir '$PI_BENCH_OUT_BASE/thread' >'$PI_THREAD_STDOUT' 2>'$PI_THREAD_STDERR'" \ - "$OUT_DIR/pi_digits_thread.csv" \ - 0 +run_mode() { + local mode="$1" + local out_dir="$RUNS_DIR/${RUN_ID}_${mode}" + local stdout_log="$out_dir/stdout.log" + local stderr_log="$out_dir/stderr.log" -run_with_sampling \ - "pi_digits_benchmark_process" \ - "cd '$ROOT_DIR' && THREAD_COUNT='$THREAD_COUNT' PROCESS_COUNT='$PROCESS_COUNT' PI_DIGITS='$PI_DIGITS' CHUNK_SIZE='$CHUNK_SIZE' ./pi_digits_benchmark --mode process --out-dir '$PI_BENCH_OUT_BASE/process' >'$PI_PROC_STDOUT' 2>'$PI_PROC_STDERR'" \ - "$OUT_DIR/pi_digits_process.csv" \ - 0 + mkdir -p "$out_dir" -log "Experiment finished" -log "Run directory: $OUT_DIR" + echo "Running mode=$mode out_dir=$out_dir" + THREAD_COUNT="$THREAD_COUNT" PROCESS_COUNT="$PROCESS_COUNT" PI_DIGITS="$PI_DIGITS" CHUNK_SIZE="$CHUNK_SIZE" \ + ./pi_digits_benchmark --mode "$mode" --out-dir "$out_dir" >"$stdout_log" 2>"$stderr_log" + + if [ -f "$out_dir/results.csv" ]; then + tail -n 1 "$out_dir/results.csv" >> "$RESULTS_CSV" + fi + + echo " stdout: $stdout_log" + echo " stderr: $stderr_log" + echo " results: $out_dir/results.csv" + echo " workers: $out_dir/workers.csv" + echo " pi output: $out_dir/pi_digits.txt" +} + +MODE=${1:-both} +case "$MODE" in + thread) + run_mode thread + ;; + process) + run_mode process + ;; + both) + run_mode thread + run_mode process + ;; + *) + echo "Usage: $0 [thread|process|both]" + exit 1 + ;; +esac diff --git a/thread_recursive_scaling/run_thread_recursive.sh b/thread_recursive_scaling/run_thread_recursive.sh index 4be8ee9..7889566 100755 --- a/thread_recursive_scaling/run_thread_recursive.sh +++ b/thread_recursive_scaling/run_thread_recursive.sh @@ -2,149 +2,119 @@ set -euo pipefail LC_ALL=C -ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +DIR=$(cd "$(dirname "$0")" && pwd) +cd "$DIR" + +gcc -O2 -pthread -o thread_recursive thread_recursive.c -lm + +echo "Compiled thread_recursive" + +# Usage: +# ./run_thread_recursive.sh [branch] [depth] [hold_seconds] +# Example: +# ./run_thread_recursive.sh 6 6 6 + +BRANCH=${1:-6} +DEPTH=${2:-6} +HOLD=${3:-6} + +RESULTS_CSV="$DIR/results.csv" +RUNS_DIR="$DIR/runs" +mkdir -p "$RUNS_DIR" + RUN_ID=$(date +"%Y%m%d_%H%M%S") -OUT_DIR="$ROOT_DIR/runs/$RUN_ID" -mkdir -p "$OUT_DIR" +STDOUT_LOG="$RUNS_DIR/${RUN_ID}_stdout.log" +STDERR_LOG="$RUNS_DIR/${RUN_ID}_stderr.log" +SAMPLE_LOG="$RUNS_DIR/${RUN_ID}_samples.csv" -LOG_FILE="$OUT_DIR/activity.log" +if [ ! -f "$RESULTS_CSV" ]; then + echo "run_id,timestamp,host,kernel,branch,depth,hold_s,exit_code,wall_s,max_rss_kb,max_vsz_kb,max_threads,avg_cpu,max_cpu,total_created_threads,estimated_full_tree" > "$RESULTS_CSV" +fi -log() { - echo "[$(date -Iseconds)] $*" | tee -a "$LOG_FILE" -} +echo "Running: ./thread_recursive -b $BRANCH -d $DEPTH -s $HOLD" -count_processes() { - ls -d /proc/[0-9]* 2>/dev/null | wc -l -} +START_UPTIME=$(awk '{print $1}' /proc/uptime) +./thread_recursive -b "$BRANCH" -d "$DEPTH" -s "$HOLD" >"$STDOUT_LOG" 2>"$STDERR_LOG" & +PID=$! -count_threads_total() { - awk '/^Threads:/ {sum+=$2} END {print sum+0}' /proc/[0-9]*/status 2>/dev/null || echo 0 -} +echo "Sampling metrics for PID=$PID (1s interval)" +echo "sec_from_start,cpu_pct,rss_kb,vsz_kb,nlwp" > "$SAMPLE_LOG" -get_mem_kb() { - awk '/^MemTotal:/ {t=$2} /^MemAvailable:/ {a=$2} END {print t" "a}' /proc/meminfo -} +MAX_RSS=0 +MAX_VSZ=0 +MAX_THR=0 +MAX_CPU=0 +SUM_CPU=0 +SAMPLE_COUNT=0 -sample_process_csv() { - local pid="$1" - local csv="$2" - local start_uptime="$3" - local max_seconds="$4" +CLK_TCK=$(getconf CLK_TCK) +PREV_UPTIME=$(awk '{print $1}' /proc/uptime) +PREV_TICKS=0 +if [ -r "/proc/$PID/stat" ]; then + PREV_TICKS=$(awk '{print $14 + $15}' "/proc/$PID/stat" 2>/dev/null || echo 0) +fi - local have_pidstat=0 - if command -v pidstat >/dev/null 2>&1; then - have_pidstat=1 - else - log "pidstat not found; install sysstat for accurate CPU sampling" - fi +while kill -0 "$PID" 2>/dev/null; do + NOW_UPTIME=$(awk '{print $1}' /proc/uptime) + ELAPSED_S=$(awk -v s="$START_UPTIME" -v n="$NOW_UPTIME" 'BEGIN{printf "%.3f", (n-s)}') - local prev_cpu_total=0 - local prev_cpu_idle=0 - if [ -r /proc/stat ]; then - read -r _ c_user c_nice c_system c_idle c_iowait c_irq c_softirq c_steal _ _ < /proc/stat - prev_cpu_total=$((c_user + c_nice + c_system + c_idle + c_iowait + c_irq + c_softirq + c_steal)) - prev_cpu_idle=$((c_idle + c_iowait)) - fi + if [ -r "/proc/$PID/status" ] && [ -r "/proc/$PID/stat" ]; then + RSS=$(awk '/^VmRSS:/ {print $2}' "/proc/$PID/status" 2>/dev/null || echo 0) + VSZ=$(awk '/^VmSize:/ {print $2}' "/proc/$PID/status" 2>/dev/null || echo 0) + NLWP=$(awk '/^Threads:/ {print $2}' "/proc/$PID/status" 2>/dev/null || echo 0) + CUR_TICKS=$(awk '{print $14 + $15}' "/proc/$PID/stat" 2>/dev/null || echo 0) - while kill -0 "$pid" 2>/dev/null; do - local now_uptime elapsed_s - now_uptime=$(awk '{print $1}' /proc/uptime) - elapsed_s=$(awk -v s="$start_uptime" -v n="$now_uptime" 'BEGIN{printf "%.3f", (n-s)}') + RSS=${RSS:-0} + VSZ=${VSZ:-0} + NLWP=${NLWP:-0} - if [ "$max_seconds" -gt 0 ]; then - if awk -v e="$elapsed_s" -v m="$max_seconds" 'BEGIN{exit (e>m)?0:1}'; then - log "Timeout reached (${max_seconds}s), stopping PID=$pid" - kill -TERM "-$pid" 2>/dev/null || true - sleep 2 - kill -KILL "-$pid" 2>/dev/null || true - break - fi - fi + DT=$(awk -v a="$PREV_UPTIME" -v b="$NOW_UPTIME" 'BEGIN{print b-a}') + DC=$(awk -v a="$PREV_TICKS" -v b="$CUR_TICKS" 'BEGIN{print b-a}') + CPU=$(awk -v dt="$DT" -v dc="$DC" -v hz="$CLK_TCK" 'BEGIN{ if (dt<=0) printf "0.00"; else printf "%.2f", (100.0*dc)/(dt*hz) }') - local proc_count thread_total - proc_count=$(count_processes || echo 0) - thread_total=$(count_threads_total || echo 0) + echo "$ELAPSED_S,$CPU,$RSS,$VSZ,$NLWP" >> "$SAMPLE_LOG" - local load1 load5 load15 - read -r load1 load5 load15 _ < /proc/loadavg + MAX_RSS=$(awk -v a="$MAX_RSS" -v b="$RSS" 'BEGIN{print (b>a)?b:a}') + MAX_VSZ=$(awk -v a="$MAX_VSZ" -v b="$VSZ" 'BEGIN{print (b>a)?b:a}') + MAX_THR=$(awk -v a="$MAX_THR" -v b="$NLWP" 'BEGIN{print (b>a)?b:a}') + MAX_CPU=$(awk -v a="$MAX_CPU" -v b="$CPU" 'BEGIN{print (b>a)?b:a}') + SUM_CPU=$(awk -v s="$SUM_CPU" -v c="$CPU" 'BEGIN{print s+c}') + SAMPLE_COUNT=$((SAMPLE_COUNT + 1)) - local mem_total mem_avail mem_used - read -r mem_total mem_avail < <(get_mem_kb || echo "0 0") - mem_used=$((mem_total - mem_avail)) + PREV_UPTIME=$NOW_UPTIME + PREV_TICKS=$CUR_TICKS + fi + sleep 1 +done - local cpu rss vsz nlwp - rss=$(awk '/^VmRSS:/ {print $2}' "/proc/$pid/status" 2>/dev/null || echo 0) - vsz=$(awk '/^VmSize:/ {print $2}' "/proc/$pid/status" 2>/dev/null || echo 0) - nlwp=$(awk '/^Threads:/ {print $2}' "/proc/$pid/status" 2>/dev/null || echo 0) - if [ "$have_pidstat" -eq 1 ]; then - cpu=$(pidstat -p "$pid" 1 1 2>/dev/null | awk -v p="$pid" '$1 ~ /^[0-9]/ && $3==p {print $8; exit}') - cpu=${cpu:-0.00} - else - cpu=0.00 - fi - local stk=0 heap=0 +set +e +wait "$PID" +EXIT_CODE=$? +set -e +END_UPTIME=$(awk '{print $1}' /proc/uptime) +WALL_S=$(awk -v s="$START_UPTIME" -v e="$END_UPTIME" 'BEGIN{printf "%.6f", (e-s)}') - local sys_cpu_pct=0.00 - if [ -r /proc/stat ]; then - read -r _ c_user c_nice c_system c_idle c_iowait c_irq c_softirq c_steal _ _ < /proc/stat - local cpu_total=$((c_user + c_nice + c_system + c_idle + c_iowait + c_irq + c_softirq + c_steal)) - local cpu_idle=$((c_idle + c_iowait)) - local dt_total=$((cpu_total - prev_cpu_total)) - local dt_idle=$((cpu_idle - prev_cpu_idle)) - sys_cpu_pct=$(awk -v t="$dt_total" -v i="$dt_idle" 'BEGIN{ if (t<=0) printf "0.00"; else printf "%.2f", (100.0*(t-i))/t }') - prev_cpu_total=$cpu_total - prev_cpu_idle=$cpu_idle - fi +AVG_CPU=0 +if [ "$SAMPLE_COUNT" -gt 0 ]; then + AVG_CPU=$(awk -v s="$SUM_CPU" -v n="$SAMPLE_COUNT" 'BEGIN{printf "%.2f", s/n}') +fi +MAX_CPU_FMT=$(awk -v m="$MAX_CPU" 'BEGIN{printf "%.2f", m}') - printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n" \ - "$(date -Iseconds)" "$elapsed_s" "$load1" "$load5" "$load15" \ - "$mem_total" "$mem_avail" "$mem_used" "$proc_count" "$thread_total" \ - "$pid" "$cpu" "$sys_cpu_pct" "${rss:-0}" "${vsz:-0}" "${stk:-0}" "${heap:-0}" "${nlwp:-0}" \ - >> "$csv" +TOTAL_CREATED=$(grep -E "total_created_threads:" "$STDOUT_LOG" | awk -F': ' '{print $2}' | tail -n1) +ESTIMATED=$(grep -E "estimated_full_tree:" "$STDOUT_LOG" | awk -F': ' '{print $2}' | tail -n1) +TOTAL_CREATED=${TOTAL_CREATED:-NA} +ESTIMATED=${ESTIMATED:-NA} - sleep 0.2 - done -} +TS=$(date +"%Y-%m-%dT%H:%M:%S%z") +HOST=$(hostname) +KERNEL=$(uname -r) -run_with_sampling() { - local name="$1" - local cmd="$2" - local csv="$3" - local max_seconds="$4" +echo "$RUN_ID,$TS,$HOST,$KERNEL,$BRANCH,$DEPTH,$HOLD,$EXIT_CODE,$WALL_S,$MAX_RSS,$MAX_VSZ,$MAX_THR,$AVG_CPU,$MAX_CPU_FMT,$TOTAL_CREATED,$ESTIMATED" >> "$RESULTS_CSV" - log "Starting $name: $cmd" - - echo "timestamp,elapsed_s,load1,load5,load15,mem_total_kb,mem_available_kb,mem_used_kb,proc_count,thread_count_total,pid,cpu_pct,sys_cpu_pct,rss_kb,vsz_kb,stack_kb,heap_kb,proc_threads" > "$csv" - - local start_uptime pid - start_uptime=$(awk '{print $1}' /proc/uptime) - - if command -v setsid >/dev/null 2>&1; then - setsid bash -c "$cmd" & - pid=$! - else - bash -c "$cmd" & - pid=$! - fi - - sample_process_csv "$pid" "$csv" "$start_uptime" "$max_seconds" - - set +e - wait "$pid" - local exit_code=$? - set -e - - log "Finished $name (exit_code=$exit_code)" -} - -log "Compiling thread_recursive" -gcc -O2 -pthread -o "$ROOT_DIR/thread_recursive" "$ROOT_DIR/thread_recursive.c" -lm - -run_with_sampling \ - "thread_recursive_scaling" \ - "cd '$ROOT_DIR' && exec ./thread_recursive -b 6 -d 6 -s 6" \ - "$OUT_DIR/thread_recursive_scaling.csv" \ - 0 - -log "Experiment finished" -log "Run directory: $OUT_DIR" +echo +echo "Run complete" +echo " stdout: $STDOUT_LOG" +echo " stderr: $STDERR_LOG" +echo " samples: $SAMPLE_LOG" +echo " results csv: $RESULTS_CSV" +echo " exit_code=$EXIT_CODE wall_s=$WALL_S max_rss_kb=$MAX_RSS max_threads=$MAX_THR avg_cpu=$AVG_CPU max_cpu=$MAX_CPU_FMT"