Last active
August 23, 2024 22:47
-
-
Save Clemapfel/83ad0fb7a4ba1d2522850ee49f4ef773 to your computer and use it in GitHub Desktop.
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
-- ### BENCHMARK CONFIG | |
n_runs = 10 -- number of total runs | |
n_vectors = 10e4 -- number of vectors per run | |
n_adds = 200 -- number of operations per vector | |
io.stdout:setvbuf("no") | |
-- ### NAIVE VECTOR ### | |
_vector_naive_metatable = { | |
__add = function(self, other) | |
return VectorNaive(self.x + other.x, self.y + other.y) | |
end | |
} | |
VectorNaive = function(x, y) | |
local out = {x = x, y = y} | |
setmetatable(out, _vector_naive_metatable) | |
return out | |
end | |
-- ### NAIVE ARRAY VECTOR ### | |
_vector_naive_array_metatable = { | |
__add = function(self, other) | |
return VectorNaive(self[1] + other[1], self[2] + other[2]) | |
end | |
} | |
VectorNaiveArray = function(x, y) | |
local out = {x, y} | |
setmetatable(out, _vector_naive_array_metatable) | |
return out | |
end | |
-- ### POOLED VECTOR ### | |
_vector_pool = {} | |
_vector_pool_n = 1 | |
for i = 1, 2 * n_vectors * n_adds do _vector_pool[i] = 0 end -- preallocate | |
VectorPooled = function(x, y) | |
local i = _vector_pool_n | |
_vector_pool[i] = x | |
_vector_pool[i + 1] = y | |
_vector_pool_n = _vector_pool_n + 2 | |
return i | |
end | |
function pooled_add(a, b) | |
return VectorPooled(_vector_pool[a] + _vector_pool[b], _vector_pool[a + 1] + _vector_pool[b + 1]) | |
end | |
-- ### FFI METATYPE ### | |
ffi = require "ffi" | |
ffi.cdef[[ | |
typedef struct Vec2 { | |
float x; | |
float y; | |
} Vec2; | |
]] | |
_vector_ffi_metatable = { | |
__add = function(self, other) | |
return VectorMetatype(self.x + other.x, self.y + other.y) | |
end | |
} | |
VectorMetatype = ffi.metatype("Vec2", _vector_ffi_metatable) | |
-- ### BENCHMARK ### | |
naive_run = {} | |
naive_array_run = {} | |
pooled_run = {} | |
metatype_run = {} | |
res = 0 -- prevents optimizing out | |
function get_values() | |
return love.math.random(), love.math.random() | |
end | |
io.write("Starting...\n") | |
collectgarbage("stop") | |
for run_i = 1, n_runs do | |
io.write("\r", run_i) | |
do | |
local current = love.timer.getTime() | |
local vec2 = VectorNaive | |
for vec_i = 1, n_vectors do | |
local a = vec2(get_values()) | |
local b = vec2(get_values()) | |
for i = 1, n_adds do | |
local c = a + b | |
res = res + c.x | |
res = res + c.y | |
end | |
end | |
table.insert(naive_run, love.timer.getTime() - current) | |
end | |
collectgarbage("collect") | |
do | |
local current = love.timer.getTime() | |
local vec2 = VectorNaiveArray | |
for vec_i = 1, n_vectors do | |
local a = vec2(get_values()) | |
local b = vec2(get_values()) | |
for i = 1, n_adds do | |
local c = a + b | |
res = res + c.x | |
res = res + c.y | |
end | |
end | |
table.insert(naive_array_run, love.timer.getTime() - current) | |
end | |
collectgarbage("collect") | |
do | |
local current = love.timer.getTime() | |
local add = pooled_add | |
local vec2 = VectorPooled | |
for vec_i = 1, n_vectors do | |
local a = vec2(get_values()) | |
local b = vec2(get_values()) | |
for i = 1, n_adds do | |
local c = add(a, b) | |
res = res + _vector_pool[c] | |
res = res + _vector_pool[c+1] | |
end | |
end | |
table.insert(pooled_run, love.timer.getTime() - current) | |
end | |
_vector_pool = {} -- reset to avoid table overflow | |
for i = 1, 2 * n_vectors * n_adds do _vector_pool[i] = 0 end | |
_vector_pool_n = 1 | |
collectgarbage("collect") | |
do | |
local current = love.timer.getTime() | |
local vec2 = VectorMetatype | |
for vec_i = 1, n_vectors do | |
local a = vec2(get_values()) | |
local b = vec2(get_values()) | |
for i = 1, n_adds do | |
local c = a + b | |
res = res + c.x | |
res = res + c.y | |
end | |
end | |
table.insert(metatype_run, love.timer.getTime() - current) | |
end | |
collectgarbage("collect") | |
end | |
collectgarbage("restart") | |
function mean(t) | |
local sum = 0 | |
for i = 1, #t do | |
sum = sum + t[i] | |
end | |
return sum / #t | |
end | |
function median(t) | |
table.sort(t) | |
return t[math.floor(#t / 2)] | |
end | |
io.write("\r", res) -- print to force res to be kept around through all benchmarks | |
io.write("\n\n# Runs : ", n_runs, "\n") | |
io.write("Naive : ", mean(naive_run), " ", median(naive_run), "\n") | |
io.write("Naive Array : ", mean(naive_array_run), " ", median(naive_array_run), "\n") | |
io.write("Pooled : ", mean(pooled_run), " ", median(pooled_run), "\n") | |
io.write("Metatype : ", mean(metatype_run), " ", median(metatype_run), "\n") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment