So I’m really looking to optimize my code for CPU performance, and in particular I wanted to know how I should organize this condition:

excuse my pseudo-code

local Raycast = SimpleRaycastingFunction
local vector,onscreen = Camera:WorldToScreenPoint(point)
If RaycastReachesPoint and Onscreen then
--The user must be able to see that point
end

I want to know if Raycasting or WorldToScreenPoint is the more expensive operation. Ideally if the point isn’t visible, the code within shouldn’t run.

More broadly, I’d like to know if there is a reliable method that works for most operations like this, where I can almost time how long certain operations take to run?

A method that developers use to determine which process takes longer is to record tick() at the start of the process and record another tick() when completed. Subtract the 2 ticks and you’ll get how long that process took.

local function Process()
--does something
end
local InitialTick = tick()
Process()
local FinalTick = tick()
print(InitialTick - FinalTick)

I don’t know how accurate this method is, but I guess it does the job.

I initially thought of this, but I believe, at least in my specific example, that the operation is already so fast that the tick() wouldn’t be that different.

If that is the case and this is not binded to renderstep (or in some infinite loop) then I would drop it. The hardest part of optimization is knowing when to stop.

Thanks for the help guys, after a little bit of testing I was able to find that WorldToScreenPoint is basically faster than any other method even if I don’t utilize half the things it returns. In contrast I tried this function to see what was more efficient and it was actually 0.00002 seconds slower under every condition (which I thought was weird because GetPartsObscuringTarget is supposed to be better than raycasting)

local ignorelist = {workspace.CurrentCamera,workspace.Vis}
function CFrameVisible(CF,Ignore)
local AspectRatio = workspace.CurrentCamera.ViewportSize.X/workspace.CurrentCamera.ViewportSize.Y
local vFOV,hFOV = workspace.CurrentCamera.FieldOfView,math.floor(workspace.CurrentCamera.FieldOfView*AspectRatio)
if ((workspace.CurrentCamera.CFrame+workspace.CurrentCamera.CFrame.LookVector).p-CF.p).Magnitude < (workspace.CurrentCamera.CFrame.p-CF.p).Magnitude then
local TargetCF = CFrame.new(workspace.CurrentCamera.CFrame.p,CF.p)
local offset = workspace.CurrentCamera.CFrame:ToObjectSpace(TargetCF)
local x,y,z = offset:ToEulerAnglesXYZ()
if math.abs(math.deg(y)) > hFOV/2 or math.abs(math.deg(x)) > vFOV/2 then
return false
else
local ilist = ignorelist
if Ignore ~= nil then ilist = Ignore end
local parts = workspace.CurrentCamera:GetPartsObscuringTarget({CF.p}, ilist)
if #parts <= 0 then
return true
elseif #parts >= 10 then
return false
elseif #parts < 10 then
local result = true
for i,v in pairs(parts) do
if v.CanCollide == true and v.Transparency <= 0.2 and (v.ClassName ~= "MeshPart" or v.CollisionFidelity == Enum.CollisionFidelity.Default) and (v.ClassName ~= "UnionOperation" or v.CollisionFidelity == Enum.CollisionFidelity.Default) then
result = false
break
end
end
return result
end
end
else
--Is behind them
return false
end
end

I’d just like to add on what @sparker22 suggested. Bascially his test involves stressing the process to see how it keeps up over time. It can be done with this:

local function Process()
--does something
end
local Interations = 1000000 --how many times you want to run the function, the bigger the number, the more stress
local InitialTick = tick()
for i = 1, Iterations do
Process()
end
local FinalTick = tick()
print(FinalTick - InitialTick) --final should go first than initial :P my bad