lua-users home
lua-l archive

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


David Given wrote:
Incidentally, it occurs to me that you should be able to optimise things by making __call pregenerate all the closures. It ought to be something along the lines of:

		__call = function(self, ...)
			tmp = {}
			setmetatable(tmp, klass)
			for i, j in pairs(super) do
				tmp[i] = function (...)
					return j(tmp, unpack(arg))
				end
			end
			if self.init then
				self.init(tmp, unpack(arg))
			end
			return tmp
		end

...although that doesn't take in to account object inheritence.

Would that work? If so, would it speed things up any?
I don't think it would works. It would works only for one level of inheritance.

I've modified the class() function to add a cache for the methods, and tested on my machine (apple ibook G3 800 640Mb) with lua 5.0.2

without cache
10:32:47 Mar Dic 07 raf@ice ~
$ time lua klass.lua

real    0m1.877s
user    0m1.420s
sys     0m0.040s
10:33:57 Mar Dic 07 raf@ice ~
$ time lua klass.lua

real    0m1.912s
user    0m1.450s
sys     0m0.040s
10:34:00 Mar Dic 07 raf@ice ~
$ time lua klass.lua

real    0m1.924s
user    0m1.480s
sys     0m0.040s

with cache
10:34:03 Mar Dic 07 raf@ice ~
$ time lua klass.lua

real    0m1.377s
user    0m1.030s
sys     0m0.050s
10:34:46 Mar Dic 07 raf@ice ~
$ time lua klass.lua

real    0m1.453s
user    0m1.060s
sys     0m0.030s
10:34:48 Mar Dic 07 raf@ice ~
$ time lua klass.lua

real    0m1.431s
user    0m1.070s
sys     0m0.030s

So with a cache is really faster. But you trade speed with (memory) space.

Attacched are the two version, bugs free (I hope!), and a little test.

--
()_() | Always keep the Titanic in mind when I talk        | +----
(o.o) | about security or safety, meaning that nothin      | +---+
'm m' | is fully secure.                                   |  O  |
(___) |              raffaele punto salmaso presso libero punto it
GPG fingerprint 1CF5 51D4 E528 EB87 9977  B277 BE8C BF1E 620C 40ED
--
-- Copyright (C) 2004, Salmaso Raffaele <raffaele@salmaso.org>
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
--  1. Redistributions of source code must retain the above copyright notice,
--     this list of conditions and the following disclaimer.
--  2. Redistributions in binary form must reproduce the above copyright
--     notice, this list of conditions and the following disclaimer in the
--     documentation and/or other materials provided with the distribution.
--  3. If the binary program depends on a modified version of this package,
--     you are encouraged to publicly release the modified version of this
--     package.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.

-- operator overloading
-- __add +
-- __mul *
-- __sub -
-- __div /
-- __le <=
-- __lt <
-- __eq ==
-- __tostring
-- __call ()
-- __index []
-- __newindex
-- __pow ^
-- __unm
-- __concat ..

function class_nocache(super)
    -- create a new class description
    local klass = {}
    -- set the superclass (for object inheritance)
    setmetatable(klass, {
        __index = super,
        __call = function(self, ...)
            local tmp = {}
            setmetatable(tmp, klass)
            if self.init then
                self.init(tmp, unpack(arg))
            end
            return tmp
        end
    })
    klass.__index = function(table, key)
        local r = klass[key]
        if table ~= klass and type(r) == 'function' then
            return function(...) return r(table, unpack(arg)) end
        else
            return r
        end
    end
    return klass
end

function class_cache(super)
    -- create a new class description
    local klass = {}
    -- set the superclass (for object inheritance)
    setmetatable(klass, {
        __index = super,
        __call = function(self, ...)
            local tmp = {}
            setmetatable(tmp, klass)
            tmp.__method_cache__ = {}
            if self.init then
                self.init(tmp, unpack(arg))
            end
            return tmp
        end
    })
    klass.__index = function(table, key)
        local r = klass[key]
        if table ~= klass and type(r) == 'function' then
            local f = table.__method_cache__[r]
            if not f then
                f = function(...) return r(table, unpack(arg)) end
                table.__method_cache__[r] = f
            end
            return f
        else
            return r
        end
    end
    return klass
end

class = class_nocache

-- ######################
-- test the object system
-- ######################

object = class()
function object.method(self)
    return 1
end

o=object()
for i=1,100000 do
    o.method()
end