Skip to content

Commit 249fc6f

Browse files
authored
More doc comments for SparseSet and SparseArray (#23685)
# Objective The design and purpose of `SparseSet` is not immediately obvious, and there is very little documentation explaining it. ## Solution Write more doc comments for `SparseSet` and `SparseArray`.
1 parent 3455503 commit 249fc6f

1 file changed

Lines changed: 82 additions & 6 deletions

File tree

crates/bevy_ecs/src/storage/sparse_set.rs

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,37 @@ use bevy_ptr::{OwningPtr, Ptr};
1010
use core::{cell::UnsafeCell, hash::Hash, marker::PhantomData, num::NonZero, panic::Location};
1111
use nonmax::{NonMaxU32, NonMaxUsize};
1212

13+
/// A map from `I` to `V` implemented as a `Vec<Option<V>>`.
14+
///
15+
/// The key type, `I`, must implement [`SparseSetIndex`]
16+
/// to allow conversion to and from array indexes.
17+
///
18+
/// This supports fast O(1) lookups, since they are simple
19+
/// array indexing operations with no calculations.
20+
///
21+
/// However, it may use a lot of excess memory if the
22+
/// values are large or the set is sparsely populated.
1323
#[derive(Debug)]
1424
pub(crate) struct SparseArray<I, V = I> {
1525
values: Vec<Option<V>>,
1626
marker: PhantomData<I>,
1727
}
1828

19-
/// A space-optimized version of [`SparseArray`] that cannot be changed
20-
/// after construction.
29+
/// A map from `I` to `V` implemented as a `Box<[Option<V>]>`.
30+
///
31+
/// This uses less space than [`SparseArray`] because it does not
32+
/// need to store both length and capacity,
33+
/// but it cannot be changed after construction.
34+
///
35+
/// The key type, `I`, must implement [`SparseSetIndex`]
36+
/// to allow conversion to and from array indexes.
37+
///
38+
/// This supports fast O(1) lookups, since they are simple
39+
/// array indexing operations with no calculations.
40+
///
41+
/// However, it may use a lot of excess memory if the
42+
/// values are large or the set is sparsely populated.
43+
2144
#[derive(Debug)]
2245
pub(crate) struct ImmutableSparseArray<I, V = I> {
2346
values: Box<[Option<V>]>,
@@ -445,22 +468,75 @@ impl Drop for ComponentSparseSet {
445468
}
446469
}
447470

448-
/// A data structure that blends dense and sparse storage
471+
/// A map from `I` to `V` that combines dense and sparse storage.
472+
///
473+
/// This is implemented as a sparse array mapping keys to dense indexes,
474+
/// plus dense arrays of indexes and keys.
475+
///
476+
/// The key type, `I`, must implement [`SparseSetIndex`]
477+
/// to allow conversion to and from array indexes.
449478
///
450-
/// `I` is the type of the indices, while `V` is the type of data stored in the dense storage.
479+
/// This supports fast O(1) lookups, since they consist of one array index to map
480+
/// the key to a dense index, followed by a second array index to find the value.
481+
///
482+
/// This may use a lot of excess memory if the set is sparsely populated,
483+
/// since it stores an empty entry for each key.
484+
///
485+
/// Compared to a simple `Vec<Option<V>>`,
486+
/// the dense storage of values takes less memory when `V` is large,
487+
/// although the overhead of tracking which entries have values
488+
/// may make it larger when `V` is small or the set is densely populated.
451489
#[derive(Debug)]
452490
pub struct SparseSet<I, V: 'static> {
491+
/// The mapping from dense index to value.
492+
///
493+
/// `dense[sparse[k]]` holds the value for `k`.
453494
dense: Vec<V>,
495+
496+
/// The reverse mapping from dense index to key.
497+
///
498+
/// `indices[sparse[k]] == k`
454499
indices: Vec<I>,
500+
501+
/// The mapping from keys to dense indexes.
455502
sparse: SparseArray<I, NonMaxUsize>,
456503
}
457504

458-
/// A space-optimized version of [`SparseSet`] that cannot be changed
459-
/// after construction.
505+
/// A map from `I` to `V` that combines dense and sparse storage.
506+
///
507+
/// This is implemented as a sparse array mapping keys to dense indexes,
508+
/// plus dense arrays of indexes and keys.
509+
///
510+
/// This uses less space than [`SparseSet`] because it does not
511+
/// need to store both length and capacity,
512+
/// but it cannot be changed after construction.
513+
///
514+
/// The key type, `I`, must implement [`SparseSetIndex`]
515+
/// to allow conversion to and from array indexes.
516+
///
517+
/// This supports fast O(1) lookups, since they consist of one array index to map
518+
/// the key to a dense index, followed by a second array index to find the value.
519+
///
520+
/// This may use a lot of excess memory if the set is sparsely populated,
521+
/// since it stores an empty entry for each key.
522+
///
523+
/// Compared to a simple `Vec<Option<V>>`,
524+
/// the dense storage of values takes less memory when `V` is large,
525+
/// although the overhead of tracking which entries have values
526+
/// may make it larger when `V` is small or the set is densely populated.
460527
#[derive(Debug)]
461528
pub(crate) struct ImmutableSparseSet<I, V: 'static> {
529+
/// The mapping from dense index to value.
530+
///
531+
/// `dense[sparse[k]]` holds the value for `k`.
462532
dense: Box<[V]>,
533+
534+
/// The reverse mapping from dense index to key.
535+
///
536+
/// `indices[sparse[k]] == k`
463537
indices: Box<[I]>,
538+
539+
/// The mapping from keys to dense indexes.
464540
sparse: ImmutableSparseArray<I, NonMaxUsize>,
465541
}
466542

0 commit comments

Comments
 (0)