Re: Using the __newindex method with tables: performance

  • From: Saptarshi Guha <saptarshi.guha@xxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Mon, 24 Jun 2013 15:03:28 -0700

Thanks for the suggestion.

Here is a reproducible example. On  Ubuntu 12.10 (64bit).
Did i implement your advice correctly?
(the differences become larger for larger N)


$ luajit -jv  ~/tmp/a.lua
testing {} access
[TRACE   1 a.lua:31 loop]
[TRACE   2 a.lua:19 return]
[TRACE   3 (1/5) a.lua:30 -> 1]
elapsed time: 10.43

testing [] access
[TRACE   4 a.lua:40 loop]
[TRACE   5 (4/3) a.lua:39 -> 4]
elapsed time: 2.18




Code:
require("os")

local ffi = require("ffi")
ffi.cdef[[
        void *malloc(size_t size);
]]

function createObject(n, dims)
   -- not worried about freeing this
   local arr = ffi.cast("double *", ffi.C.malloc(n*ffi.sizeof("double")))
   return {base=arr, nrows=dims["nrows"], ncols=dims["ncols"]}
end


local X = {
   __index  = function(tabl, key)
      return(tabl.base[ key[1] + key[2]*tabl.nrows ] )
   end,
   __newindex = function(tabl, key, value)
      tabl.base[ key[1] + key[2]*tabl.nrows ]  = value
   end
}
makeMatrix  = function(d)
   setmetatable(d, X)
   return(d)
end

function MuFunction1(d)
   local z = makeMatrix(d)
   for i=0, z.nrows-1 do
      for j=0, z.ncols-1 do
     z[{i,j}] = 10.0
      end
   end
end

function MuFunction2(d)
   local z = makeMatrix(d)
   for i=0, z.nrows-1 do
      for j=0,z.ncols-1 do
     z.base[i + j*z.nrows ] = 10.0
      end
   end
end



N = 10000
M = 10000
function testme()
   local x
   print("testing {} access")
   local d1 = createObject(N*M, {nrows=N, ncols=M})
   x= os.clock()
   local b1 =  MuFunction1(d1)
   print(string.format("elapsed time: %.2f\n", os.clock() - x))

   print("testing [] access")
   local d2 = createObject(N*M, {nrows=N, ncols=M})
   x= os.clock()
   local b2 =  MuFunction2(d2)
   print(string.format("elapsed time: %.2f\n", os.clock() - x))
end

testme()



On Mon, Jun 24, 2013 at 2:09 PM, Mike Pall <mike-1306@xxxxxxxxxx> wrote:

> Saptarshi Guha wrote:
> > Q1. Is muFunction slower because of the 100MM {i,j} objects created or
> the
> > __index accessing method?
>
> [You mean __newindex.]
>
> Can't say much without seeing an isolated test case. I've tried to
> write a simple test for it, but that turned out to have the same
> speed.
>
> There are some NYI cases for returns from metamethods -- not sure
> these would apply here. I suggest to compare the output of -jv and
> -jdump for the two cases.
>
> One thing I noticed is that you're giving each of these types a
> different metatable with different closures, too. That's rarely a
> good idea. Create a generic metatable (once!) whose functions
> retrieve the dimensions from the object itself.
>
> --Mike
>
>

Other related posts: