@@ -65,6 +65,7 @@ import Cardano.Slotting.Slot (
6565 at ,
6666 fromWithOrigin ,
6767 )
68+ import Codec.CBOR.Write (toBuilder )
6869import Control.Concurrent.Class.MonadSTM.Strict (
6970 atomically ,
7071 newTVarIO ,
@@ -74,6 +75,7 @@ import Control.Concurrent.Class.MonadSTM.Strict (
7475import Control.Concurrent.STM.TBQueue (TBQueue , newTBQueueIO , readTBQueue , writeTBQueue )
7576import qualified Control.Exception as Exception
7677import qualified Data.ByteString.Base16 as Base16
78+ import qualified Data.ByteString.Builder as Builder
7779import qualified Data.ByteString.Char8 as BS
7880import qualified Data.ByteString.Lazy.Char8 as LBS
7981import qualified Data.ByteString.Short as SBS
@@ -121,6 +123,7 @@ import Ouroboros.Network.Block (HeaderHash, Point (..))
121123import qualified Ouroboros.Network.Point as Point
122124import System.Directory (doesFileExist , listDirectory , removeFile )
123125import System.FilePath (dropExtension , takeExtension , (</>) )
126+ import qualified System.IO as IO
124127import System.Mem (performMajorGC )
125128import Prelude (String , id )
126129
@@ -376,26 +379,24 @@ ledgerStateWriteLoop tracer swQueue codecConfig =
376379 writeLedgerStateFile :: FilePath -> CardanoLedgerState -> IO ()
377380 writeLedgerStateFile file ledger = do
378381 startTime <- getCurrentTime
379- -- TODO: write the builder directly.
380- -- BB.writeFile file $ toBuilder $
381- LBS. writeFile file $
382- Serialize. serialize $
383- encodeCardanoLedgerState
384- ( Consensus. encodeExtLedgerState
385- (encodeDisk codecConfig)
386- (encodeDisk codecConfig)
387- (encodeDisk codecConfig)
388- . forgetLedgerTables
389- )
390- ledger
382+ -- Use streaming builder to avoid loading entire state into memory
383+ IO. withBinaryFile file IO. WriteMode $ \ h -> do
384+ let encoding =
385+ encodeCardanoLedgerState
386+ ( Consensus. encodeExtLedgerState
387+ (encodeDisk codecConfig)
388+ (encodeDisk codecConfig)
389+ (encodeDisk codecConfig)
390+ )
391+ ledger
392+ Builder. hPutBuilder h (toBuilder encoding)
391393 endTime <- getCurrentTime
392394 logInfo tracer $
393395 mconcat
394396 [ " Asynchronously wrote a ledger snapshot to "
395397 , Text. pack file
396398 , " in "
397399 , textShow (diffUTCTime endTime startTime)
398- , " ."
399400 ]
400401
401402mkLedgerStateFilename :: LedgerStateDir -> ExtLedgerState CardanoBlock mk -> Maybe EpochNo -> WithOrigin FilePath
@@ -641,12 +642,13 @@ loadLedgerStateFromFile tracer config delete point lsf = do
641642 safeReadFile :: FilePath -> IO (Either Text CardanoLedgerState )
642643 safeReadFile fp = do
643644 startTime <- getCurrentTime
644- mbs <- Exception. try $ BS. readFile fp
645+ -- Use lazy ByteString to enable streaming read
646+ mbs <- Exception. try $ LBS. readFile fp
645647 case mbs of
646648 Left (err :: IOException ) -> pure $ Left (Text. pack $ displayException err)
647- Right bs -> do
649+ Right lbs -> do
648650 mediumTime <- getCurrentTime
649- case decode bs of
651+ case decode lbs of
650652 Left err -> pure $ Left $ textShow err
651653 Right ls -> do
652654 endTime <- getCurrentTime
@@ -656,7 +658,7 @@ loadLedgerStateFromFile tracer config delete point lsf = do
656658 , renderPoint point
657659 , " . It took "
658660 , textShow (diffUTCTime mediumTime startTime)
659- , " to read from disk and "
661+ , " to read from disk (streaming) and "
660662 , textShow (diffUTCTime endTime mediumTime)
661663 , " to parse."
662664 ]
@@ -665,12 +667,11 @@ loadLedgerStateFromFile tracer config delete point lsf = do
665667 codecConfig :: CodecConfig CardanoBlock
666668 codecConfig = configCodec config
667669
668- decode :: ByteString -> Either DecoderError CardanoLedgerState
669- decode = do
670+ decode :: LBS. ByteString -> Either DecoderError CardanoLedgerState
671+ decode =
670672 Serialize. decodeFullDecoder
671673 " Ledger state file"
672674 decodeState
673- . LBS. fromStrict
674675
675676 decodeState :: (forall s . Decoder s CardanoLedgerState )
676677 decodeState =
0 commit comments