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  }