Best practices in creating performant formulas in Polaris.

Avoid multiple concatenations. Split commonly used concatenations into separate line items.

Make use of IF ISBLANK() when concatenating text with delimiters and set to BLANK to avoid unnecessarily populating cells . Because the text data type consumes more memory than other formats (Classic only) minimizing their use and avoiding unnecessary calculations is crucial for optimal model performance. 

Engine Applicability: Classic Hyperblock and Polaris

If a text string concatenation is needed, build it in the smallest possible dimensionality. This minimizes the size of the text strings and significantly reduces calculation effort and memory usage. Guards should be used in Polaris to reduce populated cell count.
Engine Applicability: Classic Hyperblock and Polaris

Never combine SUM and LOOKUP within the same formula expression. This combination forces the calculation engine to perform a massive number of calculations and creates slow intermediate relationship mappings, especially when Time is a dimension or when source and target structures differ. To drastically reduce calculation size and optimize performance, you must always split SUM and LOOKUP operations into separate modules and line items.
Engine Applicability: Classic Hyperblock and Polaris

For long timescales or high cell counts, using the PREVIOUS() function is faster than the CUMULATE() function due to the potential number of cells required for the calculation. Use the expression: 'Calc line item' = 'data line item' + PREVIOUS('Calc line item') rather than CUMULATE('data line item').
Engine Applicability: Classic Hyperblock and Polaris
2.02-10a Short timescalesWhere the number of periods is small (Year granularity with a small number of years), CUMULATE is faster.

Polaris achieves calculation efficiency by minimizing the number of cells that the engine has to do work for. Some formulas can be calculated very efficiently by only doing work for 'populated' cells. The Calculation Complexity column will tell the modeler how the engine is interpreting a formula and how much work will be required for each populated source cell.

There are three types of Calculation Complexity: One-to-One, One-to-Many, and All Cells.

One-to-One 

This is the most efficient type of formula. ‌A One-to-One formula is a formula where the engine can ‘drive’ the calculation by only iterating over the populated cells in one or more of the source line items. In the example of “Revenue = Units * Price”, it's possible to drive this calculation in several ways:

  • You could calculate every target cell in Revenue.
  • You could multiply each non-zero value in Units to get the result, since the formula is a straight multiplication and anything multiplied by zero is zero.
  • You could also do a multiplication of every item in Price, but this would be less efficient.
One-to-One


In this case, the Polaris engine chooses the most efficient way to calculate the result. It takes only three real calculations instead of 15. This is key to efficiently calculating at high dimensionality.

One-to-Many 

One-to-Many formulas require a multiple of work for every populated source cell. This is displayed in the Calculation Complexity column as One-to-Many(x) where x is the 'Fan-out factor' or the number of calculations that has to be done for every source cell.

Having a formula with One-To-Many(x) can be a sign that data is being spread out over a dimension. 

One-to-Many
The formula for Units Months= QuarterValue(Units Quarters)

In this example, a simple reference between two line items where the target has a finer granularity than the source will have a Calculation Complexity of One-to-Many(3). ‌Note that not all cells are having to be calculated (or populated) here, but a multiple of the number of source cells are having work done.

All Cells 

All Cells is the least efficient when modeling with significant dimensionality. ‌This is the simplest to explain, in that the only mathematically valid way for Polaris to calculate the result of the formula is to do a calculation for every target cell. This is ‌how Classic calculates line items in almost all cases. This becomes very inefficient with significant dimensionality due to the sheer number of cells.

All Cells
The formula for Units Total = Units + 1

Having a large Fan-Out in the Complexity Column can lead to performance issues with line items with significant dimensionality.

Having All Cells in the Complexity Column can lead to performance issues with line items having significant dimensionality.

Unlike Classic, using Booleans instead of Number format isn't a big benefit because Boolean are about the same size as other formats.

In general, Polaris will interpret the meaning of the formula and attempt to identify the most efficient way to drive the calculation. The order of cases in an IF clause doesn't matter. For example, IF X THEN Y ELSE Z is exactly equivalent to IF NOT X THEN Z ELSE Y.

Polaris only uses memory when storing populated (non-default) values. This is why it's important to ensure that the logic of a model maintains default values (blank, false, and zero) as often as possible. For example, if the common scenario is for a value to be TRUE, consider reversing the logic and making the common result FALSE which is the default value.

Using constants and item(list) will create a 100% dense module as every cell will be populated.

A few functions are inherently computationally intensive. Used in significant dimensionality, they can be very slow to calculate. Examples of these are:

    • ISFIRSTOCCURRENCE()
    • RANK()
    • CUMULATE()

While SUM/LOOKUP combination should be avoided in Classic, it's paramount to avoid using it in Polaris. ‌The net result of a SUM and LOOKUP in the same formula is that the engine has to do a very large number of calculations for every target cell in a line item. Although the logic will take up a smaller amount of space, it's MUCH more efficient to split the LOOKUP into a different line item and then do the SUMs separately.

LOOKUPs in Polaris are computationally quite intensive, especially with significant dimensionality. The engine must iterate over every item in the dimension being LOOKED UP over. Consider making LOOKUPs their own line item. This might make the system work better by reducing how many times a LOOKUP needs to be calculated.

In the Polaris engine, comparing a line item value to a list member, most commonly seen in the format Module.Line Item = ITEM(List), can cause severe performance degradation at high cell counts. Because the system must cycle through the entire list for every cell to find the matching value, this approach consumes significant calculation effort. To optimize performance, use a SUM function instead, which processes substantially faster.
Engine Applicability: Polaris Only
Prioritize using the SUM function over LOOKUP whenever possible. Because Polaris is a natively sparse calculation engine, its performance characteristics and memory utilization differ significantly from the Classic Hyperblock Engine. SUM operations scale and execute more efficiently than LOOKUP operations, particularly across high dimensionality. Minimizing LOOKUPs helps preserve sparsity, reduces memory consumption, and significantly improves on-demand calculation speeds.

Engine Applicability: Polaris Only
To preserve sparsity and reduce calculation complexity, use an IF/THEN statement as a guard so that formulas only calculate and populate data where required (for example, IF 'In Season?' THEN Revenue * Units ELSE 0). Keep in mind that the Polaris engine inherently ignores default values (zero, BLANK or FALSE), meaning guards are only needed to introduce explicit conditions that the engine cannot automatically deduce.
Engine Applicability: Polaris Only
Using the ROUND function on a calculated value can reduce infinitesimally small values to an actual zero, dropping them out of memory and reducing the populated cell count. This is especially useful at the end of a calculation chain in a reporting module that may also have summaries and ODC, whereby reducing the populated count can have a greater impact.
Engine Applicability: Polaris Only