Skip to content

Commit 9f9c0a9

Browse files
committed
Optimize duplicate entity checks
Use HashSet for O(N) duplicate entity detection if number of entities exceeds the threshold. This improves performance significantly for larger entity lists.
1 parent c252abd commit 9f9c0a9

File tree

1 file changed

+27
-16
lines changed

1 file changed

+27
-16
lines changed

crates/bevy_ecs/src/world/entity_fetch.rs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -302,14 +302,7 @@ unsafe impl<const N: usize> WorldEntityFetch for &'_ [Entity; N] {
302302
self,
303303
cell: UnsafeWorldCell<'_>,
304304
) -> Result<Self::Mut<'_>, EntityMutableFetchError> {
305-
// Check for duplicate entities.
306-
for i in 0..self.len() {
307-
for j in 0..i {
308-
if self[i] == self[j] {
309-
return Err(EntityMutableFetchError::AliasedMutability(self[i]));
310-
}
311-
}
312-
}
305+
check_duplicate_entities(self)?;
313306

314307
let mut refs = [const { MaybeUninit::uninit() }; N];
315308
for (r, &id) in core::iter::zip(&mut refs, self) {
@@ -364,14 +357,7 @@ unsafe impl WorldEntityFetch for &'_ [Entity] {
364357
self,
365358
cell: UnsafeWorldCell<'_>,
366359
) -> Result<Self::Mut<'_>, EntityMutableFetchError> {
367-
// Check for duplicate entities.
368-
for i in 0..self.len() {
369-
for j in 0..i {
370-
if self[i] == self[j] {
371-
return Err(EntityMutableFetchError::AliasedMutability(self[i]));
372-
}
373-
}
374-
}
360+
check_duplicate_entities(self)?;
375361

376362
let mut refs = Vec::with_capacity(self.len());
377363
for &id in self {
@@ -441,3 +427,28 @@ unsafe impl WorldEntityFetch for &'_ EntityHashSet {
441427
unsafe { self.fetch_mut(cell) }
442428
}
443429
}
430+
431+
/// Checks for duplicate entities in a slice.
432+
#[inline]
433+
fn check_duplicate_entities(entities: &[Entity]) -> Result<(), EntityMutableFetchError> {
434+
const THRESHOLD: usize = 40;
435+
436+
if entities.len() <= THRESHOLD {
437+
for i in 0..entities.len() {
438+
for j in 0..i {
439+
if entities[i] == entities[j] {
440+
return Err(EntityMutableFetchError::AliasedMutability(entities[i]));
441+
}
442+
}
443+
}
444+
} else {
445+
let mut seen = EntityHashSet::with_capacity(entities.len());
446+
for &id in entities {
447+
if !seen.insert(id) {
448+
return Err(EntityMutableFetchError::AliasedMutability(id));
449+
}
450+
}
451+
}
452+
453+
Ok(())
454+
}

0 commit comments

Comments
 (0)