#Massive performance inefficiency in baking code

1 messages · Page 1 of 1 (latest)

lone latch
#

Files:
Unity.Entities.Hybrid - BakingUtility.cs static void PreprocessBake (line 103)

settings.BakingSystemFilterSettings which involves virtual method call is called in a loop per every system type. Can improve performance by caching in a local variable before going through the loop.

Next:
Unity.Entities.Hybrid - BakedEntityData.cs public void ApplyBakeInstructions (line 428)

In a loop at line 716 which goes over every single bake component (can count in several thousands depending on how big subscene is) - every single baker instance gets recalculated for it's enabled state, even though result will be the same each time.

Will **MASSIVELY **improve performance by moving this code outside of loop.

#

BakingUtility.cs
Before

            if (settings.BakingSystemFilterSettings != null)
            {
                for (var i = systemTypes.Count - 1; i >= 0;  i--)
                {
                    if (!settings.BakingSystemFilterSettings.ShouldRunBakingSystem(systemTypes[i]))
                        systemTypes.RemoveAt(i);
                }
            }

After

            var bakingSystemFilterSettings = settings.BakingSystemFilterSettings;
            if (bakingSystemFilterSettings != null)
            {
                for (var i = systemTypes.Count - 1; i >= 0;  i--)
                {
                    if (!bakingSystemFilterSettings.ShouldRunBakingSystem(systemTypes[i]))
                        systemTypes.RemoveAt(i);
                }
            }
#

BakedEntityData
Before

                    // bake new and changed components
                    foreach (var component in instructions.BakeComponents)
                    {
                        var instanceID = component.ComponentID;

                        _GameObjectToEntity.TryGetValue(component.GameObjectInstanceID, out var entity);
                        if (!_EntityManager.Exists(entity))
                            Debug.LogError(
                                $"Baking entity that doesn't exist: {entity} GameObject: {component.GameObjectInstanceID} Component: {component}",
                                (GameObject) Resources.InstanceIDToObject(component.GameObjectInstanceID));

#if UNITY_EDITOR
                        if (bakingSettings != null && bakingSettings.BakingSystemFilterSettings != null)
                        {
                            BakerDataUtility.ApplyAssemblyFilter(bakingSettings.BakingSystemFilterSettings);
                        }
#endif

After

#if UNITY_EDITOR
                    if (bakingSettings != null)
                    {
                        var bakingSettingsBakingSystemFilterSettings = bakingSettings.BakingSystemFilterSettings;
                        if (bakingSettingsBakingSystemFilterSettings != null)
                        {
                            BakerDataUtility.ApplyAssemblyFilter(bakingSettingsBakingSystemFilterSettings);
                        }
                    }
#endif

                    // bake new and changed components
                    foreach (var component in instructions.BakeComponents)
                    {
#

@dawn monolith I really hope those changes will be reviewed, because it makes it nearly impossible to put any slightly expensive logic inside IEntitiesPlayerSettings.GetFilterSettings without using a fork.

#

My use case for IEntitiesPlayerSettings.GetFilterSettings is detecting whether currently baked subscene is Build/Editor, which involves going through World.All and checking if their BakingSystem contains IsBuildingForPlayer flag.

Without my changes above - it will be invoked BakingSystemCount * 2 + BakedComponent * 2 times.
With my changes above - it will be invoked 2 times per whole subscene Bake.

dawn monolith
#

forwarded to slack; i don't know too much about baking myself

ruby wolf
#

Looking into it adding it in an upcoming entities release.