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 }