Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added cache for functions #2

Open
wants to merge 1 commit into
base: 1.4-seeburger
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

import org.apache.commons.jxpath.CompiledExpression;
import org.apache.commons.jxpath.ExceptionHandler;
Expand Down Expand Up @@ -89,6 +90,8 @@ public class JXPathContextReferenceImpl extends JXPathContext {
private static final Compiler COMPILER = new TreeCompiler();
private static final Map<String, Expression> compiled;

private static final Map<Integer, Function> functionCache;

private static NodePointerFactory[] nodeFactoryArray;
private static final Collection<NodePointerFactory> nodeFactories = new CopyOnWriteArrayList<>();

Expand All @@ -98,14 +101,22 @@ public class JXPathContextReferenceImpl extends JXPathContext {
CACHE_STATISTICS = Boolean.getBoolean("jxpath.cache.statistics");
USE_SOFT_CACHE = "true".equalsIgnoreCase(System.getProperty("jxpath.cache.soft", "true"));
if (CACHE_ENABLED) {
final int compileCacheSize = Integer.getInteger("jxpath.cache.size", 50_000);
final int cacheSize = Integer.getInteger("jxpath.cache.size", 50_000);
if (USE_SOFT_CACHE) {
compiled = new SoftConcurrentHashMap<>(compileCacheSize);
compiled = new SoftConcurrentHashMap<>(cacheSize);
functionCache = new SoftConcurrentHashMap<>(cacheSize);
} else {
compiled = new LinkedHashMap<String, Expression>() {
@Override
protected boolean removeEldestEntry(java.util.Map.Entry eldest) {
return this.size() > compileCacheSize;
return this.size() > cacheSize;
}
};

functionCache = new LinkedHashMap<Integer, Function>() {
@Override
protected boolean removeEldestEntry(java.util.Map.Entry eldest) {
return this.size() > cacheSize;
}
};
}
Expand All @@ -123,6 +134,7 @@ protected boolean removeEldestEntry(java.util.Map.Entry eldest) {
}
else {
compiled = null;
functionCache = null;
}

nodeFactories.add(new CollectionPointerFactory());
Expand Down Expand Up @@ -765,16 +777,26 @@ public NodePointer getVariablePointer(QName name) {
* @return Function
*/
public Function getFunction(QName functionName, Object[] parameters) {
Integer functionHash = getFunctionHash(functionName, parameters);
if (CACHE_ENABLED) {
Function func = functionCache.get(functionHash);
if (func != null) {
return func;
}
}

String namespace = functionName.getPrefix();
String name = functionName.getName();
JXPathContext funcCtx = this;
Function func = null;
Functions funcs;
while (funcCtx != null) {
funcs = funcCtx.getFunctions();
if (funcs != null) {
func = funcs.getFunction(namespace, name, parameters);
Function func = funcs.getFunction(namespace, name, parameters);
if (func != null) {
if (CACHE_ENABLED) {
functionCache.put(functionHash, func);
}
return func;
}
}
Expand All @@ -784,6 +806,27 @@ public Function getFunction(QName functionName, Object[] parameters) {
"Undefined function: " + functionName.toString());
}


private static Integer getFunctionHash(QName functionName, Object[] parameters)
{
if (!CACHE_ENABLED) {
return Integer.valueOf(-1);
}

int hashParameters;
if (parameters == null) {
hashParameters = 0;
}
else
{
List<Object> paramList = Arrays.asList(parameters);
List<Class> classList = paramList.stream().map(p -> p.getClass()).collect(Collectors.toList());
hashParameters = Arrays.hashCode(classList.toArray());
}
return Integer.valueOf(Objects.hash(functionName, hashParameters));
}


public void registerNamespace(String prefix, String namespaceURI) {
if (namespaceResolver.isSealed()) {
namespaceResolver = (NamespaceResolver) namespaceResolver.clone();
Expand Down