|
|
||
|
Hi, list!
Thank you all for your answers. Since there were that many, I would
answer them in a single post, sorry. :-)
1. About module() trick (thanks, Javier, I haven't thought about this
one). I like to have table population code written by hand -- this
gives easy to read 'reference' to available functions in given object.
(A poor-mans documentation :-) .) Otherwise your approach seems to be
quite good.
2. Why no syntax sugar (var = function(self) vs. function self:var()).
I do not like this sugar because I want strong emphasis in my code on
that functions are the first-class objects in Lua. It helps when
switching from C++ to Lua frequently. (This is nothing more than a
personal preference of course.)
3. Why not to clone table. For performance considerations. I want my
object creation to be as fast as possible (see benchmark below).
4. Why not metatable approach. I have naively thought that 'plain'
table creation would be faster. I wrote a benchmark, and it appears
that I was wrong (thank you, Matthew!). I do not quite understand why
the difference is so great though.
Benchmark is attached. Usage:
KBENCH_SCRIPT=factorybench.lua ./kbench.sh
*_init is creation of factory function, *_call is call of that
function (that is, creation of object -- what I want to optimize).
Results:
$ time lua factorybench.lua clone_init 10000000
47.66 real 46.99 user 0.20 sys
$ time lua factorybench.lua metatable_init 10000000
47.69 real 46.88 user 0.20 sys
$ time lua factorybench.lua plain_init 10000000
56.00 real 54.59 user 0.30 sys
$ time lua factorybench.lua metatable_call 10000000
5.84 real 5.75 user 0.02 sys
$ time lua factorybench.lua plain_call 10000000
18.69 real 18.43 user 0.06 sys
$ time lua factorybench.lua clone_call 10000000
66.36 real 64.61 user 0.34 sys
Also I do not understand the reasons for significant slowdown of
plain_init. Is hash table constructor so heavy?
For reference, here is a LuaJIT timings (I see no big differences in
relative speeds):
$ time luajit -O factorybench.lua clone_init 10000000
37.16 real 36.75 user 0.12 sys
$ time luajit -O factorybench.lua metatable_init 10000000
37.18 real 36.69 user 0.13 sys
$ time luajit -O factorybench.lua plain_init 10000000
48.67 real 48.00 user 0.18 sys
$ time luajit -O factorybench.lua metatable_call 10000000
3.50 real 3.45 user 0.01 sys
$ time luajit -O factorybench.lua plain_call 10000000
11.17 real 10.99 user 0.04 sys
$ time luajit -O factorybench.lua clone_call 10000000
34.15 real 33.73 user 0.11 sys
Alexander.
P.S. BTW, I've actually (temporarily) solved my problem by a different
way: that class had a large number of copy-pasted getter functions
(doh), and I've replaced them with generated functions:
local simple_getter
do
local cache = setmetatable({},{
__index = function(t, k)
local v = function(self) return self[k] end
rawset(t, k, v)
return v
end
})
simple_getter = function(name)
return cache[name]
end
end
local factory
do
local method1 = function(self)
print("method1", tostring(self))
end
factory = function()
return
{
method1 = method1;
method2 = simple_getter("var1_");
--...
methodN = simple_getter("varN_");
--
var1_ = false;
varN_ = true;
}
end
end
I understand that this does not solve any of performance problems
mentioned above -- but for this specific object performance is not
issue, and it is kind of first step to refactoring. :-)
Attachment:
kbench.sh
Description: Bourne shell script
Attachment:
factorybench.lua
Description: Binary data