![]() |
Quote:
Lua Code:
Tested it ingame: 7980 ms 8073 ms 8664 ms Also it's pretty fast with integers only, much slower with strings/other variables. ~8500 ms ~600 ms gain on a million calls. |
Quote:
I mean, in the example bellow (from a non publshed little addon of mine), the function AlkaT_SpORCo_update() is called only once every 0.25 seconds, and it is in this function that I call two global functions. If I understood correctly, upvalueing these two functions would bring no benefit at all, right? Lua Code:
|
The point of upvaluing global functions called frequently is to reduce the amount of time it takes to get a return from those functions. A local is much faster to access than a global is.
Your script calls your AlkaT_SpORCo_update function and has to wait for it to finish before moving on to the next line in the script (AlkaT_timeSinceLastUpdate = 0). The faster it is completed, the faster it can move on. Your AlkaT_SpORCo_update function has to wait on the global functions that it calls before moving on in its code. And so on. Lua is single-threaded. |
Thank you for your reply, Seerah.
I was however already aware of what you said. Funny though, it made the thoughts clearer in my mind - I don't know how you did that, but thank you! :cool: So, I guess my real question should rather be: What would be the cons, if any, of upvalueing those global functions? I now recall that, on the thread which brought me to this one, there was a link to another thread, specifically on upvalueing, so I guess I'll have a look at that when I get some time. If I still have questions about this snippet afterwards, I'll post them back here. ;) P.s.: Your comment about the single-threaded nature of Lua wasn't exactly new to me, but, honestly, I had presumed it rather than properly looked into it. I'm not in the ITC industry (never was) but codeing has been a hobby of mine since I was about 15 (back then mainly in plain C), over 25 years now. And to be honest, the multi-threading technology was never something I fully understood (nor dived much into), codeing-wise. The way I see it, even something like Lua coroutines is only a sequential pause-this-thread, then jump-to-another, then back-to-the-first (at the simplest case of only two "coroutines"). I can understand event-driven programming and have a shallow understanding of CPU IRQs as well, so I have a vague idea on how two (or more) cores CPUs work together. But again, it's only a vague understanding of it, and as far I remember, I've never actually done any programming that wasn't, in my mind, "single-threaded". I guess I could have started a new topic about this but I fear I would quickly loose the "thread" of it in the ensueing discussion, so I'm just dropping this here now. :D |
This is a huge oversimplification, and is not 100% accurate, but it gets the point across:
Lua Code:
If a language supported up to the new 36 threads from AMD and Intel, you could send 36 commands at the same time. As to your question about cons, the two biggest about upvaluing are:
|
(Someone with 8GB of RAM would be fine ;) )
|
Upvaluing globals is a micro-optimization that you shouldn't bother actively thinking about when you're coding; looking up a variable is very fast and any addon that would see an appreciable difference from storing a local copy to access is probably not going to be saved by this.
Write your program to do what you want it to do, then if something is impacting performance, clean it up. Anything that isn't an obvious performance gain should be deferred. Premature optimization can introduce unexpected behavior that can end up wasting a lot of your time tracking down and debugging. Creating a local copy of a variable comes with the unintended (or intentional) consequence of preventing it from being replaced or hooked by other addons later in the loading process. For example, let's say you want to monitor when another addon modifies a cvar so you know not to touch that cvar in the future, so you hook the global function SetCVar. When an addon calls SetCVar it also runs your function and everyone is happy. But what if this addon creates a local reference to SetCVar before you hook it? Now when it calls SetCVar your function hook doesn't run, and everyone is sad because your addon ends up overwriting their addon's settings because it didn't see the change it made. Additionally, lua actually has an internal limit of 60 upvalues. This isn't something you normally have to worry about, but you could conceivably run into it by redeclaring a large number of globals as local variables in your addon, and then trying to access them all in a function. |
Quote:
And since both calls also goes up to another C function the time execute it would be a minuscule bit faster call, for the memory size of the function pointer. |
Thanks for all your replies.
@ myrroddin Very nice explanation ons single-threaded vs multi-threaded languages. That was pretty much what I thought, it's the "huge oversimplification, and is not 100% accurate" part I'm sure would loose me... :D On the cons of upvalueing, again, nice explanation, and makes perfect sense. But I was a bit surprised that 8GB would give so little leeway, having WoW running (mostly) alnoe. Seerah seems to have a different view on this, so... :confused: @ aemiar Those are very interesting points. Regarding that little addon of mine (prints player coordinates and speed on BattlefieldMinimap), it's pretty much done. I actually picked it up as example fpr its simplicity. But thanks for the hint, it is a good coding principle, I think. And you pretty much answered it in regards to my original question: upvalueing, in my case, where the globals are called only once per 0.25 seconds isn't worth it; might be if they were called every time OnUpdate was called (only to check how long since last call presently). But, as it is, no point. Quote:
@ Resike Quote:
I thought it was (NOT actual code): Lua Code:
A) Lua Code:
or... B) Lua Code:
Which way does it work like? |
A, I guess. The function never changes, you just get a new reference to it.
|
Quote:
![]() Imagine that a is a reference to the function you want to upvalue. By accessing the function through a variable, you're essentially just retrieving the pointer to the memory where the function is stored (b). When you upvalue a function, you're copying the contents of a, that is to say the memory address to your function, but not the actual function. The function you end up calling is the same, whether global or local in your scope. |
Quote:
Global call: Pointer to the global table _G -> lookup for the subtable _G.func -> get the table's pointer value -> call the C function from the returned pointer (Since lua does not support multithreading calling _G and accessing it's subtable's value will take 2 cycles!) Upvalued call: Pointer to the upvalued func function -> get the table's pointer value -> call the C function from the returned pointer |
Quote:
|
Quote:
|
Quote:
You can try it yourself: Lua Code:
You can do this in the other way around, it won't change a thing: Lua Code:
|
Quote:
|
Quote:
This does not print anything: Code:
local SetCVar = SetCVar |
Quote:
Lua Code:
So globalIndexName is a _G[index] value. You can abuse this for most work that runs alongside the default WoW interface. However, of course, it only works for functions and most frame functions that are global. You can find some more info on WoWProgramming. |
Quote:
|
Quote:
|
All times are GMT -6. The time now is 06:12 PM. |
vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI