How To Tell Which Operations Are More Expensive?

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.

But I’ll give it a shot.

People usually repeat operations say 100, 1000, 100000 etc times in a for loop to get a more significant difference.

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