As a Novacura Flow designer, you are partly responsible for the performance of the applications you create with Novacura Flow. This chapter contains design guidelines that are important to consider.
Data Filtering: Filter data at the source (e.g., SQL where clauses, REST filters) to minimize resource usage across data layers, networks, servers, and clients.
Indexed Fields in Database: Use indexed fields when retrieving data. Embedding logic in SQL queries is often more efficient than processing in FlowScript.
FlowScript Specific Optimizations
Avoid Nested Loops
Poor Practice: Nested loops in large datasets cause performance bottlenecks.
Optimized Approach: Reduce nesting by preprocessing data or using efficient data structures.
Use for Reused Table Expressions:
Poor Practice: Repeated evaluation of the same condition.
for DataRow in DS_MyData {
let mySum = case when x then tmpTab WHERE X = DataRow.X AND Y = 't1'
when y then tmpTab WHERE X = DataRow.X AND Y = 't2' end;
}
Optimized Approach: Use Eval() to evaluate once, then reference the result.
for DataRow in DS_MyData {
let preEvaluatedCondition = Eval(tmpTab where X = DataRow.X);
// Subsequent operations using preEvaluatedCondition
let mySum = Eval(case when x then preEvaluatedCondition WHERE Y = 't1'
when y then preEvaluatedCondition WHERE Y = 't2' end);
}
Efficient Data Grouping:
Poor Practice: Inefficient data processing without grouping.
Optimized Approach: Use group-by or inner join for data aggregation.
let joinedData = DS_MyData INNER JOIN DS_Another ON MyId=OtherId;
// Process joinedData
Code Clarity and Testing
Clarity: Ensure Flow Script is clear and maintainable.
Testing: Regularly test scripts to avoid performance issues in production environments.
Documentation
Comprehensive Documentation: Maintain detailed documentation for each script, including functionality and special considerations.
Flow Studio Performance Tips
Parallel Execution: Fetch independent data simultaneously using data arrows to optimize execution time.
This will ensure that the data is fetched simultaneously. In the example below, the execution time would have been 15 seconds if the machine tasks had been placed in a line. Using data arrows like, in this example, the execution time will be 10 seconds.
Portal Performance Tips
The two most impactful tips that should always be considered are:
Avoid using the table operations connector! (when having a workflow as a data source).
Always try to use OnRowSelected when possible! (see more info below).
More information on the table operations connector:
In the early versions of Flow 6, the table operations connector enabled sorting, filtering, and other interactions in table portlets within Portal. However, in later versions, these capabilities have been re-implemented in a more performance-optimized way that no longer relies on the table operations connector.
Due to its complexity, the table operations connector may still function adequately in low-load scenarios, such as environments with few users or minimal usage of portlets tied to workflows using this connector.
We subjected the system to stress testing using automated tools to identify performance issues related to the table operations connector. Without diving into the specifics of the resulting charts, here is a simplified explanation:
Purple ascending line: Number of requests per minute (right Y-axis).
Bar height: Average response time in seconds experienced by users (left Y-axis).
X-axis: The duration of the test is in seconds.
During the test, the system was gradually loaded with more users, performing an increasing number of requests over time.
With Table Operation
Without Table Operation
This aligns well with customer feedback using the table operations connector—performance is often acceptable but can randomly degrade, sometimes causing the system to freeze or even time out.
Diagnosing the root cause using Windows performance monitoring tools (CPU, memory, disk, or network usage) proved difficult due to the inconsistent and unpredictable nature of the performance issues.
After rebuilding the workflows to avoid the table operations connector, performance became far more predictable. In the lower chart below, the CPU usage correlated much better, making system behavior easier to interpret and manage under stress.
More information on OnRowSelected vs. OnFilter
For the portal, some portlets are more sensitive than others. A table has an easier time keeping 100,000 records than, for example, the Kanban portlet, which has a much more complex rendering process. One hundred thousand cards would not only be impossible to scroll through, but it would also take time to render all the cards. The more complex the portlet, the more critical it is to narrow down the data.
Always use OnRowSelected rather than OnFilter, regardless of whether filtering is performed from a filter or another portlet. OnFilter retrieves all the data and filters, while OnRowSelected predicates the search using search parameters (i.e., using them in a WHERE clause in SQL or narrowing down the data with an OData parameter in a where clause in SQL or narrowing down the data with an Odata parameter in a HTTP call)
Requesting data without pre-filters is like going to a library and bringing all books home just to decide which one to read later. A more efficient approach is to first decide which book you need and ask the librarian for that specific one—saving time and effort. Similarly, applying filters before retrieving data ensures you only get what you actually need.
Portlet specific recommendations
Gantt Portlet Performance
Virtual Scrolling: Enable virtual scrolling for better performance with long task lists.
Consider the "Enable virtual scrolling" setting under GENERAL - ADVANCED SETTINGS to set how the tasks are rendered. If 'Enable virtual scrolling' is not set, all tasks returned by the query will be rendered, regardless of whether they are visible on the screen or not. If it is set, only the tasks seen are rendered directly, and tasks continue to be rendered as the user scrolls in the Gantt. This setting can significantly enhance the performance experience in scenarios with a lengthy task list. Still, it may also appear flickering since it re-renders the screen more frequently.
ID Optimization: Use numerical values for IDs in hierarchical data. Avoid long text strings, special characters, and spaces.
The Gantt portlet offers the option to use hierarchical data, where tasks can consist of other sub-tasks. A numerical value should be used to match IDs. Using long special character columns as the ID could significantly negatively impact performance. For example, if there are 5 entries where ID 1 is the parent of 3, 4, and 5, matching the parent and children on the "Name" column incurs a larger performance hit than matching a numerical value.
Tests have shown that a short text string, such as Char(5), is significantly faster than a longer one. The same applies to spaces that should be avoided if possible. If numeric IDs are not an option, try to keep the IDs to short strings without special characters and spaces.