git.delta.rocks / jrsonnet / refs/commits / 337d066dc72d

difftreelog

perf std ast codegen

Лач2020-06-27parent: #0ed995f.patch.diff
in: master

5 files changed

modifiedCargo.lockdiffbeforeafterboth
142 "jsonnet-stdlib",142 "jsonnet-stdlib",
143 "md5",143 "md5",
144 "serde",144 "serde",
145 "structdump",
145]146]
146147
147[[package]]148[[package]]
148name = "jsonnet-parser"149name = "jsonnet-parser"
149version = "0.1.0"150version = "0.1.0"
150dependencies = [151dependencies = [
151 "bincode",
152 "jsonnet-stdlib",152 "jsonnet-stdlib",
153 "peg",153 "peg",
154 "serde",154 "serde",
155 "structdump",
156 "structdump-derive",
155 "unescape",157 "unescape",
156]158]
157159
247249
248[[package]]250[[package]]
249name = "quote"251name = "quote"
250version = "1.0.5"252version = "1.0.7"
251source = "registry+https://github.com/rust-lang/crates.io-index"253source = "registry+https://github.com/rust-lang/crates.io-index"
252checksum = "42934bc9c8ab0d3b273a16d8551c8f0fcff46be73276ca083ec2414c15c4ba5e"254checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
253dependencies = [255dependencies = [
254 "proc-macro2",256 "proc-macro2",
255]257]
274 "syn",276 "syn",
275]277]
278
279[[package]]
280name = "structdump"
281version = "0.1.2"
282source = "registry+https://github.com/rust-lang/crates.io-index"
283checksum = "2e16ec33a0342fdb67d13913b4ffae6527ebccfa04b5d7da174bdc7a31db29b8"
284
285[[package]]
286name = "structdump-derive"
287version = "0.1.2"
288source = "registry+https://github.com/rust-lang/crates.io-index"
289checksum = "06c337fdc077e02ccbfcc62af0090564a4af342975c3b7be09705efab90c1888"
290dependencies = [
291 "proc-macro2",
292 "quote",
293 "syn",
294]
276295
277[[package]]296[[package]]
278name = "syn"297name = "syn"
modifiedcrates/jsonnet-evaluator/Cargo.tomldiffbeforeafterboth
9[features]9[features]
10default = ["serialized-stdlib", "faster"]10default = ["serialized-stdlib", "faster"]
11# Serializes standard library AST instead of parsing them every run11# Serializes standard library AST instead of parsing them every run
12serialized-stdlib = ["serde", "bincode"]12serialized-stdlib = ["serde", "bincode", "jsonnet-parser/deserialize"]
13# Same as above, but with generated code instead of serde. Reduces memory usage, but increases binary size and compilation time
14codegenerated-stdlib = []
13# Replace some standard library functions with faster implementations15# Replace some standard library functions with faster implementations (I.e manifestJsonEx)
14# Library works fine without this feature, but requires more memory and time for std function calls16# Library works fine without this feature, but requires more memory and time for std function calls
15faster = []17faster = []
1618
21indexmap = "1.4.0"23indexmap = "1.4.0"
22md5 = "0.7.0"24md5 = "0.7.0"
2325
24[dependencies.serde]26serde = { version = "1.0.114", optional = true }
25version = "1.0.114"27bincode = { version = "1.3.1", optional = true }
26optional = true
27
28[dependencies.bincode]
29version = "1.3.1"
30optional = true
3128
32[build-dependencies]29[build-dependencies]
33jsonnet-parser = { path = "../jsonnet-parser" }30jsonnet-parser = { path = "../jsonnet-parser", features = ["dump", "serialize", "deserialize"] }
34jsonnet-stdlib = { path = "../jsonnet-stdlib" }31jsonnet-stdlib = { path = "../jsonnet-stdlib" }
32structdump = "0.1.2"
35serde = "1.0.114"33serde = "1.0.114"
36bincode = "1.3.1"34bincode = "1.3.1"
3735
modifiedcrates/jsonnet-evaluator/README.mddiffbeforeafterboth
22
3Interpreter for parsed jsonnet tree3Interpreter for parsed jsonnet tree
44
5## Standard library
6
7jsonnet stdlib is embedded into evaluator, but there is different modes for this:
8
9- `codegenerated-stdlib`
10 - generates source code for reproducing stdlib AST ([Example](https://gist.githubusercontent.com/CertainLach/7b3149df556f3406f5e9368aaa9f32ec/raw/0c80d8ab9aa7b9288c6219a2779cb2ab37287669/a.rs))
11 - fastest on interpretation, slowest on compilation (it takes more than 5 minutes to optimize them by llvm)
12- `serialized-stdlib`
13 - serializes standard library AST using serde
14 - slower than `codegenerated-stdlib` at runtime, but have no compilation speed penality
15- none
16 - leaves only stdlib source code in binary, processing them same way as user supplied data
17 - slowest (as it involves parsing of standard library source code)
18
19Because of `codegenerated-stdlib` compilation slowdown, `serialized-stdlib` is used by default
20
21### Benchmark
22
23Can also be run via `cargo bench`
24
25```md
26# codegenerated-stdlib
27test tests::bench_codegen ... bench: 401,696 ns/iter (+/- 38,521)
28# serialized-stdlib
29test tests::bench_serialize ... bench: 1,763,999 ns/iter (+/- 76,211)
30# none
31test tests::bench_parse ... bench: 7,206,164 ns/iter (+/- 1,067,418)
32```
33
5## Intristics34## Intristics
635
7Some functions from stdlib are implemented as intristics36Some functions from stdlib are implemented as intristics
modifiedcrates/jsonnet-evaluator/build.rsdiffbeforeafterboth
10 path::{Path, PathBuf},10 path::{Path, PathBuf},
11 rc::Rc,11 rc::Rc,
12};12};
13use structdump::CodegenResult;
1314
14fn main() {15fn main() {
15 let parsed = parse(16 let parsed = parse(
46 } else {47 } else {
47 parsed48 parsed
48 };49 };
50 {
51 let mut codegen = CodegenResult::default();
52 let code = codegen.codegen(&parsed);
4953
50 let out_dir = env::var("OUT_DIR").unwrap();54 let out_dir = env::var("OUT_DIR").unwrap();
55 let dest_path = Path::new(&out_dir).join("stdlib.rs");
56 let mut f = File::create(&dest_path).unwrap();
57 f.write_all(&code.as_bytes()).unwrap();
58 }
59 {
60 let out_dir = env::var("OUT_DIR").unwrap();
51 let dest_path = Path::new(&out_dir).join("stdlib.bincode");61 let dest_path = Path::new(&out_dir).join("stdlib.bincode");
52 let mut f = File::create(&dest_path).unwrap();62 let mut f = File::create(&dest_path).unwrap();
53 f.write_all(&serialize(&parsed).expect("serialize"))63 f.write_all(&serialize(&parsed).unwrap()).unwrap();
54 .unwrap();64 }
55}65}
5666
modifiedcrates/jsonnet-evaluator/src/lib.rsdiffbeforeafterboth
1#![feature(box_syntax, box_patterns)]1#![feature(box_syntax, box_patterns)]
2#![feature(type_alias_impl_trait)]2#![feature(type_alias_impl_trait)]
3#![feature(debug_non_exhaustive)]3#![feature(debug_non_exhaustive)]
4#![feature(test)]
4#![allow(macro_expanded_macro_exports_accessed_by_absolute_paths)]5#![allow(macro_expanded_macro_exports_accessed_by_absolute_paths)]
6
7extern crate test;
8
5mod ctx;9mod ctx;
6mod dynamic;10mod dynamic;
228 let std_path = Rc::new(PathBuf::from("std.jsonnet"));232 let std_path = Rc::new(PathBuf::from("std.jsonnet"));
229 self.run_in_state(|| {233 self.run_in_state(|| {
230 use jsonnet_stdlib::STDLIB_STR;234 use jsonnet_stdlib::STDLIB_STR;
235 let mut parsed = false;
236 #[cfg(feature = "codegenerated-stdlib")]
237 if !parsed {
238 parsed = true;
239 #[allow(clippy::all)]
240 let stdlib = {
241 use jsonnet_parser::*;
242 include!(concat!(env!("OUT_DIR"), "/stdlib.rs"))
243 };
244 self.add_parsed_file(std_path.clone(), STDLIB_STR.to_owned().into(), stdlib)
245 .unwrap();
246 }
247
231 if cfg!(feature = "serialized-stdlib") {248 #[cfg(feature = "serialized-stdlib")]
249 if !parsed {
250 parsed = true;
232 self.add_parsed_file(251 self.add_parsed_file(
233 std_path,252 std_path.clone(),
234 STDLIB_STR.to_owned().into(),253 STDLIB_STR.to_owned().into(),
235 bincode::deserialize(include_bytes!(concat!(254 bincode::deserialize(include_bytes!(concat!(
236 env!("OUT_DIR"),255 env!("OUT_DIR"),
239 .expect("deserialize stdlib"),258 .expect("deserialize stdlib"),
240 )259 )
241 .unwrap();260 .unwrap();
242 } else {261 }
243 self.add_file(std_path, STDLIB_STR.to_owned().into())262
244 .unwrap();263 if !parsed {
245 }264 self.add_file(std_path, STDLIB_STR.to_owned().into())
265 .unwrap();
266 }
246 let val = self.evaluate_file(&PathBuf::from("std.jsonnet")).unwrap();267 let val = self.evaluate_file(&PathBuf::from("std.jsonnet")).unwrap();
247 self.add_global("std".into(), val);268 self.add_global("std".into(), val);
248 });269 });
663 );684 );
664 }685 }
686
687 use test::Bencher;
688
689 // This test is commented out by default, because of huge compilation slowdown
690 // #[bench]
691 // fn bench_codegen(b: &mut Bencher) {
692 // b.iter(|| {
693 // #[allow(clippy::all)]
694 // let stdlib = {
695 // use jsonnet_parser::*;
696 // include!(concat!(env!("OUT_DIR"), "/stdlib.rs"))
697 // };
698 // stdlib
699 // })
700 // }
701
702 #[bench]
703 fn bench_serialize(b: &mut Bencher) {
704 b.iter(|| {
705 bincode::deserialize::<jsonnet_parser::LocExpr>(include_bytes!(concat!(
706 env!("OUT_DIR"),
707 "/stdlib.bincode"
708 )))
709 .expect("deserialize stdlib")
710 })
711 }
712
713 #[bench]
714 fn bench_parse(b: &mut Bencher) {
715 b.iter(|| {
716 jsonnet_parser::parse(
717 jsonnet_stdlib::STDLIB_STR,
718 &jsonnet_parser::ParserSettings {
719 loc_data: true,
720 file_name: Rc::new(PathBuf::from("std.jsonnet")),
721 },
722 )
723 })
724 }
665}725}
666726