LEFT | RIGHT |
1 // Copyright 2012 The Go Authors. All rights reserved. | 1 // Copyright 2012 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package net | 5 package net |
6 | 6 |
7 import ( | 7 import ( |
8 "fmt" | 8 "fmt" |
9 "io" | 9 "io" |
10 "reflect" | 10 "reflect" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 func BenchmarkTCP6PersistentTimeout(b *testing.B) { | 54 func BenchmarkTCP6PersistentTimeout(b *testing.B) { |
55 if !supportsIPv6 { | 55 if !supportsIPv6 { |
56 b.Skip("ipv6 is not supported") | 56 b.Skip("ipv6 is not supported") |
57 } | 57 } |
58 benchmarkTCP(b, true, true, "[::1]:0") | 58 benchmarkTCP(b, true, true, "[::1]:0") |
59 } | 59 } |
60 | 60 |
61 func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) { | 61 func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) { |
62 const msgLen = 512 | 62 const msgLen = 512 |
63 conns := b.N | 63 conns := b.N |
64 » numConcurrent := runtime.GOMAXPROCS(-1) * 16 | 64 » numConcurrent := runtime.GOMAXPROCS(-1) * 2 |
65 msgs := 1 | 65 msgs := 1 |
66 if persistent { | 66 if persistent { |
67 conns = numConcurrent | 67 conns = numConcurrent |
68 msgs = b.N / conns | 68 msgs = b.N / conns |
69 if msgs == 0 { | 69 if msgs == 0 { |
70 msgs = 1 | 70 msgs = 1 |
71 } | 71 } |
72 if conns > b.N { | 72 if conns > b.N { |
73 conns = b.N | 73 conns = b.N |
74 } | 74 } |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 break | 142 break |
143 } | 143 } |
144 } | 144 } |
145 }() | 145 }() |
146 } | 146 } |
147 for i := 0; i < cap(sem); i++ { | 147 for i := 0; i < cap(sem); i++ { |
148 sem <- true | 148 sem <- true |
149 } | 149 } |
150 } | 150 } |
151 | 151 |
| 152 func BenchmarkTCP4ConcurrentReadWrite(b *testing.B) { |
| 153 benchmarkTCPConcurrentReadWrite(b, "127.0.0.1:0") |
| 154 } |
| 155 |
| 156 func BenchmarkTCP6ConcurrentReadWrite(b *testing.B) { |
| 157 if !supportsIPv6 { |
| 158 b.Skip("ipv6 is not supported") |
| 159 } |
| 160 benchmarkTCPConcurrentReadWrite(b, "[::1]:0") |
| 161 } |
| 162 |
| 163 func benchmarkTCPConcurrentReadWrite(b *testing.B, laddr string) { |
| 164 // The benchmark creates GOMAXPROCS client/server pairs. |
| 165 // Each pair creates 4 goroutines: client reader/writer and server reade
r/writer. |
| 166 // The benchmark stresses concurrent reading and writing to the same con
nection. |
| 167 // Such pattern is used in net/http and net/rpc. |
| 168 |
| 169 b.StopTimer() |
| 170 |
| 171 P := runtime.GOMAXPROCS(0) |
| 172 N := b.N / P |
| 173 W := 1000 |
| 174 |
| 175 // Setup P client/server connections. |
| 176 clients := make([]Conn, P) |
| 177 servers := make([]Conn, P) |
| 178 ln, err := Listen("tcp", laddr) |
| 179 if err != nil { |
| 180 b.Fatalf("Listen failed: %v", err) |
| 181 } |
| 182 defer ln.Close() |
| 183 done := make(chan bool) |
| 184 go func() { |
| 185 for p := 0; p < P; p++ { |
| 186 s, err := ln.Accept() |
| 187 if err != nil { |
| 188 b.Fatalf("Accept failed: %v", err) |
| 189 } |
| 190 servers[p] = s |
| 191 } |
| 192 done <- true |
| 193 }() |
| 194 for p := 0; p < P; p++ { |
| 195 c, err := Dial("tcp", ln.Addr().String()) |
| 196 if err != nil { |
| 197 b.Fatalf("Dial failed: %v", err) |
| 198 } |
| 199 clients[p] = c |
| 200 } |
| 201 <-done |
| 202 |
| 203 b.StartTimer() |
| 204 |
| 205 var wg sync.WaitGroup |
| 206 wg.Add(4 * P) |
| 207 for p := 0; p < P; p++ { |
| 208 // Client writer. |
| 209 go func(c Conn) { |
| 210 defer wg.Done() |
| 211 var buf [1]byte |
| 212 for i := 0; i < N; i++ { |
| 213 v := byte(i) |
| 214 for w := 0; w < W; w++ { |
| 215 v *= v |
| 216 } |
| 217 buf[0] = v |
| 218 _, err := c.Write(buf[:]) |
| 219 if err != nil { |
| 220 b.Fatalf("Write failed: %v", err) |
| 221 } |
| 222 } |
| 223 }(clients[p]) |
| 224 |
| 225 // Pipe between server reader and server writer. |
| 226 pipe := make(chan byte, 128) |
| 227 |
| 228 // Server reader. |
| 229 go func(s Conn) { |
| 230 defer wg.Done() |
| 231 var buf [1]byte |
| 232 for i := 0; i < N; i++ { |
| 233 _, err := s.Read(buf[:]) |
| 234 if err != nil { |
| 235 b.Fatalf("Read failed: %v", err) |
| 236 } |
| 237 pipe <- buf[0] |
| 238 } |
| 239 }(servers[p]) |
| 240 |
| 241 // Server writer. |
| 242 go func(s Conn) { |
| 243 defer wg.Done() |
| 244 var buf [1]byte |
| 245 for i := 0; i < N; i++ { |
| 246 v := <-pipe |
| 247 for w := 0; w < W; w++ { |
| 248 v *= v |
| 249 } |
| 250 buf[0] = v |
| 251 _, err := s.Write(buf[:]) |
| 252 if err != nil { |
| 253 b.Fatalf("Write failed: %v", err) |
| 254 } |
| 255 } |
| 256 s.Close() |
| 257 }(servers[p]) |
| 258 |
| 259 // Client reader. |
| 260 go func(c Conn) { |
| 261 defer wg.Done() |
| 262 var buf [1]byte |
| 263 for i := 0; i < N; i++ { |
| 264 _, err := c.Read(buf[:]) |
| 265 if err != nil { |
| 266 b.Fatalf("Read failed: %v", err) |
| 267 } |
| 268 } |
| 269 c.Close() |
| 270 }(clients[p]) |
| 271 } |
| 272 wg.Wait() |
| 273 } |
| 274 |
152 type resolveTCPAddrTest struct { | 275 type resolveTCPAddrTest struct { |
153 net string | 276 net string |
154 litAddr string | 277 litAddr string |
155 addr *TCPAddr | 278 addr *TCPAddr |
156 err error | 279 err error |
157 } | 280 } |
158 | 281 |
159 var resolveTCPAddrTests = []resolveTCPAddrTest{ | 282 var resolveTCPAddrTests = []resolveTCPAddrTest{ |
160 {"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, | 283 {"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, |
161 {"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535
}, nil}, | 284 {"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535
}, nil}, |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 if err != nil { | 446 if err != nil { |
324 t.Fatalf("Dial failed: %v", err) | 447 t.Fatalf("Dial failed: %v", err) |
325 } | 448 } |
326 c.Close() | 449 c.Close() |
327 } | 450 } |
328 ln.Close() | 451 ln.Close() |
329 wg.Wait() | 452 wg.Wait() |
330 } | 453 } |
331 | 454 |
332 func TestTCPReadWriteMallocs(t *testing.T) { | 455 func TestTCPReadWriteMallocs(t *testing.T) { |
| 456 maxMallocs := 10000 |
| 457 switch runtime.GOOS { |
| 458 // Add other OSes if you know how many mallocs they do. |
| 459 case "windows": |
| 460 maxMallocs = 0 |
| 461 } |
333 ln, err := Listen("tcp", "127.0.0.1:0") | 462 ln, err := Listen("tcp", "127.0.0.1:0") |
334 if err != nil { | 463 if err != nil { |
335 t.Fatalf("Listen failed: %v", err) | 464 t.Fatalf("Listen failed: %v", err) |
336 } | 465 } |
337 defer ln.Close() | 466 defer ln.Close() |
338 var server Conn | 467 var server Conn |
339 errc := make(chan error) | 468 errc := make(chan error) |
340 go func() { | 469 go func() { |
341 var err error | 470 var err error |
342 server, err = ln.Accept() | 471 server, err = ln.Accept() |
(...skipping 11 matching lines...) Expand all Loading... |
354 mallocs := testing.AllocsPerRun(1000, func() { | 483 mallocs := testing.AllocsPerRun(1000, func() { |
355 _, err := server.Write(buf[:]) | 484 _, err := server.Write(buf[:]) |
356 if err != nil { | 485 if err != nil { |
357 t.Fatalf("Write failed: %v", err) | 486 t.Fatalf("Write failed: %v", err) |
358 } | 487 } |
359 _, err = io.ReadFull(client, buf[:]) | 488 _, err = io.ReadFull(client, buf[:]) |
360 if err != nil { | 489 if err != nil { |
361 t.Fatalf("Read failed: %v", err) | 490 t.Fatalf("Read failed: %v", err) |
362 } | 491 } |
363 }) | 492 }) |
364 » if mallocs > 0 { | 493 » if int(mallocs) > maxMallocs { |
365 » » t.Fatalf("Got %v allocs, want %v", mallocs, 0) | 494 » » t.Fatalf("Got %v allocs, want %v", mallocs, maxMallocs) |
366 » } | 495 » } |
367 } | 496 } |
LEFT | RIGHT |