github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/cmd/pebble/sync.go (about)

     1  // Copyright 2018 The LevelDB-Go and Pebble Authors. All rights reserved. Use
     2  // of this source code is governed by a BSD-style license that can be found in
     3  // the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"fmt"
     9  	"log"
    10  	"sync"
    11  	"sync/atomic"
    12  	"time"
    13  
    14  	"github.com/cockroachdb/pebble"
    15  	"github.com/cockroachdb/pebble/internal/randvar"
    16  	"github.com/spf13/cobra"
    17  	"golang.org/x/exp/rand"
    18  )
    19  
    20  var syncConfig struct {
    21  	batch   *randvar.Flag
    22  	walOnly bool
    23  	values  *randvar.BytesFlag
    24  }
    25  
    26  var syncCmd = &cobra.Command{
    27  	Use:   "sync <dir>",
    28  	Short: "run the sync benchmark",
    29  	Long:  ``,
    30  	Args:  cobra.ExactArgs(1),
    31  	Run:   runSync,
    32  }
    33  
    34  func init() {
    35  	syncConfig.batch = randvar.NewFlag("5")
    36  	syncCmd.Flags().Var(
    37  		syncConfig.batch, "batch",
    38  		"batch size distribution [{zipf,uniform}:]min[-max]")
    39  	syncCmd.Flags().BoolVar(
    40  		&syncConfig.walOnly, "wal-only", false, "write data only to the WAL")
    41  	syncConfig.values = randvar.NewBytesFlag("uniform:60-80/1.0")
    42  	syncCmd.Flags().Var(
    43  		syncConfig.values, "values",
    44  		"value size distribution [{zipf,uniform}:]min[-max][/<target-compression>]")
    45  }
    46  
    47  func runSync(cmd *cobra.Command, args []string) {
    48  	reg := newHistogramRegistry()
    49  	var bytes atomic.Uint64
    50  	var lastBytes uint64
    51  
    52  	opts := pebble.Sync
    53  	if disableWAL {
    54  		opts = pebble.NoSync
    55  	}
    56  
    57  	batchDist := syncConfig.batch
    58  
    59  	runTest(args[0], test{
    60  		init: func(d DB, wg *sync.WaitGroup) {
    61  			limiter := maxOpsPerSec.newRateLimiter()
    62  
    63  			wg.Add(concurrency)
    64  			for i := 0; i < concurrency; i++ {
    65  				latency := reg.Register("ops")
    66  				go func() {
    67  					defer wg.Done()
    68  
    69  					rand := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
    70  					var raw []byte
    71  					var buf []byte
    72  					var block []byte
    73  					for {
    74  						wait(limiter)
    75  
    76  						start := time.Now()
    77  						b := d.NewBatch()
    78  						var n uint64
    79  						count := int(batchDist.Uint64(rand))
    80  						for j := 0; j < count; j++ {
    81  							block = syncConfig.values.Bytes(rand, block)
    82  
    83  							if syncConfig.walOnly {
    84  								if err := b.LogData(block, nil); err != nil {
    85  									log.Fatal(err)
    86  								}
    87  							} else {
    88  								raw = encodeUint32Ascending(raw[:0], rand.Uint32())
    89  								key := mvccEncode(buf[:0], raw, 0, 0)
    90  								buf = key[:0]
    91  								if err := b.Set(key, block, nil); err != nil {
    92  									log.Fatal(err)
    93  								}
    94  							}
    95  							n += uint64(len(block))
    96  						}
    97  						if err := b.Commit(opts); err != nil {
    98  							log.Fatal(err)
    99  						}
   100  						latency.Record(time.Since(start))
   101  						bytes.Add(n)
   102  					}
   103  				}()
   104  			}
   105  		},
   106  
   107  		tick: func(elapsed time.Duration, i int) {
   108  			if i%20 == 0 {
   109  				fmt.Println("_elapsed____ops/sec___mb/sec__p50(ms)__p95(ms)__p99(ms)_pMax(ms)")
   110  			}
   111  			reg.Tick(func(tick histogramTick) {
   112  				h := tick.Hist
   113  				n := bytes.Load()
   114  				fmt.Printf("%8s %10.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n",
   115  					time.Duration(elapsed.Seconds()+0.5)*time.Second,
   116  					float64(h.TotalCount())/tick.Elapsed.Seconds(),
   117  					float64(n-lastBytes)/(1024.0*1024.0)/tick.Elapsed.Seconds(),
   118  					time.Duration(h.ValueAtQuantile(50)).Seconds()*1000,
   119  					time.Duration(h.ValueAtQuantile(95)).Seconds()*1000,
   120  					time.Duration(h.ValueAtQuantile(99)).Seconds()*1000,
   121  					time.Duration(h.ValueAtQuantile(100)).Seconds()*1000,
   122  				)
   123  				lastBytes = n
   124  			})
   125  		},
   126  
   127  		done: func(elapsed time.Duration) {
   128  			fmt.Println("\n_elapsed___ops(total)_ops/sec(cum)_mb/sec(cum)__avg(ms)__p50(ms)__p95(ms)__p99(ms)_pMax(ms)")
   129  			reg.Tick(func(tick histogramTick) {
   130  				h := tick.Cumulative
   131  				fmt.Printf("%7.1fs %12d %12.1f %11.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n\n",
   132  					elapsed.Seconds(), h.TotalCount(),
   133  					float64(h.TotalCount())/elapsed.Seconds(),
   134  					float64(bytes.Load()/(1024.0*1024.0))/elapsed.Seconds(),
   135  					time.Duration(h.Mean()).Seconds()*1000,
   136  					time.Duration(h.ValueAtQuantile(50)).Seconds()*1000,
   137  					time.Duration(h.ValueAtQuantile(95)).Seconds()*1000,
   138  					time.Duration(h.ValueAtQuantile(99)).Seconds()*1000,
   139  					time.Duration(h.ValueAtQuantile(100)).Seconds()*1000)
   140  			})
   141  		},
   142  	})
   143  }