Title: lua: global var vs table entry var
Tags: lua;lua-table
Question: In lua when u have a function in a table, what is the difference between declaring a global variable within the function vs declaring the variable as an entry in the table (if any)? The variable is x in the example below.
dog={x=33,
func=function(self)
self.x=self.x*self.x
cat={func=function()
In dog I can use the properties of self to call the function with dog:func() instead of dog.func(dog). But outside of that, is there anything performance-wise to take into consideration in choosing between the two? The examples work a bit different when called in a loop, but outside of that?

Here is the accepted answer: Well, I heard that the two first rules about optimization are &quot;Don't do it!&quot; and &quot;Don't do it yet!&quot;.
There is an official document exposing some ways to optimize Lua code and I recommend it. The most important rule is to prefer local variables to global variables because global variables are 30% slower than local ones.
The first thing we can do with the previous code is to compile it and check the bytecode instructions to understand what happen at the execution time. I stored the first function inside &quot;test-1.lua&quot; and the second one in &quot;test-2.lua&quot;.
&gt; cat test-1.lua
dog={x=33,
func=function(self)
self.x=self.x*self.x
function TEST ()
dog:func()
&gt; luac54 -l -s test-1.lua
#(part of output omitted for clarity)
# Function: dog.func
function <test-1.lua:2,4&gt; (6 instructions at 0000000000768740)
1 param, 3 slots, 0 upvalues, 1 local, 1 constant, 0 functions
1       [3]     GETFIELD        1 0 0   ; &quot;x&quot;
2       [3]     GETFIELD        2 0 0   ; &quot;x&quot;
3       [3]     MUL             1 1 2
4       [3]     MMBIN           1 2 8   ; __mul
5       [3]     SETFIELD        0 0 1   ; &quot;x&quot;
6       [4]     RETURN0
# Function: TEST (function to call dog.func)
function <test-1.lua:7,9&gt; (4 instructions at 00000000000a8a90)
0 params, 2 slots, 1 upvalue, 0 locals, 2 constants, 0 functions
1       [8]     GETTABUP        0 0 0   ; _ENV &quot;dog&quot;
2       [8]     SELF            0 0 1k  ; &quot;func&quot;
3       [8]     CALL            0 2 1   ; 1 in 0 out
4       [9]     RETURN0
So, if we want to execute TEST 10 times, we will need to execute at least 10*(4+6) bytecode instructions, that's said 100 bytecode instructions.
&gt; cat test-2.lua
cat={func=function()
function TEST ()
cat.func()
&gt; luac54 -l -s test-2.lua
#(part of output omitted for clarity)
# Function: cat.func
function <test-2.lua:1,3&gt; (6 instructions at 00000000001b87f0)
0 params, 2 slots, 1 upvalue, 0 locals, 1 constant, 0 functions
1       [2]     GETTABUP        0 0 0   ; _ENV &quot;x&quot;
2       [2]     GETTABUP        1 0 0   ; _ENV &quot;x&quot;
3       [2]     MUL             0 0 1
4       [2]     MMBIN           0 1 8   ; __mul
5       [2]     SETTABUP        0 0 0   ; _ENV &quot;x&quot;
6       [3]     RETURN0
# Function: TEST (function to call cat.func)
function <test-2.lua:8,10&gt; (4 instructions at 00000000001b8a80)
0 params, 2 slots, 1 upvalue, 0 locals, 2 constants, 0 functions
1       [9]     GETTABUP        0 0 0   ; _ENV &quot;cat&quot;
2       [9]     GETFIELD        0 0 1   ; &quot;func&quot;
3       [9]     CALL            0 1 1   ; 0 in 0 out
4       [10]    RETURN0
So, if we want to execute TEST 10 times, we will need to execute at least 10*(4+6) bytecode instructions, that's said 100 bytecode instructions.... which is exactly the same as the first version!
Obviously, all the bytecode instructions does not take the same time to execute. Some instructions will spend much more time in the C runtime the other ones. The addition of two integer might be much faster than allocating a new table and initialize some fields. At that point, we could try to do a dirty-and-pointless microbenchmark to give us an idea.
One might copy and paste this code in a Lua interpreter:
&gt; cat dirty-and-pointess-benchmark.lua
dog={x=33,
func=function(self)
self.x=self.x*self.x
cat={func=function()
function StartMeasure ()
StartTime = os.clock()
function StopMeasure (TestName)
local Duration = os.clock() - StartTime
print(string.format(&quot;%s: %f sec&quot;, TestName, Duration))
function DoTest1 (Count)
for Index = 1, Count do
dog:func()
function DoTest2 (Count)
for Index = 1, Count do
cat.func()
COUNT = 5000000000
StartMeasure()
DoTest1(COUNT)
StopMeasure(&quot;VERSION_1&quot;)
StartMeasure()
DoTest2(COUNT)
StopMeasure(&quot;VERSION_2&quot;)
This code give this results on my computer:
VERSION_1: 246.816000 sec
VERSION_2: 250.412000 sec
Obviously, the difference is probably negligible for the most of the programs. We should always try to spend more time on writing correct programs and less time to do micro-benchmarks.

Here is another answer: First of all you should change
cat={func=function()
cat={func=function()
Now we have the same operations.
If I run both functions 10000 times I end up with cat.func() a few percent slower than dog:func()
This does not surprise as indexing locals is faster than indexing globals.
To speed up cat you could do something like this:
cat={func=function()
local _x = x
x = _x*_x
The fastest solution is probably
dog={x=33,
func=function(self)
local x = self.x
self.x = x*x
and you could even gain more speed by making your tables and x local.
Usually you don't win anything significant doing things like that.
Premature optimiziation is a big no-no and you should ask yourself what problem you're actually trying to solve.
It also doesn't make sense to squeeze the last percent out of your code if you do not even know enough Lua to write a simple benchmark for your code... just a thought.

Here is another answer: The two code snippets do very different things. dog.func sets self.x to the square of its previous value. cat.func sets the global x to 1089. You can't really compare performance between two things whose functionality are so different.

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 3, 'CommentCount': 0, 'ContentLicense': 'CC BY-SA 4.0', 'CreationDate': '2021:00:10/25/21', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<lua><lua-table>', 'Title': 'lua: global var vs table entry var', 'ViewCount': 92, 'id': 69713974, 'user_AboutMe': None, 'user_AccountId': 12266070.0, 'user_DisplayName': 'kite', 'user_Reputation': 290.0, 'user_Views': 63.0, 'user_id': 11361179.0}}