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

difftreelog

perf(evaluator) cache LazyVal/obj fields

Лач2020-06-01parent: #11818aa.patch.diff
in: master

2 files changed

modifiedcrates/jsonnet-evaluator/src/obj.rsdiffbeforeafterboth
1use crate::{evaluate_binary_op, Binding, Val};1use crate::{evaluate_binary_op, Binding, Val};
2use jsonnet_parser::{BinaryOpType, Visibility};2use jsonnet_parser::{BinaryOpType, Visibility};
3use std::{3use std::{
4 cell::RefCell,
4 collections::{BTreeMap, BTreeSet},5 collections::{BTreeMap, BTreeSet, HashMap},
5 fmt::Debug,6 fmt::Debug,
6 rc::Rc,7 rc::Rc,
7};8};
17pub struct ObjValueInternals {18pub struct ObjValueInternals {
18 super_obj: Option<ObjValue>,19 super_obj: Option<ObjValue>,
19 this_entries: Rc<BTreeMap<String, ObjMember>>,20 this_entries: Rc<BTreeMap<String, ObjMember>>,
21 value_cache: RefCell<HashMap<String, Val>>,
20}22}
21pub struct ObjValue(pub(crate) Rc<ObjValueInternals>);23pub struct ObjValue(pub(crate) Rc<ObjValueInternals>);
22impl Debug for ObjValue {24impl Debug for ObjValue {
48 ObjValue(Rc::new(ObjValueInternals {50 ObjValue(Rc::new(ObjValueInternals {
49 super_obj,51 super_obj,
50 this_entries,52 this_entries,
53 value_cache: RefCell::new(HashMap::new()),
51 }))54 }))
52 }55 }
53 pub fn with_super(&self, super_obj: ObjValue) -> ObjValue {56 pub fn with_super(&self, super_obj: ObjValue) -> ObjValue {
69 fields72 fields
70 }73 }
71 pub fn get(&self, key: &str) -> Option<Val> {74 pub fn get(&self, key: &str) -> Option<Val> {
72 // TODO: Cache get_raw result75 if let Some(v) = self.0.value_cache.borrow().get(key) {
76 return Some(v.clone());
77 }
73 self.get_raw(key, self)78 let v = self.get_raw(key, self).map(|v| v.unwrap_if_lazy());
79 if let Some(v) = v.clone() {
80 self.0.value_cache.borrow_mut().insert(key.to_owned(), v);
81 }
82 v
74 }83 }
75 fn get_raw(&self, key: &str, real_this: &ObjValue) -> Option<Val> {84 fn get_raw(&self, key: &str, real_this: &ObjValue) -> Option<Val> {
76 match (self.0.this_entries.get(key), &self.0.super_obj) {85 match (self.0.this_entries.get(key), &self.0.super_obj) {
modifiedcrates/jsonnet-evaluator/src/val.rsdiffbeforeafterboth
--- a/crates/jsonnet-evaluator/src/val.rs
+++ b/crates/jsonnet-evaluator/src/val.rs
@@ -1,14 +1,54 @@
-use crate::{
-	lazy_binding, rc_fn_helper, Context, FunctionDefault, FunctionRhs, LazyBinding, ObjValue,
-};
+use crate::{lazy_binding, Context, FunctionDefault, FunctionRhs, LazyBinding, ObjValue};
 use closure::closure;
-use jsonnet_parser::{LiteralType, ParamsDesc};
+use jsonnet_parser::ParamsDesc;
 use std::{
+	cell::RefCell,
 	collections::HashMap,
 	fmt::{Debug, Display},
+	rc::Rc,
 };
 
-rc_fn_helper!(LazyVal, lazy_val, dyn Fn() -> Val);
+struct LazyValInternals {
+	pub f: Box<dyn Fn() -> Val>,
+	pub cached: RefCell<Option<Val>>,
+}
+#[derive(Clone)]
+pub struct LazyVal(Rc<LazyValInternals>);
+impl LazyVal {
+	pub fn new(f: Box<dyn Fn() -> Val>) -> Self {
+		LazyVal(Rc::new(LazyValInternals {
+			f,
+			cached: RefCell::new(None),
+		}))
+	}
+	pub fn evaluate(&self) -> Val {
+		{
+			let cached = self.0.cached.borrow();
+			if cached.is_some() {
+				return cached.clone().unwrap();
+			}
+		}
+		let result = (self.0.f)();
+		self.0.cached.borrow_mut().replace(result.clone());
+		result
+	}
+}
+#[macro_export]
+macro_rules! lazy_val {
+	($f: expr) => {
+		$crate::LazyVal::new(Box::new($f))
+	};
+}
+impl Debug for LazyVal {
+	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+		write!(f, "Lazy")
+	}
+}
+impl PartialEq for LazyVal {
+	fn eq(&self, other: &Self) -> bool {
+		Rc::ptr_eq(&self.0, &other.0)
+	}
+}
 
 #[derive(Debug, PartialEq, Clone)]
 pub struct FuncDesc {
@@ -64,7 +104,8 @@
 
 #[derive(Debug, PartialEq, Clone)]
 pub enum Val {
-	Literal(LiteralType),
+	Bool(bool),
+	Null,
 	Str(String),
 	Num(f64),
 	Lazy(LazyVal),
@@ -78,7 +119,7 @@
 impl Val {
 	pub fn unwrap_if_lazy(self) -> Self {
 		if let Val::Lazy(v) = self {
-			v.0().unwrap_if_lazy()
+			v.evaluate().unwrap_if_lazy()
 		} else {
 			self
 		}
@@ -97,7 +138,6 @@
 impl Display for Val {
 	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 		match self {
-			Val::Literal(v) => write!(f, "{}", v)?,
 			Val::Str(str) => write!(f, "\"{}\"", str)?,
 			Val::Num(n) => write!(f, "{}", n)?,
 			Val::Arr(values) => {
@@ -128,7 +168,7 @@
 				write!(f, "}}")?;
 			}
 			Val::Lazy(lazy) => {
-				write!(f, "{}", lazy.0())?;
+				write!(f, "{}", lazy.evaluate())?;
 			}
 			Val::Func(_) => {
 				write!(f, "<<FUNC>>")?;
@@ -140,9 +180,5 @@
 }
 
 pub fn bool_val(v: bool) -> Val {
-	if v {
-		Val::Literal(LiteralType::True)
-	} else {
-		Val::Literal(LiteralType::False)
-	}
+	Val::Bool(v)
 }