mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-12 02:56:37 +00:00
triedb/pathdb: use binary.append to eliminate the tmp scratch slice (#32250)
`binary.AppendUvarint` offers better performance than using append directly, because it avoids unnecessary memory allocation and copying. In our case, it can increase the performance by +35.8% for the `blockWriter.append` function: ``` benchmark old ns/op new ns/op delta BenchmarkBlockWriterAppend-8 5.97 3.83 -35.80% ``` --------- Signed-off-by: jsvisa <delweng@gmail.com> Co-authored-by: Gary Rong <garyrong0905@gmail.com>
This commit is contained in:
parent
83aa643621
commit
264c06a72c
2 changed files with 27 additions and 21 deletions
|
|
@ -221,17 +221,14 @@ func (br *blockReader) readGreaterThan(id uint64) (uint64, error) {
|
||||||
type blockWriter struct {
|
type blockWriter struct {
|
||||||
desc *indexBlockDesc // Descriptor of the block
|
desc *indexBlockDesc // Descriptor of the block
|
||||||
restarts []uint16 // Offsets into the data slice, marking the start of each section
|
restarts []uint16 // Offsets into the data slice, marking the start of each section
|
||||||
scratch []byte // Buffer used for encoding full integers or value differences
|
|
||||||
data []byte // Aggregated encoded data slice
|
data []byte // Aggregated encoded data slice
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBlockWriter(blob []byte, desc *indexBlockDesc) (*blockWriter, error) {
|
func newBlockWriter(blob []byte, desc *indexBlockDesc) (*blockWriter, error) {
|
||||||
scratch := make([]byte, binary.MaxVarintLen64)
|
|
||||||
if len(blob) == 0 {
|
if len(blob) == 0 {
|
||||||
return &blockWriter{
|
return &blockWriter{
|
||||||
desc: desc,
|
desc: desc,
|
||||||
scratch: scratch,
|
data: make([]byte, 0, 1024),
|
||||||
data: make([]byte, 0, 1024),
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
restarts, data, err := parseIndexBlock(blob)
|
restarts, data, err := parseIndexBlock(blob)
|
||||||
|
|
@ -241,7 +238,6 @@ func newBlockWriter(blob []byte, desc *indexBlockDesc) (*blockWriter, error) {
|
||||||
return &blockWriter{
|
return &blockWriter{
|
||||||
desc: desc,
|
desc: desc,
|
||||||
restarts: restarts,
|
restarts: restarts,
|
||||||
scratch: scratch,
|
|
||||||
data: data, // safe to own the slice
|
data: data, // safe to own the slice
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
@ -268,22 +264,14 @@ func (b *blockWriter) append(id uint64) error {
|
||||||
//
|
//
|
||||||
// The first element in a restart range is encoded using its
|
// The first element in a restart range is encoded using its
|
||||||
// full value.
|
// full value.
|
||||||
n := binary.PutUvarint(b.scratch[0:], id)
|
b.data = binary.AppendUvarint(b.data, id)
|
||||||
b.data = append(b.data, b.scratch[:n]...)
|
|
||||||
} else {
|
} else {
|
||||||
// The current section is not full, append the element.
|
|
||||||
// The element which is not the first one in the section
|
// The element which is not the first one in the section
|
||||||
// is encoded using the value difference from the preceding
|
// is encoded using the value difference from the preceding
|
||||||
// element.
|
// element.
|
||||||
n := binary.PutUvarint(b.scratch[0:], id-b.desc.max)
|
b.data = binary.AppendUvarint(b.data, id-b.desc.max)
|
||||||
b.data = append(b.data, b.scratch[:n]...)
|
|
||||||
}
|
}
|
||||||
b.desc.entries++
|
b.desc.entries++
|
||||||
|
|
||||||
// The state history ID must be greater than 0.
|
|
||||||
//if b.desc.min == 0 {
|
|
||||||
// b.desc.min = id
|
|
||||||
//}
|
|
||||||
b.desc.max = id
|
b.desc.max = id
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -392,11 +380,10 @@ func (b *blockWriter) full() bool {
|
||||||
//
|
//
|
||||||
// This function is safe to be called multiple times.
|
// This function is safe to be called multiple times.
|
||||||
func (b *blockWriter) finish() []byte {
|
func (b *blockWriter) finish() []byte {
|
||||||
var buf []byte
|
buf := make([]byte, len(b.restarts)*2+1)
|
||||||
for _, number := range b.restarts {
|
for i, restart := range b.restarts {
|
||||||
binary.BigEndian.PutUint16(b.scratch[:2], number)
|
binary.BigEndian.PutUint16(buf[2*i:], restart)
|
||||||
buf = append(buf, b.scratch[:2]...)
|
|
||||||
}
|
}
|
||||||
buf = append(buf, byte(len(b.restarts)))
|
buf[len(buf)-1] = byte(len(b.restarts))
|
||||||
return append(b.data, buf...)
|
return append(b.data, buf...)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -232,3 +232,22 @@ func BenchmarkParseIndexBlock(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BenchmarkBlockWriterAppend benchmarks the performance of indexblock.writer
|
||||||
|
func BenchmarkBlockWriterAppend(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
desc := newIndexBlockDesc(0)
|
||||||
|
writer, _ := newBlockWriter(nil, desc)
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if writer.full() {
|
||||||
|
desc = newIndexBlockDesc(0)
|
||||||
|
writer, _ = newBlockWriter(nil, desc)
|
||||||
|
}
|
||||||
|
if err := writer.append(writer.desc.max + 1); err != nil {
|
||||||
|
b.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue