Skip to content

Commit c9157bc

Browse files
rjl493456442Jacek Glen
authored andcommitted
core, ethdb, tests, trie: implement NewBatchWithSize API for batcher (ethereum#24392)
This PR adds an addtional API called `NewBatchWithSize` for db batcher. It turns out that leveldb batch memory allocation is super inefficient. The main reason is the allocation step of leveldb Batch is too small when the batch size is large. It can take a few second to build a leveldb batch with 100MB size. Luckily, leveldb also offers another API called MakeBatch which can pre-allocate the memory area. So if the approximate size of batch is known in advance, this API can be used in this case. It's needed in new state scheme PR which needs to commit a batch of trie nodes in a single batch. Implement the feature in a seperate PR.
1 parent 72715b5 commit c9157bc

File tree

8 files changed

+30
-0
lines changed

8 files changed

+30
-0
lines changed

core/rawdb/table.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,11 @@ func (t *table) NewBatch() ethdb.Batch {
172172
return &tableBatch{t.db.NewBatch(), t.prefix}
173173
}
174174

175+
// NewBatchWithSize creates a write-only database batch with pre-allocated buffer.
176+
func (t *table) NewBatchWithSize(size int) ethdb.Batch {
177+
return &tableBatch{t.db.NewBatchWithSize(size), t.prefix}
178+
}
179+
175180
// tableBatch is a wrapper around a database batch that prefixes each key access
176181
// with a pre-configured string.
177182
type tableBatch struct {

ethdb/batch.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ type Batcher interface {
4343
// NewBatch creates a write-only database that buffers changes to its host db
4444
// until a final write is called.
4545
NewBatch() Batch
46+
47+
// NewBatchWithSize creates a write-only database batch with pre-allocated buffer.
48+
NewBatchWithSize(size int) Batch
4649
}
4750

4851
// HookedBatch wraps an arbitrary batch where each operation may be hooked into

ethdb/leveldb/leveldb.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,14 @@ func (db *Database) NewBatch() ethdb.Batch {
213213
}
214214
}
215215

216+
// NewBatchWithSize creates a write-only database batch with pre-allocated buffer.
217+
func (db *Database) NewBatchWithSize(size int) ethdb.Batch {
218+
return &batch{
219+
db: db.db,
220+
b: leveldb.MakeBatch(size),
221+
}
222+
}
223+
216224
// NewIterator creates a binary-alphabetical iterator over a subset
217225
// of database content with a particular key prefix, starting at a particular
218226
// initial key (or after, if it does not exist).

ethdb/memorydb/memorydb.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ func (db *Database) NewBatch() ethdb.Batch {
129129
}
130130
}
131131

132+
// NewBatchWithSize creates a write-only database batch with pre-allocated buffer.
133+
func (db *Database) NewBatchWithSize(size int) ethdb.Batch {
134+
return &batch{
135+
db: db,
136+
}
137+
}
138+
132139
// NewIterator creates a binary-alphabetical iterator over a subset
133140
// of database content with a particular key prefix, starting at a particular
134141
// initial key (or after, if it does not exist).

tests/fuzzers/bn256/bn256_fuzz.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be found
33
// in the LICENSE file.
44

5+
//go:build gofuzz
56
// +build gofuzz
67

78
package bn256

tests/fuzzers/stacktrie/trie_fuzzer.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ func (s *spongeDb) Has(key []byte) (bool, error) { panic("implement
6666
func (s *spongeDb) Get(key []byte) ([]byte, error) { return nil, errors.New("no such elem") }
6767
func (s *spongeDb) Delete(key []byte) error { panic("implement me") }
6868
func (s *spongeDb) NewBatch() ethdb.Batch { return &spongeBatch{s} }
69+
func (s *spongeDb) NewBatchWithSize(size int) ethdb.Batch { return &spongeBatch{s} }
6970
func (s *spongeDb) Stat(property string) (string, error) { panic("implement me") }
7071
func (s *spongeDb) Compact(start []byte, limit []byte) error { panic("implement me") }
7172
func (s *spongeDb) Close() error { return nil }

trie/iterator_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,10 @@ func (l *loggingDb) NewBatch() ethdb.Batch {
470470
return l.backend.NewBatch()
471471
}
472472

473+
func (l *loggingDb) NewBatchWithSize(size int) ethdb.Batch {
474+
return l.backend.NewBatchWithSize(size)
475+
}
476+
473477
func (l *loggingDb) NewIterator(prefix []byte, start []byte) ethdb.Iterator {
474478
fmt.Printf("NewIterator\n")
475479
return l.backend.NewIterator(prefix, start)

trie/trie_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,7 @@ func (s *spongeDb) Has(key []byte) (bool, error) { panic("implement
675675
func (s *spongeDb) Get(key []byte) ([]byte, error) { return nil, errors.New("no such elem") }
676676
func (s *spongeDb) Delete(key []byte) error { panic("implement me") }
677677
func (s *spongeDb) NewBatch() ethdb.Batch { return &spongeBatch{s} }
678+
func (s *spongeDb) NewBatchWithSize(size int) ethdb.Batch { return &spongeBatch{s} }
678679
func (s *spongeDb) Stat(property string) (string, error) { panic("implement me") }
679680
func (s *spongeDb) Compact(start []byte, limit []byte) error { panic("implement me") }
680681
func (s *spongeDb) Close() error { return nil }

0 commit comments

Comments
 (0)