From d364b0825c5c1da6c5f32bc1252c426c31091320 Mon Sep 17 00:00:00 2001 From: MariusSchultchen Date: Tue, 13 Feb 2024 13:59:41 +0100 Subject: [PATCH] Performance optimization for multi-threaded execution --- .../validators/JavaScriptEvaluator.java | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/core/src/main/java/org/verapdf/pdfa/validation/validators/JavaScriptEvaluator.java b/core/src/main/java/org/verapdf/pdfa/validation/validators/JavaScriptEvaluator.java index 2b8eec497..786704dd8 100644 --- a/core/src/main/java/org/verapdf/pdfa/validation/validators/JavaScriptEvaluator.java +++ b/core/src/main/java/org/verapdf/pdfa/validation/validators/JavaScriptEvaluator.java @@ -18,36 +18,37 @@ public class JavaScriptEvaluator { private static final int OPTIMIZATION_LEVEL = 9; - private static Context context; + private static final ThreadLocal context = new ThreadLocal<>(); - private static final Map ruleScripts = new HashMap<>(); - private static final Map variableScripts = new HashMap<>(); - private static final Map argumentScripts = new HashMap<>(); + private static final ThreadLocal> ruleScripts = ThreadLocal.withInitial(HashMap::new); + private static final ThreadLocal> variableScripts = ThreadLocal.withInitial(HashMap::new); + private static final ThreadLocal> argumentScripts = ThreadLocal.withInitial(HashMap::new); - public static synchronized ScriptableObject initialise() { - context = Context.enter(); - context.setOptimizationLevel(OPTIMIZATION_LEVEL); - return context.initStandardObjects(); + public static ScriptableObject initialise() { + final Context newContext = Context.enter(); + context.set(newContext); + newContext.setOptimizationLevel(OPTIMIZATION_LEVEL); + return newContext.initStandardObjects(); } - public static synchronized java.lang.Object evaluateString(String source, ScriptableObject scope) { - return context.evaluateString(scope, source, null, 0, null); + public static java.lang.Object evaluateString(String source, ScriptableObject scope) { + return context.get().evaluateString(scope, source, null, 0, null); } - public static synchronized java.lang.Object evalVariableResult(Variable variable, Object object, ScriptableObject scope) { + public static java.lang.Object evalVariableResult(Variable variable, Object object, ScriptableObject scope) { Script script; - if (!variableScripts.containsKey(variable.getName())) { + if (!variableScripts.get().containsKey(variable.getName())) { String source = getStringScript(object, variable.getValue()); script = JavaScriptEvaluator.compileString(source); - variableScripts.put(variable.getName(), script); + variableScripts.get().put(variable.getName(), script); } else { - script = variableScripts.get(variable.getName()); + script = variableScripts.get().get(variable.getName()); } scope.put("obj", scope, object); - java.lang.Object res = script.exec(context, scope); + java.lang.Object res = script.exec(context.get(), scope); if (res instanceof NativeJavaObject) { res = ((NativeJavaObject) res).unwrap(); @@ -56,7 +57,7 @@ public static synchronized java.lang.Object evalVariableResult(Variable variable } private static Script compileString(String source) { - return context.compileString(source, null, 0, null); + return context.get().compileString(source, null, 0, null); } private static String getStringScript(Object obj, String arg) { @@ -107,33 +108,33 @@ private static String getScript(Object obj, String test) { return getStringScript(obj, "(" + test + ")==true"); } - public static synchronized boolean getTestEvalResult(Object obj, Rule rule, ScriptableObject scope) { + public static boolean getTestEvalResult(Object obj, Rule rule, ScriptableObject scope) { scope.put("obj", scope, obj); Script scr; String test = rule.getTest(); - if (!ruleScripts.containsKey(test)) { + if (!ruleScripts.get().containsKey(test)) { scr = compileString(getScript(obj, test)); - ruleScripts.put(test, scr); + ruleScripts.get().put(test, scr); } else { - scr = ruleScripts.get(test); + scr = ruleScripts.get().get(test); } - boolean testEvalResult = (Boolean) scr.exec(context, scope); + boolean testEvalResult = (Boolean) scr.exec(context.get(), scope); return testEvalResult; } - private static synchronized String getErrorArgumentResult(String argument, Object obj, ScriptableObject scope) { + private static String getErrorArgumentResult(String argument, Object obj, ScriptableObject scope) { Script scr; - if (!argumentScripts.containsKey(argument)) { + if (!argumentScripts.get().containsKey(argument)) { scr = JavaScriptEvaluator.compileString(getStringScript(obj, argument)); - argumentScripts.put(argument, scr); + argumentScripts.get().put(argument, scr); } else { - scr = argumentScripts.get(argument); + scr = argumentScripts.get().get(argument); } - java.lang.Object res = scr.exec(context, scope); + java.lang.Object res = scr.exec(context.get(), scope); if (res instanceof NativeJavaObject) { res = ((NativeJavaObject) res).unwrap(); } @@ -150,7 +151,7 @@ private static synchronized String getErrorArgumentResult(String argument, Objec } - public static synchronized List getErrorArgumentsResult(Object obj, List arguments, + public static List getErrorArgumentsResult(Object obj, List arguments, ScriptableObject scope) { List result = new LinkedList<>(); for (ErrorArgument argument : arguments) {