Skip to content

Commit fb3bf51

Browse files
committed
WIP: profiling for ns_per_call
1 parent 1f9c6a8 commit fb3bf51

24 files changed

+750
-7
lines changed

Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ DTC ?= dtc
7777
E :=
7878
S := $E $E
7979

80+
LDFLAGS := -pg
81+
8082
SMP ?= 1
8183
CFLAGS += -D SEMU_BOOT_TARGET_TIME=10
8284
.PHONY: riscv-harts.dtsi

analyze.sh

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#!/usr/bin/env bash
2+
#
3+
# parse_results.sh:
4+
# Parse "emulator_SMP_{N}.log" and "gprof_SMP_{N}.log" for each N=1..32
5+
# to extract:
6+
# - predict_sec
7+
# - real_boot_time
8+
# - times (calls)
9+
# - semu_timer_clocksource percentage
10+
# - ns_per_call
11+
# - real_ns_per_call (calculated)
12+
# - scale_factor
13+
#
14+
# Output a summary line for each SMP=N in tab-delimited format.
15+
16+
LOGDIR="logs" # or wherever your logs are
17+
OUTFILE="results_summary.txt"
18+
19+
echo -e "SMP\treal_boot_time\ttimes\t\tns_per_call\tpredict_sec\tscale_factor\tpercentage\treal_ns_per_call" > "$OUTFILE"
20+
21+
for N in $(seq 1 32); do
22+
EMU_LOG="$LOGDIR/emulator_SMP_${N}.log"
23+
GPROF_LOG="$LOGDIR/gprof_SMP_${N}.log"
24+
25+
# Check that the files exist
26+
if [[ ! -f "$EMU_LOG" ]]; then
27+
echo "Warning: $EMU_LOG not found, skipping"
28+
continue
29+
fi
30+
if [[ ! -f "$GPROF_LOG" ]]; then
31+
echo "Warning: $GPROF_LOG not found, skipping"
32+
continue
33+
fi
34+
35+
# Initialize variables we want to parse
36+
predict_sec=""
37+
real_boot_time=""
38+
times_called=""
39+
ns_per_call=""
40+
scale_factor=""
41+
percentage=""
42+
real_ns_per_call=""
43+
44+
# 1) Parse from emulator_SMP_{N}.log:
45+
# We look for lines:
46+
# "[SEMU LOG]: Boot time: 7.82979 seconds, called 233068043 times semu_timer_clocksource"
47+
# next line: "ns_per_call = 5.10756, predict_sec = 10.21511, scale_factor = 0.97894"
48+
# We can do it with grep + sed or awk or a while-read approach
49+
50+
# Extract the "Boot time" line
51+
# e.g. "Boot time: 7.82979 seconds, called 233068043 times semu_timer_clocksource"
52+
# We'll parse the "7.82979" as real_boot_time, "233068043" as times_called
53+
line_boot_time="$(grep -Eo '\[SEMU LOG\]: Boot time: [^,]*, called [^ ]* times semu_timerclocksource.*' "$EMU_LOG")"
54+
# Alternatively you might want a simpler approach:
55+
# Let's do a grep for "Boot time:" and read the line with everything
56+
if [[ -z "$line_boot_time" ]]; then
57+
# Possibly there's an ANSI color code. Let's remove them with sed
58+
line_boot_time="$(grep 'Boot time:' "$EMU_LOG" | sed 's/\x1b\[[0-9;]*m//g')"
59+
fi
60+
61+
# Now parse it. Example format:
62+
# Boot time: 7.82979 seconds, called 233068043 times semu_timer_clocksource
63+
# We can use sed or awk:
64+
if [[ -n "$line_boot_time" ]]; then
65+
# Remove ANSI codes again if needed:
66+
no_ansi="$(echo "$line_boot_time" | sed 's/\x1b\[[0-9;]*m//g')"
67+
# Extract e.g. 7.82979 and 233068043
68+
real_boot_time="$(echo "$no_ansi" | sed -E 's/.*Boot time: ([0-9.]+) seconds, called ([0-9]+) times.*/\1/')"
69+
times_called="$(echo "$no_ansi" | sed -E 's/.*Boot time: ([0-9.]+) seconds, called ([0-9]+) times.*/\2/')"
70+
fi
71+
72+
# Next line with "ns_per_call = 5.10756, predict_sec = 10.21511, scale_factor = 0.97894"
73+
# We'll grep and parse similarly
74+
line_ns_call="$(grep -Eo 'ns_per_call = [^,]*, predict_sec = [^,]*, scale_factor = [^ ]*' "$EMU_LOG" | sed 's/\x1b\[[0-9;]*m//g')"
75+
if [[ -n "$line_ns_call" ]]; then
76+
# Example: "ns_per_call = 5.10756, predict_sec = 10.21511, scale_factor = 0.97894"
77+
ns_per_call="$(echo "$line_ns_call" | sed -E 's/.*ns_per_call = ([0-9.]+), predict_sec = ([0-9.]+), scale_factor = ([0-9.]+)/\1/')"
78+
predict_sec="$(echo "$line_ns_call" | sed -E 's/.*ns_per_call = ([0-9.]+), predict_sec = ([0-9.]+), scale_factor = ([0-9.]+)/\2/')"
79+
scale_factor="$(echo "$line_ns_call" | sed -E 's/.*ns_per_call = ([0-9.]+), predict_sec = ([0-9.]+), scale_factor = ([0-9.]+)/\3/')"
80+
fi
81+
82+
# 2) From gprof_SMP_{N}.log:
83+
# We search for the line that includes "semu_timer_clocksource" in the "Flat profile:" section
84+
# Example: "47.74 3.07 3.07 ... semu_timer_clocksource"
85+
# We'll parse the first field as the percentage
86+
# We'll do something like:
87+
line_gprof="$(grep -E '[0-9]+\.[0-9]+[[:space:]]+[0-9]+\.[0-9]+[[:space:]]+[0-9]+\.[0-9]+.*semu_timer_clocksource' "$GPROF_LOG")"
88+
# fallback if the spacing is different, or just search for 'semu_timer_clocksource'
89+
if [[ -z "$line_gprof" ]]; then
90+
line_gprof="$(grep 'semu_timer_clocksource' "$GPROF_LOG")"
91+
fi
92+
93+
# e.g.: " 47.74 3.07 3.07 semu_timer_clocksource"
94+
# The first column is 47.74. We'll parse that:
95+
if [[ -n "$line_gprof" ]]; then
96+
# remove leading spaces
97+
no_space="$(echo "$line_gprof" | sed 's/^[[:space:]]*//')"
98+
# e.g. "47.74 3.07 ...
99+
# let's cut by spaces
100+
percentage="$(echo "$no_space" | awk '{print $1}')"
101+
fi
102+
103+
# 3) Compute real_ns_per_call
104+
# real_ns_per_call = real_boot_time * (percentage/100) * 1e9 / times_called
105+
# Check if the fields are not empty
106+
if [[ -n "$real_boot_time" && -n "$percentage" && -n "$times_called" ]]; then
107+
real_ns_per_call="$(awk -v rbt="$real_boot_time" -v pct="$percentage" -v calls="$times_called" '
108+
BEGIN {
109+
# real_boot_time * (percentage/100) * 1e9 / times
110+
if (calls == 0) {
111+
print 0
112+
} else {
113+
val = rbt * (pct/100.0) * 1e9 / calls
114+
printf("%.5f", val)
115+
}
116+
}')"
117+
fi
118+
119+
# 4) Print in tab-delimited format
120+
echo -e "${N}\t${real_boot_time}\t${times_called}\t${ns_per_call}\t${predict_sec}\t${scale_factor}\t${percentage}\t${real_ns_per_call}" >> "$OUTFILE"
121+
122+
done
123+
124+
echo "Data parsed and saved to $OUTFILE."

auto_test.sh

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env bash
2+
3+
# Create a directory to store logs (optional)
4+
mkdir -p logs
5+
6+
for N in $(seq 1 32); do
7+
echo "============================================="
8+
echo "Starting experiment with SMP=$N"
9+
echo "============================================="
10+
11+
# 2) Build and run checks with SMP=N, capturing emulator output
12+
# The 'tee' command copies output to the terminal AND a log file
13+
echo "Building and running 'make check SMP=$N'..."
14+
make check SMP=$N 2>&1 | tee "logs/emulator_SMP_${N}.log"
15+
16+
# 3) After the emulator run, record gprof output
17+
# We assume 'gprof ./semu' uses data from 'gmon.out'
18+
echo "Running gprof for SMP=$N..."
19+
gprof ./semu > "logs/gprof_SMP_${N}.log" 2>&1
20+
21+
echo "Done with SMP=$N. Logs saved:"
22+
echo " - logs/emulator_SMP_${N}.log"
23+
echo " - logs/gprof_SMP_${N}.log"
24+
echo
25+
done
26+
27+
echo "All experiments complete!"

mac_analyze.sh

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/usr/bin/env bash
2+
#
3+
# parse_results_macos.sh
4+
#
5+
# Parses log files of the form: emulator_SMP_{N}.log
6+
# Each log ends with lines like:
7+
# [SEMU LOG]: Real boot time: 43.63820 seconds, called 220128512 times semu_timer_clocksource
8+
# [SEMU LOG]: ns_per_call = 4.46425, predict_sec = 8.92851, scale_factor = 1.12001
9+
#
10+
# We output a table with columns:
11+
# 1) SMP
12+
# 2) real_boot_time
13+
# 3) times_called
14+
# 4) ns_per_call
15+
# 5) predict_sec
16+
# 6) scale_factor
17+
#
18+
# We do not parse total_clocksource_ns or percentage, as they do not appear in this log snippet.
19+
20+
LOGDIR="mac_log" # Directory containing emulator_SMP_{N}.log
21+
OUTFILE="results_summary.txt"
22+
23+
# Print a header:
24+
echo -e "SMP\treal_boot_time\ttimes\t\tns_per_call\tpredict_sec\tscale_factor" > "$OUTFILE"
25+
26+
# Iterate from SMP=1..32 (adjust if needed)
27+
for N in $(seq 1 32); do
28+
FILE="$LOGDIR/emulator_SMP_${N}.log"
29+
30+
if [[ ! -f "$FILE" ]]; then
31+
echo "Skipping N=$N, file not found: $FILE"
32+
continue
33+
fi
34+
35+
# Initialize variables
36+
real_boot_time=""
37+
times_called=""
38+
ns_per_call=""
39+
predict_sec=""
40+
scale_factor=""
41+
42+
# 1) Parse the "Real boot time" line:
43+
# Example:
44+
# [SEMU LOG]: Real boot time: 43.63820 seconds, called 220128512 times semu_timer_clocksource
45+
line_boot="$(grep 'Real boot time:' "$FILE")"
46+
if [[ -n "$line_boot" ]]; then
47+
# Remove ANSI color codes, if any
48+
line_no_ansi="$(echo "$line_boot" | sed 's/\x1b\[[0-9;]*m//g')"
49+
# e.g. "[SEMU LOG]: Real boot time: 43.63820 seconds, called 220128512 times semu_timer_clocksource"
50+
# We'll extract:
51+
# real_boot_time = 43.63820
52+
# times = 220128512
53+
real_boot_time="$(echo "$line_no_ansi" | sed -E 's/.*Real boot time: ([0-9.]+) seconds, called ([0-9]+) .*/\1/')"
54+
times_called="$(echo "$line_no_ansi" | sed -E 's/.*Real boot time: ([0-9.]+) seconds, called ([0-9]+) .*/\2/')"
55+
fi
56+
57+
# 2) Parse the "ns_per_call" line:
58+
# Example:
59+
# [SEMU LOG]: ns_per_call = 4.46425, predict_sec = 8.92851, scale_factor = 1.12001
60+
line_ns="$(grep 'ns_per_call =' "$FILE")"
61+
if [[ -n "$line_ns" ]]; then
62+
# Also remove ANSI codes
63+
ns_no_ansi="$(echo "$line_ns" | sed 's/\x1b\[[0-9;]*m//g')"
64+
# e.g. "ns_per_call = 4.46425, predict_sec = 8.92851, scale_factor = 1.12001"
65+
# We'll extract them
66+
ns_per_call="$(echo "$ns_no_ansi" | sed -E 's/.*ns_per_call = ([0-9.]+).*/\1/')"
67+
predict_sec="$(echo "$ns_no_ansi" | sed -E 's/.*predict_sec = ([0-9.]+).*/\1/')"
68+
scale_factor="$(echo "$ns_no_ansi" | sed -E 's/.*scale_factor = ([0-9.]+).*/\1/')"
69+
fi
70+
71+
# 3) Print a line with the data
72+
echo -e "${N}\t${real_boot_time}\t${times_called}\t${ns_per_call}\t${predict_sec}\t${scale_factor}" >> "$OUTFILE"
73+
done
74+
75+
echo "Done. Results saved to ${OUTFILE}."

main.c

+10
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,17 @@ static int semu_start(int argc, char **argv)
677677
return 0;
678678
}
679679

680+
#include <time.h>
681+
#ifdef CLOCK_MONOTONIC_COARSE
682+
#define CLOCKID CLOCK_MONOTONIC_COARSE
683+
#else
684+
#define CLOCKID CLOCK_REALTIME_COARSE
685+
#endif
686+
687+
extern struct timespec boot_begin;
688+
680689
int main(int argc, char **argv)
681690
{
691+
clock_gettime(CLOCK_REALTIME, &boot_begin);
682692
return semu_start(argc, argv);
683693
}

statistic/README

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
1: 13th Gen Intel(R) Core(TM) i7-13700
2+
2: Intel(R) Xeon(R) CPU E5-2640 v4 @ 2.40GHz
3+
3: Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz
4+
4: arm (ThunderX2-99xx)
5+
5: mag

statistic/boot time difference.png

93.1 KB
Loading

0 commit comments

Comments
 (0)