go.ligato.io/vpp-agent/v3@v3.5.0/plugins/kvscheduler/bench_test.go (about) 1 // Copyright (c) 2019 Cisco and/or its affiliates. 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 kvscheduler_test 16 17 import ( 18 "context" 19 "flag" 20 "fmt" 21 "strconv" 22 "testing" 23 24 "go.ligato.io/cn-infra/v2/logging" 25 _ "go.ligato.io/cn-infra/v2/logging/logrus" // for setting default registry 26 27 mock_ifplugin "go.ligato.io/vpp-agent/v3/examples/kvscheduler/mock_plugins/ifplugin" 28 "go.ligato.io/vpp-agent/v3/examples/kvscheduler/mock_plugins/ifplugin/model" 29 mock_l2plugin "go.ligato.io/vpp-agent/v3/examples/kvscheduler/mock_plugins/l2plugin" 30 "go.ligato.io/vpp-agent/v3/examples/kvscheduler/mock_plugins/l2plugin/model" 31 "go.ligato.io/vpp-agent/v3/pkg/models" 32 . "go.ligato.io/vpp-agent/v3/plugins/kvscheduler" 33 . "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" 34 ) 35 36 /* 37 ------------------------ 38 KVScheduler benchmarks 39 ------------------------ 40 - starts scheduler together with mocked ifplugin and l2plugin 41 - configures 1/10/100/1000 number of interfaces with bridge domain 42 43 How to run: 44 - build test binary `go test -c` 45 - run all benchmarks: `./kvscheduler.test -test.run=XXX -test.bench=.` 46 - with CPU profile: `./kvscheduler.test -test.run=XXX -test.bench=. -test.cpuprofile=cpu.out` 47 - analyze profile: `go tool pprof cpu.out` 48 - with mem profile: `./kvscheduler.test -test.run=XXX -test.bench=. -memprofile mem.out` 49 - analyze profile: `go tool pprof -alloc_space mem.out` 50 - with trace profile: `./kvscheduler.test -test.run=XXX -test.bench=. -trace trace.out` 51 - analyze profile: `go tool trace -http=:6060 trace.out` 52 53 */ 54 55 func BenchmarkScale(b *testing.B) { 56 benchmarkScale(b, true) 57 } 58 59 func BenchmarkScaleWithoutSimulation(b *testing.B) { 60 benchmarkScale(b, false) 61 } 62 63 func benchmarkScale(b *testing.B, withSimulation bool) { 64 for _, n := range [...]int{1, 10, 100, 1000} { 65 b.Run(strconv.Itoa(n), func(b *testing.B) { 66 b.ResetTimer() 67 for i := 0; i < b.N; i++ { 68 err := runScale(n, withSimulation) 69 if err != nil { 70 b.Fatal(err) 71 } 72 } 73 }) 74 } 75 } 76 77 // result should be saved to global variable to prevent compiler optimization 78 var seqNum uint64 79 80 func runScale(n int, withSimulation bool) error { 81 c := setupScale() 82 defer teardownScale(c) 83 84 // run non-resync transaction against empty SB 85 txn := c.scheduler.StartNBTransaction() 86 87 // create single bridge domain 88 valBd := &mock_l2.BridgeDomain{ 89 Name: fmt.Sprintf("bd-%d", 1), 90 } 91 // create n interfaces for bridge domain 92 for i := 0; i < n; i++ { 93 valIface := &mock_interfaces.Interface{ 94 Name: fmt.Sprintf("iface-%d", i), 95 Type: mock_interfaces.Interface_LOOPBACK, 96 } 97 valBd.Interfaces = append(valBd.Interfaces, &mock_l2.BridgeDomain_Interface{ 98 Name: valIface.Name, 99 }) 100 txn.SetValue(models.Key(valIface), valIface) 101 } 102 txn.SetValue(models.Key(valBd), valBd) 103 104 testCtx := context.Background() 105 if withSimulation { 106 testCtx = WithSimulation(testCtx) 107 } 108 seq, err := txn.Commit(WithDescription(testCtx, "benchmarking scale")) 109 if err != nil { 110 return err 111 } 112 113 seqNum = seq 114 115 return err 116 } 117 118 func setupScale() *runCtx { 119 // prepare run context 120 c := newRunCtx() 121 if err := c.Init(); err != nil { 122 panic(err) 123 } 124 return c 125 } 126 127 func teardownScale(c *runCtx) { 128 if err := c.Close(); err != nil { 129 panic(err) 130 } 131 } 132 133 type runCtx struct { 134 scheduler *Scheduler 135 IfPlugin *mock_ifplugin.IfPlugin 136 L2Plugin *mock_l2plugin.L2Plugin 137 } 138 139 func newRunCtx() *runCtx { 140 c := &runCtx{} 141 c.scheduler = NewPlugin(UseDeps(func(deps *Deps) { 142 deps.HTTPHandlers = nil 143 })) 144 c.IfPlugin = mock_ifplugin.NewPlugin(mock_ifplugin.UseDeps( 145 func(deps *mock_ifplugin.Deps) { 146 deps.KVScheduler = c.scheduler 147 })) 148 c.L2Plugin = mock_l2plugin.NewPlugin(mock_l2plugin.UseDeps( 149 func(deps *mock_l2plugin.Deps) { 150 deps.KVScheduler = c.scheduler 151 })) 152 return c 153 } 154 155 func (c *runCtx) Init() error { 156 if err := c.scheduler.Init(); err != nil { 157 return err 158 } 159 if err := c.IfPlugin.Init(); err != nil { 160 return err 161 } 162 if err := c.L2Plugin.Init(); err != nil { 163 return err 164 } 165 return nil 166 } 167 168 func (c *runCtx) Close() error { 169 if err := c.L2Plugin.Close(); err != nil { 170 return err 171 } 172 if err := c.IfPlugin.Close(); err != nil { 173 return err 174 } 175 if err := c.scheduler.Close(); err != nil { 176 return err 177 } 178 logging.DefaultRegistry.ClearRegistry() 179 return nil 180 } 181 182 var scaleFlag = flag.Int("scale", 10, "number of items for scale test") 183 184 func TestScale(t *testing.T) { 185 if err := runScale(*scaleFlag, true); err != nil { 186 t.Fatal(err) 187 } 188 }