Last active
May 11, 2019 14:40
-
-
Save haizaar/efcc083eb048d915a774ca901b0047ac to your computer and use it in GitHub Desktop.
Lua "class" performance
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Closure | |
local IClass = function(id) | |
local foo = function() | |
return id | |
end | |
local bar = function() | |
local v, err = foo() | |
if err then | |
error("Failure") | |
return nil, err | |
end | |
if not v then return false end | |
return true | |
end | |
return { | |
id = id, | |
foo = foo, | |
bar = bar, | |
} | |
end | |
-- Metatables (similar to JS prototype) | |
local MTClass_mt = { | |
__index = { | |
foo = function(self) | |
return self.id | |
end, | |
bar = function(self) | |
local v, err = self:foo() | |
if err then | |
error("Failure") | |
return nil, err | |
end | |
if not v then return false end | |
return true | |
end, | |
} | |
} | |
local MTClass = function(id) | |
local obj = { | |
id = id, | |
} | |
setmetatable(obj, MTClass_mt) | |
return obj | |
end | |
-- penlight.Class - first variation | |
local PLClass1 = class() | |
function PLClass1:_init(id) | |
self.id = id | |
end | |
function PLClass1:foo() | |
return self.id | |
end | |
function PLClass1:bar() | |
local v, err = self:foo() | |
if err then | |
error("Failure") | |
return nil, err | |
end | |
if not v then return false end | |
return true | |
end | |
-- penlight.Class - second variation | |
class.PLClass2({ | |
_init = function(self, id) | |
self.id = id | |
end, | |
foo = function(self) | |
return self.id | |
end, | |
bar = function(self) | |
local v, err = self:foo() | |
if err then | |
error("Failure") | |
return nil, err | |
end | |
if not v then return false end | |
return true | |
end, | |
}) | |
local timeit = function(call, multiplier) | |
local million = 1000000 | |
multiplier = multiplier or 10 | |
local timeone = function(amount, name, Class) | |
local sts = os.clock() | |
for i = 1, amount do Class() end | |
print(string.format("%s: %d calls/sec", name, amount/(os.clock() - sts))) | |
end | |
local timeone_with_call = function(amount, name, Class, callback) | |
local sts = os.clock() | |
for i = 1, amount do callback(Class(42)) end | |
print(string.format("%s: %d calls/sec", name, amount/(os.clock() - sts))) | |
end | |
if call then timeone = timeone_with_call end | |
print("Checking correctness") | |
local c = OClass(5) | |
print("OClass: id=", c.id, " foo()=", c.foo(), " bar()=", c.bar()) | |
local c = MTClass(5) | |
print("MTClass: id=", c.id, " foo()=", c:foo(), " bar()=", c:bar()) | |
local c = IClass(5) | |
print("IClass: id=", c.id, " foo()=", c.foo(), " bar()=", c.bar()) | |
local c = PLClass1(5) | |
print("PLClass1: id=", c.id, " foo()=", c:foo(), " bar()=", c:bar()) | |
local c = PLClass2(5) | |
print("PLClass2: id=", c.id, " foo()=", c:bar(), " bar()=", c:bar()) | |
local msg = "Benchmarking initialization ..." | |
if call then | |
msg = "Benchmarking initialization + invocation ..." | |
end | |
print(msg) | |
local dot = function(c) | |
local id = c.id; c.foo(); c.bar() | |
end | |
local colon = function(c) | |
local id = c.id, c:foo(), c:bar() | |
end | |
-- Additional multiplier since these two are fast | |
local amount = multiplier * 1000 * million | |
timeone(amount, "Baseline", OClass, dot) | |
timeone(amount, "Metatable", MTClass, colon) | |
local amount = multiplier * million | |
timeone(amount, "Closure", IClass, dot) | |
timeone(amount, "PLClass1", PLClass1, colon) | |
timeone(amount, "PLClass2", PLClass2, colon) | |
end | |
return { | |
timeit = timeit, | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import time | |
class A: | |
def __init__(self, id): | |
self.id = id | |
def foo(self): | |
return self.id | |
def bar(self): | |
id = self.foo() | |
if not id: | |
raise Exception() | |
return True | |
amount = 100_000_000 | |
sts = time.monotonic() | |
for i in range(amount): | |
a = A(42) | |
print("Init: {} ops/sec".format(int(amount / (time.monotonic() - sts)))) | |
sts = time.monotonic() | |
for i in range(amount): | |
a = A(42) | |
a.foo() | |
a.bar() | |
print("Init: {} ops/sec".format(int(amount / (time.monotonic() - sts)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment