Skip to content

Commit 39c16c8

Browse files
kurkomisikaralabe
authored andcommitted
cmd, ethdb, vendor: integrate leveldb iostats (ethereum#16277)
* cmd, dashboard, ethdb, vendor: send iostats to dashboard * ethdb: change names * ethdb: handle parsing errors * ethdb: handle iostats syntax error * ethdb: r -> w
1 parent 4871e25 commit 39c16c8

File tree

11 files changed

+180
-84
lines changed

11 files changed

+180
-84
lines changed

cmd/geth/chaincmd.go

+13
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,13 @@ func importChain(ctx *cli.Context) error {
225225
utils.Fatalf("Failed to read database stats: %v", err)
226226
}
227227
fmt.Println(stats)
228+
229+
ioStats, err := db.LDB().GetProperty("leveldb.iostats")
230+
if err != nil {
231+
utils.Fatalf("Failed to read database iostats: %v", err)
232+
}
233+
fmt.Println(ioStats)
234+
228235
fmt.Printf("Trie cache misses: %d\n", trie.CacheMisses())
229236
fmt.Printf("Trie cache unloads: %d\n\n", trie.CacheUnloads())
230237

@@ -255,6 +262,12 @@ func importChain(ctx *cli.Context) error {
255262
}
256263
fmt.Println(stats)
257264

265+
ioStats, err = db.LDB().GetProperty("leveldb.iostats")
266+
if err != nil {
267+
utils.Fatalf("Failed to read database iostats: %v", err)
268+
}
269+
fmt.Println(ioStats)
270+
258271
return nil
259272
}
260273

dashboard/dashboard.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,8 @@ func (db *Dashboard) collectData() {
270270
prevNetworkEgress = metrics.DefaultRegistry.Get("p2p/OutboundTraffic").(metrics.Meter).Count()
271271
prevProcessCPUTime = getProcessCPUTime()
272272
prevSystemCPUUsage = systemCPUUsage
273-
prevDiskRead = metrics.DefaultRegistry.Get("eth/db/chaindata/compact/input").(metrics.Meter).Count()
274-
prevDiskWrite = metrics.DefaultRegistry.Get("eth/db/chaindata/compact/output").(metrics.Meter).Count()
273+
prevDiskRead = metrics.DefaultRegistry.Get("eth/db/chaindata/disk/read").(metrics.Meter).Count()
274+
prevDiskWrite = metrics.DefaultRegistry.Get("eth/db/chaindata/disk/write").(metrics.Meter).Count()
275275

276276
frequency = float64(db.config.Refresh / time.Second)
277277
numCPU = float64(runtime.NumCPU())
@@ -289,8 +289,8 @@ func (db *Dashboard) collectData() {
289289
curNetworkEgress = metrics.DefaultRegistry.Get("p2p/OutboundTraffic").(metrics.Meter).Count()
290290
curProcessCPUTime = getProcessCPUTime()
291291
curSystemCPUUsage = systemCPUUsage
292-
curDiskRead = metrics.DefaultRegistry.Get("eth/db/chaindata/compact/input").(metrics.Meter).Count()
293-
curDiskWrite = metrics.DefaultRegistry.Get("eth/db/chaindata/compact/output").(metrics.Meter).Count()
292+
curDiskRead = metrics.DefaultRegistry.Get("eth/db/chaindata/disk/read").(metrics.Meter).Count()
293+
curDiskWrite = metrics.DefaultRegistry.Get("eth/db/chaindata/disk/write").(metrics.Meter).Count()
294294

295295
deltaNetworkIngress = float64(curNetworkIngress - prevNetworkIngress)
296296
deltaNetworkEgress = float64(curNetworkEgress - prevNetworkEgress)

ethdb/database.go

+59-43
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,11 @@ type LDBDatabase struct {
3737
fn string // filename for reporting
3838
db *leveldb.DB // LevelDB instance
3939

40-
getTimer metrics.Timer // Timer for measuring the database get request counts and latencies
41-
putTimer metrics.Timer // Timer for measuring the database put request counts and latencies
42-
delTimer metrics.Timer // Timer for measuring the database delete request counts and latencies
43-
missMeter metrics.Meter // Meter for measuring the missed database get requests
44-
readMeter metrics.Meter // Meter for measuring the database get request data usage
45-
writeMeter metrics.Meter // Meter for measuring the database put request data usage
4640
compTimeMeter metrics.Meter // Meter for measuring the total time spent in database compaction
4741
compReadMeter metrics.Meter // Meter for measuring the data read during compaction
4842
compWriteMeter metrics.Meter // Meter for measuring the data written during compaction
43+
diskReadMeter metrics.Meter // Meter for measuring the effective amount of data read
44+
diskWriteMeter metrics.Meter // Meter for measuring the effective amount of data written
4945

5046
quitLock sync.Mutex // Mutex protecting the quit channel access
5147
quitChan chan chan error // Quit channel to stop the metrics collection before closing the database
@@ -94,16 +90,9 @@ func (db *LDBDatabase) Path() string {
9490

9591
// Put puts the given key / value to the queue
9692
func (db *LDBDatabase) Put(key []byte, value []byte) error {
97-
// Measure the database put latency, if requested
98-
if db.putTimer != nil {
99-
defer db.putTimer.UpdateSince(time.Now())
100-
}
10193
// Generate the data to write to disk, update the meter and write
10294
//value = rle.Compress(value)
10395

104-
if db.writeMeter != nil {
105-
db.writeMeter.Mark(int64(len(value)))
106-
}
10796
return db.db.Put(key, value, nil)
10897
}
10998

@@ -113,32 +102,17 @@ func (db *LDBDatabase) Has(key []byte) (bool, error) {
113102

114103
// Get returns the given key if it's present.
115104
func (db *LDBDatabase) Get(key []byte) ([]byte, error) {
116-
// Measure the database get latency, if requested
117-
if db.getTimer != nil {
118-
defer db.getTimer.UpdateSince(time.Now())
119-
}
120105
// Retrieve the key and increment the miss counter if not found
121106
dat, err := db.db.Get(key, nil)
122107
if err != nil {
123-
if db.missMeter != nil {
124-
db.missMeter.Mark(1)
125-
}
126108
return nil, err
127109
}
128-
// Otherwise update the actually retrieved amount of data
129-
if db.readMeter != nil {
130-
db.readMeter.Mark(int64(len(dat)))
131-
}
132110
return dat, nil
133111
//return rle.Decompress(dat)
134112
}
135113

136114
// Delete deletes the key from the queue and database
137115
func (db *LDBDatabase) Delete(key []byte) error {
138-
// Measure the database delete latency, if requested
139-
if db.delTimer != nil {
140-
defer db.delTimer.UpdateSince(time.Now())
141-
}
142116
// Execute the actual operation
143117
return db.db.Delete(key, nil)
144118
}
@@ -178,15 +152,11 @@ func (db *LDBDatabase) Meter(prefix string) {
178152
return
179153
}
180154
// Initialize all the metrics collector at the requested prefix
181-
db.getTimer = metrics.NewRegisteredTimer(prefix+"user/gets", nil)
182-
db.putTimer = metrics.NewRegisteredTimer(prefix+"user/puts", nil)
183-
db.delTimer = metrics.NewRegisteredTimer(prefix+"user/dels", nil)
184-
db.missMeter = metrics.NewRegisteredMeter(prefix+"user/misses", nil)
185-
db.readMeter = metrics.NewRegisteredMeter(prefix+"user/reads", nil)
186-
db.writeMeter = metrics.NewRegisteredMeter(prefix+"user/writes", nil)
187155
db.compTimeMeter = metrics.NewRegisteredMeter(prefix+"compact/time", nil)
188156
db.compReadMeter = metrics.NewRegisteredMeter(prefix+"compact/input", nil)
189157
db.compWriteMeter = metrics.NewRegisteredMeter(prefix+"compact/output", nil)
158+
db.diskReadMeter = metrics.NewRegisteredMeter(prefix+"disk/read", nil)
159+
db.diskWriteMeter = metrics.NewRegisteredMeter(prefix+"disk/write", nil)
190160

191161
// Create a quit channel for the periodic collector and run it
192162
db.quitLock.Lock()
@@ -207,12 +177,17 @@ func (db *LDBDatabase) Meter(prefix string) {
207177
// 1 | 85 | 109.27913 | 28.09293 | 213.92493 | 214.26294
208178
// 2 | 523 | 1000.37159 | 7.26059 | 66.86342 | 66.77884
209179
// 3 | 570 | 1113.18458 | 0.00000 | 0.00000 | 0.00000
180+
//
181+
// This is how the iostats look like (currently):
182+
// Read(MB):3895.04860 Write(MB):3654.64712
210183
func (db *LDBDatabase) meter(refresh time.Duration) {
211-
// Create the counters to store current and previous values
212-
counters := make([][]float64, 2)
184+
// Create the counters to store current and previous compaction values
185+
compactions := make([][]float64, 2)
213186
for i := 0; i < 2; i++ {
214-
counters[i] = make([]float64, 3)
187+
compactions[i] = make([]float64, 3)
215188
}
189+
// Create storage for iostats.
190+
var iostats [2]float64
216191
// Iterate ad infinitum and collect the stats
217192
for i := 1; ; i++ {
218193
// Retrieve the database stats
@@ -233,8 +208,8 @@ func (db *LDBDatabase) meter(refresh time.Duration) {
233208
lines = lines[3:]
234209

235210
// Iterate over all the table rows, and accumulate the entries
236-
for j := 0; j < len(counters[i%2]); j++ {
237-
counters[i%2][j] = 0
211+
for j := 0; j < len(compactions[i%2]); j++ {
212+
compactions[i%2][j] = 0
238213
}
239214
for _, line := range lines {
240215
parts := strings.Split(line, "|")
@@ -247,19 +222,60 @@ func (db *LDBDatabase) meter(refresh time.Duration) {
247222
db.log.Error("Compaction entry parsing failed", "err", err)
248223
return
249224
}
250-
counters[i%2][idx] += value
225+
compactions[i%2][idx] += value
251226
}
252227
}
253228
// Update all the requested meters
254229
if db.compTimeMeter != nil {
255-
db.compTimeMeter.Mark(int64((counters[i%2][0] - counters[(i-1)%2][0]) * 1000 * 1000 * 1000))
230+
db.compTimeMeter.Mark(int64((compactions[i%2][0] - compactions[(i-1)%2][0]) * 1000 * 1000 * 1000))
256231
}
257232
if db.compReadMeter != nil {
258-
db.compReadMeter.Mark(int64((counters[i%2][1] - counters[(i-1)%2][1]) * 1024 * 1024))
233+
db.compReadMeter.Mark(int64((compactions[i%2][1] - compactions[(i-1)%2][1]) * 1024 * 1024))
259234
}
260235
if db.compWriteMeter != nil {
261-
db.compWriteMeter.Mark(int64((counters[i%2][2] - counters[(i-1)%2][2]) * 1024 * 1024))
236+
db.compWriteMeter.Mark(int64((compactions[i%2][2] - compactions[(i-1)%2][2]) * 1024 * 1024))
237+
}
238+
239+
// Retrieve the database iostats.
240+
ioStats, err := db.db.GetProperty("leveldb.iostats")
241+
if err != nil {
242+
db.log.Error("Failed to read database iostats", "err", err)
243+
return
244+
}
245+
parts := strings.Split(ioStats, " ")
246+
if len(parts) < 2 {
247+
db.log.Error("Bad syntax of ioStats", "ioStats", ioStats)
248+
return
262249
}
250+
r := strings.Split(parts[0], ":")
251+
if len(r) < 2 {
252+
db.log.Error("Bad syntax of read entry", "entry", parts[0])
253+
return
254+
}
255+
read, err := strconv.ParseFloat(r[1], 64)
256+
if err != nil {
257+
db.log.Error("Read entry parsing failed", "err", err)
258+
return
259+
}
260+
w := strings.Split(parts[1], ":")
261+
if len(w) < 2 {
262+
db.log.Error("Bad syntax of write entry", "entry", parts[1])
263+
return
264+
}
265+
write, err := strconv.ParseFloat(w[1], 64)
266+
if err != nil {
267+
db.log.Error("Write entry parsing failed", "err", err)
268+
return
269+
}
270+
if db.diskReadMeter != nil {
271+
db.diskReadMeter.Mark(int64((read - iostats[0]) * 1024 * 1024))
272+
}
273+
if db.diskWriteMeter != nil {
274+
db.diskWriteMeter.Mark(int64((write - iostats[1]) * 1024 * 1024))
275+
}
276+
iostats[0] = read
277+
iostats[1] = write
278+
263279
// Sleep a bit, then repeat the stats collection
264280
select {
265281
case errc := <-db.quitChan:

vendor/github.com/syndtr/goleveldb/leveldb/db.go

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/syndtr/goleveldb/leveldb/iterator/iter.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/syndtr/goleveldb/leveldb/memdb/memdb.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/syndtr/goleveldb/leveldb/session.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/syndtr/goleveldb/leveldb/storage.go

+63
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/syndtr/goleveldb/leveldb/storage/file_storage_plan9.go

+1-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/syndtr/goleveldb/leveldb/util/util.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)