I just confirmed that it’s more efficient to avoid large FilterDescendantInstance tables.
I did a small experiment to test it. I hope this is useful for those looking into this in the future!
Experiment Place
OverlapParamGetTagged.rbxl (73.3 KB)
Experiment
Cost to do a single overlap query:
I created 1024 blue cubes and tagged them with “Blue.” I also grouped them into a folder called BluePoints.
I created 1024 red cubes and tagged them with “Red.” I also grouped them into a folder called RedPoints.
Green ball (Method 1) uses:
local propParam = OverlapParams.new()
propParam.FilterDescendantsInstances = {workspace.BluePoints}
propParam.FilterType = Enum.RaycastFilterType.Include
propParam.MaxParts = math.huge
workspace:GetPartBoundsInRadius(...)
Yellow ball (Method 2) uses:
local propParam = OverlapParams.new()
propParam.FilterDescendantsInstances = game:GetService("CollectionService"):GetTagged("Red")
propParam.FilterType = Enum.RaycastFilterType.Include
propParam.MaxParts = math.huge
workspace:GetPartBoundsInRadius(...)
Result
I ran the query 1000 times and took the average:
- Method 1 (Green ball): ~86,527 ns
- Method 2 (Yellow ball): ~180,597 ns
This is around a 2.1x increase in time when using :GetTagged().
Creating the OverlapParam:
I also wrote some code to check how fast it is to instantiate the OverlapParam.
local startTime = os.clock()
local overlapCast1 = OverlapParams.new()
overlapCast1.FilterDescendantsInstances = {workspace.RedPoints}
overlapCast1.FilterType = Enum.RaycastFilterType.Include
overlapCast1.MaxParts = math.huge
print(sp.Name, "Overlap1 created, took", os.clock() - startTime)
local startTime = os.clock()
local overlapCast2 = OverlapParams.new()
overlapCast2.FilterDescendantsInstances = game.CollectionService:GetTagged("Red")
overlapCast2.FilterType = Enum.RaycastFilterType.Include
overlapCast2.MaxParts = math.huge
print(sp.Name, "Overlap2 created, took", os.clock() - startTime)
Output log
YellowBall Overlap1 created, took 0.000008399947546422482
YellowBall Overlap2 created, took 0.000542099995072931
GreenBall Overlap1 created, took 0.000007299997378140688
GreenBall Overlap2 created, took 0.0003494000411592424
Overlap2 ( :GetTagged() ) took ~349,400-542,100 ns to create, while Overlap1 ( {folder} ) took ~7,300-8,400 ns to create. The average time 445,750 ns for overlap2 and 7,850 ns for Overlap1. This is nearly a 57x increase in time.
Same experiment but with fewer parts
I re-ran the experiment with 192 parts each instead of 1024. Roblox’s runtime initialization is strange, and the numbers will go to different values each time depending on a random order. Overall, the disparity is still present in most initializations.
- Method 1 (Green ball): ~60830 ns (averaged)
- Method 2 (Yellow ball): ~75097 ns (averaged)
This is around a 1.2x increase in time when using :GetTagged().
Output log still shows initialization to be slower for :GetTagged().
YellowBall Overlap1 created, took 0.000008500006515532732
YellowBall Overlap2 created, took 0.0000686999992467463
GreenBall Overlap1 created, took 0.000004100031219422817
GreenBall Overlap2 created, took 0.00005289999535307288
Overlap2 ( :GetTagged() ) took ~52,900-68,700 ns to create, while Overlap1 ( {folder} ) took ~4,100-8,500 ns to create. The average time 60,800 ns for Overlap2 and 6,300 ns for Overlap1. This is nearly a 9.7x increase in time.
Experiment Place
OverlapParamGetTagged.rbxl (73.3 KB)
TL;DR / Conclusion
Don’t use :GetTagged() for overlap param filtering:
-- don't do this
local propParam = OverlapParams.new()
propParam.FilterDescendantsInstances = game:GetService("CollectionService"):GetTagged("Prop")
Just organize your objects into a folder/model and pass the model itself into the filter:
-- do this!
local propParam = OverlapParams.new()
propParam.FilterDescendantsInstances = {workspace.Map.Props}
OverlapParams.new() is generally slower when you use :GetTagged() for FilterDescendantsInstances. The difference is 9.7x - 57x increase in time for 192 - 1024 parts.
workspace:GetPart…() is generally slower when you use :GetTagged() for FilterDescendantsInstances. The difference is 1.2x - 2.1x increase in time for 192 - 1024 parts.
Note: This applies to more than just :GetTagged(), this is essentially the behavior for many FilterDescendantsInstances instance compared to a single grouped instance.
Extra note: As others have noted here, the improvement is negligible for very small use cases. Does your game really need a 0.1 ms improvement if you’re only going to call it once? For small use cases, organization is better!