Commit 319421c0 authored by Adrian Sutton's avatar Adrian Sutton

op-program: Use an LRU for caches.

parent aaca212f
......@@ -4,53 +4,60 @@ import (
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/hashicorp/golang-lru/v2/simplelru"
)
// Cache size is quite high as retrieving data from the pre-image oracle can be quite expensive
const cacheSize = 2000
// CachingOracle is an implementation of Oracle that delegates to another implementation, adding caching of all results
type CachingOracle struct {
oracle Oracle
blocks map[common.Hash]eth.BlockInfo
txs map[common.Hash]types.Transactions
rcpts map[common.Hash]types.Receipts
blocks *simplelru.LRU[common.Hash, eth.BlockInfo]
txs *simplelru.LRU[common.Hash, types.Transactions]
rcpts *simplelru.LRU[common.Hash, types.Receipts]
}
func NewCachingOracle(oracle Oracle) *CachingOracle {
blockLRU, _ := simplelru.NewLRU[common.Hash, eth.BlockInfo](cacheSize, nil)
txsLRU, _ := simplelru.NewLRU[common.Hash, types.Transactions](cacheSize, nil)
rcptsLRU, _ := simplelru.NewLRU[common.Hash, types.Receipts](cacheSize, nil)
return &CachingOracle{
oracle: oracle,
blocks: make(map[common.Hash]eth.BlockInfo),
txs: make(map[common.Hash]types.Transactions),
rcpts: make(map[common.Hash]types.Receipts),
blocks: blockLRU,
txs: txsLRU,
rcpts: rcptsLRU,
}
}
func (o CachingOracle) HeaderByBlockHash(blockHash common.Hash) eth.BlockInfo {
block, ok := o.blocks[blockHash]
func (o *CachingOracle) HeaderByBlockHash(blockHash common.Hash) eth.BlockInfo {
block, ok := o.blocks.Get(blockHash)
if ok {
return block
}
block = o.oracle.HeaderByBlockHash(blockHash)
o.blocks[blockHash] = block
o.blocks.Add(blockHash, block)
return block
}
func (o CachingOracle) TransactionsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Transactions) {
txs, ok := o.txs[blockHash]
func (o *CachingOracle) TransactionsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Transactions) {
txs, ok := o.txs.Get(blockHash)
if ok {
return o.HeaderByBlockHash(blockHash), txs
}
block, txs := o.oracle.TransactionsByBlockHash(blockHash)
o.blocks[blockHash] = block
o.txs[blockHash] = txs
o.blocks.Add(blockHash, block)
o.txs.Add(blockHash, txs)
return block, txs
}
func (o CachingOracle) ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Receipts) {
rcpts, ok := o.rcpts[blockHash]
func (o *CachingOracle) ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Receipts) {
rcpts, ok := o.rcpts.Get(blockHash)
if ok {
return o.HeaderByBlockHash(blockHash), rcpts
}
block, rcpts := o.oracle.ReceiptsByBlockHash(blockHash)
o.blocks[blockHash] = block
o.rcpts[blockHash] = rcpts
o.blocks.Add(blockHash, block)
o.rcpts.Add(blockHash, rcpts)
return block, rcpts
}
......@@ -3,50 +3,58 @@ package l2
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/hashicorp/golang-lru/v2/simplelru"
)
const blockCacheSize = 2_000
const nodeCacheSize = 100_000
const codeCacheSize = 10_000
type CachingOracle struct {
oracle Oracle
blocks map[common.Hash]*types.Block
nodes map[common.Hash][]byte
codes map[common.Hash][]byte
blocks *simplelru.LRU[common.Hash, *types.Block]
nodes *simplelru.LRU[common.Hash, []byte]
codes *simplelru.LRU[common.Hash, []byte]
}
func NewCachingOracle(oracle Oracle) *CachingOracle {
blockLRU, _ := simplelru.NewLRU[common.Hash, *types.Block](blockCacheSize, nil)
nodeLRU, _ := simplelru.NewLRU[common.Hash, []byte](nodeCacheSize, nil)
codeLRU, _ := simplelru.NewLRU[common.Hash, []byte](codeCacheSize, nil)
return &CachingOracle{
oracle: oracle,
blocks: make(map[common.Hash]*types.Block),
nodes: make(map[common.Hash][]byte),
codes: make(map[common.Hash][]byte),
blocks: blockLRU,
nodes: nodeLRU,
codes: codeLRU,
}
}
func (o CachingOracle) NodeByHash(nodeHash common.Hash) []byte {
node, ok := o.nodes[nodeHash]
func (o *CachingOracle) NodeByHash(nodeHash common.Hash) []byte {
node, ok := o.nodes.Get(nodeHash)
if ok {
return node
}
node = o.oracle.NodeByHash(nodeHash)
o.nodes[nodeHash] = node
o.nodes.Add(nodeHash, node)
return node
}
func (o CachingOracle) CodeByHash(codeHash common.Hash) []byte {
code, ok := o.codes[codeHash]
func (o *CachingOracle) CodeByHash(codeHash common.Hash) []byte {
code, ok := o.codes.Get(codeHash)
if ok {
return code
}
code = o.oracle.CodeByHash(codeHash)
o.codes[codeHash] = code
o.codes.Add(codeHash, code)
return code
}
func (o CachingOracle) BlockByHash(blockHash common.Hash) *types.Block {
block, ok := o.blocks[blockHash]
func (o *CachingOracle) BlockByHash(blockHash common.Hash) *types.Block {
block, ok := o.blocks.Get(blockHash)
if ok {
return block
}
block = o.oracle.BlockByHash(blockHash)
o.blocks[blockHash] = block
o.blocks.Add(blockHash, block)
return block
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment