git.delta.rocks / jrsonnet / refs/commits / faa4e4ef05c4

difftreelog

perf use mimalloc instead of jemalloc

Лач2020-06-28parent: #8dc1868.patch.diff
in: master

3 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -36,9 +36,9 @@
 
 [[package]]
 name = "cc"
-version = "1.0.54"
+version = "1.0.55"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311"
+checksum = "b1be3409f94d7bdceeb5f5fac551039d9b3f00e25da7a74fc4d33400a0d96368"
 
 [[package]]
 name = "clap"
@@ -76,12 +76,6 @@
 checksum = "d6173fd61b610d15a7566dd7b7620775627441c4ab9dac8906e17cb93a24b782"
 
 [[package]]
-name = "fs_extra"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674"
-
-[[package]]
 name = "heck"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -97,27 +91,6 @@
 checksum = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe"
 dependencies = [
  "autocfg",
-]
-
-[[package]]
-name = "jemalloc-sys"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45"
-dependencies = [
- "cc",
- "fs_extra",
- "libc",
-]
-
-[[package]]
-name = "jemallocator"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43ae63fcfc45e99ab3d1b29a46782ad679e98436c3169d15a167a1108a724b69"
-dependencies = [
- "jemalloc-sys",
- "libc",
 ]
 
 [[package]]
@@ -126,9 +99,9 @@
 dependencies = [
  "annotate-snippets",
  "clap",
- "jemallocator",
  "jrsonnet-evaluator",
  "jrsonnet-parser",
+ "mimallocator",
 ]
 
 [[package]]
@@ -189,6 +162,25 @@
 checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
 
 [[package]]
+name = "mimalloc-sys"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4aa3cefb626f6ae3d0b2f71c5378c89d2b1d4d7bc246b0ca9a7ee61a4daad291"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "mimallocator"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d44fe4ebf6b538fcf39d9975c2b90bb3232d1ba8e8bffeacd004f27b20c577a"
+dependencies = [
+ "mimalloc-sys",
+]
+
+[[package]]
 name = "os_str_bytes"
 version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
modifiedcmds/jrsonnet/Cargo.tomldiffbeforeafterboth
--- a/cmds/jrsonnet/Cargo.toml
+++ b/cmds/jrsonnet/Cargo.toml
@@ -12,7 +12,8 @@
 jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "1.0.0" }
 jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "1.0.0" }
 annotate-snippets = "0.8.0"
-jemallocator = "0.3.2"
+# TODO: Fix mimalloc compile errors, and use them
+mimallocator = "0.1.3"
 
 [dependencies.clap]
 version = "3.0.0-beta.1"
modifiedcmds/jrsonnet/src/main.rsdiffbeforeafterboth
before · cmds/jrsonnet/src/main.rs
1pub mod location;23use clap::Clap;4use jrsonnet_evaluator::{EvaluationState, LocError, StackTrace, Val};5use jrsonnet_parser::{el, Arg, ArgsDesc, Expr, LocExpr, ParserSettings};6use location::{offset_to_location, CodeLocation};7use std::env::current_dir;8use std::{collections::HashMap, path::PathBuf, rc::Rc, str::FromStr};910#[global_allocator]11static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;1213enum Format {14	None,15	Json,16	Yaml,17}1819impl FromStr for Format {20	type Err = &'static str;21	fn from_str(s: &str) -> Result<Self, Self::Err> {22		Ok(match s {23			"none" => Format::None,24			"json" => Format::Json,25			"yaml" => Format::Yaml,26			_ => return Err("no such format"),27		})28	}29}3031#[derive(PartialEq)]32enum TraceFormat {33	CppJsonnet,34	GoJsonnet,35	Custom,36}37impl FromStr for TraceFormat {38	type Err = &'static str;39	fn from_str(s: &str) -> Result<Self, Self::Err> {40		Ok(match s {41			"cpp" => TraceFormat::CppJsonnet,42			"go" => TraceFormat::GoJsonnet,43			"default" => TraceFormat::Custom,44			_ => return Err("no such format"),45		})46	}47}4849#[derive(Clone)]50struct ExtStr {51	name: String,52	value: String,53}54impl FromStr for ExtStr {55	type Err = &'static str;56	fn from_str(s: &str) -> Result<Self, Self::Err> {57		let out: Vec<_> = s.split('=').collect();58		match out.len() {59			1 => Ok(ExtStr {60				name: out[0].to_owned(),61				value: std::env::var(out[0]).or(Err("missing env var"))?,62			}),63			2 => Ok(ExtStr {64				name: out[0].to_owned(),65				value: out[1].to_owned(),66			}),67			_ => Err("bad ext-str syntax"),68		}69	}70}7172#[derive(Clap)]73#[clap(version = "0.1.0", author = "Lach <iam@lach.pw>")]74struct Opts {75	#[clap(long, about = "Disable global std variable")]76	no_stdlib: bool,77	#[clap(long, about = "Add external string")]78	ext_str: Vec<ExtStr>,79	#[clap(long, about = "Add external string from code")]80	ext_code: Vec<ExtStr>,81	#[clap(long, about = "Add TLA")]82	tla_str: Vec<ExtStr>,83	#[clap(long, about = "Add TLA from code")]84	tla_code: Vec<ExtStr>,85	#[clap(long, short = "f", default_value = "json", possible_values = &["none", "json", "yaml"], about = "Output format, wraps resulting value to corresponding std.manifest call")]86	format: Format,87	#[clap(long, default_value = "default", possible_values = &["cpp", "go", "default"], about = "Emulated needed stacktrace display")]88	trace_format: TraceFormat,8990	#[clap(91		long,92		short = "s",93		default_value = "200",94		about = "Number of allowed stack frames"95	)]96	max_stack: usize,97	#[clap(98		long,99		short = "t",100		default_value = "20",101		about = "Max length of stack trace before cropping"102	)]103	max_trace: usize,104105	#[clap(long, short = "J", about = "Library search dir")]106	jpath: Vec<PathBuf>,107108	#[clap(109		long,110		default_value = "3",111		about = "When using --format, this option specifies string to pad output with"112	)]113	line_padding: usize,114115	#[clap(about = "File to compile", index = 1)]116	input: String,117}118119fn main() {120	let opts: Opts = Opts::parse();121	let evaluator = jrsonnet_evaluator::EvaluationState::default();122	evaluator.set_max_trace(opts.max_trace);123	evaluator.set_max_stack(opts.max_stack);124	evaluator.set_import_resolver(Box::new(jrsonnet_evaluator::FileImportResolver {125		library_paths: opts.jpath.clone(),126	}));127	if !opts.no_stdlib {128		evaluator.with_stdlib();129	}130	for ExtStr { name, value } in opts.ext_str.iter().cloned() {131		evaluator.add_ext_var(name.into(), Val::Str(value.into()));132	}133	for ExtStr { name, value } in opts.ext_code.iter().cloned() {134		evaluator.add_ext_var(name.into(), evaluator.parse_evaluate_raw(&value).unwrap());135	}136	let mut input = current_dir().unwrap();137	input.push(opts.input.clone());138	let code_string = String::from_utf8(std::fs::read(opts.input.clone()).unwrap()).unwrap();139	if let Err(e) = evaluator.add_file(Rc::new(input.clone()), code_string.clone().into()) {140		print_syntax_error(e, &input, &code_string);141		std::process::exit(1);142	}143	let result = evaluator.evaluate_file(&input);144	match result {145		Ok(v) => {146			let v = match v {147				Val::Func(f) => {148					let mut desc_map = HashMap::new();149					for ExtStr { name, value } in opts.tla_str.iter().cloned() {150						desc_map.insert(name, el!(Expr::Str(value.into())));151					}152					for ExtStr { name, value } in opts.tla_code.iter().cloned() {153						desc_map.insert(154							name,155							jrsonnet_parser::parse(156								&value,157								&ParserSettings {158									file_name: Rc::new(PathBuf::new()),159									loc_data: false,160								},161							)162							.unwrap(),163						);164					}165					evaluator.add_global("__tmp__tlf__".into(), Val::Func(f));166					evaluator167						.evaluate_raw(el!(Expr::Apply(168							el!(Expr::Var("__tmp__tlf__".into())),169							ArgsDesc(desc_map.into_iter().map(|(k, v)| Arg(Some(k), v)).collect()),170							false,171						)))172						.unwrap()173				}174				v => v,175			};176			let v = evaluator.run_in_state(|| match opts.format {177				Format::Json => Ok(Val::Str(v.into_json(opts.line_padding)?)),178				Format::Yaml => {179					evaluator.add_global("__tmp__to_yaml__".into(), v);180					evaluator.parse_evaluate_raw("std.manifestYamlDoc(__tmp__to_yaml__, \"  \")")181				}182				_ => Ok(v),183			});184			let v = match v {185				Ok(v) => v,186				Err(err) => {187					print_error(&err, evaluator, &opts);188					std::process::exit(1);189				}190			};191			match v {192				Val::Str(s) => println!("{}", s),193				Val::Num(n) => println!("{}", n),194				_v => eprintln!(195					"jsonnet output is not a string.\nDid you forgot to set --format, or wrap your data with std.manifestJson?"196				),197			}198		}199		Err(err) => {200			print_error(&err, evaluator, &opts);201			std::process::exit(1);202		}203	}204}205206fn print_error(err: &LocError, evaluator: EvaluationState, opts: &Opts) {207	println!("Error: {:?}", err.0);208	print_trace(&(err.1), evaluator, &opts);209}210211fn print_syntax_error(error: jrsonnet_parser::ParseError, file: &PathBuf, code: &str) {212	use annotate_snippets::{213		display_list::{DisplayList, FormatOptions},214		snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation},215	};216	//&("Expected: ".to_owned() + error.expected)217	let origin = file.to_str().unwrap();218	let error_message = format!("Expected: {}", error.expected);219	let snippet = Snippet {220		opt: FormatOptions {221			color: true,222			..Default::default()223		},224		title: Some(Annotation {225			label: Some(&error_message),226			id: None,227			annotation_type: AnnotationType::Error,228		}),229		footer: vec![],230		slices: vec![Slice {231			source: &code,232			line_start: 1,233			origin: Some(origin),234			fold: false,235			annotations: vec![SourceAnnotation {236				label: "At this position",237				annotation_type: AnnotationType::Error,238				range: (error.location.offset, error.location.offset + 1),239			}],240		}],241	};242243	let dl = DisplayList::from(snippet);244	println!("{}", dl);245}246247fn print_trace(trace: &StackTrace, evaluator: EvaluationState, opts: &Opts) {248	use annotate_snippets::{249		display_list::{DisplayList, FormatOptions},250		snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation},251	};252	for item in trace.0.iter() {253		let desc = &item.1;254		let source = item.0.clone();255		let code = evaluator.get_source(&source.0);256		if code.is_none() {257			continue;258		}259		let code = code.unwrap();260		let start_end = offset_to_location(&code, &[source.1, source.2]);261		if opts.trace_format == TraceFormat::Custom {262			let source_fragment: String = code263				.chars()264				.skip(start_end[0].line_start_offset)265				.take(start_end[1].line_end_offset - start_end[0].line_start_offset)266				.collect();267			let snippet = Snippet {268				opt: FormatOptions {269					color: true,270					..Default::default()271				},272				title: Some(Annotation {273					label: Some(&item.1),274					id: None,275					annotation_type: AnnotationType::Error,276				}),277				footer: vec![],278				slices: vec![Slice {279					source: &source_fragment,280					line_start: start_end[0].line,281					origin: Some(&source.0.to_str().unwrap()),282					fold: false,283					annotations: vec![SourceAnnotation {284						label: desc,285						annotation_type: AnnotationType::Error,286						range: (287							source.1 - start_end[0].line_start_offset,288							source.2 - start_end[0].line_start_offset,289						),290					}],291				}],292			};293294			let dl = DisplayList::from(snippet);295			println!("{}", dl);296		} else {297			print_jsonnet_pair(298				source.0.to_str().unwrap(),299				&start_end[0],300				&start_end[1],301				opts.trace_format == TraceFormat::GoJsonnet,302			);303		}304	}305}306307fn print_jsonnet_pair(file: &str, start: &CodeLocation, end: &CodeLocation, is_go: bool) {308	if is_go {309		print!("        ");310	} else {311		print!("  ");312	}313	print!("{}:", file);314	if start.line == end.line {315		// IDK why, but this is the behavior original jsonnet cpp impl shows316		if start.column == end.column || !is_go && start.column + 1 == end.column {317			println!("{}:{}", start.line, end.column)318		} else {319			println!("{}:{}-{}", start.line, start.column, end.column);320		}321	} else {322		println!(323			"({}:{})-({}:{})",324			start.line, end.column, start.line, end.column325		);326	}327}
after · cmds/jrsonnet/src/main.rs
1pub mod location;23use clap::Clap;4use jrsonnet_evaluator::{EvaluationState, LocError, StackTrace, Val};5use jrsonnet_parser::{el, Arg, ArgsDesc, Expr, LocExpr, ParserSettings};6use location::{offset_to_location, CodeLocation};7use std::env::current_dir;8use std::{collections::HashMap, path::PathBuf, rc::Rc, str::FromStr};910#[global_allocator]11static GLOBAL: mimallocator::Mimalloc = mimallocator::Mimalloc;1213enum Format {14	None,15	Json,16	Yaml,17}1819impl FromStr for Format {20	type Err = &'static str;21	fn from_str(s: &str) -> Result<Self, Self::Err> {22		Ok(match s {23			"none" => Format::None,24			"json" => Format::Json,25			"yaml" => Format::Yaml,26			_ => return Err("no such format"),27		})28	}29}3031#[derive(PartialEq)]32enum TraceFormat {33	CppJsonnet,34	GoJsonnet,35	Custom,36}37impl FromStr for TraceFormat {38	type Err = &'static str;39	fn from_str(s: &str) -> Result<Self, Self::Err> {40		Ok(match s {41			"cpp" => TraceFormat::CppJsonnet,42			"go" => TraceFormat::GoJsonnet,43			"default" => TraceFormat::Custom,44			_ => return Err("no such format"),45		})46	}47}4849#[derive(Clone)]50struct ExtStr {51	name: String,52	value: String,53}54impl FromStr for ExtStr {55	type Err = &'static str;56	fn from_str(s: &str) -> Result<Self, Self::Err> {57		let out: Vec<_> = s.split('=').collect();58		match out.len() {59			1 => Ok(ExtStr {60				name: out[0].to_owned(),61				value: std::env::var(out[0]).or(Err("missing env var"))?,62			}),63			2 => Ok(ExtStr {64				name: out[0].to_owned(),65				value: out[1].to_owned(),66			}),67			_ => Err("bad ext-str syntax"),68		}69	}70}7172#[derive(Clap)]73#[clap(version = "0.1.0", author = "Lach <iam@lach.pw>")]74struct Opts {75	#[clap(long, about = "Disable global std variable")]76	no_stdlib: bool,77	#[clap(long, about = "Add external string")]78	ext_str: Vec<ExtStr>,79	#[clap(long, about = "Add external string from code")]80	ext_code: Vec<ExtStr>,81	#[clap(long, about = "Add TLA")]82	tla_str: Vec<ExtStr>,83	#[clap(long, about = "Add TLA from code")]84	tla_code: Vec<ExtStr>,85	#[clap(long, short = "f", default_value = "json", possible_values = &["none", "json", "yaml"], about = "Output format, wraps resulting value to corresponding std.manifest call")]86	format: Format,87	#[clap(long, default_value = "default", possible_values = &["cpp", "go", "default"], about = "Emulated needed stacktrace display")]88	trace_format: TraceFormat,8990	#[clap(91		long,92		short = "s",93		default_value = "200",94		about = "Number of allowed stack frames"95	)]96	max_stack: usize,97	#[clap(98		long,99		short = "t",100		default_value = "20",101		about = "Max length of stack trace before cropping"102	)]103	max_trace: usize,104105	#[clap(long, short = "J", about = "Library search dir")]106	jpath: Vec<PathBuf>,107108	#[clap(109		long,110		default_value = "3",111		about = "When using --format, this option specifies string to pad output with"112	)]113	line_padding: usize,114115	#[clap(about = "File to compile", index = 1)]116	input: String,117}118119fn main() {120	let opts: Opts = Opts::parse();121	let evaluator = jrsonnet_evaluator::EvaluationState::default();122	evaluator.set_max_trace(opts.max_trace);123	evaluator.set_max_stack(opts.max_stack);124	evaluator.set_import_resolver(Box::new(jrsonnet_evaluator::FileImportResolver {125		library_paths: opts.jpath.clone(),126	}));127	if !opts.no_stdlib {128		evaluator.with_stdlib();129	}130	for ExtStr { name, value } in opts.ext_str.iter().cloned() {131		evaluator.add_ext_var(name.into(), Val::Str(value.into()));132	}133	for ExtStr { name, value } in opts.ext_code.iter().cloned() {134		evaluator.add_ext_var(name.into(), evaluator.parse_evaluate_raw(&value).unwrap());135	}136	let mut input = current_dir().unwrap();137	input.push(opts.input.clone());138	let code_string = String::from_utf8(std::fs::read(opts.input.clone()).unwrap()).unwrap();139	if let Err(e) = evaluator.add_file(Rc::new(input.clone()), code_string.clone().into()) {140		print_syntax_error(e, &input, &code_string);141		std::process::exit(1);142	}143	let result = evaluator.evaluate_file(&input);144	match result {145		Ok(v) => {146			let v = match v {147				Val::Func(f) => {148					let mut desc_map = HashMap::new();149					for ExtStr { name, value } in opts.tla_str.iter().cloned() {150						desc_map.insert(name, el!(Expr::Str(value.into())));151					}152					for ExtStr { name, value } in opts.tla_code.iter().cloned() {153						desc_map.insert(154							name,155							jrsonnet_parser::parse(156								&value,157								&ParserSettings {158									file_name: Rc::new(PathBuf::new()),159									loc_data: false,160								},161							)162							.unwrap(),163						);164					}165					evaluator.add_global("__tmp__tlf__".into(), Val::Func(f));166					evaluator167						.evaluate_raw(el!(Expr::Apply(168							el!(Expr::Var("__tmp__tlf__".into())),169							ArgsDesc(desc_map.into_iter().map(|(k, v)| Arg(Some(k), v)).collect()),170							false,171						)))172						.unwrap()173				}174				v => v,175			};176			let v = evaluator.run_in_state(|| match opts.format {177				Format::Json => Ok(Val::Str(v.into_json(opts.line_padding)?)),178				Format::Yaml => {179					evaluator.add_global("__tmp__to_yaml__".into(), v);180					evaluator.parse_evaluate_raw("std.manifestYamlDoc(__tmp__to_yaml__, \"  \")")181				}182				_ => Ok(v),183			});184			let v = match v {185				Ok(v) => v,186				Err(err) => {187					print_error(&err, evaluator, &opts);188					std::process::exit(1);189				}190			};191			match v {192				Val::Str(s) => println!("{}", s),193				Val::Num(n) => println!("{}", n),194				_v => eprintln!(195					"jsonnet output is not a string.\nDid you forgot to set --format, or wrap your data with std.manifestJson?"196				),197			}198		}199		Err(err) => {200			print_error(&err, evaluator, &opts);201			std::process::exit(1);202		}203	}204}205206fn print_error(err: &LocError, evaluator: EvaluationState, opts: &Opts) {207	println!("Error: {:?}", err.0);208	print_trace(&(err.1), evaluator, &opts);209}210211fn print_syntax_error(error: jrsonnet_parser::ParseError, file: &PathBuf, code: &str) {212	use annotate_snippets::{213		display_list::{DisplayList, FormatOptions},214		snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation},215	};216	//&("Expected: ".to_owned() + error.expected)217	let origin = file.to_str().unwrap();218	let error_message = format!("Expected: {}", error.expected);219	let snippet = Snippet {220		opt: FormatOptions {221			color: true,222			..Default::default()223		},224		title: Some(Annotation {225			label: Some(&error_message),226			id: None,227			annotation_type: AnnotationType::Error,228		}),229		footer: vec![],230		slices: vec![Slice {231			source: &code,232			line_start: 1,233			origin: Some(origin),234			fold: false,235			annotations: vec![SourceAnnotation {236				label: "At this position",237				annotation_type: AnnotationType::Error,238				range: (error.location.offset, error.location.offset + 1),239			}],240		}],241	};242243	let dl = DisplayList::from(snippet);244	println!("{}", dl);245}246247fn print_trace(trace: &StackTrace, evaluator: EvaluationState, opts: &Opts) {248	use annotate_snippets::{249		display_list::{DisplayList, FormatOptions},250		snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation},251	};252	for item in trace.0.iter() {253		let desc = &item.1;254		let source = item.0.clone();255		let code = evaluator.get_source(&source.0);256		if code.is_none() {257			continue;258		}259		let code = code.unwrap();260		let start_end = offset_to_location(&code, &[source.1, source.2]);261		if opts.trace_format == TraceFormat::Custom {262			let source_fragment: String = code263				.chars()264				.skip(start_end[0].line_start_offset)265				.take(start_end[1].line_end_offset - start_end[0].line_start_offset)266				.collect();267			let snippet = Snippet {268				opt: FormatOptions {269					color: true,270					..Default::default()271				},272				title: Some(Annotation {273					label: Some(&item.1),274					id: None,275					annotation_type: AnnotationType::Error,276				}),277				footer: vec![],278				slices: vec![Slice {279					source: &source_fragment,280					line_start: start_end[0].line,281					origin: Some(&source.0.to_str().unwrap()),282					fold: false,283					annotations: vec![SourceAnnotation {284						label: desc,285						annotation_type: AnnotationType::Error,286						range: (287							source.1 - start_end[0].line_start_offset,288							source.2 - start_end[0].line_start_offset,289						),290					}],291				}],292			};293294			let dl = DisplayList::from(snippet);295			println!("{}", dl);296		} else {297			print_jsonnet_pair(298				source.0.to_str().unwrap(),299				&start_end[0],300				&start_end[1],301				opts.trace_format == TraceFormat::GoJsonnet,302			);303		}304	}305}306307fn print_jsonnet_pair(file: &str, start: &CodeLocation, end: &CodeLocation, is_go: bool) {308	if is_go {309		print!("        ");310	} else {311		print!("  ");312	}313	print!("{}:", file);314	if start.line == end.line {315		// IDK why, but this is the behavior original jsonnet cpp impl shows316		if start.column == end.column || !is_go && start.column + 1 == end.column {317			println!("{}:{}", start.line, end.column)318		} else {319			println!("{}:{}-{}", start.line, start.column, end.column);320		}321	} else {322		println!(323			"({}:{})-({}:{})",324			start.line, end.column, start.line, end.column325		);326	}327}