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
//! A "packed archetype" storage model. //! //! Any combination of types of components can be attached to each entity //! in a [world](../world/struct.World.html). Storing the (potentially //! unique) set of component values for each entity in a manor 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 coherence. 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 module](../query/index.html)). //! //! 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 eligable //! 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 //! and 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](../world/struct.WorldOptions.html) //! 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, }, };