github.com/matrixorigin/matrixone@v1.2.0/pkg/util/trace/impl/motrace/mo_trace_bench_test.go (about) 1 // Copyright 2023 Matrix Origin 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 motrace 16 17 import ( 18 "context" 19 "math/rand" 20 "sync" 21 "testing" 22 23 "github.com/matrixorigin/matrixone/pkg/util/trace" 24 ) 25 26 // BenchmarkMOSpan_1kFree 27 // BenchmarkMOSpan_1kFree/empty 28 // BenchmarkMOSpan_1kFree/empty-10 111921 10699 ns/op 29 // BenchmarkMOSpan_1kFree/just_apply 30 // BenchmarkMOSpan_1kFree/just_apply-10 6447 173771 ns/op 31 // BenchmarkMOSpan_1kFree/goroutine 32 // BenchmarkMOSpan_1kFree/goroutine-10 2029 606984 ns/op 33 // BenchmarkMOSpan_1kFree/sync 34 // BenchmarkMOSpan_1kFree/sync-10 10000 115171 ns/op 35 // BenchmarkMOSpan_1kFree/channel 36 // BenchmarkMOSpan_1kFree/channel-10 4363 278533 ns/op 37 // BenchmarkMOSpan_1kFree/lock_free_queue 38 // BenchmarkMOSpan_1kFree/lock_free_queue-10 1045 1155037 ns/op 39 // 40 // with 100 goroutine 41 // BenchmarkMOSpan_1kFree/empty_multi 42 // BenchmarkMOSpan_1kFree/empty_multi-10 224 5092005 ns/op 43 // BenchmarkMOSpan_1kFree/just_apply_multi 44 // BenchmarkMOSpan_1kFree/just_apply_multi-10 69 16713981 ns/op 45 // BenchmarkMOSpan_1kFree/goroutine_multi 46 // BenchmarkMOSpan_1kFree/goroutine_multi-10 33 35532263 ns/op 47 // BenchmarkMOSpan_1kFree/sync_multi 48 // BenchmarkMOSpan_1kFree/sync_multi-10 74 15893255 ns/op 49 // BenchmarkMOSpan_1kFree/channel_multi 50 // BenchmarkMOSpan_1kFree/channel_multi-10 39 40667865 ns/op 51 func BenchmarkMOSpan_1kFree(b *testing.B) { 52 53 p := newMOTracerProvider(WithFSWriterFactory(&dummyFileWriterFactory{}), EnableTracer(true)) 54 tracer := p.Tracer("test").(*MOTracer) 55 ctx, cancel := context.WithCancel(context.TODO()) 56 defer cancel() 57 58 type mospanChan struct { 59 ch chan *MOSpan 60 } 61 62 benchmarks := []struct { 63 name string 64 prepare func(wg *sync.WaitGroup, eventCnt int) any 65 op func(wg *sync.WaitGroup, eventCnt int, param any) 66 }{ 67 { 68 name: "empty", 69 op: func(wg *sync.WaitGroup, eventCnt int, param any) { 70 for i := 0; i < eventCnt; i++ { 71 wg.Done() 72 } 73 }, 74 }, 75 { 76 name: "just_apply", 77 op: func(wg *sync.WaitGroup, eventCnt int, param any) { 78 for i := 0; i < eventCnt; i++ { 79 tracer.Start(ctx, "span") 80 wg.Done() 81 } 82 }, 83 }, 84 { 85 name: "goroutine", 86 op: func(wg *sync.WaitGroup, eventCnt int, param any) { 87 for i := 0; i < eventCnt; i++ { 88 _, span := tracer.Start(ctx, "span") 89 go func() { 90 span.(*MOSpan).Free() 91 wg.Done() 92 }() 93 } 94 }, 95 }, 96 { 97 name: "sync", 98 op: func(wg *sync.WaitGroup, eventCnt int, param any) { 99 for i := 0; i < eventCnt; i++ { 100 _, span := tracer.Start(ctx, "span") 101 span.(*MOSpan).Free() 102 wg.Done() 103 } 104 }, 105 }, 106 { 107 name: "channel", 108 prepare: func(wg *sync.WaitGroup, eventCnt int) any { 109 c := &mospanChan{make(chan *MOSpan, eventCnt)} 110 go func() { 111 loop: 112 for { 113 select { 114 case <-ctx.Done(): 115 break loop 116 case s := <-c.ch: 117 s.Free() 118 wg.Done() 119 } 120 } 121 }() 122 return c 123 }, 124 op: func(wg *sync.WaitGroup, eventCnt int, param any) { 125 eventC, _ := param.(*mospanChan) 126 127 for i := 0; i < eventCnt; i++ { 128 _, span := tracer.Start(ctx, "span") 129 eventC.ch <- span.(*MOSpan) 130 } 131 }, 132 }, 133 /*{ 134 name: "lock_free_queue", 135 prepare: func(wg *sync.WaitGroup, eventCnt int) any { 136 q := queue.NewQueue(uint32(eventCnt)) 137 elems := make([]interface{}, 100) 138 var gets, remain uint32 139 go func() { 140 for { 141 if gets, remain = q.Gets(elems); gets > 0 { 142 for i := uint32(0); i < gets; i++ { 143 elems[i].(*MOSpan).Free() 144 wg.Done() 145 } 146 } 147 if remain > 0 { 148 continue 149 } else { 150 time.Sleep(time.Millisecond) 151 } 152 } 153 }() 154 return q 155 }, 156 op: func(wg *sync.WaitGroup, eventCnt int, param any) { 157 q, _ := param.(*queue.EsQueue) 158 159 for i := 0; i < eventCnt; i++ { 160 _, span := tracer.Start(ctx, "span") 161 q.Put(span) 162 } 163 }, 164 },*/ 165 } 166 167 var wg sync.WaitGroup 168 169 eventCnt := 1_000 170 171 for _, bm := range benchmarks { 172 b.Run(bm.name, func(b *testing.B) { 173 prepare := func(wg *sync.WaitGroup, eventCnt int) any { 174 return nil 175 } 176 if bm.prepare != nil { 177 prepare = bm.prepare 178 } 179 param := prepare(&wg, eventCnt) 180 b.ResetTimer() 181 for i := 0; i < b.N; i++ { 182 wg.Add(eventCnt) 183 go bm.op(&wg, eventCnt, param) 184 wg.Wait() 185 } 186 }) 187 } 188 for _, bm := range benchmarks { 189 190 worker := 100 191 totalEvent := eventCnt * worker 192 b.Run(bm.name+"_multi", func(b *testing.B) { 193 prepare := func(wg *sync.WaitGroup, eventCnt int) any { 194 return nil 195 } 196 if bm.prepare != nil { 197 prepare = bm.prepare 198 } 199 param := prepare(&wg, totalEvent) 200 b.ResetTimer() 201 for i := 0; i < b.N; i++ { 202 wg.Add(totalEvent) 203 for j := 0; j < worker; j++ { 204 go bm.op(&wg, eventCnt, param) 205 } 206 wg.Wait() 207 } 208 }) 209 } 210 } 211 212 // BenchmarkMOSpan_ApplyOneAndFree/empty 213 // BenchmarkMOSpan_ApplyOneAndFree/empty-10 4520266 290.6 ns/op 214 // BenchmarkMOSpan_ApplyOneAndFree/apply 215 // BenchmarkMOSpan_ApplyOneAndFree/apply-10 3541989 346.5 ns/op 216 // BenchmarkMOSpan_ApplyOneAndFree/applyNewAndFree 217 // BenchmarkMOSpan_ApplyOneAndFree/applyNewAndFree-10 3931137 354.3 ns/op 218 // BenchmarkMOSpan_ApplyOneAndFree/prepare1000ApplyAndFree 219 // BenchmarkMOSpan_ApplyOneAndFree/prepare1000ApplyAndFree-10 3546651 339.8 ns/op 220 // BenchmarkMOSpan_ApplyOneAndFree/apply_after 221 // BenchmarkMOSpan_ApplyOneAndFree/apply_after-10 3559951 370.3 ns/op 222 func BenchmarkMOSpan_ApplyOneAndFree(b *testing.B) { 223 224 p := newMOTracerProvider(WithFSWriterFactory(&dummyFileWriterFactory{}), EnableTracer(true)) 225 tracer := p.Tracer("test").(*MOTracer) 226 ctx, cancel := context.WithCancel(context.TODO()) 227 defer cancel() 228 229 benchmarks := []struct { 230 name string 231 prepare func(wg *sync.WaitGroup, eventCnt int) any 232 op func(wg *sync.WaitGroup, eventCnt int, param any) 233 }{ 234 { 235 name: "empty", 236 op: func(wg *sync.WaitGroup, eventCnt int, param any) { 237 }, 238 }, 239 { 240 name: "apply", 241 op: func(wg *sync.WaitGroup, eventCnt int, param any) { 242 tracer.Start(ctx, "span") 243 }, 244 }, 245 { 246 name: "applyNewAndFree", 247 op: func(wg *sync.WaitGroup, eventCnt int, param any) { 248 for i := 0; i < eventCnt; i++ { 249 _, span := tracer.Start(ctx, "span") 250 span.(*MOSpan).Free() 251 } 252 }, 253 }, 254 { 255 name: "prepare1000ApplyAndFree", 256 prepare: func(wg *sync.WaitGroup, _ int) any { 257 eventCnt := 1_000 // reset cnt 258 for i := 0; i < eventCnt; i++ { 259 _, span := tracer.Start(ctx, "span") 260 span.(*MOSpan).Free() 261 } 262 return nil 263 }, 264 op: func(wg *sync.WaitGroup, eventCnt int, param any) { 265 _, span := tracer.Start(ctx, "span") 266 defer span.(*MOSpan).Free() 267 }, 268 }, 269 { 270 name: "apply_after", 271 op: func(wg *sync.WaitGroup, eventCnt int, param any) { 272 tracer.Start(ctx, "span") 273 }, 274 }, 275 } 276 277 var wg sync.WaitGroup 278 279 eventCnt := 1 280 281 for _, bm := range benchmarks { 282 b.Run(bm.name, func(b *testing.B) { 283 prepare := func(wg *sync.WaitGroup, eventCnt int) any { 284 return nil 285 } 286 if bm.prepare != nil { 287 prepare = bm.prepare 288 } 289 param := prepare(&wg, eventCnt) 290 b.ResetTimer() 291 for i := 0; i < b.N; i++ { 292 go bm.op(&wg, eventCnt, param) 293 } 294 }) 295 } 296 } 297 298 func dummyReturnNilEndFuncNoCtxValue( 299 ctx context.Context, 300 ) ( 301 _ context.Context, 302 end func(), 303 ) { 304 return ctx, nil 305 } 306 307 func dummyReturnNilEndFunc( 308 ctx context.Context, 309 ) ( 310 _ context.Context, 311 end func(), 312 ) { 313 return ctx, nil 314 } 315 316 func dummyReturnEmptyEndFunc( 317 ctx context.Context, 318 ) ( 319 _ context.Context, 320 end func(), 321 ) { 322 return ctx, func() {} 323 } 324 325 func BenchmarkMOSpan_if_vs_for(b *testing.B) { 326 327 ctx := context.TODO() 328 329 benchmarks := []struct { 330 name string 331 prepare func(arrF []func()) []func() 332 }{ 333 { 334 name: "if_check_nil_no_ctx_value", 335 prepare: func(arrF []func()) []func() { 336 _, end := dummyReturnNilEndFuncNoCtxValue(ctx) 337 if end != nil { 338 return append(arrF, end) 339 } 340 return arrF 341 }, 342 }, 343 { 344 name: "if_check_nil", 345 prepare: func(arrF []func()) []func() { 346 _, end := dummyReturnNilEndFunc(ctx) 347 if end != nil { 348 return append(arrF, end) 349 } 350 return arrF 351 }, 352 }, 353 { 354 name: "for_empty_end", 355 prepare: func(arrF []func()) []func() { 356 _, end := dummyReturnEmptyEndFunc(ctx) 357 return append(arrF, end) 358 }, 359 }, 360 } 361 362 eventCnt := rand.Intn(10) + 1 363 var arrF = make([]func(), 0, eventCnt) 364 b.Logf("eventCnt: %d", eventCnt) 365 366 for _, bm := range benchmarks { 367 b.Run(bm.name, func(b *testing.B) { 368 b.ResetTimer() 369 for i := 0; i < b.N; i++ { 370 arrF = arrF[:0] 371 for j := 0; j < eventCnt; j++ { 372 arrF = bm.prepare(arrF) 373 } 374 for _, f := range arrF { 375 f() 376 } 377 } 378 }) 379 } 380 } 381 382 func BenchmarkMOTracer_WithOpts_vs_WithoutOpts(b *testing.B) { 383 tracer := &MOTracer{ 384 TracerConfig: trace.TracerConfig{Name: "motrace_test"}, 385 provider: defaultMOTracerProvider(), 386 } 387 tracer.provider.enable = true 388 389 trace.InitMOCtledSpan() 390 trace.SetMoCtledSpanState("local", true, 0) 391 392 b.Run("enable with opts", func(b *testing.B) { 393 for i := 0; i < b.N; i++ { 394 tracer.IsEnable(trace.WithKind(trace.SpanKindLocalFSVis)) 395 } 396 }) 397 398 b.Run("enable without opts", func(b *testing.B) { 399 for i := 0; i < b.N; i++ { 400 tracer.IsEnable() 401 } 402 }) 403 404 b.Run("total with opts", func(b *testing.B) { 405 for i := 0; i < b.N; i++ { 406 _, span := tracer.Start(context.Background(), "test", trace.WithKind( 407 trace.SpanKindLocalFSVis)) 408 span.End(trace.WithFSReadWriteExtra("xxx", nil, 0)) 409 } 410 }) 411 412 b.Run("total without opts", func(b *testing.B) { 413 for i := 0; i < b.N; i++ { 414 _, span := tracer.Start(context.Background(), "test") 415 span.End() 416 } 417 }) 418 }