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  }