@@ -48,6 +48,8 @@ import Control.Monad
48
48
import qualified Data.Aeson as Aeson
49
49
import qualified Data.ByteString as BS
50
50
import qualified Data.Text as T
51
+ import System.Directory (getFileSize )
52
+ import qualified System.IO.MMap as MMap
51
53
52
54
------------------------------------------------------------------------------
53
55
-- Shelley protocol
@@ -94,12 +96,33 @@ readGenesis :: GenesisFile
94
96
(ShelleyGenesis , GenesisHash )
95
97
readGenesis = readGenesisAny
96
98
99
+ -- | Read a genesis file using a memory-safe strategy.
100
+ --
101
+ -- Genesis files are used in testing and benchmarking to create testnets with
102
+ -- large datasets. To be able to read these files in memory constrained
103
+ -- environments we use a conditional loading strategy: if file is below ~10
104
+ -- megabytes it is entirely read into memory, otherwise the 'ByteString' is
105
+ -- created using `mmap` that uses the virtual memory subsystem to do on-demand
106
+ -- loading.
107
+ -- With current usage and how benchmakring is done only Shelley and Conway are
108
+ -- affected (Shelley's `initialFunds` and Conway's "delegs" and "initialDReps").
97
109
readGenesisAny :: FromJSON genesis
98
110
=> GenesisFile
99
111
-> Maybe GenesisHash
100
112
-> ExceptT GenesisReadError IO (genesis , GenesisHash )
101
113
readGenesisAny (GenesisFile file) mExpectedGenesisHash = do
102
- content <- handleIOExceptT (GenesisReadFileError file) $ BS. readFile file
114
+ content <- handleIOExceptT (GenesisReadFileError file) $ do
115
+ -- Size of the file in 8-bit bytes.
116
+ size <- getFileSize file
117
+ {- - Mainnet files for reference:
118
+ -byron-genesis.json: 1056360 (1.1M)
119
+ -shelley-genesis.json: 2486 (2.5K)
120
+ -alonzo-genesis.json: 9459 (9.3K)
121
+ -conway-genesis.json: 4168 (4.1K)
122
+ --}
123
+ if size >= 10485760 -- 10 megabytes.
124
+ then MMap. mmapFileByteString file Nothing -- MMap version.
125
+ else BS. readFile file -- Non-lazy version.
103
126
genesisHash <- checkExpectedGenesisHash content mExpectedGenesisHash
104
127
genesis <- firstExceptT (GenesisDecodeError file) $ hoistEither $
105
128
Aeson. eitherDecodeStrict' content
0 commit comments