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

op-program: Use an LRU for caches.

parent aaca212f
...@@ -4,53 +4,60 @@ import ( ...@@ -4,53 +4,60 @@ import (
"github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "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 // CachingOracle is an implementation of Oracle that delegates to another implementation, adding caching of all results
type CachingOracle struct { type CachingOracle struct {
oracle Oracle oracle Oracle
blocks map[common.Hash]eth.BlockInfo blocks *simplelru.LRU[common.Hash, eth.BlockInfo]
txs map[common.Hash]types.Transactions txs *simplelru.LRU[common.Hash, types.Transactions]
rcpts map[common.Hash]types.Receipts rcpts *simplelru.LRU[common.Hash, types.Receipts]
} }
func NewCachingOracle(oracle Oracle) *CachingOracle { 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{ return &CachingOracle{
oracle: oracle, oracle: oracle,
blocks: make(map[common.Hash]eth.BlockInfo), blocks: blockLRU,
txs: make(map[common.Hash]types.Transactions), txs: txsLRU,
rcpts: make(map[common.Hash]types.Receipts), rcpts: rcptsLRU,
} }
} }
func (o CachingOracle) HeaderByBlockHash(blockHash common.Hash) eth.BlockInfo { func (o *CachingOracle) HeaderByBlockHash(blockHash common.Hash) eth.BlockInfo {
block, ok := o.blocks[blockHash] block, ok := o.blocks.Get(blockHash)
if ok { if ok {
return block return block
} }
block = o.oracle.HeaderByBlockHash(blockHash) block = o.oracle.HeaderByBlockHash(blockHash)
o.blocks[blockHash] = block o.blocks.Add(blockHash, block)
return block return block
} }
func (o CachingOracle) TransactionsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Transactions) { func (o *CachingOracle) TransactionsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Transactions) {
txs, ok := o.txs[blockHash] txs, ok := o.txs.Get(blockHash)
if ok { if ok {
return o.HeaderByBlockHash(blockHash), txs return o.HeaderByBlockHash(blockHash), txs
} }
block, txs := o.oracle.TransactionsByBlockHash(blockHash) block, txs := o.oracle.TransactionsByBlockHash(blockHash)
o.blocks[blockHash] = block o.blocks.Add(blockHash, block)
o.txs[blockHash] = txs o.txs.Add(blockHash, txs)
return block, txs return block, txs
} }
func (o CachingOracle) ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Receipts) { func (o *CachingOracle) ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Receipts) {
rcpts, ok := o.rcpts[blockHash] rcpts, ok := o.rcpts.Get(blockHash)
if ok { if ok {
return o.HeaderByBlockHash(blockHash), rcpts return o.HeaderByBlockHash(blockHash), rcpts
} }
block, rcpts := o.oracle.ReceiptsByBlockHash(blockHash) block, rcpts := o.oracle.ReceiptsByBlockHash(blockHash)
o.blocks[blockHash] = block o.blocks.Add(blockHash, block)
o.rcpts[blockHash] = rcpts o.rcpts.Add(blockHash, rcpts)
return block, rcpts return block, rcpts
} }
...@@ -3,50 +3,58 @@ package l2 ...@@ -3,50 +3,58 @@ package l2
import ( import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "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 { type CachingOracle struct {
oracle Oracle oracle Oracle
blocks map[common.Hash]*types.Block blocks *simplelru.LRU[common.Hash, *types.Block]
nodes map[common.Hash][]byte nodes *simplelru.LRU[common.Hash, []byte]
codes map[common.Hash][]byte codes *simplelru.LRU[common.Hash, []byte]
} }
func NewCachingOracle(oracle Oracle) *CachingOracle { 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{ return &CachingOracle{
oracle: oracle, oracle: oracle,
blocks: make(map[common.Hash]*types.Block), blocks: blockLRU,
nodes: make(map[common.Hash][]byte), nodes: nodeLRU,
codes: make(map[common.Hash][]byte), codes: codeLRU,
} }
} }
func (o CachingOracle) NodeByHash(nodeHash common.Hash) []byte { func (o *CachingOracle) NodeByHash(nodeHash common.Hash) []byte {
node, ok := o.nodes[nodeHash] node, ok := o.nodes.Get(nodeHash)
if ok { if ok {
return node return node
} }
node = o.oracle.NodeByHash(nodeHash) node = o.oracle.NodeByHash(nodeHash)
o.nodes[nodeHash] = node o.nodes.Add(nodeHash, node)
return node return node
} }
func (o CachingOracle) CodeByHash(codeHash common.Hash) []byte { func (o *CachingOracle) CodeByHash(codeHash common.Hash) []byte {
code, ok := o.codes[codeHash] code, ok := o.codes.Get(codeHash)
if ok { if ok {
return code return code
} }
code = o.oracle.CodeByHash(codeHash) code = o.oracle.CodeByHash(codeHash)
o.codes[codeHash] = code o.codes.Add(codeHash, code)
return code return code
} }
func (o CachingOracle) BlockByHash(blockHash common.Hash) *types.Block { func (o *CachingOracle) BlockByHash(blockHash common.Hash) *types.Block {
block, ok := o.blocks[blockHash] block, ok := o.blocks.Get(blockHash)
if ok { if ok {
return block return block
} }
block = o.oracle.BlockByHash(blockHash) block = o.oracle.BlockByHash(blockHash)
o.blocks[blockHash] = block o.blocks.Add(blockHash, block)
return 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