I want to add something that is related and interesting.
I said that indexing a RaycastParams
with FilterDescendantsInstances
returns unrelated tables stored in different memory addresses. Interestingly, it’s possible to get similar behavior with much more common userdata, like events.
Code to test it:
local plrs = game:GetService("Players")
local function print_event(signal: RBXScriptSignal)
print("\nEvent: " .. tostring(signal) ..
"\nConnect, twice: " .. tostring(signal.Connect) .. " | " .. tostring(signal.Connect) ..
"\nConnectParallel, twice: " .. tostring(signal.ConnectParallel) .. tostring(signal.ConnectParallel) ..
"\nWait, twice: " .. tostring(signal.Wait) .. " | " .. tostring(signal.Wait)
)
end
print_event(workspace.Destroying)
print_event(plrs.PlayerAdded)
print_event(plrs.PlayerRemoving)
print_event(workspace.DescendantRemoving)
This time it’s even more confusing - is a function being copied?
I decided to do a quick benchmark; because copying is a pretty expensive task, it would be noticeable.
local plrs = game:GetService("Players")
local t = table.create(65536)
local test_connectable = {
Connect = function()
--The key doesn't matter, Luau optimizes it anyways
end,
}
local plradd = plrs.PlayerAdded
local clock = os.clock
local t1 = clock()
for i = 1, 65536 do
t[i] = test_connectable.Connect
end
local t2 = clock()
warn("Done in " .. t2 - t1 .. " seconds!")
Results (Code executed 3 times for each test, 6 times in total):
RBXScriptSignal:
0.011972700012847781
0.011786399991251528
0.011438199959229678
Empty Function:
0.001651400001719594
0.0017411999870091677
0.0016474999720230699
About the addresses being different
If you aren’t sure about the addresses being different, here is a modified version:
local plrs = game:GetService("Players")
local t = table.create(65536)
local exact = {}
local match = 0
local test_connectable = {
Connect = function()
--The key doesn't matter, Luau optimizes it anyways
end,
}
local plradd = plrs.PlayerAdded
local clock = os.clock
local t1 = clock()
for i = 1, 65536 do
local x = test_connectable.Connect
t[i] = x
if exact[x] then match += 1 end
exact[x] = true
end
local t2 = clock()
warn("Done in " .. t2 - t1 .. " seconds! Matches: " .. match)
Results:
Empty Function: 65535
RBXScriptSignal Connect: 0
First index will be unique, that’s why it’s not 65536.
The delay could have different explanations. I know that the function size doesn’t matter, I tried initializing Connect
in test_connectable
to plradd
and it was just as fast. To me though, it looks like the function is somehow copied.
I also don’t know about how it’s copied. Perhaps the Connect
function is written in C++ and for whatever reason the engine copies the instructions (copying instructions is not easy). Luau is compiled to bytecode and it could be related to bytecode. I don’t have a lot of knowledge about either of these. Again, I’ve got no idea about what’s happening / why it’s copied (if it even is).