Skip to content

Commit 098cc7e

Browse files
authored
ethdb/pebble: expose stall counter of pebble (#31782)
This pull request adds a more Pebble metrics, tracking the amount of write stalls with specific reasons
1 parent fa86416 commit 098cc7e

File tree

1 file changed

+73
-18
lines changed

1 file changed

+73
-18
lines changed

ethdb/pebble/pebble.go

Lines changed: 73 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"bytes"
2222
"fmt"
2323
"runtime"
24+
"strings"
2425
"sync"
2526
"sync/atomic"
2627
"time"
@@ -55,24 +56,35 @@ const (
5556
// Apart from basic data storage functionality it also supports batch writes and
5657
// iterating over the keyspace in binary-alphabetical order.
5758
type Database struct {
58-
fn string // filename for reporting
59-
db *pebble.DB // Underlying pebble storage engine
60-
61-
compTimeMeter *metrics.Meter // Meter for measuring the total time spent in database compaction
62-
compReadMeter *metrics.Meter // Meter for measuring the data read during compaction
63-
compWriteMeter *metrics.Meter // Meter for measuring the data written during compaction
64-
writeDelayNMeter *metrics.Meter // Meter for measuring the write delay number due to database compaction
65-
writeDelayMeter *metrics.Meter // Meter for measuring the write delay duration due to database compaction
66-
diskSizeGauge *metrics.Gauge // Gauge for tracking the size of all the levels in the database
67-
diskReadMeter *metrics.Meter // Meter for measuring the effective amount of data read
68-
diskWriteMeter *metrics.Meter // Meter for measuring the effective amount of data written
69-
memCompGauge *metrics.Gauge // Gauge for tracking the number of memory compaction
70-
level0CompGauge *metrics.Gauge // Gauge for tracking the number of table compaction in level0
71-
nonlevel0CompGauge *metrics.Gauge // Gauge for tracking the number of table compaction in non0 level
72-
seekCompGauge *metrics.Gauge // Gauge for tracking the number of table compaction caused by read opt
73-
manualMemAllocGauge *metrics.Gauge // Gauge for tracking amount of non-managed memory currently allocated
74-
75-
levelsGauge []*metrics.Gauge // Gauge for tracking the number of tables in levels
59+
fn string // filename for reporting
60+
db *pebble.DB // Underlying pebble storage engine
61+
namespace string // Namespace for metrics
62+
63+
compTimeMeter *metrics.Meter // Meter for measuring the total time spent in database compaction
64+
compReadMeter *metrics.Meter // Meter for measuring the data read during compaction
65+
compWriteMeter *metrics.Meter // Meter for measuring the data written during compaction
66+
writeDelayNMeter *metrics.Meter // Meter for measuring the write delay number due to database compaction
67+
writeDelayMeter *metrics.Meter // Meter for measuring the write delay duration due to database compaction
68+
diskSizeGauge *metrics.Gauge // Gauge for tracking the size of all the levels in the database
69+
diskReadMeter *metrics.Meter // Meter for measuring the effective amount of data read
70+
diskWriteMeter *metrics.Meter // Meter for measuring the effective amount of data written
71+
memCompGauge *metrics.Gauge // Gauge for tracking the number of memory compaction
72+
level0CompGauge *metrics.Gauge // Gauge for tracking the number of table compaction in level0
73+
nonlevel0CompGauge *metrics.Gauge // Gauge for tracking the number of table compaction in non0 level
74+
seekCompGauge *metrics.Gauge // Gauge for tracking the number of table compaction caused by read opt
75+
manualMemAllocGauge *metrics.Gauge // Gauge for tracking amount of non-managed memory currently allocated
76+
liveMemTablesGauge *metrics.Gauge // Gauge for tracking the number of live memory tables
77+
zombieMemTablesGauge *metrics.Gauge // Gauge for tracking the number of zombie memory tables
78+
blockCacheHitGauge *metrics.Gauge // Gauge for tracking the number of total hit in the block cache
79+
blockCacheMissGauge *metrics.Gauge // Gauge for tracking the number of total miss in the block cache
80+
tableCacheHitGauge *metrics.Gauge // Gauge for tracking the number of total hit in the table cache
81+
tableCacheMissGauge *metrics.Gauge // Gauge for tracking the number of total miss in the table cache
82+
filterHitGauge *metrics.Gauge // Gauge for tracking the number of total hit in bloom filter
83+
filterMissGauge *metrics.Gauge // Gauge for tracking the number of total miss in bloom filter
84+
estimatedCompDebtGauge *metrics.Gauge // Gauge for tracking the number of bytes that need to be compacted
85+
liveCompGauge *metrics.Gauge // Gauge for tracking the number of in-progress compactions
86+
liveCompSizeGauge *metrics.Gauge // Gauge for tracking the size of in-progress compactions
87+
levelsGauge []*metrics.Gauge // Gauge for tracking the number of tables in levels
7688

7789
quitLock sync.RWMutex // Mutex protecting the quit channel and the closed flag
7890
quitChan chan chan error // Quit channel to stop the metrics collection before closing the database
@@ -88,6 +100,7 @@ type Database struct {
88100

89101
writeStalled atomic.Bool // Flag whether the write is stalled
90102
writeDelayStartTime time.Time // The start time of the latest write stall
103+
writeDelayReason string // The reason of the latest write stall
91104
writeDelayCount atomic.Int64 // Total number of write stall counts
92105
writeDelayTime atomic.Int64 // Total time spent in write stalls
93106

@@ -120,11 +133,30 @@ func (d *Database) onWriteStallBegin(b pebble.WriteStallBeginInfo) {
120133
d.writeDelayStartTime = time.Now()
121134
d.writeDelayCount.Add(1)
122135
d.writeStalled.Store(true)
136+
137+
// Take just the first word of the reason. These are two potential
138+
// reasons for the write stall:
139+
// - memtable count limit reached
140+
// - L0 file count limit exceeded
141+
reason := b.Reason
142+
if i := strings.IndexByte(reason, ' '); i != -1 {
143+
reason = reason[:i]
144+
}
145+
if reason == "L0" || reason == "memtable" {
146+
d.writeDelayReason = reason
147+
metrics.GetOrRegisterGauge(d.namespace+"stall/count/"+reason, nil).Inc(1)
148+
}
123149
}
124150

125151
func (d *Database) onWriteStallEnd() {
126152
d.writeDelayTime.Add(int64(time.Since(d.writeDelayStartTime)))
127153
d.writeStalled.Store(false)
154+
155+
if d.writeDelayReason != "" {
156+
metrics.GetOrRegisterResettingTimer(d.namespace+"stall/time/"+d.writeDelayReason, nil).UpdateSince(d.writeDelayStartTime)
157+
d.writeDelayReason = ""
158+
}
159+
d.writeDelayStartTime = time.Time{}
128160
}
129161

130162
// panicLogger is just a noop logger to disable Pebble's internal logger.
@@ -270,6 +302,17 @@ func New(file string, cache int, handles int, namespace string, readonly bool) (
270302
db.nonlevel0CompGauge = metrics.GetOrRegisterGauge(namespace+"compact/nonlevel0", nil)
271303
db.seekCompGauge = metrics.GetOrRegisterGauge(namespace+"compact/seek", nil)
272304
db.manualMemAllocGauge = metrics.GetOrRegisterGauge(namespace+"memory/manualalloc", nil)
305+
db.liveMemTablesGauge = metrics.GetOrRegisterGauge(namespace+"table/live", nil)
306+
db.zombieMemTablesGauge = metrics.GetOrRegisterGauge(namespace+"table/zombie", nil)
307+
db.blockCacheHitGauge = metrics.GetOrRegisterGauge(namespace+"cache/block/hit", nil)
308+
db.blockCacheMissGauge = metrics.GetOrRegisterGauge(namespace+"cache/block/miss", nil)
309+
db.tableCacheHitGauge = metrics.GetOrRegisterGauge(namespace+"cache/table/hit", nil)
310+
db.tableCacheMissGauge = metrics.GetOrRegisterGauge(namespace+"cache/table/miss", nil)
311+
db.filterHitGauge = metrics.GetOrRegisterGauge(namespace+"filter/hit", nil)
312+
db.filterMissGauge = metrics.GetOrRegisterGauge(namespace+"filter/miss", nil)
313+
db.estimatedCompDebtGauge = metrics.GetOrRegisterGauge(namespace+"compact/estimateDebt", nil)
314+
db.liveCompGauge = metrics.GetOrRegisterGauge(namespace+"compact/live/count", nil)
315+
db.liveCompSizeGauge = metrics.GetOrRegisterGauge(namespace+"compact/live/size", nil)
273316

274317
// Start up the metrics gathering and return
275318
go db.meter(metricsGatheringInterval, namespace)
@@ -517,6 +560,18 @@ func (d *Database) meter(refresh time.Duration, namespace string) {
517560
d.nonlevel0CompGauge.Update(nonLevel0CompCount)
518561
d.level0CompGauge.Update(level0CompCount)
519562
d.seekCompGauge.Update(stats.Compact.ReadCount)
563+
d.liveCompGauge.Update(stats.Compact.NumInProgress)
564+
d.liveCompSizeGauge.Update(stats.Compact.InProgressBytes)
565+
566+
d.liveMemTablesGauge.Update(stats.MemTable.Count)
567+
d.zombieMemTablesGauge.Update(stats.MemTable.ZombieCount)
568+
d.estimatedCompDebtGauge.Update(int64(stats.Compact.EstimatedDebt))
569+
d.tableCacheHitGauge.Update(stats.TableCache.Hits)
570+
d.tableCacheMissGauge.Update(stats.TableCache.Misses)
571+
d.blockCacheHitGauge.Update(stats.BlockCache.Hits)
572+
d.blockCacheMissGauge.Update(stats.BlockCache.Misses)
573+
d.filterHitGauge.Update(stats.Filter.Hits)
574+
d.filterMissGauge.Update(stats.Filter.Misses)
520575

521576
for i, level := range stats.Levels {
522577
// Append metrics for additional layers

0 commit comments

Comments
 (0)