Thread Tools Display Modes
04-17-09, 05:21 AM   #1
Azul
Banned
 
Azul's Avatar
Join Date: Apr 2009
Posts: 19
function "has more then 60 upvalues"

It seems my OnUpdate function has to be pretty small or else the whole addon fails to load with the above error. How do I solve this (besides a horribly hackish (and slow) solution like making tons of frames with OnEvent functions)? Please help!

Last edited by Azul : 04-17-09 at 05:23 AM.
 
04-17-09, 07:07 AM   #2
xConStruct
A Chromatic Dragonspawn
 
xConStruct's Avatar
AddOn Author - Click to view addons
Join Date: May 2008
Posts: 199
Never encountered your message, but it seems like you're using a lot (over 60) of local variables which are then accessed by your OnUpdate-function which causes trouble.

As you create a lot of frames, you could try to store them in tables rather than locals - this would basically eliminate a lot of your upvalues as you're only accessing one in your function(the table).

In general, it would be more helpful to see some of your code or a description how you're creating/storing the frames.
__________________
« Website | GitHub »

Oh hai!
 
04-17-09, 07:20 AM   #3
Azul
Banned
 
Azul's Avatar
Join Date: Apr 2009
Posts: 19
Originally Posted by Cargor View Post
Never encountered your message, but it seems like you're using a lot (over 60) of local variables which are then accessed by your OnUpdate-function which causes trouble.

As you create a lot of frames, you could try to store them in tables rather than locals - this would basically eliminate a lot of your upvalues as you're only accessing one in your function(the table).

In general, it would be more helpful to see some of your code or a description how you're creating/storing the frames.
Thanks.

There is just one frame, for the OnUpdate function. It's a command based addon.

Also, arrays and globals are to slow and use to much meory.. and locals in the OnUpdate function lose all of their data on each frame.. so I need to know how to do it this way, with more then 60. Please help.


Here is some pseudo code;
Code:
local Var,AnotherVar,Foo,Bar,Etc=1,"blah blah blah",GetTime(),nil
local frame=CreateFrame("Frame")

frame:SetScript("OnUpdate",function(self)

some stuff that uses Var
some stuff that uses AnotherVar
some stuff that uses Foo
some stuff that doesn't use any of them
some stuff that uses Bar
some stuff that uses Etc

end)

SlashCmdList["somecmd"] = function (arg1)
	if Etc then
		Etc=nil
	else
		Etc=1
	end
end
SLASH_somecmd1="/justacmd"
SlashCmdList["anothercmd"] = function (arg1)
	AnotherVar=arg1
end
SLASH_anothercmd1="/justanothercmd"
In this little example there are 5 variables used. If I use a lot then I get the error and it won't run.

Last edited by Azul : 04-17-09 at 07:36 AM.
 
04-17-09, 07:50 AM   #4
xConStruct
A Chromatic Dragonspawn
 
xConStruct's Avatar
AddOn Author - Click to view addons
Join Date: May 2008
Posts: 199
You could try to split your OnUpdate-function into several smaller function which are called from the OnUpdate-function so that less upvalues are used in one single function.

Sorry if it doesn't help, but I'm just wondering why you need to do calculations with over 60 variables on every update. Maybe if you describe a bit what you want to achieve with the functions, we can come up with another solution.

Seems like a dilemma to me: accessing lots of upvalues without using tables/global environment while Lua can only handle up to 60.
Can't think of alternatives besides storing them somewhere else at the cost of speed or splitting up the function.
__________________
« Website | GitHub »

Oh hai!
 
04-17-09, 08:01 AM   #5
Azul
Banned
 
Azul's Avatar
Join Date: Apr 2009
Posts: 19
Originally Posted by Cargor View Post
You could try to split your OnUpdate-function into several smaller function which are called from the OnUpdate-function so that less upvalues are used in one single function.

Sorry if it doesn't help, but I'm just wondering why you need to do calculations with over 60 variables on every update. Maybe if you describe a bit what you want to achieve with the functions, we can come up with another solution.

Seems like a dilemma to me: accessing lots of upvalues without using tables/global environment while Lua can only handle up to 60.
Can't think of alternatives besides storing them somewhere else at the cost of speed or splitting up the function.
Thank you. I split them and the performance wasn't as bad as the other ways.


I still wish there was a way to fix the 60 upvalue limit though.
 
04-17-09, 08:41 AM   #6
Nuckin
is laughing at you
 
Nuckin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 58
Originally Posted by Azul View Post
Thank you. I split them and the performance wasn't as bad as the other ways.


I still wish there was a way to fix the 60 upvalue limit though.
the 60-up error is there to try and keep you from eating up all the memory

And what splitting into functions does is it scopes parts of OnUpdate.
General info on scope: http://en.wikipedia.org/wiki/Variable_scoping
__________________
SELECT * FROM users WHERE clue > 0;
0 rows returned.
 
04-17-09, 08:46 AM   #7
Azul
Banned
 
Azul's Avatar
Join Date: Apr 2009
Posts: 19
Originally Posted by Nuckin View Post
the 60-up error is there to try and keep you from eating up all the memory

And what splitting into functions does is it scopes parts of OnUpdate.
General info on scope: http://en.wikipedia.org/wiki/Variable_scoping
If I had malicious intentions couldn't I just eat all the memory with "var={} while 1 do table.tinsert(var,' ') end"? >_>
 
04-17-09, 11:18 PM   #8
Azul
Banned
 
Azul's Avatar
Join Date: Apr 2009
Posts: 19
What is wrong with this? It says that foo is global, and that it's nil.. when obviously it should be local (they all should), and not nil..

Code:
local frame=CreateFrame("Frame")
frame:SetScript("OnUpdate",function(self)
	if not foo then local foo,bar,text="foo","bar","" end
	text=foo..bar
end)

I'm really starting to hate lua with a passion. To bad there are no alternatives.

Last edited by Azul : 04-17-09 at 11:40 PM.
 
04-17-09, 11:39 PM   #9
Sythalin
Curse staff
 
Sythalin's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 680
Originally Posted by Azul View Post
What is wrong with this? It says that bar is global, and that it's nil.. when obviously it should be local, and not nil..

Code:
local frame=CreateFrame("Frame")
frame:SetScript("OnUpdate",function(self)
	if not foo then
		local foo=1
		local bar="blah"
		local pi=3.14
		local text=""
	end
	text=foo..bar..pi
end)

I'm really starting to hate lua. I wish there was something else I could make addons in.
Since bar is declared locally in your IF statement, it won't be carried outside the block. Try putting it inside and see if it works.
 
04-17-09, 11:41 PM   #10
Azul
Banned
 
Azul's Avatar
Join Date: Apr 2009
Posts: 19
Originally Posted by ChaosInc View Post
Since bar is declared locally in your IF statement, it won't be carried outside the block. Try putting it inside and see if it works.
Then I will lose the value of it on every frame.. not to mention the overhead will be nuts.
 
04-17-09, 11:59 PM   #11
haste
Featured Artist
 
haste's Avatar
Premium Member
Featured
Join Date: Dec 2005
Posts: 1,027
Originally Posted by Azul View Post
Then I will lose the value of it on every frame.. not to mention the overhead will be nuts.
Premature optimization. Your design is obviously corrupted by this. You shouldn't really worry about the overhead in a OnUpdate from locals. Unless you create a bunch of tables on every OnUpdate, but then we're back to flawed design.

The overhead from locals is also far from nuts.
 
04-18-09, 12:13 AM   #12
Sythalin
Curse staff
 
Sythalin's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 680
Originally Posted by Azul View Post
What is wrong with this? It says that foo is global, and that it's nil.. when obviously it should be local (they all should), and not nil..

Code:
local frame=CreateFrame("Frame")
frame:SetScript("OnUpdate",function(self)
	if not foo then local foo,bar,text="foo","bar","" end
	text=foo..bar
end)

I'm really starting to hate lua with a passion. To bad there are no alternatives.
Ok, no offense mate, but don't edit a different code into it when people are trying to help you figure out the original. I was confused there for a sec...

Try separating the function out to test functionality better:
Code:
local f = CreateFrame("Blah")
f:SetScript("OnUpdate", testfunction(self))

function testfunction(frame)
    if not foo then 
        local foo = "foo"
        local bar = "bar"
    end
    text=foo..bar
    DEFAULT_CHAT_FRAME:AddMessage(text)  -- test to make sure everything goes smoothly
end
Also note that I removed local text = "" as you don't need it. It's already going to be overridden each time without having to manually clear it. After you get it working how you want, then go back and optimize the code (as haste pointed out).

Last edited by Sythalin : 04-18-09 at 12:15 AM. Reason: code typo
 
04-18-09, 12:15 AM   #13
Azul
Banned
 
Azul's Avatar
Join Date: Apr 2009
Posts: 19
Originally Posted by haste View Post
Premature optimization. Your design is obviously corrupted by this. You shouldn't really worry about the overhead in a OnUpdate from locals. Unless you create a bunch of tables on every OnUpdate, but then we're back to flawed design.

The overhead from locals is also far from nuts.
No.


Originally Posted by ChaosInc View Post
Ok, no offense mate, but don't edit a different code into it when people are trying to help you figure out the original. I was confused there for a sec...

Try separating the function out to test functionality better:
Code:
local f = CreateFrame("Blah")
f:SetScript("OnUpdate", testfunction(self))

function testfunction(frame)
    if not foo then 
        local foo,bar="foo","bar"
    end
    text=foo..bar
    DEFAULT_CHAT_FRAME:AddMessage(text)  -- test to make sure everything goes smoothly
end
Also note that I removed local text = "" as you don't need it. It's already going to be overridden each time without having to manually clear it. After you get it working how you want, then go back and optimize the code (as haste pointed out).
Was just simplifying the example to make it easier to understand, and hadn't seen your reply yet.

Yes text is supposed to be overwritten in the example.. and it's supposed to be a local.


BTW your example is broken.

Even after fixing the CreateFrame, it says "attempt to call function 'testfunction', a nil value" and I don't know how to fix that, since it's defined right there clear as day. :s


Edit: fixed it by moving it over the OnUpdate.. and now it says it's trying to concatenate foo as a GLOBAL, and that it's NIL. Just like in my example.

Last edited by Azul : 04-18-09 at 12:21 AM.
 
04-18-09, 12:16 AM   #14
celebros
A Deviate Faerie Dragon
 
celebros's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2007
Posts: 12
At first blush this looks like a scope issue.
http://www.lua.org/manual/5.1/manual.html#2.6

I'm a bit curious of the need for 60 separate local variables being accessed on each frame update. You also should take care of creating new locals in each update as well, as it appears that your goal is extreme performance. Though I would offer the advice that getting it working with a table at first and then going back and optimizing the most often executed code wouldntield better or at least more timely results. Just my $.02. I could be wrong.
 
04-18-09, 12:22 AM   #15
Sythalin
Curse staff
 
Sythalin's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 680
Sorry, wasn't meant to be a full blown working example, just kind of a guide to help ya debug. It's 1:30am and I'm tired.
 
04-18-09, 12:25 AM   #16
Azul
Banned
 
Azul's Avatar
Join Date: Apr 2009
Posts: 19
Originally Posted by celebros View Post
At first blush this looks like a scope issue.
http://www.lua.org/manual/5.1/manual.html#2.6

I'm a bit curious of the need for 60 separate local variables being accessed on each frame update. You also should take care of creating new locals in each update as well, as it appears that your goal is extreme performance. Though I would offer the advice that getting it working with a table at first and then going back and optimizing the most often executed code wouldntield better or at least more timely results. Just my $.02. I could be wrong.
They are generated once on load. This process is very expensive, and can't really be optimized any more then it already is. Their values are (sometimes) modified outside of the OnUpdate by slash commands. Performance is to slow when they are global. When there are over 60 defined local above the OnUpdate function I get that stupid "to many upvalues" error.

Guess I should have explained this in the first post. I thought I did though. Sorry.

P.S. It does work as tables but is to slow.


Originally Posted by ChaosInc View Post
Sorry, wasn't meant to be a full blown working example, just kind of a guide to help ya debug. It's 1:30am and I'm tired.
Thanks, it has the exact same problem my example does, though.

Last edited by Azul : 04-18-09 at 12:28 AM.
 
04-18-09, 12:32 AM   #17
Sythalin
Curse staff
 
Sythalin's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 680
Originally Posted by Azul View Post
Edit: fixed it by moving it over the OnUpdate.. and now it says it's trying to concatenate foo as a GLOBAL, and that it's NIL. Just like in my example.
Oh duh, it's a logic issue. Ok,here's the lowdown on what's happening in your example (still tired, bear with me ).

1) check for global foo
Code:
if not foo then...
2) if global foo doesn't exist, create a local foo
Code:
local foo = "foo"
3) after declaring the end of the if statement, local foo is destroyed. Translated as per the compiler:
Code:
foo = NIL
4) attempt to create text
Code:
text = foo..bar
5) ERROR - a global foo still hasn't been created. And since the local was destroyed in stage 3, foo still remains as NIL

Also, I realize after looking back that the function would have to go before the scripts (which is always a good practice to maintain, for the record), but you posted the fix already.
 
04-18-09, 12:35 AM   #18
Azul
Banned
 
Azul's Avatar
Join Date: Apr 2009
Posts: 19
Originally Posted by ChaosInc View Post
Oh duh, it's a logic issue. Ok,here's the lowdown on what's happening in your example (still tired, bear with me ).

1) check for global foo
Code:
if not foo then...
2) if global foo doesn't exist, create a local foo
Code:
local foo = "foo"
3) after declaring the end of the if statement, local foo is destroyed. Translated as per the compiler:
Code:
foo = NIL
4) attempt to create text
Code:
text = foo..bar
5) ERROR - a global foo still hasn't been created. And since the local was destroyed in stage 3, foo still remains as NIL

Also, I realize after looking back that the function would have to go before the scripts (which is always a good practice to maintain, for the record), but you posted the fix already.
How do I check for a local foo instead? And be defined in the function scope instead of the if statement? If this is impossible then defining them inside the update definitely isn't an alternative and I need a way around the 60 upvalue limit like I asked for in the first post.
 
04-18-09, 12:42 AM   #19
Sythalin
Curse staff
 
Sythalin's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 680
You can't check for a local variable outside it's block. You'd have to rename the global foo as something else and pass the data out to it.

Code:
function testfunction(frame)
    if not arg1 then 
        local foo = "foo"
        local bar = "bar"
        arg1 = foo
        arg2 = bar
    end
    text=arg1.. arg2
    DEFAULT_CHAT_FRAME:AddMessage(text)  -- test to make sure everything goes smoothly

local f = CreateFrame("FRAME", "Blah")
f:SetScript("OnUpdate", testfunction(self))

end
But that won't help your 60 upvalue any. For that, you're don't really have a choice but to condense it down via one of the previously mentioned methods.

Last edited by Sythalin : 04-18-09 at 12:43 AM. Reason: code typo
 
04-18-09, 12:47 AM   #20
Azul
Banned
 
Azul's Avatar
Join Date: Apr 2009
Posts: 19
Originally Posted by ChaosInc View Post
You can't check for a local variable outside it's block. You'd have to rename the global foo as something else and pass the data out to it.

Code:
function testfunction(frame)
    if not arg1 then 
        local foo = "foo"
        local bar = "bar"
        arg1 = foo
        arg2 = bar
    end
    text=arg1.. arg2
    DEFAULT_CHAT_FRAME:AddMessage(text)  -- test to make sure everything goes smoothly

local f = CreateFrame("FRAME, "Blah")
f:SetScript("OnUpdate", testfunction(self))

end
But that won't help your 60 upvalue any. For that, you're don't really have a choice but to condense it down via one of the previously mentioned methods.
Tables are to slow. If there's a decent (not function call, like the extremely slow bit library) way to do bitwise operations in it, I think I could bring the variable count down enough to placate this arbitrary limitation. I don't know how though. All I could find was that uselessly slow bit function library. Any ideas?

If not, then all I can think of is updating the lua package in WoW to one that works better.. I don't know how to do this though, and it might be frowned upon by Blizzard (can anyone confirm this?).

Last edited by Azul : 04-18-09 at 12:51 AM.
 

WoWInterface » Developer Discussions » Lua/XML Help » function "has more then 60 upvalues"

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