What are upvalues?
I probably shouldn't even try to answer this, but here's what I think I know, based on what I've read:
Upvalues are
keys that are stored in the stack for a particular Lua execution to use at runtime, when your software needs to either query the API, which then talks to Spring, or send the API a request to make Spring execute a particular function call.
Every bit of information in Lua is basically table-oriented. It's the main thing I hate about Lua, tbh, but I've gradually gotten used to it. It's like hating your talented, popular roommate, who brings all of the ladies and their friends over on a regular basis- you can hate him, sure, but he's bringing
women, man.
At any rate, using the
key to specific table locations in the global area greatly speeds stuff up, because you're not asking Lua to find the key "Color" in the table "gl"- which is what
gl.Color really means- you're giving it a very
specific key number, and saying, "go there, pass these arguments, do not bother searching".
With the global variables, this is really, really important, because they're huge tables, and table searches are, alas, quite slow.
Therefore, what you want to do, to increase efficiency, is to bring certain common variables or locations within "upper" tables "down" into the stack your program's using, so that your software doesn't have to ever search the huge tables created when Lua's initialized. Then your function loops are basically using this "upper" table- a table that's created when your Lua is initialized, basically- to make their requests to the API using those
keys, instead of requesting a search.
Lastly, upvalues are a way to create a "local-global" pool of variables for your various functions- things that all of the functions "know about". If you create a variable within a function loop, that key-value pair can only be searched by that function loop's logic- the other functions simply cannot get access to that data (
er, I should say that it's possible, but would be very, very, very difficult and eat CPU like mad).
An example of creating upvalues would be this, outside of a function:
Code: Select all
local glResetState = gl.ResetState
local glColor = gl.Color
local glText = gl.Text
local math_random = math.random
local x,z = 0,0
Which we could then use inside a function like this:
Code: Select all
function widget:DrawScreen()
x = math_random(0,500)
z = math_random(0,500)
glColor(1,0,1,1)
glText("Hello World",x,z,"rno")
glResetState
end
Basically, it's shorthand for a key value, AF. We cannot entirely avoid going back to the global variables, because those are necessary for the Lua API to pass on to Spring as a function call or query, along with whatever arguments the function wants.
But, there is a limit as to how many key values you can store this way. That's the "upvalues limit", basically, which is the wall I just smacked into. I've been trying to keep everything I need to use in
any function an upvalue, because that was pretty much my understanding about good coding practice with this language when I first started talking to Trepan about this, over a year and a half ago.
If your program gets complicated enough, that's not possible. I'm surprised I haven't hit this wall before- anything involving OpenGL involves having to localize a
lot of API calls, and that's completely necessary, if you want things to run fast.
Config is set to defaults: 60 upvalues & 200 local vars, the max stack size is 250. I don't know if those upvalues are part of the local vars or if they are seperate, so I don't know if it is possible to increase any of these numbers, but cuz the stacksize limits both of those it wouldn't change a lot.
and yes, lua creates each time it gets a local cmd a new variable on the stack. That's why you should create values only where they are needed and not to create a list of used vars at the top of the function (pascal/delphi style). Also you should try to avoid to create a local var w/o giving it any input (like "local myvar;").
Thanks for the detailed answer, I really appreciate that.
Meh, I need to learn how to profile, and see what the real difference is, between doing it as a populate --> destruct cycle and an iterative table search.
Somehow I'm guessing that it'll come out so close it won't matter a lot for what I'm doing, though- these are all variables that only get used within one function loop, and can be created before the main logical loops within the function start, so it's a one-time cost, vs. table searches over and over and over again. I suspect I come out ahead on speed, in this particular instance.