Some Benchmarks for Bursted Structural Changes in Entities 0.4.0

Entities is in a good state right now with bursted CmdBuffers and now bursted Structural Changes. So I ran my old quick-and-simple benchmark again. When tested against Entities 0.1.1, I get about 1.1x to 1.6x speed up for the following tests (in-editor, leak detection off):

using NUnit.Framework;
using Unity.Collections;
using Unity.Entities;
using UnityEngine;

namespace Tests {

    public class StructuralChangeTests : ECSTestsFixture {

        public struct Tag : IComponentData { }

        [Test]
        public void AddRemoveComp() {
            var archetype = m_Manager.CreateArchetype(typeof(EcsTestData2), typeof(EcsTestData3), typeof(EcsTestData4), typeof(EcsTestData5));
            var entity = m_Manager.CreateEntity(archetype);
            int length = 50000;
            var sw = new SimpleStopWatch(true);
            for (int i = 0; i < length; i++) {
                m_Manager.AddComponentData<Tag>(entity, new Tag());
                m_Manager.RemoveComponent<Tag>(entity);
            }
            Debug.Log($"Add+Remove Tag: {sw.Stop()}");
            sw = new SimpleStopWatch(true);
            for (int i = 0; i < length; i++) {
                m_Manager.AddComponentData<EcsTestData>(entity, new EcsTestData());
                m_Manager.RemoveComponent<EcsTestData>(entity);
            }
            Debug.Log($"Add+Remove Comp: {sw.Stop()}");
        }

        [Test]
        public void CmdBufferTest() {
            var cmdBuffer = new EntityCommandBuffer(Allocator.Temp);
            var archetype = m_Manager.CreateArchetype(typeof(EcsTestData2), typeof(EcsTestData3), typeof(EcsTestData4), typeof(EcsTestData5));
            var entity = m_Manager.CreateEntity(archetype);
            int length = 50000;
            for (int i = 0; i < length; i++) {
                cmdBuffer.AddComponent<Tag>(entity, new Tag());
                cmdBuffer.RemoveComponent<Tag>(entity);
            }
            var sw = new SimpleStopWatch(true);
            cmdBuffer.Playback(m_Manager);
            Debug.Log($"Add+Remove Tag: {sw.Stop()}");
            cmdBuffer.Dispose();
            cmdBuffer = new EntityCommandBuffer(Allocator.Temp);
            for (int i = 0; i < length; i++) {
                cmdBuffer.AddComponent<EcsTestData>(entity, new EcsTestData());
                cmdBuffer.RemoveComponent<EcsTestData>(entity);
            }
            sw = new SimpleStopWatch(true);
            cmdBuffer.Playback(m_Manager);
            Debug.Log($"Add+Remove Comp: {sw.Stop()}");
            cmdBuffer.Dispose();
        }

        [Test]
        public void ArrayOfEntities() {
            var entities = new NativeArray<Entity>(50000, Allocator.TempJob);
            var archetype = m_Manager.CreateArchetype(typeof(EcsTestData2), typeof(EcsTestData3), typeof(EcsTestData4), typeof(EcsTestData5));
            m_Manager.CreateEntity(archetype, entities);
            var sw = new SimpleStopWatch(true);
            for (int i = 0; i < entities.Length; i++) {
                m_Manager.AddComponentData<Tag>(entities[i], new Tag());
            }
            Debug.Log($"Add Tag: {sw.Stop()}");
            sw = new SimpleStopWatch(true);
            for (int i = 0; i < entities.Length; i++) {
                m_Manager.AddComponentData<EcsTestData>(entities[i], new EcsTestData());
            }
            Debug.Log($"Add Comp: {sw.Stop()}");
            sw = new SimpleStopWatch(true);
            for (int i = 0; i < entities.Length; i++) {
                m_Manager.SetComponentData<EcsTestData2>(entities[i], new EcsTestData2());
            }
            Debug.Log($"Set Comp: {sw.Stop()}");
            sw = new SimpleStopWatch(true);
            for (int i = 0; i < entities.Length; i++) {
                m_Manager.RemoveComponent<Tag>(entities[i]);
            }
            Debug.Log($"Remove Tag: {sw.Stop()}");
            sw = new SimpleStopWatch(true);
            for (int i = 0; i < entities.Length; i++) {
                m_Manager.RemoveComponent<EcsTestData>(entities[i]);
            }
            Debug.Log($"Remove Comp: {sw.Stop()}");

            entities.Dispose();
        }

    }

}
using System;
using System.Diagnostics;

public class SimpleStopWatch {

    public string ElapsedTime => String.Format(format, sw.Elapsed.Minutes, sw.Elapsed.Seconds, sw.Elapsed.Milliseconds);

    string format;
    Stopwatch sw;

    public SimpleStopWatch(bool start = false, string format = "{0:00}:{1:00}.{2:000}ms") {
        this.format = format;
        sw = new Stopwatch();
        if (start)
            Start();
    }

    public void Start() {
        sw.Start();
    }

    public string Stop() {
        sw.Stop();
        return ElapsedTime;
    }

}

Sample Results (Entities 0.4.0):

Sample Results (Entities 0.1.1):

I’m using Entities 0.1.1 here because it seems to be faster than the 2 subsequent versions. The same tests ran in 0.2.0 and 0.3.0 are noticeably slower than 0.1.1. (All tested using Unity 2019.3.0f1)

1 Like

How did you run this? Upgrading to 0.4.0 results in this compile error:

error CS0117: ‘ContentBuildInterface’ does not contain a definition for ‘GetPlayerObjectIdentifiersInSerializedFile’

1 Like

While I didn’t encounter that error, I did have to upgrade collection to the latest version too (then restart unity).