@@ -82,8 +82,8 @@ LiveBucketIndex::LiveBucketIndex(BucketManager const& bm, Archive& ar,
82
82
}
83
83
84
84
void
85
- LiveBucketIndex::maybeInitializeCache (size_t bucketListTotalAccounts ,
86
- size_t maxBucketListAccountsToCache ) const
85
+ LiveBucketIndex::maybeInitializeCache (size_t totalBucketListAccountsSizeBytes ,
86
+ Config const & cfg ) const
87
87
{
88
88
// Everything is already in memory, no need for a redundant cache.
89
89
if (mInMemoryIndex )
@@ -109,19 +109,46 @@ LiveBucketIndex::maybeInitializeCache(size_t bucketListTotalAccounts,
109
109
return ;
110
110
}
111
111
112
+ // Convert from MB to bytes, max size for entire BucketList cache
113
+ auto maxBucketListBytesToCache =
114
+ cfg.BUCKETLIST_DB_MEMORY_FOR_CACHING * 1024 * 1024 ;
115
+
112
116
std::unique_lock<std::shared_mutex> lock (mCacheMutex );
113
- if (bucketListTotalAccounts < maxBucketListAccountsToCache )
117
+ if (totalBucketListAccountsSizeBytes < maxBucketListBytesToCache )
114
118
{
115
119
// We can cache the entire bucket
116
- mCache = std::make_unique<CacheT>(bucketListTotalAccounts );
120
+ mCache = std::make_unique<CacheT>(accountsInThisBucket );
117
121
}
118
122
else
119
123
{
120
- double percentAccountsInBucket =
121
- static_cast <double >(accountsInThisBucket) / bucketListTotalAccounts;
122
- auto cacheSize = static_cast <size_t >(bucketListTotalAccounts *
123
- percentAccountsInBucket);
124
- mCache = std::make_unique<CacheT>(cacheSize);
124
+ // The random eviction cache has an entry limit, but we expose a memory
125
+ // limit in the validator config. We can't do an exact 1 to 1 mapping
126
+ // because account entries have different sizes.
127
+ //
128
+ // First we take the fraction of the total BucketList size that this
129
+ // bucket occupies to figure out how much memory to allocate. Then we
130
+ // use the average account size to convert that to an entry count for
131
+ // the cache.
132
+
133
+ auto accountBytesInThisBucket =
134
+ mDiskIndex ->getBucketEntryCounters ().entryTypeSizes .at (
135
+ LedgerEntryTypeAndDurability::ACCOUNT);
136
+
137
+ double fractionOfTotalBucketListBytes =
138
+ static_cast <double >(accountBytesInThisBucket) /
139
+ totalBucketListAccountsSizeBytes;
140
+
141
+ size_t bytesAvailableForBucketCache = static_cast <size_t >(
142
+ maxBucketListBytesToCache * fractionOfTotalBucketListBytes);
143
+
144
+ double averageAccountSize =
145
+ static_cast <double >(accountBytesInThisBucket) /
146
+ accountsInThisBucket;
147
+
148
+ auto accountsToCache = static_cast <size_t >(
149
+ bytesAvailableForBucketCache / averageAccountSize);
150
+
151
+ mCache = std::make_unique<CacheT>(accountsToCache);
125
152
}
126
153
}
127
154
@@ -360,6 +387,18 @@ LiveBucketIndex::operator==(LiveBucketIndex const& in) const
360
387
361
388
return true ;
362
389
}
390
+
391
+ size_t
392
+ LiveBucketIndex::getMaxCacheSize () const
393
+ {
394
+ if (shouldUseCache ())
395
+ {
396
+ std::shared_lock<std::shared_mutex> lock (mCacheMutex );
397
+ return mCache ->maxSize ();
398
+ }
399
+
400
+ return 0 ;
401
+ }
363
402
#endif
364
403
365
404
template LiveBucketIndex::LiveBucketIndex(BucketManager const & bm,
0 commit comments