mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 01:13:45 +00:00
consensus/ethash: restore 'future item' logic in lru
This commit is contained in:
parent
253747abcc
commit
2b9665abbc
1 changed files with 21 additions and 12 deletions
|
|
@ -145,13 +145,15 @@ func memoryMapAndGenerate(path string, size uint64, generator func(buffer []uint
|
||||||
}
|
}
|
||||||
|
|
||||||
// lru tracks caches or datasets by their last use time, keeping at most N of them.
|
// lru tracks caches or datasets by their last use time, keeping at most N of them.
|
||||||
// Whenever an item is requested through get, lru ensures that the next item is also
|
|
||||||
// present.
|
|
||||||
type lru struct {
|
type lru struct {
|
||||||
what string
|
what string
|
||||||
new func(epoch uint64) interface{}
|
new func(epoch uint64) interface{}
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
cache *simplelru.LRU
|
// Items are kept in a LRU cache, but there is a special case:
|
||||||
|
// We always keep an item for (highest seen epoch) + 1 as the 'future item'.
|
||||||
|
cache *simplelru.LRU
|
||||||
|
future uint64
|
||||||
|
futureItem interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newlru(what string, maxItems int, new func(epoch uint64) interface{}) *lru {
|
func newlru(what string, maxItems int, new func(epoch uint64) interface{}) *lru {
|
||||||
|
|
@ -164,22 +166,29 @@ func newlru(what string, maxItems int, new func(epoch uint64) interface{}) *lru
|
||||||
return &lru{what: what, new: new, cache: cache}
|
return &lru{what: what, new: new, cache: cache}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lru *lru) get(epoch uint64) (current, future interface{}) {
|
// get retrieves or creates an item for the given epoch. The first return value is always
|
||||||
|
// non-nil. The second return value is non-nil if lru thinks that an item will be useful in
|
||||||
|
// the near future.
|
||||||
|
func (lru *lru) get(epoch uint64) (item, future interface{}) {
|
||||||
lru.mu.Lock()
|
lru.mu.Lock()
|
||||||
defer lru.mu.Unlock()
|
defer lru.mu.Unlock()
|
||||||
|
|
||||||
// Get or create the item for the requested epoch.
|
// Get or create the item for the requested epoch.
|
||||||
current, ok := lru.cache.Get(epoch)
|
item, ok := lru.cache.Get(epoch)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
if lru.future > 0 && lru.future == epoch {
|
||||||
|
return lru.futureItem, nil
|
||||||
|
}
|
||||||
log.Trace("Requiring new ethash "+lru.what, "epoch", epoch)
|
log.Trace("Requiring new ethash "+lru.what, "epoch", epoch)
|
||||||
current = lru.new(epoch)
|
item = lru.new(epoch)
|
||||||
lru.cache.Add(epoch, current)
|
lru.cache.Add(epoch, current)
|
||||||
}
|
}
|
||||||
// Ensure that there is an item for the next epoch.
|
// Update the 'future item' if epoch is larger than previously seen.
|
||||||
if epoch < maxEpoch-1 && !lru.cache.Contains(epoch+1) {
|
if epoch < maxEpoch-1 && lru.future < epoch+1 {
|
||||||
log.Trace("Requiring new future ethash "+lru.what, "epoch", epoch+1)
|
log.Trace("Requiring new future ethash "+lru.what, "epoch", epoch+1)
|
||||||
future = lru.new(epoch + 1)
|
future = lru.new(epoch + 1)
|
||||||
lru.cache.Add(epoch, future)
|
lru.future = epoch + 1
|
||||||
|
lru.futureItem = future
|
||||||
}
|
}
|
||||||
return current, future
|
return current, future
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue