perf: use plain-map FastStore for giga executor snapshots#2917
perf: use plain-map FastStore for giga executor snapshots#2917
Conversation
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>
|
The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ 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
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
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>
| 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
| for k := range keyStrs { | ||
| res = append(res, k) | ||
| } |
Check warning
Code scanning / CodeQL
Iteration over map Warning
| } | ||
|
|
||
| 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
| } | ||
|
|
||
| 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
| for k, v := range cms.stores { | ||
| parents[k] = v | ||
| } |
Check warning
Code scanning / CodeQL
Iteration over map Warning
| for k, v := range cms.parents { | ||
| parents[k] = v | ||
| } |
Check warning
Code scanning / CodeQL
Iteration over map Warning
| for k, v := range cms.gigaStores { | ||
| gigaStores[k] = v | ||
| } |
Check warning
Code scanning / CodeQL
Iteration over map Warning
| for key, s := range stores { | ||
| cms.parents[key] = s | ||
| } |
Check warning
Code scanning / CodeQL
Iteration over map Warning
Summary
cachekv.FastStoreandgigacachekv.FastStoreusing plain maps instead ofsync.Mapfor single-goroutine snapshot stores in the giga executor pathCacheMultiStoreGiga()tocachemulti.Storefor lightweight CMS creation using FastStoreDBImpl.Snapshot()usesCacheMultiStoreGiga()when available (via interface assertion)getOrCreateStoreuses FastStore when CMS is in fast modeSince each OCC task's snapshot stores are owned by a single goroutine,
sync.Map's thread-safety overhead is unnecessary. Plain maps eliminatesync.Mapinternal trie node allocations (newIndirectNode,newEntryNode) andHashTrieMap.Load/Mutex.Lockcontention.Benchmark results (120s, GIGA_EXECUTOR=true GIGA_OCC=true):
Allocation impact:
sync.newIndirectNode: -3.4 GBsync.newEntryNode: -1.2 GBcachekv.NewStore: -1.6 GBTest plan
giga/deps/xevm/statetests passstore/cachekvtests passstore/cachemultitests passgo build ./...clean🤖 Generated with Claude Code