1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//! A "packed archetype" storage model.
//!
//! Any combination of types of components can be attached to each entity
//! in a [`World`](super::world::World). Storing the (potentially unique)
//! set of component values for each entity in a manner which is efficient
//! to search and access is the responsibility of the ECS libary.
//!
//! Legion achieves this via the use of "archetypes". Archetypes are a
//! collection of entities who all have exactly the same set of component
//! types attached. By storing these together, we can perform filtering
//! operations at the archetype level without needing to ever inspect each
//! individual entity. Archetypes also allow us to store contiguous and
//! ordered arrays of each component. For example, all `Position` components
//! for all entities in an archetype are stored together in one array, and
//! can be returned from queries as a slice. All component arrays for an
//! archetype are stored in the same order and are necessarily the same
//! length, allowing us to index them together to access the components for
//! a single entity.
//!
//! Because these components are stored contiguously in memory, iterating
//! through the components in an archetype is extremely performant as
//! it offers perfect cache locality. By storing each component type in
//! its own array, we only need to access the memory containing components
//! actually reqested by the query's view (see the [`query`](crate::query)
//! module).
//!
//! One of the disadvantages of archetypes is that there are discontinuities
//! between component arrays of different archetypes. In practise this causes
//! approximately one additional L2/3 cache miss per unique entity layout that
//! exists among the result set of a query.
//!
//! Legion mitigates this by conservatively packing archetype component
//! slices next to each other. A component slice is considered eligible
//! for packing if its components have remained stable for some time (i.e no
//! entities have been added or removed from the archetype recently) and
//! an estimate of potential saved cache misses passes a "worthwhile"
//! threshold.
//!
//! By default, legion will pack component slices in the order in which
//! the archetypes were created. This matches the order in which queries will
//! attempt to access each slice. However, most queries do not access all
//! archetypes that contain a certain component - more likely they will skip
//! past many archetypes due to other filters (such as only being interested
//! in archetypes which also contain another specific component).
//!
//! We can provide hints to a world about how it should pack archetypes by
//! declaring groups with the world's [options](super::world::WorldOptions)
//! which can be provided while constructing the world. Component groups can be
//! used to accelerate the largest and most common queries by optmizing the data
//! layout for those queries.
//!
//! Each component type in a world may belong to precisely one group. A group is
//! a set of components which are frequently queried for together. Queries which
//! match a group will not suffer from performance loss due to archetype
//! fragmentation.
//!
//! Each group implicitly also defines sub-groups, such that the group
//! `(A, B, C, D)` also defines the groups `(A, B, C)` and `(A, B)`.
//!
//! Groups are defined before constructing a world and are passed in the world's
//! options.
//!
//! ```
//! # use legion::*;
//! // our component types
//! struct A;
//! struct B;
//! struct C;
//!
//! // create a world optimized for cases where (A, B) and/or
//! // (A, B, C) are significant queries.
//! let group = <(A, B, C)>::to_group();
//! let options = WorldOptions {
//!     groups: vec![group],
//! };
//! let world = World::new(options);
//! ```

pub use crate::internals::{
    cons::{ConsAppend, ConsFlatten},
    hash::{ComponentTypeIdHasher, U64Hasher},
    insert::{
        ArchetypeSource, ArchetypeWriter, ComponentSource, ComponentWriter, IntoComponentSource,
        IntoSoa, UnknownComponentWriter,
    },
    storage::{
        archetype::{Archetype, ArchetypeIndex, EntityLayout},
        component::{Component, ComponentTypeId},
        group::{Group, GroupDef, GroupSource},
        index::SearchIndex,
        packed::PackedStorage,
        ComponentIndex, ComponentMeta, ComponentSlice, ComponentSliceMut, ComponentStorage,
        Components, Epoch, MultiMut, PackOptions, UnknownComponentStorage, Version,
    },
};