local Queue = {}
Queue.__index = Queue
function Queue.new()
return setmetatable({ _a = 1, _b = 1 }, Queue)
end
function Queue:size()
return self._b - self._a
end
function Queue:push(val)
self[self._b] = val
self._b += 1
end
function Queue:pop()
local val = self[self._a]
self[self._a] = nil
self._a += 1
return val
end
return Queue
To test it out I made a simple script that performs 100000 push and 100000 pop operations. Here are the results:
Using table: 1.2s
Using queue: 9ms
local x = 100000
local s = tick()
local t = {}
for i = 1, x do
table.insert(t, i)
end
for i = 1, x do
table.remove(t, 1)
end
print("Using table", tick() - s)
s = tick()
local q = Queue.new()
for i = 1, x do
q:push(i)
end
for i = 1, x do
q:pop()
end
print("Using Queue", tick() - s)
Your benchmark code is not correct, table.remove(t, 1) will shift every element in the array down by 1 to fill the gap of the removed element this does not match the behavior of the :pop() method which just leaves holes in the array. You should also use os.clock() instead of tick() for any benchmarks.
Here are the results once you correct for this issue:
--[[
This file is for use by Benchmarker (https://boatbomber.itch.io/benchmarker)
|WARNING| THIS RUNS IN YOUR REAL ENVIRONMENT. |WARNING|
--]]
local Queue = {}
Queue.__index = Queue
function Queue.new()
return setmetatable({ _a = 1, _b = 1 }, Queue)
end
function Queue:size()
return self._b - self._a
end
function Queue:push(val)
self[self._b] = val
self._b += 1
end
function Queue:pop()
local val = self[self._a]
self[self._a] = nil
self._a += 1
return val
end
local Samples = 10_000
local Array = {}
local Object = Queue.new()
return {
ParameterGenerator = function()
return
end,
Functions = {
["table.insert"] = function(Profiler)
for Index = 1, Samples do
table.insert(Array, Index)
end
end,
["table.remove"] = function(Profiler)
for Index = 1, Samples do
local Element = Array[Index]
Array[Index] = nil
end
end,
["Queue Push"] = function(Profiler)
for Index = 1, Samples do
Object:push(Index)
end
end,
["Queue Pop"] = function(Profiler)
for Index = 1, Samples do
local Element = Object:pop()
end
end,
},
}
Thank you for your response. Yes, it looks like my “fast” queue module isn’t fast XD.
But can you please explain why is OOP slower than just using the same code without wrapping it in a method?
Well, makes sense why tables took so long. Try with table.remove(q) only (which is identical to pop!), it went from being ~135 times slower to being 4 times faster :).
@Ax3nx I just saw your response, said exactly what I wanted! Just read the slight edit I have here.