# Button with long script inconsistent

**URL:** <https://forum.inductiveautomation.com/t/button-with-long-script-inconsistent/54070>\
**Category:** Ignition\
**Tags:** ignition81, scripting\
**Created:** [December 13, 2021, 8:03pm UTC](https://forum.inductiveautomation.com/t/button-with-long-script-inconsistent/54070 "2021-12-13T20:03:57Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Yvain17](https://avatars.discourse-cdn.com/v4/letter/y/977dab/32.png) [@Yvain17](https://forum.inductiveautomation.com/u/Yvain17)\
**Post date:** [December 13, 2021, 8:03pm UTC](https://forum.inductiveautomation.com/t/button-with-long-script-inconsistent/54070/1 "2021-12-13T20:03:57Z")

</div>

Ignition Version 8.1.2

Hello, I have recently started ignition at a new job and the project I am now working on is huge. Over 50 different main screens and 20k+ tags. On one screen there is a momentary button that runs a script that is about 400 lines long. It is a mix of reading tags & OPC values, doing calculations on the values, and then writing the new values back. The script is triggered off the “mouseClicked” event handler. The problem is sometimes the values that the script is supposed to write back never get written, which then will throw an error on the screen it is located on. I am curious if I can get this button working more reliably. If it matters, the script also sets a tag value based on “mouseReleased”.

Any help is appreciated.

---

<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:** [December 13, 2021, 8:42pm UTC](https://forum.inductiveautomation.com/t/button-with-long-script-inconsistent/54070/2 "2021-12-13T20:42:17Z")

</div>

> [@Yvain17](#):
>
> On one screen there is a momentary button that runs a script that is about 400 lines long. It is a mix of reading tags & OPC values, doing calculations on the values, and then writing the new values back. The script is triggered off the “mouseClicked” event handler.

Without seeing the script I can only guess at how best to help.

First, this sounds like an Anti-pattern known as the Magic-Pushbutton. Does this type of programming, even the exact same programming, exist in other places in the project?

You should consider moving the code to a project script and generalizing it, such that it can be used in multiple places. Especially if this code is a long running task (note: not determined by the number of lines). If it is a long running task then it should be moved to a background script if it isn't already. There are numerous threads relating to that topic. Search for `system.util.invokeAsynchronous()`.

Second group all tag reads at the start of the script and all tag writes to the end of the script. Doing single tag reads and writes will greatly increase the execution time of the script.

Finally, you said reading/writing OPC values. I would avoid reading directly from the device unless necessary, off load that work to the gateway.

Without seeing the script its going to be difficult to really help you optimize it.

---

<div class="post-metadata">

**Author:** ![Yvain17](https://avatars.discourse-cdn.com/v4/letter/y/977dab/32.png) [@Yvain17](https://forum.inductiveautomation.com/u/Yvain17)\
**Post date:** [December 13, 2021, 9:06pm UTC](https://forum.inductiveautomation.com/t/button-with-long-script-inconsistent/54070/3 "2021-12-13T21:06:55Z")

</div>

This is the only button in the program that uses a script of this magnitude. It is also not something that is used anywhere other than this screen, so I do not believe it is necessary to have the script running in the background. The script is also only used every few hours at the most.

The script itself is split up. The first half of the script is reading tags and OPC values.  
The second half is doing the calculating and writing. Should the calculating be split up as well? Each calculation takes place just before each write. The calculations are simple arithmetic.

The script goes like this.

valueX = system.tag.read(“tagpath”).value (x25 lines)

valueX = system.opc.readValue(serverName, “direct OPC path”).value (x60 lines)

valueX = system.tag.read(“tagpath”).value (x25 lines)

value = value \* value / value (example calculation)  
system.tag.write(“tagpath”, value) (75x lines)

The last two lines of the script:  
value = system.tag.read(“tagpath”).value  
system.tag.write(“tagpath”,value)

There are over 60 lines that are reading direct OPC values, so that could definitely have an effect on the performance. I will create tags for those tomorrow and see if performance increases. If this has no effect I will upload the script. I would just like to delete the tag paths/names beforehand for privacy purposes and that may take me a bit.

Thank you for your response.

---

<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:** [December 13, 2021, 9:10pm UTC](https://forum.inductiveautomation.com/t/button-with-long-script-inconsistent/54070/4 "2021-12-13T21:10:01Z")

</div>

Any script that needs more than one tag value or OPC item value should be using lists of tag paths or lists of item paths (with the “Blocking” function). So too with the writes–write that all at once.

You will be stunned at the change in performance.

---

<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:** [December 13, 2021, 9:21pm UTC](https://forum.inductiveautomation.com/t/button-with-long-script-inconsistent/54070/5 "2021-12-13T21:21:27Z")

</div>

> [@Yvain17](#):
>
> There are over 60 lines that are reading direct OPC values, so that could definitely have an effect on the performance. I will create tags for those tomorrow and see if performance increases.

This will not have near the performance increase that combining all of the reads and writes into 1 will.

Your script should look something like:

```python
tagValues = system.tag.readBlocking(['tagPath1','tagPath2', ... ,'tagPathN'])

#do your calculations

system.tag.writeBlocking(['tagPath1','tagPath2',...,'tagPathN'],[writeValue1,writeValue2,...writeValueN])

```

[https://docs.inductiveautomation.com/display/DOC81/system.tag.readBlocking](https://docs.inductiveautomation.com/display/DOC81/system.tag.readBlocking)  
[https://docs.inductiveautomation.com/display/DOC81/system.tag.writeBlocking](https://docs.inductiveautomation.com/display/DOC81/system.tag.writeBlocking)

I like to create a dictionary that holds all of the read values where the tagName is the key and then modify those values, then I can use that same dictionary at the end to write all of the values back.

---

<div class="post-metadata">

**Author:** ![dkhayes117](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/dkhayes117/32/68344_2.png) [@dkhayes117](https://forum.inductiveautomation.com/u/dkhayes117)\
**Post date:** [December 13, 2021, 9:30pm UTC](https://forum.inductiveautomation.com/t/button-with-long-script-inconsistent/54070/6 "2021-12-13T21:30:59Z")

</div>

> [@Yvain17](#):
>
> he script also sets a tag value based on “mouseReleased”.

I would be using the `onActionPerformed` event, not the mouse events

> [@lrose](#):
>
> I like to create a dictionary that holds all of the read values where the tagName is the key and then modify those values, then I can use that same dictionary at the end to write all of the values back.

Oh nice, I didn't think of that. I guess you are doing something like

```auto
myDict = {data...}
system.tag.writeBlocking(myDict.keys(),myDict.values())

```

---

<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:** [December 13, 2021, 11:55pm UTC](https://forum.inductiveautomation.com/t/button-with-long-script-inconsistent/54070/7 "2021-12-13T23:55:58Z")

</div>

Similar, though I’m lazy so I’ve written the scripts to account for a parent path so that I don’t have to type the entire tagPath when referencing a value.

You can find the exact scripts here:

> [@Editing historian tag data](https://forum.inductiveautomation.com/t/editing-historian-tag-data/49328/29):
>
> First of all, please don’t think I am saying that your are doing it wrong, IMO if it works then it isn’t really “wrong”. However, there are often more ‘reliable’, ‘performant’ and/or ‘more readable’ ways of doing things. That is what makes best practices, best practices. You can read each tag individually, it will work, it is not the most performant way to do it. This is the way I do it, it is not the only way to do it, nor is it probably the “best” way to do it. So, here is how I do this. …

---

<div class="post-metadata">

**Author:** ![Yvain17](https://avatars.discourse-cdn.com/v4/letter/y/977dab/32.png) [@Yvain17](https://forum.inductiveautomation.com/u/Yvain17)\
**Post date:** [December 14, 2021, 1:11pm UTC](https://forum.inductiveautomation.com/t/button-with-long-script-inconsistent/54070/8 "2021-12-14T13:11:00Z")

</div>

Ah that makes a lot of sense. Will be doing this today and will report on the results when I finish. I’ve sort of inherited this project and there are definitely some rough edges so I’m just working through it piece by piece.

---

<div class="post-metadata">

**Author:** ![Yvain17](https://avatars.discourse-cdn.com/v4/letter/y/977dab/32.png) [@Yvain17](https://forum.inductiveautomation.com/u/Yvain17)\
**Post date:** [December 14, 2021, 7:49pm UTC](https://forum.inductiveautomation.com/t/button-with-long-script-inconsistent/54070/9 "2021-12-14T19:49:27Z")

</div>

Got the script working. I was able to make a huge reading list and huge writing list. At the very end of the script I had to add an additional read/write because the value being read is being written in the block before it. Much better performance so far from what I can see, but I will gather more feedback as the operators use the button. Thank you for your help. I will definitely be using the readBlocking/writeBlocking for future scripts.

---

<div class="post-metadata">

**Author:** ![jlandwerlen](https://avatars.discourse-cdn.com/v4/letter/j/bc8723/32.png) [@jlandwerlen](https://forum.inductiveautomation.com/u/jlandwerlen)\
**Post date:** [December 14, 2021, 8:29pm UTC](https://forum.inductiveautomation.com/t/button-with-long-script-inconsistent/54070/10 "2021-12-14T20:29:53Z")

</div>

FYI, you can use this code to help narrow down long execution times.

```auto
import datetime
startTime = datetime.datetime.now()
print startTime 

'Do stuff'

print datetime.datetime.now()
print datetime.datetime.now() - startTime 

```

---

<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:** [December 14, 2021, 8:46pm UTC](https://forum.inductiveautomation.com/t/button-with-long-script-inconsistent/54070/11 "2021-12-14T20:46:55Z")

</div>

You really ought not to be recommending python’s datetime module. Ignition has a family of date functions for a reason. For timing measurements that aren’t affected by system clock adjustments, use java.lang.System.nanoTime(). It is monotonic and carefully synchronized across CPU cores.

---

<div class="post-metadata">

**Author:** ![jlandwerlen](https://avatars.discourse-cdn.com/v4/letter/j/bc8723/32.png) [@jlandwerlen](https://forum.inductiveautomation.com/u/jlandwerlen)\
**Post date:** [December 14, 2021, 9:13pm UTC](https://forum.inductiveautomation.com/t/button-with-long-script-inconsistent/54070/12 "2021-12-14T21:13:08Z")

</div>

Dude, I think it’s good enough for most purposes, especially what the OP described. But, feel free to post your example on top of mine 🙂
