1package yamux
2
3import (
4	"io"
5	"io/ioutil"
6	"testing"
7)
8
9func BenchmarkPing(b *testing.B) {
10	client, server := testClientServer()
11	defer func() {
12		client.Close()
13		server.Close()
14	}()
15
16	b.ReportAllocs()
17	b.ResetTimer()
18
19	for i := 0; i < b.N; i++ {
20		rtt, err := client.Ping()
21		if err != nil {
22			b.Fatalf("err: %v", err)
23		}
24		if rtt == 0 {
25			b.Fatalf("bad: %v", rtt)
26		}
27	}
28}
29
30func BenchmarkAccept(b *testing.B) {
31	client, server := testClientServer()
32	defer func() {
33		client.Close()
34		server.Close()
35	}()
36
37	doneCh := make(chan struct{})
38	b.ReportAllocs()
39	b.ResetTimer()
40
41	go func() {
42		defer close(doneCh)
43
44		for i := 0; i < b.N; i++ {
45			stream, err := server.AcceptStream()
46			if err != nil {
47				return
48			}
49			stream.Close()
50		}
51	}()
52
53	for i := 0; i < b.N; i++ {
54		stream, err := client.Open()
55		if err != nil {
56			b.Fatalf("err: %v", err)
57		}
58		stream.Close()
59	}
60	<-doneCh
61}
62
63func BenchmarkSendRecv32(b *testing.B) {
64	const payloadSize = 32
65	benchmarkSendRecv(b, payloadSize, payloadSize)
66}
67
68func BenchmarkSendRecv64(b *testing.B) {
69	const payloadSize = 64
70	benchmarkSendRecv(b, payloadSize, payloadSize)
71}
72
73func BenchmarkSendRecv128(b *testing.B) {
74	const payloadSize = 128
75	benchmarkSendRecv(b, payloadSize, payloadSize)
76}
77
78func BenchmarkSendRecv256(b *testing.B) {
79	const payloadSize = 256
80	benchmarkSendRecv(b, payloadSize, payloadSize)
81}
82
83func BenchmarkSendRecv512(b *testing.B) {
84	const payloadSize = 512
85	benchmarkSendRecv(b, payloadSize, payloadSize)
86}
87
88func BenchmarkSendRecv1024(b *testing.B) {
89	const payloadSize = 1024
90	benchmarkSendRecv(b, payloadSize, payloadSize)
91}
92
93func BenchmarkSendRecv2048(b *testing.B) {
94	const payloadSize = 2048
95	benchmarkSendRecv(b, payloadSize, payloadSize)
96}
97
98func BenchmarkSendRecv4096(b *testing.B) {
99	const payloadSize = 4096
100	benchmarkSendRecv(b, payloadSize, payloadSize)
101}
102
103func BenchmarkSendRecvLarge(b *testing.B) {
104	const sendSize = 512 * 1024 * 1024 //512 MB
105	const recvSize = 4 * 1024          //4 KB
106	benchmarkSendRecv(b, sendSize, recvSize)
107}
108
109func benchmarkSendRecv(b *testing.B, sendSize, recvSize int) {
110	client, server := testClientServer()
111	defer func() {
112		client.Close()
113		server.Close()
114	}()
115
116	sendBuf := make([]byte, sendSize)
117	recvBuf := make([]byte, recvSize)
118	doneCh := make(chan struct{})
119
120	b.SetBytes(int64(sendSize))
121	b.ReportAllocs()
122	b.ResetTimer()
123
124	go func() {
125		defer close(doneCh)
126
127		stream, err := server.AcceptStream()
128		if err != nil {
129			return
130		}
131		defer stream.Close()
132
133		switch {
134		case sendSize == recvSize:
135			for i := 0; i < b.N; i++ {
136				if _, err := stream.Read(recvBuf); err != nil {
137					b.Fatalf("err: %v", err)
138				}
139			}
140
141		case recvSize > sendSize:
142			b.Fatalf("bad test case; recvSize was: %d and sendSize was: %d, but recvSize must be <= sendSize!", recvSize, sendSize)
143
144		default:
145			chunks := sendSize / recvSize
146			for i := 0; i < b.N; i++ {
147				for j := 0; j < chunks; j++ {
148					if _, err := stream.Read(recvBuf); err != nil {
149						b.Fatalf("err: %v", err)
150					}
151				}
152			}
153		}
154	}()
155
156	stream, err := client.Open()
157	if err != nil {
158		b.Fatalf("err: %v", err)
159	}
160	defer stream.Close()
161
162	for i := 0; i < b.N; i++ {
163		if _, err := stream.Write(sendBuf); err != nil {
164			b.Fatalf("err: %v", err)
165		}
166	}
167	<-doneCh
168}
169
170func BenchmarkSendRecvParallel32(b *testing.B) {
171	const payloadSize = 32
172	benchmarkSendRecvParallel(b, payloadSize)
173}
174
175func BenchmarkSendRecvParallel64(b *testing.B) {
176	const payloadSize = 64
177	benchmarkSendRecvParallel(b, payloadSize)
178}
179
180func BenchmarkSendRecvParallel128(b *testing.B) {
181	const payloadSize = 128
182	benchmarkSendRecvParallel(b, payloadSize)
183}
184
185func BenchmarkSendRecvParallel256(b *testing.B) {
186	const payloadSize = 256
187	benchmarkSendRecvParallel(b, payloadSize)
188}
189
190func BenchmarkSendRecvParallel512(b *testing.B) {
191	const payloadSize = 512
192	benchmarkSendRecvParallel(b, payloadSize)
193}
194
195func BenchmarkSendRecvParallel1024(b *testing.B) {
196	const payloadSize = 1024
197	benchmarkSendRecvParallel(b, payloadSize)
198}
199
200func BenchmarkSendRecvParallel2048(b *testing.B) {
201	const payloadSize = 2048
202	benchmarkSendRecvParallel(b, payloadSize)
203}
204
205func BenchmarkSendRecvParallel4096(b *testing.B) {
206	const payloadSize = 4096
207	benchmarkSendRecvParallel(b, payloadSize)
208}
209
210func benchmarkSendRecvParallel(b *testing.B, sendSize int) {
211	client, server := testClientServer()
212	defer func() {
213		client.Close()
214		server.Close()
215	}()
216
217	sendBuf := make([]byte, sendSize)
218	discarder := ioutil.Discard.(io.ReaderFrom)
219	b.SetBytes(int64(sendSize))
220	b.ReportAllocs()
221	b.ResetTimer()
222
223	b.RunParallel(func(pb *testing.PB) {
224		doneCh := make(chan struct{})
225
226		go func() {
227			defer close(doneCh)
228
229			stream, err := server.AcceptStream()
230			if err != nil {
231				return
232			}
233			defer stream.Close()
234
235			if _, err := discarder.ReadFrom(stream); err != nil {
236				b.Fatalf("err: %v", err)
237			}
238		}()
239
240		stream, err := client.Open()
241		if err != nil {
242			b.Fatalf("err: %v", err)
243		}
244
245		for pb.Next() {
246			if _, err := stream.Write(sendBuf); err != nil {
247				b.Fatalf("err: %v", err)
248			}
249		}
250
251		stream.Close()
252		<-doneCh
253	})
254}
255