ScriptUO
Official ScriptUO EasyUO Scripts => Scripting Chat => Topic started by: Cerveza on January 21, 2011, 06:15:23 AM
-
Just wondering if there's any increase in speed doing one of these methods over the other....
Case 1 - checking for conditions in the mainloop and subbing if conditions are met.
- doesn't need to jump to the sub routine each loop
repeat
if %condition = #true
gosub Do_Something_Sub
until #false
Case 2 - going to the sub and checking the condition.
- jumps into the sub each loop
repeat
gosub Do_Something_Sub
until #false
sub Do_Something_Sub
if %condition = #false
return
the rest of the sub here
The only difference is that in Case 2 you have to jump to the sub routine where in Case 1 you wouldn't need to.
Any real difference when you start putting together LOTS of subs?
-
I have two versions of my Bard/Heal bot that I'm going to test tonight...
Version A (gosub) main loop:
repeat
set %timer1 #sCnt2
gosub discord
gosub cast_heal
gosub follow
gosub check_res
set %timer2 ( #sCnt2 - %timer1 )
event sysmessage The "gosub" version: %timer2
until #false
Version B (condition checking) main loop:
repeat
set %timer1 #sCnt2
if #enemyID <> N/A && #enemyID notin %iList . %listName && %disco_wait < #sCnt
gosub discord
if #hits < ( #maxhits - %healpoint )
gosub cast_heal
finditem !support G_15
if #finddist > %buffer
gosub follow
if #clixres <> 1200
gosub check_res
set %timer2 ( #sCnt2 - %timer1 )
event sysmessage The "if" version: %timer2
until #false
-
Is discord built into enemyIDcheck in the first version?
-
Yes, I forgot to change the gosub, thanks for pointing it out.... I removed the enemyIDcheck sub completely and just put it into the disco...
-
Cerv, the old saying the simplest answer is usually the right one holds true for code execution. :) I constantly think in my head, "What would make this the fastest possible?" And it's always using if's in the right place, only subbing when absolutely necessary... optimizing hard waits so they only do the wait when absolutely necessary... I've really noticed the only thing that slows a script down is waits really. If you can find creative ways to get past waits, like setting timers instead... you'll see large speed benefits. In the new dexer, I loop through TONS of code REALLY fast, and do most everything based on timers so it never stops looping until it absolutely has to. Instead of doing waits, I set a timer, and say, if #timer > #systime, then the wait is still in effect don't sub. A lot of times in my scripts, I have 20 possible things that could happen at any second, but usually you only needs 2 of those, and a lot of times only one requires a wait after it, so there's no real need to actually DO the wait and slow the script down. Does that make sense? :)
-
Absolutely... why put a "wait 40" at the end of a line when you could setup a timer instead?
Makes sense to me.
I've always been curious which way runs faster in my example, the "gosub and check it there" or the "check it and gosub if necessary" methods.
I'm going to test each tonight and hopefully, see a little timing difference between the two.
-
Preliminary testing with following only shows the "if's" ahead of the "gosubs"
While dragging around my bard, I was getting between 4 and 9 using the gosubs.
Same situation with the if condition statements was netting 4-6 per loop.
I'll test again later tonight and note it when actually barding/healing etc... to get an overall feel for which way works faster. Right now it's the condition statement in the loop (if) ahead. Just a little better feel about the times with it as well.
-
Preliminary testing with following only shows the "if's" ahead of the "gosubs"
While dragging around my bard, I was getting between 4 and 9 using the gosubs.
Same situation with the if condition statements was netting 4-6 per loop.
I'll test again later tonight and note it when actually barding/healing etc... to get an overall feel for which way works faster. Right now it's the condition statement in the loop (if) ahead. Just a little better feel about the times with it as well.
Cause it's only executing one line of code instead of however many it takes to sub, then check the if then return. Makes sense it will be a bit faster. Over the course of 10k iterations that's a lot of time. That's why I constantly am looking for little ways to squeeze milliseconds out of things. :) Timers are seriously great for this purpose too. I use timers for everything, but it gets confusing keeping them all straight if you're not carefull. And they can be a pain to debug when you have literally hundreds of them doing different things.
-
Yep, this is the result I was expecting. I'll run each one during some full tests with barding and healing and get a feel for which is producing the better numbers.
I'm fairly certain it'll be the "if" script.
-
Yep, this is the result I was expecting. I'll run each one during some full tests with barding and healing and get a feel for which is producing the better numbers.
I'm fairly certain it'll be the "if" script.
It should be the if script, but the if can make for cluttered code eg
if x=y gosub z
if a=b gobub x
is defainlty more cluttered than
gosub checkz
gosub checkx
Therefor I personally take the 2nd approach but compensate by increasing the LPC to get the same/better performance.
-
Hmmmmm.... Interesting Findings there cerveza, implementing this into the army would definitely increase speed,
-
It kinda made sense to me before I was testing it.
I *know* the guys at easyuo will say that scripts run so fast you won't notice any difference, but the fact is that you DO notice a difference.
By having to "skp" down to the sub routine and then do a check - then "skip" back to the main loop it takes more time then just checking in the loop.
I don't really like the clutter it creates in the mainloop, and sometimes I would really rather have a "return", I have started using the method of checking for conditions in the mainloop and only subbing if the requirements are met.
And I know from my little test that the *feel* of the script was smoother with the checks in the loop (the *if* method). When I was running the two versions the gosub one just seemed a little clunkier for some reason and the *if* one seemed a little smoother. That includes the movement and the actual actions (healing and barding).
*Does this mean an army update? ;D
-
Another thing to consider in the same vein .. is the overall location of code in the script. Considering the script reads from top down its prudent to place the most often used code closer to the top and the least used code near the end. But really I wouldn't bother except on the most critical of high speed scripts.
-
Wasn't it TM who said script execution actually increases near the end of a script? I have never tested it tho. Organizing your code by execution order does make a difference in speed critial situations but for general use it's not such a huge deal. Something to think about is seperating speed critical from non speed critical code also. Like scanning for buff bar icons, you probly only need to do that every half second to a second, so that could be put on a timer. But checking for health needs to be instantaneous, so you keep that in the main loop on a tight leash. Also, minimizing your use of waits is huge. If your script needs to heal, but isn't doing anything AFTER that heal for 2 seconds, there's no need to put a wait there... Soft waits... :) You put the wait inside the top of the script, and check the soft wait timer so you only have to wait the leftover amount of time from the wait. This allows you to do things based on variable timers also. So one thing requires a wait 20, but something else requires only a wait 5, if it's a variable timer, the flow of the script is nearly perfect. Example:
Note: Doing it this way will also allow you to skip things based on that same time if you'd like too. So say if you wanted to cast a heal above all else, in your sub whatever, you'd have if %softWait > #sysTime && #hits < #maxhits - 20 then return... so it would skip the whatever sub because your health was low, and go on to the next sub which would be heal, and would have nothing there to make it skip the heal. So you can work script flow with tons of set conditions too, that work with your timers.
sub whatever
if %sofWait > #sysTime
return
set #lobjectid #findid
event macro 17
set %softWait #sysTime + 2000
return
sub nextsub
if %hits < #maxhits - 20
{
REPEAT
UNTIL %SOFTWAIT < #SYSTIME
DO HEAL HERE
SET %SOFTWAIT #SYSTIME + 2000
}
return
-
Good stuff!
-
Wasn't it TM who said script execution actually increases near the end of a script?
Yup, that was me. You don't really notice it until your script grows large enough. That's why I have the CLAw formatted so that the main loops appear at the end of the script. I forget the exact comparison, but I think I could get 30% more speed out of it.