Skip to content

Commit 90d2551

Browse files
authored
core, eth: merge snap-sync chain download progress logs (#26676)
1 parent 7d4db69 commit 90d2551

File tree

9 files changed

+106
-42
lines changed

9 files changed

+106
-42
lines changed

core/blockchain.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1278,7 +1278,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
12781278
if stats.ignored > 0 {
12791279
context = append(context, []interface{}{"ignored", stats.ignored}...)
12801280
}
1281-
log.Info("Imported new block receipts", context...)
1281+
log.Debug("Imported new block receipts", context...)
12821282

12831283
return 0, nil
12841284
}

core/headerchain.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, start time.Time,
389389
if res.ignored > 0 {
390390
context = append(context, []interface{}{"ignored", res.ignored}...)
391391
}
392-
log.Info("Imported new block headers", context...)
392+
log.Debug("Imported new block headers", context...)
393393
return res.status, err
394394
}
395395

core/rawdb/accessors_chain.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import (
3737
func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash {
3838
var data []byte
3939
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
40-
data, _ = reader.Ancient(chainFreezerHashTable, number)
40+
data, _ = reader.Ancient(ChainFreezerHashTable, number)
4141
if len(data) == 0 {
4242
// Get it by hash from leveldb
4343
data, _ = db.Get(headerHashKey(number))
@@ -334,7 +334,7 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu
334334
}
335335
// read remaining from ancients
336336
max := count * 700
337-
data, err := db.AncientRange(chainFreezerHeaderTable, i+1-count, count, max)
337+
data, err := db.AncientRange(ChainFreezerHeaderTable, i+1-count, count, max)
338338
if err == nil && uint64(len(data)) == count {
339339
// the data is on the order [h, h+1, .., n] -- reordering needed
340340
for i := range data {
@@ -351,7 +351,7 @@ func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValu
351351
// First try to look up the data in ancient database. Extra hash
352352
// comparison is necessary since ancient database only maintains
353353
// the canonical data.
354-
data, _ = reader.Ancient(chainFreezerHeaderTable, number)
354+
data, _ = reader.Ancient(ChainFreezerHeaderTable, number)
355355
if len(data) > 0 && crypto.Keccak256Hash(data) == hash {
356356
return nil
357357
}
@@ -427,7 +427,7 @@ func deleteHeaderWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number
427427
// isCanon is an internal utility method, to check whether the given number/hash
428428
// is part of the ancient (canon) set.
429429
func isCanon(reader ethdb.AncientReaderOp, number uint64, hash common.Hash) bool {
430-
h, err := reader.Ancient(chainFreezerHashTable, number)
430+
h, err := reader.Ancient(ChainFreezerHashTable, number)
431431
if err != nil {
432432
return false
433433
}
@@ -443,7 +443,7 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue
443443
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
444444
// Check if the data is in ancients
445445
if isCanon(reader, number, hash) {
446-
data, _ = reader.Ancient(chainFreezerBodiesTable, number)
446+
data, _ = reader.Ancient(ChainFreezerBodiesTable, number)
447447
return nil
448448
}
449449
// If not, try reading from leveldb
@@ -458,7 +458,7 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue
458458
func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue {
459459
var data []byte
460460
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
461-
data, _ = reader.Ancient(chainFreezerBodiesTable, number)
461+
data, _ = reader.Ancient(ChainFreezerBodiesTable, number)
462462
if len(data) > 0 {
463463
return nil
464464
}
@@ -526,7 +526,7 @@ func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
526526
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
527527
// Check if the data is in ancients
528528
if isCanon(reader, number, hash) {
529-
data, _ = reader.Ancient(chainFreezerDifficultyTable, number)
529+
data, _ = reader.Ancient(ChainFreezerDifficultyTable, number)
530530
return nil
531531
}
532532
// If not, try reading from leveldb
@@ -586,7 +586,7 @@ func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawVa
586586
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
587587
// Check if the data is in ancients
588588
if isCanon(reader, number, hash) {
589-
data, _ = reader.Ancient(chainFreezerReceiptTable, number)
589+
data, _ = reader.Ancient(ChainFreezerReceiptTable, number)
590590
return nil
591591
}
592592
// If not, try reading from leveldb
@@ -787,19 +787,19 @@ func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts
787787

788788
func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *types.Header, receipts []*types.ReceiptForStorage, td *big.Int) error {
789789
num := block.NumberU64()
790-
if err := op.AppendRaw(chainFreezerHashTable, num, block.Hash().Bytes()); err != nil {
790+
if err := op.AppendRaw(ChainFreezerHashTable, num, block.Hash().Bytes()); err != nil {
791791
return fmt.Errorf("can't add block %d hash: %v", num, err)
792792
}
793-
if err := op.Append(chainFreezerHeaderTable, num, header); err != nil {
793+
if err := op.Append(ChainFreezerHeaderTable, num, header); err != nil {
794794
return fmt.Errorf("can't append block header %d: %v", num, err)
795795
}
796-
if err := op.Append(chainFreezerBodiesTable, num, block.Body()); err != nil {
796+
if err := op.Append(ChainFreezerBodiesTable, num, block.Body()); err != nil {
797797
return fmt.Errorf("can't append block body %d: %v", num, err)
798798
}
799-
if err := op.Append(chainFreezerReceiptTable, num, receipts); err != nil {
799+
if err := op.Append(ChainFreezerReceiptTable, num, receipts); err != nil {
800800
return fmt.Errorf("can't append block %d receipts: %v", num, err)
801801
}
802-
if err := op.Append(chainFreezerDifficultyTable, num, td); err != nil {
802+
if err := op.Append(ChainFreezerDifficultyTable, num, td); err != nil {
803803
return fmt.Errorf("can't append block %d total difficulty: %v", num, err)
804804
}
805805
return nil

core/rawdb/ancient_scheme.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,30 @@ package rawdb
1818

1919
// The list of table names of chain freezer.
2020
const (
21-
// chainFreezerHeaderTable indicates the name of the freezer header table.
22-
chainFreezerHeaderTable = "headers"
21+
// ChainFreezerHeaderTable indicates the name of the freezer header table.
22+
ChainFreezerHeaderTable = "headers"
2323

24-
// chainFreezerHashTable indicates the name of the freezer canonical hash table.
25-
chainFreezerHashTable = "hashes"
24+
// ChainFreezerHashTable indicates the name of the freezer canonical hash table.
25+
ChainFreezerHashTable = "hashes"
2626

27-
// chainFreezerBodiesTable indicates the name of the freezer block body table.
28-
chainFreezerBodiesTable = "bodies"
27+
// ChainFreezerBodiesTable indicates the name of the freezer block body table.
28+
ChainFreezerBodiesTable = "bodies"
2929

30-
// chainFreezerReceiptTable indicates the name of the freezer receipts table.
31-
chainFreezerReceiptTable = "receipts"
30+
// ChainFreezerReceiptTable indicates the name of the freezer receipts table.
31+
ChainFreezerReceiptTable = "receipts"
3232

33-
// chainFreezerDifficultyTable indicates the name of the freezer total difficulty table.
34-
chainFreezerDifficultyTable = "diffs"
33+
// ChainFreezerDifficultyTable indicates the name of the freezer total difficulty table.
34+
ChainFreezerDifficultyTable = "diffs"
3535
)
3636

3737
// chainFreezerNoSnappy configures whether compression is disabled for the ancient-tables.
3838
// Hashes and difficulties don't compress well.
3939
var chainFreezerNoSnappy = map[string]bool{
40-
chainFreezerHeaderTable: false,
41-
chainFreezerHashTable: true,
42-
chainFreezerBodiesTable: false,
43-
chainFreezerReceiptTable: false,
44-
chainFreezerDifficultyTable: true,
40+
ChainFreezerHeaderTable: false,
41+
ChainFreezerHashTable: true,
42+
ChainFreezerBodiesTable: false,
43+
ChainFreezerReceiptTable: false,
44+
ChainFreezerDifficultyTable: true,
4545
}
4646

4747
// The list of identifiers of ancient stores.

core/rawdb/chain_freezer.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -280,19 +280,19 @@ func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hash
280280
}
281281

282282
// Write to the batch.
283-
if err := op.AppendRaw(chainFreezerHashTable, number, hash[:]); err != nil {
283+
if err := op.AppendRaw(ChainFreezerHashTable, number, hash[:]); err != nil {
284284
return fmt.Errorf("can't write hash to Freezer: %v", err)
285285
}
286-
if err := op.AppendRaw(chainFreezerHeaderTable, number, header); err != nil {
286+
if err := op.AppendRaw(ChainFreezerHeaderTable, number, header); err != nil {
287287
return fmt.Errorf("can't write header to Freezer: %v", err)
288288
}
289-
if err := op.AppendRaw(chainFreezerBodiesTable, number, body); err != nil {
289+
if err := op.AppendRaw(ChainFreezerBodiesTable, number, body); err != nil {
290290
return fmt.Errorf("can't write body to Freezer: %v", err)
291291
}
292-
if err := op.AppendRaw(chainFreezerReceiptTable, number, receipts); err != nil {
292+
if err := op.AppendRaw(ChainFreezerReceiptTable, number, receipts); err != nil {
293293
return fmt.Errorf("can't write receipts to Freezer: %v", err)
294294
}
295-
if err := op.AppendRaw(chainFreezerDifficultyTable, number, td); err != nil {
295+
if err := op.AppendRaw(ChainFreezerDifficultyTable, number, td); err != nil {
296296
return fmt.Errorf("can't write td to Freezer: %v", err)
297297
}
298298

core/rawdb/chain_iterator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func InitDatabaseFromFreezer(db ethdb.Database) {
5050
if i+count > frozen {
5151
count = frozen - i
5252
}
53-
data, err := db.AncientRange(chainFreezerHashTable, i, count, 32*count)
53+
data, err := db.AncientRange(ChainFreezerHashTable, i, count, 32*count)
5454
if err != nil {
5555
log.Crit("Failed to init database from freezer", "err", err)
5656
}

core/rawdb/database.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
231231
// If the freezer already contains something, ensure that the genesis blocks
232232
// match, otherwise we might mix up freezers across chains and destroy both
233233
// the freezer and the key-value store.
234-
frgenesis, err := frdb.Ancient(chainFreezerHashTable, 0)
234+
frgenesis, err := frdb.Ancient(ChainFreezerHashTable, 0)
235235
if err != nil {
236236
return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err)
237237
} else if !bytes.Equal(kvgenesis, frgenesis) {

eth/downloader/downloader.go

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,11 @@ type Downloader struct {
154154
bodyFetchHook func([]*types.Header) // Method to call upon starting a block body fetch
155155
receiptFetchHook func([]*types.Header) // Method to call upon starting a receipt fetch
156156
chainInsertHook func([]*fetchResult) // Method to call upon inserting a chain of blocks (possibly in multiple invocations)
157+
158+
// Progress reporting metrics
159+
syncStartBlock uint64 // Head snap block when Geth was started
160+
syncStartTime time.Time // Time instance when chain sync started
161+
syncLogTime time.Time // Time instance when status was last reported
157162
}
158163

159164
// LightChain encapsulates functions required to synchronise a light chain.
@@ -231,7 +236,9 @@ func New(checkpoint uint64, stateDb ethdb.Database, mux *event.TypeMux, chain Bl
231236
quitCh: make(chan struct{}),
232237
SnapSyncer: snap.NewSyncer(stateDb, chain.TrieDB().Scheme()),
233238
stateSyncStart: make(chan *stateSync),
239+
syncStartBlock: chain.CurrentFastBlock().NumberU64(),
234240
}
241+
// Create the post-merge skeleton syncer and start the process
235242
dl.skeleton = newSkeleton(stateDb, dl.peers, dropPeer, newBeaconBackfiller(dl, success))
236243

237244
go dl.stateFetcher()
@@ -1614,6 +1621,7 @@ func (d *Downloader) processSnapSyncContent() error {
16141621
if len(results) == 0 {
16151622
// If pivot sync is done, stop
16161623
if oldPivot == nil {
1624+
d.reportSnapSyncProgress(true)
16171625
return sync.Cancel()
16181626
}
16191627
// If sync failed, stop
@@ -1627,6 +1635,8 @@ func (d *Downloader) processSnapSyncContent() error {
16271635
if d.chainInsertHook != nil {
16281636
d.chainInsertHook(results)
16291637
}
1638+
d.reportSnapSyncProgress(false)
1639+
16301640
// If we haven't downloaded the pivot block yet, check pivot staleness
16311641
// notifications from the header downloader
16321642
d.pivotLock.RLock()
@@ -1739,7 +1749,7 @@ func (d *Downloader) commitSnapSyncData(results []*fetchResult, stateSync *state
17391749
}
17401750
default:
17411751
}
1742-
// Retrieve the a batch of results to import
1752+
// Retrieve the batch of results to import
17431753
first, last := results[0].Header, results[len(results)-1].Header
17441754
log.Debug("Inserting snap-sync blocks", "items", len(results),
17451755
"firstnum", first.Number, "firsthash", first.Hash(),
@@ -1820,3 +1830,56 @@ func (d *Downloader) readHeaderRange(last *types.Header, count int) []*types.Hea
18201830
}
18211831
return headers
18221832
}
1833+
1834+
// reportSnapSyncProgress calculates various status reports and provides it to the user.
1835+
func (d *Downloader) reportSnapSyncProgress(force bool) {
1836+
// Initialize the sync start time if it's the first time we're reporting
1837+
if d.syncStartTime.IsZero() {
1838+
d.syncStartTime = time.Now().Add(-time.Millisecond) // -1ms offset to avoid division by zero
1839+
}
1840+
// Don't report all the events, just occasionally
1841+
if !force && time.Since(d.syncLogTime) < 8*time.Second {
1842+
return
1843+
}
1844+
// Don't report anything until we have a meaningful progress
1845+
var (
1846+
headerBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerHeaderTable)
1847+
bodyBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerBodiesTable)
1848+
receiptBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerReceiptTable)
1849+
)
1850+
syncedBytes := common.StorageSize(headerBytes + bodyBytes + receiptBytes)
1851+
if syncedBytes == 0 {
1852+
return
1853+
}
1854+
var (
1855+
header = d.blockchain.CurrentHeader()
1856+
block = d.blockchain.CurrentFastBlock()
1857+
)
1858+
syncedBlocks := block.NumberU64() - d.syncStartBlock
1859+
if syncedBlocks == 0 {
1860+
return
1861+
}
1862+
// Retrieve the current chain head and calculate the ETA
1863+
latest, _, err := d.skeleton.Bounds()
1864+
if err != nil {
1865+
// We're going to cheat for non-merged networks, but that's fine
1866+
latest = d.pivotHeader
1867+
}
1868+
if latest == nil {
1869+
// This should really never happen, but add some defensive code for now.
1870+
// TODO(karalabe): Remove it eventually if we don't see it blow.
1871+
log.Error("Nil latest block in sync progress report")
1872+
return
1873+
}
1874+
var (
1875+
left = latest.Number.Uint64() - block.NumberU64()
1876+
eta = time.Since(d.syncStartTime) / time.Duration(syncedBlocks) * time.Duration(left)
1877+
1878+
progress = fmt.Sprintf("%.2f%%", float64(block.NumberU64())*100/float64(latest.Number.Uint64()))
1879+
headers = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(header.Number.Uint64()), common.StorageSize(headerBytes).TerminalString())
1880+
bodies = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(block.NumberU64()), common.StorageSize(bodyBytes).TerminalString())
1881+
receipts = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(block.NumberU64()), common.StorageSize(receiptBytes).TerminalString())
1882+
)
1883+
log.Info("Syncing: chain download in progress", "synced", progress, "chain", syncedBytes, "headers", headers, "bodies", bodies, "receipts", receipts, "eta", common.PrettyDuration(eta))
1884+
d.syncLogTime = time.Now()
1885+
}

eth/downloader/queue.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ type queue struct {
144144
active *sync.Cond
145145
closed bool
146146

147-
lastStatLog time.Time
147+
logTime time.Time // Time instance when status was last reported
148148
}
149149

150150
// newQueue creates a new download queue for scheduling block retrieval.
@@ -390,11 +390,12 @@ func (q *queue) Results(block bool) []*fetchResult {
390390
}
391391
}
392392
// Log some info at certain times
393-
if time.Since(q.lastStatLog) > 60*time.Second {
394-
q.lastStatLog = time.Now()
393+
if time.Since(q.logTime) >= 60*time.Second {
394+
q.logTime = time.Now()
395+
395396
info := q.Stats()
396397
info = append(info, "throttle", throttleThreshold)
397-
log.Info("Downloader queue stats", info...)
398+
log.Debug("Downloader queue stats", info...)
398399
}
399400
return results
400401
}

0 commit comments

Comments
 (0)