Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement world-local component id resolution and complete rewrite of type registration code #23

Merged
merged 13 commits into from
Apr 20, 2024

Conversation

BeanCheeseBurrito
Copy link
Owner

@BeanCheeseBurrito BeanCheeseBurrito commented Apr 16, 2024

This pull request refactors the component registration/lookup behavior to use a world-local array lookup instead of a static field lookup when attempting to resolve component ids. This approach addresses a known issue in multi-world applications where registering components in a different order can cause failed assertions due to id clashing.

Each type is given a unique index that denotes its position in the world-local array. The id for a type will be found at the same array index for all worlds.

public static class Type<T> {
    public static int TypeIndex = Interlocked.Increment(ref Ecs.CacheIndexCount);
}

public struct World {
    public List<ecs_entity_t> Cache; // world.Cache[Type<Position>.TypeIndex]
}
using World a = World.Create();
a.Component<Position>(); // Type index 1 for all worlds
a.Component<Velocity>(); // Type index 2 for all worlds

using World b = World.Create();
b.Component<Mass>(); // Type index 3 for all worlds
b.Component<Position>(); // Type index 1 still
b.Component<Velocity>(); // Type index 2 still

The following is done to determine whether or not a component needs to be registered for a particular world:

  • If the type index is not within the bounds of the world-local array, it is not registered. Grow the array and register the component id at the given type index.
if (index >= world.Cache.Count)
    // Grow array and register id at cache[index].
  • If the type index is within the bounds of the world-local array and the component id occupying its location is 0, it is not registered. Register the component id.
if (world.Cache[index] == 0)
    // Register id at cache[index].

The benchmark results below show decent performance improvements compared to the previous implementation.

Before: (Static Field)

| Method  | EntityCount | Mean     | Error     | StdDev    |
|-------- |------------ |---------:|----------:|----------:|
| TypeTag | 100000      | 8.399 ms | 0.0258 ms | 0.0216 ms |
| IntTag  | 100000      | 4.866 ms | 0.0585 ms | 0.0547 ms |

After: (World-Local Array)

| Method  | EntityCount | Mean     | Error     | StdDev    |
|-------- |------------ |---------:|----------:|----------:|
| TypeTag | 100000      | 7.150 ms | 0.0334 ms | 0.0296 ms |
| IntTag  | 100000      | 4.861 ms | 0.0365 ms | 0.0323 ms |

@BeanCheeseBurrito BeanCheeseBurrito changed the title Implement world-local component id resolution Implement world-local component id resolution and complete rewrite of type registration code Apr 18, 2024
@BeanCheeseBurrito
Copy link
Owner Author

Further performance improvements from removing unnecessary string argument from Type<T>.Id() function.
Type<T>.Id(ecs_world_t*, string?) -> Type<T>.Id(ecs_world_t*)

| Method  | EntityCount | Mean     | Error     | StdDev    |
|-------- |------------ |---------:|----------:|----------:|
| TypeTag | 100000      | 5.456 ms | 0.0339 ms | 0.0300 ms |
| IntTag  | 100000      | 4.723 ms | 0.0319 ms | 0.0298 ms |

@BeanCheeseBurrito
Copy link
Owner Author

Adding aggressive inlining to id lookup functions and adding a SuppressGCTransition attribute to the ecs_get_binding_ctx function gives even more performance improvements.

| Method              | EntityCount | Mean     | Error     | StdDev    |
|-------------------- |------------ |---------:|----------:|----------:|
| AddRemoveTypeTag    | 100000      | 5.128 ms | 0.0195 ms | 0.0163 ms |
| AddRemoveIntegerTag | 100000      | 4.722 ms | 0.0756 ms | 0.0670 ms |

@BeanCheeseBurrito BeanCheeseBurrito merged commit 9b3731c into v4 Apr 20, 2024
6 checks passed
@BeanCheeseBurrito BeanCheeseBurrito deleted the v4-world-local-type-ids branch April 30, 2024 06:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant