Reproduction Steps
These are the steps used in the place file I provide below:
-
Start play solo, then do the next two steps using scripts:
-
Create new assemblies (10k total parts, each assembly has 20 parts each) using Welds or Motor6Ds. The assemblies should be flat (no hierarchies of joints, all parts should just be connected directly to the root part).
- For my particular use case all the parts have CanQuery, CanTouch, CanCollide, and CastShadow disabled, and CollisionGroup set to a group that cannot collide with anything else.
-
Immediately set the jointsā C1 property (other properties probably work too, but I havenāt tested them). This will cause the performance issue. To cause the freezing issue, the value you set the C1 property to should be really big, like
CFrame.new(10e8, 10e8, 10e8)
. -
(If you havenāt frozen) open the microprofiler, and move your camera around, and observe choppy frame times. Dump some frames and check the RaycastBroadphase label.
To prevent the issues from happening, directly before step 3 do the following (this is step 2.5):
- Call
workspace:Raycast()
orRunService.Stepped:Wait()
Here is the reproduction file with a more in-depth explanation of these things:
assembly_performance_bug.rbxl (40.5 KB)
Expected Behavior
There should be no long-term impact in performance and no freezing when you set Joint.C1 in an assembly that is waiting to be processed. Itās fine if there is a temporary performance difference, like a bunch of extra work being done to process things correctly when you set Joint.C1, but long-term behaviour should be consistent and correct no matter what order assembly processing and property setting are performed in.
Actual Behavior
Performance reduction: An observed large amount of time taken by the RaycastBroadphase label in the microprofiler. Presumably, parts in the assembly are becoming visible to RaycastBroadphase when they were not visible to it previously. Problematic when I have a large numbers of parts in assemblies.
Freezing: With large values of Joint.C1 the game will become completely unresponsive (for long enough for me to give up waiting and kill the process).
I believe this is related to when the āassembleā microprofiler label runs - if Joint.C1 is set before it runs, we have the problems, if Joint.C1 is set after it runs, we are fine. So I view it as being a problem of modifying joints when the assembly is in an āinvalidatedā state.
Workaround
Wait until the assembly has been updated (i.e. āassembleā microprofiler label runs). I think you can rely on it being done before RunService.Stepped, so you can do RunService.Stepped:Wait()
. I believe you can also force it to run immediately by calling workspace:Raycast()
, which works too (though I may be wrong about why).
Issue Area: Engine
Issue Type: Performance
Impact: Moderate
Frequency: Constantly