brewery
notashelf /
66c0d5bb99879c2c1d813ae5b84ccb817b9690b6

nixir

public

Import-resolving Nix IR plugin

Star0tarball
clone
ssh://git@git.notashelf.dev:33/notashelf/nixir.git
tests/benchmark/run.shBash158 lines4.6 KB
1
#!/usr/bin/env bash
2
set -e
3
4
echo "# Running benchmarks..."
5
echo ""
6
7
BENCH_DIR="$(pwd)/tests/benchmark"
8
IRC_BIN="$(pwd)/build/nix-irc"
9
10
GREEN='\033[0;32m'
11
BLUE='\033[0;34m'
12
YELLOW='\033[0;33m'
13
NC='\033[0m'
14
15
get_ms() {
16
	local time_str="$1"
17
	if [[ $time_str =~ ([0-9]+)m([0-9.]+)s ]]; then
18
		local mins="${BASH_REMATCH[1]}"
19
		local secs="${BASH_REMATCH[2]}"
20
		local ms
21
		ms=$(awk "BEGIN {printf \"%.1f\", ($mins * 60000) + ($secs * 1000)}")
22
		echo "$ms"
23
	else
24
		echo "0"
25
	fi
26
}
27
28
run_benchmark() {
29
	local name="$1"
30
	local file="$2"
31
32
	echo -e "${BLUE}=== $name ===${NC}"
33
	echo ""
34
35
	# Measure compilation time only
36
	echo -n "  Compilation only:     "
37
	local compile_start
38
	compile_start=$(date +%s%N)
39
	"$IRC_BIN" "$file" /tmp/bench.nixir >/dev/null 2>&1
40
	local compile_end
41
	compile_end=$(date +%s%N)
42
	local compile_ms=$(((compile_end - compile_start) / 1000000))
43
	echo -e "${YELLOW}${compile_ms}ms${NC}"
44
45
	# Measure IR loading only (deserialization + evaluation)
46
	echo -n "  IR load only:         "
47
	PLUGIN_PATH="$(pwd)/build/nix-ir-plugin.so"
48
	if [ ! -f "$PLUGIN_PATH" ]; then
49
		echo -e "${YELLOW}skipped${NC} (plugin not built)"
50
	else
51
		# Pre-compile the IR
52
		"$IRC_BIN" "$file" /tmp/bench.nixir >/dev/null 2>&1
53
54
		# Measure just the loading (average of 10 runs to reduce noise)
55
		local total_load_us=0
56
		for _ in {1..10}; do
57
			local load_output
58
			load_output=$(nix-instantiate --plugin-files "$PLUGIN_PATH" --eval --expr "builtins.nixIR_loadIR \"/tmp/bench.nixir\"" 2>&1 >/dev/null | grep "nixIR timing" | grep -oP 'total=\K[0-9]+')
59
			total_load_us=$((total_load_us + load_output))
60
		done
61
		local avg_load_us=$((total_load_us / 10))
62
		local avg_load_ms_frac=$(awk "BEGIN {printf \"%.3f\", $avg_load_us / 1000}")
63
		echo -e "${GREEN}${avg_load_ms_frac}ms${NC} avg (10 runs)"
64
	fi
65
66
	# Measure full pipeline (compile + nix-instantiate overhead + IR load)
67
	echo -n "  Full pipeline:        "
68
	if [ ! -f "$PLUGIN_PATH" ]; then
69
		echo -e "${YELLOW}skipped${NC}"
70
	else
71
		local pipeline_start
72
		pipeline_start=$(date +%s%N)
73
		"$IRC_BIN" "$file" /tmp/bench.nixir >/dev/null 2>&1
74
		nix-instantiate --plugin-files "$PLUGIN_PATH" --eval --expr "builtins.nixIR_loadIR \"/tmp/bench.nixir\"" >/dev/null 2>&1
75
		local pipeline_end
76
		pipeline_end=$(date +%s%N)
77
		local pipeline_ms=$(((pipeline_end - pipeline_start) / 1000000))
78
		echo -e "${YELLOW}${pipeline_ms}ms${NC}"
79
	fi
80
81
	# Source and IR sizes
82
	local src_size
83
	src_size=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null)
84
	local ir_size
85
	ir_size=$(stat -c%s /tmp/bench.nixir 2>/dev/null || stat -f%z /tmp/bench.nixir 2>/dev/null)
86
	local ratio=0
87
	if [[ "$src_size" -gt 0 ]]; then
88
		ratio=$((ir_size * 100 / src_size))
89
	fi
90
	echo -e "  Source size:          ${src_size}B"
91
	echo -e "  IR bundle size:       ${ir_size}B (${ratio}% of source)"
92
93
	echo ""
94
95
	# Native Nix evaluation (baseline)
96
	echo -n "  Native Nix eval:      "
97
	local native_total=0
98
	for _ in {1..5}; do
99
		local t
100
		t=$( (time nix-instantiate --eval --strict "$file" >/dev/null 2>&1) 2>&1 | grep "real" | awk '{print $2}')
101
		local ms
102
		ms=$(get_ms "$t")
103
		native_total=$(awk "BEGIN {print $native_total + $ms}")
104
	done
105
	local native_avg
106
	native_avg=$(awk "BEGIN {printf \"%.1f\", $native_total / 5}")
107
	echo -e "${GREEN}${native_avg}ms${NC} avg (5 runs)"
108
109
	echo ""
110
}
111
112
echo "Measuring IR compilation speed and bundle size characteristics."
113
echo ""
114
115
run_benchmark "Simple Expression" "$BENCH_DIR/simple.nix"
116
run_benchmark "Medium Complexity" "$BENCH_DIR/medium.nix"
117
run_benchmark "Large Expression" "$BENCH_DIR/large.nix"
118
119
# Overall statistics
120
echo -e "${BLUE}=== Overall Statistics ===${NC}"
121
echo ""
122
123
testdir=$(mktemp -d)
124
total_nix=0
125
total_ir=0
126
total_compile_time=0
127
128
for f in "$BENCH_DIR"/*.nix; do
129
	nixsize=$(stat -c%s "$f" 2>/dev/null || stat -f%z "$f" 2>/dev/null)
130
	base=$(basename "$f" .nix)
131
	irfile="${testdir}/${base}.nixir"
132
133
	start=$(date +%s%N)
134
	"$IRC_BIN" "$f" "$irfile" >/dev/null 2>&1
135
	end=$(date +%s%N)
136
	compile_time=$(((end - start) / 1000000))
137
138
	if [ -f "$irfile" ]; then
139
		irsize=$(stat -c%s "$irfile" 2>/dev/null || stat -f%z "$irfile" 2>/dev/null)
140
		total_nix=$((total_nix + nixsize))
141
		total_ir=$((total_ir + irsize))
142
		total_compile_time=$((total_compile_time + compile_time))
143
	fi
144
done
145
146
total_ratio=$((total_ir * 100 / total_nix))
147
avg_compile_time=$((total_compile_time / 3))
148
149
# TBH those are entirely unnecessary. However, I'm a sucker for data
150
# and those are trivial to compile. Might as well. Who knows, maybe it'll
151
# come in handy in the future.
152
echo "  Total source size:     ${total_nix}B"
153
echo "  Total IR size:         ${total_ir}B"
154
echo "  Compression ratio:     ${total_ratio}% of source"
155
echo "  Average compile time:  ${avg_compile_time}ms"
156
echo ""
157
158
rm -rf "$testdir"