Skip to content

Commit 070a307

Browse files
authored
Merge pull request #1916 from IntersectMBO/1906-add-caching-for-address
1906 - Add cache for address
2 parents e4a0980 + a885d88 commit 070a307

File tree

7 files changed

+163
-126
lines changed

7 files changed

+163
-126
lines changed

cardano-db-sync/src/Cardano/DbSync/Api.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,8 @@ mkSyncEnv trce backend connectionString syncOptions protoInfo nw nwMagic systemS
353353
then
354354
newEmptyCache
355355
CacheCapacity
356-
{ cacheCapacityStake = 100000
356+
{ cacheCapacityAddress = 100000
357+
, cacheCapacityStake = 100000
357358
, cacheCapacityDatum = 250000
358359
, cacheCapacityMultiAsset = 250000
359360
, cacheCapacityTx = 100000

cardano-db-sync/src/Cardano/DbSync/Cache.hs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module Cardano.DbSync.Cache (
1818
queryPrevBlockWithCache,
1919
queryOrInsertStakeAddress,
2020
queryOrInsertRewardAccount,
21+
insertAddressUsingCache,
2122
insertStakeAddress,
2223
queryStakeAddrWithCache,
2324
queryTxIdWithCache,
@@ -31,6 +32,7 @@ module Cardano.DbSync.Cache (
3132

3233
import Cardano.BM.Trace
3334
import qualified Cardano.Db as DB
35+
import qualified Cardano.Db.Schema.Variant.TxOut as V
3436
import Cardano.DbSync.Cache.Epoch (rollbackMapEpochInCache)
3537
import qualified Cardano.DbSync.Cache.FIFO as FIFO
3638
import qualified Cardano.DbSync.Cache.LRU as LRU
@@ -253,6 +255,61 @@ queryPoolKeyWithCache cache cacheUA hsh =
253255
Map.insert hsh phId
254256
pure $ Right phId
255257

258+
insertAddressUsingCache ::
259+
(MonadBaseControl IO m, MonadIO m) =>
260+
CacheStatus ->
261+
CacheAction ->
262+
ByteString ->
263+
V.Address ->
264+
ReaderT SqlBackend m V.AddressId
265+
insertAddressUsingCache cache cacheUA addrRaw vAdrs = do
266+
case cache of
267+
NoCache -> do
268+
-- Directly query the database for the address ID when no caching is active.
269+
mAddrId <- DB.queryAddressId addrRaw
270+
processResult mAddrId
271+
ActiveCache ci -> do
272+
-- Use active cache to attempt fetching the address ID from the cache.
273+
adrs <- liftIO $ readTVarIO (cAddress ci)
274+
case LRU.lookup addrRaw adrs of
275+
Just (addrId, adrs') -> do
276+
-- If found in cache, record a cache hit and update the cache state.
277+
liftIO $ hitAddress (cStats ci)
278+
liftIO $ atomically $ writeTVar (cAddress ci) adrs'
279+
pure addrId
280+
Nothing -> do
281+
-- If not found in cache, log a miss, and query the database.
282+
liftIO $ missAddress (cStats ci)
283+
mAddrId <- DB.queryAddressId addrRaw
284+
processWithCache mAddrId ci
285+
where
286+
processResult mAddrId =
287+
case mAddrId of
288+
-- If address ID isn't found in the database, insert it.
289+
Nothing -> DB.insertAddress vAdrs
290+
-- Return the found address ID.
291+
Just addrId -> pure addrId
292+
293+
processWithCache mAddrId ci =
294+
case mAddrId of
295+
-- If address ID isn't found, insert and possibly cache it.
296+
Nothing -> do
297+
addrId <- DB.insertAddress vAdrs
298+
cacheIfNeeded addrId ci
299+
pure addrId
300+
-- If found, optionally cache it.
301+
Just addrId -> do
302+
cacheIfNeeded addrId ci
303+
pure addrId
304+
305+
cacheIfNeeded addrId ci =
306+
-- Cache the address ID if the caching action specifies it should be cached.
307+
when (shouldCache cacheUA) $
308+
liftIO $
309+
atomically $
310+
modifyTVar (cAddress ci) $
311+
LRU.insert addrRaw addrId
312+
256313
insertPoolKeyWithCache ::
257314
(MonadBaseControl IO m, MonadIO m) =>
258315
CacheStatus ->
@@ -535,6 +592,15 @@ missMAssets :: StrictTVar IO CacheStatistics -> IO ()
535592
missMAssets ref =
536593
atomically $ modifyTVar ref (\cs -> cs {multiAssetsQueries = 1 + multiAssetsQueries cs})
537594

595+
-- Address
596+
hitAddress :: StrictTVar IO CacheStatistics -> IO ()
597+
hitAddress ref =
598+
atomically $ modifyTVar ref (\cs -> cs {addressHits = 1 + addressHits cs, addressQueries = 1 + addressQueries cs})
599+
600+
missAddress :: StrictTVar IO CacheStatistics -> IO ()
601+
missAddress ref =
602+
atomically $ modifyTVar ref (\cs -> cs {addressQueries = 1 + addressQueries cs})
603+
538604
-- Blocks
539605
hitPBlock :: StrictTVar IO CacheStatistics -> IO ()
540606
hitPBlock ref =

cardano-db-sync/src/Cardano/DbSync/Cache/Types.hs

Lines changed: 76 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module Cardano.DbSync.Cache.Types (
3131
) where
3232

3333
import qualified Cardano.Db as DB
34+
import qualified Cardano.Db.Schema.Variant.TxOut as V
3435
import Cardano.DbSync.Cache.FIFO (FIFOCache)
3536
import qualified Cardano.DbSync.Cache.FIFO as FIFO
3637
import Cardano.DbSync.Cache.LRU (LRUCache)
@@ -82,6 +83,7 @@ data CacheInternal = CacheInternal
8283
, cPrevBlock :: !(StrictTVar IO (Maybe (DB.BlockId, ByteString)))
8384
, cStats :: !(StrictTVar IO CacheStatistics)
8485
, cEpoch :: !(StrictTVar IO CacheEpoch)
86+
, cAddress :: !(StrictTVar IO (LRUCache ByteString V.AddressId))
8587
, cTxIds :: !(StrictTVar IO (FIFOCache (Ledger.TxId StandardCrypto) DB.TxId))
8688
}
8789

@@ -96,13 +98,16 @@ data CacheStatistics = CacheStatistics
9698
, multiAssetsQueries :: !Word64
9799
, prevBlockHits :: !Word64
98100
, prevBlockQueries :: !Word64
101+
, addressHits :: !Word64
102+
, addressQueries :: !Word64
99103
, txIdsHits :: !Word64
100104
, txIdsQueries :: !Word64
101105
}
102106

103107
-- CacheCapacity is used to define capacities for different types of cache entries.
104108
data CacheCapacity = CacheCapacity
105-
{ cacheCapacityStake :: !Word64
109+
{ cacheCapacityAddress :: !Word64
110+
, cacheCapacityStake :: !Word64
106111
, cacheCapacityDatum :: !Word64
107112
, cacheCapacityMultiAsset :: !Word64
108113
, cacheCapacityTx :: !Word64
@@ -128,7 +133,7 @@ data CacheEpoch = CacheEpoch
128133
deriving (Show)
129134

130135
textShowStats :: CacheStatus -> IO Text
131-
textShowStats NoCache = pure "NoCache"
136+
textShowStats NoCache = pure "No Caches"
132137
textShowStats (ActiveCache ic) = do
133138
isCacheOptimised <- readTVarIO $ cIsCacheOptimised ic
134139
stats <- readTVarIO $ cStats ic
@@ -137,77 +142,77 @@ textShowStats (ActiveCache ic) = do
137142
datums <- readTVarIO (cDatum ic)
138143
mAssets <- readTVarIO (cMultiAssets ic)
139144
txIds <- readTVarIO (cTxIds ic)
145+
address <- readTVarIO (cAddress ic)
140146
pure $
141147
mconcat
142148
[ "\nCache Statistics:"
143149
, "\n Caches Optimised: " <> textShow isCacheOptimised
144-
, "\n Stake Addresses: "
145-
, "cache sizes: "
146-
, textShow (Map.size $ scStableCache stakeHashRaws)
147-
, " and "
148-
, textShow (LRU.getSize $ scLruCache stakeHashRaws)
149-
, if credsQueries stats == 0
150-
then ""
151-
else ", hit rate: " <> textShow (100 * credsHits stats `div` credsQueries stats) <> "%"
152-
, ", hits: "
153-
, textShow (credsHits stats)
154-
, ", misses: "
155-
, textShow (credsQueries stats - credsHits stats)
156-
, "\n Pools: "
157-
, "cache size: "
158-
, textShow (Map.size pools)
159-
, if poolsQueries stats == 0
160-
then ""
161-
else ", hit rate: " <> textShow (100 * poolsHits stats `div` poolsQueries stats) <> "%"
162-
, ", hits: "
163-
, textShow (poolsHits stats)
164-
, ", misses: "
165-
, textShow (poolsQueries stats - poolsHits stats)
166-
, "\n Datums: "
167-
, "cache capacity: "
168-
, textShow (LRU.getCapacity datums)
169-
, ", cache size: "
170-
, textShow (LRU.getSize datums)
171-
, if datumQueries stats == 0
172-
then ""
173-
else ", hit rate: " <> textShow (100 * datumHits stats `div` datumQueries stats) <> "%"
174-
, ", hits: "
175-
, textShow (datumHits stats)
176-
, ", misses: "
177-
, textShow (datumQueries stats - datumHits stats)
178-
, "\n Multi Assets: "
179-
, "cache capacity: "
180-
, textShow (LRU.getCapacity mAssets)
181-
, ", cache size: "
182-
, textShow (LRU.getSize mAssets)
183-
, if multiAssetsQueries stats == 0
184-
then ""
185-
else ", hit rate: " <> textShow (100 * multiAssetsHits stats `div` multiAssetsQueries stats) <> "%"
186-
, ", hits: "
187-
, textShow (multiAssetsHits stats)
188-
, ", misses: "
189-
, textShow (multiAssetsQueries stats - multiAssetsHits stats)
190-
, "\n Previous Block: "
191-
, if prevBlockQueries stats == 0
192-
then ""
193-
else "hit rate: " <> textShow (100 * prevBlockHits stats `div` prevBlockQueries stats) <> "%"
194-
, ", hits: "
195-
, textShow (prevBlockHits stats)
196-
, ", misses: "
197-
, textShow (prevBlockQueries stats - prevBlockHits stats)
198-
, "\n TxId: "
199-
, "cache size: "
200-
, textShow (FIFO.getSize txIds)
201-
, ", cache capacity: "
202-
, textShow (FIFO.getCapacity txIds)
203-
, if txIdsQueries stats == 0
204-
then ""
205-
else ", hit rate: " <> textShow (100 * txIdsHits stats `div` txIdsQueries stats) <> "%"
206-
, ", hits: "
207-
, textShow (txIdsHits stats)
208-
, ", misses: "
209-
, textShow (txIdsQueries stats - txIdsHits stats)
150+
, textCacheSection "Stake Addresses" (scLruCache stakeHashRaws) (scStableCache stakeHashRaws) (credsHits stats) (credsQueries stats)
151+
, textMapSection "Pools" pools (poolsHits stats) (poolsQueries stats)
152+
, textLruSection "Datums" datums (datumHits stats) (datumQueries stats)
153+
, textLruSection "Addresses" address (addressHits stats) (addressQueries stats)
154+
, textLruSection "Multi Assets" mAssets (multiAssetsHits stats) (multiAssetsQueries stats)
155+
, textPrevBlockSection stats
156+
, textFifoSection "TxId" txIds (txIdsHits stats) (txIdsQueries stats)
210157
]
158+
where
159+
textCacheSection title cacheLru cacheStable hits queries =
160+
mconcat
161+
[ "\n " <> title <> ": "
162+
, "cache sizes: "
163+
, textShow (Map.size cacheStable)
164+
, " and "
165+
, textShow (LRU.getSize cacheLru)
166+
, hitMissStats hits queries
167+
]
168+
169+
textMapSection title cache hits queries =
170+
mconcat
171+
[ "\n " <> title <> ": "
172+
, "cache size: "
173+
, textShow (Map.size cache)
174+
, hitMissStats hits queries
175+
]
176+
177+
textLruSection title cache hits queries =
178+
mconcat
179+
[ "\n " <> title <> ": "
180+
, "cache capacity: "
181+
, textShow (LRU.getCapacity cache)
182+
, ", cache size: "
183+
, textShow (LRU.getSize cache)
184+
, hitMissStats hits queries
185+
]
186+
187+
textFifoSection title cache hits queries =
188+
mconcat
189+
[ "\n " <> title <> ": "
190+
, "cache size: "
191+
, textShow (FIFO.getSize cache)
192+
, ", cache capacity: "
193+
, textShow (FIFO.getCapacity cache)
194+
, hitMissStats hits queries
195+
]
196+
197+
textPrevBlockSection stats =
198+
mconcat
199+
[ "\n Previous Block: "
200+
, hitMissStats (prevBlockHits stats) (prevBlockQueries stats)
201+
]
202+
203+
hitMissStats hits queries =
204+
mconcat
205+
[ hitRate hits queries
206+
, ", hits: "
207+
, textShow hits
208+
, ", misses: "
209+
, textShow (queries - hits)
210+
]
211+
212+
hitRate hits queries =
213+
if queries == 0
214+
then ""
215+
else ", hit rate: " <> textShow (100 * hits `div` queries) <> "%"
211216

212217
useNoCache :: CacheStatus
213218
useNoCache = NoCache
@@ -218,6 +223,7 @@ newEmptyCache CacheCapacity {..} = liftIO $ do
218223
cStake <- newTVarIO (StakeCache Map.empty (LRU.empty cacheCapacityStake))
219224
cPools <- newTVarIO Map.empty
220225
cDatum <- newTVarIO (LRU.empty cacheCapacityDatum)
226+
cAddress <- newTVarIO (LRU.empty cacheCapacityAddress)
221227
cMultiAssets <- newTVarIO (LRU.empty cacheCapacityMultiAsset)
222228
cPrevBlock <- newTVarIO Nothing
223229
cStats <- newTVarIO initCacheStatistics
@@ -234,11 +240,12 @@ newEmptyCache CacheCapacity {..} = liftIO $ do
234240
, cPrevBlock = cPrevBlock
235241
, cStats = cStats
236242
, cEpoch = cEpoch
243+
, cAddress = cAddress
237244
, cTxIds = cTxIds
238245
}
239246

240247
initCacheStatistics :: CacheStatistics
241-
initCacheStatistics = CacheStatistics 0 0 0 0 0 0 0 0 0 0 0 0
248+
initCacheStatistics = CacheStatistics 0 0 0 0 0 0 0 0 0 0 0 0 0 0
242249

243250
initCacheEpoch :: CacheEpoch
244251
initCacheEpoch = CacheEpoch mempty Nothing

cardano-db-sync/src/Cardano/DbSync/Era/Byron/Genesis.hs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import qualified Cardano.Db.Schema.Core.TxOut as C
2121
import qualified Cardano.Db.Schema.Variant.TxOut as V
2222
import Cardano.DbSync.Api
2323
import Cardano.DbSync.Api.Types (SyncEnv (..))
24+
import Cardano.DbSync.Cache (insertAddressUsingCache)
25+
import Cardano.DbSync.Cache.Types (CacheAction (..))
2426
import Cardano.DbSync.Config.Types
2527
import qualified Cardano.DbSync.Era.Byron.Util as Byron
2628
import Cardano.DbSync.Era.Util (liftLookupFail)
@@ -228,10 +230,12 @@ insertTxOutsByron syncEnv disInOut blkId (address, value) = do
228230
DB.TxOutVariantAddress -> do
229231
let addrRaw = serialize' address
230232
vAddress = mkVAddress addrRaw
231-
addrDetailId <- insertAddress addrRaw vAddress
233+
addrDetailId <- insertAddressUsingCache cache UpdateCache addrRaw vAddress
232234
void . DB.insertTxOut $
233235
DB.VTxOutW (mkVTxOut txId addrDetailId) Nothing
234236
where
237+
cache = envCache syncEnv
238+
235239
mkVTxOut :: DB.TxId -> V.AddressId -> V.TxOut
236240
mkVTxOut txId addrDetailId =
237241
V.TxOut
@@ -256,19 +260,7 @@ insertTxOutsByron syncEnv disInOut blkId (address, value) = do
256260
, V.addressStakeAddressId = Nothing -- Byron does not have a stake address.
257261
}
258262

259-
insertAddress ::
260-
(MonadBaseControl IO m, MonadIO m) =>
261-
ByteString ->
262-
V.Address ->
263-
ReaderT SqlBackend m V.AddressId
264-
insertAddress addrRaw vAdrs = do
265-
mAddrId <- DB.queryAddressId addrRaw
266-
case mAddrId of
267-
Nothing -> DB.insertAddress vAdrs
268-
-- this address is already in the database, so we can just return the id to be linked to the txOut.
269-
Just addrId -> pure addrId
270-
271-
-- -----------------------------------------------------------------------------
263+
---------------------------------------------------------------------------------
272264

273265
configGenesisHash :: Byron.Config -> ByteString
274266
configGenesisHash =

0 commit comments

Comments
 (0)