RSS .92| RSS 2.0| ATOM 0.3
  • Home
  • About ArchestrAnaut Blog
  • About Our Authors
  • Email Subscription
  •  

    Async scripts without using Async

    October 31st, 2011

     

    First off, yes we’re still around.  Got tied up in a rush job on a DeltaV Batch project that has taken me away for the last 3 weeks or so. 

    As promised in our last article we’re going to discuss how you can write a long running script without using asynchronous scripting.  To be totally fair this only works in the situation where your script is long running because you are iterating some kind of array.  If you need an async script because you have a really long database call or some long running file transaction there’s not much I can do for you.

    Before we get into the technique the first thing you need to understand is what an asynchronous script is.  When IAS executes its objects, on a particular engine all objects and scripts in those objects are executed one after another.  It’s pretty amazing that the software engines can get through so many pieces of code so fast.  Kudos to the software architects.  If you find yourself with scan overruns on an engine, the first thing to do if figure out if you have any objects hanging or hogging resources.  If everything checks out there you should create a new engine and move some objects over.  At this point you have now split your object list and allowed them to run in parallel.  A while back I saw some advice that said you shouldn’t have more engines than cores on your computer.  That seems to make sense if we’re trying to run all the engines in parallel as efficiently as possible.  By the way… getting back to the previous post… does this help you understand why it takes at least one scan to hookup to an attribute that is on another engine?  Back to what we were talking about, there’s not a lot of good information in the books on what async scripts are but here’s one line I found that helps a little bit

    Asynchronous scripting mode is a group of scripts running on the same, lower priority execution thread.

    There are two key points here to think about.  First, the scripts are running on a different thread.  If you know much about software development you know that in a single thread all actions are lined up and happen one after another.  In other words, if there is a slow poke in the group then everybody waits behind them to get done before they can execute, kinda like the old person in the grocery store who still insists on writing a check.  Extending the analogy a little bit imagine you’re at a Wal-Mart supercenter with 32 checkout lines.  Only problem is the manager only has 3 lines open.  Wow, did I just tie-in Wal-Mart to a discussion of asynchronous scripting in Archestra?  The second part of the analogy makes us think about the difference in speed of the checkout folks. We all know that all cashiers are not created equal.  Imagine you have one cashier that is totally focused on the customer in front of them, that customer is a high priority.  Chances are the line is going to move really fast  Let’s call this cashier Fay.  Now imagine another cashier who puts a low priority on the customer in front of them, say his name is Cletus.  They are answering their cell phone, chatting with the guy stocking the drinks, commenting on what the person behind you is wearing, in general they are being interrupted by higher priority tasks.  That process is going to move pretty slowly.  When you run your scripts in a normal fashion you get into Fay’s line.  While the line may be long she’s really efficient and gets everyone through in a quick manner.  When you run your scripts async you are in Cletus’s line.  You’ll get through, eventually, but you may be waiting around for a while.  What I have left out of this discussion though, is that Fay can only work for 15 minutes at a time and if you are standing in line when her 15 minutes is up, then you have to put everything back and start over again… this is like a scan overrun.  Enough of the Wal-Mart analogies, back to the highbrow stuff.

    So we have an array we’re trying to loop through but because of the length of the array and the nature of what we’re doing in the array, there is no way we can make it through the whole array in one scan.   How do you handle this.

    Well, the first thing to do is figure out how long you have to execute your script.  This is available to you via some parameters on your engine.  Here’s the expression we use to calculate what we call a Halt Time.

    Me._HaltTime = MyEngine.Scheduler.ScanTime + Me._ScanFraction * MyEngine.Scheduler.ScanPeriod / 1000;

    Basically what we’re doing is saying take the start time of the current scan cycle then add a portion of the scheduled scan time.  We will typically use something like 75%.  Say we start this scan at 13.2 seconds after the minute.  If we have a 1 second scan time and a 75% scan fraction we end up calculating a halt time of 13.95 seconds after the minute.  We’ll use this later in our loop.

    Next, we need to setup our tracking devices.  On the first time through our script we reset our tracking variable; say we call it j to 1.  You should keep track of what you have or haven’t done either via flags or some internal step counter.  Next, before you start looping, set your loop index, say we call it i , to whatever the value of j is.  What this is doing is allowing you to restart in the middle of your loop.  After each step you should be incrementing i along with setting j equal to i.  This is a bit hard to explain in prose so here it is in pseudocode.  Apologies in advance for my code not being as pretty as David’s.  I don’t have the patience to do all the formatting like he does.

    Dim j as Integer (in declarations section of script so it persists across scans)
    Dim i as Integer (in regular header part of script)

    If (we’re just starting this sequence) Then
           j = 1
         Go to Step 2
    End If

    If (we’re at Step 2)
         ‘ Initialize the loop index counter to whatever the last value of j was.  First time through this is 1, next time through it might be somewhere between 1 and the end of the array
         i = j

         ‘ Start looping and bail out of the loop if we are at the end OR we have reached our pre-calculated halt time
         While (I < ArrayLength AND Now() < Halt Time)
                    { Do yo thang….}
                     {Maybe a message saying you are x% done}
                     ‘Advance the counter and track the counter with j, which persists across scans
                     i = i + 1
                     j = i

          End While

         If (I >= ArrayLength) Then
                  ‘ We’ve made it all the way through so reset j and advance to the next step
                   j = 1
                   Go to Step 3
          End If

    So, if you follow what we’re doing we’re just using a secondary variable to keep up with how far we’ve made it in the array before we had to bail out.  Then, when we jump back in on the next scan we pick up where we left off.  Pretty slick huh?

    One of the interesting things we discovered while doing our testing was the idea that Async scripts are definitely slower.  During a test using this particular method above we saw a distinct 5x slowdown (70 ms to 370 ms) when we swapped to Async from Sync,  changing nothing else.  That should give you some perspective on what it means to swap to a low priority thread.

    I hope this was useful and worth the wait.

    Anyone else have a method they’ve developed that accomplishes something similar?


    Auto Assigning IO

    December 30th, 2010

    One of the things we do a lot of is automatically assigning IO to a corresponding IAS object or a PLC data structure.  We’ve tried several different auto-assignment schemes.  We had two main requirements:  be scalable and be reliable.

    Read the rest of this entry »


    Using .NET in IAS Scripting

    October 29th, 2010

    IAS is as flexible as or more flexible than any other platform out on the market in terms of the breadth of programming possibilities. The concept of inheritance makes it possible to make changes at a template level and all of its children (templates & instances) will be changed too. Equally as powerful is IAS’s inclusion of .NET in their QuickScript language.

    Read the rest of this entry »


    Getting Around Limitations in Logging Alarms

    October 29th, 2010

    Andy & I have always been fairly frustrated with the Wonderware Alarm Logger service.  It almost seems like an afterthought for System Platform (just look at the service name:  New_AlarmLogger).  Perhaps the most frustrating part is trying to integrate it into a system with redundant App Servers.  To the developers:  please integrate this into the System Platform in a future release.

    Read the rest of this entry »


    Writing Robust Scripts in IAS: Building Composite DataChange Expressions

    October 11th, 2010

    In my last article, I discussed a more reliable way of writing DataChange scripts. We often write scripts that are intended to be executed if one of multiple values change state or if a certain set of conditions occur. For the latter of the two scenarios, we write a simulated OnTrue / OnFalse script in the method described by the previous article.  Both scenarios require a composite value to execute a data comparison on.

    Read the rest of this entry »


    Writing Robust Scripts in IAS: Building DataChange Scripts that are Guaranteed to Execute

    October 4th, 2010

    In my last article, I laid out the basics on the inner workings of IAS objects and pointed out a few basic pitfalls.  The most important of these is the reliability of DataChange, OnTrue, and OnFalse scripts.  In a heavily loaded system, the AppEngine can spend too much time doing housekeeping work (i.e. checkpointing or communication with its redundant partner engine).  This leads to scan overruns which can be monitored (via object viewer or historizing) the AppEngine’s Scheduler.ScanOverrunCnt variable.

    Read the rest of this entry »


    Intro to Writing Robust Scripts in IAS

    September 27th, 2010

    In implementing the latest project, we have discovered many tips & tricks to improving reliability of ArchestrA objects.  In this series of blogs, I am going to shed a little light on some potential pitfalls in ArchestrA scripting and some useful workarounds.

    Read the rest of this entry »