Skip to content

perf: use plain-map FastStore for giga executor snapshots#2917

Open
pdrobnjak wants to merge 4 commits intomainfrom
pd/perf-fast-store-snapshots
Open

perf: use plain-map FastStore for giga executor snapshots#2917
pdrobnjak wants to merge 4 commits intomainfrom
pd/perf-fast-store-snapshots

Conversation

@pdrobnjak
Copy link
Contributor

Summary

  • Add cachekv.FastStore and gigacachekv.FastStore using plain maps instead of sync.Map for single-goroutine snapshot stores in the giga executor path
  • Add CacheMultiStoreGiga() to cachemulti.Store for lightweight CMS creation using FastStore
  • DBImpl.Snapshot() uses CacheMultiStoreGiga() when available (via interface assertion)
  • Lazy store creation in getOrCreateStore uses FastStore when CMS is in fast mode

Since each OCC task's snapshot stores are owned by a single goroutine, sync.Map's thread-safety overhead is unnecessary. Plain maps eliminate sync.Map internal trie node allocations (newIndirectNode, newEntryNode) and HashTrieMap.Load/Mutex.Lock contention.

Benchmark results (120s, GIGA_EXECUTOR=true GIGA_OCC=true):

  • Baseline (7d2cd92): Median 6800 TPS, Avg 6836
  • Candidate (497b13e): Median 7000 TPS, Avg 6879
  • +2.9% median TPS

Allocation impact:

  • sync.newIndirectNode: -3.4 GB
  • sync.newEntryNode: -1.2 GB
  • cachekv.NewStore: -1.6 GB
  • Net sync.Map overhead eliminated: ~4.6 GB

Test plan

  • All giga/deps/xevm/state tests pass
  • All store/cachekv tests pass
  • All store/cachemulti tests pass
  • Full go build ./... clean
  • Benchmark comparison shows no regression

🤖 Generated with Claude Code

Replace sync.Map-based cachekv stores with plain-map FastStore in the
giga executor snapshot path. Since each OCC task's snapshot stores are
owned by a single goroutine, sync.Map's thread-safety overhead is
unnecessary waste.

Changes:
- Add cachekv.FastStore and gigacachekv.FastStore using plain maps
- Add CacheMultiStoreGiga() to cachemulti.Store for lightweight CMS
- DBImpl.Snapshot() uses CacheMultiStoreGiga() when available
- Lazy store creation uses FastStore when CMS is in fast mode

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link

github-actions bot commented Feb 18, 2026

The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedFeb 18, 2026, 2:52 PM

@codecov
Copy link

codecov bot commented Feb 18, 2026

Codecov Report

❌ Patch coverage is 81.10236% with 24 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.26%. Comparing base (07025b9) to head (26e85c7).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
giga/deps/store/fast_cachekv.go 75.64% 17 Missing and 2 partials ⚠️
sei-cosmos/store/cachemulti/store.go 92.85% 2 Missing and 1 partial ⚠️
giga/deps/xevm/state/state.go 71.42% 1 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2917      +/-   ##
==========================================
+ Coverage   57.22%   57.26%   +0.04%     
==========================================
  Files        2094     2100       +6     
  Lines      171956   172535     +579     
==========================================
+ Hits        98400    98808     +408     
- Misses      64739    64871     +132     
- Partials     8817     8856      +39     
Flag Coverage Δ
sei-chain 52.76% <81.10%> (+0.02%) ⬆️
sei-cosmos 48.15% <4.76%> (-0.05%) ⬇️
sei-db 68.72% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
giga/deps/xevm/state/state.go 95.27% <71.42%> (-1.42%) ⬇️
sei-cosmos/store/cachemulti/store.go 79.00% <92.85%> (+4.00%) ⬆️
giga/deps/store/fast_cachekv.go 75.64% <75.64%> (ø)

... and 31 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

pdrobnjak and others added 3 commits February 18, 2026 15:36
Replace the per-entry CValue allocation loop with clear() on both cache
and deleted maps. In the FastStore snapshot chain, parents (FastStore or
VIS) make writes immediately visible, so reads after Write() correctly
fall through to the parent.

This eliminates ~18M CValue object allocations per 30s benchmark run
that were the main contributor to the memclrNoHeapPointers increase
from the FastStore change.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the duplicate sei-cosmos cachekv.FastStore and use the giga
FastStore (giga/deps/store.FastStore) for both regular module stores
and giga stores in the fast CMS path. cachemulti already imports the
giga store package, so this adds no new dependency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
newFastCacheMultiStoreFromCMS was eagerly materializing all parent
stores via cachekv.NewStore for ~50 store keys on every Snapshot,
even though only 3-4 stores are accessed per EVM transaction.

Now passes both stores and parents through to the child CMS,
letting getOrCreateStore create FastStore wrappers lazily on demand.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment on lines +132 to +142
for k, v := range store.cache {
kbz := []byte(k)
if bytes.Compare(kbz, start) < 0 || bytes.Compare(kbz, end) >= 0 {
continue
}
if v.Value() == nil {
delete(keyStrs, k)
} else {
keyStrs[k] = struct{}{}
}
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
Comment on lines +143 to +145
for k := range keyStrs {
res = append(res, k)
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
}

func (store *FastStore) Iterator(start, end []byte) types.Iterator {
panic("unexpected iterator call on fast giga cachekv store")

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

Possible panics in BeginBock- or EndBlock-related consensus methods could cause a chain halt
}

func (store *FastStore) ReverseIterator(start, end []byte) types.Iterator {
panic("unexpected reverse iterator call on fast giga cachekv store")

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

Possible panics in BeginBock- or EndBlock-related consensus methods could cause a chain halt
Comment on lines +152 to +154
for k, v := range cms.stores {
parents[k] = v
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
Comment on lines +155 to +157
for k, v := range cms.parents {
parents[k] = v
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
Comment on lines +161 to +163
for k, v := range cms.gigaStores {
gigaStores[k] = v
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
Comment on lines +189 to +191
for key, s := range stores {
cms.parents[key] = s
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments