Skip to content

feat(x/vm): apply stack-based StateDB snapshot mechamism for precompile call #244

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

Open
wants to merge 20 commits into
base: main
Choose a base branch
from

Conversation

cloudgray
Copy link
Contributor

Description

Summary

  • Applying the stack-based snapshot mechanism achieves the same effect as a deep copy of the original store.
  • Benchmark results show that the stack-based snapshot mechanism uses about 1.4× more memory than CacheMultiStore, but far less than a deep copy—and the gap grows larger as the load increases.

Stack-based Snapshot Mechanism

  • When executing a precompile, a new store layer is added to the top of the stack, and state writes are performed on this new layer.
  • If a revert occurs during execution, the invalid store layers are popped off the stack to ensure that a valid store layer remains at the top.
  • When committing changes, the writes are propagated sequentially from the top of the stack down to the bottom and applied to the initialStore.
  • The Snapshot() method of the new store uses approximately 1.4 times more memory than the previously used CacheMultiStore(), but it provides a more robust structure that avoids edge cases.

Benchmark

memory_usage_full_stack_based_updated

The benchmark results show that the new Snapshot() method uses significantly less memory than a deep copy, and the gap widens as the number of iterations increases.

cms_vs_snapshot_stack_based_updated

Like CacheMultiStore(), the new Snapshot() method exhibits linear memory growth with increasing iterations, using approximately 1.4× more memory than CacheMultiStore()

Closes: #225


Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • tackled an existing issue or discussed with a team member
  • left instructions on how to review the changes
  • targeted the main branch

Reviewers Checklist

All items are required.
Please add a note if the item is not applicable
and please add your handle next to the items reviewed
if you only reviewed selected items.

I have...

  • added a relevant changelog entry to the Unreleased section in CHANGELOG.md
  • confirmed all author checklist items have been addressed
  • confirmed that this PR does not change production code
  • reviewed content
  • tested instructions (if applicable)
  • confirmed all CI checks have passed

@cloudgray cloudgray changed the title Poc/apply cache stack feat(x/vm): apply stack-based StateDB snapshot mechamism for precompile call Jun 24, 2025
@cloudgray cloudgray self-assigned this Jun 24, 2025
@cloudgray cloudgray marked this pull request as ready for review June 25, 2025 14:09
Copy link
Contributor

@zsystm zsystm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cloudgray
Since the actual type of s.cacheCtx.MultiStore() at this point is *snapshotmulti.Store, I think it's clearer to cast it explicitly rather than going through the storetypes.CacheMultiStore interface.

While *snapshotmulti.Store does implement CacheMultiStore, making that implicit assumption here could lead to confusion for future maintainers who aren’t aware of the underlying implementation. Being explicit improves readability and reduces ambiguity in understanding what store we’re operating on.

I checked that there are no errors after the suggested change.

s.ctx.EventManager().EmitEvents(events)
cms.Write()
s.cacheCtx.MultiStore().(storetypes.CacheMultiStore).Write()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
s.cacheCtx.MultiStore().(storetypes.CacheMultiStore).Write()
s.cacheCtx.MultiStore().(*snapshotmulti.Store).Write()

s.cacheCtx = s.cacheCtx.WithMultiStore(snapshotStore)
s.writeCache = func() {
s.ctx.EventManager().EmitEvents(s.cacheCtx.EventManager().Events())
s.cacheCtx.MultiStore().(storetypes.CacheMultiStore).Write()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
s.cacheCtx.MultiStore().(storetypes.CacheMultiStore).Write()
snapshotStore.Write()

kv.Set([]byte(fmt.Sprintf("%s-tx-%d-%d", key.Name(), tx, j)), genBytes(32))
}
snapshot := cms.Snapshot()
benchSink = snapshot
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious — what’s the purpose of benchSink here?

}

func TestSnapshotMultiIndexing(t *testing.T) {
cms, _ := setupStore()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor naming suggestion: would it be possible to rename the cms variable to something like ss or snapshotStore?

Since cms often refers to CacheMultiStore in the SDK context, it might be a bit misleading here, especially if it’s actually a snapshotmulti.Store. Renaming it could help reduce confusion for readers familiar with the SDK naming conventions.

@zsystm
Copy link
Contributor

zsystm commented Jun 26, 2025

@cloudgray
Left a couple of nits, but overall LGTM — nice work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Research Possibility of Keeping CMS instead of Copy()
2 participants