From 92f79b71262569ab71d18b40e46c0c5855a079bf Mon Sep 17 00:00:00 2001 From: Matteo Mortari Date: Tue, 1 Oct 2019 17:58:10 +0200 Subject: [PATCH] Parametrized benchmark (#11) * Fixes and benchmark for 26x2x4 rules * Parametrized benchmark --- kie-dmn/kie-dmn-core/pom.xml | 5 + ...ecisionTableAlphaSupportingDraftBench.java | 55 +++- .../alphanetbased/CompiledAlphaNetwork.java | 60 ++-- .../src/main/resources/logback.xml | 4 +- .../core/alphasupport/alphasupport.dmn.ftlh | 294 ++++++++++++++++++ 5 files changed, 383 insertions(+), 35 deletions(-) create mode 100644 kie-dmn/kie-dmn-core/src/main/resources/org/kie/dmn/core/alphasupport/alphasupport.dmn.ftlh diff --git a/kie-dmn/kie-dmn-core/pom.xml b/kie-dmn/kie-dmn-core/pom.xml index cd1e6afd670f..cae0505bbca0 100644 --- a/kie-dmn/kie-dmn-core/pom.xml +++ b/kie-dmn/kie-dmn-core/pom.xml @@ -56,6 +56,11 @@ jmh-core compile + + org.freemarker + freemarker + + org.kie kie-dmn-api diff --git a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/alphasupport/DMNDecisionTableAlphaSupportingDraftBench.java b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/alphasupport/DMNDecisionTableAlphaSupportingDraftBench.java index d871c1c53158..acd778c5b35f 100644 --- a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/alphasupport/DMNDecisionTableAlphaSupportingDraftBench.java +++ b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/alphasupport/DMNDecisionTableAlphaSupportingDraftBench.java @@ -16,11 +16,18 @@ package org.kie.dmn.core.alphasupport; +import java.io.StringWriter; import java.math.BigDecimal; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import java.util.Random; import java.util.UUID; import java.util.concurrent.TimeUnit; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateExceptionHandler; import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; import org.kie.dmn.api.core.DMNContext; @@ -34,6 +41,7 @@ import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; @@ -42,8 +50,8 @@ @BenchmarkMode(Mode.SingleShotTime) @State(Scope.Thread) -@Warmup(iterations = 100) -@Measurement(iterations = 50) +@Warmup(iterations = 200) +@Measurement(iterations = 100) @OutputTimeUnit(TimeUnit.MILLISECONDS) public class DMNDecisionTableAlphaSupportingDraftBench { @@ -53,11 +61,35 @@ public class DMNDecisionTableAlphaSupportingDraftBench { private String existingCustomer; private BigDecimal score; + @Param({"0", "1", "2", "3", "4", "5", "10", "15", "20", "30", "40", "52"}) + private int alphalength; + private char[] alphabet; + @Setup() - public void init() { + public void init() throws Exception { + char[] az = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray(); + this.alphabet = Arrays.copyOf(az, alphalength); + System.setProperty("alphalength", Integer.toString(alphalength)); + + Configuration cfg = new Configuration(Configuration.VERSION_2_3_26); + cfg.setClassForTemplateLoading(DMNDecisionTableAlphaSupportingDraftBench.class, ""); + cfg.setDefaultEncoding("UTF-8"); + cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + + Template temp = cfg.getTemplate("alphasupport.dmn.ftlh"); + StringWriter out = new StringWriter(); + Map root = new HashMap<>(); + root.put("letters", alphabet); + temp.process(root, out); + String xml = out.getBuffer().toString(); + + LOG.debug("{}", xml); + final KieServices ks = KieServices.Factory.get(); final KieContainer kieContainer = KieHelper.getKieContainer(ks.newReleaseId("org.kie", "dmn-test-" + UUID.randomUUID(), "1.0"), - ks.getResources().newClassPathResource("alphasupport.dmn", DMNDecisionTableAlphaSupportingDraftBench.class)); + ks.getResources() + .newByteArrayResource(xml.getBytes()) + .setTargetPath("src/main/resources/alphasupport.dmn")); runtime = kieContainer.newKieSession().getKieRuntime(DMNRuntime.class); dmnModel = runtime.getModel("http://www.trisotech.com/definitions/_c0cf6e20-0b43-43ce-9def-c759a5f86df2", "DMN Specification Chapter 11 Example Reduced"); } @@ -69,12 +101,11 @@ public void initIterationValues() { } public String existingCustomer() { - char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray(); int randomIdx = new Random().nextInt(alphabet.length + 2); - if (randomIdx < alphabet.length - 2) { + if (randomIdx < alphabet.length) { return String.valueOf(alphabet[randomIdx]); } else { - return (randomIdx - 2) == 0 ? "true" : "false"; + return (randomIdx - alphabet.length) == 0 ? "true" : "false"; } } @@ -93,10 +124,14 @@ public void testSimpleDecision() { LOG.debug("{}", dmnResult); } - public static void main(String[] args) { + public static void main(String[] args) throws Exception { DMNDecisionTableAlphaSupportingDraftBench u = new DMNDecisionTableAlphaSupportingDraftBench(); + u.alphalength = 2; u.init(); - u.initIterationValues(); - u.doTest(); + for (int i = 0; i < 1000; i++) { + u.initIterationValues(); + u.doTest(); + } + System.out.println("done."); } } diff --git a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/compiler/alphanetbased/CompiledAlphaNetwork.java b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/compiler/alphanetbased/CompiledAlphaNetwork.java index e2fdb1a90190..2071352d1fc7 100644 --- a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/compiler/alphanetbased/CompiledAlphaNetwork.java +++ b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/compiler/alphanetbased/CompiledAlphaNetwork.java @@ -17,7 +17,9 @@ package org.kie.dmn.core.compiler.alphanetbased; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.UUID; import org.drools.compiler.builder.impl.KnowledgeBuilderImpl; import org.drools.core.base.ClassObjectType; @@ -56,6 +58,7 @@ import static org.kie.dmn.feel.codegen.feel11.CompiledFEELSemanticMappings.includes; import static org.kie.dmn.feel.codegen.feel11.CompiledFEELSemanticMappings.lt; import static org.kie.dmn.feel.codegen.feel11.CompiledFEELSemanticMappings.range; + public class CompiledAlphaNetwork { private final ResultCollector resultCollector = new ResultCollector(); @@ -73,6 +76,7 @@ private Object applyHitPolicy( List results ) { } public static final org.kie.dmn.feel.runtime.UnaryTest UT1 = (feelExprCtx, left) -> gracefulEq(feelExprCtx, "false", left); + public static final org.kie.dmn.feel.runtime.UnaryTest UT1x = (feelExprCtx, left) -> gracefulEq(feelExprCtx, "false", left); public static final java.math.BigDecimal K_80 = new java.math.BigDecimal(80, java.math.MathContext.DECIMAL128); public static final java.math.BigDecimal K_90 = new java.math.BigDecimal(90, java.math.MathContext.DECIMAL128); @@ -119,30 +123,33 @@ public static CompiledAlphaNetwork generateCompiledNetwork() { NetworkBuilderContext ctx = new NetworkBuilderContext(); Index index1 = createIndex(String.class, x -> (String)x.getValue("Existing Customer"), "false"); - AlphaNode alphac1r1 = createAlphaNode(ctx, ctx.otn, x -> UT1.apply(x, x.getValue("Existing Customer")), index1); + AlphaNode alphac1r1 = createAlphaNode(ctx, ctx.otn, "\"false\"", x -> UT1.apply(x, x.getValue("Existing Customer")), index1); - AlphaNode alphac2r1 = createAlphaNode(ctx, alphac1r1, x -> UT2.apply(x, x.getValue("Application Risk Score"))); + AlphaNode alphac2r1 = createAlphaNode(ctx, alphac1r1, "<100", x -> UT2.apply(x, x.getValue("Application Risk Score"))); addResultSink(ctx, network, alphac2r1, "HIGH"); - AlphaNode alphac2r2 = createAlphaNode(ctx, alphac1r1, x -> UT3.apply(x, x.getValue("Application Risk Score"))); + AlphaNode alphac2r2 = createAlphaNode(ctx, alphac1r1, "[100..120)", x -> UT3.apply(x, x.getValue("Application Risk Score"))); addResultSink(ctx, network, alphac2r2, "MEDIUM"); - AlphaNode alphac2r3 = createAlphaNode(ctx, alphac1r1, x -> UT4.apply(x, x.getValue("Application Risk Score"))); + AlphaNode alphac2r3 = createAlphaNode(ctx, alphac1r1, "[120..130]", x -> UT4.apply(x, x.getValue("Application Risk Score"))); addResultSink(ctx, network, alphac2r3, "LOW"); - AlphaNode alphac2r4 = createAlphaNode(ctx, alphac1r1, x -> UT5.apply(x, x.getValue("Application Risk Score"))); + AlphaNode alphac2r4 = createAlphaNode(ctx, alphac1r1, ">130", x -> UT5.apply(x, x.getValue("Application Risk Score"))); addResultSink(ctx, network, alphac2r4, "VERY LOW"); Index index2 = createIndex(String.class, x -> (String)x.getValue("Existing Customer"), "true"); - AlphaNode alphac1r5 = createAlphaNode(ctx, ctx.otn, x -> UT6.apply(x, x.getValue("Existing Customer")), index2); + AlphaNode alphac1r5 = createAlphaNode(ctx, ctx.otn, "\"true\"", x -> UT6.apply(x, x.getValue("Existing Customer")), index2); - AlphaNode alphac2r5 = createAlphaNode(ctx, alphac1r5, x -> UT7.apply(x, x.getValue("Application Risk Score"))); + AlphaNode alphac2r5 = createAlphaNode(ctx, alphac1r5, "<80", x -> UT7.apply(x, x.getValue("Application Risk Score"))); addResultSink(ctx, network, alphac2r5, "DECLINE"); - AlphaNode alphac2r6 = createAlphaNode(ctx, alphac1r5, x -> UT8.apply(x, x.getValue("Application Risk Score"))); + AlphaNode alphac2r6 = createAlphaNode(ctx, alphac1r5, "[80..90)", x -> UT8.apply(x, x.getValue("Application Risk Score"))); addResultSink(ctx, network, alphac2r6, "HIGH"); - AlphaNode alphac2r7 = createAlphaNode(ctx, alphac1r5, x -> UT9.apply(x, x.getValue("Application Risk Score"))); + AlphaNode alphac2r7 = createAlphaNode(ctx, alphac1r5, "[90..110]", x -> UT9.apply(x, x.getValue("Application Risk Score"))); addResultSink(ctx, network, alphac2r7, "MEDIUM"); - AlphaNode alphac2r8 = createAlphaNode(ctx, alphac1r5, x -> UT10.apply(x, x.getValue("Application Risk Score"))); + AlphaNode alphac2r8 = createAlphaNode(ctx, alphac1r5, ">110", x -> UT10.apply(x, x.getValue("Application Risk Score"))); addResultSink(ctx, network, alphac2r8, "LOW"); char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray(); + System.out.println(System.getProperty("alphalength")); + int alphalength = Integer.valueOf(System.getProperty("alphalength", "52")); + alphabet = Arrays.copyOf(alphabet, alphalength); for (char c : alphabet) { alphabet(network, ctx, String.valueOf(c)); } @@ -157,18 +164,17 @@ public static CompiledAlphaNetwork generateCompiledNetwork() { } private static void alphabet(CompiledAlphaNetwork network, NetworkBuilderContext ctx, String sChar) { - System.out.println(sChar); final org.kie.dmn.feel.runtime.UnaryTest UTx = (feelExprCtx, left) -> gracefulEq(feelExprCtx, sChar, left); Index index1 = createIndex(String.class, x -> (String) x.getValue("Existing Customer"), sChar); - AlphaNode alphac1r1 = createAlphaNode(ctx, ctx.otn, x -> UTx.apply(x, x.getValue("Existing Customer")), index1); + AlphaNode alphac1r1 = createAlphaNode(ctx, ctx.otn, "\"" + sChar + "\"", x -> UTx.apply(x, x.getValue("Existing Customer")), index1); - AlphaNode alphac2r1 = createAlphaNode(ctx, alphac1r1, x -> UT2.apply(x, x.getValue("Application Risk Score"))); + AlphaNode alphac2r1 = createAlphaNode(ctx, alphac1r1, "<100", x -> UT2.apply(x, x.getValue("Application Risk Score"))); addResultSink(ctx, network, alphac2r1, "HIGH"); - AlphaNode alphac2r2 = createAlphaNode(ctx, alphac1r1, x -> UT3.apply(x, x.getValue("Application Risk Score"))); + AlphaNode alphac2r2 = createAlphaNode(ctx, alphac1r1, "[100..120)", x -> UT3.apply(x, x.getValue("Application Risk Score"))); addResultSink(ctx, network, alphac2r2, "MEDIUM"); - AlphaNode alphac2r3 = createAlphaNode(ctx, alphac1r1, x -> UT4.apply(x, x.getValue("Application Risk Score"))); + AlphaNode alphac2r3 = createAlphaNode(ctx, alphac1r1, "[120..130]", x -> UT4.apply(x, x.getValue("Application Risk Score"))); addResultSink(ctx, network, alphac2r3, "LOW"); - AlphaNode alphac2r4 = createAlphaNode(ctx, alphac1r1, x -> UT5.apply(x, x.getValue("Application Risk Score"))); + AlphaNode alphac2r4 = createAlphaNode(ctx, alphac1r1, ">130", x -> UT5.apply(x, x.getValue("Application Risk Score"))); addResultSink(ctx, network, alphac2r4, "VERY LOW"); } @@ -176,16 +182,24 @@ private static void addResultSink( NetworkBuilderContext ctx, CompiledAlphaNetwo source.addObjectSink( new ResultCollectorAlphaSink( ctx.buildContext.getNextId(), source, ctx.buildContext, result, network.resultCollector ) ); } - private static AlphaNode createAlphaNode( NetworkBuilderContext ctx, ObjectSource source, Predicate1 predicate ) { - return createAlphaNode( ctx, source, predicate, null ); + private static AlphaNode createAlphaNode(NetworkBuilderContext ctx, ObjectSource source, String id, Predicate1 predicate) { + return createAlphaNode( ctx, source, id, predicate, null ); } + @Deprecated private static AlphaNode createAlphaNode( NetworkBuilderContext ctx, ObjectSource source, Predicate1 predicate, Index index ) { - SingleConstraint1 constraint = new SingleConstraint1(ctx.variable, predicate); - constraint.setIndex( index ); - LambdaConstraint lambda = new LambdaConstraint(new ConstraintEvaluator(new Declaration[] { ctx.declaration }, constraint)); - lambda.setType( Constraint.ConstraintType.ALPHA ); - return attachNode( ctx.buildContext, new AlphaNode( ctx.buildContext.getNextId(), lambda, source, ctx.buildContext ) ); + return createAlphaNode(ctx, source, UUID.randomUUID().toString(), predicate, null); + } + + /** + * IMPORTANT: remember to use the FEEL expression as an Identifier for the same constraint + */ + private static AlphaNode createAlphaNode(NetworkBuilderContext ctx, ObjectSource source, String id, Predicate1 predicate, Index index) { + SingleConstraint1 constraint = new SingleConstraint1(id, ctx.variable, predicate); + constraint.setIndex(index); + LambdaConstraint lambda = new LambdaConstraint(new ConstraintEvaluator(new Declaration[]{ctx.declaration}, constraint)); + lambda.setType(Constraint.ConstraintType.ALPHA); + return attachNode(ctx.buildContext, new AlphaNode(ctx.buildContext.getNextId(), lambda, source, ctx.buildContext)); } private static AlphaIndexImpl createIndex( Class indexedClass, Function1 leftExtractor, I rightValue) { diff --git a/kie-dmn/kie-dmn-core/src/main/resources/logback.xml b/kie-dmn/kie-dmn-core/src/main/resources/logback.xml index b7f6efe9153b..ab049774b085 100644 --- a/kie-dmn/kie-dmn-core/src/main/resources/logback.xml +++ b/kie-dmn/kie-dmn-core/src/main/resources/logback.xml @@ -23,8 +23,8 @@ - - + + diff --git a/kie-dmn/kie-dmn-core/src/main/resources/org/kie/dmn/core/alphasupport/alphasupport.dmn.ftlh b/kie-dmn/kie-dmn-core/src/main/resources/org/kie/dmn/core/alphasupport/alphasupport.dmn.ftlh new file mode 100644 index 000000000000..beaffe42882a --- /dev/null +++ b/kie-dmn/kie-dmn-core/src/main/resources/org/kie/dmn/core/alphasupport/alphasupport.dmn.ftlh @@ -0,0 +1,294 @@ + + + + + string + + "INELIGIBLE", "ELIGIBLE" + + + + string + + "FULL", "MINI", "NONE" + + + + string + + "DECLINE", "BUREAU", "THROUGH" + + + + string + + "DECLINE", "HIGH", "MEDIUM", "LOW", "VERY LOW" + + + + string + + "DECLINE", "REFER", "ACCEPT" + + + + + number + + [0..999], null + + + + boolean + + + + + + number + + + number + + + number + + + + number + + + boolean + + + string + + "S","M" + + + + string + + "EMPLOYED","SELF-EMPLOYED","STUDENT","UNEMPLOYED" + + + + + + string + + "STANDARD LOAN","SPECIAL LOAN" + + + + number + + + number + + + number + + + + string + + "FULL","MINI","NONE" + + + + <p align="LEFT"><span style="font-family: arial,helvetica,sans-serif; font-size: 10pt;"><span lang="JA">The </span><strong><span lang="JA">Pre-Bureau Risk Category Table </span></strong><span lang="JA">decision logic (Figure 82) defines a complete, unique-hit decision table </span>deriving Pre-Bureau Risk Category from Existing Customer and Application Risk Score.</span></p> + + + + + + + + + + + Existing Customer + + + + + Application Risk Score + + + + + "DECLINE", "HIGH", "MEDIUM", "LOW", "VERY LOW" + + + + + + "false" + + + <100 + + + "HIGH" + + + + + + + + "false" + + + [100..120) + + + "MEDIUM" + + + + + + + + "false" + + + [120..130] + + + "LOW" + + + + + + + + "false" + + + >130 + + + "VERY LOW" + + + + + + + + "true" + + + <80 + + + "DECLINE" + + + + + + + + "true" + + + [80..90) + + + "HIGH" + + + + + + + + "true" + + + [90..110] + + + "MEDIUM" + + + + + + + + "true" + + + >110 + + + "LOW" + + + + + + +<#list letters as letter > + + + "${letter}" + + + <100 + + + "HIGH" + + + + + "${letter}" + + + [100..120) + + + "MEDIUM" + + + + + "${letter}" + + + [120..130] + + + "LOW" + + + + + "${letter}" + + + >130 + + + "VERY LOW" + + + + + + + + + + + + + + \ No newline at end of file