@@ -19,6 +19,9 @@ import (
19
19
"fmt"
20
20
"io"
21
21
"io/ioutil"
22
+ "log"
23
+ "os"
24
+ "runtime/pprof"
22
25
"testing"
23
26
"time"
24
27
@@ -251,6 +254,8 @@ func TestIndexSeeks(t *testing.T) {
251
254
trs , err = sr .FindTraces (context .Background (), params )
252
255
assert .NoError (t , err )
253
256
assert .Equal (t , 6 , len (trs ))
257
+ assert .Equal (t , uint64 (56 ), trs [0 ].Spans [0 ].TraceID .Low )
258
+ assert .Equal (t , uint64 (51 ), trs [5 ].Spans [0 ].TraceID .Low )
254
259
})
255
260
}
256
261
@@ -442,3 +447,183 @@ func runFactoryTest(tb testing.TB, test func(tb testing.TB, sw spanstore.Writer,
442
447
}()
443
448
test (tb , sw , sr )
444
449
}
450
+
451
+ // Benchmarks intended for profiling
452
+
453
+ func writeSpans (sw spanstore.Writer , tags []model.KeyValue , services , operations []string , traces , spans int , high uint64 , tid time.Time ) {
454
+ for i := 0 ; i < traces ; i ++ {
455
+ for j := 0 ; j < spans ; j ++ {
456
+ s := model.Span {
457
+ TraceID : model.TraceID {
458
+ Low : uint64 (i ),
459
+ High : high ,
460
+ },
461
+ SpanID : model .SpanID (j ),
462
+ OperationName : operations [j ],
463
+ Process : & model.Process {
464
+ ServiceName : services [j ],
465
+ },
466
+ Tags : tags ,
467
+ StartTime : tid .Add (time .Duration (time .Millisecond )),
468
+ Duration : time .Duration (time .Millisecond * time .Duration (i + j )),
469
+ }
470
+ _ = sw .WriteSpan (& s )
471
+ }
472
+ }
473
+ }
474
+
475
+ func BenchmarkWrites (b * testing.B ) {
476
+ runFactoryTest (b , func (tb testing.TB , sw spanstore.Writer , sr spanstore.Reader ) {
477
+ tid := time .Now ()
478
+ traces := 1000
479
+ spans := 32
480
+ tagsCount := 64
481
+ tags , services , operations := makeWriteSupports (tagsCount , spans )
482
+
483
+ f , err := os .Create ("writes.out" )
484
+ if err != nil {
485
+ log .Fatal ("could not create CPU profile: " , err )
486
+ }
487
+ if err := pprof .StartCPUProfile (f ); err != nil {
488
+ log .Fatal ("could not start CPU profile: " , err )
489
+ }
490
+ defer pprof .StopCPUProfile ()
491
+
492
+ b .ResetTimer ()
493
+ for a := 0 ; a < b .N ; a ++ {
494
+ writeSpans (sw , tags , services , operations , traces , spans , uint64 (0 ), tid )
495
+ }
496
+ b .StopTimer ()
497
+ })
498
+ }
499
+
500
+ func makeWriteSupports (tagsCount , spans int ) ([]model.KeyValue , []string , []string ) {
501
+ tags := make ([]model.KeyValue , tagsCount )
502
+ for i := 0 ; i < tagsCount ; i ++ {
503
+ tags [i ] = model.KeyValue {
504
+ Key : fmt .Sprintf ("a%d" , i ),
505
+ VStr : fmt .Sprintf ("b%d" , i ),
506
+ }
507
+ }
508
+ operations := make ([]string , spans )
509
+ for j := 0 ; j < spans ; j ++ {
510
+ operations [j ] = fmt .Sprintf ("operation-%d" , j )
511
+ }
512
+ services := make ([]string , spans )
513
+ for i := 0 ; i < spans ; i ++ {
514
+ services [i ] = fmt .Sprintf ("service-%d" , i )
515
+ }
516
+
517
+ return tags , services , operations
518
+ }
519
+
520
+ func makeReadBenchmark (b * testing.B , tid time.Time , params * spanstore.TraceQueryParameters , outputFile string ) {
521
+ runLargeFactoryTest (b , func (tb testing.TB , sw spanstore.Writer , sr spanstore.Reader ) {
522
+ tid := time .Now ()
523
+
524
+ // Total amount of traces is traces * tracesTimes
525
+ traces := 1000
526
+ tracesTimes := 1
527
+
528
+ // Total amount of spans written is traces * tracesTimes * spans
529
+ spans := 32
530
+
531
+ // Default is 160k
532
+
533
+ tagsCount := 64
534
+ tags , services , operations := makeWriteSupports (tagsCount , spans )
535
+
536
+ for h := 0 ; h < tracesTimes ; h ++ {
537
+ writeSpans (sw , tags , services , operations , traces , spans , uint64 (h ), tid )
538
+ }
539
+
540
+ f , err := os .Create (outputFile )
541
+ if err != nil {
542
+ log .Fatal ("could not create CPU profile: " , err )
543
+ }
544
+ if err := pprof .StartCPUProfile (f ); err != nil {
545
+ log .Fatal ("could not start CPU profile: " , err )
546
+ }
547
+ defer pprof .StopCPUProfile ()
548
+
549
+ b .ResetTimer ()
550
+ for a := 0 ; a < b .N ; a ++ {
551
+ sr .FindTraces (context .Background (), params )
552
+ }
553
+ b .StopTimer ()
554
+ })
555
+
556
+ }
557
+
558
+ func BenchmarkServiceTagsRangeQueryLimitIndexFetch (b * testing.B ) {
559
+ tid := time .Now ()
560
+ params := & spanstore.TraceQueryParameters {
561
+ StartTimeMin : tid ,
562
+ StartTimeMax : tid .Add (time .Duration (time .Millisecond * 2000 )),
563
+ ServiceName : "service-1" ,
564
+ Tags : map [string ]string {
565
+ "a8" : "b8" ,
566
+ },
567
+ }
568
+
569
+ params .DurationMin = time .Duration (1 * time .Millisecond ) // durationQuery takes 53% of total execution time..
570
+ params .NumTraces = 50
571
+
572
+ makeReadBenchmark (b , tid , params , "scanrangeandindexlimit.out" )
573
+ }
574
+
575
+ func BenchmarkServiceIndexLimitFetch (b * testing.B ) {
576
+ tid := time .Now ()
577
+ params := & spanstore.TraceQueryParameters {
578
+ StartTimeMin : tid ,
579
+ StartTimeMax : tid .Add (time .Duration (time .Millisecond * 2000 )),
580
+ ServiceName : "service-1" ,
581
+ }
582
+
583
+ params .NumTraces = 50
584
+
585
+ makeReadBenchmark (b , tid , params , "serviceindexlimit.out" )
586
+ }
587
+
588
+ // Opens a badger db and runs a a test on it.
589
+ func runLargeFactoryTest (tb testing.TB , test func (tb testing.TB , sw spanstore.Writer , sr spanstore.Reader )) {
590
+ f := badger .NewFactory ()
591
+ opts := badger .NewOptions ("badger" )
592
+ v , command := config .Viperize (opts .AddFlags )
593
+
594
+ dir := "/mnt/ssd/badger/testRun"
595
+ err := os .MkdirAll (dir , 0700 )
596
+ defer os .RemoveAll (dir )
597
+ assert .NoError (tb , err )
598
+ keyParam := fmt .Sprintf ("--badger.directory-key=%s" , dir )
599
+ valueParam := fmt .Sprintf ("--badger.directory-value=%s" , dir )
600
+
601
+ command .ParseFlags ([]string {
602
+ "--badger.ephemeral=false" ,
603
+ "--badger.consistency=false" , // Consistency is false as default to reduce effect of disk speed
604
+ keyParam ,
605
+ valueParam ,
606
+ })
607
+
608
+ f .InitFromViper (v )
609
+
610
+ err = f .Initialize (metrics .NullFactory , zap .NewNop ())
611
+ assert .NoError (tb , err )
612
+
613
+ sw , err := f .CreateSpanWriter ()
614
+ assert .NoError (tb , err )
615
+
616
+ sr , err := f .CreateSpanReader ()
617
+ assert .NoError (tb , err )
618
+
619
+ defer func () {
620
+ if closer , ok := sw .(io.Closer ); ok {
621
+ err := closer .Close ()
622
+ assert .NoError (tb , err )
623
+ } else {
624
+ tb .FailNow ()
625
+ }
626
+
627
+ }()
628
+ test (tb , sw , sr )
629
+ }
0 commit comments