Signal+|Insanely optimized script signal

:bell: Version 2.6.0

Changes & improvements:

  • Wait no longer creates and returns a metatable — it was never supposed to.
  • Now functions won’t error after Destroy, but will still do nothing.
  • Minor function description changes.
  • Minor description change.

Would you mind making this a wally package? I’d like to use this, but seeing as it’s a brand new resource I’d like to have a package manager for it.

Really cool to see everyone bash this guy at the start and then they all get proven wrong at the end.

This module seems cool, might switch from FastSignal to it.

3 Likes

I can’t argue that it’s better than GoodSignal :person_shrugging: (SimpleSignal still faster tho heheheheh, connection order reliability? Who?)

Download SignalPlus_package.rbxm from the GitHub. When you drag it into Studio, you’ll get a package that will automatically update.

Hope this helps.

Have you seen the benchmark from VortechBirb?
Even v2.2.0 was significantly faster than GoodSignal.
The newest version at the moment is v2.6.0.

Here’s VortechBirb’s benchmark with Signal+ v2.2.0 (old):

Faster than GoodSignal? Sure.
Faster than Signal+? Think again.

Benchmark:

Create 100 signals:

Signal+ measured at 0.0034189999496447854 milliseconds
SimpleSignal measured at 0.007416999887936981 milliseconds
:trophy: Signal+ was 0.003997999938292196 milliseconds (~2.17x) faster than SimpleSignal

Connect 100 functions:

Signal+ measured at 0.010097000013047364 milliseconds
SimpleSignal measured at 0.018533000020397594 milliseconds
:trophy: Signal+ was 0.00843600000735023 milliseconds (~1.84x) faster than SimpleSignal

Fire with 100 functions:

Signal+ measured at 0.03844200000457931 milliseconds
SimpleSignal measured at 0.04617999997208244 milliseconds
:trophy: Signal+ was 0.007737999967503129 milliseconds (~1.2x) faster than SimpleSignal

Once 100 functions:

Signal+ measured at 0.016663000005792128 milliseconds
SimpleSignal measured at 0.024316000071848975 milliseconds
:trophy: Signal+ was 0.007653000066056848 milliseconds (~1.46x) faster than SimpleSignal

Disconnect 100 functions:

Signal+ measured at 0.009299999874201603 milliseconds
SimpleSignal measured at 0.014799999917158857 milliseconds
:trophy: Signal+ was 0.005500000042957254 milliseconds (~1.59x) faster than SimpleSignal

Disconnect all with 100 functions:

Signal+ measured at 0.0008999995770864189 milliseconds
SimpleSignal measured at 0.010800000382005237 milliseconds
:trophy: Signal+ was 0.009900000804918818 milliseconds (~12x) faster than SimpleSignal

How many repeats? Is this the mean or the total? (Why not share both?) What’s the standard deviation?

I ran each test 100 times (e.g. 100 connections 100 times), and the measurements are average run time. You are free to test yourself, but I think it’s really clear who’s the winner in that benchmark.

100 times is far too few to be conclusive… I’ll test it out tmrw after i sleep zzz

I just benchmarked with 10.000 cycles.

Create 100 signals

Signal+ measured at 0.0028682000023763973 milliseconds
SimpleSignal measured at 0.006316119998336944 milliseconds
:trophy: Signal+ was 0.0034479199959605465 milliseconds (~2.2x) faster than SimpleSignal

Connect 100 functions:

Signal+ measured at 0.011354389998450643 milliseconds
SimpleSignal measured at 0.039814160002242714 milliseconds
:trophy: Signal+ was 0.028459770003792073 milliseconds (~3.51x) faster than SimpleSignal

Fire with 100 functions:

Signal+ measured at 0.03842830000940012 milliseconds
SimpleSignal measured at 1.4735136999843235 milliseconds
:trophy: Signal+ was 1.4350853999749233 milliseconds (~38.34x) faster than SimpleSignal

Once 100 functions:

Signal+ measured at 0.03111915999525081 milliseconds
SimpleSignal measured at 0.05852859000151511 milliseconds
:trophy: Signal+ was 0.027409430006264304 milliseconds (~1.88x) faster than SimpleSignal

Disconnect 100 functions:

Signal+ measured at 0.007469740002306935 milliseconds
SimpleSignal measured at 0.023178689999440394 milliseconds
:trophy: Signal+ was 0.01570894999713346 milliseconds (~3.1x) faster than SimpleSignal

Disconnect all with 100 functions:

Signal+ measured at 0.003145279998352635 milliseconds
SimpleSignal measured at 0.013685699996858602 milliseconds
:trophy: Signal+ was 0.010540419998505968 milliseconds (~4.35x) faster than SimpleSignal

How does Signal+ compare to LemonSignal?

Here’s LemonSignal:

Create 100 signals:

Signal+ measured at 0.0029365899961703687 milliseconds
LemonSignal measured at 0.004803160001574725 milliseconds
:trophy: Signal+ was 0.001866570005404356 milliseconds (~1.64x) faster than LemonSignal

Connect 100 functions:

Signal+ measured at 0.013497720008854231 milliseconds
LemonSignal measured at 0.025186950003444508 milliseconds
:trophy: Signal+ was 0.011689229994590277 milliseconds (~1.87x) faster than LemonSignal

Fire with 100 functions:

Signal+ measured at 0.042660700009946595 milliseconds
LemonSignal measured at 0.041893600044204504 milliseconds
:trophy: LemonSignal was 0.0007670999657420907 milliseconds (~1.02x) faster than Signal+

Once 100 functions:

Signal+ measured at 0.028835559998151437 milliseconds
LemonSignal measured at 0.04398460000320483 milliseconds
:trophy: Signal+ was 0.015149040005053394 milliseconds (~1.53x) faster than LemonSignal

Disconnect 100 functions:

Signal+ measured at 0.007742059994416195 milliseconds
LemonSignal measured at 0.0053807700047400426 milliseconds
:trophy: LemonSignal was 0.0023612899896761526 milliseconds (~1.44x) faster than Signal+

Disconnect all with 100 functions:

Signal+ measured at 0.0036735600029714987 milliseconds
LemonSignal measured at 0.00356048000685405 milliseconds
:trophy: LemonSignal was 0.00011307999611744881 milliseconds (~1.03x) faster than Signal+

And here’s FastSignal btw:

Create 100 signals:

Signal+ measured at 0.002846440000575967 milliseconds
FastSignal measured at 0.005018470000504749 milliseconds
:trophy: Signal+ was 0.002172029999928782 milliseconds (~1.76x) faster than FastSignal

Connect 100 functions:

Signal+ measured at 0.012557659999765746 milliseconds
FastSignal measured at 0.03306501000042772 milliseconds
:trophy: Signal+ was 0.02050735000066197 milliseconds (~2.63x) faster than FastSignal

Fire with 100 functions:

Signal+ measured at 0.041073800004596706 milliseconds
FastSignal measured at 0.0390601999934006 milliseconds
:trophy: FastSignal was 0.002013600011196104 milliseconds (~1.05x) faster than Signal+

Once 100 functions:

Signal+ measured at 0.024617289999696368 milliseconds
FastSignal measured at 0.03905997000711068 milliseconds
:trophy: Signal+ was 0.014442680007414312 milliseconds (~1.59x) faster than FastSignal

Disconnect 100 functions:

Signal+ measured at 0.007536460004666878 milliseconds
FastSignal measured at 0.005873989997417084 milliseconds
:trophy: FastSignal was 0.0016624700072497937 milliseconds (~1.28x) faster than Signal+

Disconnect all with 100 functions:

Signal+ measured at 0.0032694300036382627 milliseconds
FastSignal measured at 0.0041916699979992695 milliseconds
:trophy: Signal+ was 0.0009222399943610068 milliseconds (~1.28x) faster than FastSignal

Overall Signal+ is the winner (faster than FastSignal and LemonSignal) — if you take the total speeds.

1 Like






bench.lua.txt (3.3 KB)

These are some benchmarks sent by a friend of mine after I shared this resource

The difference is miniscule for the functions, (except :Connect(), tho that might just be some flaws in how my friend benchmarked it) and for :Fire() it’s faster.

Since you didn’t share how you did your benchmarks, I’m a bit skeptical as to wether or not they’re real.

Will be doing my own benchmarks when I can

Provide context as to what these numbers mean, is it total? (I think it is because you said “total speeds”), is it the mean? Is it the median? Just to clear any doubt in anyones mind

Dude, stop replying to @athar_adv on some of his replies he is not being serious and he just posted benchmarks that ironically still show the module is faster, by his logic his benchmarks can’t be trusted either.

Just focuss on working on the module, its fire!!!

1 Like

:skull_and_crossbones: The difference is literally microseconds for most functions

I also shared how the benchmarks were done

Who has 100 connections on 1 signal anyway…

Heres some more benchmarks comparing SimpleSignal and FastSignal (My friends own Signal implementation, not to be confused with the same named FastSignal)

message (1).txt (2.8 KB)

It’s even faster than both SimpleSignal and SignalPlus

Honesty I don’t really mind trying to develop a resource, I get that, just try being more transparent so people can see for themselves if your resource holds water or not instead of only making claims

1 Like

You’re talking about unclear benchmarks, and you provide a benchmark where half of the results are just called Create, Fire, Connect, instead of the actual module names.

I benchmarked against FastSignal, and trust me I did it properly, and Signal+ won.

May I ask why you can’t accept that Signal+ is at least faster in 80% of scenarios?
Stop making weird conclusions, trying to promote you and your friend’s work.

It’s pretty clear what each benchmark represents, I also shared the benchmark module for each

Source: Trust me

Why can’t i accept unbacked claims?

I just shared what my friend got from benchmarking the signal modules, it has nothing to do with me or them

What are you trying to say? How can I trust your benchmark any more?
Why are you always avoiding the point?

You can trust my benchmark because I gave the code for it so you can test it out for yourself :v
Also mine has pictures… idk if its relevant but imo more believable than numbers in text

This is what I used for Good-, Lemon- and FastSignal benchmarks.
Just change the OtherSignalModule to require the desired module.
You shouldn’t have to change anything because they all share the same syntax.

Signal+ vs other signal module benchmark
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local function difference(a, b)
	if b < a then
		return a - b
	else
		return b - a
	end
end
local function benchmark(funcs, runs)
	if type(runs) ~= "number" or runs <= 1 then runs = nil end
	
	local function measure(func)
		if not runs then
			-- Run only once.
			local start = os.clock()
			func()
			return os.clock() - start
		else
			-- Run specified amount of times.
			local sum = 0
			for index = 1, runs, 1 do
				local start = os.clock()
				func()
				sum += os.clock() - start
			end
			return sum/runs -- Calculate average run time.
		end
	end
	
	local output = ""
	
	local one = measure(funcs[1])*1000
	local two = measure(funcs[2])*1000
	
	local diff = difference(one, two)
	local fastest = if two < one then two else one
	
	if diff < fastest*0.001 then
		-- Basically identical speeds.
		output ..= "\n⚖️ Both functions measured at "..tostring(fastest+diff/2).." milliseconds\n"
	else
		output ..= "\nFunction 1 measured at "..tostring(one).." milliseconds"
		output ..= "\nFunction 2 measured at "..tostring(two).." milliseconds"
		if two == fastest then
			output ..= "\n🏆 Function 2 was "..tostring(diff).." milliseconds (~"..tostring(math.round(one/two*100)/100).."x) faster than function 1\n"
		else
			output ..= "\n🏆 Function 1 was "..tostring(diff).." milliseconds (~"..tostring(math.round(two/one*100)/100).."x) faster than function 2\n"
		end
	end
	warn(output)
end

task.wait(5)

local signalPlusCreate = require(ReplicatedStorage.SignalPlus)
local otherSignalModule = require(ReplicatedStorage.SimpleSignal)

print("Create 100 signals:")
benchmark(
	{
		function()
			for index = 1, 100, 1 do
				signalPlusCreate()
			end
		end,
		function()
			for index = 1, 100, 1 do
				otherSignalModule.new()
			end
		end
	},
	10000
)

local signalPlus = signalPlusCreate()
local otherSignal = otherSignalModule.new()

print("Connect 100 functions:")
benchmark(
	{
		function()
			for index = 1, 100, 1 do
				signalPlus:Connect(function() end)
			end
		end,
		function()
			for index = 1, 100, 1 do
				otherSignal:Connect(function() end)
			end
		end
	},
	10000
)

signalPlus:DisconnectAll()
otherSignal:DisconnectAll()
for index = 1, 100, 1 do
	signalPlus:Connect(function() end)
end
for index = 1, 100, 1 do
	otherSignal:Connect(function() end)
end
print("Fire with 100 functions:")
benchmark(
	{
		function()
			signalPlus:Fire()
		end,
		function()
			otherSignal:Fire()
		end
	},
	1000
)

print("Once 100 functions:")
benchmark(
	{
		function()
			for index = 1, 100, 1 do
				signalPlus:Once(function() end)
			end
		end,
		function()
			for index = 1, 100, 1 do
				otherSignal:Once(function() end)
			end
		end
	},
	10000
)

signalPlus:DisconnectAll()
otherSignal:DisconnectAll()

print("Disconnect 100 functions:")
local signalPlusTable = {}
for index = 1, 100*10000, 1 do
	table.insert(signalPlusTable, signalPlus:Connect(function() end))
end
local simpleSignalTable = {}
for index = 1, 100*10000, 1 do
	table.insert(simpleSignalTable, otherSignal:Connect(function() end))
end
local signalPlusCurrent = 1
local otherSignalCurrent = 1
benchmark(
	{
		function()
			for index = signalPlusCurrent, signalPlusCurrent + 99, 1 do
				signalPlusTable[index]:Disconnect()
			end
			signalPlusCurrent += 100
		end,
		function()
			for index = otherSignalCurrent, otherSignalCurrent + 99, 1 do
				simpleSignalTable[index]:Disconnect()
			end
			otherSignalCurrent += 100
		end
	},
	10000
)

print("Disconnect all with 100 functions:")
local signalPlusses = {}
for index = 1, 10000, 1 do
	local signal = signalPlusCreate()
	for index = 1, 100, 1 do
		signal:Connect(function() end)
	end
	table.insert(signalPlusses, signal)
end
local otherSignals = {}
for index = 1, 10000, 1 do
	local signal = otherSignalModule.new()
	for index = 1, 100, 1 do
		signal:Connect(function() end)
	end
	table.insert(otherSignals, signal)
end
local signalPlusIndex = 1
local otherSignalIndex = 1
benchmark(
	{
		function()
			signalPlusses[signalPlusIndex]:DisconnectAll()
			signalPlusIndex += 1
		end,
		function()
			otherSignals[otherSignalIndex]:DisconnectAll()
			otherSignalIndex += 1
		end
	},
	10000
)
1 Like