Skip to content

Conversation

@ecoskey
Copy link
Contributor

@ecoskey ecoskey commented Jan 14, 2026

Objective

Make query iteration faster, more flexible, and give query terms more control over how to iterate.

This PR implements "chunk-based query lookahead". Instead of checking the conditions for each row row-wise, we now check them column-wise, iterating forward for each term until we find the next contiguous "chunk" of valid rows. By passing the chunk returned by each query term to the next one, we can gradually narrow down our search area, like if we were short-circuiting in a row-wise check.

This works fine for normal query iteration (and is even faster by default in some cases!), but the main point is it gives query terms more control over how they iterate. In particular, this pattern is perfect for searching in something like a segment tree! The goal is for custom query terms (and changed detection eventually!) to be able to greatly speed up iteration where they need to.

It also might******* be more likely to auto-vectorize plain condition checking, there were vectorized loops in some of the asm dumps but I wasn't able to verify that it was condition checking in particular.

Solution

  • move IS_ARCHETYPAL onto WorldQuery
  • move all conditional logic into WorldQuery::matches, leaving QueryFilter empty, and
    removing the Option wrapper from QueryData::fetch.
  • add WorldQuery::find_table_chunk and find_archetype_chunk to let query terms determine
    if/how to seek ahead in the query.
  • rewrite QueryIter::fold/for_each to use chunk-based iteration.

NOTE: I had some strange performance issues with QueryIter::next, so I left it as-is for now. I saw as much as a 50% performance hit in some benchmarks, and I was able to (mostly) fix it, but at the cost of a similar hit to for_each. It feels like a weird bug though, so it seems worth coming back to eventually.

Testing

  • Ran examples

  • Ran benchmarks:

  • none_changed_detection: 10-20% faster or no change vs main

  • few_changed_detection: 40-55% faster vs main

  • all_changed_detection: ~20% faster vs main for table iteration, ~20% slower for sparse (that feels like a bug, will investigate)

  • iter_simple: generally no change, 15% faster for wide_sparse_set, 3-4% slower for
    foreach_hybrid and par_hybrid

  • iter_frag: generally no change, a few were faster by 5-7% and a few were slower by 5-10%

  • heavy_compute: no change vs main

Needs real world testing! I don't have a good representative benchmark myself.

Future Work

  • implement a fast wide segment tree for change ticks, and implement proper lookahead for Added and Changed
  • look into tracking "last-checked" ranges for each query term, so work during lookahead doesn't get lost/redone.
  • opt-in change ticks (WIP)
  • add lookahead to Query::next
  • controversial: after this change we could totally merge the two generics on Query into one

@ecoskey ecoskey changed the title QueryData/QueryFilter refactors, and query lookahead QueryData/QueryFilter refactors and query lookahead Jan 14, 2026
@ecoskey ecoskey added A-ECS Entities, components, systems, and events C-Performance A change motivated by improving speed, memory usage or compile times S-Needs-Benchmarking This set of changes needs performance benchmarking to double-check that they help S-Needs-Review Needs reviewer attention (from anyone!) to move forward D-Complex Quite challenging from either a design or technical perspective. Ask for help! S-Needs-SME Decision or review from an SME is required and removed S-Needs-Benchmarking This set of changes needs performance benchmarking to double-check that they help labels Jan 14, 2026
@ecoskey ecoskey added the M-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide label Jan 14, 2026
@alice-i-cecile alice-i-cecile added X-Controversial There is active debate or serious implications around merging this PR M-Release-Note Work that should be called out in the blog due to impact labels Jan 14, 2026
@github-actions
Copy link
Contributor

It looks like your PR has been selected for a highlight in the next release blog post, but you didn't provide a release note.

Please review the instructions for writing release notes, then expand or revise the content in the release notes directory to showcase your changes.

@alice-i-cecile
Copy link
Member

controversial: after this change we could totally merge the two generics on Query into one

No thanks 😅 I think this approach is clearer, and I really don't want to break user code that badly.

@alice-i-cecile
Copy link
Member

I'd be very interested in seeing some rendering benchmarks for this too!

@ecoskey
Copy link
Contributor Author

ecoskey commented Jan 14, 2026

controversial: after this change we could totally merge the two generics on Query into one

No thanks 😅 I think this approach is clearer, and I really don't want to break user code that badly.

Yeah, I thought not lol :)

I'd be very interested in seeing some rendering benchmarks for this too!

Will do! I've been meaning to get one of the big glTF scenes set up locally to test AssetChanged perf for materials. I don't have a sizable real-world ECS workload to test this on though unfortunately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-ECS Entities, components, systems, and events C-Performance A change motivated by improving speed, memory usage or compile times D-Complex Quite challenging from either a design or technical perspective. Ask for help! M-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide M-Release-Note Work that should be called out in the blog due to impact S-Needs-Review Needs reviewer attention (from anyone!) to move forward S-Needs-SME Decision or review from an SME is required X-Controversial There is active debate or serious implications around merging this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants