Macro causing performance issues

Need help running MacroQuest2? Ask your questions about how to get things to work on your computer.

Moderator: MacroQuest Developers

ikill
decaying skeleton
decaying skeleton
Posts: 7
Joined: Thu Aug 07, 2014 1:25 am

Macro causing performance issues

Post by ikill » Sat Sep 27, 2014 10:02 pm

I have a macro that I have been writing for years now. There have been numerous revisions and addition etc over the years, and the macro has grown to several thousand lines (I'd guess between 10-20k). Because of the size and number of functions of the macro, I have it broken into several includes, about 35 or so. I play on an emulated EQ server where boxing is the norm, and it's not uncommon to see someone running an army of 24+ characters. My issue is that for people running large numbers of bots, my newest version can have a significant performance issues. I've noticed the issue myself, at times, but after a restart things seem to clear up. However, I have had several people who use my macro tell me that it causes significant video lag when running on all characters. To be specific, a friend running a GTX 760ti went from 46fps logged in to 3fps when running my macro. I'm not a coder by trade, and everything I've written has been a matter of guess work, so I'm really not sure what could be making this version of the macro so resource heavy. My guesses include, too many includes, an overly complex main loop, or perhaps an overuse of a SUB that argues a given string for a specific variable. To run, my macro imports a list of functions from an ini, then uses a /for loop to execute each function in turn. The macro also depends on the argueString sub to return several variables during the main loop, and also I have several calls which call scripts that are located in several different includes.

As stated, I'm not a coder by trade, and I'm not really sure what impact any of these things would have, this is just my best guess as to what I could have done wrong. If anyone has anymore insight it would be greatly appreciated.

Thanks

Kill

dewey2461
Contributing Member
Contributing Member
Posts: 1759
Joined: Sun Apr 17, 2005 1:53 am

Re: Macro causing performance issues

Post by dewey2461 » Sun Sep 28, 2014 2:11 am

Too many triggers
Too many ${Ini[...]} statements
Too many lines in general.

Friend of mine had triggers for all the melee types like:

#event Hit "You got hit by ..." repeat for bash, kick, etc.

With 20-30 people + pets that's a serious amount of added work the parser is doing.

ikill
decaying skeleton
decaying skeleton
Posts: 7
Joined: Thu Aug 07, 2014 1:25 am

Re: Macro causing performance issues

Post by ikill » Mon Sep 29, 2014 10:27 pm

First off, thanks for the reply, Dewey. Had a couple follow up questions,

I've looked through the macro, checking for Ini statements, triggers, etc, but I'm not seeing much that would lead to such a drastic impact as what I believe I'm seeing. All my ${Ini[...]} statements are either called during startup, or by events that would be triggered by a user, for example "Check loot setting for X" would search the file for a given entry, but only on command. As far as triggers, most of the events in the macro are triggered by user commands, rather than game text like "You have been hit by" because of that, I don't think they would be causing the issue since they are only getting called rarely, if ever.

Would breaking the macro down into several includes rather than a few larger files have an impact? Is it better to have functions broken into small pieces and each piece being /called in turn, or is it more efficient to have everything in the same SUB? During the start of the macro, there is a list of functions imported from an ini, and then built into an array which is later parsed in the mainloop as a /for. Could having 2 /for loops, one with 10-15 lines the other with 15-20ish, be causing extra overhead that may not be necessary?

Not that I expect you to go digging through my macro, but if you wanted to get a better look at what I'm talking about, the macro can be found at, https://code.google.com/p/e3-macro-builds/. There is a link on the home page to my google drive where the macro can be downloaded.

Here's an example of my mainloop of the macro revision that's causing issues,

Code: Select all

 SUB Main(modeSelect)

/declare macroVersion string outer 5.1.36 (r8)
/declare i int local

/call e3_Setup "${modeSelect}"

:MainLoop
/if (${Debug}) /echo |- MainLoop ==>

	| If my class is not set, I must not be in game, end the macro.
	/if (!${Bool[${Me.Class}]}) {
		/endmacro
	} else {
|	************************************************************************************	|
|   ******************************* Background Functions *******************************	|
|	************************************************************************************	|
	
		/if (${ActionTaken}) /varset ActionTaken FALSE
		
		/if (${currentZone} != ${Zone.ID}) /call check_Zone
		/if (${Following} && !${Assisting}) /call check_Follow
		/call check_Active
		/call check_Combat
		/call check_Idle
		/call check_autoTribute
		
		| If I'm not holding an item, check Life Support and Instant Buffs.
		/if (!${Bool[${Cursor}]}) {
		
			| Check if I'm casting
			/if (!${Me.Casting.ID} || ${Me.Casting.ID} && ${Me.Class.ShortName.Equal[BRD]}) {
		
				| Check LifeSupport
				/if (${lifeSupport.Size} && ${Me.PctHPs} < 100) /call check_lifeSupport

				| Check Instant buffs
				/if (${BuffCheck} && ${InstantBuffs.Size} && ${Me.FreeBuffSlots} > ${MaxBuffs}) /call buffInstants
			}
		}
		
		/call Background_Events
		/doevents

		| If I'm not active, call mainFunctions
		/if (!${activeTimer}) {
		
			| check for a pending item exchange
			/if (${swapItemBack} && !${itemExchange_Timer}) /call completePendingExchange
			
|	******************************************************************************	|
|   ******************************* Main Functions *******************************	|
|	******************************************************************************	|
			
			/for i 1 to ${mainLoop_Array.Size}
				/if (${Bool[${mainLoop_Array[${i}]}]}) /call ${mainLoop_Array[${i}]}
			/if (!${ActionTaken}) /next i
	
|	**********************************************************************************	|
|   ******************************* Tertiary Functions *******************************	|
|	**********************************************************************************	|
			
			| MedBreak
			/if (${medBreak}) /call check_MedBreak
			
			| Maintain macro timers
			/if (${timerArray.Size}) /call check_macroTimers
		}		
	}

/if (${Debug}) {
	/echo <== MainLoop -|
	/delay 5
}
/goto :MainLoop	
/RETURN 
Here is an example of the list of functions called by the main loop,
[CLR Functions]
CLR Function#1=check_DivineArb
CLR Function#2=check_Yaulp
CLR Function#3=check_celestialRegen
CLR Function#4=check_healChain
CLR Function#5=check_Heals
CLR Function#6=check_CombatBuffs
CLR Function#7=check_Debuffs
CLR Function#8=check_Nukes
CLR Function#9=check_Buffs

And the second /for loop would use an array similar to this,

Include#1=background
Include#2=basics
Include#3=casting
Include#4=begForBuffs
Include#5=buffCheck
Include#6=buy
Include#7=pet
Include#8=heal
Include#9=healChain
Include#10=assist
Include#11=class
Include#12=corpseSummon
Include#13=loot
Include#14=sell
Include#15=smoothMoves
Include#16=Wait4Rez

And finally, here is a rebuild of the main loop which I tried to condense into one file to test performance impact. This is still a work in progress.

Code: Select all

SUB Main(modeSelect)
/declare macroVersion string outer 5.2.35 (r8)
/echo Initializing...
|
| Declare file paths ====================================================================================================== 
|
/declare botIni_Folder string outer e3 Bot Inis\
/declare altBotIni_Folder string outer e3 Bot Inis\Alternate Bot Inis\
/declare macroIni_Folder string outer e3 Macro Inis\
/declare MacroData_Ini string outer ${macroIni_Folder}Macro Data.ini
/declare genSettings_Ini string outer ${macroIni_Folder}General Settings.ini
/declare advSettings_Ini string outer ${macroIni_Folder}Advanced Settings.ini
/declare Character_Ini string outer ${botIni_Folder}${MacroQuest.Server}-${Me.CleanName}.ini
|
| Check Debug ============================================================================================================= 
|
/declare Debug bool outer ${Ini[${advSettings_Ini},Debug,Debug All]}
/declare Debug_Core bool outer ${Ini[${advSettings_Ini},Debug,Debug Core]} 
/declare Debug_Setup bool outer ${Ini[${advSettings_Ini},Debug,Debug Setup]} 
/declare Debug_Utilities bool outer ${Ini[${advSettings_Ini},Debug,Debug Utilities]}
|
| Check for Debug calls at startup
|
/if (${modeSelect.Find[/Debug|]} || ${modeSelect.Find[/Debug All|]}) {
	/varset Debug TRUE
} else /if (${modeSelect.Find[/Debug Core|]}) {
	/varset Debug_Core TRUE
} else /if (${modeSelect.Find[/Debug Setup|]}) {
	/varset Debug_Setup TRUE
} else /if (${modeSelect.Find[/Debug Utilities|]}) {
	/varset Debug_Utilities TRUE
}
|
/if (${Debug} || ${Debug_Setup}) /echo |- e3_Setup ==>
	| Check Plugins 
	/if (!${pluginsVerified-${Me.CleanName}} || !${EQBC.Connected}) /call check_Plugins
| Create or Update Ini files ============================================================================================== 
	|
	| Check for first time setup.
	/if (!${Ini[${MacroData_Ini}].Length}) {
		/echo Welcome to e3! Preforming first time setup...
	} else /if (!${Ini[${MacroData_Ini},e3 Build,Version].Equal[${macroVersion}]}) {
		/echo New version of e3 detected. Hold on to your nuggets!
	}
	| Macro Setting Inis 
	/if (!${Ini[${MacroData_Ini},e3 Build,Version].Equal[${macroVersion}]} || !${Bool[${Ini[${genSettings_Ini}]}]}) /call EVENT_make_MacroSettingsIni
	|  Character_Ini 
	/if (!${Ini[${MacroData_Ini},${MacroQuest.Server}-${Me.CleanName},Bot_Ini version].Equal[${macroVersion}]} || !${Bool[${Ini[${Character_Ini}]}]}) /call EVENT_make_CharacterSettingsIni
	| Aliases
	/if (!${Ini[${MacroData_Ini},e3 Build,Version].Equal[${macroVersion}]}) /call EVENT_updateAliases
	| Update Macro Version if a new build is detected
	/if (!${Ini[${MacroData_Ini},e3 Build,Version].Equal[${macroVersion}]}) /call WriteToIni "${MacroData_Ini},e3 Build,Version" "${macroVersion}" 1
	|
| Declare Core Variables and Import Settings ============================================================================== 
	/declare ActionTaken bool outer FALSE
	/declare ChatToggle string outer ${If[${Ini[${genSettings_Ini},General,Macro Output Channel].Length},${Ini[${genSettings_Ini},General,Macro Output Channel]},/bc]}
	/declare currentZone int outer 0
	/declare Old_cursorID int outer 0
	|
	/declare activeTimer timer outer
	/declare combatTimer timer outer
	/declare cursorTimer timer outer
	/declare rebuffTimer timer outer
	/declare spamTimer timer outer
	|
	/declare combatDelay int outer ${If[${Ini[${genSettings_Ini},General,Out of Combat Timer (Sec)].Length},${Ini[${genSettings_Ini},General,Out of Combat Timer (Sec)]},10]}
	/declare inventoryTimer int outer ${If[${Ini[${genSettings_Ini},General,Auto-Inventory Timer (Sec)].Length},${Ini[${genSettings_Ini},General,Auto-Inventory Timer (Sec)]},30]}
	/declare rebuffDelay int outer ${If[${Ini[${genSettings_Ini},General,Rebuff Delay Timer (Sec)].Length},${Ini[${genSettings_Ini},General,Rebuff Delay Timer (Sec)]},10]}
	|
	/if (!${Defined[idle]}) /declare idle bool global
	/if (!${Defined[idleTimer]}) /declare idleTimer timer global
	/declare idleInterval int outer ${If[${Ini[${genSettings_Ini},General,Idle Time Out (Min)].Length},${Ini[${genSettings_Ini},General,Idle Time Out (Min)]},10]}
	|
| Setup Includes 
|**
															
															
	add code to run include setups														
															
															
**|
| Complete a pending exchange ============================================================================================= 
	/if (${Ini[${MacroData_Ini},${MacroQuest.Server}-${Me.CleanName},Pending Exchange].Length} && ${Ini[${MacroData_Ini},${MacroQuest.Server}-${Me.CleanName},Pending Exchange].NotEqual[NONE]} && !${itemExchange_Timer}) /call completePendingExchange
| Startup echos =========================================================================================================== 
/echo e3 v${macroVersion} loaded.
/echo
/echo ** For updates, issues, suggestions, or donations, visit 'http://code.google.com/p/e3-macro-builds/'.
/echo ** For help using e3, use /e3help to learn about different basic functions and /comannds.
/if (${NetBots.Client.Find[Tackleberry]}) /echo Though you may find this message a bit 'extreme' so is bitching about a few lines of text which can easily be ignored.
/echo
/if (${Debug} || ${Debug_Setup}) {
	/echo botIni_Folder=${botIni_Folder} 
	/echo altBotIni_Folder=${altBotIni_Folder}
	/echo macroIni_Folder=${macroIni_Folder}
	/echo MacroData_Ini=${MacroData_Ini}
	/echo genSettings_Ini=${genSettings_Ini}
	/echo advSettings_Ini=${advSettings_Ini}
	/echo Character_Ini=${Character_Ini}
	/echo Debug=${Debug}
	/echo Debug_Core=${Debug_Core}
	/echo Debug_Setup=${Debug_Setup}
	/echo Debug_Utilities=${Debug_Utilities}
	/echo ChatToggle=${ChatToggle}
	/echo combatDelay=${combatDelay}
	/echo rebuffDelay=${rebuffDelay}
	/echo inventoryTimer=${inventoryTimer}
	/echo idleInterval=${idleInterval}
	/echo
	/echo *** Debug_Mode ON ***
	/echo The macro has paused so you can review setup information, type /mqpause to continue.
	/echo
	/mqpause
}
/if (${Debug} || ${Debug_Setup}) /echo <== e3_Setup -|
|**
 :MainLoop
**|
:MainLoop
/if (${Debug} || ${Debug_Core}) /echo |- MainLoop ==>
	| If my class is not set. I must not be in game, end the macro.
	/if (${ActionTaken}) /varset ActionTaken FALSE
	/if (!${Bool[${Me.Class}]}) {
		/endmacro
	} else {
| Check Background functions =================================================================================
		| Update zone ID
		/if (${currentZone} != ${Zone.ID}) /call check_Zone
		| Check Follow
		/if (${Following} && !${Assisting}) /call check_Follow
		| Check Zoning
		/if (!${SpawnCount[pc ${Me}]}) {
			/varset activeTimer 15
			/varset rebuffTimer 0
		}
		| Check Movement
		/if (${Me.Moving} || ${Corpse.Open}) {
			/varset activeTimer 5
			/varset rebuffTimer ${rebuffDelay}
		}
		| Check Cursor
		/if (${Cursor.ID}) {
			| Destroy badItems.
			/if (${Defined[badItems]}) {
				/if (${Select[${Cursor},${badItems}]} || ${Select[${Cursor.ID},${badItems}]}) {
					/echo Destroying ${Cursor}...
					/destroy
				}
			}
			| Check to see if I'm waiting to drop this item, or if I've picked up something new
			/if (${Old_cursorID} != ${Cursor.ID}) {
				/varset cursorTimer ${Math.Calc[${inventoryTimer} * 10].Int}
				/varset Old_cursorID ${Cursor.ID}
			} else {
				/if (!${cursorTimer}) /call clearCursor
			}
			/varset activeTimer 5
			/if (${rebuffTimer} < 30) /varset rebuffTimer 30
		} else {
			/if (${Old_cursorID}) {
				/varset cursorTimer 0
				/varset Old_cursorID 0
			}
		}
		| Check AutoAttack
		/if (${Me.Combat}) {
			/if (!${Target.ID} || ${Target.Type.Equal[corpse]} && !${Assisting}|| ${Spawn[${Target.ID}].Type.Equal[PC]} && !${Toggle-PvP}) /attack off
		}
		| Check Casting
		/if (${Me.Class.ShortName.NotEqual[BRD]} && ${Me.Casting.ID}) {
			/if (${e3Casting}) /call e3_CastingChecks
			/varset activeTimer 5
			/varset rebuffTimer ${rebuffDelay}
		}
		| Check windows
		/if (${Window[BigBankWnd].Open} || ${Window[MerchantWnd].Open} || ${Window[TradeWnd].Open} || ${Window[GuildBankWnd].Open} || ${Window[MerchantWnd].Open}) {
			/varset activeTimer 30
			/varset rebuffTimer ${rebuffDelay}
			/doevents flush
		}	
		| Check Feigning
		/if (${Me.Feigning}) {
			/if (!${Select[${Me.Class.ShortName},NEC,SHD,MNK]}) {
				/stand
				/if (${Assisting} && ${StickOn}) /attack on
			} else {
				/if (!${Defined[feign_Timer]}) {
					/docommand ${ChatToggle} I AM FEIGNED.
					/declare feign_Timer timer outer 15s
				}
			}
			/varset activeTimer 30
			/varset rebuffTimer ${rebuffDelay}			
		} else {
			/if (${Defined[feign_Timer]}) /deletevar feign_Timer
		}
		| Check Combat
		/call check_Combat
		| Check to see if I have been active recently.  If so, set Idle false, and update the idleTimer	
		/if (${activeTimer} || ${combatTimer}) {
			/varset idleTimer ${idleInterval}m
			/if (${idle}) /varset idle FALSE
		} else {
			| If I haven't been active, and the idleTimer is spent, set idle TRUE.
			/if (!${idle} && !${idleTimer}) /varset idle TRUE
		}
		| If I'm not holding an item, check Life Support and Instant Buffs.
		/if (!${Bool[${Cursor}]}) {
			| Check if I'm casting
			/if (!${Me.Casting.ID} || ${Me.Casting.ID} && ${Me.Class.ShortName.Equal[BRD]}) {
				| Check LifeSupport
				/if (${lifeSupport.Size} && ${Me.PctHPs} < 100) /call check_lifeSupport
				| Check Instant buffs
				/if (${BuffCheck} && ${InstantBuffs.Size} && ${Me.FreeBuffSlots} > ${MaxBuffs}) /call buffInstants
			}
		}
		/if (${autoTribute}) /call check_autoTribute
		/call Background_Events
		/doevents
		| If I'm not active, check mainLoop_Array functions
		/if (!${activeTimer}) {
			| check for a pending item exchange
			/if (${swapItemBack} && !${itemExchange_Timer}) /call completePendingExchange
|	******************************************************************************	|
|   ******************************* Main Functions *******************************	|
|	******************************************************************************	|
		|**
		
		This may need to be redesigned,
		
		/for i 1 to ${mainLoop_Array.Size}
			/if (${Bool[${mainLoop_Array[${i}]}]}) /call ${mainLoop_Array[${i}]}
		/if (!${ActionTaken}) /next i
		**|											
|	**********************************************************************************	|
|   ******************************* Tertiary Functions *******************************	|
|	**********************************************************************************	|
			| MedBreak
			/if (${medBreak}) /call check_MedBreak
			| Maintain macro timers
			/if (${timerArray.Size}) /call check_macroTimers		
		}
	}
/if (${Debug} || ${Debug_Core}) {
	/echo <== MainLoop -|
	/delay 5
}
/goto :MainLoop
/RETURN
Again, any insight offered is greatly appreciated.

Thank you for the time, effort, and information.

-Kill

demonstar55
a snow griffon
a snow griffon
Posts: 314
Joined: Fri Nov 28, 2008 6:31 am

Re: Macro causing performance issues

Post by demonstar55 » Mon Sep 29, 2014 11:17 pm

by triggers I believe he means #events, you have like 567 of them.

ikill
decaying skeleton
decaying skeleton
Posts: 7
Joined: Thu Aug 07, 2014 1:25 am

Re: Macro causing performance issues

Post by ikill » Tue Sep 30, 2014 12:47 am

I do have several events, but the vast majority are triggered by the user, rather than the game. Only things I can think of that the game would trigger would be loot, death, zone, enrage, and a few various NPC or raid triggers. I could see them possibly causing slight spikes of lag, but this is more of a persistent issue, rather than intermittent or caused by an event. Even stranger to me, is that v4.x was larger over all, and had even more events. v5 is more complex, and I think that's the issue, but I'm just not sure which changes caused such a drop in performance.

dewey2461
Contributing Member
Contributing Member
Posts: 1759
Joined: Sun Apr 17, 2005 1:53 am

Re: Macro causing performance issues

Post by dewey2461 » Tue Sep 30, 2014 6:10 pm

If you can replicate the problem, then you should be able to do some basic profiling to determine the problem area.

You can use ${EverQuest.Running} to capture a millisecond time hack and then do something like


/declare StartTime int outer ${EverQuest.Running}
| -- do something
/declare EndTime int outer ${EverQuest.Running}
/declare T int outer
/varcalc T ${EndTime}-${StartTime}
/echo It took ${T} milliseconds to perform the operation !

Now sprinkle your code with this kind of stuff and see what happens. Remove some of the events.

If you truly have like 500 events it wouldn't surprise me things slow to a crawl. Especially in combat, during a raid, you get 100's of lines of text each one of which gets checked against EVERY event description.

good luck !

demonstar55
a snow griffon
a snow griffon
Posts: 314
Joined: Fri Nov 28, 2008 6:31 am

Re: Macro causing performance issues

Post by demonstar55 » Tue Sep 30, 2014 6:23 pm

Code: Select all

grep -ir "\#event" | wc -l
567
567 events, most of which should be handled through chat events. (raid has to be routed to chat event)

User avatar
warlock45
a grimling bloodguard
a grimling bloodguard
Posts: 881
Joined: Sat Oct 06, 2007 8:32 pm

Re: Macro causing performance issues

Post by warlock45 » Tue Sep 30, 2014 10:32 pm

for those of us who don't know... what if the performance difference between an event, and a chat event?

ikill
decaying skeleton
decaying skeleton
Posts: 7
Joined: Thu Aug 07, 2014 1:25 am

Re: Macro causing performance issues

Post by ikill » Wed Oct 01, 2014 9:09 pm

The macro has a few dozen events, most of which are macro commands set up through /bc, not triggered by the game. Since /bc is not a chat channel event Chat doesn't pick them up, and is why I have so many events. Demonstar is mostly just talking out of his butt =P

demonstar55
a snow griffon
a snow griffon
Posts: 314
Joined: Fri Nov 28, 2008 6:31 am

Re: Macro causing performance issues

Post by demonstar55 » Fri Oct 03, 2014 1:09 pm

ikill wrote:The macro has a few dozen events, most of which are macro commands set up through /bc, not triggered by the game. Since /bc is not a chat channel event Chat doesn't pick them up, and is why I have so many events. Demonstar is mostly just talking out of his butt =P
Killians. I'm not. EVERY line of text on the client is being checked against 567 events. EVERY LINE OF TEXT.

Code: Select all

#Event IRC            "<#1#> #2#"
#Event IRC            "[#1#(msg)] #2#"

Sub Event_IRC(IRCSay,IRCSender,IRCCommand)
/call Event_Chat "irc" "${IRCSender}" "${IRCCommand}"
/return
(This will work for MQ2IRC and MQ2EQBC)

and do the same for raid.

User avatar
warlock45
a grimling bloodguard
a grimling bloodguard
Posts: 881
Joined: Sat Oct 06, 2007 8:32 pm

Re: Macro causing performance issues

Post by warlock45 » Fri Oct 03, 2014 5:12 pm

Honestly just trying to work out the reasoning here. On the surface it would seem the same amount of work for the macro/pc no matter where the even ended up. So at a guess, moving the command related events to a chat event will reduce the amount of checking I am assuming? (only triggered when something is sent in chat)

demonstar55
a snow griffon
a snow griffon
Posts: 314
Joined: Fri Nov 28, 2008 6:31 am

Re: Macro causing performance issues

Post by demonstar55 » Fri Oct 03, 2014 6:03 pm

warlock45 wrote:Honestly just trying to work out the reasoning here. On the surface it would seem the same amount of work for the macro/pc no matter where the even ended up. So at a guess, moving the command related events to a chat event will reduce the amount of checking I am assuming? (only triggered when something is sent in chat)
If a line of text matches #chat say, that line will be passed to the Sub Event_Chat. Then you do your processing there. If it doesn't match the chat line it then gets checked against every other #event you defined. You define your group messages as #events, that means every time you get say a spell worn off message, that gets checked against all your #event group stuff. At the end of the day, we still need to do text processing in Event_Chat, but there is no reason your buff fade message needs to be checked against 10s of group messages that should of been pushed to Event_Chat.

dewey2461
Contributing Member
Contributing Member
Posts: 1759
Joined: Sun Apr 17, 2005 1:53 am

Re: Macro causing performance issues

Post by dewey2461 » Fri Oct 03, 2014 10:40 pm

Have you identified that events are the cause of the problem? I was just throwing out that it might be one part of the problem.

An easy check would be to run a set of characters full text like you want to parse. Run another with minimal spam and see how much of a difference there is.

It could be something else entirely.

ikill
decaying skeleton
decaying skeleton
Posts: 7
Joined: Thu Aug 07, 2014 1:25 am

Re: Macro causing performance issues

Post by ikill » Sun Oct 12, 2014 11:33 am

I haven't had a chance to do a lot of testing, but I have been using the idea of capturing "time hacks", as dewey put it, to check iteration speed of the macro when running different configurations. I only had a few minutes to play around with things, but I'll try to collect some actual data to post a little later this week. I've stripped the macro down to bare functionality and rebuilt a more condensed version to try and test the difference in speed.

Few questions,

Is there any difference between having several small .inc vs having a few large .incs?

Is there any difference between having several subs vs one larger more complex sub?

For example,

Code: Select all

SUB check_Active
/if (${Debug} || ${Debug_Background}) /echo |- check_Active ==>

	/if (!${SpawnCount[pc ${Me}]}) /call check_Zoning
	/if (${Me.Moving} || ${Corpse.Open}) /call check_Movement
	/if (${Me.Combat}) /call check_AutoAttack
	/if (${Me.Class.ShortName.NotEqual[BRD]} && ${Me.Casting.ID}) /call check_Casting
	/if (${Window[BigBankWnd].Open} || ${Window[MerchantWnd].Open} || ${Window[TradeWnd].Open} || ${Window[GuildBankWnd].Open} || ${Window[MerchantWnd].Open}) /call check_MerchantWnd

	
/if (${Debug} || ${Debug_Background}) /echo <== check_Active -|
/RETURN
SUB check_Zoning

	/varset activeTimer 15
	/varset rebuffTimer 0

/RETURN
SUB check_Movement

	/varset activeTimer 5
	/varset rebuffTimer ${rebuffDelay}

/RETURN
SUB check_AutoAttack

	/if (!${Target.ID} || ${Target.Type.Equal[corpse]} && !${Assisting}|| ${Spawn[${Target.ID}].Type.Equal[PC]} && !${Toggle-PvP}) /attack off

/RETURN	
SUB check_Casting

	/call e3_CastingChecks
	/varset activeTimer 5
	/varset rebuffTimer ${rebuffDelay}

/RETURN	
SUB check_MerchantWnd

	/varset activeTimer 30
	/varset rebuffTimer ${rebuffDelay}
	/doevents flush

/RETURN
vs

Code: Select all

SUB check_Active
/if (${Debug} || ${Debug_Background}) /echo |- check_Active ==>
	| Check Zoning
	/if (!${SpawnCount[pc ${Me}]}) {
		/varset activeTimer 15
		/varset rebuffTimer 0
	}
	| Check Movement
	/if (${Me.Moving} || ${Corpse.Open}) {
		/varset activeTimer 5
		/varset rebuffTimer ${rebuffDelay}
	}
	| Check AutoAttack
	/if (${Me.Combat}) {
		/if (!${Target.ID} || ${Target.Type.Equal[corpse]} && !${Assisting}|| ${Spawn[${Target.ID}].Type.Equal[PC]} && !${Toggle-PvP}) /attack off
	}
	| Check Casting
	/if (${Me.Class.ShortName.NotEqual[BRD]} && ${Me.Casting.ID}) {
		/if (${e3Casting}) /call e3_CastingChecks
		/varset activeTimer 5
		/varset rebuffTimer ${rebuffDelay}
	}
	| Check windows
	/if (${Window[BigBankWnd].Open} || ${Window[MerchantWnd].Open} || ${Window[TradeWnd].Open} || ${Window[GuildBankWnd].Open} || ${Window[MerchantWnd].Open}) {
		/varset activeTimer 30
		/varset rebuffTimer ${rebuffDelay}
		/doevents flush
	}
/if (${Debug} || ${Debug_Background}) /echo <== check_Active -|	
/RETURN
Thanks

Kill

dewey2461
Contributing Member
Contributing Member
Posts: 1759
Joined: Sun Apr 17, 2005 1:53 am

Re: Macro causing performance issues

Post by dewey2461 » Sun Oct 12, 2014 8:03 pm

There is a slight difference but I don't think it would cause the issue you explained.

A macro will execute 40 or 80 lines of code per frame EQ draws.

The more lines it evaluates the slower your macro responds.

If you have a /call DoSomething and it only executes a couple lines of code you might get a very slight advantage in speed at the cost of readability.

The best answer is to time it and see. I doubt that is going to be the issue.