v / bench / bench_closure.v
278 lines · 237 sloc · 7.72 KB · 2d87ac4837e319397a8e8a366fc9458a09a9ebf7
Raw
1module main
2
3import time
4import sync
5import os
6import runtime
7import v.util.version
8
9// Define closure type alias
10type ClosureFN = fn () int
11
12// Test closures with different capture sizes
13fn create_closure_small() ClosureFN {
14 a := 0
15 return fn [a] () int {
16 return a
17 }
18}
19
20fn create_closure_medium() ClosureFN {
21 a, b, c, d := 1, 2, 3, 4
22 return fn [a, b, c, d] () int {
23 return a + b - c * d
24 }
25}
26
27struct LargeData {
28 array [10]int
29}
30
31fn create_closure_large() ClosureFN {
32 data := LargeData{
33 array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]!
34 }
35 return fn [data] () int {
36 mut sum := 0
37 for i in 0 .. 10 {
38 sum += data.array[i]
39 }
40 return sum
41 }
42}
43
44// Result structs
45struct TestResult {
46 test_name string
47 iterations int
48 time_ms i64
49 ops_per_sec f64 // Operations per second
50 notes string
51}
52
53struct MemoryResult {
54 test_name string
55 count int
56 start_mem_kb int
57 end_mem_kb int
58 delta_kb int
59 bytes_per_closure int
60 check_sum int
61}
62
63// Benchmark group - returns result structs
64fn benchmark_closure_creation(iterations int) []TestResult {
65 mut results := []TestResult{}
66
67 // Test small closure creation
68 mut start := time.ticks()
69 for _ in 0 .. iterations {
70 _ = create_closure_small()
71 }
72 small_time := time.ticks() - start
73 mut ops_per_sec := f64(iterations) * 1000.0 / f64(small_time)
74 results << TestResult{'Small Closure Creation', iterations, small_time, ops_per_sec, ''}
75
76 // Test medium closure creation
77 start = time.ticks()
78 for _ in 0 .. iterations {
79 _ = create_closure_medium()
80 }
81 medium_time := time.ticks() - start
82 ops_per_sec = f64(iterations) * 1000.0 / f64(medium_time)
83 results << TestResult{'Medium Closure Creation', iterations, medium_time, ops_per_sec, ''}
84
85 // Test large closure creation
86 large_iter := iterations / 10
87 start = time.ticks()
88 for _ in 0 .. large_iter {
89 _ = create_closure_large()
90 }
91 large_time := time.ticks() - start
92 ops_per_sec = f64(large_iter) * 1000.0 / f64(large_time)
93 results << TestResult{'Large Closure Creation', large_iter, large_time, ops_per_sec, ''} //, "Equivalent iterations: ${iterations/10}"}
94 return results
95}
96
97fn benchmark_closure_call(iterations int) []TestResult {
98 mut results := []TestResult{}
99
100 closure_small := create_closure_small()
101 closure_medium := create_closure_medium()
102 closure_large := create_closure_large()
103
104 // Test small closure call
105 mut start := time.ticks()
106 for _ in 0 .. iterations {
107 _ = closure_small()
108 }
109 small_time := time.ticks() - start
110 mut ops_per_sec := f64(iterations) * 1000.0 / f64(small_time)
111 results << TestResult{'Small Closure Call', iterations, small_time, ops_per_sec, ''}
112
113 // Test medium closure call
114 start = time.ticks()
115 for _ in 0 .. iterations {
116 _ = closure_medium()
117 }
118 medium_time := time.ticks() - start
119 ops_per_sec = f64(iterations) * 1000.0 / f64(medium_time)
120 results << TestResult{'Medium Closure Call', iterations, medium_time, ops_per_sec, ''}
121
122 // Test large closure call
123 large_iter := iterations / 10
124 start = time.ticks()
125 for _ in 0 .. large_iter {
126 _ = closure_large()
127 }
128 large_time := time.ticks() - start
129 ops_per_sec = f64(large_iter) * 1000.0 / f64(large_time)
130 results << TestResult{'Large Closure Call', large_iter, large_time, ops_per_sec, ''}
131
132 return results
133}
134
135fn benchmark_threaded_creation(threads int, iterations_per_thread int) TestResult {
136 total_iterations := threads * iterations_per_thread
137
138 mut wg := sync.new_waitgroup()
139 wg.add(threads)
140
141 start := time.ticks()
142
143 for _ in 0 .. threads {
144 go fn [mut wg, iterations_per_thread] () {
145 defer { wg.done() }
146 for _ in 0 .. iterations_per_thread {
147 _ = create_closure_medium()
148 }
149 }()
150 }
151
152 wg.wait()
153 elapsed := time.ticks() - start
154 ops_per_sec := f64(total_iterations) * 1000.0 / f64(elapsed)
155
156 return TestResult{
157 test_name: 'Multi-threaded Creation'
158 iterations: total_iterations
159 time_ms: elapsed
160 ops_per_sec: ops_per_sec
161 notes: 'Threads: ${threads} Iterations per thread: ${iterations_per_thread}'
162 }
163}
164
165fn baseline_call_performance(iterations int) TestResult {
166 start := time.ticks()
167 for _ in 0 .. iterations {
168 _ = normal_function()
169 }
170 elapsed := time.ticks() - start
171 ops_per_sec := f64(iterations) * 1000.0 / f64(elapsed)
172
173 return TestResult{
174 test_name: 'Normal Function Call'
175 iterations: iterations
176 time_ms: elapsed
177 ops_per_sec: ops_per_sec
178 notes: 'Baseline'
179 }
180}
181
182fn benchmark_memory_usage(count int) MemoryResult {
183 mut closures := []ClosureFN{}
184 start_mem := runtime.used_memory() or { panic(err) }
185
186 for i in 0 .. count {
187 the_closure := create_closure_medium()
188 closures << the_closure
189
190 if i % 1000 == 0 {
191 _ = the_closure()
192 }
193 }
194
195 end_mem := runtime.used_memory() or { panic(err) }
196 delta := int(end_mem) - int(start_mem)
197 bytes_per_closure := delta / count
198
199 // Calculate verification sum
200 mut check_sum := 0
201 n := if closures.len < 100 { closures.len } else { 100 }
202 for idx in 0 .. n {
203 check_sum += closures[idx]()
204 }
205
206 return MemoryResult{
207 test_name: 'Closure Memory Overhead'
208 count: count
209 start_mem_kb: int(start_mem / 1024)
210 end_mem_kb: int(end_mem / 1024)
211 delta_kb: delta / 1024
212 bytes_per_closure: bytes_per_closure
213 check_sum: check_sum
214 }
215}
216
217fn normal_function() int {
218 return 42
219}
220
221// Format performance data for readability
222fn format_perf(ops_per_sec f64) string {
223 if ops_per_sec >= 1_000_000 {
224 return '${ops_per_sec / 1_000_000:5.2f} Mop/s'
225 } else if ops_per_sec >= 1_000 {
226 return '${ops_per_sec / 1_000:5.2f} Kop/s'
227 } else {
228 return '${ops_per_sec:5.2f} op/s'
229 }
230}
231
232fn print_results_table(results []TestResult, title string) {
233 println('|---------------------------|------------|----------|--------------|--------------|')
234 for res in results {
235 perf_str := format_perf(res.ops_per_sec)
236 println('| ${res.test_name:-25} | ${res.iterations:10} | ${res.time_ms:8} | ${perf_str:-12} | ${res.notes:-12} |')
237 }
238}
239
240fn main() {
241 println('# V Language Closure Performance Benchmark Report')
242
243 // Configurable test parameters
244 base_iter := 100_000_000 // 100 million iterations
245 creation_iter := 10_000_000 // 1 million iterations
246 mem_count := 100_000
247 threads := 8
248 thread_iter := 125_000
249
250 // Execute tests
251 baseline_result := baseline_call_performance(base_iter)
252 creation_results := benchmark_closure_creation(creation_iter)
253 call_results := benchmark_closure_call(base_iter)
254 thread_result := benchmark_threaded_creation(threads, thread_iter)
255 mem_result := benchmark_memory_usage(mem_count)
256
257 // Print result tables
258 println('\n## 1. Closure Performance Analysis')
259 println('| Test Name | Iterations | Time(ms) | Ops/sec | Notes |')
260 print_results_table([baseline_result], '1. Performance Baseline')
261 print_results_table(creation_results, '2. Closure Creation Performance')
262 print_results_table(call_results, '3. Closure Call Performance')
263 print_results_table([thread_result], '4. Multi-threaded Performance')
264
265 // Print memory results
266 println('\n## 2. Memory Overhead Analysis')
267 println('| Test Name | Closure Count | Start Mem(KB) | End Mem(KB) | Delta(KB) | Bytes/Closure |')
268 println('|-------------------------|---------------|---------------|------------|-----------|---------------|')
269 println('| ${mem_result.test_name:-20} | ${mem_result.count:13} | ${mem_result.start_mem_kb:13} | ${mem_result.end_mem_kb:10} | ${mem_result.delta_kb:9} | ${mem_result.bytes_per_closure:13} |')
270 println('\n**Verification Sum: ${mem_result.check_sum}** (Calculated from random sample of 100 closures)')
271
272 println('\n## Test Environment')
273 println('- V Language Version: ${version.full_v_version(false)}')
274 println('- CPU Cores: ${runtime.nr_cpus()}')
275 println('- System Memory: ${runtime.total_memory()! / 1024 / 1024} MB')
276 println('- Operating System: ${os.user_os()}')
277 println('\n> Test Time: ${time.now().format_ss_micro()}')
278}
279