@@ -63,6 +63,7 @@ import Cardano.Slotting.Slot (
6363 at ,
6464 fromWithOrigin ,
6565 )
66+ import Codec.CBOR.Write (toBuilder )
6667import Control.Concurrent.Class.MonadSTM.Strict (
6768 atomically ,
6869 newTVarIO ,
@@ -80,6 +81,7 @@ import Cardano.Ledger.BaseTypes (StrictMaybe)
8081import Cardano.Ledger.Conway.Core as Shelley
8182import Cardano.Ledger.Conway.Governance
8283import qualified Cardano.Ledger.Conway.Governance as Shelley
84+ import qualified Data.ByteString.Builder as Builder
8385import qualified Data.ByteString.Char8 as BS
8486import qualified Data.ByteString.Lazy.Char8 as LBS
8587import qualified Data.ByteString.Short as SBS
@@ -132,6 +134,7 @@ import Ouroboros.Network.Block (HeaderHash, Point (..), blockNo)
132134import qualified Ouroboros.Network.Point as Point
133135import System.Directory (doesFileExist , listDirectory , removeFile )
134136import System.FilePath (dropExtension , takeExtension , (</>) )
137+ import qualified System.IO as IO
135138import System.Mem (performMajorGC )
136139import Prelude (String , id )
137140
@@ -380,25 +383,24 @@ ledgerStateWriteLoop tracer swQueue codecConfig =
380383 writeLedgerStateFile :: FilePath -> CardanoLedgerState -> IO ()
381384 writeLedgerStateFile file ledger = do
382385 startTime <- getCurrentTime
383- -- TODO: write the builder directly.
384- -- BB.writeFile file $ toBuilder $
385- LBS. writeFile file $
386- Serialize. serialize $
387- encodeCardanoLedgerState
388- ( Consensus. encodeExtLedgerState
389- (encodeDisk codecConfig)
390- (encodeDisk codecConfig)
391- (encodeDisk codecConfig )
392- )
393- ledger
386+ -- Use streaming builder to avoid loading entire state into memory
387+ IO. withBinaryFile file IO. WriteMode $ \ h -> do
388+ let encoding =
389+ encodeCardanoLedgerState
390+ ( Consensus. encodeExtLedgerState
391+ (encodeDisk codecConfig)
392+ (encodeDisk codecConfig)
393+ (encodeDisk codecConfig)
394+ )
395+ ledger
396+ Builder. hPutBuilder h (toBuilder encoding)
394397 endTime <- getCurrentTime
395398 logInfo tracer $
396399 mconcat
397400 [ " Asynchronously wrote a ledger snapshot to "
398401 , Text. pack file
399402 , " in "
400403 , textShow (diffUTCTime endTime startTime)
401- , " ."
402404 ]
403405
404406mkLedgerStateFilename :: LedgerStateDir -> ExtLedgerState CardanoBlock -> Maybe EpochNo -> WithOrigin FilePath
@@ -643,12 +645,13 @@ loadLedgerStateFromFile tracer config delete point lsf = do
643645 safeReadFile :: FilePath -> IO (Either Text CardanoLedgerState )
644646 safeReadFile fp = do
645647 startTime <- getCurrentTime
646- mbs <- Exception. try $ BS. readFile fp
648+ -- Use lazy ByteString to enable streaming read
649+ mbs <- Exception. try $ LBS. readFile fp
647650 case mbs of
648651 Left (err :: IOException ) -> pure $ Left (Text. pack $ displayException err)
649- Right bs -> do
652+ Right lbs -> do
650653 mediumTime <- getCurrentTime
651- case decode bs of
654+ case decode lbs of
652655 Left err -> pure $ Left $ textShow err
653656 Right ls -> do
654657 endTime <- getCurrentTime
@@ -658,7 +661,7 @@ loadLedgerStateFromFile tracer config delete point lsf = do
658661 , renderPoint point
659662 , " . It took "
660663 , textShow (diffUTCTime mediumTime startTime)
661- , " to read from disk and "
664+ , " to read from disk (streaming) and "
662665 , textShow (diffUTCTime endTime mediumTime)
663666 , " to parse."
664667 ]
@@ -667,12 +670,11 @@ loadLedgerStateFromFile tracer config delete point lsf = do
667670 codecConfig :: CodecConfig CardanoBlock
668671 codecConfig = configCodec config
669672
670- decode :: ByteString -> Either DecoderError CardanoLedgerState
671- decode = do
673+ decode :: LBS. ByteString -> Either DecoderError CardanoLedgerState
674+ decode =
672675 Serialize. decodeFullDecoder
673676 " Ledger state file"
674677 decodeState
675- . LBS. fromStrict
676678
677679 decodeState :: (forall s . Decoder s CardanoLedgerState )
678680 decodeState =
0 commit comments