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

Linear Search in TypeExpression.Matches(IEnumerable) impacts performance for (extremely) wide Archetype Signatures #15

Open
thygrrr opened this issue Jun 6, 2024 · 3 comments
Labels
enhancement Improvement on existing implementation

Comments

@thygrrr
Copy link
Collaborator

thygrrr commented Jun 6, 2024

What:

Optimization potential. In very complex N:N or 1:N / O(N²) cases, type expression searches have a massive impact on runtime. While the shown unit test is a THEORETICAL situation, the same might also apply in normal use.

For example it could also be a case for very complex Worlds (i.e. many, many Archetypes) where new Queries would need to search and match many Archetypes, and Archetypes would need to go and update Queries many times (each time a new Archetype is created or disposed).

Filter Expressions would also drastically benefit from this in complex or degenerate Worlds, not just Query Expressions / Match Expressions.

Repro:

e.g. this code is very slow for 500+ relations (that's a LOT of relations on just one Entity, clearly a degenerate case); and it is slow mostly because of the foreach loop in the while loop, which causes to the order of 500² linear set searches of O(~500) elements each, but the cost is also significant (but in the low milliseconds) without this extra loop.

    [Theory]
    [InlineData(1)]
    [InlineData(2)]
    [InlineData(3)]
    [InlineData(10)]
    [InlineData(100)]
    [InlineData(500)] // takes a long time
    public void DespawnRelationTargetRemovesComponent(int relations)
    {
        using var world = new World();
        
        var subject = world.Spawn();
        
        world.Entity()
            .Add<int>(default, subject)
            .Add(Link.With("relation target"))
            .Spawn(relations)
            .Dispose();
        
        var targets = new List<Entity>(world.Query<int>(subject).Compile());

        var rnd = new Random(1234 + relations);
        foreach (var target in targets)
        {
            subject.Add<int>(Relate.To(target));
        }

        while (targets.Count > 0)
        {
            var target = targets[rnd.Next(targets.Count)];

            Assert.True(subject.Has<int>(target)); // o(n)*o(n)
            
            target.Despawn();
            targets.Remove(target);

            foreach (var remaining in targets)
            {
                Assert.True(subject.Has<int>(remaining)); // o(n)*o(n)*o(n)
            }
            
            Assert.False(subject.Has<int>(target));
        }
    }

Potential Fix

It would be possible to considerably speed this up by providing a MatchSignature property (this is cheap to make) which is the same as the Signature, but also includes the relevant wildcards. e.g. an Archetype with Entity-Entity Relation components will also contain the Match<T>.Entity wildcard for those relations in its MatchSignature even though no such Storage<T> exists; simply as to match queries with Match<T>.Entity in them.

In fact, this may be a simple enhancement with profound impact on scalability for (admittedly degenerate!) relationship scenarios.

Caution

If this is implemented, reverse lookups, such as DespawnDependencies, must have access to a non-commutative means of matching; because commutative matching will not work with these wildcards added to the Signatures.

Possibly a storage list / storage signature / pure signature is easier to build.

This could also speed up matching in general for a infinitesimal, one-time cost during Archetype creation.

@thygrrr thygrrr added the enhancement Improvement on existing implementation label Jun 6, 2024
@thygrrr thygrrr changed the title Linear Search in TypeExpression.Matches(IEnumerable) impactful for wide Archetype Signatures Linear Search in TypeExpression.Matches(IEnumerable) impacted by wide Archetype Signatures Jun 6, 2024
@thygrrr thygrrr changed the title Linear Search in TypeExpression.Matches(IEnumerable) impacted by wide Archetype Signatures Linear Search in TypeExpression.Matches(IEnumerable) impacts performance for wide Archetype Signatures Jun 6, 2024
@thygrrr
Copy link
Collaborator Author

thygrrr commented Jun 7, 2024

Improved in #16

@thygrrr thygrrr closed this as completed Jun 7, 2024
@thygrrr
Copy link
Collaborator Author

thygrrr commented Jun 8, 2024

No, I was mistaken. This is still alive and kicking, because of how Signature.Contains works (it's not the set contain - it's actually the Linq IEnumerable Contains!)

Only cut it down by ~50%, but that doesn't help with polynomial degree > 2 runtime.

@thygrrr thygrrr reopened this Jun 8, 2024
@thygrrr
Copy link
Collaborator Author

thygrrr commented Jun 8, 2024

Nah, it was actually resolved, but now the linear o(n) runtime is in Signature.Expand() which takes up half of the cost of creating new archetypes (for CRAZY LARGE signatures, averaging lengths of ~500 Match Expressions ... and only when doing this in a CRAZY complex N:M relation web)

Might need to turn the matching logic around somehow. This is tricky, I'll keep you all posted.

@thygrrr thygrrr changed the title Linear Search in TypeExpression.Matches(IEnumerable) impacts performance for wide Archetype Signatures Perf: Linear Search in TypeExpression.Matches(IEnumerable) impacts performance for wide Archetype Signatures Jun 14, 2024
@thygrrr thygrrr changed the title Perf: Linear Search in TypeExpression.Matches(IEnumerable) impacts performance for wide Archetype Signatures Linear Search in TypeExpression.Matches(IEnumerable) impacts performance for extremely wide Archetype Signatures Jun 15, 2024
@thygrrr thygrrr changed the title Linear Search in TypeExpression.Matches(IEnumerable) impacts performance for extremely wide Archetype Signatures Linear Search in TypeExpression.Matches(IEnumerable) impacts performance for (very) wide Archetype Signatures Jun 15, 2024
@thygrrr thygrrr changed the title Linear Search in TypeExpression.Matches(IEnumerable) impacts performance for (very) wide Archetype Signatures Linear Search in TypeExpression.Matches(IEnumerable) impacts performance for (extremely) wide Archetype Signatures Jun 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Improvement on existing implementation
Projects
None yet
Development

No branches or pull requests

1 participant