github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/cli/systembench/network_test_client.go (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package systembench 12 13 import ( 14 "context" 15 "fmt" 16 "math/rand" 17 "sync/atomic" 18 "time" 19 20 "github.com/cockroachdb/cockroach/pkg/cli/systembench/systembenchpb" 21 "github.com/cockroachdb/cockroach/pkg/util/timeutil" 22 "golang.org/x/sync/errgroup" 23 "google.golang.org/grpc" 24 ) 25 26 // ClientOptions holds parameters for client part of 27 // the network test. 28 type ClientOptions struct { 29 Concurrency int 30 Duration time.Duration 31 LatencyMode bool 32 33 Addresses []string 34 } 35 36 // RunClient runs the client workload for the network benchmark. 37 func RunClient(clientOptions ClientOptions) error { 38 ctx := context.TODO() 39 clients := make([]systembench.PingerClient, len(clientOptions.Addresses)) 40 reg := newHistogramRegistry() 41 42 var packetSize int 43 if clientOptions.LatencyMode { 44 packetSize = 56 45 } else { 46 packetSize = 128 << 10 // 128KB 47 } 48 49 for i := 0; i < len(clientOptions.Addresses); i++ { 50 conn, err := grpc.Dial(clientOptions.Addresses[i], 51 grpc.WithInsecure(), 52 grpc.WithBlock(), 53 grpc.WithInitialWindowSize(65535), 54 grpc.WithInitialConnWindowSize(65535), 55 ) 56 if err != nil { 57 return err 58 } 59 clients[i] = systembench.NewPingerClient(conn) 60 } 61 lastNow := time.Second * 0 62 var lastOps uint64 63 var lastBytes uint64 64 65 return runTest(ctx, test{ 66 init: func(g *errgroup.Group) { 67 for i := range clients { 68 name := clientOptions.Addresses[i] 69 namedHist := reg.Register(name) 70 g.Go(func() error { 71 return grpcClientWorker(ctx, clients[i], namedHist, packetSize) 72 }) 73 } 74 }, 75 76 tick: func(elapsedTotal time.Duration, i int) { 77 elapsed := elapsedTotal - lastNow 78 ops := atomic.LoadUint64(&numOps) 79 bytes := atomic.LoadUint64(&numBytes) 80 81 if i%20 == 0 { 82 fmt.Println("_elapsed__________________address____ops/sec___mb/sec__p50(ms)__p95(ms)__p99(ms)_pMax(ms)") 83 } 84 reg.Tick(func(tick histogramTick) { 85 h := tick.Hist 86 fmt.Printf("%8s %24s %10.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n", 87 time.Duration(elapsedTotal.Seconds())*time.Second, 88 tick.Name, 89 float64(ops-lastOps)/elapsed.Seconds(), 90 float64(bytes-lastBytes)/(1024.0*1024.0)/elapsed.Seconds(), 91 time.Duration(h.ValueAtQuantile(50)).Seconds()*1000, 92 time.Duration(h.ValueAtQuantile(95)).Seconds()*1000, 93 time.Duration(h.ValueAtQuantile(99)).Seconds()*1000, 94 time.Duration(h.ValueAtQuantile(100)).Seconds()*1000, 95 ) 96 }) 97 lastNow = elapsedTotal 98 lastOps = ops 99 lastBytes = bytes 100 }, 101 102 done: func(elapsed time.Duration) { 103 const totalHeader = "\n_elapsed__________________address____ops(total)__mb(total)__avg(ms)__p50(ms)__p95(ms)__p99(ms)_pMax(ms)" 104 fmt.Println(totalHeader + `__total`) 105 reg.Tick(func(tick histogramTick) { 106 h := tick.Cumulative 107 fmt.Printf("%8s %24s %13d %10.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n", 108 time.Duration(elapsed.Seconds())*time.Second, 109 tick.Name, 110 atomic.LoadUint64(&numOps), 111 float64(atomic.LoadUint64(&numBytes)/(1024.0*1024.0)), 112 time.Duration(h.Mean()).Seconds()*1000, 113 time.Duration(h.ValueAtQuantile(50)).Seconds()*1000, 114 time.Duration(h.ValueAtQuantile(95)).Seconds()*1000, 115 time.Duration(h.ValueAtQuantile(99)).Seconds()*1000, 116 time.Duration(h.ValueAtQuantile(100)).Seconds()*1000) 117 }) 118 }, 119 }, clientOptions.Duration) 120 } 121 122 func grpcClientWorker( 123 ctx context.Context, c systembench.PingerClient, latency *namedHistogram, payloadSize int, 124 ) error { 125 payload := make([]byte, payloadSize) 126 _, _ = rand.Read(payload) 127 128 for { 129 start := timeutil.Now() 130 resp, err := c.Ping(ctx, &systembench.PingRequest{Payload: payload}) 131 132 if err != nil { 133 return err 134 } 135 136 elapsed := timeutil.Since(start) 137 latency.Record(elapsed) 138 atomic.AddUint64(&numOps, 1) 139 atomic.AddUint64(&numBytes, uint64(len(payload)+len(resp.Payload))) 140 } 141 }