Skip to content

Commit 29c6838

Browse files
author
HuangYi
committed
Problem: many memory allocs in cache store wrapping
Solution: - init cachestore on cachestore lazily. - cleanup some unused stuff. Update store/CHANGELOG.md Signed-off-by: yihuang <huang@crypto.com>
1 parent 2484db0 commit 29c6838

File tree

3 files changed

+42
-38
lines changed

3 files changed

+42
-38
lines changed

store/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
3131
* [#205](https://github.com/crypto-org-chain/cosmos-sdk/pull/205) Support object store.
3232
* [#240](https://github.com/crypto-org-chain/cosmos-sdk/pull/240) Split methods from `MultiStore` into specialized `RootMultiStore`, keep `MultiStore` generic.
3333
* [#241](https://github.com/crypto-org-chain/cosmos-sdk/pull/241) Refactor the cache store to be btree backed, prepare to support copy-on-write atomic branching.
34+
* [#242](https://github.com/crypto-org-chain/cosmos-sdk/pull/242) Init cache on cache lazily, save memory allocations.
3435

3536
## v1.1.0 (March 20, 2024)
3637

store/cachemulti/store.go

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ import (
44
"fmt"
55
"io"
66

7-
dbm "github.com/cosmos/cosmos-db"
8-
9-
"cosmossdk.io/store/dbadapter"
107
"cosmossdk.io/store/tracekv"
118
"cosmossdk.io/store/types"
129
)
@@ -23,12 +20,11 @@ const storeNameCtxKey = "store_name"
2320
// NOTE: a Store (and MultiStores in general) should never expose the
2421
// keys for the substores.
2522
type Store struct {
26-
db types.CacheWrap
2723
stores map[types.StoreKey]types.CacheWrap
28-
keys map[string]types.StoreKey
2924

3025
traceWriter io.Writer
3126
traceContext types.TraceContext
27+
parentStore func(types.StoreKey) types.CacheWrap
3228
}
3329

3430
var _ types.CacheMultiStore = Store{}
@@ -37,29 +33,17 @@ var _ types.CacheMultiStore = Store{}
3733
// CacheWrapper objects and a KVStore as the database. Each CacheWrapper store
3834
// is a branched store.
3935
func NewFromKVStore(
40-
store types.CacheWrapper, stores map[types.StoreKey]types.CacheWrapper,
41-
keys map[string]types.StoreKey, traceWriter io.Writer, traceContext types.TraceContext,
36+
stores map[types.StoreKey]types.CacheWrapper,
37+
traceWriter io.Writer, traceContext types.TraceContext,
4238
) Store {
4339
cms := Store{
44-
db: store.CacheWrap(),
4540
stores: make(map[types.StoreKey]types.CacheWrap, len(stores)),
46-
keys: keys,
4741
traceWriter: traceWriter,
4842
traceContext: traceContext,
4943
}
5044

5145
for key, store := range stores {
52-
if cms.TracingEnabled() {
53-
// only support tracing on KVStore.
54-
if kvstore, ok := store.(types.KVStore); ok {
55-
tctx := cms.traceContext.Clone().Merge(types.TraceContext{
56-
storeNameCtxKey: key.Name(),
57-
})
58-
59-
store = tracekv.NewStore(kvstore, cms.traceWriter, tctx)
60-
}
61-
}
62-
cms.stores[key] = store.CacheWrap()
46+
cms.initStore(key, store)
6347
}
6448

6549
return cms
@@ -68,19 +52,35 @@ func NewFromKVStore(
6852
// NewStore creates a new Store object from a mapping of store keys to
6953
// CacheWrapper objects. Each CacheWrapper store is a branched store.
7054
func NewStore(
71-
db dbm.DB, stores map[types.StoreKey]types.CacheWrapper, keys map[string]types.StoreKey,
55+
stores map[types.StoreKey]types.CacheWrapper,
7256
traceWriter io.Writer, traceContext types.TraceContext,
7357
) Store {
74-
return NewFromKVStore(dbadapter.Store{DB: db}, stores, keys, traceWriter, traceContext)
58+
return NewFromKVStore(stores, traceWriter, traceContext)
7559
}
7660

7761
func newCacheMultiStoreFromCMS(cms Store) Store {
78-
stores := make(map[types.StoreKey]types.CacheWrapper)
79-
for k, v := range cms.stores {
80-
stores[k] = v
62+
return Store{
63+
stores: make(map[types.StoreKey]types.CacheWrap),
64+
traceWriter: cms.traceWriter,
65+
traceContext: cms.traceContext,
66+
parentStore: cms.getCacheWrap,
8167
}
68+
}
69+
70+
func (cms Store) initStore(key types.StoreKey, store types.CacheWrapper) types.CacheWrap {
71+
if cms.TracingEnabled() {
72+
// only support tracing on KVStore.
73+
if kvstore, ok := store.(types.KVStore); ok {
74+
tctx := cms.traceContext.Clone().Merge(types.TraceContext{
75+
storeNameCtxKey: key.Name(),
76+
})
8277

83-
return NewFromKVStore(cms.db, stores, nil, cms.traceWriter, cms.traceContext)
78+
store = tracekv.NewStore(kvstore, cms.traceWriter, tctx)
79+
}
80+
}
81+
cache := store.CacheWrap()
82+
cms.stores[key] = cache
83+
return cache
8484
}
8585

8686
// SetTracer sets the tracer for the MultiStore that the underlying
@@ -118,7 +118,6 @@ func (cms Store) GetStoreType() types.StoreType {
118118

119119
// Write calls Write on each underlying store.
120120
func (cms Store) Write() {
121-
cms.db.Write()
122121
for _, store := range cms.stores {
123122
store.Write()
124123
}
@@ -134,19 +133,23 @@ func (cms Store) CacheMultiStore() types.CacheMultiStore {
134133
return newCacheMultiStoreFromCMS(cms)
135134
}
136135

137-
// GetStore returns an underlying Store by key.
138-
func (cms Store) GetStore(key types.StoreKey) types.Store {
139-
s := cms.stores[key]
140-
if key == nil || s == nil {
136+
func (cms Store) getCacheWrap(key types.StoreKey) types.CacheWrap {
137+
store, ok := cms.stores[key]
138+
if !ok && cms.parentStore != nil {
139+
// load on demand
140+
store = cms.initStore(key, cms.parentStore(key))
141+
}
142+
if key == nil || store == nil {
141143
panic(fmt.Sprintf("kv store with key %v has not been registered in stores", key))
142144
}
143-
return s.(types.Store)
145+
return store
144146
}
145147

146-
func (cms Store) getCacheWrap(key types.StoreKey) types.CacheWrap {
147-
store := cms.stores[key]
148-
if key == nil || store == nil {
149-
panic(fmt.Sprintf("kv store with key %v has not been registered in stores", key))
148+
// GetStore returns an underlying Store by key.
149+
func (cms Store) GetStore(key types.StoreKey) types.Store {
150+
store, ok := cms.getCacheWrap(key).(types.Store)
151+
if !ok {
152+
panic(fmt.Sprintf("store with key %v is not Store", key))
150153
}
151154
return store
152155
}

store/rootmulti/store.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ func (rs *Store) CacheMultiStore() types.CacheMultiStore {
565565
}
566566
stores[k] = store
567567
}
568-
return cachemulti.NewStore(rs.db, stores, rs.keysByName, rs.traceWriter, rs.getTracingContext())
568+
return cachemulti.NewStore(stores, rs.traceWriter, rs.getTracingContext())
569569
}
570570

571571
// CacheMultiStoreWithVersion is analogous to CacheMultiStore except that it
@@ -627,7 +627,7 @@ func (rs *Store) CacheMultiStoreWithVersion(version int64) (types.CacheMultiStor
627627
cachedStores[key] = cacheStore
628628
}
629629

630-
return cachemulti.NewStore(rs.db, cachedStores, rs.keysByName, rs.traceWriter, rs.getTracingContext()), nil
630+
return cachemulti.NewStore(cachedStores, rs.traceWriter, rs.getTracingContext()), nil
631631
}
632632

633633
// GetStore returns a mounted Store for a given StoreKey. If the StoreKey does

0 commit comments

Comments
 (0)