Skip to content

Commit

Permalink
[RHDM-1994] Performance degradation when increasing concurrency of ru…
Browse files Browse the repository at this point in the history
…le execution in multi threads (kiegroup#13)

* [DROOLS-7214] non-executable-model doesn't react to bind-only Map pro… (apache#4771) (apache#4823)

* [DROOLS-7214] non-executable-model doesn't react to bind-only Map property with map access operator
- Test case only

* [DROOLS-7214] non-executable-model doesn't react to bind-only Map property with map access operator
- Fix

* - test method name change
- lookAheadIgnoringSpaces to return a Character

* Additional secondary super cache issue
- Bump Version
- Added benchmark to drools
- Fixed secondary super cache on AgendaItem
- Fix ObjectSinkNode, LeftTupleSinkNode
- Fix ClassAwareObjectStore
- Fix TerminalNode
- Revert "Added benchmark to drools"
- Revert "Bump Version"
  • Loading branch information
tkobayas authored Oct 31, 2023
1 parent 0870b8e commit 84aa798
Show file tree
Hide file tree
Showing 91 changed files with 1,128 additions and 979 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,8 @@ public interface AnalysisResult {
Set<String> getLocalVariables();

Class<?> getReturnType();

default boolean isTypesafe() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ private void processConstraint(StringBuilder sbuilder, ExprConstraintDescr base,

private String[] processAtomicExpression( StringBuilder sbuilder, MVELDumperContext context, AtomicExprDescr atomicExpr, ConstraintConnectiveDescr parent, int parentIdx ) {
String expr = atomicExpr.getExpression().trim();
expr = processEval(expr);
expr = normalizeEval(expr);
String[] constrAndExpr = processImplicitConstraints( expr, atomicExpr, parent, parentIdx, context );
// top-level, implicit constraints will be processed in different nodes.
// Nested CCDs require all constraints to be evaluated locally, as a complex constraints
Expand Down Expand Up @@ -198,7 +198,7 @@ private void processRelationalExpression(StringBuilder sbuilder, RelationalExprD

private String processRightAtomicExpr( StringBuilder left, AtomicExprDescr atomicExpr, ConstraintConnectiveDescr parent, int parentIdx, MVELDumperContext context ) {
String expr = atomicExpr.getExpression().trim();
expr = processEval( expr );
expr = normalizeEval( expr );
String[] constrAndExpr = processImplicitConstraints(expr, atomicExpr, parent, parentIdx, context);
left.insert( 0, constrAndExpr[0] );
return processBackReference( context, atomicExpr, constrAndExpr[1] );
Expand Down Expand Up @@ -363,9 +363,11 @@ private String getPreconditionsToAppend(String field1) {
return field1;
}

private String processEval(String expr) {
public static String normalizeEval(String expr) {
// stripping "eval" as it is no longer necessary
return evalRegexp.matcher( expr ).find() ? expr.substring( expr.indexOf( '(' ) + 1, expr.lastIndexOf( ')' ) ) : expr;
String normalized = evalRegexp.matcher( expr ).find() ? expr.substring( expr.indexOf( '(' ) + 1, expr.lastIndexOf( ')' ) ) : expr;
// we are not able to normalize nested/combined evals
return normalized.contains("eval") ? expr : normalized;
}

private String[] splitInClassAndField(String expr, MVELDumperContext context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.drools.compiler.lang.MVELDumper.normalizeEval;
import static org.drools.compiler.rule.builder.util.PatternBuilderUtil.getNormalizeDate;
import static org.drools.compiler.rule.builder.util.PatternBuilderUtil.normalizeEmptyKeyword;
import static org.drools.compiler.rule.builder.util.PatternBuilderUtil.normalizeStringOperator;
Expand Down Expand Up @@ -1760,7 +1761,7 @@ protected ConstraintConnectiveDescr parseExpression(final RuleBuildContext conte
final BaseDescr original,
final String expression) {
DrlExprParser parser = new DrlExprParser(context.getConfiguration().getLanguageLevel());
ConstraintConnectiveDescr result = parser.parse(expression);
ConstraintConnectiveDescr result = parser.parse(normalizeEval(expression));
result.setResource(patternDescr.getResource());
result.copyLocation(original);
if (parser.hasErrors()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@
public abstract class ProjectClassLoader extends ClassLoader implements KieTypeResolver, StoreClassLoader, WritableClassLoader {

private static final boolean CACHE_NON_EXISTING_CLASSES = true;
private static final ClassNotFoundException dummyCFNE = CACHE_NON_EXISTING_CLASSES ?
new ClassNotFoundException("This is just a cached Exception. Disable non existing classes cache to see the actual one.") :
null;

private static boolean enableStoreFirst = Boolean.valueOf(System.getProperty("drools.projectClassLoader.enableStoreFirst", "true"));

Expand All @@ -62,7 +59,7 @@ public abstract class ProjectClassLoader extends ClassLoader implements KieTypeR

private InternalTypesClassLoader typesClassLoader;

private final Map<String, Class<?>> loadedClasses = new ConcurrentHashMap<String, Class<?>>();
private final Map<String, Class<?>> loadedClasses = new ConcurrentHashMap<>();

protected Set<String> generatedClassNames = new HashSet<>();

Expand Down Expand Up @@ -161,7 +158,7 @@ protected boolean isStoreFirst(String name) {
// This method has to be public because is also used by the android ClassLoader
public Class<?> internalLoadClass(String name, boolean resolve) throws ClassNotFoundException {
if (CACHE_NON_EXISTING_CLASSES && nonExistingClasses.contains(name)) {
throw dummyCFNE;
throw getClassNotFoundExceptionWithName(name);
}

if (droolsClassLoader != null) {
Expand Down Expand Up @@ -195,21 +192,20 @@ private Class<?> loadType(String name, boolean resolve) throws ClassNotFoundExce
return tryDefineType(name, cnfe);
}

// This method has to be public because is also used by the android ClassLoader
public Class<?> tryDefineType(String name, ClassNotFoundException cnfe) throws ClassNotFoundException {
byte[] bytecode = getBytecode( ClassUtils.convertClassToResourcePath(name));
if (bytecode == null) {
if (CACHE_NON_EXISTING_CLASSES) {
nonExistingClasses.add(name);
}
throw cnfe != null ? cnfe : new ClassNotFoundException(name);
throw cnfe != null ? cnfe : getClassNotFoundExceptionWithName(name);
}
return defineType(name, bytecode);
}

private synchronized Class<?> defineType(String name, byte[] bytecode) {
if (definedTypes == null) {
definedTypes = new HashMap<String, ClassBytecode>();
definedTypes = new HashMap<>();
} else {
ClassBytecode existingClass = definedTypes.get(name);
if (existingClass != null && Arrays.equals(bytecode, existingClass.bytes)) {
Expand Down Expand Up @@ -266,7 +262,7 @@ public void storeClasses(Map<String, byte[]> classesMap) {

public void storeClass(String name, String resourceName, byte[] bytecode) {
if (store == null) {
store = new HashMap<String, byte[]>();
store = new HashMap<>();
}
store.put(resourceName, bytecode);
if (CACHE_NON_EXISTING_CLASSES) {
Expand Down Expand Up @@ -433,7 +429,7 @@ public void setResourceProvider(ResourceProvider resourceProvider) {
public void initFrom(ProjectClassLoader other) {
if (other.store != null) {
if (store == null) {
store = new HashMap<String, byte[]>();
store = new HashMap<>();
}
store.putAll(other.store);
}
Expand All @@ -447,7 +443,7 @@ public interface InternalTypesClassLoader extends KieTypeResolver {
Class<?> loadType( String name, boolean resolve ) throws ClassNotFoundException;
default Class<?> findLoadedClassWithoutParent(String name) {
throw new UnsupportedOperationException();
};
}
}

public synchronized List<String> reinitTypes() {
Expand All @@ -471,4 +467,24 @@ private ClassBytecode(Class<?> clazz, byte[] bytes) {
this.bytes = bytes;
}
}

private ClassNotFoundException getClassNotFoundExceptionWithName(String name) {
if (CACHE_NON_EXISTING_CLASSES) {
DummyClassNotFoundException.INSTANCE.name = name;
return DummyClassNotFoundException.INSTANCE;
}
return new ClassNotFoundException(name);
}

public static class DummyClassNotFoundException extends ClassNotFoundException {

private static final DummyClassNotFoundException INSTANCE = CACHE_NON_EXISTING_CLASSES ? new DummyClassNotFoundException() : null;

private String name;

@Override
public String getMessage() {
return name + "\n(Note: This is just a cached Exception for performance reasons, the stack trace is not correct and also the name of the class may be wrong in multithreaded situations. Disable non existing classes cache to see the actual one.)";
}
}
}
Loading

0 comments on commit 84aa798

Please sign in to comment.