#Signal+|Insanely optimized script signal
1 messages · Page 1 of 1 (latest)
can you benchmark it against goodsignal, fastsignal and other popular signal modules
Where :Once() :(
cool module but how does it stand compared to other signal modules
I'll add it.
For sure
What would this be usefull for?
It's just BindableEvents but way faster. Generally, it's good to have the best performance, and if you're creating and firing signals every frame it's a huge performance boost to use this module.
It's super simple too. Just call a function instead of having to create a new instance and access the Event property.
a
Signal+ has about the same performance as some of the best alternatives like GoodSignal and SimpleSignal, but Signal+ has slightly lower memory usage (which is good), and it also has proper types.
oh okay
Signal+|Super fast & featureful script signal
u should have thread pool instead of single thread
What
That wouldn't be good
How so
Would use a lot more memory (depending on how many you want to save at once) and isn't really necessary for signals, as you usually don't have that many connections. Working with a table rather than a single variable would also be slightly more CPU expensive — which matters when we're trying to get the absolute best performance.
But what if better performance is having a collection of threads
Like I said, for most cases, people won't have more than a few connections at once.
Is 10 too many?
I mean I prefer just one
Idk my signal does better with pool yea
How many threads are you keeping at once?
So you're keeping up to an infinite amount?
I would recommend putting a limit on that.
Well yea if your using blank functions, then they will complete immediately. If you're actually doing something in those functions, it will quickly stack up.
Nope
If there is threads in the table then they get used
And if not then add to table so
Would be flow of threads
Suphi uses same thing in his
Makes sense
I've updated the module with numerous improvements
It's definitely one of the fastest open-source signal modules.
I might do a benchmark
This is important 👍👍👍
Just checked the recent update and there is issue
Because I actually was talking to Suphi about it the other day
u shouldn't use coroutine.resume
Ahh oopsie
It works fine but there are edge cases
Cuz I legit was messing with that the other day
Cuz I thought they were the same but ig not
Yeah like a few edge cases that make everyone use task instead
Right but if you really want to use it then would want to say its unsafe in certain use cases
Who uses a signal inside of game:BindToClose()?
Suphi
And also warn() just doesn't work at all with coroutines
oops
error() i means
He said it right around where I forwarded
Could use resume in your own version but idk if you want to release one to the public where someone will end up running into one of those edge cases and be very confused
Check out the latest DevForum reply from a user by the name of VortechBirb. He benchmarked it against GoodSignal.
🗣️ 🔥
I'm changing it to task.spawn() because coroutine.create(coroutine.resume()) doesn't provide any error messages — neither error() or actual errors.
But I'm wondering what the bonus would be to use task.defer() over coroutine.yield().
Yield and defer are not the same
Yea task library only provides those that the coroutine can improve on.
So I guess yield in coroutine is all good.
Signal+|Ridiculously fast, memory efficient script signal
Signal+|Insanely fast, memory efficient script signal
Btw guys there's amazing custom types (v2.4.0+).
Signal+|Insanely optimized script signal
Which idea?
And which update?
using typeof, hopefully casting makes this work
Oh you mean how I used typeof to add comments to the functions?
Not quite
Though you probably could've done that with the type notation as well, using typeof() might make casting this actually work, I'll let you know whether it works or not
You can't do that with type notation.
Unless you use my top secret method with typeof.
type Event<E...> = {
-- ? I think it works just fine
Emit : ( --[[ Even in here!]] E...) -> ()
}
Works with no type errors with --!strict
But I don't use --!strict
With --!strict SignalPlus' side-bar looks like this:
Yep
Wait can you add comments to parameters?
I just know that block comments inside () works
Guys some guy send me his signal module (SimpleSignal) which is faster than GoodSignal.
Now watch me benchmark it against Signal+ 🔥
Create 100 signals
Signal+ measured at 0.0028682000023763973 milliseconds
SimpleSignal measured at 0.006316119998336944 milliseconds
🏆 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
🏆 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
🏆 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
🏆 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
🏆 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
🏆 Signal+ was 0.010540419998505968 milliseconds (~4.35x) faster than SimpleSignal
Nothing beats Signal+ 🗿
FastSignal's attempt:
Create 100 signals:
Signal+ measured at 0.002846440000575967 milliseconds
FastSignal measured at 0.005018470000504749 milliseconds
🏆 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
🏆 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
🏆 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
🏆 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
🏆 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
🏆 Signal+ was 0.0009222399943610068 milliseconds (~1.28x) faster than FastSignal
Final results
Total gained speed:
Signal+: 3.26x
FastSignal: 0.33x
See benchmark against LemonSignal on DevForum too
you tell em! 😼 😼 😼
heya @stable heron a quick question.. if I'm communicating between my modules using bindable events should I use custom signal such like one made by you?.. my game contains single script architecture so all of my scripts are basically modules
Since it's ssa you could use signals and the functions from the other modules
No reason for bindableevents
custom signals are just plain better than bindables
there is no reason why you shouldn't use them instead of bindables
+1
oh alright thanks
i thought that they are better a bit as they are the official roblox thing you know?
also this signal module has a really really really good feature which setting the type of the signal
which can then give me a nice auto complete for types in the :Connect function
what do you mean by ssa?
Single Script Architecture
bindables probably use some kind of custom signal as well
yes but i thought that it'll be already fairly optimized as it's a roblox thing
but it's not the case
🤷♂️
Do you think it would make change changing from GoodSignal to this?
he said the performance is the same but a tiny bit of less memory is used
That's no longer near true
Signal+ is significantly faster than GoodSignal.
See this benchmark against SimpleSignal (which is faster than GoodSignal).
what he said ^
Yes. The optimization is way beyond GoodSignal, and there is also custom parameter typing in Signal+.
That comparison was when you were using coroutine.resume instead of task.spawn
hmmm, I tried changing GoodSignal to your module, as I use a good amount of them and sometimes it crash one or other part of my game
I researched a bit and it seems to be something related to the :Wait method as it is may not well called? because with GoodSignal all works flawlessly
really Idk because the wait method seems good 🤔
That's true, but the difference is almost negligible I believe — probably around 0.1-0.2x slower fire — still significantly faster than the competitors.
Didn't know there were so many
Of course FastSignal is only so fast because it doesn't spawn new threads
Can remove outliers of SimpleSingnal, RobloxSignal and FastSignal
This is because GoodSignal only uses a single thread to reuse
So if I add a yield then fails
With yield can see
I got 100 Connections
All good 🔥
Even just having 2 yielding functions makes GoodSignal the slowest wow
But 1 and its equal and 0 its faster
Are you benchmarking fire?
Yea that's where Signal+ has the least of an advantage, but it e.g. is ~2.63x faster than FastSignal at connections in my benchmarks.
Yeah just fire
But Signal+, MySignal (your signal??) and LemonSignal are pretty much equal in fire.
Yeah MySignal is my own
Yep
If I do Connect I get this
GoodSignal's disconnect is terrible
Since it searches through all the links
Idk I'll see what FastSignal gets for connect
That's interesting, can you send me the benchmark place file?
Sure I can
MySignal is not something I've released so 😱
Its possible that there are new versions of RobloxSignal | SimpleSignal & FastSignal
Because I grabbed thenm from Stravant's GoodSignal Dev Forum post
Howd u make that graph?
Suphi's Global Library has benchmarker
Ah
@junior umbra Signal+ is better at handling many connections due to its multi-thread-recycling. Try benchmarking with 1000 connections/fires (so just do a for loop that goes up to 1000 for each test), then Signal+ will do better.
@stable heron i have 2 bindable events in my game so should i make the switch to your Signal+? Will i notice a diffrence
Depends, how often u call them. If you only call each of them once a proximity prompt is opened or something I wouldn't say its worth it. But it will do no harm
i'd say i use them. since my game is a battleground one i change states and connect them to a function
but is that a realistic scenario
yea then its good to use them
but Signal+ is faster than goodsignal?
fr?
pretty sure yea
I haven't really looked into signals that well yet. But LemonSignal and FastSignal are like almost the same
some guy on yt was glazing the guy who created goodsignal so i thought it was the best or something
and then GoodSignal is above all of em
theres a lot of them existing. Might be an old video or just personal preference
aight thanks for the help
nws
It's not a very common scenario, but try then just 10 connections/fires. But it's worth noting how much they can handle.
This is because you’re using native which makes for loops slightly faster and with tons of connections it benefits, but with a normal amount it isn’t enough to be faster
Because when mine is made native it does the same thing
Becomes slower at normal amount of connections but faster when lots
I doubt that since yours only saves one thread, right?
No
When thread yields it will make a new one
And then when thread is done yielding it gets added back to the threads
I see. In my tests (using your benchmark though) our modules are equal (at least to the eyes, because there are no numbers :( ).
👍
But it's weird because I see a lot of optimization opportunities in your module. The code ain't coding.
As in? I can explain if I know the reasoning
What do you mean?
Optimization Opportunites
- You're using functions inside of functions.
- You're assigning and indexing internal values as strings instead of numbers.
- You're yielding a reusable thread right after creation—and then resuming it after—instead of using it immediately.
- Your fire logic uses one more variable than Signal+, which can be avoided.
- You're checking the status of the thread before resuming it in
Wait, which I don't see why is needed.
- Less memory and doesn't make much slower
- Mixed Tables are slower
- I don't know what this means
- Less memory and doesn't make much slower
- Its possible for the thread to not be in the state of "suspended" and will error
Those my responses lol
Mixed tables are slower!?
Yes
Amazing
While an array is faster than dictionary, since you have metamethod of __index it now becomes mixed table and is slower than just using strings alone
Okay but if I change my numbers to strings will it be faster?
Should help tiny bit
That's perfect, because it's more readable anyways.
As for the one you don't understand, let me try to clarify:
So when you're firing a connection, you're doing this:
thread = coroutine.create(Yield)
coroutine.resume(thread)
task.spawn(thread, link.Function, thread, ...)
You see? You're resuming it, then it yields itself, and so you have to resume it again.
ah okay
This is how Signal+ fixes it:
local function reusableThread(callback, ...)
-- Use the thread first.
callback(...)
table.insert(threads, coroutine.running())
-- THEN start yielding.
while true do
reusableThreadCall(coroutine.yield())
end
end
Wait so all metatables are mixed?
No
I mean if u putting numbers into table with metatable
But if their all strings then is just dictionary
Idk u can try changing urs to strings and benchmark to numbers
Uhh it's significantly faster without numbers
There's something wrong
581x faster firing
lol
Connections are like 1.2x faster
I'll see what's up with the 581x faster firing
Okay bro thanks so fucking much for that hack
Signal+ outperforms everything else now in your benchmark thing.
I will be updating it.
Ain't no way bro I will never forget about mixed tables being slow.
🙏
Hope what u changed is correct lol
Okay maybe I should verify it works real quick
cuz they not that much slower but are
Yeah ur thread recyling still has issues I think
I am not really sure
Because yea I figured out there was something wrong.
The actual result with firing is ~1.05x faster.
Connection is ~1.44x faster.
Disconnect is ~1.05x faster.
DisconnectAll is ~1.37x faster.
Still good results for such a simple optimization.
Thanks
Wdym?
This?
It just avoids having to resume another time.
I need some context.
I mean it looks good to me
You're firing 10 new threads every frame.
Also why is FastSignal so unbelieveably fast at firing? It's missing some crucial feature, right?
Doesn't spawn threads
Yeah seems it works right
But yea firing wasn't made much faster with the mixed tables fix, so our modules are equal there.
Lemme check connection
Dude they're all in one spot, is there a way I can zoom in? I'm talking about the Global Benchmarker thing.
mmm no
Bro
Hope u have the UiDrag beta enabled tho
What?
Yea they're enabled.
But yeah zooming in no
There must be a way we can like zoom in beforehand in the code.
I mean when using the array version I get this yea
Yo how do you zoom in like that?
Doesn't work
But it is
U should be able to move the whole gui if u grab the side too
What OS u using
Windows 11
mm idk im on win 10
guess can use different benchmark yea
I just called the function to zoom and put in a fake cursor movement. I got it working.
oh dang
Yours is like 1.0 (whatever that means) faster than mine for connections.
I need to know how yours is faster
It makes no sense
Even though it's super minimal
Yea
MySignal (your signal):
local function Fire<A...>(self: Signal<A...>, ...: A...): ()
local link = self.Next
while link do
local length, thread = #threads, nil
if length ~= 0 then
thread = threads[length]
threads[length] = nil
else
thread = coroutine.create(Yield)
coroutine.resume(thread)
end
task.spawn(thread, link.Function, thread, ...)
link = link.Next
end
end
Signal+ (my signal):
Fire = function(signal, ...)
-- Fire all callbacks.
local node = signal.Head
while node do
-- Find or create a thread, and run the callback in it.
local length = #threads
if length == 0 then
task.spawn(reusableThread, node.Callback, ...)
else
local thread = threads[length]
threads[length] = nil -- Remove from free threads list.
task.spawn(thread, node.Callback, ...)
end
-- Go to the next connection.
node = node.Next
end
end,
Nice
Can we just agree that Signal+ fire should run faster?
I can not see it.
Please enlighten me
Would be related* to how threads are being handled I guess
Hm yea probably
MySignal:
local threads: {thread} = {}
local function Call<A...>(func: (A...) -> (), thread: thread, ...: A...): ()
func(...)
table.insert(threads, thread)
end
local function Yield(): ()
while true do Call(coroutine.yield()) end
end
Signal+:
local threads = {}
local function reusableThreadCall(callback, ...)
callback(...)
table.insert(threads, coroutine.running())
end
local function reusableThread(callback, ...)
callback(...)
table.insert(threads, coroutine.running())
while true do
reusableThreadCall(coroutine.yield())
end
end
It might be coroutine.running()
🤷♂️
This:
Connect = function(signal, callback)
-- Create connection.
local connection = setmetatable({
Signal = signal,
Previous = nil,
Next = signal.Head,
Callback = callback,
--Connected = true
}, connectionClass)
-- Add connection.
signal.Head = connection
-- Return connection.
return connection
end,
Is slower than this:
local function Connect<A...>(self: Signal<A...>, func: (A...) -> ()): Connection<A...>
local next = self.Next
local link = {Previous = self, Function = func, Next = next} :: any
if next ~= nil then next.Previous = link end
self.Next = link
return setmetatable(link, Connection) :: Connection<A...>
end
Yep
It's now faster than yours
wtf
Ever-so-slightly
Well if I bring back the .Connected property they are literally equal.
I did not find it beneficial to use native with mine
Alright so now for firing yours is 4 upside-down-n-s's faster.
The best (for mine) was @native on Fire() and then u also would want @native on Disconnect() because will help Fire() be faster
But then Disconnect is bit slower
And only faster firing when lots of connections
nanoseconds
Oh damn lol
Very much time
Actually does your DisconnectAll really unlink the connections?
Doesn't it cause a memory leak?
There is no reference to the table
Therefore GC will clean it
Next = {}
so once Next = nil there is no way to get that table back
It is floating in memory space 🔥
Buh yeah for native check this, 10 Connections
1000 Connections
So not worth it
Only gains because the loop is very slightly faster, so with big loop can be faster
Right so that's just why I don't have in mine
But is that the entire script native or just the disconnect and fire?
Just disconnect and fire
If I make whole script native doesn't make difference
Will still be same as Disconnect and Fire only
Only then it makes Connect slower and stuff
Seems all native is worse actually
That's because its not good to make the thread recycling functions native yea
O yeah here is reason for the check in the Wait() method https://youtu.be/yevAvHU3ewo
yer welcome!
Check out the most common signal modules here:
LemonSignal:
https://data-oriented-house.github.io/LemonSignal/
GoodSignal:
https://devforum.roblox.com/t/lua-signal-class-comparison-optimal-goodsignal-class/1387063
FastSignal:
https://devforum.roblox.com/t/fastsignal-a-consistent-signal-library/1360042
Ever wanted to learn Roblox S...
Its niche and went unnoticed for years
Weird bug
👍
Hi, Alexander, can you check DM and help me with my questions on Signal+ ?
Yo @junior umbra I just realized you don't allow for garbage collection after :DisconnectAll() in your own signal module.
You have to get rid of the next and previous pointers in each connection.
I believe a loop is unavoidable.
I think you are wrong
Buh I will see
looks fine to me
I will show how I concluded that tho
BEFORE CONNECTING
AFTER CONNECTING
AFTER DisconnectAll()
Script:
90 is about the max you can do without the Luauheap yelling at you
Since linked list kinda complex I guess
I am losing reference to all the connections?
It changes the signal from {Next = {Previous = self, Function = func, Next = self.Next}} to {}
How did you go for this insane optimization like being faster than fastSignal is a bit crazy @stable heron
like resources you learn from
I don't really look at much else. I did a lot of benchmarking to see what was fastest. You can not forget Z3SC though, he pointed out some things too.
Btw I will be releasing an update in a bit that has many more optimizations.
yeah good stuff
but the question is really more like then why the other modules didn't optimized it
They're just not as good
i mean could be a reason but just like lemon signal and other modules like that like quatrillion ppl used it
like there isn't any pro that went and made the modules more performant
by other means contributed to it
I don't know really. They likely thought it was already optimized to the maximum because it was pretty much described as that.
Well, I think the same but definitely there are some pros there who knows that it can be optimized
Also a thing you mightn't care of is that some people could make an insane optimized versions of a lot of module but they use it for themself and don't just publish it
Like blox fruit and some big games definitely has big teams of developers who makes great modules... But they keep it for the production as the scripters cannot publish it to anyone to use
Honestly I don't think cash grabs like blox fruits are super well made.
That's definitely true yea.
Well, blox fruit has more than half million ppl.. now it's not just a normal game it's a production
Also it's fps is fairly high as the game is pretty smooth with all of the abilities and effects in it
Tbh I don't play it but it's fps and performance is good
I think memory efficient is not the best way to describe this anymore
It's not any less memory efficient than say GoodSignal is it?
Probably less efficient
Can you prove it?
There's two tables anyways though?
But if you set it to itself it shouldn't have any effect. How does that work?
And the fact that code is copied instead of reusing functions would also use more memory
Roblox allows that
Sure
What
Oh
Like in Once and Wait
Instead of reuisng Connect you copied the link in it yes
I'll change the description
So I mean technically not really "Memory Efficeint" lol
More so built entirely for speed than anything
Yea go tell this guy why his is not the "Most Optimized" https://devforum.roblox.com/t/signalx-most-optimized-signal-module/3608163
My module, created absolutely for higher performance. Okay, to be honest, I’m 😶😶😶 writing a description. You’ll see it tomorrow, lol (sorry, I just really want to post it) Just look at this: here you can download it: https://create.roblox.com/store/asset/72441971932545/SignalX
Also I've thought about "featureful". It's not really so much that anymore. It was but ye I went for max performance.
Idk what to put though lol
Page isn't up 😢
He made a duplicate post stating that his other was cringe.
@stable heron do you have a ver that has .new
since i wanna switch up to this one
but i cant unless it returns a table
since im using a sharedModules table
Just remove .new
@stable heron
i have a question but have to go for a bit… will ask in a few mins
Ok
Ok, sorry about that, had a question and then something came up and I got occupied for hours.
So, if I want this to trigger 10 ish times per frame (just assuming only light functions are connected), and then possibly have spikes per frame where it’s something like 50 to 100 connections per frame, would this still handle that well?
Yep it should.
It's built for that
But let me know if you do experience performance issues.
This has probably been asked before but how does this compare against packet?
or is this even the same purpose as that
its completely different
packet is a networking library
signal+ is well, a signal
ooh wait signal like
an event?
rbxscriptsignal or wtv its called
yes you can make custom signals like that
with this
@stable heron hello, I believe im doing this correctly, but i'm unable to recieves signals with SignalPlus
I have two local scripts one for firing and the other is the listener
-- Script 1
local CustomSignal = SignalPlus()
local Bindable = ReplicatedStorage.Events.Test
local Input = KeyHandler.Create({
Name = "One",
Key = {Enum.KeyCode.E},
Type = "Single",
Began = function()
Bindable:Fire()
CustomSignal:Fire()
end
})
-- Script 2
local SignalPlus = require(ReplicatedStorage.Modules.Networking.SignalPlus)
local CustomSignal = SignalPlus()
local Bindable = ReplicatedStorage.Events.Test
CustomSignal:Connect(function()
print("Signal")
end)
local Connection = Bindable.Event:Connect(function()
print("Bindable")
end)
the bindable event connection works, but I don't receive anything from the customsignal
Those are different Signal objects
They are?
When you call SignalPlus() it makes a new signal
You'll need ModuleScript to connect to the same Signal
I see
So I'd store the created signals in some type of cache inside said module, and then I could refer to them with an index and return that found signal?
Most commonly used when you make your own objects
So for example if I had a method on my object like Object:ChangeColor() I might have an event in the object called Object.OnColorChanged
And then I can connect to that event
And whenever ChangeColor() is called it will be fired
Oh I see
Yep :D
But just have to access that same event from both scripts
Same thing you're doing with the Bindable event, just not as straight forward
My use case wouldve been as a tag listener for a module to recieve a signal once a tag has been added/changed
So during runtime if I were in the middle of some type of attack and a tag was added, id use that signal to cancel the action
Not possible with Roblox's signals?
after a bit more testing, I came up with this listener
local CS = game:GetService("CollectionService")
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
CS:GetInstanceAddedSignal("Test"):Connect(function()
local Model = CS:GetTagged("Test")
for _, Object in ipairs(Model) do
if Object == Character then
print("Found Character")
end
end
end)
But I wouldnt I need to setup this connection each time a tag is added?
I am not sure wym
The point of this method is to listen for a tag being added to a specific character during runtime, and connect a function to that listener
So let's say i have a loop, and I listen for a tag being added during that loop which cancels it and starts a new function
that's what im going for
@stable heron is your signal module checking the thread status before task.spawn?
yer welcome!
Check out the most common signal modules here:
LemonSignal:
https://data-oriented-house.github.io/LemonSignal/
GoodSignal:
https://devforum.roblox.com/t/lua-signal-class-comparison-optimal-goodsignal-class/1387063
FastSignal:
https://devforum.roblox.com/t/fastsignal-a-consistent-signal-library/1360042
Ever wanted to learn Roblox S...
and also it would be good if SignalPlus api is same as the others
like SignalPlus.new()
SignalPlus.wrap
at also it would be cool if also has reconnect like lemonsignal
Just use LemonSignal then
Is thee faster than lemon signal
The goat of all signal imo
yes
If I remember correctly
You can always try benchmarking yourself
💀
So Signal.Fire(Event) ?
i use signal.fire(name, params)
wut
i mean no it behaves the same all that changes is there are no metatables at all
pretty much just keeping everything in a simple table managing it within here
how would u do that without metatables tho
Simplesignal on devforum
black magic basically
signal for a signal?
i mean what
what so hard in fire and connect
like you can just store a func within a table and call it on fire called whats so hard bout it
if we go over it like very barebones
The SimpleSignal I found is just doing OOP but bad
ye there is 2
Both of the ones I found are doing the same thing
personally i dislike the setmetatable signals although the result is pretty much the same
Is it by Devollin or Athar
am i missing something or devollin has no simplesignal topics
https://devollin.github.io/dToolkit/. Contribute to Devollin/dToolkit development by creating an account on GitHub.
oh github
Their both called SimpleSignal and both use no metatable
But they both do the same exact thing that is even worse than metatables
athar does this as well
allthar is bindable events
lo
im trying to find the other simplesignal on devforum
To use this module, copy this code below: local freeThreads: { thread } = {} local function runCallback<T...>(callback: (T...) -> (), thread: thread, ...: T...) callback(...) table.insert(freeThreads, thread) end local function yielder() while true do runCallback(coroutine.yield()) end end local function spawn<T...>(callback: (T...) ->...
but this one is kinda what it is about
tho this one is slow
so is this worse than setmetatable
Worse for memory
how so
Because you have to write the keys "Fire" "Connect" ect.. in the object
And the __index index always exist
So putting a __index on your table actually doesn't use any extra memory over an empty table
But then you only have a pointer to the metatable
huh
local myObject = {
__index = MyClass,
}
local myObject = {
__index = BasePointer, -- This always exist idk
Connect = func,
Fire = func,
-- ect.
}```
More memory
Because each object has to have all keys
Instead of the metatable just having the keys
so you mean metatable funcs are stored more like a pointer ye
everything is a pointer yes
and in nonmetatable version you write to it
Just gets the memory address of the table
Same thing
So this would be worse on Memory but might be a tiny bit faster
aka 1 key access faster
Cuz would just do Object:Fire() vs Object.__index:Fire()
Under the hood
yea fair
well if there will be a way to use pointers in future
like pointers pointers same as c++
will metatables still be better in that case
I have no clue how pointers work really
you uh get the memory adress of the thing
and it in reality point to the given func
so you basically store a billion lines long func as a 00xblahblahblah
You can see the performance loss is from accessing __index if you do like this
I mean Roblox does that for function too yea
But trade off for that small speed is memory yea
im just curious if that still gonna be the case if for example we use 100 different signals
But yeah a while ago a friend and I were talking about it and he posted this
ye pointer
Always metatable pointer
epic
i thought metatables are dogshit before but nowadays i see why they are useful
Just helpful with memory yea
if only people told me it has a pointer yo
I mean everything is a pointer
thought its basically a walmart object management with own bs
didnt knew you can use __index like that in order to not lose memory
Yee I found that out from testing
Here's what my test was
So this is the memory usage from 100_000 blank tables
And here is memory usage for metatable
And for example
This is what you're doing
With the signals
That extra key adds some memory
It's not too much to worry about
But its something to note
if some signals dont get cleaned up by some miracle error setmetatable is superior in that case
pretty cool intel
Yeah I think Suphi even has said not to worry about it really
When seeing someone do OOP without metatables
Just because you do have a bit of memory to work with and it doesn't use an insane amount
But if memory becomes an issue then might be something you could change
how do you even cleanup the signals
local TestConnection = ToolSignals.Equipped:Connect(function()
warn(`gurt`)
end)
ClientJanitor:Add(TestConnection,"Disconnect")
im using janitor to clean up stuff and it doesnt seem to work with signal connections
any reason why
Signal:DisconnectAll()
or Signal:Destroy() to completely remove the signal.
This was my introduction to LinkedLists while attempting to decipher how the module worked, literally 100x speed compared to i,v loops in some cases in the benchmarker I used lmao.
Thx king, this stuff is goated 🤝