lua-users home
lua-l archive

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


On 13/01/2011, at 10:02 AM, Florian Weimer wrote:

> * Geoff Leyland:
> 
>> It took a while to work out how to stop LuaJIT optimising out the
>> loops altogether - it might still be optimising more than I want.
>> I'm sure this is not a good test, but for what it's worth:
> 
> It seems that if you use non-constant keys chosen from a small set,
> the performance hit from using tables is much smaller.  Isn't that the
> more relevant case?

Mike's already replied to that, so I won't pretend to have a clue.  Nonetheless, here is a different version of the earlier test.  It might be better.  It attempts to use Mike's

> p.x = 1; p.x = 1; p.y = 1; p.z = 1; p.z = 1; p.z = 1; p.y = 1;

pattern and attempts to get a measure of memory use.  It suggests that a newproxy() userdata takes about a third of the memory of an empty table.  I'm sure people knew that already, but I didn't and it hadn't come up in this thread.

$ lua proxytest.lua 
variable indexing    userdata  :     5.8154 sec,       1956 kb
variable indexing    table     :     6.8741 sec,       5079 kb
Ratios: time: 0.845975, memory 0.385089
constant indexing    userdata  :     3.4771 sec,       1953 kb
constant indexing    table     :     4.6225 sec,       5078 kb
Ratios: time: 0.752226, memory 0.384615

$ luajit proxytest.lua 
variable indexing    userdata  :     2.6869 sec,       1173 kb
variable indexing    table     :     3.4948 sec,       3907 kb
Ratios: time: 0.768837, memory 0.300332
constant indexing    userdata  :     1.6689 sec,       1172 kb
constant indexing    table     :     2.3886 sec,       3906 kb
Ratios: time: 0.698690, memory 0.300000

Cheers,
Geoff


local char, byte = string.char, string.byte
local sum = 0
local char_offset, char_set_size = byte('a'), 26
local outer_loops, inner_loops = 50000, 100

function variable(p, c)
  for i = 1, c do
    local c0 = i + char_offset - 1 
    local x, y, z = char(c0%char_set_size), char((c0+1)%char_set_size), char((c0+2)%char_set_size)
    p[x] = 1; p[x] = 1; p[y] = 1; p[z] = 1; p[z] = 1; p[z] = 1; p[y] = 1;
  end
end

function constant(p, c)
  for i = 1, c do
    p.x = 1; p.x = 1; p.y = 1; p.z = 1; p.z = 1; p.z = 1; p.y = 1;
  end
end

function test(p, f, name)
  collectgarbage("collect")
  collectgarbage("stop")
  local initial_memory = collectgarbage("count")
  local start = os.clock()
  for i = 1, outer_loops do
    f(p(), inner_loops)
  end
  local time = os.clock() - start
  local memory = collectgarbage("count") - initial_memory
  io.write(("%-20s %-10s: %10.4f sec, %10.0f kb\n"):format(name, type(p()), time, memory))
  return time, memory
end

local p0 = newproxy(true)
getmetatable(p0).__index = function(t, i) return byte(i) end
getmetatable(p0).__newindex = function(t, i, v) sum = sum + v end
function new_proxy()
  return newproxy(p0)
end

local t0m = { __index = function(t, i) return byte(i) end, __newindex = function(t, i, v) sum = sum + v end }
function new_proxy_table()
  return setmetatable({}, t0m)
end

local t1, m1 = test(new_proxy, variable, "variable indexing")
local t2, m2 = test(new_proxy_table, variable, "variable indexing")
io.write(("Ratios: time: %8.6f, memory %8.6f\n"):format(t1/t2, m1/m2))

local t1, m1 = test(new_proxy, constant, "constant indexing")
local t2, m2 = test(new_proxy_table, constant, "constant indexing")
io.write(("Ratios: time: %8.6f, memory %8.6f\n"):format(t1/t2, m1/m2))