Revert "added standalone run scripts for all tests and experiments"

This reverts commit a54a29e486.
This commit is contained in:
2026-05-28 23:30:28 +03:00
parent a54a29e486
commit 1813b15993
4 changed files with 145 additions and 478 deletions
@@ -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"
-44
View File
@@ -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"
+49 -152
View File
@@ -2,167 +2,64 @@
set -euo pipefail set -euo pipefail
LC_ALL=C LC_ALL=C
ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) DIR=$(cd "$(dirname "$0")" && pwd)
RUN_ID=$(date +"%Y%m%d_%H%M%S") cd "$DIR"
OUT_DIR="$ROOT_DIR/runs/$RUN_ID"
mkdir -p "$OUT_DIR"
LOG_FILE="$OUT_DIR/activity.log" gcc -O2 -pthread -o pi_digits_benchmark pi_digits_benchmark.c
log() { echo "Compiled pi_digits_benchmark"
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"
THREAD_COUNT=${THREAD_COUNT:-4} THREAD_COUNT=${THREAD_COUNT:-4}
PROCESS_COUNT=${PROCESS_COUNT:-4} PROCESS_COUNT=${PROCESS_COUNT:-4}
PI_DIGITS=${PI_DIGITS:-2000} PI_DIGITS=${PI_DIGITS:-2000}
CHUNK_SIZE=${CHUNK_SIZE:-500} 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" RESULTS_CSV="$DIR/results.csv"
PI_THREAD_STDERR="$OUT_DIR/pi_digits_thread_stderr.log" if [ ! -f "$RESULTS_CSV" ]; then
PI_PROC_STDOUT="$OUT_DIR/pi_digits_process_stdout.log" 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"
PI_PROC_STDERR="$OUT_DIR/pi_digits_process_stderr.log" fi
run_with_sampling \ run_mode() {
"pi_digits_benchmark_thread" \ local mode="$1"
"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'" \ local out_dir="$RUNS_DIR/${RUN_ID}_${mode}"
"$OUT_DIR/pi_digits_thread.csv" \ local stdout_log="$out_dir/stdout.log"
0 local stderr_log="$out_dir/stderr.log"
run_with_sampling \ mkdir -p "$out_dir"
"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
log "Experiment finished" echo "Running mode=$mode out_dir=$out_dir"
log "Run directory: $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
+96 -126
View File
@@ -2,149 +2,119 @@
set -euo pipefail set -euo pipefail
LC_ALL=C 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") RUN_ID=$(date +"%Y%m%d_%H%M%S")
OUT_DIR="$ROOT_DIR/runs/$RUN_ID" STDOUT_LOG="$RUNS_DIR/${RUN_ID}_stdout.log"
mkdir -p "$OUT_DIR" 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 "Running: ./thread_recursive -b $BRANCH -d $DEPTH -s $HOLD"
echo "[$(date -Iseconds)] $*" | tee -a "$LOG_FILE"
}
count_processes() { START_UPTIME=$(awk '{print $1}' /proc/uptime)
ls -d /proc/[0-9]* 2>/dev/null | wc -l ./thread_recursive -b "$BRANCH" -d "$DEPTH" -s "$HOLD" >"$STDOUT_LOG" 2>"$STDERR_LOG" &
} PID=$!
count_threads_total() { echo "Sampling metrics for PID=$PID (1s interval)"
awk '/^Threads:/ {sum+=$2} END {print sum+0}' /proc/[0-9]*/status 2>/dev/null || echo 0 echo "sec_from_start,cpu_pct,rss_kb,vsz_kb,nlwp" > "$SAMPLE_LOG"
}
get_mem_kb() { MAX_RSS=0
awk '/^MemTotal:/ {t=$2} /^MemAvailable:/ {a=$2} END {print t" "a}' /proc/meminfo MAX_VSZ=0
} MAX_THR=0
MAX_CPU=0
SUM_CPU=0
SAMPLE_COUNT=0
sample_process_csv() { CLK_TCK=$(getconf CLK_TCK)
local pid="$1" PREV_UPTIME=$(awk '{print $1}' /proc/uptime)
local csv="$2" PREV_TICKS=0
local start_uptime="$3" if [ -r "/proc/$PID/stat" ]; then
local max_seconds="$4" PREV_TICKS=$(awk '{print $14 + $15}' "/proc/$PID/stat" 2>/dev/null || echo 0)
fi
local have_pidstat=0 while kill -0 "$PID" 2>/dev/null; do
if command -v pidstat >/dev/null 2>&1; then NOW_UPTIME=$(awk '{print $1}' /proc/uptime)
have_pidstat=1 ELAPSED_S=$(awk -v s="$START_UPTIME" -v n="$NOW_UPTIME" 'BEGIN{printf "%.3f", (n-s)}')
else
log "pidstat not found; install sysstat for accurate CPU sampling"
fi
local prev_cpu_total=0 if [ -r "/proc/$PID/status" ] && [ -r "/proc/$PID/stat" ]; then
local prev_cpu_idle=0 RSS=$(awk '/^VmRSS:/ {print $2}' "/proc/$PID/status" 2>/dev/null || echo 0)
if [ -r /proc/stat ]; then VSZ=$(awk '/^VmSize:/ {print $2}' "/proc/$PID/status" 2>/dev/null || echo 0)
read -r _ c_user c_nice c_system c_idle c_iowait c_irq c_softirq c_steal _ _ < /proc/stat NLWP=$(awk '/^Threads:/ {print $2}' "/proc/$PID/status" 2>/dev/null || echo 0)
prev_cpu_total=$((c_user + c_nice + c_system + c_idle + c_iowait + c_irq + c_softirq + c_steal)) CUR_TICKS=$(awk '{print $14 + $15}' "/proc/$PID/stat" 2>/dev/null || echo 0)
prev_cpu_idle=$((c_idle + c_iowait))
fi
while kill -0 "$pid" 2>/dev/null; do RSS=${RSS:-0}
local now_uptime elapsed_s VSZ=${VSZ:-0}
now_uptime=$(awk '{print $1}' /proc/uptime) NLWP=${NLWP:-0}
elapsed_s=$(awk -v s="$start_uptime" -v n="$now_uptime" 'BEGIN{printf "%.3f", (n-s)}')
if [ "$max_seconds" -gt 0 ]; then DT=$(awk -v a="$PREV_UPTIME" -v b="$NOW_UPTIME" 'BEGIN{print b-a}')
if awk -v e="$elapsed_s" -v m="$max_seconds" 'BEGIN{exit (e>m)?0:1}'; then DC=$(awk -v a="$PREV_TICKS" -v b="$CUR_TICKS" 'BEGIN{print b-a}')
log "Timeout reached (${max_seconds}s), stopping PID=$pid" 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) }')
kill -TERM "-$pid" 2>/dev/null || true
sleep 2
kill -KILL "-$pid" 2>/dev/null || true
break
fi
fi
local proc_count thread_total echo "$ELAPSED_S,$CPU,$RSS,$VSZ,$NLWP" >> "$SAMPLE_LOG"
proc_count=$(count_processes || echo 0)
thread_total=$(count_threads_total || echo 0)
local load1 load5 load15 MAX_RSS=$(awk -v a="$MAX_RSS" -v b="$RSS" 'BEGIN{print (b>a)?b:a}')
read -r load1 load5 load15 _ < /proc/loadavg 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 PREV_UPTIME=$NOW_UPTIME
read -r mem_total mem_avail < <(get_mem_kb || echo "0 0") PREV_TICKS=$CUR_TICKS
mem_used=$((mem_total - mem_avail)) fi
sleep 1
done
local cpu rss vsz nlwp set +e
rss=$(awk '/^VmRSS:/ {print $2}' "/proc/$pid/status" 2>/dev/null || echo 0) wait "$PID"
vsz=$(awk '/^VmSize:/ {print $2}' "/proc/$pid/status" 2>/dev/null || echo 0) EXIT_CODE=$?
nlwp=$(awk '/^Threads:/ {print $2}' "/proc/$pid/status" 2>/dev/null || echo 0) set -e
if [ "$have_pidstat" -eq 1 ]; then END_UPTIME=$(awk '{print $1}' /proc/uptime)
cpu=$(pidstat -p "$pid" 1 1 2>/dev/null | awk -v p="$pid" '$1 ~ /^[0-9]/ && $3==p {print $8; exit}') WALL_S=$(awk -v s="$START_UPTIME" -v e="$END_UPTIME" 'BEGIN{printf "%.6f", (e-s)}')
cpu=${cpu:-0.00}
else
cpu=0.00
fi
local stk=0 heap=0
local sys_cpu_pct=0.00 AVG_CPU=0
if [ -r /proc/stat ]; then if [ "$SAMPLE_COUNT" -gt 0 ]; then
read -r _ c_user c_nice c_system c_idle c_iowait c_irq c_softirq c_steal _ _ < /proc/stat AVG_CPU=$(awk -v s="$SUM_CPU" -v n="$SAMPLE_COUNT" 'BEGIN{printf "%.2f", s/n}')
local cpu_total=$((c_user + c_nice + c_system + c_idle + c_iowait + c_irq + c_softirq + c_steal)) fi
local cpu_idle=$((c_idle + c_iowait)) MAX_CPU_FMT=$(awk -v m="$MAX_CPU" 'BEGIN{printf "%.2f", m}')
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" \ TOTAL_CREATED=$(grep -E "total_created_threads:" "$STDOUT_LOG" | awk -F': ' '{print $2}' | tail -n1)
"$(date -Iseconds)" "$elapsed_s" "$load1" "$load5" "$load15" \ ESTIMATED=$(grep -E "estimated_full_tree:" "$STDOUT_LOG" | awk -F': ' '{print $2}' | tail -n1)
"$mem_total" "$mem_avail" "$mem_used" "$proc_count" "$thread_total" \ TOTAL_CREATED=${TOTAL_CREATED:-NA}
"$pid" "$cpu" "$sys_cpu_pct" "${rss:-0}" "${vsz:-0}" "${stk:-0}" "${heap:-0}" "${nlwp:-0}" \ ESTIMATED=${ESTIMATED:-NA}
>> "$csv"
sleep 0.2 TS=$(date +"%Y-%m-%dT%H:%M:%S%z")
done HOST=$(hostname)
} KERNEL=$(uname -r)
run_with_sampling() { 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"
local name="$1"
local cmd="$2"
local csv="$3"
local max_seconds="$4"
log "Starting $name: $cmd" echo
echo "Run complete"
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" echo " stdout: $STDOUT_LOG"
echo " stderr: $STDERR_LOG"
local start_uptime pid echo " samples: $SAMPLE_LOG"
start_uptime=$(awk '{print $1}' /proc/uptime) 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"
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"