1use crate::ast::Node;
2use crate::cache::RWLockMapCache;
3use crate::lexer::lexer;
4use crate::parser::parse;
5use crate::token::TokenMap;
6use dashmap::DashMap;
7use serde_json::Value;
8
9#[derive(Debug)]
11pub struct RExprRuntime {
12 pub expr_cache: DashMap<String, Node>,
13 pub token_map: TokenMap<'static>,
14}
15
16impl RExprRuntime {
17 pub fn new() -> Self {
18 return Self {
19 expr_cache: DashMap::new(),
20 token_map: TokenMap::new(),
21 };
22 }
23
24 pub fn eval(&self, expr: &str, arg: &Value) -> Result<Value, crate::error::Error> {
26 match self.expr_cache.get(expr) {
27 Some(v) => {
28 return v.eval(arg);
29 }
30 _ => {
31 let node = self.parse(expr)?;
32 self.expr_cache.insert(expr.to_string(), node.clone());
33 return node.eval(arg);
34 }
35 }
36 }
37
38 pub fn eval_no_cache(
40 &self,
41 lexer_arg: &str,
42 arg: &Value,
43 ) -> Result<Value, crate::error::Error> {
44 let tokens = lexer(lexer_arg, &self.token_map)?;
45 let node = parse(&self.token_map, &tokens, lexer_arg)?;
46 return node.eval(arg);
47 }
48
49 pub fn parse(&self, lexer_arg: &str) -> Result<Node, crate::error::Error> {
51 let tokens = lexer(lexer_arg, &self.token_map)?;
52 let node = parse(&self.token_map, &tokens, lexer_arg)?;
53 return Ok(node);
54 }
55}
56
57#[cfg(test)]
58mod test {
59 use crate::bencher::QPS;
60 use crate::runtime::RExprRuntime;
61 use std::sync::Arc;
62 use std::thread::{sleep, spawn};
63 use std::time::Duration;
64
65 #[test]
67 fn test_bench() {
68 let runtime = RExprRuntime::new();
69 runtime.eval("1+1", &serde_json::Value::Null);
70 runtime.eval("1+1", &serde_json::Value::Null);
71
72 let total = 1000000;
73 let now = std::time::Instant::now();
74 for _ in 0..total {
75 let r = runtime.eval("1+1", &serde_json::Value::Null).unwrap(); }
79 now.time(total);
80 now.qps(total);
81 }
82
83 #[test]
84 fn test_thread_race() {
85 let runtime = Arc::new(RExprRuntime::new());
86 let r1 = runtime.clone();
87 spawn(move || {
88 let total = 1000000;
89 for _ in 0..total {
90 let r = r1.eval("1+1", &serde_json::Value::Null).unwrap();
91 }
92 });
93 let r2 = runtime.clone();
94 spawn(move || {
95 let total = 1000000;
96 for _ in 0..total {
97 let r = r2.eval("1+1", &serde_json::Value::Null).unwrap();
98 }
99 });
100 sleep(Duration::from_secs(10));
101 }
102}