Can someone verify this benchmark?

So I was benchmarking part.CFrame against part:PivotTo and found out that PivotTo is faster from directly setting the property by about 10 times. I don’t believe this is true, and I want to have more types of benchmarks or at least an explanation as to why. While I knew that PivotTo does not fire events for Position or other similar positional properties. I don’t believe the difference should be that big.

Here is the code I used to benchmark, I used the avrg of 1000 calls:

--!strict
--!optimize 2

--Constants
local TEST_AMOUNT = 1000000

--Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--Instances
local TestP = Instance.new("Part",script)

--Instance methods
local PivotTo = TestP.PivotTo

--Modules
--local RawLib = require(ReplicatedStorage.Modules.RawLib)

--Module methods
--local instance_newindex = RawLib.instance_newindex

--Variables
local t = 0

print("Beginning the benchmark with",TEST_AMOUNT,"calls")

for i = 1,TEST_AMOUNT do
	local t1 = os.clock()
	TestP.CFrame = CFrame.new()
	--instance_newindex(TestP,"CFrame",CFrame.identity)
	t += os.clock()-t1
end

print("CFrame avrg:",t/(TEST_AMOUNT*0.001))

t = 0

for i = 1,TEST_AMOUNT do
	local t1 = os.clock()
	TestP:PivotTo(CFrame.new())
	--PivotTo(TestP,CFrame.identity)
	t += os.clock()-t1
end

print("PivotTo avrg:",t/(TEST_AMOUNT*0.001))
1 Like

Yeah seems like it 13~% faster
image

--!strict
--!optimize 2
local part:Part = Instance.new("Part",script)
part.Anchored=true

local t:number = 0

t=0
for i=1,20 do
	local a:number = os.clock()
	for ii=1,9999 do
		part.CFrame=CFrame.identity
	end
	t+=os.clock()-a
end
print(`CFRAME avarage: {t/20}`)

t=0
for i=1,20 do
	local a:number = os.clock()
	for ii=1,9999 do
		part:PivotTo(CFrame.identity)
	end
	t+=os.clock()-a
end
print(`PivotTo avarage: {t/20}`)

Same results.


Normal CFrame is 2.3…
( changed your code a bit )

code
--!strict
--!optimize 2

local TEST_AMOUNT = 10000000

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local TestP = Instance.new("Part",script)

local PivotTo = TestP.PivotTo
local CFrame = CFrame.new

local start = 0

print("Beginning the benchmark with",TEST_AMOUNT,"calls")

start = os.clock()
for i = 1,TEST_AMOUNT do
	local t1 = os.clock()
	TestP.CFrame = CFrame()
end

print(os.clock() - start)

start = os.clock()
for i = 1,TEST_AMOUNT do
	local t1 = os.clock()
	TestP:PivotTo(CFrame())
end
print(os.clock() - start)


it is faster but PivotTo sometimes can FAIL to replicate when people lag (if you move an instance that has its physics updated by the given player such as their character).

I’m pretty sure that’s an issue with all physics replication, as they’re unreliable and unordered because usually they don’t need to be, normally it just replicates again in the next few frames.

Ok, this became even more confusing than it should. On my device in the studio, it is somehow 10 times better (the benchmark in the post). Some people have a 30% performance gain, some only about 10%. I don’t get it at this point

PVInstance:PivotTo() still fires every changed signal on the BasePart you call it on if it has no descendant parts (is this a bug?).
image

It does seem to be slightly faster than setting .CFrame directly though.
image

But really when you need to call PivotTo or set CFrame that many times, you’re likely going to be better off using WorldRoot:BulkMoveTo() and/or welding.

From my other tests, BulkMoveTo barely makes a difference between PivotTo. And most of the expenses actually come not from setting position, and is basically equal if we consider the table writing for BulkMoveTo

If you actually read the documentation for WorldRoot:BulkMoveTo, you can see it says that it’s intended for when you know that moving parts is actually the bottleneck.

Table writing is MUCH faster than indexing and writing a bunch of properties.