Performance Improvements To Expression Evaluation

Last published at: July 6th, 2021

Most workflows use some sort of decision making based on expressions, these expressions could be very simple to complex. An expression such as 1==1 or Variable.x + Variable.y could be a very simple expression to evaluate, a more complex expression evaluation could be Variable.age > 18 or ((Variable.x * Variable.x) + (Variable.y * Variable.y))/2. These expressions are more mathematical, but FlowWright also supports other .Net based expressions such as DateTime.Now.AddDays(30).

Expressions are used in so many workflows, and keys part of any workflow, especially when it comes to workflows that make decisions or computations. FlowWright has its own expression evaluation engine, where it uses algorithms to in-memory compile expression programs and executes them to get the result of the expression. The expression evaluation is designed in such a way where it has no limitations, it can evaluate any expression. Most expressions take 150-300 milliseconds to execute.

Over the years we heard from our customers to improve the performance of the expression evaluation engine, especially from customers who use the product for real-time execution of workflows and customers who use Microservices. If 5 decision steps within the workflow execute, it could take 750-1500 milliseconds to execute.

In FlowWright, we were able to change the algorithm on how we build our in-memory compiled expressions, and have a reference to the previously built expressions using caching. Given these enhancements, the first execution of an expression still takes a similar hit in execution time, but all other similar expression calls will execute at near 0 milliseconds. 

For example, if the expression Variable.x + Variable.y was sent to evaluate, then the first time it may take 150 milliseconds, but the same expression coming in with different x and y values will execute at near 0 milliseconds. This improvement can be demonstrated graphically using the following workflow, the workflow contains several “Decision” steps and 2 expression steps. Decision steps are numbered from 1 to 6, and the expression steps are 7 and 8.

Looking at the first Decision step, #1, the below diagram shows that it took 121 milliseconds to execute.

But the remaining, Decision steps took only 0 milliseconds to execute, they executed in Microseconds.

Another way to visualize this data is to look at the analytics based on elapsed time on executed steps.

In reference to the previous diagrams, Decision steps 3,4,5 & 6 executed, and they elapsed 0 milliseconds to execute. Step 7 was a computation, it took  93 milliseconds to execute.

Step 8 was the same computational expression as step 7, and it took 0 milliseconds to execute, as shown below:

As you can see the Expression evaluation engine's execution performance was drastically improved. In the case of Microservices with expressions used to take 200-400 milliseconds to execute, but today, after the first call to the Microservices, it will average ~10-15 milliseconds to execute.

FlowWright offers an expression evaluation tool to test out expressions outside of workflows