Skip to content

Commit 0a41099

Browse files
committed
ImmutableDB: allow reading concurrently with appending
Read the potentially stale value of the internal state provided by the `StrictMVar` instead of blocking on the `TMVar` in case an appender has locked it. Reads can safely happen concurrently with appends, so this will allow for some more concurrency. I don't expect this to make any impact for a "client" node that is syncing, as it will typically not read from its ImmutableDB, only append to it, which is necessarily sequential. However, a "server" node might have to read headers/blocks from its ImmutableDB to serve to other nodes. Serving multiple requests won't require taking + putting a `TMVar` anymore, it's just reading a `TVar` now. I expect to see the most improvement for a node serving others while it is also still syncing itself. Blocks being appended to the ImmutableDB will happen concurrently with all read requests.
1 parent 954dcc0 commit 0a41099

File tree

1 file changed

+10
-4
lines changed
  • ouroboros-consensus/src/Ouroboros/Consensus/Storage/ImmutableDB/Impl

1 file changed

+10
-4
lines changed

ouroboros-consensus/src/Ouroboros/Consensus/Storage/ImmutableDB/Impl/State.hs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,9 @@ getOpenState :: (HasCallStack, IOLike m)
155155
=> ImmutableDBEnv m hash
156156
-> m (SomePair (HasFS m) (OpenState m hash))
157157
getOpenState ImmutableDBEnv {..} = do
158-
internalState <- readMVar varInternalState
158+
-- We use 'readMVarSTM' to read a potentially stale internal state if
159+
-- somebody's appending to the ImmutableDB at the same time.
160+
internalState <- atomically $ readMVarSTM varInternalState
159161
case internalState of
160162
DbClosed -> throwUserError ClosedDBError
161163
DbOpen openState -> return (SomePair hasFS openState)
@@ -244,15 +246,19 @@ withOpenState ImmutableDBEnv { hasFS = hasFS :: HasFS m h, .. } action = do
244246
where
245247
HasFS{..} = hasFS
246248

249+
-- We use 'readMVarSTM' to read a potentially stale internal state if
250+
-- somebody's appending to the ImmutableDB at the same time. Reads can
251+
-- safely happen concurrently with appends, so this is fine and allows for
252+
-- some extra concurrency.
247253
open :: m (OpenState m hash h)
248-
open = readMVar varInternalState >>= \case
254+
open = atomically (readMVarSTM varInternalState) >>= \case
249255
DbOpen ost -> return ost
250256
DbClosed -> throwUserError ClosedDBError
251257

252258
-- close doesn't take the state that @open@ returned, because the state
253259
-- may have been updated by someone else since we got it (remember we're
254-
-- using 'readMVar' here, 'takeMVar'). So we need to get the most recent
255-
-- state anyway.
260+
-- using 'readMVarSTM' here, not 'takeMVar'). So we need to get the most
261+
-- recent state anyway.
256262
close :: ExitCase (Either ImmutableDBError r)
257263
-> m ()
258264
close ec = case ec of

0 commit comments

Comments
 (0)