As far as I can tell there’s little optimization whatsoever, so I wouldn’t say it’s better than native remotes & bindables. This is all constructive so don’t take this the wrong way.
But if you’re going say it’s faster and better than this or that, please provide evidence & benchmarks like @Artzified said.
I think that roblox uses something like metatables for the Value Instance because it doesn’t have methods to change the value so the only option for the changed event is metatables.
Where did you even get this? I’m pretty sure the engineers there has better tooling than just metatables, they don’t just do Luau, they also do lower level languages for more optimizations. Just because something uses a key-value property for read and write, it doesn’t mean it uses metatables. Lower level & higher level languages has native getter and setters that behaves the same way, but better.
It still wouldn’t answer why this is a better alternative to FastSignal, you’re just making stuff up now. I’m pretty sure FastSignal is just bindable but faster, you’re just using ValueBase Instances, which is completely different and you don’t provide benchmark as proof that this can replace FastSignal.
I don’t know what’s special about this ValueBase module, it doesn’t seem authentic and as advertised. What makes this different than making my own replication module using ValueBase instances, as the only superior feature you’ve written is just type annotation. What’s so safe about using this? Can some “ex-ploiters” just change the value in the client and the server would flag it as legit?
There a compilers for Lua U to machine code, even if it still wouldn’t be faster than C++ it has other advantages like that you can change the code to your likings.
I don’t know how to benchmark Value Instance, I have tried and it prints nan out here is the code:
-- Server
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local FastValue = require(ReplicatedStorage.FastValue)
local value = ReplicatedStorage.Value
local valueInstanceBenchmarks = ReplicatedStorage.ValueInstanceBenchmarks
local ValueInstanceServerTicks = {}
local ValueInstanceTicks = {}
local valueInstanceAverageTick = 0
for i = 1, 10, 1 do
task.wait(1)
value.Value = i
table.insert(ValueInstanceServerTicks, tick())
end
valueInstanceBenchmarks.OnServerEvent:Connect(function(player, ValueInstanceClientTicks)
for i, clientTick in ipairs(ValueInstanceClientTicks) do
table.insert(ValueInstanceTicks, clientTick - ValueInstanceServerTicks[i])
end
end)
for i, tick in ipairs(ValueInstanceTicks) do
valueInstanceAverageTick += tick
end
valueInstanceAverageTick /= #ValueInstanceTicks
print(valueInstanceAverageTick)
-- Client
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local FastValue = require(ReplicatedStorage.FastValue)
local value = ReplicatedStorage.Value
local valueInstanceBenchmarks = ReplicatedStorage.ValueInstanceBenchmarks
local ValueInstanceClientTicks = {}
value.Changed:Connect(function(value)
table.insert(ValueInstanceClientTicks, tick())
end)
valueInstanceBenchmarks:FireServer(ValueInstanceClientTicks)
These are my individual benchmarking tests by getting the median percentile of each result.
Now before taking a look at the results I just want to address that these tests were done with 65535 iterations, using a string generated by HttpService:GenerateGUID() & StringValue object.
ModuleScripts provide globally accessible tables within the entire datamodel, you can write your own code to replicate these states into the client or using FastValue.
Values Objects (yes again!)
If you are using simple values (numbers, strings, booleans) you can attempt to distribute these values into ValueBases stored in a folder. This method allows you to directly store key-value pairs in the Roblox hierarchy.
You can still go with the JSON method tho, which will be slower and more complex to debug. : /
Sure, wrote this in a hurry so the code runs with hopes & prayers (and a little duct tape)
local function calculateMedian(arr)
local n = #arr
table.sort(arr)
if n % 2 == 1 then
return arr[math.ceil(n / 2)]
else
local mid1 = arr[n / 2]
local mid2 = arr[n / 2 + 1]
return (mid1 + mid2) / 2
end
end
local function convert_seconds(seconds)
local milliseconds = seconds * 1000
local microseconds = milliseconds * 1000
if milliseconds < 1 then
return ("%.2f"):format(microseconds), "microseconds"
elseif milliseconds < 1000 then
return ("%.2f"):format(milliseconds), "milliseconds"
else
return ("%.2f"):format(seconds), "seconds"
end
end
local FastValue = require(workspace.FastValue)
local FastValue_Get = FastValue.Get
local FastValue_Set = FastValue.Set
local StringValue = workspace.StringValue
local FASTVALUE_Results = {}
local STRINGVALUE_Results = {}
local Value = game:GetService("HttpService"):GenerateGUID(false)
for FastValue_i = 1, 2 ^ 16 do
local t = os.clock()
FastValue_Set("Key", Value)
FASTVALUE_Results[#FASTVALUE_Results + 1] = os.clock() - t
end
for StringValue_i = 1, 2 ^ 16 do
local t = os.clock()
StringValue.Value = Value
STRINGVALUE_Results[#STRINGVALUE_Results + 1] = os.clock() - t
end
print("The 50th percentile (median) of StringValue (SETTING NEW .Value): ", convert_seconds(calculateMedian(STRINGVALUE_Results)))
print("The 50th percentile (median) of FastValue (USING THE SET FN): ", convert_seconds(calculateMedian(FASTVALUE_Results)))
Add a StringValue object in the workspace named “StringValue”