Skip to content

Instantly share code, notes, and snippets.

@haizaar
Last active May 11, 2019 14:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save haizaar/efcc083eb048d915a774ca901b0047ac to your computer and use it in GitHub Desktop.
Save haizaar/efcc083eb048d915a774ca901b0047ac to your computer and use it in GitHub Desktop.
Lua "class" performance
-- Plain function for baseline
local func = function(x)
return x
end
-- 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
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, "Func", func, function() end)
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,
}
import time
def func(x):
return x
class Klass:
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
def closure(id):
def foo():
return id
def bar():
id = foo()
if not id:
raise Exception()
return True
return {
"id": id,
"foo": foo,
"bar": bar,
}
def time_init(amount, klass, name):
sts = time.monotonic()
for i in range(amount):
klass(42)
print("{}: {} ops/sec".format(name, int(amount / (time.monotonic() - sts))))
def time_init_access(amount, klass, name, accessor):
sts = time.monotonic()
for i in range(amount):
accessor(klass(42))
print("{}: {} ops/sec".format(name, int(amount / (time.monotonic() - sts))))
amount = 10_000_000
print("Benchmarking init")
time_init(10 * amount, func, "Func")
time_init(amount, Klass, "Class")
time_init(amount, closure, "Closure")
print("Benchmarking init+invoke")
time_init_access(amount, Klass, "Class", lambda o: (o.id, o.foo(), o.bar()))
time_init_access(amount, closure, "Closure", lambda o: (o["id"], o["foo"](), o["bar"]()))
-- Fast-forward memory consumption checker
math = require("math")
local amount = 10 * 1000* 1000
stingz = {}
for i = 1, amount do
stingz[i] = string.format("%010d", math.random(amount))
end
print(io.open("/proc/self/status"):read("*a"))
# Fast-forward memory consumption checker
from random import randint
strings = []
amount = 10_000_000
for i in range(amount):
strings.append(str(randint(0, amount)).rjust(10, "0"))
print(open("/proc/self/status").read())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment