diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 1ddf355c89..4774bfda1f 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -1648,7 +1648,7 @@ checksum = "42276e3f205fe63887cca255aa9a65a63fb72764c30b9a6252a7c7e46994f689" dependencies = [ "byteorder", "dynasm", - "memmap2", + "memmap2 0.2.1", ] [[package]] @@ -4097,6 +4097,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4647a11b578fead29cdbb34d4adef8dd3dc35b876c9c6d5240d83f205abfe96e" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.6.4" @@ -6174,7 +6183,7 @@ dependencies = [ "libc", "log 0.4.14", "lz4", - "memmap2", + "memmap2 0.2.1", "parking_lot 0.11.1", "rand 0.8.4", "snap", @@ -7503,6 +7512,7 @@ name = "sc-chain-spec" version = "4.0.0-dev" dependencies = [ "impl-trait-for-tuples", + "memmap2 0.5.0", "parity-scale-codec", "sc-chain-spec-derive", "sc-network", @@ -11285,7 +11295,7 @@ dependencies = [ "backtrace", "bincode", "lazy_static", - "memmap2", + "memmap2 0.2.1", "more-asserts", "rustc-demangle", "serde", diff --git a/substrate/client/chain-spec/Cargo.toml b/substrate/client/chain-spec/Cargo.toml index 78062e600c..ba96552619 100644 --- a/substrate/client/chain-spec/Cargo.toml +++ b/substrate/client/chain-spec/Cargo.toml @@ -22,3 +22,4 @@ serde_json = "1.0.68" sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } codec = { package = "parity-scale-codec", version = "2.0.0" } +memmap2 = "0.5.0" diff --git a/substrate/client/chain-spec/src/chain_spec.rs b/substrate/client/chain-spec/src/chain_spec.rs index c4db615812..2ddb56a0df 100644 --- a/substrate/client/chain-spec/src/chain_spec.rs +++ b/substrate/client/chain-spec/src/chain_spec.rs @@ -285,10 +285,20 @@ impl ChainSpec { /// Parse json file into a `ChainSpec` pub fn from_json_file(path: PathBuf) -> Result { + // We mmap the file into memory first, as this is *a lot* faster than using + // `serde_json::from_reader`. See https://github.com/serde-rs/json/issues/160 let file = File::open(&path) .map_err(|e| format!("Error opening spec file `{}`: {}", path.display(), e))?; + + // SAFETY: `mmap` is fundamentally unsafe since technically the file can change + // underneath us while it is mapped; in practice it's unlikely to be a problem + let bytes = unsafe { + memmap2::Mmap::map(&file) + .map_err(|e| format!("Error mmaping spec file `{}`: {}", path.display(), e))? + }; + let client_spec = - json::from_reader(file).map_err(|e| format!("Error parsing spec file: {}", e))?; + json::from_slice(&bytes).map_err(|e| format!("Error parsing spec file: {}", e))?; Ok(ChainSpec { client_spec, genesis: GenesisSource::File(path) }) } }