-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
High performance sorted queries #13464
Comments
This is a follow-up to #1470. The other thing that this opens up is efficiently querying (using dynamic queries only, since enum variants aren't types) for enum variants. If we can store tables in a sorted form, requesting all |
First of all, thanks for the issue! I'd like to go through the parts of your suggested solution:
On the example itself (other than the already presented issues above):
|
// A, B
A(0), B
A(4), B
A(5), B
// A, B, C
A(1), B, C
A(2), B, C
A(3), B, C And you want to sort by
If you want different sorts in different systems. You will get dense iteration across
I don't think you actually understand the difference between these.
That is another reason why it has |
I've updated the seek example to be more flexible. |
On |
|
|
3./4./5. Most improvements to |
With queries as entities queries can have row polymorphism like everything else that's at an ECS level. This means caching is no longer limited to either:
Query entities can have different components for whatever caches they need. Aside from sort caches they will need other cache structures as we add new features. Two things that come to mind:
I would not worry about queries as entities as they're one of the prerequisite/accompanying features for relations and the sort cache can be refactored when they land. |
Another question I have about the final API example: |
This will either remove the existing API or exist along side it.
This sounds like an esoteric misfeature. How would a user know exactly which subset of items they would want sorted in the first place? There are zero guarantees about iteration order.
There should be no single use vectors.
If |
F.e. if we want to sort the children of an entity. The |
That's not a subset of entities in a query that's mapping an entity list. Which is at best niche because
|
When should the command be executed? If it's executed right away and reorders the The logical conclusion is that the reordering of the table must happen right before the system that requires the sort runs (or after the last mutable access, but its impossible to know when that would be). After thinking about it, I think there are 3 options that allow for dense, sorted iteration:
|
In the next sync point. So basically the first run would be without dense iteration, the second run will need to rebuild the sort cache again and every run after that will be dense. (Until you have a mutation which will start this whole process again) |
Hi! If indexes described here #1205, are implemented at a point, they could also resolve the sorted queries feature.
|
@mcatanzariti I fail to see how indices are anything but orthogonal here. Specifically indices do not allow for dense cache friendly iteration. An indirection has to be resolved every time. The Ergonomics are also far worse from looking at the issue. |
@BenjaminBrienen Please give motivation when adding labels like Needs Design & Contentious to issues. This issue doesn't just describe a complete design of the feature for bevy but this feature is already implemented in another ECS so I'm removing that label. I'm not seeing how this is contentious either. |
Ok. I gave it that status because it didn't have a status and it seemed like there was a lot of uncertainty in what the work should look like. I gave it the other label because the long discussion seemed like it fit the description of "has nontrivial implications". Please assign it a better status if you like. |
It's not really |
I actually disagree. While this feature has been implemented in another ECS, I think Bevy can and should make its own considerations and decisions when implementing such a feature; so that it makes sense in both Bevy and Rust contexts. |
If there is things you wish to add identify and describe them. Like I already have with the
Please identify and describe the issue.
Please describe a design you think is better. |
First, I would say that I think these labels to invite discussion, and to remove them I find akin to saying "we no longer need to think about these aspects". I'd prefer to foster discussion rather than shut it down! I'll write up my technical points sometime soon. |
There's nothing stopping you from discussing an already complete design. The thing I don't invite is:
These things create endless discussion for the sake of discussion & waste peoples energy with no productive influence on designs or implementations. |
I already had some technical thoughts in mind when I initially stated my disagreement, but I did not identify them; exactly because I did not want to waste your and any readers time and wanted to get it/phrase it right first before reengaging! For your second point, I do not quite understand what you are referring to with "imagined hypotheticals". |
An example of this would be "What if they want a custom sorting algorithm instead of the one we provide". This is a purely abstract feature with a person trying to accomplish something absent. These usually fail to examine if people would ever want to do this in the first place or if it's something that would be useful to do at all. When you do examine these they quickly fall apart. For example different sorting algorithms usually pair well with different data structures. Since the data structure of the ECS is fixed I would find this suggestion dubious. This kind of strategy tries to accommodate uses cases by allowing for every use case imaginable & hoping the use cases that actually exist are covered. |
I don't feel this example illustrates your point well, because different sorting algorithms (as in glidesort, pdqsort, radixsort, etc.) can fit different types of data and patterns in the order of that data, and less what data structure this data is from. As long as the user decides what data to store, and a slice can be formed with that data, then passing a custom sort algorithm as a function on top of a cmp function could make sense. That is separate from these questions: The above is debatable, and the value/usefulness of some ideas/the very discussion of them can be rather subjective. That being said, we are getting off-topic. While we may disagree, I don't think anyone is trying to create a bad end result! |
I feel you've demonstrated my point even better. You are humoring an idea without users in mind solely for the sake of even more API coverage for what is an even more niche scenario.
That's not the issue here. These kinds of discussions try to create perfect results first time in one cycle which is not a sustainable way to develop. |
We are talking past each other. By saying "it could make sense", I do not mean "we should do this!" I am saying that I respect that it could be useful, however to actually include it depends on whether it fits with what Bevy is trying to do. In this example, my reasoning is:
I'm not saying we have to create perfect results the first time, I am trying to say that deciding not to do/account for something is also part of design. I do not wish to continue this tangent. It seems we have different philosophies and are not likely to agree. Let us return to technical conversation. |
On to questions about what this design intends to do: I. II. III. IV. V. VI.
A closure being stateful does not guarantee non-determinism. To have a function/non-capturing closure does not guarantee determinism. There is no way to guarantee determinism with function types/traits unless you know their implementation beforehand, how does the cache here deal with this? (This ties in with question V. above) VII. VIII. On the seek portion: IX. |
I. Yes II. Doesn't matter & is irrelevant. Any further optimization or customization should be done in a follow up. III. That's the whole point of opting out of table sorting & using stable sorts. IV. This is well beyond design and into implementation details now. Change detection cannot report this. Archetype level change detection is needed. Either way the V. That is user error. VI. That is the best we can do. Do not over engineer. Anything else is user error. VII. No. VIII. Transmutes are not new queries & neither are joins. Joins that iterate over already sorted queries iterate a subset of the matches. Meaning they're still sorted. IX. There is no conflict. If anything it'll be an analogy for users. They're both doing a similar operation. "Seek"ing isn't unique to rust std. Please use numbers we're not Roamns. |
What problem does this solve or what need does it fill?
#13417 adds sorting at an iterator level. These sorts:
What solution would you like?
low..=high
ranges for cache friendly iteration.Final API should look something like this:
What alternative(s) have you considered?
Additional context
Missing prerequisite features:
World::parallel_commands
/make the world command queue thread local by default (needed to allow queries to do2.
).3.
).Not required but helpful missing feature:
The text was updated successfully, but these errors were encountered: