mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 13:46:43 +00:00
updates from gary
This commit is contained in:
parent
3d40a60beb
commit
ff5beb274b
2 changed files with 35 additions and 17 deletions
|
|
@ -16,37 +16,55 @@
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
// Arena is an allocation primitive that allows individual allocations
|
// Arena is an allocation primitive that allows individual allocations
|
||||||
// out of a page of items and bulk de-allocations of last N allocations.
|
// out of a page of items and bulk de-allocations of last N allocations.
|
||||||
// The most common way of using an Arena is to pair it up with a sync.Pool
|
// The most common way of using an Arena is to pair it up with a sync.Pool
|
||||||
// of pages.
|
// of pages.
|
||||||
|
//
|
||||||
|
// Notably, arena is not thread safe, please manage the concurrency issues
|
||||||
|
// by yourselves.
|
||||||
type Arena[T any] struct {
|
type Arena[T any] struct {
|
||||||
used uint32
|
used uint32
|
||||||
pages [][]T
|
pages [][]T
|
||||||
|
pageSize uint32
|
||||||
PageSize uint32
|
newPage func() any
|
||||||
NewPage func() any
|
releasePage func(any)
|
||||||
ReleasePage func(any)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alloc returns the next free item on the arena
|
// NewArena constructs the arena for the given type.
|
||||||
// Allocates a new page if needed
|
func NewArena[T any](pageSize uint32, newPage func() any, releasePage func(any)) *Arena[T] {
|
||||||
|
return &Arena[T]{
|
||||||
|
pageSize: pageSize,
|
||||||
|
newPage: newPage,
|
||||||
|
releasePage: releasePage,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alloc returns the next free item on the arena.
|
||||||
func (a *Arena[T]) Alloc() *T {
|
func (a *Arena[T]) Alloc() *T {
|
||||||
pageIndex := a.used / a.PageSize
|
pageIndex := a.used / a.pageSize
|
||||||
pageOffset := a.used % a.PageSize
|
pageOffset := a.used % a.pageSize
|
||||||
if pageOffset == 0 {
|
|
||||||
a.pages = append(a.pages, a.NewPage().([]T))
|
// Allocate additional items if all pre-allocated ones have been exhausted
|
||||||
|
if pageOffset == 0 && int(pageIndex) == len(a.pages) {
|
||||||
|
items := a.newPage().([]T)
|
||||||
|
if len(items) != int(a.pageSize) {
|
||||||
|
panic(fmt.Errorf("invalid page size, want: %d, got: %d", a.pageSize, len(items)))
|
||||||
|
}
|
||||||
|
a.pages = append(a.pages, items)
|
||||||
}
|
}
|
||||||
a.used++
|
a.used++
|
||||||
return &a.pages[pageIndex][pageOffset]
|
return &a.pages[pageIndex][pageOffset]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used returns the number of items that live on this arena
|
// Used returns the number of items that live on this arena.
|
||||||
func (a *Arena[T]) Used() uint32 {
|
func (a *Arena[T]) Used() uint32 {
|
||||||
return a.used
|
return a.used
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset rollsback the active set of live elements to the given number
|
// Reset rollbacks the active set of live elements to the given number.
|
||||||
func (a *Arena[T]) Reset(to uint32) {
|
func (a *Arena[T]) Reset(to uint32) {
|
||||||
a.used = to
|
a.used = to
|
||||||
}
|
}
|
||||||
|
|
@ -54,7 +72,7 @@ func (a *Arena[T]) Reset(to uint32) {
|
||||||
// Release releases all the pages that the arena currently owns
|
// Release releases all the pages that the arena currently owns
|
||||||
func (a *Arena[T]) Release() {
|
func (a *Arena[T]) Release() {
|
||||||
for _, page := range a.pages {
|
for _, page := range a.pages {
|
||||||
a.ReleasePage(page)
|
a.releasePage(page)
|
||||||
}
|
}
|
||||||
a.pages = nil
|
a.pages = nil
|
||||||
a.used = 0
|
a.used = 0
|
||||||
|
|
|
||||||
|
|
@ -90,8 +90,8 @@ func NewStackTrie(onTrieNode OnTrieNode) *StackTrie {
|
||||||
onTrieNode: onTrieNode,
|
onTrieNode: onTrieNode,
|
||||||
kBuf: make([]byte, 64),
|
kBuf: make([]byte, 64),
|
||||||
pBuf: make([]byte, 64),
|
pBuf: make([]byte, 64),
|
||||||
nodeAllocator: common.Arena[stNode]{NewPage: stPagePool.Get, PageSize: uint32(stPageSize), ReleasePage: stPagePool.Put},
|
nodeAllocator: *common.NewArena[stNode](uint32(stPageSize), stPagePool.Get, stPagePool.Put),
|
||||||
byteAllocator: common.Arena[[32]byte]{NewPage: bytePagePool.Get, PageSize: uint32(stPageSize), ReleasePage: bytePagePool.Put},
|
byteAllocator: *common.NewArena[[32]byte](uint32(stPageSize), bytePagePool.Get, bytePagePool.Put),
|
||||||
}
|
}
|
||||||
t.root = t.nodeAllocator.Alloc().reset()
|
t.root = t.nodeAllocator.Alloc().reset()
|
||||||
t.tmpNode = t.nodeAllocator.Alloc().reset()
|
t.tmpNode = t.nodeAllocator.Alloc().reset()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue