get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/test/bench_test.go (about) 1 // Copyright 2012-2020 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 // Please note that these tests will stress a system and they need generous 15 // amounts of CPU, Memory and network sockets. Make sure the 'open files' 16 // setting for your platform is at least 8192. On linux and MacOSX you can 17 // do this via 'ulimit -n 8192' 18 // 19 20 package test 21 22 import ( 23 "bufio" 24 "fmt" 25 "math/rand" 26 "net" 27 "net/url" 28 "testing" 29 "time" 30 31 "get.pme.sh/pnats/server" 32 "github.com/nats-io/nats.go" 33 ) 34 35 const PERF_PORT = 8422 36 37 // For Go routine based server. 38 func runBenchServer() *server.Server { 39 opts := DefaultTestOptions 40 opts.Port = PERF_PORT 41 opts.DisableShortFirstPing = true 42 return RunServer(&opts) 43 } 44 45 const defaultRecBufSize = 32768 46 const defaultSendBufSize = 32768 47 48 func flushConnection(b *testing.B, c net.Conn) { 49 buf := make([]byte, 32) 50 c.Write([]byte("PING\r\n")) 51 c.SetReadDeadline(time.Now().Add(5 * time.Second)) 52 n, err := c.Read(buf) 53 c.SetReadDeadline(time.Time{}) 54 if err != nil { 55 b.Fatalf("Failed read: %v\n", err) 56 } 57 if n != 6 && buf[0] != 'P' && buf[1] != 'O' { 58 b.Fatalf("Failed read of PONG: %s\n", buf) 59 } 60 } 61 62 func benchPub(b *testing.B, subject, payload string) { 63 b.StopTimer() 64 s := runBenchServer() 65 c := createClientConn(b, "127.0.0.1", PERF_PORT) 66 doDefaultConnect(b, c) 67 bw := bufio.NewWriterSize(c, defaultSendBufSize) 68 sendOp := []byte(fmt.Sprintf("PUB %s %d\r\n%s\r\n", subject, len(payload), payload)) 69 b.SetBytes(int64(len(sendOp))) 70 b.StartTimer() 71 for i := 0; i < b.N; i++ { 72 bw.Write(sendOp) 73 } 74 bw.Flush() 75 flushConnection(b, c) 76 b.StopTimer() 77 c.Close() 78 s.Shutdown() 79 } 80 81 var ch = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@$#%^&*()") 82 83 func sizedBytes(sz int) []byte { 84 b := make([]byte, sz) 85 for i := range b { 86 b[i] = ch[rand.Intn(len(ch))] 87 } 88 return b 89 } 90 91 func sizedString(sz int) string { 92 return string(sizedBytes(sz)) 93 } 94 95 // Publish subject for pub benchmarks. 96 var psub = "a" 97 98 func Benchmark______Pub0b_Payload(b *testing.B) { 99 benchPub(b, psub, "") 100 } 101 102 func Benchmark______Pub8b_Payload(b *testing.B) { 103 b.StopTimer() 104 s := sizedString(8) 105 benchPub(b, psub, s) 106 } 107 108 func Benchmark_____Pub32b_Payload(b *testing.B) { 109 b.StopTimer() 110 s := sizedString(32) 111 benchPub(b, psub, s) 112 } 113 114 func Benchmark____Pub128B_Payload(b *testing.B) { 115 b.StopTimer() 116 s := sizedString(128) 117 benchPub(b, psub, s) 118 } 119 120 func Benchmark____Pub256B_Payload(b *testing.B) { 121 b.StopTimer() 122 s := sizedString(256) 123 benchPub(b, psub, s) 124 } 125 126 func Benchmark______Pub1K_Payload(b *testing.B) { 127 b.StopTimer() 128 s := sizedString(1024) 129 benchPub(b, psub, s) 130 } 131 132 func Benchmark______Pub4K_Payload(b *testing.B) { 133 b.StopTimer() 134 s := sizedString(4 * 1024) 135 benchPub(b, psub, s) 136 } 137 138 func Benchmark______Pub8K_Payload(b *testing.B) { 139 b.StopTimer() 140 s := sizedString(8 * 1024) 141 benchPub(b, psub, s) 142 } 143 144 func Benchmark_____Pub32K_Payload(b *testing.B) { 145 b.StopTimer() 146 s := sizedString(32 * 1024) 147 benchPub(b, psub, s) 148 } 149 150 func drainConnection(b *testing.B, c net.Conn, ch chan bool, expected int) { 151 buf := make([]byte, defaultRecBufSize) 152 bytes := 0 153 154 for { 155 c.SetReadDeadline(time.Now().Add(30 * time.Second)) 156 n, err := c.Read(buf) 157 if err != nil { 158 b.Errorf("Error on read: %v\n", err) 159 break 160 } 161 bytes += n 162 if bytes >= expected { 163 break 164 } 165 } 166 if bytes != expected { 167 b.Errorf("Did not receive all bytes: %d vs %d\n", bytes, expected) 168 } 169 ch <- true 170 } 171 172 // Benchmark the authorization code path. 173 func Benchmark__AuthPub0b_Payload(b *testing.B) { 174 b.StopTimer() 175 176 srv, opts := RunServerWithConfig("./configs/authorization.conf") 177 opts.DisableShortFirstPing = true 178 defer srv.Shutdown() 179 180 c := createClientConn(b, opts.Host, opts.Port) 181 defer c.Close() 182 expectAuthRequired(b, c) 183 184 cs := fmt.Sprintf("CONNECT {\"verbose\":false,\"user\":\"%s\",\"pass\":\"%s\"}\r\n", "bench", DefaultPass) 185 sendProto(b, c, cs) 186 187 bw := bufio.NewWriterSize(c, defaultSendBufSize) 188 sendOp := []byte("PUB a 0\r\n\r\n") 189 b.SetBytes(int64(len(sendOp))) 190 b.StartTimer() 191 for i := 0; i < b.N; i++ { 192 bw.Write(sendOp) 193 } 194 bw.Flush() 195 flushConnection(b, c) 196 b.StopTimer() 197 } 198 199 func Benchmark_____________PubSub(b *testing.B) { 200 b.StopTimer() 201 s := runBenchServer() 202 c := createClientConn(b, "127.0.0.1", PERF_PORT) 203 doDefaultConnect(b, c) 204 sendProto(b, c, "SUB foo 1\r\n") 205 bw := bufio.NewWriterSize(c, defaultSendBufSize) 206 sendOp := []byte("PUB foo 2\r\nok\r\n") 207 ch := make(chan bool) 208 expected := len("MSG foo 1 2\r\nok\r\n") * b.N 209 go drainConnection(b, c, ch, expected) 210 b.StartTimer() 211 212 for i := 0; i < b.N; i++ { 213 _, err := bw.Write(sendOp) 214 if err != nil { 215 b.Errorf("Received error on PUB write: %v\n", err) 216 } 217 } 218 err := bw.Flush() 219 if err != nil { 220 b.Errorf("Received error on FLUSH write: %v\n", err) 221 } 222 223 // Wait for connection to be drained 224 <-ch 225 226 b.StopTimer() 227 c.Close() 228 s.Shutdown() 229 } 230 231 func Benchmark_____PubSubTwoConns(b *testing.B) { 232 b.StopTimer() 233 s := runBenchServer() 234 c := createClientConn(b, "127.0.0.1", PERF_PORT) 235 doDefaultConnect(b, c) 236 bw := bufio.NewWriterSize(c, defaultSendBufSize) 237 238 c2 := createClientConn(b, "127.0.0.1", PERF_PORT) 239 doDefaultConnect(b, c2) 240 sendProto(b, c2, "SUB foo 1\r\n") 241 flushConnection(b, c2) 242 243 sendOp := []byte("PUB foo 2\r\nok\r\n") 244 ch := make(chan bool) 245 246 expected := len("MSG foo 1 2\r\nok\r\n") * b.N 247 go drainConnection(b, c2, ch, expected) 248 249 b.StartTimer() 250 for i := 0; i < b.N; i++ { 251 bw.Write(sendOp) 252 } 253 err := bw.Flush() 254 if err != nil { 255 b.Errorf("Received error on FLUSH write: %v\n", err) 256 } 257 258 // Wait for connection to be drained 259 <-ch 260 261 b.StopTimer() 262 c.Close() 263 c2.Close() 264 s.Shutdown() 265 } 266 267 func benchDefaultOptionsForAccounts() *server.Options { 268 o := DefaultTestOptions 269 o.Host = "127.0.0.1" 270 o.Port = -1 271 o.Cluster.Host = o.Host 272 o.Cluster.Port = -1 273 o.DisableShortFirstPing = true 274 fooAcc := server.NewAccount("$foo") 275 fooAcc.AddStreamExport("foo", nil) 276 barAcc := server.NewAccount("$bar") 277 barAcc.AddStreamImport(fooAcc, "foo", "") 278 o.Accounts = []*server.Account{fooAcc, barAcc} 279 280 return &o 281 } 282 283 func createClientWithAccount(b *testing.B, account, host string, port int) net.Conn { 284 c := createClientConn(b, host, port) 285 checkInfoMsg(b, c) 286 cs := fmt.Sprintf("CONNECT {\"verbose\":%v,\"pedantic\":%v,\"tls_required\":%v,\"account\":%q}\r\n", false, false, false, account) 287 sendProto(b, c, cs) 288 return c 289 } 290 291 func benchOptionsForServiceImports() *server.Options { 292 o := DefaultTestOptions 293 o.Host = "127.0.0.1" 294 o.Port = -1 295 o.DisableShortFirstPing = true 296 foo := server.NewAccount("$foo") 297 bar := server.NewAccount("$bar") 298 o.Accounts = []*server.Account{foo, bar} 299 300 return &o 301 } 302 303 func addServiceImports(b *testing.B, s *server.Server) { 304 // Add a bunch of service exports with wildcards, similar to JS. 305 var exports = []string{ 306 server.JSApiAccountInfo, 307 server.JSApiTemplateCreate, 308 server.JSApiTemplates, 309 server.JSApiTemplateInfo, 310 server.JSApiTemplateDelete, 311 server.JSApiStreamCreate, 312 server.JSApiStreamUpdate, 313 server.JSApiStreams, 314 server.JSApiStreamInfo, 315 server.JSApiStreamDelete, 316 server.JSApiStreamPurge, 317 server.JSApiMsgDelete, 318 server.JSApiConsumerCreate, 319 server.JSApiConsumers, 320 server.JSApiConsumerInfo, 321 server.JSApiConsumerDelete, 322 } 323 foo, _ := s.LookupAccount("$foo") 324 bar, _ := s.LookupAccount("$bar") 325 326 for _, export := range exports { 327 if err := bar.AddServiceExport(export, nil); err != nil { 328 b.Fatalf("Could not add service export: %v", err) 329 } 330 if err := foo.AddServiceImport(bar, export, ""); err != nil { 331 b.Fatalf("Could not add service import: %v", err) 332 } 333 } 334 } 335 336 func Benchmark__PubServiceImports(b *testing.B) { 337 o := benchOptionsForServiceImports() 338 s := RunServer(o) 339 defer s.Shutdown() 340 341 addServiceImports(b, s) 342 343 c := createClientWithAccount(b, "$foo", o.Host, o.Port) 344 defer c.Close() 345 346 bw := bufio.NewWriterSize(c, defaultSendBufSize) 347 sendOp := []byte("PUB foo 2\r\nok\r\n") 348 349 b.ResetTimer() 350 for i := 0; i < b.N; i++ { 351 bw.Write(sendOp) 352 } 353 err := bw.Flush() 354 if err != nil { 355 b.Errorf("Received error on FLUSH write: %v\n", err) 356 } 357 b.StopTimer() 358 } 359 360 func Benchmark___PubSubAccsImport(b *testing.B) { 361 o := benchDefaultOptionsForAccounts() 362 s := RunServer(o) 363 defer s.Shutdown() 364 365 pub := createClientWithAccount(b, "$foo", o.Host, o.Port) 366 defer pub.Close() 367 368 sub := createClientWithAccount(b, "$bar", o.Host, o.Port) 369 defer sub.Close() 370 371 sendProto(b, sub, "SUB foo 1\r\n") 372 flushConnection(b, sub) 373 ch := make(chan bool) 374 expected := len("MSG foo 1 2\r\nok\r\n") * b.N 375 go drainConnection(b, sub, ch, expected) 376 377 bw := bufio.NewWriterSize(pub, defaultSendBufSize) 378 sendOp := []byte("PUB foo 2\r\nok\r\n") 379 380 b.ResetTimer() 381 for i := 0; i < b.N; i++ { 382 bw.Write(sendOp) 383 } 384 err := bw.Flush() 385 if err != nil { 386 b.Errorf("Received error on FLUSH write: %v\n", err) 387 } 388 389 // Wait for connection to be drained 390 <-ch 391 b.StopTimer() 392 } 393 394 func Benchmark_____PubTwoQueueSub(b *testing.B) { 395 b.StopTimer() 396 s := runBenchServer() 397 c := createClientConn(b, "127.0.0.1", PERF_PORT) 398 doDefaultConnect(b, c) 399 sendProto(b, c, "SUB foo group1 1\r\n") 400 sendProto(b, c, "SUB foo group1 2\r\n") 401 bw := bufio.NewWriterSize(c, defaultSendBufSize) 402 sendOp := []byte("PUB foo 2\r\nok\r\n") 403 ch := make(chan bool) 404 expected := len("MSG foo 1 2\r\nok\r\n") * b.N 405 go drainConnection(b, c, ch, expected) 406 b.StartTimer() 407 408 for i := 0; i < b.N; i++ { 409 _, err := bw.Write(sendOp) 410 if err != nil { 411 b.Fatalf("Received error on PUB write: %v\n", err) 412 } 413 } 414 err := bw.Flush() 415 if err != nil { 416 b.Fatalf("Received error on FLUSH write: %v\n", err) 417 } 418 419 // Wait for connection to be drained 420 <-ch 421 422 b.StopTimer() 423 c.Close() 424 s.Shutdown() 425 } 426 427 func Benchmark____PubFourQueueSub(b *testing.B) { 428 b.StopTimer() 429 s := runBenchServer() 430 c := createClientConn(b, "127.0.0.1", PERF_PORT) 431 doDefaultConnect(b, c) 432 sendProto(b, c, "SUB foo group1 1\r\n") 433 sendProto(b, c, "SUB foo group1 2\r\n") 434 sendProto(b, c, "SUB foo group1 3\r\n") 435 sendProto(b, c, "SUB foo group1 4\r\n") 436 bw := bufio.NewWriterSize(c, defaultSendBufSize) 437 sendOp := []byte("PUB foo 2\r\nok\r\n") 438 ch := make(chan bool) 439 expected := len("MSG foo 1 2\r\nok\r\n") * b.N 440 go drainConnection(b, c, ch, expected) 441 b.StartTimer() 442 443 for i := 0; i < b.N; i++ { 444 _, err := bw.Write(sendOp) 445 if err != nil { 446 b.Fatalf("Received error on PUB write: %v\n", err) 447 } 448 } 449 err := bw.Flush() 450 if err != nil { 451 b.Fatalf("Received error on FLUSH write: %v\n", err) 452 } 453 454 // Wait for connection to be drained 455 <-ch 456 457 b.StopTimer() 458 c.Close() 459 s.Shutdown() 460 } 461 462 func Benchmark___PubEightQueueSub(b *testing.B) { 463 b.StopTimer() 464 s := runBenchServer() 465 c := createClientConn(b, "127.0.0.1", PERF_PORT) 466 doDefaultConnect(b, c) 467 sendProto(b, c, "SUB foo group1 1\r\n") 468 sendProto(b, c, "SUB foo group1 2\r\n") 469 sendProto(b, c, "SUB foo group1 3\r\n") 470 sendProto(b, c, "SUB foo group1 4\r\n") 471 sendProto(b, c, "SUB foo group1 5\r\n") 472 sendProto(b, c, "SUB foo group1 6\r\n") 473 sendProto(b, c, "SUB foo group1 7\r\n") 474 sendProto(b, c, "SUB foo group1 8\r\n") 475 bw := bufio.NewWriterSize(c, defaultSendBufSize) 476 sendOp := []byte("PUB foo 2\r\nok\r\n") 477 ch := make(chan bool) 478 expected := len("MSG foo 1 2\r\nok\r\n") * b.N 479 go drainConnection(b, c, ch, expected) 480 b.StartTimer() 481 482 for i := 0; i < b.N; i++ { 483 _, err := bw.Write(sendOp) 484 if err != nil { 485 b.Fatalf("Received error on PUB write: %v\n", err) 486 } 487 } 488 err := bw.Flush() 489 if err != nil { 490 b.Fatalf("Received error on FLUSH write: %v\n", err) 491 } 492 493 // Wait for connection to be drained 494 <-ch 495 496 b.StopTimer() 497 c.Close() 498 s.Shutdown() 499 } 500 501 func Benchmark_PubSub512kTwoConns(b *testing.B) { 502 b.StopTimer() 503 s := runBenchServer() 504 c := createClientConn(b, "127.0.0.1", PERF_PORT) 505 doDefaultConnect(b, c) 506 bw := bufio.NewWriterSize(c, defaultSendBufSize) 507 508 c2 := createClientConn(b, "127.0.0.1", PERF_PORT) 509 doDefaultConnect(b, c2) 510 sendProto(b, c2, "SUB foo 1\r\n") 511 flushConnection(b, c2) 512 513 sz := 1024 * 512 514 payload := sizedString(sz) 515 516 sendOp := []byte(fmt.Sprintf("PUB foo %d\r\n%s\r\n", sz, payload)) 517 ch := make(chan bool) 518 519 expected := len(fmt.Sprintf("MSG foo 1 %d\r\n%s\r\n", sz, payload)) * b.N 520 go drainConnection(b, c2, ch, expected) 521 522 b.StartTimer() 523 for i := 0; i < b.N; i++ { 524 bw.Write(sendOp) 525 } 526 err := bw.Flush() 527 if err != nil { 528 b.Errorf("Received error on FLUSH write: %v\n", err) 529 } 530 531 // Wait for connection to be drained 532 <-ch 533 534 b.StopTimer() 535 c.Close() 536 c2.Close() 537 s.Shutdown() 538 } 539 540 func Benchmark__DenyMsgNoWCPubSub(b *testing.B) { 541 s, opts := RunServerWithConfig("./configs/authorization.conf") 542 opts.DisableShortFirstPing = true 543 defer s.Shutdown() 544 545 c := createClientConn(b, opts.Host, opts.Port) 546 defer c.Close() 547 548 expectAuthRequired(b, c) 549 cs := fmt.Sprintf("CONNECT {\"verbose\":false,\"pedantic\":false,\"user\":\"%s\",\"pass\":\"%s\"}\r\n", "bench-deny", DefaultPass) 550 sendProto(b, c, cs) 551 552 sendProto(b, c, "SUB foo 1\r\n") 553 bw := bufio.NewWriterSize(c, defaultSendBufSize) 554 sendOp := []byte("PUB foo 2\r\nok\r\n") 555 ch := make(chan bool) 556 expected := len("MSG foo 1 2\r\nok\r\n") * b.N 557 go drainConnection(b, c, ch, expected) 558 b.ResetTimer() 559 560 for i := 0; i < b.N; i++ { 561 _, err := bw.Write(sendOp) 562 if err != nil { 563 b.Errorf("Received error on PUB write: %v\n", err) 564 } 565 } 566 err := bw.Flush() 567 if err != nil { 568 b.Errorf("Received error on FLUSH write: %v\n", err) 569 } 570 571 // Wait for connection to be drained 572 <-ch 573 574 // To not count defer cleanup of client and server. 575 b.StopTimer() 576 } 577 578 func Benchmark_DenyMsgYesWCPubSub(b *testing.B) { 579 s, opts := RunServerWithConfig("./configs/authorization.conf") 580 opts.DisableShortFirstPing = true 581 defer s.Shutdown() 582 583 c := createClientConn(b, opts.Host, opts.Port) 584 defer c.Close() 585 586 expectAuthRequired(b, c) 587 cs := fmt.Sprintf("CONNECT {\"verbose\":false,\"pedantic\":false,\"user\":\"%s\",\"pass\":\"%s\"}\r\n", "bench-deny", DefaultPass) 588 sendProto(b, c, cs) 589 590 sendProto(b, c, "SUB * 1\r\n") 591 bw := bufio.NewWriterSize(c, defaultSendBufSize) 592 sendOp := []byte("PUB foo 2\r\nok\r\n") 593 ch := make(chan bool) 594 expected := len("MSG foo 1 2\r\nok\r\n") * b.N 595 go drainConnection(b, c, ch, expected) 596 b.ResetTimer() 597 598 for i := 0; i < b.N; i++ { 599 _, err := bw.Write(sendOp) 600 if err != nil { 601 b.Errorf("Received error on PUB write: %v\n", err) 602 } 603 } 604 err := bw.Flush() 605 if err != nil { 606 b.Errorf("Received error on FLUSH write: %v\n", err) 607 } 608 609 // Wait for connection to be drained 610 <-ch 611 612 // To not count defer cleanup of client and server. 613 b.StopTimer() 614 } 615 616 func routePubSub(b *testing.B, size int) { 617 b.StopTimer() 618 619 s1, o1 := RunServerWithConfig("./configs/srv_a.conf") 620 o1.DisableShortFirstPing = true 621 defer s1.Shutdown() 622 s2, o2 := RunServerWithConfig("./configs/srv_b.conf") 623 o2.DisableShortFirstPing = true 624 defer s2.Shutdown() 625 626 sub := createClientConn(b, o1.Host, o1.Port) 627 doDefaultConnect(b, sub) 628 sendProto(b, sub, "SUB foo 1\r\n") 629 flushConnection(b, sub) 630 631 payload := sizedString(size) 632 633 pub := createClientConn(b, o2.Host, o2.Port) 634 doDefaultConnect(b, pub) 635 bw := bufio.NewWriterSize(pub, defaultSendBufSize) 636 637 ch := make(chan bool) 638 sendOp := []byte(fmt.Sprintf("PUB foo %d\r\n%s\r\n", len(payload), payload)) 639 expected := len(fmt.Sprintf("MSG foo 1 %d\r\n%s\r\n", len(payload), payload)) * b.N 640 go drainConnection(b, sub, ch, expected) 641 b.StartTimer() 642 643 for i := 0; i < b.N; i++ { 644 _, err := bw.Write(sendOp) 645 if err != nil { 646 b.Fatalf("Received error on PUB write: %v\n", err) 647 } 648 649 } 650 err := bw.Flush() 651 if err != nil { 652 b.Errorf("Received error on FLUSH write: %v\n", err) 653 } 654 655 // Wait for connection to be drained 656 <-ch 657 658 b.StopTimer() 659 pub.Close() 660 sub.Close() 661 } 662 663 func Benchmark____RoutedPubSub_0b(b *testing.B) { 664 routePubSub(b, 2) 665 } 666 667 func Benchmark____RoutedPubSub_1K(b *testing.B) { 668 routePubSub(b, 1024) 669 } 670 671 func Benchmark__RoutedPubSub_100K(b *testing.B) { 672 routePubSub(b, 100*1024) 673 } 674 675 func routeQueue(b *testing.B, numQueueSubs, size int) { 676 s1, o1 := RunServerWithConfig("./configs/srv_a.conf") 677 o1.DisableShortFirstPing = true 678 defer s1.Shutdown() 679 s2, o2 := RunServerWithConfig("./configs/srv_b.conf") 680 o2.DisableShortFirstPing = true 681 defer s2.Shutdown() 682 683 sub := createClientConn(b, o1.Host, o1.Port) 684 defer sub.Close() 685 doDefaultConnect(b, sub) 686 for i := 0; i < numQueueSubs; i++ { 687 sendProto(b, sub, fmt.Sprintf("SUB foo bar %d\r\n", 100+i)) 688 } 689 flushConnection(b, sub) 690 691 payload := sizedString(size) 692 693 pub := createClientConn(b, o2.Host, o2.Port) 694 defer pub.Close() 695 doDefaultConnect(b, pub) 696 bw := bufio.NewWriterSize(pub, defaultSendBufSize) 697 698 ch := make(chan bool) 699 sendOp := []byte(fmt.Sprintf("PUB foo %d\r\n%s\r\n", len(payload), payload)) 700 expected := len(fmt.Sprintf("MSG foo 100 %d\r\n%s\r\n", len(payload), payload)) * b.N 701 go drainConnection(b, sub, ch, expected) 702 703 b.ResetTimer() 704 705 for i := 0; i < b.N; i++ { 706 _, err := bw.Write(sendOp) 707 if err != nil { 708 b.Fatalf("Received error on PUB write: %v\n", err) 709 } 710 711 } 712 err := bw.Flush() 713 if err != nil { 714 b.Errorf("Received error on FLUSH write: %v\n", err) 715 } 716 717 // Wait for connection to be drained 718 <-ch 719 720 b.StopTimer() 721 } 722 723 func Benchmark____Routed2QueueSub(b *testing.B) { 724 routeQueue(b, 2, 2) 725 } 726 727 func Benchmark____Routed4QueueSub(b *testing.B) { 728 routeQueue(b, 4, 2) 729 } 730 731 func Benchmark____Routed8QueueSub(b *testing.B) { 732 routeQueue(b, 8, 2) 733 } 734 735 func Benchmark___Routed16QueueSub(b *testing.B) { 736 routeQueue(b, 16, 2) 737 } 738 739 func doS2CompressBench(b *testing.B, compress string) { 740 b.StopTimer() 741 conf1 := createConfFile(b, []byte(fmt.Sprintf(` 742 port: -1 743 cluster { 744 name: "local" 745 port: -1 746 pool_size: -1 747 compression: %s 748 } 749 `, compress))) 750 s1, o1 := RunServerWithConfig(conf1) 751 defer s1.Shutdown() 752 753 conf2 := createConfFile(b, []byte(fmt.Sprintf(` 754 port: -1 755 cluster { 756 name: "local" 757 port: -1 758 pool_size: -1 759 compression: %s 760 routes: ["nats://127.0.0.1:%d"] 761 } 762 `, compress, o1.Cluster.Port))) 763 s2, _ := RunServerWithConfig(conf2) 764 defer s2.Shutdown() 765 766 checkClusterFormed(b, s1, s2) 767 768 nc2, err := nats.Connect(s2.ClientURL()) 769 if err != nil { 770 b.Fatalf("Error on connect: %v", err) 771 } 772 defer nc2.Close() 773 774 ch := make(chan struct{}, 1) 775 var count int 776 nc2.Subscribe("foo", func(_ *nats.Msg) { 777 if count++; count == b.N { 778 select { 779 case ch <- struct{}{}: 780 default: 781 } 782 } 783 }) 784 785 checkSubInterest(b, s1, "$G", "foo", time.Second) 786 787 nc1, err := nats.Connect(s1.ClientURL()) 788 if err != nil { 789 b.Fatalf("Error on connect: %v", err) 790 } 791 defer nc1.Close() 792 793 // This one is easily compressible. 794 payload1 := make([]byte, 128) 795 // Make it random so that compression code has more to do. 796 payload2 := make([]byte, 256) 797 for i := 0; i < len(payload); i++ { 798 payload2[i] = byte(rand.Intn(26) + 'A') 799 } 800 b.StartTimer() 801 802 for i := 0; i < b.N; i++ { 803 if i%2 == 0 { 804 nc1.Publish("foo", payload1) 805 } else { 806 nc1.Publish("foo", payload2) 807 } 808 } 809 810 select { 811 case <-ch: 812 return 813 case <-time.After(10 * time.Second): 814 b.Fatal("Timeout waiting to receive all messages") 815 } 816 } 817 818 func Benchmark____________RouteCompressOff(b *testing.B) { 819 doS2CompressBench(b, server.CompressionOff) 820 } 821 822 func Benchmark_RouteCompressS2Uncompressed(b *testing.B) { 823 doS2CompressBench(b, server.CompressionS2Uncompressed) 824 } 825 826 func Benchmark_________RouteCompressS2Fast(b *testing.B) { 827 doS2CompressBench(b, server.CompressionS2Fast) 828 } 829 830 func Benchmark_______RouteCompressS2Better(b *testing.B) { 831 doS2CompressBench(b, server.CompressionS2Better) 832 } 833 834 func Benchmark_________RouteCompressS2Best(b *testing.B) { 835 doS2CompressBench(b, server.CompressionS2Best) 836 } 837 838 func doFanout(b *testing.B, numServers, numConnections, subsPerConnection int, subject, payload string) { 839 var s1, s2 *server.Server 840 var o1, o2 *server.Options 841 842 switch numServers { 843 case 1: 844 s1, o1 = RunServerWithConfig("./configs/srv_a.conf") 845 o1.DisableShortFirstPing = true 846 defer s1.Shutdown() 847 s2, o2 = s1, o1 848 case 2: 849 s1, o1 = RunServerWithConfig("./configs/srv_a.conf") 850 o1.DisableShortFirstPing = true 851 defer s1.Shutdown() 852 s2, o2 = RunServerWithConfig("./configs/srv_b.conf") 853 o2.DisableShortFirstPing = true 854 defer s2.Shutdown() 855 default: 856 b.Fatalf("%d servers not supported for this test\n", numServers) 857 } 858 859 // To get a consistent length sid in MSG sent to us for drainConnection. 860 var sidFloor int 861 switch { 862 case subsPerConnection <= 100: 863 sidFloor = 100 864 case subsPerConnection <= 1000: 865 sidFloor = 1000 866 case subsPerConnection <= 10000: 867 sidFloor = 10000 868 default: 869 b.Fatalf("Unsupported SubsPerConnection argument of %d\n", subsPerConnection) 870 } 871 872 msgOp := fmt.Sprintf("MSG %s %d %d\r\n%s\r\n", subject, sidFloor, len(payload), payload) 873 expected := len(msgOp) * subsPerConnection * b.N 874 875 // Client connections and subscriptions. 876 clients := make([]chan bool, 0, numConnections) 877 for i := 0; i < numConnections; i++ { 878 c := createClientConn(b, o2.Host, o2.Port) 879 doDefaultConnect(b, c) 880 defer c.Close() 881 882 ch := make(chan bool) 883 clients = append(clients, ch) 884 885 for s := 0; s < subsPerConnection; s++ { 886 subOp := fmt.Sprintf("SUB %s %d\r\n", subject, sidFloor+s) 887 sendProto(b, c, subOp) 888 } 889 flushConnection(b, c) 890 go drainConnection(b, c, ch, expected) 891 } 892 // Publish Connection 893 c := createClientConn(b, o1.Host, o1.Port) 894 doDefaultConnect(b, c) 895 flushConnection(b, c) 896 897 bw := bufio.NewWriterSize(c, defaultSendBufSize) 898 sendOp := []byte(fmt.Sprintf("PUB %s %d\r\n%s\r\n", subject, len(payload), payload)) 899 900 b.SetBytes(int64(len(sendOp) + (len(msgOp) * numConnections * subsPerConnection))) 901 b.ResetTimer() 902 903 for i := 0; i < b.N; i++ { 904 _, err := bw.Write(sendOp) 905 if err != nil { 906 b.Fatalf("Received error on PUB write: %v\n", err) 907 } 908 } 909 err := bw.Flush() 910 if err != nil { 911 b.Fatalf("Received error on FLUSH write: %v\n", err) 912 } 913 914 // Wait for connections to be drained 915 for i := 0; i < numConnections; i++ { 916 <-clients[i] 917 } 918 b.StopTimer() 919 } 920 921 var sub = "x" 922 var payload = "12345678" 923 924 func Benchmark______FanOut_8x1x10(b *testing.B) { 925 doFanout(b, 1, 1, 10, sub, payload) 926 } 927 928 func Benchmark_____FanOut_8x1x100(b *testing.B) { 929 doFanout(b, 1, 1, 100, sub, payload) 930 } 931 932 func Benchmark____FanOut_8x10x100(b *testing.B) { 933 doFanout(b, 1, 10, 100, sub, payload) 934 } 935 936 func Benchmark___FanOut_8x10x1000(b *testing.B) { 937 doFanout(b, 1, 10, 1000, sub, payload) 938 } 939 940 func Benchmark___FanOut_8x100x100(b *testing.B) { 941 doFanout(b, 1, 100, 100, sub, payload) 942 } 943 944 func Benchmark__FanOut_8x100x1000(b *testing.B) { 945 doFanout(b, 1, 100, 1000, sub, payload) 946 } 947 948 func Benchmark__FanOut_8x10x10000(b *testing.B) { 949 doFanout(b, 1, 10, 10000, sub, payload) 950 } 951 952 func Benchmark___FanOut_8x500x100(b *testing.B) { 953 doFanout(b, 1, 500, 100, sub, payload) 954 } 955 956 func Benchmark___FanOut_128x1x100(b *testing.B) { 957 doFanout(b, 1, 1, 100, sub, sizedString(128)) 958 } 959 960 func Benchmark__FanOut_128x10x100(b *testing.B) { 961 doFanout(b, 1, 10, 100, sub, sizedString(128)) 962 } 963 964 func Benchmark_FanOut_128x10x1000(b *testing.B) { 965 doFanout(b, 1, 10, 1000, sub, sizedString(128)) 966 } 967 968 func Benchmark_FanOut_128x100x100(b *testing.B) { 969 doFanout(b, 1, 100, 100, sub, sizedString(128)) 970 } 971 972 func BenchmarkFanOut_128x100x1000(b *testing.B) { 973 doFanout(b, 1, 100, 1000, sub, sizedString(128)) 974 } 975 976 func BenchmarkFanOut_128x10x10000(b *testing.B) { 977 doFanout(b, 1, 10, 10000, sub, sizedString(128)) 978 } 979 980 func BenchmarkFanOut__128x500x100(b *testing.B) { 981 doFanout(b, 1, 500, 100, sub, sizedString(128)) 982 } 983 984 func Benchmark_FanOut_512x100x100(b *testing.B) { 985 doFanout(b, 1, 100, 100, sub, sizedString(512)) 986 } 987 988 func Benchmark__FanOut_512x100x1k(b *testing.B) { 989 doFanout(b, 1, 100, 1000, sub, sizedString(512)) 990 } 991 992 func Benchmark____FanOut_1kx10x1k(b *testing.B) { 993 doFanout(b, 1, 10, 1000, sub, sizedString(1024)) 994 } 995 996 func Benchmark__FanOut_1kx100x100(b *testing.B) { 997 doFanout(b, 1, 100, 100, sub, sizedString(1024)) 998 } 999 1000 func Benchmark_____RFanOut_8x1x10(b *testing.B) { 1001 doFanout(b, 2, 1, 10, sub, payload) 1002 } 1003 1004 func Benchmark____RFanOut_8x1x100(b *testing.B) { 1005 doFanout(b, 2, 1, 100, sub, payload) 1006 } 1007 1008 func Benchmark___RFanOut_8x10x100(b *testing.B) { 1009 doFanout(b, 2, 10, 100, sub, payload) 1010 } 1011 1012 func Benchmark__RFanOut_8x10x1000(b *testing.B) { 1013 doFanout(b, 2, 10, 1000, sub, payload) 1014 } 1015 1016 func Benchmark__RFanOut_8x100x100(b *testing.B) { 1017 doFanout(b, 2, 100, 100, sub, payload) 1018 } 1019 1020 func Benchmark_RFanOut_8x100x1000(b *testing.B) { 1021 doFanout(b, 2, 100, 1000, sub, payload) 1022 } 1023 1024 func Benchmark_RFanOut_8x10x10000(b *testing.B) { 1025 doFanout(b, 2, 10, 10000, sub, payload) 1026 } 1027 1028 func Benchmark_RFanOut_1kx10x1000(b *testing.B) { 1029 doFanout(b, 2, 10, 1000, sub, sizedString(1024)) 1030 } 1031 1032 func doFanIn(b *testing.B, numServers, numPublishers, numSubscribers int, subject, payload string) { 1033 b.Helper() 1034 if b.N < numPublishers { 1035 return 1036 } 1037 // Don't check for number of subscribers being lower than the number of publishers. 1038 // We also use this bench to show the performance impact of increased number of publishers, 1039 // and for those tests, the number of publishers will start at 1 and increase to 10, 1040 // while the number of subscribers will always be 3. 1041 if numSubscribers > 10 { 1042 b.Fatalf("numSubscribers should be <= 10") 1043 } 1044 1045 var s1, s2 *server.Server 1046 var o1, o2 *server.Options 1047 1048 switch numServers { 1049 case 1: 1050 s1, o1 = RunServerWithConfig("./configs/srv_a.conf") 1051 o1.DisableShortFirstPing = true 1052 defer s1.Shutdown() 1053 s2, o2 = s1, o1 1054 case 2: 1055 s1, o1 = RunServerWithConfig("./configs/srv_a.conf") 1056 o1.DisableShortFirstPing = true 1057 defer s1.Shutdown() 1058 s2, o2 = RunServerWithConfig("./configs/srv_b.conf") 1059 o2.DisableShortFirstPing = true 1060 defer s2.Shutdown() 1061 default: 1062 b.Fatalf("%d servers not supported for this test\n", numServers) 1063 } 1064 1065 msgOp := fmt.Sprintf("MSG %s %d %d\r\n%s\r\n", subject, 9, len(payload), payload) 1066 l := b.N / numPublishers 1067 expected := len(msgOp) * l * numPublishers 1068 1069 // Client connections and subscriptions. For fan in these are smaller then numPublishers. 1070 clients := make([]chan bool, 0, numSubscribers) 1071 for i := 0; i < numSubscribers; i++ { 1072 c := createClientConn(b, o2.Host, o2.Port) 1073 doDefaultConnect(b, c) 1074 defer c.Close() 1075 1076 ch := make(chan bool) 1077 clients = append(clients, ch) 1078 1079 subOp := fmt.Sprintf("SUB %s %d\r\n", subject, i) 1080 sendProto(b, c, subOp) 1081 flushConnection(b, c) 1082 go drainConnection(b, c, ch, expected) 1083 } 1084 1085 sendOp := []byte(fmt.Sprintf("PUB %s %d\r\n%s\r\n", subject, len(payload), payload)) 1086 startCh := make(chan bool) 1087 1088 pubLoop := func(c net.Conn, ch chan bool) { 1089 bw := bufio.NewWriterSize(c, defaultSendBufSize) 1090 1091 // Signal we are ready 1092 close(ch) 1093 1094 // Wait to start up actual sends. 1095 <-startCh 1096 1097 for i := 0; i < l; i++ { 1098 _, err := bw.Write(sendOp) 1099 if err != nil { 1100 b.Errorf("Received error on PUB write: %v\n", err) 1101 return 1102 } 1103 } 1104 err := bw.Flush() 1105 if err != nil { 1106 b.Errorf("Received error on FLUSH write: %v\n", err) 1107 return 1108 } 1109 } 1110 1111 // Publish Connections SPINUP 1112 for i := 0; i < numPublishers; i++ { 1113 c := createClientConn(b, o1.Host, o1.Port) 1114 doDefaultConnect(b, c) 1115 flushConnection(b, c) 1116 ch := make(chan bool) 1117 1118 go pubLoop(c, ch) 1119 <-ch 1120 } 1121 1122 b.SetBytes(int64(len(sendOp) + len(msgOp))) 1123 b.ResetTimer() 1124 1125 // Closing this will start all publishers at once (roughly) 1126 close(startCh) 1127 1128 // Wait for connections to be drained 1129 for i := 0; i < len(clients); i++ { 1130 <-clients[i] 1131 } 1132 b.StopTimer() 1133 } 1134 1135 func Benchmark_____FanIn_1kx100x1(b *testing.B) { 1136 doFanIn(b, 1, 100, 1, sub, sizedString(1024)) 1137 } 1138 1139 func Benchmark_____FanIn_4kx100x1(b *testing.B) { 1140 doFanIn(b, 1, 100, 1, sub, sizedString(4096)) 1141 } 1142 1143 func Benchmark_____FanIn_8kx100x1(b *testing.B) { 1144 doFanIn(b, 1, 100, 1, sub, sizedString(8192)) 1145 } 1146 1147 func Benchmark____FanIn_16kx100x1(b *testing.B) { 1148 doFanIn(b, 1, 100, 1, sub, sizedString(16384)) 1149 } 1150 1151 func Benchmark____FanIn_64kx100x1(b *testing.B) { 1152 doFanIn(b, 1, 100, 1, sub, sizedString(65536)) 1153 } 1154 1155 func Benchmark___FanIn_128kx100x1(b *testing.B) { 1156 doFanIn(b, 1, 100, 1, sub, sizedString(65536*2)) 1157 } 1158 1159 func Benchmark___BumpPubCount_1x3(b *testing.B) { 1160 doFanIn(b, 1, 1, 3, sub, sizedString(128)) 1161 } 1162 1163 func Benchmark___BumpPubCount_2x3(b *testing.B) { 1164 doFanIn(b, 1, 2, 3, sub, sizedString(128)) 1165 } 1166 1167 func Benchmark___BumpPubCount_5x3(b *testing.B) { 1168 doFanIn(b, 1, 5, 3, sub, sizedString(128)) 1169 } 1170 1171 func Benchmark__BumpPubCount_10x3(b *testing.B) { 1172 doFanIn(b, 1, 10, 3, sub, sizedString(128)) 1173 } 1174 1175 func testDefaultBenchOptionsForGateway(name string) *server.Options { 1176 opts := testDefaultOptionsForGateway(name) 1177 opts.DisableShortFirstPing = true 1178 return opts 1179 } 1180 1181 func gatewaysBench(b *testing.B, optimisticMode bool, payload string, numPublishers int, subInterest bool) { 1182 b.Helper() 1183 if b.N < numPublishers { 1184 return 1185 } 1186 1187 ob := testDefaultBenchOptionsForGateway("B") 1188 sb := RunServer(ob) 1189 defer sb.Shutdown() 1190 1191 server.SetGatewaysSolicitDelay(10 * time.Millisecond) 1192 defer server.ResetGatewaysSolicitDelay() 1193 1194 gwbURL, err := url.Parse(fmt.Sprintf("nats://%s:%d", ob.Gateway.Host, ob.Gateway.Port)) 1195 if err != nil { 1196 b.Fatalf("Error parsing url: %v", err) 1197 } 1198 oa := testDefaultBenchOptionsForGateway("A") 1199 oa.Gateway.Gateways = []*server.RemoteGatewayOpts{ 1200 { 1201 Name: "B", 1202 URLs: []*url.URL{gwbURL}, 1203 }, 1204 } 1205 sa := RunServer(oa) 1206 defer sa.Shutdown() 1207 1208 sub := createClientConn(b, ob.Host, ob.Port) 1209 defer sub.Close() 1210 doDefaultConnect(b, sub) 1211 sendProto(b, sub, "SUB end.test 1\r\n") 1212 if subInterest { 1213 sendProto(b, sub, "SUB foo 2\r\n") 1214 } 1215 flushConnection(b, sub) 1216 1217 // If not optimisticMode, make B switch GW connection 1218 // to interest mode only 1219 if !optimisticMode { 1220 pub := createClientConn(b, oa.Host, oa.Port) 1221 doDefaultConnect(b, pub) 1222 // has to be more that defaultGatewayMaxRUnsubBeforeSwitch 1223 for i := 0; i < 2000; i++ { 1224 sendProto(b, pub, fmt.Sprintf("PUB reject.me.%d 2\r\nok\r\n", i+1)) 1225 } 1226 flushConnection(b, pub) 1227 pub.Close() 1228 } 1229 1230 ch := make(chan bool) 1231 var msgOp string 1232 var expected int 1233 l := b.N / numPublishers 1234 if subInterest { 1235 msgOp = fmt.Sprintf("MSG foo 2 %d\r\n%s\r\n", len(payload), payload) 1236 expected = len(msgOp) * l * numPublishers 1237 } 1238 // Last message sent to end.test 1239 lastMsg := "MSG end.test 1 2\r\nok\r\n" 1240 expected += len(lastMsg) * numPublishers 1241 go drainConnection(b, sub, ch, expected) 1242 1243 sendOp := []byte(fmt.Sprintf("PUB foo %d\r\n%s\r\n", len(payload), payload)) 1244 startCh := make(chan bool) 1245 1246 lastMsgSendOp := []byte("PUB end.test 2\r\nok\r\n") 1247 1248 pubLoop := func(c net.Conn, ch chan bool) { 1249 bw := bufio.NewWriterSize(c, defaultSendBufSize) 1250 1251 // Signal we are ready 1252 close(ch) 1253 1254 // Wait to start up actual sends. 1255 <-startCh 1256 1257 for i := 0; i < l; i++ { 1258 if _, err := bw.Write(sendOp); err != nil { 1259 b.Errorf("Received error on PUB write: %v\n", err) 1260 return 1261 } 1262 } 1263 if _, err := bw.Write(lastMsgSendOp); err != nil { 1264 b.Errorf("Received error on PUB write: %v\n", err) 1265 return 1266 } 1267 if err := bw.Flush(); err != nil { 1268 b.Errorf("Received error on FLUSH write: %v\n", err) 1269 return 1270 } 1271 flushConnection(b, c) 1272 } 1273 1274 // Publish Connections SPINUP 1275 for i := 0; i < numPublishers; i++ { 1276 c := createClientConn(b, oa.Host, oa.Port) 1277 defer c.Close() 1278 doDefaultConnect(b, c) 1279 flushConnection(b, c) 1280 ch := make(chan bool) 1281 1282 go pubLoop(c, ch) 1283 <-ch 1284 } 1285 1286 // To report the number of bytes: 1287 // from publisher to server on cluster A: 1288 numBytes := len(sendOp) 1289 if subInterest { 1290 // from server in cluster A to server on cluster B: 1291 // RMSG $G foo <payload size> <payload>\r\n 1292 numBytes += len("RMSG $G foo xxxx ") + len(payload) + 2 1293 1294 // From server in cluster B to sub: 1295 numBytes += len(msgOp) 1296 } 1297 b.SetBytes(int64(numBytes)) 1298 b.ResetTimer() 1299 1300 // Closing this will start all publishers at once (roughly) 1301 close(startCh) 1302 1303 // Wait for end of test 1304 <-ch 1305 1306 b.StopTimer() 1307 } 1308 1309 func Benchmark____GWs_Opt_1kx01x0(b *testing.B) { 1310 gatewaysBench(b, true, sizedString(1024), 1, false) 1311 } 1312 1313 func Benchmark____GWs_Opt_2kx01x0(b *testing.B) { 1314 gatewaysBench(b, true, sizedString(2048), 1, false) 1315 } 1316 1317 func Benchmark____GWs_Opt_4kx01x0(b *testing.B) { 1318 gatewaysBench(b, true, sizedString(4096), 1, false) 1319 } 1320 1321 func Benchmark____GWs_Opt_1kx10x0(b *testing.B) { 1322 gatewaysBench(b, true, sizedString(1024), 10, false) 1323 } 1324 1325 func Benchmark____GWs_Opt_2kx10x0(b *testing.B) { 1326 gatewaysBench(b, true, sizedString(2048), 10, false) 1327 } 1328 1329 func Benchmark____GWs_Opt_4kx10x0(b *testing.B) { 1330 gatewaysBench(b, true, sizedString(4096), 10, false) 1331 } 1332 1333 func Benchmark____GWs_Opt_1kx01x1(b *testing.B) { 1334 gatewaysBench(b, true, sizedString(1024), 1, true) 1335 } 1336 1337 func Benchmark____GWs_Opt_2kx01x1(b *testing.B) { 1338 gatewaysBench(b, true, sizedString(2048), 1, true) 1339 } 1340 1341 func Benchmark____GWs_Opt_4kx01x1(b *testing.B) { 1342 gatewaysBench(b, true, sizedString(4096), 1, true) 1343 } 1344 1345 func Benchmark____GWs_Opt_1kx10x1(b *testing.B) { 1346 gatewaysBench(b, true, sizedString(1024), 10, true) 1347 } 1348 1349 func Benchmark____GWs_Opt_2kx10x1(b *testing.B) { 1350 gatewaysBench(b, true, sizedString(2048), 10, true) 1351 } 1352 1353 func Benchmark____GWs_Opt_4kx10x1(b *testing.B) { 1354 gatewaysBench(b, true, sizedString(4096), 10, true) 1355 } 1356 1357 func Benchmark____GWs_Int_1kx01x0(b *testing.B) { 1358 gatewaysBench(b, false, sizedString(1024), 1, false) 1359 } 1360 1361 func Benchmark____GWs_Int_2kx01x0(b *testing.B) { 1362 gatewaysBench(b, false, sizedString(2048), 1, false) 1363 } 1364 1365 func Benchmark____GWs_Int_4kx01x0(b *testing.B) { 1366 gatewaysBench(b, false, sizedString(4096), 1, false) 1367 } 1368 1369 func Benchmark____GWs_Int_1kx10x0(b *testing.B) { 1370 gatewaysBench(b, false, sizedString(1024), 10, false) 1371 } 1372 1373 func Benchmark____GWs_Int_2kx10x0(b *testing.B) { 1374 gatewaysBench(b, false, sizedString(2048), 10, false) 1375 } 1376 1377 func Benchmark____GWs_Int_4kx10x0(b *testing.B) { 1378 gatewaysBench(b, false, sizedString(4096), 10, false) 1379 } 1380 1381 func Benchmark____GWs_Int_1kx01x1(b *testing.B) { 1382 gatewaysBench(b, false, sizedString(1024), 1, true) 1383 } 1384 1385 func Benchmark____GWs_Int_2kx01x1(b *testing.B) { 1386 gatewaysBench(b, false, sizedString(2048), 1, true) 1387 } 1388 1389 func Benchmark____GWs_Int_4kx01x1(b *testing.B) { 1390 gatewaysBench(b, false, sizedString(4096), 1, true) 1391 } 1392 1393 func Benchmark____GWs_Int_1kx10x1(b *testing.B) { 1394 gatewaysBench(b, false, sizedString(1024), 10, true) 1395 } 1396 1397 func Benchmark____GWs_Int_2kx10x1(b *testing.B) { 1398 gatewaysBench(b, false, sizedString(2048), 10, true) 1399 } 1400 1401 func Benchmark____GWs_Int_4kx10x1(b *testing.B) { 1402 gatewaysBench(b, false, sizedString(4096), 10, true) 1403 } 1404 1405 // This bench only sends the requests to verify impact 1406 // of reply mapping in GW code. 1407 func gatewaySendRequestsBench(b *testing.B, singleReplySub bool) { 1408 server.SetGatewaysSolicitDelay(10 * time.Millisecond) 1409 defer server.ResetGatewaysSolicitDelay() 1410 1411 ob := testDefaultBenchOptionsForGateway("B") 1412 sb := RunServer(ob) 1413 defer sb.Shutdown() 1414 1415 gwbURL, err := url.Parse(fmt.Sprintf("nats://%s:%d", ob.Gateway.Host, ob.Gateway.Port)) 1416 if err != nil { 1417 b.Fatalf("Error parsing url: %v", err) 1418 } 1419 oa := testDefaultBenchOptionsForGateway("A") 1420 oa.Gateway.Gateways = []*server.RemoteGatewayOpts{ 1421 { 1422 Name: "B", 1423 URLs: []*url.URL{gwbURL}, 1424 }, 1425 } 1426 sa := RunServer(oa) 1427 defer sa.Shutdown() 1428 1429 sub := createClientConn(b, ob.Host, ob.Port) 1430 defer sub.Close() 1431 doDefaultConnect(b, sub) 1432 sendProto(b, sub, "SUB foo 1\r\n") 1433 flushConnection(b, sub) 1434 1435 lenMsg := len("MSG foo reply.xxxxxxxxxx 1 2\r\nok\r\n") 1436 expected := b.N * lenMsg 1437 ch := make(chan bool, 1) 1438 go drainConnection(b, sub, ch, expected) 1439 1440 c := createClientConn(b, oa.Host, oa.Port) 1441 defer c.Close() 1442 doDefaultConnect(b, c) 1443 flushConnection(b, c) 1444 1445 // From pub to server in cluster A: 1446 numBytes := len("PUB foo reply.0123456789 2\r\nok\r\n") 1447 if !singleReplySub { 1448 // Add the preceding SUB 1449 numBytes += len("SUB reply.0123456789 0123456789\r\n") 1450 // And UNSUB... 1451 numBytes += len("UNSUB 0123456789\r\n") 1452 } 1453 // From server in cluster A to cluster B 1454 numBytes += len("RMSG $G foo reply.0123456789 2\r\nok\r\n") 1455 // If mapping of reply... 1456 if !singleReplySub { 1457 // the mapping uses about 24 more bytes. So add them 1458 // for RMSG from server to server. 1459 numBytes += 24 1460 } 1461 // From server in cluster B to sub 1462 numBytes += lenMsg 1463 b.SetBytes(int64(numBytes)) 1464 1465 bw := bufio.NewWriterSize(c, defaultSendBufSize) 1466 var subStr string 1467 1468 b.ResetTimer() 1469 1470 for i := 0; i < b.N; i++ { 1471 if !singleReplySub { 1472 subStr = fmt.Sprintf("SUB reply.%010d %010d\r\n", i+1, i+1) 1473 } 1474 bw.Write([]byte(fmt.Sprintf("%sPUB foo reply.%010d 2\r\nok\r\n", subStr, i+1))) 1475 // Simulate that we are doing actual request/reply and therefore 1476 // unsub'ing the subs on the reply subject. 1477 if !singleReplySub && i > 1000 { 1478 bw.Write([]byte(fmt.Sprintf("UNSUB %010d\r\n", (i - 1000)))) 1479 } 1480 } 1481 bw.Flush() 1482 flushConnection(b, c) 1483 1484 <-ch 1485 } 1486 1487 func Benchmark__GWs_Reqs_1_SubAll(b *testing.B) { 1488 gatewaySendRequestsBench(b, true) 1489 } 1490 1491 func Benchmark__GWs_Reqs_1SubEach(b *testing.B) { 1492 gatewaySendRequestsBench(b, false) 1493 }