Thread Tools Display Modes
06-30-20, 03:24 AM   #1
LudiusMaximus
A Rage Talon Dragon Guard
 
LudiusMaximus's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2018
Posts: 320
Registering for all events / asynchronous code execution

I need kind of an event log for one of my addons.
Is there a concise way to register a frame for all possible events?
__________________
~ Be the change you want to see in the world... of warcraft interface! ~

Last edited by LudiusMaximus : 07-01-20 at 12:52 AM. Reason: I hijacked my own thread, so I extent its title.
  Reply With Quote
06-30-20, 03:27 AM   #2
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,857
RegisterAllEvents
/etrace might also be useful.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 06-30-20 at 03:33 AM.
  Reply With Quote
06-30-20, 03:32 AM   #3
LudiusMaximus
A Rage Talon Dragon Guard
 
LudiusMaximus's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2018
Posts: 320
Thanks for the instant and very concise reply!
I guess I could have googled this myself...

Regarding the remark: "It is not advisable to use this for anything except debugging purposes, as the incurred performance penalty is quite large." Do you think this is still an issue with today's computers? I have never noticed that having /eventtrace open would give me any performance penalties.
__________________
~ Be the change you want to see in the world... of warcraft interface! ~
  Reply With Quote
06-30-20, 03:40 AM   #4
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,857
It depends on how much "extra" processing you might add to the event call(s).

On it's own it's probably not an overly great burden.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
06-30-20, 03:44 AM   #5
LudiusMaximus
A Rage Talon Dragon Guard
 
LudiusMaximus's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2018
Posts: 320
All right, I will give it a try.

I just want to continuously log the events of the most recent second or so, such that under certain circumstances I can see what has just happened.

Thanks again!
__________________
~ Be the change you want to see in the world... of warcraft interface! ~
  Reply With Quote
06-30-20, 05:27 AM   #6
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,308
It'll keep calling your OnEvent handler for literally everything. Especially in combat, this happens a lot. Calling a Lua function is the most taxing operation you can do. The best you can do is to make sure the game spends the least time possible in Lua code. Even if it's just an empty function.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
06-30-20, 05:40 AM   #7
LudiusMaximus
A Rage Talon Dragon Guard
 
LudiusMaximus's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2018
Posts: 320
Originally Posted by SDPhantom View Post
Calling a Lua function is the most taxing operation you can do. The best you can do is to make sure the game spends the least time possible in Lua code. Even if it's just an empty function.
That's interesting. Are you saying that calling a function is significantly more taxing than it would be to execute the function's code "inline"? When I code I try to use functions wherever I can to avoid writing the same code more than once. Does this make my code less efficient as more functions are called?

Another thing I was wondering: Is it more efficient to have one frame listening to several events and decide what to do depending on the event within the one OnEvent function. Or to have several frames each listening to only one event? Or does this make no difference?
__________________
~ Be the change you want to see in the world... of warcraft interface! ~
  Reply With Quote
06-30-20, 06:21 AM   #8
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,308
Originally Posted by LudiusMaximus View Post
That's interesting. Are you saying that calling a function is significantly more taxing than it would be to execute the function's code "inline"?
All Lua operations are relatively quick, but compared to C code and being called literally thousands of times, this adds up. Also this is comparing simple operations like creating a table, assigning a variable, indexing, etc. A single line of code often has many of these operations in it.



Originally Posted by LudiusMaximus View Post
When I code I try to use functions wherever I can to avoid writing the same code more than once. Does this make my code less efficient as more functions are called?
It's a balancing act between speed, readability, and maintainability. You shouldn't have separate functions for code that's only being run for one place or be calling a function that you know does nothing in a situation you can avoid.

The overall goal is to have code that's easy to read and maintain, but not be too wasteful of CPU time if you can help it.



Originally Posted by LudiusMaximus View Post
Another thing I was wondering: Is it more efficient to have one frame listening to several events and decide what to do depending on the event within the one OnEvent function. Or to have several frames each listening to only one event? Or does this make no difference?
This is another balancing act. It's weighing between having many frames call one function independently or having one frame loop through a list of others, calling an iterator in a for loop to retrieve each one. Comparing the two, I would say it makes no difference.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 06-30-20 at 07:00 AM.
  Reply With Quote
06-30-20, 07:03 AM   #9
LudiusMaximus
A Rage Talon Dragon Guard
 
LudiusMaximus's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2018
Posts: 320
Thanks for the advice.

One more thing I have been thinking about. Do you think there will ever by a major update that will allow something like "asynchronous" execution of lua code?

At the moment it seems that the framerate is determined by whoever is slower: the GPU rendering the game world or the CPU executing any pending UI code. Normally, the UI does not take that much time. But actions like e.g. opening the "Appearances" frame brings with it a massive momentary FPS drop. The same is true to a lesser degree for just openning your bagpack (also without any addons). And even picking up an item while your backpack is open leads to 1-2 frames with a lower rate than the GPU would be able to render.

How fundamentally different would it be if the GPU does its thing rendering the game world as fast as possible and the lua code does its thing taking as long as it needs without throttling the FPS...?
__________________
~ Be the change you want to see in the world... of warcraft interface! ~
  Reply With Quote
06-30-20, 10:50 AM   #10
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,308
Lua is a single-threaded scripting engine, so async threads are impossible. You can fake it though by spreading your workload using coroutines or other fancy coding. You end up passing execution around like a hot potato instead of it truly being asynchronous.

It may be possible for Blizzard to separate the render and Lua into their own threads, but that's entirely up to them.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 06-30-20 at 11:11 AM.
  Reply With Quote
06-30-20, 09:50 PM   #11
kurapica.igas
A Chromatic Dragonspawn
Join Date: Aug 2011
Posts: 152
Originally Posted by LudiusMaximus View Post
Thanks for the advice.

One more thing I have been thinking about. Do you think there will ever by a major update that will allow something like "asynchronous" execution of lua code?

At the moment it seems that the framerate is determined by whoever is slower: the GPU rendering the game world or the CPU executing any pending UI code. Normally, the UI does not take that much time. But actions like e.g. opening the "Appearances" frame brings with it a massive momentary FPS drop. The same is true to a lesser degree for just openning your bagpack (also without any addons). And even picking up an item while your backpack is open leads to 1-2 frames with a lower rate than the GPU would be able to render.

How fundamentally different would it be if the GPU does its thing rendering the game world as fast as possible and the lua code does its thing taking as long as it needs without throttling the FPS...?
This could be done with the Lua's coroutine, and since the Lua is single thread, so you don't need worry about the thread lock. We can yield those coroutines to make sure they don't cost too much in one frame to prevent fps dropping by the Lua codes.

But it's not easily to be done, we can't make all authors to use the coroutines, also we can't make all authors to use the coroutines under the same framework.

You can check my Scorpio-Async FrameWork for some ideas. Since most addons I used are created by my own, I can make all codes processed without fps dropping, but that only works for myself.

Somebody told me, the Scorpio is largely used in hack-apps like automatic combat for performance, it's sad that it's popular in a wrong direction.
  Reply With Quote
07-01-20, 12:59 AM   #12
LudiusMaximus
A Rage Talon Dragon Guard
 
LudiusMaximus's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2018
Posts: 320
Originally Posted by kurapica.igas View Post
I can make all codes processed without fps dropping.
Wow, this sounds amazing. I cannot even begin to understand how this works.
I mean you somehow have to "pass the execution around" (like SDPhantom said) from frame to frame, right? So when WoW is running at 120 FPS you do less lua executions per frame than when it is running at 60 FPS? How does your framework estimate how many lua executions "fit" into one frame, before the FPS would drop??
__________________
~ Be the change you want to see in the world... of warcraft interface! ~
  Reply With Quote
07-01-20, 04:15 AM   #13
kurapica.igas
A Chromatic Dragonspawn
Join Date: Aug 2011
Posts: 152
Originally Posted by LudiusMaximus View Post
Wow, this sounds amazing. I cannot even begin to understand how this works.
I mean you somehow have to "pass the execution around" (like SDPhantom said) from frame to frame, right? So when WoW is running at 120 FPS you do less lua executions per frame than when it is running at 60 FPS? How does your framework estimate how many lua executions "fit" into one frame, before the FPS would drop??
Task an example:

Lua Code:
  1. Scorpio "ScorpioTest" ""
  2.  
  3. __Async__()
  4. __SlashCmd__ "sct" "start"  -- use `/sct start` to start the process
  5. function bigCycle()
  6.     local time = GetTime()
  7.     local prev = 0
  8.     for i = 1, 10^7 do
  9.         if i%10 == 0 then
  10.             Continue() -- The frame will freeze if miss this
  11.  
  12.             if time ~= GetTime() then
  13.                 -- Means the thread is resumed in the next frame OnUpdate
  14.                 time = GetTime()
  15.  
  16.                 -- Here is the current time and the cycle count of the previous phase
  17.                 -- On my laptop(i7-9750H), it's about 14600(10 level) or 20000(1 level)
  18.                 print(time, i - prev)
  19.                 prev = i
  20.             end
  21.         end
  22.     end
  23. end

Dont' mind the __SlashCmd__, it means use command "/sct start" to call the function bigCycle, the __Async__ means the function will be processed in a coroutine, there are many ways to simple code like this.

The blz provide the debugprofilestop, so we can mesaure the cost of code in one frame(The GetTime() can't do that, since it won't change the result during one frame)

The core part in the example is the Continue API provided by the Scorpio. It'll yield the coroutine, queue it to a high priority task list. So the code is stopped, the task schedule system will check if there is still enough time in one frame, if it's has, the system will check the task list, and resume each task one by one until there is no task or not enough time.

The time limit for one frame is calcluated by the fps, it is less in 120 hz game than the 60hz(but normally the CPU is more powerful in the 120 Hz hardware platform).

The system will also try to calcuate the average cost of the codes(from resume to the yield, since many codes doesn't finish in one frame), so if there is too many tasks, the task system will try to get more time to reduce the amount of the tasks, but with a max time limit, the fps dropping could be unnoticeable, we still can change the max time limit to make sure no fps dropping.

So to dot it, we need a task schedule system to manage the time and resume the tasks, and several async APIs like the Continue, Delay and etc to queue the tasks into the schedule system, so we can manage them no matter where and how the code works.
  Reply With Quote
07-01-20, 04:28 AM   #14
LudiusMaximus
A Rage Talon Dragon Guard
 
LudiusMaximus's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2018
Posts: 320
Cool, it's great to know that something like that exists. Maybe some day I will try to implement a bag inventory that gets updated without FPS drop when looting something.
__________________
~ Be the change you want to see in the world... of warcraft interface! ~
  Reply With Quote
07-01-20, 08:58 AM   #15
DahkCeles
A Cliff Giant
 
DahkCeles's Avatar
AddOn Author - Click to view addons
Join Date: Jun 2020
Posts: 73
This makes sense, actually. I've considered adding a flag my addon to detect when something like UNIT_AURA has happened a bazillion times in just one frame, and waiting until the next frame to execute the code only once. The downside is that you are imposing 'latency' on the player.

In theory, they will see the information one frame later and thus have a slower reaction time. It's kind of like purposefully having tiny lag, in order to have a faster framerate... but of course we're talking about imperceptibly small fractions of a second.

After playing around, though, I found the savings on a 120Hz screen to be so marginal that it wasn't worth it. I guess if it were an expensive function then it might be helpful... but displaying buffs on a screen doesn't take much effort. A computer capable of super-duper-fast refresh rates probably has the processing power to push through it anyways.
  Reply With Quote
07-01-20, 05:03 PM   #16
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,308
Keep in mind, not everyone is running bleeding edge hardware nor can afford to.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Registering for all events / asynchronous code execution

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off