gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/benchmarks/database/redis_test.go (about) 1 // Copyright 2021 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package database 16 17 import ( 18 "context" 19 "os" 20 "strings" 21 "testing" 22 "time" 23 24 "gvisor.dev/gvisor/pkg/test/dockerutil" 25 "gvisor.dev/gvisor/test/benchmarks/harness" 26 "gvisor.dev/gvisor/test/benchmarks/tools" 27 "gvisor.dev/gvisor/test/metricsviz" 28 ) 29 30 // All possible operations from redis. Note: "ping" will 31 // run both PING_INLINE and PING_BUILD. 32 var operations []string = []string{ 33 "PING_INLINE", 34 "PING_MBULK", 35 "SET", 36 "GET", 37 "INCR", 38 "LPUSH", 39 "RPUSH", 40 "LPOP", 41 "RPOP", 42 "SADD", 43 "HSET", 44 "SPOP", 45 "LRANGE_100", 46 "LRANGE_300", 47 "LRANGE_500", 48 "LRANGE_600", 49 "MSET", 50 } 51 52 // BenchmarkAllRedisOperations runs redis-benchmark against a redis instance and reports 53 // data in queries per second. Each is reported by named operation (e.g. LPUSH). 54 func BenchmarkAllRedisOperations(b *testing.B) { 55 doBenchmarkRedis(b, operations) 56 } 57 58 // BenchmarkRedisDashboard runs a subset of redis benchmarks for the performance dashboard. 59 func BenchmarkRedis(b *testing.B) { 60 doBenchmarkRedis(b, []string{"SET", "LPUSH", "LRANGE_100"}) 61 } 62 63 func doBenchmarkRedis(b *testing.B, ops []string) { 64 clientMachine, err := harness.GetMachine() 65 if err != nil { 66 b.Fatalf("failed to get machine: %v", err) 67 } 68 defer clientMachine.CleanUp() 69 70 serverMachine, err := harness.GetMachine() 71 if err != nil { 72 b.Fatalf("failed to get machine: %v", err) 73 } 74 defer serverMachine.CleanUp() 75 76 // Redis runs on port 6379 by default. 77 port := 6379 78 ctx := context.Background() 79 server := serverMachine.GetContainer(ctx, b) 80 defer server.CleanUp(ctx) 81 82 // The redis docker container takes no arguments to run a redis server. 83 if err := server.Spawn(ctx, dockerutil.RunOpts{ 84 Image: "benchmarks/redis", 85 Ports: []int{port}, 86 }); err != nil { 87 b.Fatalf("failed to start redis server with: %v", err) 88 } 89 defer metricsviz.FromContainerLogs(ctx, b, server) 90 91 if out, err := server.WaitForOutput(ctx, "Ready to accept connections", 3*time.Second); err != nil { 92 b.Fatalf("failed to start redis server: %v %s", err, out) 93 } 94 95 pinger := clientMachine.GetNativeContainer(ctx, b) 96 defer pinger.CleanUp(ctx) 97 98 out, err := pinger.Run(ctx, dockerutil.RunOpts{ 99 Image: "benchmarks/redis", 100 Links: []string{ 101 server.MakeLink("redis"), 102 }, 103 }, strings.Split("redis-cli -h redis -r 5 -i 1 ping", " ")...) 104 105 if err != nil { 106 b.Fatalf("redis-benchmark failed with: %v", err) 107 } 108 109 if !strings.Contains(strings.ToLower(out), "pong") { 110 b.Fatalf("redis-benchmark failed to start redis server: %s", out) 111 } 112 113 for _, operation := range ops { 114 param := tools.Parameter{ 115 Name: "operation", 116 Value: operation, 117 } 118 name, err := tools.ParametersToName(param) 119 if err != nil { 120 b.Fatalf("Failed to parse paramaters: %v", err) 121 } 122 123 b.Run(name, func(b *testing.B) { 124 redis := tools.Redis{ 125 Operation: operation, 126 } 127 128 // Sometimes, the connection between the redis client and server can be 129 // flaky such that the client returns infinity as the QPS measurement for 130 // a give operation. If this happens, retry the client up to 3 times. 131 out := "inf" 132 for retries := 0; strings.Contains(out, "inf") && retries < 3; retries++ { 133 b.ResetTimer() 134 client := clientMachine.GetNativeContainer(ctx, b) 135 defer client.CleanUp(ctx) 136 137 out, err = client.Run(ctx, dockerutil.RunOpts{ 138 Image: "benchmarks/redis", 139 Links: []string{server.MakeLink("redis")}, 140 }, redis.MakeCmd("redis", port, b.N /*requests*/)...) 141 } 142 143 if err != nil { 144 b.Fatalf("redis-benchmark failed with: %v", err) 145 } 146 147 b.StopTimer() 148 redis.Report(b, out) 149 }) 150 } 151 } 152 153 func TestMain(m *testing.M) { 154 harness.Init() 155 os.Exit(m.Run()) 156 }