v / vlib / goroutines / examples / spawn_benchmark.v
124 lines · 96 sloc · 2.78 KB · e21acca549c0df34c98beb389088dbf7cee4c4d0
Raw
1// V spawn (OS threads) benchmark – for comparison with Go goroutines.
2//
3// Uses V's built-in `spawn` (OS threads) and `chan` (V1 channels).
4// This measures V's current threading primitives vs Go's goroutines.
5//
6// Run: v -prod run spawn_benchmark.v
7module main
8
9import time
10
11// ---------------------------------------------------------------------------
12// Benchmark 1 – fan-out / fan-in
13// ---------------------------------------------------------------------------
14
15fn fan_worker(c chan int) {
16 c <- 1
17}
18
19fn bench_fan_out_fan_in(n int) {
20 c := chan int{cap: n}
21
22 sw := time.new_stopwatch()
23
24 for _ in 0 .. n {
25 spawn fan_worker(c)
26 }
27
28 for _ in 0 .. n {
29 _ = <-c
30 }
31
32 elapsed := sw.elapsed()
33 us := elapsed.microseconds()
34 ns_per := elapsed.nanoseconds() / n
35 println('fan-out/fan-in ${n} threads: ${us} us (${ns_per} ns/thread)')
36}
37
38// ---------------------------------------------------------------------------
39// Benchmark 2 – channel ping-pong
40// ---------------------------------------------------------------------------
41
42fn pinger(c1 chan int, c2 chan int, n int) {
43 mut val := 0
44 for _ in 0 .. n {
45 val = <-c1
46 val++
47 c2 <- val
48 }
49}
50
51fn bench_ping_pong(n int) {
52 c1 := chan int{cap: 1}
53 c2 := chan int{cap: 1}
54
55 spawn pinger(c1, c2, n)
56
57 sw := time.new_stopwatch()
58
59 mut val := 0
60 for _ in 0 .. n {
61 c1 <- val
62 val = <-c2
63 }
64
65 elapsed := sw.elapsed()
66 us := elapsed.microseconds()
67 ns_per := elapsed.nanoseconds() / n
68 println('ping-pong ${n} round-trips: ${us} us (${ns_per} ns/round-trip)')
69}
70
71// ---------------------------------------------------------------------------
72// Benchmark 3 – contended channel (many producers, one consumer)
73// ---------------------------------------------------------------------------
74
75fn producer(c chan int, count int) {
76 mut val := 0
77 for _ in 0 .. count {
78 val++
79 c <- val
80 }
81}
82
83fn bench_contended_channel(num_producers int, msgs_per_producer int) {
84 total := num_producers * msgs_per_producer
85 c := chan int{cap: 64}
86
87 sw := time.new_stopwatch()
88
89 for _ in 0 .. num_producers {
90 spawn producer(c, msgs_per_producer)
91 }
92
93 for _ in 0 .. total {
94 _ = <-c
95 }
96
97 elapsed := sw.elapsed()
98 us := elapsed.microseconds()
99 ns_per := elapsed.nanoseconds() / total
100 println('contended chan ${num_producers} producers x ${msgs_per_producer} msgs: ${us} us (${ns_per} ns/msg)')
101}
102
103// ---------------------------------------------------------------------------
104// Main
105// ---------------------------------------------------------------------------
106
107fn main() {
108 println('=== V spawn (OS threads) Benchmark ===')
109 println('')
110
111 bench_fan_out_fan_in(1000)
112 bench_fan_out_fan_in(10000)
113 // Skip 100k - too many OS threads
114
115 println('')
116 bench_ping_pong(10000)
117 bench_ping_pong(100000)
118
119 println('')
120 bench_contended_channel(10, 1000)
121 bench_contended_channel(100, 1000)
122
123 println('')
124}
125