List of Part Property Costs, by Frame Time

Property Frame Time Costs

Here is a list of Part properties and frame times that resulted from changing them in a benchmarking plugin.

The higher the number, the slower changing that property programmatically is. Numbers are immediate frame time, not anything else. Units are in microseconds. All results are based on the 50th percentile during a set of trials.

These numbers do not matter if you are doing any of these only sometimes, since they are microsecond calculations. However, when done multiple times per frame, it makes a difference. For example, this might help you find the best culling method for parts (transparency).

Here is the .bench file if you would like to test this yourself:

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

local Properties = {
	BrickColor = BrickColor.random(),

	CastShadow = false,

	Color = Color3.new(math.random(), math.random(), math.random()),

	Material = Enum.Material.Neon,

	Reflectance = math.random(),

	Transparency = math.random(),

	Name = tostring(math.random()),

	Parent = ReplicatedStorage,

	Size = Vector3.new(math.random(), math.random(), math.random()),

	Position = Vector3.new(math.random(), math.random(), math.random()),

	Orientation = Vector3.new(math.random(), math.random(), math.random()),

	CanCollide = false,

	CanTouch = false,

	CollisionGroupId = math.random(),

	Anchored = true,

	CustomPhysicalProperties = PhysicalProperties.new(math.random(), math.random(), math.random(), math.random(), math.random()),

	Massless = true,

	RootPriority = math.random(),

	Shape = "Ball",

	AssemblyLinearVelocity = Vector3.new(math.random(), math.random(), math.random()),

	AssemblyAngularVelocity = Vector3.new(math.random(), math.random(), math.random()),

	CFrame = CFrame.new(math.random(), math.random(), math.random()) * CFrame.fromEulerAnglesXYZ(math.random(), math.random(), math.random()),
}


local Benchmark = {
	ParameterGenerator = function()

	end;

	Functions = {},
}

for Property, Value in pairs(Properties) do
	Benchmark.Functions[Property] = function()
		local Old = Part[Property]

		for _ = 1, 10 do
			Part[Property] = Value

			Part[Property] = Old
		end
	end
end

return Benchmark

That’s it! Save this if you’re a programmer trying to optimize your game.

Thanks for reading ^v^

43 Likes

This is useful! Thank you so much! But now I can make the laggiest game on roblox!! HAHAHA

2 Likes

This is interesting.
Did anyone else expect CastShadow to be higher up on the list?

  • yes
  • n/a

0 voters

This is the cost of changing the property, not of the cast shadow itself.

4 Likes

Suprises me to see CFrame being more expensive than setting Position and Orientation separately.

1 Like

This is from 2017, but is it still applicable and if so don’t these results contradict what this is saying: Event that fires when rendering finishes - #19 by zeuxcg

Only very very barely. Setting both of those properties in sequence is about 2x as expensive as setting CFrame.

1 Like

CFrame recalculates geometry, so it should make sense that it’s the most expensive property. Even before this data, myself and other developers have known for a very long time that CFrame is to be avoided when possible.

Also, that post doesn’t debate it since it’s not relative to other properties.

tl;dr you can’t argue data.

Most likely this has been implemented by now:

If in doubt, use BulkMoveTo.

Like you said aren’t these measurements calculating the cost of changing the property and not how it affects the environment? Shown below.

1 Like

Correct… and it’s in the title of the post.

I realize that. Here is the post for reference:

Your results show CFrame taking the most time, but that contradicts what the post in the image is saying.

You also stated this in response to my first reply, but saying this again contradicts what you said earlier to someone else:

The above quote would be the same thing as saying “this is the cost or changing the CFrame property not the recalculation of the geometry itself.”

So I’m assuming these results aren’t purely the speed of just changing the property? Can you explain the difference between what zeuxcg is saying and what your results are measuring?

Geometry calculation happens immediately when modifying the property. A CFrame modification is the geometry recalculation.

CastShadow is a boolean that affects whether the separate render thread will show a shadow, making it not immediate.

Again, you cannot argue hard data, so I’m not really sure what you’re getting at here. There really is nothing to disagree with, especially since you can test it yourself with the benchmark file I provided.

I think the main Lua thread is currently intertwined with the render thread, not separate. Parallel Luau will allow for Lua states that aren’t on the main thread.

Have they? I’ve never avoided using CFrame because of a 21 microsecond duration.

Actually… You can. There could be a number of issues going on here. Perhaps your PC is slower than other computers at intervals, or maybe setting the parent ten times repeatedly is much slower than setting it just once. The properties you’ve set them to don’t even equal each other (you’ve set reflectance to 1 but transparency to 0.5.)

No offense, but this is the most pointless micro-optimisation I’ve seen so far on the dev forum.

4 Likes

This is a really crappy way of measuring the performance impact of changing a parts property. There are wayyyy to many variables that can change the outcome that the guy above me said:

Also you can argue your “hard” data since it isn’t even reliable.

At the end of the day don’t change anything you were doing because of the “resource” because it is more useless than a white crayon.

1 Like

Microseconds does not mean micro-optimization, since repeating these operations repeatedly in one frame will drop framerate consistently and notably. These aren’t of use to you if you’re intentions are to work on simpler games that don’t use per-frame calculations.

Some crucial examples in my experience:

  • Custom animation handler; I had to optimize CFrame calculations per-frame to prevent lag issues with additive animation
  • Hitboxes; it was recommend to me by loleris a while back that custom hitboxes should not have a CFrame operation per-hitbox-part, but rather, it should be a simulated rig with only one CFrame operation per frame
  • Procedural map animation; Using a combination of depth-based truncation and MeshPart application, I saved a very large number of frames on a map that has more moving parts than static.

Expanding upon the CFrame operation, do realize that changing that property recalculates geometry; this forces the engine to update both the render and the collision cells. CFrame is more expensive than just doing position or orientation (as one or the other) since it’s a 4x4 matrix calculation.

Here are some demo places changing a part’s property a very high number of times per frame. The first one uses CFrame, other uses Transparency. No other differences.

CFrameDemo.rbxl (34.5 KB)
TransparencyDemo.rbxl (34.4 KB)

A micro-optimization would be something silly like replacing pairs with ipairs, since while it “saves” something, it doesn’t actually do anything. ( cc: @mostbootifulgirlever )

As a side note, no, my computer is fine.

If you don’t take my word for it, I can call over @PoptartNoahh to back me up here, since he has more experience with experimenting on the platform.

3 Likes

if you optimize your code by a few micro seconds that is a micro-optimization.

Literally basic optimization practices which don’t change how useless this “resource” is.

What do you even mean by “recalculates geometry”?

Clearly you have no goddamn idea on what the hell you are saying. At this point your just saying words to sound smart. What is a render and collision cell?

Also I’m sure a 4x4 matrix calculation should be easy enough for any pc’s CPU to calculate multiple times per frame without any lag.

ok?

He doesn’t need to back you up since everything your saying is wrong.


You make a lot of good resources and I use them all the time but this one’s a miss.

3 Likes

image

That’s his response, but anyways,

A render/collision cell is just that – a portion that is being rendered or collision-calculated. These are the parts of the game that connect to make, y’know, the whole thing.

Not if it’s many times per frame.

When your frame rate is lower by, let’s say, 10 FPS, that means your frame times are increased by a few milliseconds per-frame.

Again, you may check out my demos:

If you find no use of this resource, that’s your problem. However, it’s useful to developers such as myself that make many calculations per-frame.

It’s not single micro-second saved, it’s the thousands saved. It’s the same reason somebody should cull instead of destroy many times per frame.


Side note: A common definition of a micro-optimization is one that saves less than one microsecond of frame time, since it makes no difference. Typically, 10-20 is when it makes a difference when done many times per frame.

I’m not sure how your benchmarking plugin works, but wouldn’t this cache the result of the matrix multiplication result so when you iteratively set it there is no matrix multiplication actually happening.

So what you are measuring is just the “render and collision cells” thing? I feel like this measurement wouldn’t be very consistent across all devices or wouldn’t be a very good general measurement.

Note: might also be beneficial to tell what each measurement is measuring exactly because that would be more helpful. For example, people might not have known about the “render and collision cells” thing for CFrame just as I did not.

3 Likes