difftreelog
perf(evaluator) cache LazyVal/obj fields
in: master
2 files changed
crates/jsonnet-evaluator/src/obj.rsdiffbeforeafterboth1use 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 fields70 }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 v74 }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) {crates/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)
}