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

DROOLS-7469 DMN memoize escaping for better runtime perf #5298

Merged
merged 1 commit into from
Jun 28, 2023

Conversation

tarilabs
Copy link
Member

@tarilabs tarilabs commented Jun 9, 2023

Memoize escaping in string literal for better runtime performance.

On a few selected benchmarks I get a 13-21% runtime improvement, confirming this works good for Compile-Interpreted mode, which is likely the majority of the users:

Tabular version of a performance report validating this approach:

Screenshot 2023-06-09 at 16 59 01

Textual version of the report:

## BASELINE
FEELStringComparisonBenchmark.evaluateCompiledButInterpretedExpression   "foo" < "bar"  avgt  100   0.136 ± 0.002  us/op
FEELStringComparisonBenchmark.evaluateCompiledButInterpretedExpression  "foo" >= "bar"  avgt  100   0.267 ± 0.006  us/op
FEELStringComparisonBenchmark.evaluateCompiledButInterpretedExpression  "foo" != "bar"  avgt  100   0.227 ± 0.004  us/op
FEELStringComparisonBenchmark.evaluateCompiledButInterpretedExpression   "foo" = "foo"  avgt  100   0.227 ± 0.002  us/op
FEELStringComparisonBenchmark.evaluateCompiledJavaExpressionBenchmark    "foo" < "bar"  avgt  100   0.111 ± 0.006  us/op
FEELStringComparisonBenchmark.evaluateCompiledJavaExpressionBenchmark   "foo" >= "bar"  avgt  100   0.237 ± 0.004  us/op
FEELStringComparisonBenchmark.evaluateCompiledJavaExpressionBenchmark   "foo" != "bar"  avgt  100   0.188 ± 0.003  us/op
FEELStringComparisonBenchmark.evaluateCompiledJavaExpressionBenchmark    "foo" = "foo"  avgt  100   0.191 ± 0.004  us/op
FEELStringComparisonBenchmark.evaluateExpressionBenchmark                "foo" < "bar"  avgt  100  11.370 ± 0.172  us/op
FEELStringComparisonBenchmark.evaluateExpressionBenchmark               "foo" >= "bar"  avgt  100  11.611 ± 0.323  us/op
FEELStringComparisonBenchmark.evaluateExpressionBenchmark               "foo" != "bar"  avgt  100  11.635 ± 0.174  us/op
FEELStringComparisonBenchmark.evaluateExpressionBenchmark                "foo" = "foo"  avgt  100  11.807 ± 0.260  us/op

## MODIFIED
FEELStringComparisonBenchmark.evaluateCompiledButInterpretedExpression   "foo" < "bar"  avgt  100   0.107 ± 0.002  us/op
FEELStringComparisonBenchmark.evaluateCompiledButInterpretedExpression  "foo" >= "bar"  avgt  100   0.229 ± 0.003  us/op
FEELStringComparisonBenchmark.evaluateCompiledButInterpretedExpression  "foo" != "bar"  avgt  100   0.191 ± 0.003  us/op
FEELStringComparisonBenchmark.evaluateCompiledButInterpretedExpression   "foo" = "foo"  avgt  100   0.198 ± 0.003  us/op
FEELStringComparisonBenchmark.evaluateCompiledJavaExpressionBenchmark    "foo" < "bar"  avgt  100   0.105 ± 0.009  us/op
FEELStringComparisonBenchmark.evaluateCompiledJavaExpressionBenchmark   "foo" >= "bar"  avgt  100   0.222 ± 0.008  us/op
FEELStringComparisonBenchmark.evaluateCompiledJavaExpressionBenchmark   "foo" != "bar"  avgt  100   0.189 ± 0.003  us/op
FEELStringComparisonBenchmark.evaluateCompiledJavaExpressionBenchmark    "foo" = "foo"  avgt  100   0.187 ± 0.004  us/op
FEELStringComparisonBenchmark.evaluateExpressionBenchmark                "foo" < "bar"  avgt  100  11.032 ± 0.200  us/op
FEELStringComparisonBenchmark.evaluateExpressionBenchmark               "foo" >= "bar"  avgt  100  10.985 ± 0.109  us/op
FEELStringComparisonBenchmark.evaluateExpressionBenchmark               "foo" != "bar"  avgt  100  10.879 ± 0.104  us/op
FEELStringComparisonBenchmark.evaluateExpressionBenchmark                "foo" = "foo"  avgt  100  10.958 ± 0.194  us/op

## BASELINE
DMNEvaluateContextBenchmark.evaluateContext                            1000    ss  250  134.989 ± 14.884  ms/op

## MODIFIED
DMNEvaluateContextBenchmark.evaluateContext                            1000    ss  250  106.649 ± 0.415  ms/op

Please notice it is expected that only Compile-Interpreted mode is benefitting the most from this change, given this change would put-forward, anticipate, bring-forward an operation at FEEL-compile-time, so to be netted-out for runtime.

As mentioned, the Compile-Interpreted is still the default so this would benefit the majority of the user base.

For example, a Decision Table with many FEEL:String enumerations, this would also benefit.

Bonus content (because it's Friday 🥳 ): https://thedailywtf.com/articles/The-Speedup-Loop

JIRA: https://issues.redhat.com/browse/DROOLS-7469

referenced Pull Requests: none

How to replicate CI configuration locally?

Build Chain tool does "simple" maven build(s), the builds are just Maven commands, but because the repositories relates and depends on each other and any change in API or class method could affect several of those repositories there is a need to use build-chain tool to handle cross repository builds and be sure that we always use latest version of the code for each repository.

build-chain tool is a build tool which can be used on command line locally or in Github Actions workflow(s), in case you need to change multiple repositories and send multiple dependent pull requests related with a change you can easily reproduce the same build by executing it on Github hosted environment or locally in your development environment. See local execution details to get more information about it.

How to retest this PR or trigger a specific build:
  • for pull request checks
    Please add comment: Jenkins retest this

  • for a specific pull request check
    Please add comment: Jenkins (re)run [drools|kogito-runtimes|kogito-apps|kogito-examples] tests

  • for a full downstream build

    • for jenkins job: please add comment: Jenkins run fdb
    • for github actions job: add the label run_fdb
  • a compile downstream build please add comment: Jenkins run cdb

  • a full production downstream build please add comment: Jenkins execute product fdb

  • an upstream build please add comment: Jenkins run upstream

  • for quarkus branch checks
    Run checks against Quarkus current used branch
    Please add comment: Jenkins run quarkus-branch

  • for a quarkus branch specific check
    Run checks against Quarkus current used branch
    Please add comment: Jenkins (re)run [drools|kogito-runtimes|kogito-apps|kogito-examples] quarkus-branch

  • for quarkus main checks
    Run checks against Quarkus main branch
    Please add comment: Jenkins run quarkus-main

  • for a specific quarkus main check
    Run checks against Quarkus main branch
    Please add comment: Jenkins (re)run [drools|kogito-runtimes|kogito-apps|kogito-examples] quarkus-main

  • for quarkus lts checks
    Run checks against Quarkus lts branch
    Please add comment: Jenkins run quarkus-lts

  • for a specific quarkus lts check
    Run checks against Quarkus lts branch
    Please add comment: Jenkins (re)run [drools|kogito-runtimes|kogito-apps|kogito-examples] quarkus-lts

  • for native checks
    Run native checks
    Please add comment: Jenkins run native

  • for a specific native check
    Run native checks
    Please add comment: Jenkins (re)run [drools|kogito-runtimes|kogito-apps|kogito-examples] native

  • for native lts checks
    Run native checks against quarkus lts branch
    Please add comment: Jenkins run native-lts

  • for a specific native lts check
    Run native checks against quarkus lts branch
    Please add comment: Jenkins (re)run [drools|kogito-runtimes|kogito-apps|kogito-examples] native-lts

How to backport a pull request to a different branch?

In order to automatically create a backporting pull request please add one or more labels having the following format backport-<branch-name>, where <branch-name> is the name of the branch where the pull request must be backported to (e.g., backport-7.67.x to backport the original PR to the 7.67.x branch).

NOTE: backporting is an action aiming to move a change (usually a commit) from a branch (usually the main one) to another one, which is generally referring to a still maintained release branch. Keeping it simple: it is about to move a specific change or a set of them from one branch to another.

Once the original pull request is successfully merged, the automated action will create one backporting pull request per each label (with the previous format) that has been added.

If something goes wrong, the author will be notified and at this point a manual backporting is needed.

NOTE: this automated backporting is triggered whenever a pull request on main branch is labeled or closed, but both conditions must be satisfied to get the new PR created.

@kie-ci4
Copy link
Contributor

kie-ci4 commented Jun 9, 2023

(tests) - serverless-workflow-examples job #674 was: UNSTABLE
Possible explanation: This should be test failures

Reproducer

export BUILD_MVN_OPTS_CURRENT=
build-chain build cross_pr -f 'https://raw.githubusercontent.com/kiegroup/drools/main/.ci/buildchain-config.yaml' -o 'bc' -p kiegroup/kogito-examples -u https://github.com/kiegroup/drools/pull/5298 --skipParallelCheckout

NOTE: To install the build-chain tool, please refer to https://github.com/kiegroup/github-action-build-chain#local-execution

Please look here: https://eng-jenkins-csb-business-automation.apps.ocp-c1.prod.psi.redhat.com/job/KIE/job/drools/job/main/job/pullrequest/job/drools.tests.downstream.serverless-workflow-examples/674/display/redirect

Test results:

  • PASSED: 79
  • FAILED: 1

Those are the test failures:

org.kie.kogito.examples.DataIndexRestIT.testDataIndexRest 1 expectation failed.
JSON path data.ProcessInstances[0].state doesn't match.
Expected: is "COMPLETED"
Actual: ACTIVE

@tarilabs
Copy link
Member Author

tarilabs commented Jun 9, 2023

Jenkins rerun serverless-workflow-examples tests

@dupliaka
Copy link
Contributor

Performance report for dmn feel cases that compares this PR performance vs main baseline based on 1d6f95d
https://issues.redhat.com/secure/attachment/12987489/JMH%20Visualizer.pdf
https://issues.redhat.com/secure/attachment/12987488/JMH%20Visualizer%20Summary.pdf

@tarilabs tarilabs force-pushed the tarilabs-20230609-DROOLS-7469 branch from b38b7ce to 2344c56 Compare June 25, 2023 19:19
@tarilabs
Copy link
Member Author

(rebased on main)

@sonarcloud
Copy link

sonarcloud bot commented Jun 25, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

100.0% 100.0% Coverage
0.0% 0.0% Duplication

@kie-ci4
Copy link
Contributor

kie-ci4 commented Jun 25, 2023

(tests) - kogito-runtimes job #1471 was: UNSTABLE
Possible explanation: This should be test failures

Reproducer

export BUILD_MVN_OPTS_CURRENT=
build-chain build cross_pr -f 'https://raw.githubusercontent.com/kiegroup/drools/main/.ci/buildchain-config.yaml' -o 'bc' -p kiegroup/kogito-runtimes -u https://github.com/kiegroup/drools/pull/5298 --skipParallelCheckout

NOTE: To install the build-chain tool, please refer to https://github.com/kiegroup/github-action-build-chain#local-execution

Please look here: https://eng-jenkins-csb-business-automation.apps.ocp-c1.prod.psi.redhat.com/job/KIE/job/drools/job/main/job/pullrequest/job/drools.tests.downstream.kogito-runtimes/1471/display/redirect

Test results:

  • PASSED: 3348
  • FAILED: 1

Those are the test failures:

org.kie.kogito.it.KafkaPersistenceIT.testAsyncWIH Assertion condition defined as a lambda expression in org.kie.kogito.it.PersistenceTest that uses java.lang.String 1 expectation failed.
Expected status code <404> but was <200>.
within 10 seconds.

@tarilabs
Copy link
Member Author

Jenkins run kogito-runtimes tests

@tarilabs
Copy link
Member Author

tarilabs commented Jun 26, 2023

I've taken the time this past weekend to comprehensively run the benchmark suite using my "gaming" pc.
This reports on comparing this PR change (2344c56)
against main branch from main at: ad19dc5

system info

[tarilabs@fedora ~]$ java --version
openjdk 17.0.7 2023-04-18
OpenJDK Runtime Environment Temurin-17.0.7+7 (build 17.0.7+7)
OpenJDK 64-Bit Server VM Temurin-17.0.7+7 (build 17.0.7+7, mixed mode, sharing)
[tarilabs@fedora ~]$ hostnamectl 
    Operating System: Fedora Linux 38 (Workstation Edition)
         CPE OS Name: cpe:/o:fedoraproject:fedora:38
              Kernel: Linux 6.3.8-200.fc38.x86_64
[tarilabs@fedora ~]$ sudo lshw -short
H/W path                  Device          Class       Description
=================================================================
                                          system      System Product Name (SKU)
/0                                        bus         ROG STRIX X570-F GAMING
/0/0                                      memory      64KiB BIOS
/0/33                                     memory      32GiB System Memory
/0/33/0                                   memory      [empty]
/0/33/1                                   memory      16GiB DIMM DDR4 Synchronou
/0/33/2                                   memory      [empty]
/0/33/3                                   memory      16GiB DIMM DDR4 Synchronou
/0/36                                     memory      768KiB L1 cache
/0/37                                     memory      6MiB L2 cache
/0/38                                     memory      64MiB L3 cache
/0/39                                     processor   AMD Ryzen 9 3900XT 12-Core

query

used for comparing csv files

let
  Source = Csv.Document(File.Contents("/Users/mmortari/git/results20230625/baseline.results.csv"), [Delimiter = ",", Columns = 19, QuoteStyle = QuoteStyle.None]),
  #"Promoted headers" = Table.PromoteHeaders(Source, [PromoteAllScalars = true]),
  #"Changed column type" = Table.TransformColumnTypes(#"Promoted headers", {{"Benchmark", type text}, {"Mode", type text}, {"Threads", Int64.Type}, {"Samples", Int64.Type}, {"Score", type number}, {"Score Error (99.9%)", type number}, {"Unit", type text}, {"Param: alphalength", type text}, {"Param: expression", type text}, {"Param: numberOfDecisionTableRules", Int64.Type}, {"Param: numberOfDecisions", Int64.Type}, {"Param: numberOfDecisionsWithBKM", Int64.Type}, {"Param: numberOfDecisionsWithContext", Int64.Type}, {"Param: numberOfElements", type text}, {"Param: param", type text}, {"Param: resourceName", type text}, {"Param: sparseness", type text}, {"Param: useAlphaNetworkCompiled", type text}, {"Param: useExecModelCompiler", type text}}),
  #"Merged queries" = Table.NestedJoin(#"Changed column type", {"Benchmark", "Param: alphalength", "Param: expression", "Param: numberOfDecisionTableRules", "Param: numberOfDecisions", "Param: numberOfDecisionsWithBKM", "Param: numberOfDecisionsWithContext", "Param: numberOfElements", "Param: param", "Param: resourceName", "Param: sparseness", "Param: useAlphaNetworkCompiled", "Param: useExecModelCompiler"}, #"pr results2", {"Benchmark", "Param: alphalength", "Param: expression", "Param: numberOfDecisionTableRules", "Param: numberOfDecisions", "Param: numberOfDecisionsWithBKM", "Param: numberOfDecisionsWithContext", "Param: numberOfElements", "Param: param", "Param: resourceName", "Param: sparseness", "Param: useAlphaNetworkCompiled", "Param: useExecModelCompiler"}, "pr results2", JoinKind.Inner),
  #"Expanded pr results2" = Table.ExpandTableColumn(#"Merged queries", "pr results2", {"Benchmark", "Mode", "Threads", "Samples", "Score", "Score Error (99.9%)", "Unit"}, {"pr results2.Benchmark", "pr results2.Mode", "pr results2.Threads", "pr results2.Samples", "pr results2.Score", "pr results2.Score Error (99.9%)", "pr results2.Unit"})
in
  #"Expanded pr results2"

full dataset at: https://github.com/tarilabs/results20230625

Results

As mentioned in https://github.com/kiegroup/drools/pull/5298#issue-1750078050, the Compile-but-Interpreted is still the default so this would benefit the majority of the user base.

In this graph, I've focused on relevant changes for the Compile-but-Interpreted case only:

image

We notice the difference is mostly a very relevant positive change.
We also notice some cases appears to be negatively affected by this change, yet on further inspection sampling for instance the allegedly -9% is for the expression 10 - 5, the case for -7% is for the expression 1.12, etc. which are not to be impacted by the code change, hence likely tests fluctuations not filtered if compared to base error.

A more comprehensive report is available as PDF:
report_comparison full.pdf

Again mostly a very relevant positive change:
report_comparison full_page1

It is to be noted the most positive impacts pertain to expressions/model using string-literals, which is expected.
It is also to be noted in the negative deltas we notice in the reports are mostly related to benchmarks which are not to be impacted by the code change, so as above. Also, it is to be expected in the case of mere compilation time, now this code change impacts for more time spent during compilation (in order to save it at runtime).

Conclusions

  • Most changes are a very relevant positive change; when sampled a given result in details pertain to expressions/model using string-literals, which is expected.
  • Some negative changes relate to benchmarks which are not to be impacted by the code change (result fluctuations?) or for mere compilation time, which is expected (consuming more compile-time once, to save multiple times at runtime).
  • Will proceed to merge.

Copy link
Contributor

@dupliaka dupliaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regression results supports string-literals affection as well

@tarilabs tarilabs merged commit 20be49b into apache:main Jun 28, 2023
nprentza pushed a commit to nprentza/drools that referenced this pull request Jun 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants