lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Michael Welsh Duggan <mwd@cert.org> writes:

> Mason Mackaman <masondeanm@aol.com> writes:
>
>> So to make a program run as fast as possible should you localize
>> everything in _ENV you’re going to use in your program?
>
> I was going to say, "No; only if you're going to use it more than once."
> But my empirical studies seem to demonstrate otherwise.  The included
> program has three functions, all which use a global sub-function "foo".
> The first function uses it directly as a global reference.  The second
> stashes it in a local variable and uses it from there.  The third has it
> pre-stashed as an upvalue.  In each run, the function is referenced one
> more time than in the previous run.  The results look like they speak
> for themselves.  I tried to be careful in my methodology, but I wouldn't
> be surprised if I didn't account for something in my experiment.  Feel
> free to attempt to replicate my results (numbers are number of seconds):

I take that back.  There was a trivial bug in my code.  The following
results seem closer to what I would expect.  Code attached.

1	global = 3	local = 3	upvalue = 3
2	global = 5	local = 4	upvalue = 4
3	global = 6	local = 6	upvalue = 5
4	global = 8	local = 6	upvalue = 6
5	global = 10	local = 8	upvalue = 7
6	global = 11	local = 8	upvalue = 9
7	global = 12	local = 10	upvalue = 9
8	global = 14	local = 11	upvalue = 10
9	global = 16	local = 12	upvalue = 11
10	global = 17	local = 14	upvalue = 12

function foo(a, b)
   return a + b
end

-- uses global foo
local function bar1(n)
   local total = 0
   for i = 1, n do
      total = total + foo(1, 1)
   end
   return total
end

-- uses local foo
local function bar2(n)
   local total = 0
   local foo = foo
   for i = 1, n do
      total = total + foo(1, 1)
   end
   return total
end

-- uses upvalue foo
local fooup = foo
local function bar3(n)
   local total = 0
   for i = 1, n do
      total = total + fooup(1, 1)
   end
   return total
end

local tests = {{"global", bar1}, {"local", bar2}, {"upvalue", bar3}}
local repeats = 10000000

collectgarbage("stop")
for times = 1, 10 do
   local out = {tostring(times)}
   for i, v in ipairs(tests) do
      local stime, etime, diff
      local fn = v[2]
      stime = os.time()
      for i = 1, repeats do
         fn(times)
      end
      etime = os.time()
      diff= os.difftime(etime, stime)
      out[i + 1] = v[1] .. " = " .. diff
      collectgarbage()
   end
   print (table.unpack(out))
end


-- 
Michael Welsh Duggan
(mwd@cert.org)