#General Feedback on System's Performance

1 messages · Page 1 of 1 (latest)

steep cargo
#

I've been using DOTS for a while now but I'm still not comfortable with it. I wrote this system as a part of my terrain generator and I'd like to hear some feedback. Let me know if I'm doing anything wrong or if I can improve the performance somehow.

I feel like the code gives enough context but a short TLDR; This system is responsible for instantiating new chunk entities around points of interest. The chunks will be used and modified by other systems, this system's scope is just the chunk creation phase.

I'm expecting to iterate over around thousands of chunks every update, which isn't much, but I want it to be as fast as possible.

#
[BurstCompile]
public partial class ChunkCreationSystem : SystemBase
{
    [BurstCompile]
    protected override void OnUpdate()
    {
        EntityCommandBuffer entityCommandBuffer =
            SystemAPI.GetSingleton<BeginSimulationEntityCommandBufferSystem.Singleton>()
                .CreateCommandBuffer(World.Unmanaged);

        TerrainGrid grid = SystemAPI.GetSingleton<TerrainGrid>();

        NativeHashSet<int3> loadedChunks = new NativeHashSet<int3>(0, Allocator.Temp);
        JobHandle chunkFindJob = Entities.WithAll<ChunkPosition>().ForEach((in ChunkPosition chunkPosition) =>
        {
            loadedChunks.Add(chunkPosition.position);
        }).Schedule(Dependency);

        chunkFindJob.Complete();

        JobHandle chunkCreationJob = new ChunkCreationJob
        {
            grid = grid,
            entityCommandBuffer = entityCommandBuffer,
            loadedChunks = loadedChunks
        }.Schedule(Dependency);

        chunkCreationJob.Complete();

        loadedChunks.Dispose(Dependency);
    }
}
#
[BurstCompile]
public partial struct ChunkCreationJob : IJobEntity
{
    public TerrainGrid grid;
    public EntityCommandBuffer entityCommandBuffer;
    public NativeHashSet<int3> loadedChunks;

    [BurstCompile]
    public void Execute(in InterestPoint interestPoint, in LocalToWorld localToWorld)
    {
        int loadDistance = interestPoint.highestDistance;
        int3 interestPosition = grid.GetChunkPosition(localToWorld.Position);

        bool hasBounds = math.all(grid.worldBounds == 0);

        for (int x = -loadDistance; x <= loadDistance; x++)
        for (int y = -loadDistance; y <= loadDistance; y++)
        for (int z = -loadDistance; z <= loadDistance; z++)
        {
            int3 chunkPosition = new int3(x, y, z) + interestPosition;

            if (hasBounds && math.any(chunkPosition >= grid.worldBounds))
            {
                continue;
            }

            if (loadedChunks.Contains(chunkPosition))
            {
                continue;
            }

            loadedChunks.Add(chunkPosition);

            Entity chunkEntity = entityCommandBuffer.CreateEntity();
            entityCommandBuffer.AddComponent(chunkEntity, new ChunkPosition
            {
                position = chunkPosition
            });
        }
    }
}
#

One aspect that I don't like is how I collect the loaded chunk positions into a hashset every update. I'd like to store the collection somewhere and use it between updates but I want to keep the code burstable.
Also, whatever I'm doing with it causes a lot of memory leak warnings

fallen musk
#

first of all - you can't use Temp allocation in job

#

I recommend state.WorldUpdateAllocator instead

#

also, seems like you can early return with hasBounds in your job, instead of checking it in a loop each iteration

patent marsh