brewery
notashelf /
54892c3121d4fd98ef6b96dacdbe015923bc4394

nixir

public

Import-resolving Nix IR plugin

Star0tarball
clone
ssh://git@git.notashelf.dev:33/notashelf/nixir.git
tests/benchmark/run.shBash155 lines4.5 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=$((ir_size * 100 / src_size))
87
	echo -e "  Source size:          ${src_size}B"
88
	echo -e "  IR bundle size:       ${ir_size}B (${ratio}% of source)"
89
90
	echo ""
91
92
	# Native Nix evaluation (baseline)
93
	echo -n "  Native Nix eval:      "
94
	local native_total=0
95
	for _ in {1..5}; do
96
		local t
97
		t=$( (time nix-instantiate --eval --strict "$file" >/dev/null 2>&1) 2>&1 | grep "real" | awk '{print $2}')
98
		local ms
99
		ms=$(get_ms "$t")
100
		native_total=$(awk "BEGIN {print $native_total + $ms}")
101
	done
102
	local native_avg
103
	native_avg=$(awk "BEGIN {printf \"%.1f\", $native_total / 5}")
104
	echo -e "${GREEN}${native_avg}ms${NC} avg (5 runs)"
105
106
	echo ""
107
}
108
109
echo "Measuring IR compilation speed and bundle size characteristics."
110
echo ""
111
112
run_benchmark "Simple Expression" "$BENCH_DIR/simple.nix"
113
run_benchmark "Medium Complexity" "$BENCH_DIR/medium.nix"
114
run_benchmark "Large Expression" "$BENCH_DIR/large.nix"
115
116
# Overall statistics
117
echo -e "${BLUE}=== Overall Statistics ===${NC}"
118
echo ""
119
120
testdir=$(mktemp -d)
121
total_nix=0
122
total_ir=0
123
total_compile_time=0
124
125
for f in "$BENCH_DIR"/*.nix; do
126
	nixsize=$(stat -c%s "$f" 2>/dev/null || stat -f%z "$f" 2>/dev/null)
127
	base=$(basename "$f" .nix)
128
	irfile="${testdir}/${base}.nixir"
129
130
	start=$(date +%s%N)
131
	"$IRC_BIN" "$f" "$irfile" >/dev/null 2>&1
132
	end=$(date +%s%N)
133
	compile_time=$(((end - start) / 1000000))
134
135
	if [ -f "$irfile" ]; then
136
		irsize=$(stat -c%s "$irfile" 2>/dev/null || stat -f%z "$irfile" 2>/dev/null)
137
		total_nix=$((total_nix + nixsize))
138
		total_ir=$((total_ir + irsize))
139
		total_compile_time=$((total_compile_time + compile_time))
140
	fi
141
done
142
143
total_ratio=$((total_ir * 100 / total_nix))
144
avg_compile_time=$((total_compile_time / 3))
145
146
# TBH those are entirely unnecessary. However, I'm a sucker for data
147
# and those are trivial to compile. Might as well. Who knows, maybe it'll
148
# come in handy in the future.
149
echo "  Total source size:     ${total_nix}B"
150
echo "  Total IR size:         ${total_ir}B"
151
echo "  Compression ratio:     ${total_ratio}% of source"
152
echo "  Average compile time:  ${avg_compile_time}ms"
153
echo ""
154
155
rm -rf "$testdir"