Home AMX User Forum NetLinx Studio

Efficiency of running code in DEFINE_PROGRAM

Just picked up a job that was done by a company that is out of business and the program is full of stuff under DEFINE_PROGRAM. From a style and maintenance standpoint, it is always my goal to never run code there. In my view, it is horribly inefficient to keep running code on every pass, especially for things like button feedback and time of day.

However, from an internal efficiency standpoint, I don't know how much this really "costs" in terms of performance. For example, is there much of a difference in performance in a CHANNEL_EVENT vs. running a boolean in DEFINE_PROGRAM?? Any thoughts or experiences?

<this programmer must have gotten paid by the line>
«1

Comments

  • DHawthorneDHawthorne Posts: 4,584
    It depends on the code. Some types of feedback are hardly more than a register comparison, and have very little impact. Once you start running functions, manipulating strings, etc., the impact is far greater ... but honestly, I've done all that and haven't seen much of a difference. I think as long as you try to keep it under control, and give any functions in there a quick abort if there is nothing to be done, it's not really an important issue. Of course, if you are running tens of thousands of lines of code, it could become one, but I think that falls under "keep it under control."

    But your main difference between something being fired in DEFINE_PROGRAM vs a channel event is that the code doesn't run from CHANNEL_EVENT unless that channel has changed. DEFINE_PROGRAM runs every time. If it doesn't do much of anything though, how much harm is it?
  • a_riot42a_riot42 Posts: 1,624
    sonny wrote: »
    <this programmer must have gotten paid by the line>

    It must be Vinings code :)

    It shouldn't be that noticeable to the ordinary user. However, I have noticed quite a difference on larger systems with lots of code in define_program but never to the point where people would notice if they couldn't directly compare. As long you aren't sending strings to UIs or running for loops in define_program you should be ok.
    Paul
  • sonnysonny Posts: 208
    DHawthorne wrote: »
    But your main difference between something being fired in DEFINE_PROGRAM vs a channel event is that the code doesn't run from CHANNEL_EVENT unless that channel has changed. DEFINE_PROGRAM runs every time. If it doesn't do much of anything though, how much harm is it?

    hard to say because the system obviously has some sort of event processor running that has overhead for each defined event, so I assume that load is removed by placing it in DEFINE_PROGRAM
  • sonnysonny Posts: 208
    a_riot42 wrote: »
    As long you aren't sending strings to UIs or running for loops in define_program you should be ok.
    Paul

    there is definitely a lot of button feedback going on, also nested waits with loops, selects, etc. looking for time events. I'm going to re-write all those for scheduled events as some don't appear to be properly executing.
  • viningvining Posts: 4,368
    A simple fix would be to add a simple wait 1 or 2 (more if possible) before all the code running in DEFINE_PROGRAM. At least then the master doesn't have to deal with that code on every pass.
    a_riot42 wrote: »
    It must be Vinings code :)

    Paul
    That wasn't very nice but since you used a smiley face I'll let it pass, besides you're too far away to smack :D but for the record I don't get paid by the line since I'm self employed and my code isn't really that long, I just stretch it out by using alot of braces because it's more readable, at least to me and that's what's important.
  • HedbergHedberg Posts: 671
    I don't have a problem with putting stuff in define_program. It only gets run when there's nothing else for the master to do (as I understand it) and if it's just feedback and conditionals, well, you can probably evaluate 100,000 of those in a msec. Ok, maybe not quite that many, but I'd bet lots and lots. Perhaps there would be a hit when a tp comes on line, or something, but that hit's going to happen somewhere anyway.

    And as for smilies, anybody who doesn't agree with me can go screw themselves(insert smilie of your choice here).
  • a_riot42a_riot42 Posts: 1,624
    Hedberg wrote: »
    It only gets run when there's nothing else for the master to do (as I understand it)

    That's true, although once define_program is started it needs to complete before servicing any more requests. If you put an infinite while loop in define_program your button events won't get triggered since the processor is hung up in define_program.
    Paul
  • HedbergHedberg Posts: 671
    a_riot42 wrote: »
    That's true, although once define_program is started it needs to complete before servicing any more requests. If you put an infinite while loop in define_program your button events won't get triggered since the processor is hung up in define_program.
    Paul

    Yeah, and if you put an infinite loop in our button event it will, at the very least, slow down your system too. Moral of that story is: don't write code with infinite loops. Has nothing to do with whether coding in define_program is well or ill advised.

    The way Netlinx programming works, almost everything is better handled with events and timelines and functions and such. But, feedback to tps and the stray if-then can be handled well and easily within define_program with very little risk to program functioning/efficiency. A single Duet module probably inflicts more damage than just about anything a Netlinx programmer would normally do in define_program.(insert desired smiley here)
  • TurnipTruckTurnipTruck Posts: 1,485
    Hedberg wrote: »
    A single Duet module probably inflicts more damage than just about anything a Netlinx programmer would normally do in define_program.(insert desired smiley here)

    Amen my brother! So many within the AMX world look at me like I'm nuts when I mention my outright refusal to have any Duet running in my system.

    When I first started programming Netlinx, it was drilled into my head that NOTHING belongs in define_program and that my systems would blow up if one line of code was placed there.

    To date, I have seen no ill effects from code within define_program. Although I rarely place code there, I have used IF statements to check if there is anything in a buffer, then call other functions. No problems.
  • ericmedleyericmedley Posts: 4,177
    Amen my brother! So many within the AMX world look at me like I'm nuts when I mention my outright refusal to have any Duet running in my system.

    When I first started programming Netlinx, it was drilled into my head that NOTHING belongs in define_program and that my systems would blow up if one line of code was placed there.

    To date, I have seen no ill effects from code within define_program. Although I rarely place code there, I have used IF statements to check if there is anything in a buffer, then call other functions. No problems.

    I've been trying to write all my code without anything in Def_Prog for about a year. I can say that it seems to have made a difference. However, when I put in any modules made by others (Kaleidescape, ReQuest, AMX, etc... ) all bets are off since in many cases, I don't know what's in them. I played with the K-Scape module to move all the code out of DP and it seemed to work a lot better on my overall system.

    I can say that it's best, if you choose to put stuff in DP, to keep the checkers very simple. If you put If( condition A && condition B && with lots of stuff here) it can have noticeable effects.

    This is all anecdotal information and I have no hard facts to back up anything I've said.
  • a_riot42a_riot42 Posts: 1,624
    Hedberg wrote: »
    Yeah, and if you put an infinite loop in our button event it will, at the very least, slow down your system too. Moral of that story is: don't write code with infinite loops. Has nothing to do with whether coding in define_program is well or ill advised.

    You missed my point but that's ok.
    Paul
  • HedbergHedberg Posts: 671
    a_riot42 wrote: »
    You missed my point but that's ok.
    Paul
    Maybe I did. What was it? That if you clutter up your define_program with a bunch of crappy code that it will slow things down or something subtle?
  • a_riot42a_riot42 Posts: 1,624
    Hedberg wrote: »
    Maybe I did. What was it? That if you clutter up your define_program with a bunch of crappy code that it will slow things down or something subtle?

    My point was that once define_program is started it needs to complete before further processing can be done. So even though its true as Dave Hawthorne mentions that it runs as an idle process, and therefore only gets run when nothing else is going on, once define_program has started running it has to complete before processing button events. The fact that its an idle process doesn't mean it can't hold up processing of other I/O.
    Paul
  • viningvining Posts: 4,368
    a_riot42 wrote: »
    My point was that once define_program is started it needs to complete before further processing can be done. So even though its true as Dave Hawthorne mentions that it runs as an idle process, and therefore only gets run when nothing else is going on, once define_program has started running it has to complete before processing button events. The fact that its an idle process doesn't mean it can't hold up processing of other I/O.
    Paul
    So if we're in DEFINE_PROGRAM and some event happens the master must completely finish running what ever is in DEF_PROG and when it exits it checks the event queue for any business. If something's there it handles it and if there's nothing it runs through DEF_PROG again and this repeats continously. Basically everything the system does that isn't in DEF_PROG is an event of some sort whether they're internally (waits, timelines, etc.) or externally driven events (button pushes, IO's channels, etc). Is that a reasonably accurate simplified assessment?
  • a_riot42a_riot42 Posts: 1,624
    vining wrote: »
    Is that a reasonably accurate simplified assessment?

    Yes, but I could have said the same thing in half as many lines :)
    Paul
  • Joe HebertJoe Hebert Posts: 2,159
    a_riot42 wrote: »
    That's true, although once define_program is started it needs to complete before servicing any more requests. If you put an infinite while loop in define_program your button events won't get triggered since the processor is hung up in define_program.
    Paul
    Exact same can be said for any event or function.
    Netlinx doesn’t discriminate.
    A while(1){} anywhere brings the system down.
  • mpullinmpullin Posts: 949
    Joe Hebert wrote: »
    Exact same can be said for any event or function.
    Netlinx doesn’t discriminate.
    A while(1){} anywhere brings the system down.

    While(1) is that uncle that went to prison for money laundering. If you're wise you won't ask him to do your taxes, but you still invite him to thanksgiving once a year, because he's family.
    DEFINE_FUNCTION INTEGER LUTRON_COMPARE_ADDR(CHAR addrA[20],CHAR addrB[20]){
        // returns true if addrA is the same as addrB.  Disregards possible leading 0s in all quads
        STACK_VAR CHAR cAddrA[20];
        STACK_VAR CHAR cAddrB[20];
        STACK_VAR INTEGER iA;
        STACK_VAR INTEGER iB;
        cAddrA = addrA;
        cAddrB = addrB;
            
        while(1){ // keep stripping away :s and comparing digits until mismatch, or no more :s
    	if(FIND_STRING(cAddrA,':',1) == false){
    	    if(FIND_STRING(cAddrB,':',1) == false){
    		// neither one has a :.  do final evaluation!
    		iA = atoi("cAddrA");
    		iB = atoi("cAddrB");
    		if(iA == iB) return true;
    		else return false;
    	    }
    	    else return false;
    	}
    	if(FIND_STRING(cAddrB,':',1) == false) return false;
    	iA = atoi("REMOVE_STRING(cAddrA,':',1)");
    	iB = atoi("REMOVE_STRING(cAddrB,':',1)");
    	if(iA != iB) return false;
        }
        return false; // unreachable
    }
    
  • Joe HebertJoe Hebert Posts: 2,159
    I said while(1){} (open and close braces...an infinite while loop which is what a_riot42 referred to.)
  • mpullinmpullin Posts: 949
    Joe Hebert wrote: »
    I said while(1){} (open and close braces...an infinite while loop which is what a_riot42 referred to.)
    Whoops, my bad. Must not have noted those.
  • jjamesjjames Posts: 2,908
    BAZINGA!!!!!! :D
  • a_riot42a_riot42 Posts: 1,624
    Joe Hebert wrote: »
    Exact same can be said for any event or function.
    Netlinx doesn’t discriminate.
    A while(1){} anywhere brings the system down.

    Except that button events don't get executed 200-300 times a second.
    Paul
  • viningvining Posts: 4,368
    a_riot42 wrote: »
    Yes, but I could have said the same thing in half as many lines :)
    Paul
    Good one, now that was actually funny! :)
    ---Quote (Originally by Joe Hebert)---
    Exact same can be said for any event or function.
    Netlinx doesn’t discriminate.
    A while(1){} anywhere brings the system down.
    ---End Quote---
    Except that button events don't get executed 200-300 times a second.
    Paul
    Doesn't really matter does it? Any where you put it, it will execute only once and that's it for the processor.
  • HedbergHedberg Posts: 671
    a_riot42 wrote: »
    Except that button events don't get executed 200-300 times a second.
    Paul

    Neither does define_program if it has an infinite loop in it. The only way that define_program gets run 200-300/sec is if there's nothing going on elsewhere and if there's not much going on in define_program either.
  • Joe HebertJoe Hebert Posts: 2,159
    a_riot42 wrote: »
    Except that button events don't get executed 200-300 times a second.
    I guess I’m missing the point also.
    Getting smacked in the head with a wrecking ball is better than getting blasted in the face with a cannon ball?
    Either way, one hit and you’re more than dead.
  • viningvining Posts: 4,368
    a_riot42 wrote: »
    It must be Vinings code :)

    It shouldn't be that noticeable to the ordinary user. However, I have noticed quite a difference on larger systems with lots of code in define_program but never to the point where people would notice if they couldn't directly compare. As long you aren't sending strings to UIs or running for loops in define_program you should be ok.
    Paul
    To kind of bring this full circle it does take a lot more code to minimize the burden on the processor. To put FB in DEF_PROG is probably the easiest way to achieve FB and uses the least amount of code but places the largest burden on the processor regardless of loops and everyone agrees an infinite loop is just bad no matter where it is. Ideally though if we try an keep everything event driven then we need to remove FB from DEF_PROG and write code to update UIs when a UIs come online, come to page and when events trigger changes. To make thing even more efficient for the processor we then should add code to send FB only to UI devices that actually need them and then even more code to determine when modules should do nothing at all. If a device doesn't need constant polling we don't need timelines running to regulate queues for device strings or timelines for FB. If no UIs are on page it takes more code to stop all timelines and start them up again when they are.

    Long story short it takes more code to have the processor do less so more and less are both better in the right context if that makes any sense at all.
  • Jorde_VJorde_V Posts: 393
    vining wrote: »
    To kind of bring this full circle it does take a lot more code to minimize the burden on the processor. To put FB in DEF_PROG is probably the easiest way to achieve FB and uses the least amount of code but places the largest burden on the processor regardless of loops and everyone agrees an infinite loop is just bad no matter where it is. Ideally though if we try an keep everything event driven then we need to remove FB from DEF_PROG and write code to update UIs when a UIs come online, come to page and when events trigger changes. To make thing even more efficient for the processor we then should add code to send FB only to UI devices that actually need them and then even more code to determine when modules should do nothing at all. If a device doesn't need constant polling we don't need timelines running to regulate queues for device strings or timelines for FB. If no UIs are on page it takes more code to stop all timelines and start them up again when they are.

    Long story short it takes more code to have the processor do less so more and less are both better in the right context if that makes any sense at all.

    Yeah this is also what makes the programming complicated and fun to do :P. But do we ever get the time to make it as brilliant as we want it to be? :(

    On that note I wonder how you guys handle feedback? True return events from functions? Or through Strings you get back from devices? Of course it depends on the situation, but imo feedback through rs232 can be slow depending on the device and if it's too slow it looks as if the button wasn't triggered etc.

    I'd like to hear what you guys generally do.
  • a_riot42a_riot42 Posts: 1,624
    Nerieru wrote: »
    Yeah this is also what makes the programming complicated and fun to do :P. But do we ever get the time to make it as brilliant as we want it to be? :(

    On that note I wonder how you guys handle feedback? True return events from functions? Or through Strings you get back from devices? Of course it depends on the situation, but imo feedback through rs232 can be slow depending on the device and if it's too slow it looks as if the button wasn't triggered etc.

    I'd like to hear what you guys generally do.

    I have found trying to manage feedback in define_program far more difficult and bug prone than not. How do you do feedback in define_program for 20 TPs, 5 R4s, 5 keypads and a few iPads all with multi zone capabilities and 10-12 sources, with a few sink options and personalized user settings? Sounds like a nightmare to me. Since feedback generally consists of simply turning channels on or off or sending text why is having it somewhere other than define_program considered so difficult? Its the same commands just in a different place.
    Paul
  • Jorde_VJorde_V Posts: 393
    a_riot42 wrote: »
    I have found trying to manage feedback in define_program far more difficult and bug prone than not. How do you do feedback in define_program for 20 TPs, 5 R4s, 5 keypads and a few iPads all with multi zone capabilities and 10-12 sources, with a few sink options and personalized user settings? Sounds like a nightmare to me. Since feedback generally consists of simply turning channels on or off or sending text why is having it somewhere other than define_program considered so difficult? Its the same commands just in a different place.
    Paul

    Glad you responded, but that wasn't what I was saying/asking. I handle my feedback through functions or rs232 replies, I'm asking how you guys generally do it I'm not talking about how 'difficult' it is whether it's through define_program or not. As a relative newcomer I generally don't have a DP Section and my predecessor more often than not did it in DP (pun intended). That has made me curious as to how you guys do it.

    As you said the DP section gets out of hand on larger scale project. Sometimes straining the processor so much that the system is slow/unresponsive for periods of time and occasionally leading to lock-ups.

    ~Jorde
  • Nerieru wrote: »
    Yeah this is also what makes the programming complicated and fun to do :P. But do we ever get the time to make it as brilliant as we want it to be? :(

    On that note I wonder how you guys handle feedback? True return events from functions? Or through Strings you get back from devices? Of course it depends on the situation, but imo feedback through rs232 can be slow depending on the device and if it's too slow it looks as if the button wasn't triggered etc.

    I'd like to hear what you guys generally do.


    I use both, assuming I am correct in understanding "true return events from functions" to mean just setting the feedback in code without waiting for any response from the device.

    Most of the times where I set feedback directly, it's because my module will eventually get the device into the desired state, even if it doesn't want to execute the command right this second (because it's still warming up, or whatever).

    I used to do feedback in define_program, since that's how the instructor did it in the programmer classes I attended, but now all my feedback in new projects is event based (though some define_program stuff still lurks in my modules).
  • sonnysonny Posts: 208
    Nerieru wrote: »
    On that note I wonder how you guys handle feedback? True return events from functions? Or through Strings you get back from devices? Of course it depends on the situation, but imo feedback through rs232 can be slow depending on the device and if it's too slow it looks as if the button wasn't triggered etc.

    I typically always do feedback based on returns from the device...if you tell something to turn on, the fact that the target device processed the command should be the feedback. In a couple of instances I've done a flash or a multi-state when response is slow, otherwise some clients will just start pounding the button.

    As far as the more code, less overhead point...the last big project I did I used a lot of user defined types with metadata, and state machine-like processing to really trim down the number of lines of code required.
Sign In or Register to comment.