# Building for Performance

**URL:** <https://forum.inductiveautomation.com/t/building-for-performance/71082>\
**Category:** Ignition\
**Tags:** ignition81, perspective\
**Created:** [March 15, 2023, 9:53am UTC](https://forum.inductiveautomation.com/t/building-for-performance/71082 "2023-03-15T09:53:12Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alex\_Leech](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/alex_leech/32/39391_2.png) [@Alex\_Leech](https://forum.inductiveautomation.com/u/Alex_Leech)\
**Post date:** [March 15, 2023, 9:53am UTC](https://forum.inductiveautomation.com/t/building-for-performance/71082/1 "2023-03-15T09:53:12Z")

</div>

Hi all,

Whilst I've been getting to grips with perspective bindings, I've noticed theres often multiple ways to achieve the same result. Taking a simple example, Which would be the most efficient way to perform the following:

A binding of the display parameter on label-1 to label-2, except it is required to be inverse?  
The few ways that jump out are:

1. Create a property binding, and add an expression transform as `!{value}`
2. Create a property binding, and add an mapping transform with true \> false and vice versa.
3. Create an expression binding as `!{path/to/prop}`

Is there any one of these that is 'prefered' or more efficient?  
The above is but a simple example. I'd love to see (or be pointed to as it no doubt exists) a guide on the best way to maximise performance of the system by design.

Have a great day!

Alex

---

<div class="post-metadata">

**Author:** ![andrew.budaiev](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/andrew.budaiev/32/72921_2.png) [@andrew.budaiev](https://forum.inductiveautomation.com/u/andrew.budaiev)\
**Post date:** [March 15, 2023, 10:11am UTC](https://forum.inductiveautomation.com/t/building-for-performance/71082/2 "2023-03-15T10:11:08Z")

</div>

Maybe somebody has a guide, but I got some topics for you.

> [@General Binding Efficiency Ranking](https://forum.inductiveautomation.com/t/general-binding-efficiency-ranking/67686):
>
> In general, what is the ranking for binding efficiency for something like a template? For example, would it be something like the following? Is there a resource or topic that has addressed this (I can't seem to find it)? Direct Binding Indirect Binding Expressions Scripting SQL Query Also, for Perspective, where would the various transforms fall into the ranking (map, expression, script, etc.)?

> [@Perspective: Binding efficiency between using Expression and Indirect Tag + Expression tranform](https://forum.inductiveautomation.com/t/perspective-binding-efficiency-between-using-expression-and-indirect-tag-expression-tranform/38881):
>
> v8.1.0 What’s more efficient and more performant for bindings: Using an expression binding for example: toBoolean(tag('tag/path/' + {parameterX})) Using an indirect tag binding and then applying an expression transform, e.g.: a)tag indirect binding: tag/path/{1}, {1} =\> {parameterX} b)expression transform: toBoolean({value})

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [March 15, 2023, 2:11pm UTC](https://forum.inductiveautomation.com/t/building-for-performance/71082/3 "2023-03-15T14:11:43Z")

</div>

In this example, #3 is the most performant, though it could be argued that the performance gain in this instance would be negligible. Anytime you add an additional processing step you add latency.

In general for the best performance I follow these guidelines:

- If you can achieve what you want with a binding, use a binding.
- Always use the binding type that is the most direct. (e.g. if all you need is a binding to a property use a property binding, not an expression binding.)
- Given the choice between an expression and a script, use an expression.
- Minimize the amount of data that must travel between gateway and client.
- Minimize the amount of duplicate data repeatedly sucked out of your database (caching, etc).
- Minimize the amount of duplicate calculations done for multiple points of use
- When scripting choose a Java import over a python import if available
- When scripting use the NetBeans shortcuts where applicable
- Keep global script data in top level variables in a project script rather than recreating it
- When scripting tag reads and writes always combine them to as few function calls as possible.

I've picked these up from various posts on the forum over time. I keep a running list for quick reference (particularly for training) and add little golden nuggets when I see them.

A couple of links for references.

@paul-griffith's assumptions about the performance of different binding transforms

> [@Binding Transforms Best Practices](https://forum.inductiveautomation.com/t/binding-transforms-best-practices/24899/2):
>
> Seat of the pants answer with no performance testing to back it up: native transforms (ie, mapping) will be faster than expression transforms will be faster than script transforms “Native” transforms are executing as direct Java code in and out. Expressions have to be parsed and calculated in steps, so there’s more lookups and variable timing involved. Scripts will almost certainly be the slowest - we have to either grab or create a Python interpreter, compile the function you provide (we …

> [@General Binding Efficiency Ranking](https://forum.inductiveautomation.com/t/general-binding-efficiency-ranking/67686/3):
>
> Without actually doing the research to back it up: Format \> Map \> Expression \> Script, in terms of performance. Again, caveats as Phil noted, including the fact that map transforms can have expressions in the output.

NetBeans shortcuts are faster than the long form. For example if getting the column names from a dataset object use `dataset.columnNames` rather than `dataset.getColumnNames()`

> [@Looking for advice on dynamic Pen creation in the Power Chart component](https://forum.inductiveautomation.com/t/looking-for-advice-on-dynamic-pen-creation-in-the-power-chart-component/67751/3):
>
> Yes, if scripting anyways. If avoiding scripting to avoid its startup penalty, the lookup() expression function with a dataset tag is a performant option. No, this: pyr['value'].quality.good not pyr['value'].quality.good Use the NetBeans shortcuts everywhere applicable, not just .value or .quality, as they run faster and are more readable. Even better is to only check .good in the if clause and use an else: clause for not good.

> [@How do you increase performance for clients?](https://forum.inductiveautomation.com/t/how-do-you-increase-performance-for-clients/62703/2):
>
> Vision or Perspective? In general, though: Minimize the amount of data that must travel between gateway and client. Minimize the amount of duplicate data repeatedly sucked out of your database (caching, etc). Minimize the amount of duplicate calculations done for multiple points of use (less important in Vision clients).

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [August 6, 2024, 3:39pm UTC](https://forum.inductiveautomation.com/t/building-for-performance/71082/4 "2024-08-06T15:39:03Z")

</div>

A link to one of my experiments belongs here:

> [@Tag binding or expression to read dynamic list of tags](https://forum.inductiveautomation.com/t/tag-binding-or-expression-to-read-dynamic-list-of-tags/76610/16):
>
> Collected some overhead stats. Added a sixth binding for comparison, and made them all trigger from a common reference. The new expression transform looks like this: nanoTime() - {value} It is notably faster than the other transforms. To make the recorder() run smoothly, I made a trigger timestamp with now({this.custom.pace}) and set pace to 200. Then I modified the transforms' first stages to look like this: asList( {this.custom.trigger}, nanoTime() )[1] The non-transform tests of run…
