feat: improve performance of exprs in apps using memoized expr functors

This commit is contained in:
Ruben Fiszel
2024-02-28 10:52:58 +01:00
parent 03dc11f1cf
commit afa3c54140
@@ -18,16 +18,20 @@ export function computeGlobalContext(world: World | undefined, extraContext: any
}
}
function create_context_function_template(eval_string: string, context, noReturn: boolean) {
function create_context_function_template(
eval_string: string,
contextKeys: string[],
noReturn: boolean
) {
let lastBreak = eval_string.lastIndexOf('\n')
let lines = lastBreak == -1 ? "" : eval_string.substring(0, lastBreak)
let lines = lastBreak == -1 ? '' : eval_string.substring(0, lastBreak)
let lastLine = lastBreak == -1 ? eval_string : eval_string.substring(lastBreak + 1)
return `
return async function (context, state, goto, setTab, recompute, getAgGrid, setValue, setSelectedIndex, openModal, closeModal, open, close, validate, invalidate, validateAll, clearFiles, showToast) {
"use strict";
${
Object.keys(context).length > 0
? `let ${Object.keys(context).map((key) => ` ${key} = context['${key}']`)};`
contextKeys && contextKeys.length > 0
? `let ${contextKeys.map((key) => ` ${key} = context['${key}']`)};`
: ``
}
${lines}
@@ -40,11 +44,7 @@ ${
`
}
function make_context_evaluator(
eval_string,
context,
noReturn: boolean
): (
type WmFunctor = (
context,
state,
goto,
@@ -62,11 +62,19 @@ function make_context_evaluator(
validateAll,
clearFiles,
showToast
) => Promise<any> {
let template = create_context_function_template(eval_string, context, noReturn)
let functor = Function(template)
) => Promise<any>
return functor()
let functorCache: Record<number, WmFunctor> = {}
function make_context_evaluator(eval_string, contextKeys: string[], noReturn: boolean): WmFunctor {
let cacheKey = hashCode(JSON.stringify({ eval_string, contextKeys, noReturn }))
if (functorCache[cacheKey]) {
return functorCache[cacheKey]
}
let template = create_context_function_template(eval_string, contextKeys, noReturn)
let functor = Function(template)
let r = functor()
functorCache[cacheKey] = r
return r
}
function isSerializable(obj) {
@@ -101,6 +109,18 @@ function isSerializable(obj) {
return true
}
function hashCode(s: string): number {
var hash = 0,
i,
chr
if (s.length === 0) return hash
for (i = 0; i < s.length; i++) {
chr = s.charCodeAt(i)
hash = (hash << 5) - hash + chr
hash |= 0 // Convert to 32bit integer
}
return hash
}
export async function eval_like(
text: string,
context = {},
@@ -142,8 +162,10 @@ export async function eval_like(
return true
}
})
let evaluator = make_context_evaluator(text, context, noReturn)
const r = await evaluator(
let evaluator = make_context_evaluator(text, Object.keys(context ?? {}), noReturn)
// console.log(i, j)
return await evaluator(
context,
proxiedState,
async (x, newTab) => {
@@ -201,5 +223,4 @@ export async function eval_like(
sendUserToast(message, error)
}
)
return r
}