Skip to content

Instantly share code, notes, and snippets.

@haizaar
Last active May 11, 2019 14:40

Revisions

  1. haizaar revised this gist May 11, 2019. 2 changed files with 20 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions mem.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,11 @@
    -- 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"))
    9 changes: 9 additions & 0 deletions mem.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,9 @@
    # 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())
  2. haizaar revised this gist May 11, 2019. 1 changed file with 36 additions and 16 deletions.
    52 changes: 36 additions & 16 deletions bench.py
    Original file line number Diff line number Diff line change
    @@ -5,7 +5,7 @@ def func(x):
    return x


    class A:
    class Klass:
    def __init__(self, id):
    self.id = id

    @@ -19,24 +19,44 @@ def bar(self):
    return True


    amount = 10_000_000
    def closure(id):
    def foo():
    return id

    def bar():
    id = foo()
    if not id:
    raise Exception()
    return True

    sts = time.monotonic()
    for i in range(amount):
    a = A(42)
    return {
    "id": id,
    "foo": foo,
    "bar": bar,
    }

    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()
    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))))

    print("Call: {} ops/sec".format(int(amount / (time.monotonic() - sts))))

    sts = time.monotonic()
    for i in range(amount):
    func(42)
    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("Func: {} ops/sec".format(int(amount / (time.monotonic() - sts))))
    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"]()))
  3. haizaar revised this gist May 11, 2019. 1 changed file with 2 additions and 3 deletions.
    5 changes: 2 additions & 3 deletions bench.lua
    Original file line number Diff line number Diff line change
    @@ -131,11 +131,10 @@ local timeit = function(call, multiplier)
    local id = c.id, c:foo(), c:bar()
    end

    -- Additional multiplier since these three are fast
    -- Additional multiplier since these two are fast
    local amount = multiplier * 1000 * million

    timeone(amount, "func", func, function() end)
    timeone(amount, "Baseline", OClass, dot)
    timeone(amount, "Func", func, function() end)
    timeone(amount, "Metatable", MTClass, colon)

    local amount = multiplier * million
  4. haizaar revised this gist May 11, 2019. 2 changed files with 21 additions and 15 deletions.
    20 changes: 7 additions & 13 deletions bench.lua
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,8 @@
    -- Plain function for baseline
    local func = function(x)
    return x
    end

    -- Closure
    local IClass = function(id)
    local foo = function()
    @@ -112,18 +117,6 @@ local timeit = function(call, multiplier)

    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 ..."
    @@ -138,9 +131,10 @@ local timeit = function(call, multiplier)
    local id = c.id, c:foo(), c:bar()
    end

    -- Additional multiplier since these two are fast
    -- Additional multiplier since these three are fast
    local amount = multiplier * 1000 * million

    timeone(amount, "func", func, function() end)
    timeone(amount, "Baseline", OClass, dot)
    timeone(amount, "Metatable", MTClass, colon)

    16 changes: 14 additions & 2 deletions bench.py
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,10 @@
    import time


    def func(x):
    return x


    class A:
    def __init__(self, id):
    self.id = id
    @@ -15,16 +19,24 @@ def bar(self):
    return True


    amount = 100_000_000
    amount = 10_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))))

    print("Call: {} ops/sec".format(int(amount / (time.monotonic() - sts))))

    sts = time.monotonic()
    for i in range(amount):
    func(42)

    print("Func: {} ops/sec".format(int(amount / (time.monotonic() - sts))))
  5. haizaar created this gist May 11, 2019.
    157 changes: 157 additions & 0 deletions bench.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,157 @@
    -- 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,
    }
    30 changes: 30 additions & 0 deletions bench.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,30 @@
    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))))