Skip to content

ETCM-1061 Remove caching from ArchiveStateStorage and ReferenceCountedStateStorage #1080

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,11 @@ object FixtureProvider {
override val transactionMappingStorage: TransactionMappingStorage = new TransactionMappingStorage(dataSource)
override val appStateStorage: AppStateStorage = new AppStateStorage(dataSource)
val nodeStorage: NodeStorage = new NodeStorage(dataSource)
val cachedNodeStorage: CachedNodeStorage = new CachedNodeStorage(nodeStorage, caches.nodeCache)
val pruningMode: PruningMode = ArchivePruning
override val stateStorage: StateStorage =
StateStorage(
pruningMode,
nodeStorage,
cachedNodeStorage,
new LruCache[NodeHash, HeapEntry](
Config.InMemoryPruningNodeCacheConfig,
Some(CachedReferenceCountedStorage.saveOnlyNotificationHandler(nodeStorage))
Expand Down
3 changes: 0 additions & 3 deletions src/main/scala/io/iohk/ethereum/db/components/Storages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ object Storages {

override val nodeStorage: NodeStorage = new NodeStorage(dataSource)

val cachedNodeStorage: CachedNodeStorage = new CachedNodeStorage(nodeStorage, caches.nodeCache)

override val fastSyncStateStorage: FastSyncStateStorage = new FastSyncStateStorage(dataSource)

override val evmCodeStorage: EvmCodeStorage = new EvmCodeStorage(dataSource)
Expand All @@ -50,7 +48,6 @@ object Storages {
StateStorage(
pruningMode,
nodeStorage,
cachedNodeStorage,
new LruCache[NodeHash, HeapEntry](
Config.InMemoryPruningNodeCacheConfig,
Some(CachedReferenceCountedStorage.saveOnlyNotificationHandler(nodeStorage))
Expand Down
57 changes: 19 additions & 38 deletions src/main/scala/io/iohk/ethereum/db/storage/StateStorage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,76 +31,57 @@ trait StateStorage {
def forcePersist(reason: FlushSituation): Boolean
}

class ArchiveStateStorage(private val nodeStorage: NodeStorage, private val cachedNodeStorage: CachedNodeStorage)
extends StateStorage {
class ArchiveStateStorage(private val nodeStorage: NodeStorage) extends StateStorage {

override def forcePersist(reason: FlushSituation): Boolean = {
cachedNodeStorage.forcePersist()
true
}
override def forcePersist(reason: FlushSituation): Boolean = true

override def onBlockSave(bn: BigInt, currentBestSavedBlock: BigInt)(updateBestBlocksData: () => Unit): Unit =
if (cachedNodeStorage.persist()) {
updateBestBlocksData()
}
updateBestBlocksData()

override def onBlockRollback(bn: BigInt, currentBestSavedBlock: BigInt)(updateBestBlocksData: () => Unit): Unit =
if (cachedNodeStorage.persist()) {
updateBestBlocksData()
}
updateBestBlocksData()

override def getReadOnlyStorage: MptStorage =
new SerializingMptStorage(ReadOnlyNodeStorage(new ArchiveNodeStorage(cachedNodeStorage)))
new SerializingMptStorage(ReadOnlyNodeStorage(new ArchiveNodeStorage(nodeStorage)))

override def getBackingStorage(bn: BigInt): MptStorage =
new SerializingMptStorage(new ArchiveNodeStorage(cachedNodeStorage))
new SerializingMptStorage(new ArchiveNodeStorage(nodeStorage))

override def saveNode(nodeHash: NodeHash, nodeEncoded: NodeEncoded, bn: BigInt): Unit =
nodeStorage.put(nodeHash, nodeEncoded)

override def getNode(nodeHash: NodeHash): Option[MptNode] =
cachedNodeStorage.get(nodeHash).map(_.toMptNode)
nodeStorage.get(nodeHash).map(_.toMptNode)
}

class ReferenceCountedStateStorage(
private val nodeStorage: NodeStorage,
private val cachedNodeStorage: CachedNodeStorage,
private val pruningHistory: BigInt
) extends StateStorage {
override def forcePersist(reason: FlushSituation): Boolean = {
cachedNodeStorage.forcePersist()
true
}
override def forcePersist(reason: FlushSituation): Boolean = true

override def onBlockSave(bn: BigInt, currentBestSavedBlock: BigInt)(updateBestBlocksData: () => Unit): Unit = {
val blockToPrune = bn - pruningHistory

ReferenceCountNodeStorage.prune(blockToPrune, cachedNodeStorage, inMemory = blockToPrune > currentBestSavedBlock)

if (cachedNodeStorage.persist()) {
updateBestBlocksData()
}
ReferenceCountNodeStorage.prune(blockToPrune, nodeStorage, inMemory = blockToPrune > currentBestSavedBlock)
updateBestBlocksData()
}

override def onBlockRollback(bn: BigInt, currentBestSavedBlock: BigInt)(updateBestBlocksData: () => Unit): Unit = {
ReferenceCountNodeStorage.rollback(bn, cachedNodeStorage, inMemory = bn > currentBestSavedBlock)

if (cachedNodeStorage.persist()) {
updateBestBlocksData()
}
ReferenceCountNodeStorage.rollback(bn, nodeStorage, inMemory = bn > currentBestSavedBlock)
updateBestBlocksData()
}

override def getBackingStorage(bn: BigInt): MptStorage =
new SerializingMptStorage(new ReferenceCountNodeStorage(cachedNodeStorage, bn))
new SerializingMptStorage(new ReferenceCountNodeStorage(nodeStorage, bn))

override def getReadOnlyStorage: MptStorage =
new SerializingMptStorage(ReadOnlyNodeStorage(new FastSyncNodeStorage(cachedNodeStorage, 0)))
new SerializingMptStorage(ReadOnlyNodeStorage(new FastSyncNodeStorage(nodeStorage, 0)))

override def saveNode(nodeHash: NodeHash, nodeEncoded: NodeEncoded, bn: BigInt): Unit =
new FastSyncNodeStorage(nodeStorage, bn).update(Nil, Seq(nodeHash -> nodeEncoded))

override def getNode(nodeHash: NodeHash): Option[MptNode] =
new FastSyncNodeStorage(cachedNodeStorage, 0).get(nodeHash).map(_.toMptNode)
new FastSyncNodeStorage(nodeStorage, 0).get(nodeHash).map(_.toMptNode)
}

class CachedReferenceCountedStateStorage(
Expand Down Expand Up @@ -159,12 +140,11 @@ object StateStorage {
def apply(
pruningMode: PruningMode,
nodeStorage: NodeStorage,
cachedNodeStorage: CachedNodeStorage,
lruCache: LruCache[NodeHash, HeapEntry]
): StateStorage =
pruningMode match {
case ArchivePruning => new ArchiveStateStorage(nodeStorage, cachedNodeStorage)
case pruning.BasicPruning(history) => new ReferenceCountedStateStorage(nodeStorage, cachedNodeStorage, history)
case ArchivePruning => new ArchiveStateStorage(nodeStorage)
case pruning.BasicPruning(history) => new ReferenceCountedStateStorage(nodeStorage, history)
case pruning.InMemoryPruning(history) => new CachedReferenceCountedStateStorage(nodeStorage, history, lruCache)
}

Expand All @@ -185,8 +165,9 @@ object StateStorage {
}
val nodeStorage = new NodeStorage(source)
val cachedNodeStorage = new CachedNodeStorage(nodeStorage, MapCache.createTestCache(testCacheSize))

(
StateStorage(pruningMode, nodeStorage, cachedNodeStorage, new LruCache[NodeHash, HeapEntry](testCacheConfig)),
StateStorage(pruningMode, nodeStorage, new LruCache[NodeHash, HeapEntry](testCacheConfig)),
nodeStorage,
cachedNodeStorage
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ class ConsensusSpec extends AnyFlatSpec with Matchers with ScalaFutures {
// dying before updating the storage but after updating the cache, inconsistency is created
blockchain.saveBestKnownBlocks(oldBlock4.number)

blockchainReader.getBestBlock() shouldBe Some(ancestorForValidation)
blockchainReader.getBestBlock() shouldBe Some(newBlock3)
}

it should "handle error when trying to reorganise chain" in new EphemBlockchain {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ import io.iohk.ethereum.utils.Config.NodeCacheConfig
class ReadOnlyNodeStorageSpec extends AnyFlatSpec with Matchers {

"ReadOnlyNodeStorage" should "not update dataSource" in new TestSetup {
val readOnlyNodeStorage = stateStorage.getReadOnlyStorage
val readOnlyNodeStorage = archiveStateStorage.getReadOnlyStorage
readOnlyNodeStorage.updateNodesInStorage(Some(newLeaf), Nil)
dataSource.storage.size shouldEqual 0
}

it should "be able to persist to underlying storage when needed" in new TestSetup {
val (nodeKey, nodeVal) = MptStorage.collapseNode(Some(newLeaf))._2.head
val readOnlyNodeStorage = stateStorage.getReadOnlyStorage
val (nodeKey, _) = MptStorage.collapseNode(Some(newLeaf))._2.head
val readOnlyNodeStorage = archiveStateStorage.getReadOnlyStorage

readOnlyNodeStorage.updateNodesInStorage(Some(newLeaf), Nil)

Expand All @@ -41,12 +41,11 @@ class ReadOnlyNodeStorageSpec extends AnyFlatSpec with Matchers {

readOnlyNodeStorage.persist()

stateStorage.forcePersist(GenesisDataLoad)
dataSource.storage.size shouldEqual 1
}

it should "be able to persist to underlying storage when Genesis loading" in new TestSetup {
val (nodeKey, nodeVal) = MptStorage.collapseNode(Some(newLeaf))._2.head
val (nodeKey, _) = MptStorage.collapseNode(Some(newLeaf))._2.head
val readOnlyNodeStorage = cachedStateStorage.getReadOnlyStorage

readOnlyNodeStorage.updateNodesInStorage(Some(newLeaf), Nil)
Expand All @@ -65,7 +64,7 @@ class ReadOnlyNodeStorageSpec extends AnyFlatSpec with Matchers {
trait TestSetup {
val newLeaf: LeafNode = LeafNode(ByteString(1), ByteString(1))
val dataSource: EphemDataSource = EphemDataSource()
val (stateStorage, nodeStorage, cachedStorage) = StateStorage.createTestStateStorage(dataSource)
val (archiveStateStorage, nodeStorage, cachedStorage) = StateStorage.createTestStateStorage(dataSource)

object TestCacheConfig extends NodeCacheConfig {
override val maxSize: Long = 100
Expand All @@ -76,7 +75,6 @@ class ReadOnlyNodeStorageSpec extends AnyFlatSpec with Matchers {
val testCache: Cache[NodeHash, NodeEncoded] = MapCache.createTestCache[NodeHash, NodeEncoded](10)
val newCachedNodeStorage = new CachedNodeStorage(newNodeStorage, testCache)

val cachedStateStorage: StateStorage =
StateStorage(InMemoryPruning(10), newNodeStorage, newCachedNodeStorage, lruCache)
val cachedStateStorage: StateStorage = StateStorage(InMemoryPruning(10), newNodeStorage, lruCache)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,12 @@ class StateStorageSpec extends AnyFlatSpec with Matchers with ScalaCheckProperty
val lruCache = new LruCache[NodeHash, HeapEntry](TestCacheConfig)

val archiveNodeStorage = new ArchiveNodeStorage(nodeStorage)
val archiveStateStorage: StateStorage = StateStorage(ArchivePruning, nodeStorage, cachedNodeStorage, lruCache)
val archiveStateStorage: StateStorage = StateStorage(ArchivePruning, nodeStorage, lruCache)

val refCountNodeStorage = new ReferenceCountNodeStorage(nodeStorage, 10)
val referenceCounteStateStorage: StateStorage =
StateStorage(BasicPruning(10), nodeStorage, cachedNodeStorage, lruCache)
val referenceCounteStateStorage: StateStorage = StateStorage(BasicPruning(10), nodeStorage, lruCache)

val cachedStateStorage: StateStorage = StateStorage(InMemoryPruning(10), nodeStorage, cachedNodeStorage, lruCache)
val cachedStateStorage: StateStorage = StateStorage(InMemoryPruning(10), nodeStorage, lruCache)
val cachedPrunedNodeStorage = new CachedReferenceCountedStorage(nodeStorage, lruCache, changeLog, 10)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import io.iohk.ethereum.proof.ProofVerifyResult.ValidProof
class MerklePatriciaTrieSuite extends AnyFunSuite with ScalaCheckPropertyChecks with ObjectGenerators {

val dataSource: EphemDataSource = EphemDataSource()
val (stateStorage, emptyNodeStorage, _) = StateStorage.createTestStateStorage(dataSource)
val (stateStorage, emptyNodeStorage, cachedNodeStorage) = StateStorage.createTestStateStorage(dataSource)
val emptyEphemNodeStorage: MptStorage = stateStorage.getBackingStorage(0)
val emptyMpt: MerklePatriciaTrie[Array[Byte], Array[Byte]] =
MerklePatriciaTrie[Array[Byte], Array[Byte]](emptyEphemNodeStorage)
Expand Down Expand Up @@ -484,7 +484,7 @@ class MerklePatriciaTrieSuite extends AnyFunSuite with ScalaCheckPropertyChecks

val pruningOffset = 10

val (stateStorage, nodeStorage, cachedNodeStorage) =
val (stateStorage, _, cachedNodeStorage) =
StateStorage.createTestStateStorage(EphemDataSource(), BasicPruning(40))

val referenceCountBlock0 = stateStorage.getBackingStorage(0)
Expand Down