I don’t think the amount of times a variable is used produces lag or impacts performance.
But by logic, I think it’ll be faster if you define a variable first then use it later it, it’ll have less impact on performance since it’s already defined and “stored”, instead of like going back to the workspace and find a certain object every time you run something like: workspace.Part.Transparency = 1
say if you have a local variable named “part” that’s defining a part named “Part” in workspace: local part = workspace.Part
and you put that variable outside of a loop:
local part = workspace.Part
while wait() do part.Transparency = 1
It will always try to change that defined part’s transparency. But if you do while wait() do workspace.Part.Transparency = 1 end it will always try to find an object named “Part” in workspace and try to set its transparency to 1.
again, I don’t think either way would have much of a performance impact, but by logic, it’ll be better if you define it first. I’m not too sure myself.
In that specific case it’s pretty much the same thing, in both you’re searching workspace for its Part child. The first only differs in that it uses some memory to keep a reference to the instance.
Of course it would be faster to have a direct reference to an object rather than indexing tables/userdata to find it everytime you need it. In your example with setting the part’s transparency, I found it took around 2 seconds to do it by indexing workspace directly, and about 0.75 seconds when accessing the variable instead. This was for 10 million iterations. Generally the most often you’ll be doing something is once every frame, or 60 times a second (not 5 million times a second) so you won’t really see much impact, which is why readability can be considered instead. However readability usually favours the more performant option in this case anyway; it’s easier to read a variable name than follow chains of object indexings.
I marked you as the solution, but let me make sure I understand.
game.workspace.Part.Transparency = 1
--is the same SPEED as
local Part = game.workspace.Part
Part.Transparency = 1
--BUT Assigning the variable uses MORE MEMORY.
Yes. I’m not sure if assignments are taxing enough to divide both cases in terms of speed, so I’d say they are the same.
The memory I’m not 100% sure on, as an instance is a userdata that is handled by reference unlike things like strings, booleans or numbers. The instance still exists in memory regardless of the references held to it, so if anything the memory taken up by the reference would be very small compared to the memory taken up by the object itself.
wait(5)
print("Direct")
debug.profilebegin("Direct")
for i = 1, 1000 do
game.workspace.Part.Transparency = math.random()
print(game.workspace.Part.Transparency)
end
debug.profileend()
wait(5)
print("Variable")
debug.profilebegin("Variable")
local Part = game.workspace.Part
for i = 1, 1000 do
Part.Transparency = math.random()
print(Part.Transparency)
end
debug.profileend()
4 milisecond difference for 1000 iterations. More testing will be needed to see if it isn’t just my computer being slow. Not sure if I’m interpreting it wrong but it was pretty interesting I guess to learn how the microprofiler works.
Hold up, I don’t know how I didn’t think of this before, but what if I set the variable to nil if I’m done using it so it gets picked up by the garbage collector and removes it from the memory?
Also I did a test of this of my own by making code run ten times and finding the mean elapsed time, but there was some weird bug I couldn’t figure out which made both time elapsed print the same number, but if I did the test again it would do a different number.
Bugged Code
function VFunc ()
local StartTick = tick()--Starting time
local Var = workspace.Baseplate
Var.Transparency = .5
Var = nil
wait(.05)
return(tick() - StartTick)
end
function NFunc ()
local StartTick = tick()--Starting time
workspace.Baseplate.Transparency = .5
wait(.05)
return (tick() - StartTick)
end
local MeanV,MeanN = {},{}
for Count = 1, 10 do
table.insert(MeanV,VFunc())
end
for Count = 1, 10 do
table.insert(MeanN,NFunc())
end
local VTotal = 0
for _, Number in pairs(MeanV) do
VTotal = VTotal + Number
end
local NTotal = 0
for _, Number in pairs(MeanV) do
NTotal = NTotal + Number
end
print("V"..(VTotal / 10))
print("N"..(NTotal / 10))
Setting the variable to nil in this case is just extra work for nothing. The reference is gone once the variable goes out of scope anyway (2 lines after you set it to nil), so it would get garbage collected in that case anyway.
The bug with your benchmark is that you used MeanV in both loops when counting the sums, which is why you were getting the same numbers. Aside from that, there are a few things wrong with the benchmark itself.
When benchmarking, the most accurate function to use is os.clock() instead of tick(). Additionally, wait() is very inaccurate and unpredictable so that shouldn’t be used within a benchmark. Last thing, you won’t normally find a significant difference in time in a microoptimization if you only test it for 10 iterations. I tested it for 1,000,000 iterations instead and even then the difference was negligible between the two cases. Sometimes one was faster than the other, other times they were roughly the same; they never really differed from each other by more than 0.02 seconds.