List of Part Property Costs, by Frame Time

I cannot care less about lego doom guy’s opinion.

Just say you made that up.

And you still don’t know what you are saying because a “render cell” (which I am assuming is just a mesh or a part’s geometry) is calculated on the GPU not the CPU (where Luau code is ran), and I’m pretty sure collisions are calculated on a separated thread. So therefore your reason literally is a bunch of crap.

You are right on that but CFrames wouldn’t be the root cause of bad performance if you use them reasonably.


The reason why I say this is useless is because there are way too many holes in it and isn’t even accurate (Look at guy above me explanation).

4 Likes

I used your benchmark module and ran some tests myself and I got pretty different results.

According to this benchmark, CFrame is still high on the list but not nearly as expensive as the previous results showed, only being around x2 as expensive as basic stuff like Name, and BrickColor, etc.

Although, I imagine these results could vary widely on a range of devices.

Here’s the code if anyone wants to check my work:

local Part = workspace.Part
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CreatedParts = {}

local Properties = {
	BrickColor = BrickColor.new("Alder"),

	CastShadow = false,

	Color = Color3.new(1, 0, 0),

	Material = Enum.Material.Neon,

	Reflectance = 1,

	Transparency = 0.5,

	Name = "oof",

	Parent = ReplicatedStorage,

	Size = Vector3.new(1,1,1),

	Position = Vector3.new(1,1,1),

	Orientation = Vector3.new(1,1,1),

	CanCollide = false,

	CanTouch = false,

	CollisionGroupId = 1,

	Anchored = true,

	CustomPhysicalProperties = PhysicalProperties.new(1,1,1,1,1),

	Massless = true,

	RootPriority = 1,

	Shape = "Ball",

	AssemblyLinearVelocity = Vector3.new(1,1,1),

	AssemblyAngularVelocity = Vector3.new(1,1,1),

	CFrame = CFrame.new(1,1,1) * CFrame.fromEulerAnglesXYZ(1,1,1),
}


local Benchmark = {
	ParameterGenerator = function()

	end;

	Functions = {},
}

local Iterations = 100
local SubIterations = 10
local Microseconds = 1000000

for Property, Value in pairs(Properties) do
	Benchmark.Functions[Property] = function()
		local Old = Part[Property]
		
		local t = os.clock()
		for i = 1, SubIterations do
			Part[Property] = Value
			Part[Property] = Old
		end
		return os.clock() - t
		
	end
end

function Benchmark:Run()
	
	local Results = {}
	local Percentiles = {10, 50, 90}
	
	-- Execution
	for Property, Function in pairs(Benchmark.Functions) do
		Results[Property] = {}
		for i = 1, Iterations do
			table.insert(Results[Property], Function()/SubIterations * Microseconds)
		end
		table.sort(Results[Property], function(a,b)
			return a > b
		end)
	end
	
	-- Readout
	print(("Property	%dth	%dth	%dth	"):format(unpack(Percentiles)))
	for Property, Result in pairs(Results) do
		local out = Property.."	"
		for _, Percentile in ipairs(Percentiles) do
			local Index = math.ceil(#Result*(Percentile/100))
			out..=string.format("%.2f μs	", Result[Index])
		end
		print(out)
	end
	
end

return Benchmark
3 Likes

That’s… the point of the post.

Good catch! That was a mistake on my part.

I updated the post to include randomized inputs.

Here are the updated numbers:

image

@AljoSven This is closer to the results you got! However, I would try running your test on the Benchmarker plugin if you would like, since it makes sure tests do not interfere with each other.

1 Like