Compared this with my own signal module SimpleSignal which i use for all my other modules:
There isn’t really much of a difference other than the fact your module has 0 autocomplete


And also that mine has a lower standard deviation (which means the times vary less)
Honestly I don’t see why this should be used over, say, GoodSignal (considering Signal+ source code is also alot more unreadable )
Heres SimpleSignal if you wanna do your own comparison, and the Benchmark module i used:
SimpleSignal:
--!optimize 2
-- SIMPLESIGNAL UTILITY MODULE
-- GoodSignal but simple
-- Author: athar_adv
local Types = require(script.Types)
export type RBXScriptConnection = Types.RBXScriptConnection
export type RBXScriptSignal<T...> = Types.RBXScriptSignal<T...>
local freeRunnerThread = nil
local function acquireRunnerThreadAndCallEventHandler(fn, ...)
local acquiredRunnerThread = freeRunnerThread
freeRunnerThread = nil
fn(...)
freeRunnerThread = acquiredRunnerThread
end
local function runEventHandlerInFreeThread()
while true do
acquireRunnerThreadAndCallEventHandler(coroutine.yield())
end
end
local Connection = {}
local meta = {__index = Connection}
function Connection:Disconnect()
local signal = self._signal
signal._connections[self] = nil
signal._connectionCount -= 1
setmetatable(self, nil)
table.clear(self)
self.Connected = false
end
local function connection_new(signal, fn): RBXScriptConnection
return setmetatable({
_signal = signal,
_fn = fn,
Connected = true,
}, meta)
end
local Signal = {}
local meta = {__index = Signal}
function Signal:Destroy()
self:DisconnectAll()
setmetatable(self, nil)
table.clear(self)
end
function Signal:Connect(fn)
local connection = connection_new(self, fn)
self._connections[connection] = true
self._connectionCount += 1
return connection
end
function Signal:Once(fn)
local connection
connection = self:Connect(function(...)
connection:Disconnect()
fn(...)
end)
return connection
end
function Signal:DisconnectAll()
-- It's that shrimple
for connection in self._connections do
connection:Disconnect()
end
end
function Signal:Fire(...)
for connection in self._connections do
if not freeRunnerThread then
freeRunnerThread = coroutine.create(runEventHandlerInFreeThread)
coroutine.resume(freeRunnerThread)
end
task.spawn(freeRunnerThread, connection._fn, ...)
end
end
function Signal:Wait()
local running = coroutine.running()
local connection
connection = self:Connect(function(...)
connection:Disconnect()
if coroutine.status(running) ~= "suspended" then
return
end
task.spawn(running, ...)
end)
return coroutine.yield()
end
-- Create a new <code>RBXScriptSignal</code> object.
local function signal_new<T...>(): RBXScriptSignal<T...>
return setmetatable({
_connections = {},
_connectionCount = 0,
}, meta)
end
return {
new = signal_new
}
Benchmark:
local function table_sum(t)
local sum = 0
for _, v in t do
sum += v
end
return sum
end
local function table_maxv(t)
local max = -math.huge
for _, v in t do
if v > max then
max = v
end
end
return max
end
local function table_minv(t)
local min = math.huge
for _, v in t do
if v < min then
min = v
end
end
return min
end
local function table_mode(t)
local counts = {}
local maxCount = 0
local modeValue = 0
for _, value in t do
counts[value] = (counts[value] or 0) + 1
if counts[value] > maxCount then
maxCount = counts[value]
modeValue = value
end
end
return modeValue -- Return only the first most popular mode
end
local function dround(n: number, r: number)
local p = 10^r
return math.floor(n * p) / p
end
-- Returns the time it took <code>testfn</code> to run after the initial call.
local function benchmark_start<A..., R...>(testfn: (A...) -> R..., ...: A...): (number, R...)
local start = os.clock()
local result = {testfn(...)}
return os.clock() - start, unpack(result)
end
-- Calls <code>testfn</code> <code>repeats</code> times and returns <code>avtype</code> elapsed time (truncated to <code>decimals</code> decimal places).
local function benchmark_findavg(repeats: number, avtype: "mean"|"max"|"min"|"median"|"mode"|"total", decimals: number, benchInterval: number, testfn: () -> ()): (number, {number})
local times = {}
local total = 0
for i = 1, repeats do
local t = benchmark_start(testfn)
total += t
table.insert(times, t)
if i % benchInterval == 0 then
task.wait()
end
end
table.sort(times)
if avtype == "max" then
return dround(table_maxv(times), decimals), times
elseif avtype == "min" then
return dround(table_minv(times), decimals), times
elseif avtype == "median" then
return dround(times[#times//2], decimals), times
elseif avtype == "mean" then
return dround(table_sum(times)/repeats, decimals), times
elseif avtype == "mode" then
return dround(table_mode(times), decimals), times
elseif avtype == "total" then
return dround(total, decimals), times
else
error(`Unknown avtype {avtype}`)
end
end
local function stdDeviation(times, mean)
local sum = 0
for _, v in times do
sum += (v - mean)^2
end
return math.sqrt(sum/#times)
end
return {
findavg = benchmark_findavg,
start = benchmark_start,
stdDeviation = stdDeviation
}
Also,
Not very convincing :V