/GetPartBoundsInBox.lua Secret
Created
August 25, 2021 07:08
Performance testing Roblox's new OverlapParams functions.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Workspace = game:GetService("Workspace") | |
local PART_SIZES = { 0, 25, 100, 1000, 5000, 10000 } | |
local hitbox = Workspace:FindFirstChild("Hitbox") | |
local hitboxCf = hitbox.CFrame | |
local hitboxSz = hitbox.Size | |
local start = hitbox.CFrame * CFrame.new(hitbox.Size / 2) | |
local finish = hitbox.CFrame * CFrame.new(-hitbox.Size / 2) | |
local overlap = OverlapParams.new() | |
local region = Region3.new(start.Position, finish.Position) | |
local random = Random.new() | |
for _, size in ipairs(PART_SIZES) do | |
local descendants = {} | |
for _ = 1, size do | |
local newPart = Instance.new("Part") | |
newPart.CFrame = hitbox.CFrame * CFrame.new( | |
hitbox.Size.X * random:NextNumber(-0.5, 0.5), | |
hitbox.Size.Y * random:NextNumber(-0.5, 0.5), | |
hitbox.Size.Z * random:NextNumber(-0.5, 0.5) | |
) | |
newPart.Anchored = true | |
newPart.Size = Vector3.new(2, 2, 2) | |
newPart.Transparency = 0.5 | |
newPart.Color = Color3.fromRGB(255, 255, 255) | |
newPart.Parent = Workspace | |
table.insert(descendants, newPart) | |
end | |
for i = 1, 2 do | |
local useNewApi = i % 2 == 0 | |
-- small wait before we perform benchmark for any expensive operations to finish | |
task.wait(2) | |
-- perform benchmark | |
local start = os.clock() | |
for _ = 1, 100 do | |
if useNewApi then | |
Workspace:GetPartBoundsInBox(hitboxCf, hitboxSz, overlap) | |
else | |
Workspace:FindPartsInRegion3(region) | |
end | |
end | |
print(size, string.format("%0.4fms", (os.clock() - start) * 1000), useNewApi) | |
end | |
-- GC instances | |
for _, part in ipairs(descendants) do | |
part.Parent = nil | |
end | |
task.wait(5) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Similar format results to before, where the first number indicates the amount of parts, second is the amount of milliseconds for 100 API calls, third element is if GetPartBoundsInBox is used (true) or FindPartsInRegion3 is used (false): | |
0 0.1535ms false | |
0 0.3553ms true | |
25 0.1393ms false | |
25 1.7630ms true | |
100 0.0809ms false | |
100 5.3808ms true | |
1000 0.0638ms false | |
1000 61.0919ms true | |
5000 0.0899ms false | |
5000 514.3444ms true | |
10000 0.0638ms false | |
10000 1259.1286ms true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Workspace = game:GetService("Workspace") | |
local PART_SIZES = { 0, 25, 100, 1000, 5000, 10000 } | |
local hitbox = Workspace:FindFirstChild("Hitbox") | |
local hitboxCf = hitbox.CFrame | |
local hitboxSz = hitbox.Size | |
local start = hitbox.CFrame * CFrame.new(hitbox.Size / 2) | |
local finish = hitbox.CFrame * CFrame.new(-hitbox.Size / 2) | |
local overlap = OverlapParams.new() | |
overlap.FilterType = Enum.RaycastFilterType.Whitelist | |
local region = Region3.new(start.Position, finish.Position) | |
local random = Random.new() | |
for _, size in ipairs(PART_SIZES) do | |
local descendants = {} | |
for _ = 1, size do | |
local newPart = Instance.new("Part") | |
newPart.CFrame = hitbox.CFrame | |
* CFrame.new( | |
hitbox.Size.X * random:NextNumber(-0.5, 0.5), | |
hitbox.Size.Y * random:NextNumber(-0.5, 0.5), | |
hitbox.Size.Z * random:NextNumber(-0.5, 0.5) | |
) | |
newPart.Anchored = true | |
newPart.Size = Vector3.new(2, 2, 2) | |
newPart.Transparency = 0.5 | |
newPart.Color = Color3.fromRGB(255, 255, 255) | |
newPart.Parent = Workspace | |
table.insert(descendants, newPart) | |
end | |
-- add a random 25 parts to our FilterDescendantsInstances | |
local filterDescendants = table.create(#descendants) | |
for i = 1, math.min(size, 25) do | |
table.insert(filterDescendants, descendants[i]) | |
end | |
overlap.FilterDescendantsInstances = descendants | |
for i = 1, 2 do | |
local useNewApi = i % 2 == 0 | |
-- small wait before we perform benchmark for any expensive operations to finish | |
task.wait(2) | |
-- perform benchmark | |
local start = os.clock() | |
for _ = 1, 100 do | |
if useNewApi then | |
Workspace:GetPartBoundsInBox(hitboxCf, hitboxSz, overlap) | |
else | |
Workspace:FindPartsInRegion3(region) | |
end | |
end | |
print(size, string.format("%0.4fms", (os.clock() - start) * 1000), useNewApi) | |
end | |
-- GC instances | |
for _, part in ipairs(descendants) do | |
part.Parent = nil | |
end | |
task.wait(5) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Similar format results to before, where the first number indicates the amount of parts, second is the amount of milliseconds for 100 API calls, third element is if GetPartBoundsInBox is used alongside FilterDescendantsInstances set to 25 parts (true) or FindPartsInRegion3 is used (false): | |
0 0.0708ms false | |
0 0.3183ms true | |
25 0.0760ms false | |
25 2.4035ms true | |
100 0.0624ms false | |
100 7.2634ms true | |
1000 0.1041ms false | |
1000 81.3375ms true | |
5000 0.0742ms false | |
5000 765.0460ms true | |
10000 0.0678ms false | |
10000 1717.8362ms true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Workspace = game:GetService("Workspace") | |
local PART_SIZES = { 0, 25, 100, 1000, 5000, 10000 } | |
local hitbox = Workspace:FindFirstChild("Hitbox") | |
local hitboxCf = hitbox.CFrame | |
local hitboxSz = hitbox.Size | |
local start = hitbox.CFrame * CFrame.new(hitbox.Size / 2) | |
local finish = hitbox.CFrame * CFrame.new(-hitbox.Size / 2) | |
local overlap = OverlapParams.new() | |
overlap.MaxParts = 1 | |
local region = Region3.new(start.Position, finish.Position) | |
local random = Random.new() | |
for _, size in ipairs(PART_SIZES) do | |
local descendants = {} | |
for _ = 1, size do | |
local newPart = Instance.new("Part") | |
newPart.CFrame = hitbox.CFrame | |
* CFrame.new( | |
hitbox.Size.X * random:NextNumber(-0.5, 0.5), | |
hitbox.Size.Y * random:NextNumber(-0.5, 0.5), | |
hitbox.Size.Z * random:NextNumber(-0.5, 0.5) | |
) | |
newPart.Anchored = true | |
newPart.Size = Vector3.new(2, 2, 2) | |
newPart.Transparency = 0.5 | |
newPart.Color = Color3.fromRGB(255, 255, 255) | |
newPart.Parent = Workspace | |
table.insert(descendants, newPart) | |
end | |
for i = 1, 2 do | |
local useNewApi = i % 2 == 0 | |
-- small wait before we perform benchmark for any expensive operations to finish | |
task.wait(2) | |
-- perform benchmark | |
local start = os.clock() | |
for _ = 1, 100 do | |
if useNewApi then | |
Workspace:GetPartBoundsInBox(hitboxCf, hitboxSz, overlap) | |
else | |
Workspace:FindPartsInRegion3(region) | |
end | |
end | |
print(size, string.format("%0.4fms", (os.clock() - start) * 1000), useNewApi) | |
end | |
-- GC instances | |
for _, part in ipairs(descendants) do | |
part.Parent = nil | |
end | |
task.wait(5) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Similar format results to before, where the first number indicates the amount of parts, second is the amount of milliseconds for 100 API calls, third element is if GetPartBoundsInBox is used alongside MaxParts set to 1 (true) or FindPartsInRegion3 is used (false): | |
0 0.1057ms false | |
0 0.9415ms true | |
25 0.1370ms false | |
25 1.1478ms true | |
100 0.0670ms false | |
100 2.0912ms true | |
1000 0.0869ms false | |
1000 19.3874ms true | |
5000 0.0662ms false | |
5000 103.2925ms true | |
10000 0.2380ms false | |
10000 213.2466ms true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Workspace = game:GetService("Workspace") | |
local PART_SIZES = { 0, 25, 100, 1000, 5000, 10000 } | |
local hitbox = Workspace:FindFirstChild("Hitbox") | |
local start = hitbox.CFrame * CFrame.new(hitbox.Size / 2) | |
local finish = hitbox.CFrame * CFrame.new(-hitbox.Size / 2) | |
local overlap = OverlapParams.new() | |
local region = Region3.new(start.Position, finish.Position) | |
local random = Random.new() | |
for _, size in ipairs(PART_SIZES) do | |
local descendants = {} | |
for _ = 1, size do | |
local newPart = Instance.new("Part") | |
newPart.CFrame = hitbox.CFrame * CFrame.new( | |
hitbox.Size.X * random:NextNumber(-0.5, 0.5), | |
hitbox.Size.Y * random:NextNumber(-0.5, 0.5), | |
hitbox.Size.Z * random:NextNumber(-0.5, 0.5) | |
) | |
newPart.Anchored = true | |
newPart.Size = Vector3.new(2, 2, 2) | |
newPart.Transparency = 0.5 | |
newPart.Color = Color3.fromRGB(255, 255, 255) | |
newPart.Parent = Workspace | |
table.insert(descendants, newPart) | |
end | |
for i = 1, 2 do | |
local useNewApi = i % 2 == 0 | |
-- small wait before we perform benchmark for any expensive operations to finish | |
task.wait(2) | |
-- perform benchmark | |
local start = os.clock() | |
for _ = 1, 100 do | |
if useNewApi then | |
Workspace:GetPartsInPart(hitbox, overlap) | |
else | |
Workspace:FindPartsInRegion3(region) | |
end | |
end | |
print(size, string.format("%0.4fms", (os.clock() - start) * 1000), useNewApi) | |
end | |
-- GC instances | |
for _, part in ipairs(descendants) do | |
part.Parent = nil | |
end | |
task.wait(5) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The first number indicates the amount of parts, second is the amount of milliseconds for 100 API calls, third element is if GetPartsInPart is used (true) or FindPartsInRegion3 is used (false): | |
0 0.0778ms false | |
0 0.4018ms true | |
25 0.0913ms false | |
25 6.1577ms true | |
100 0.0825ms false | |
100 21.1336ms true | |
1000 0.0768ms false | |
1000 240.5298ms true | |
5000 0.0632ms false | |
5000 1459.7305ms true | |
10000 0.0665ms false | |
10000 3090.1008ms true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Workspace = game:GetService("Workspace") | |
local PART_SIZES = { 0, 25, 100, 1000, 5000, 10000 } | |
local hitbox = Workspace:FindFirstChild("Hitbox") | |
local hitboxCf = hitbox.CFrame | |
local hitboxSz = hitbox.Size | |
local r = hitboxSz.X | |
local hitboxPos = hitboxCf.Position | |
local overlap = OverlapParams.new() | |
local random = Random.new() | |
for _, size in ipairs(PART_SIZES) do | |
local descendants = {} | |
for _ = 1, size do | |
local newPart = Instance.new("Part") | |
newPart.CFrame = hitbox.CFrame | |
* CFrame.new( | |
hitbox.Size.X * random:NextNumber(-0.5, 0.5), | |
hitbox.Size.Y * random:NextNumber(-0.5, 0.5), | |
hitbox.Size.Z * random:NextNumber(-0.5, 0.5) | |
) | |
newPart.Anchored = true | |
newPart.Size = Vector3.new(2, 2, 2) | |
newPart.Transparency = 0.5 | |
newPart.Color = Color3.fromRGB(255, 255, 255) | |
newPart.Parent = Workspace | |
table.insert(descendants, newPart) | |
end | |
for i = 1, 2 do | |
local useNewApi = i % 2 == 0 | |
-- small wait before we perform benchmark for any expensive operations to finish | |
task.wait(2) | |
-- perform benchmark | |
local start = os.clock() | |
for _ = 1, 100 do | |
if useNewApi then | |
Workspace:GetPartBoundsInRadius(hitboxPos, r, overlap) | |
else | |
Workspace:GetPartBoundsInBox(hitboxCf, hitboxSz, overlap) | |
end | |
end | |
print(size, string.format("%0.4fms", (os.clock() - start) * 1000), useNewApi) | |
end | |
-- GC instances | |
for _, part in ipairs(descendants) do | |
part.Parent = nil | |
end | |
task.wait(5) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I ran these on a Hitbox with size 50, 50, 50 | |
Similar format results to before, where the first number indicates the amount of parts second is the amount of milliseconds for 100 API calls third number is if GetPartBoundsInRadius is used (true) or GetPartBoundsInBox is used (false): | |
0 0.5943ms false | |
0 0.8691ms true | |
25 2.1426ms false | |
25 2.3293ms true | |
100 5.0867ms false | |
100 4.4336ms true | |
1000 47.9035ms false | |
1000 34.5973ms true | |
5000 606.7480ms false | |
5000 637.8543ms true | |
10000 1367.7854ms false | |
10000 997.0864ms true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment