Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove redundent information and optimize dynamic allocations in Table #12929

Open
wants to merge 64 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
5564de5
added blob_array
Adamkob12 Apr 5, 2024
7d74489
seperated column into different file
Adamkob12 Apr 5, 2024
f5baf43
implemented ThinArrayPtr, not tested yet
Adamkob12 Apr 5, 2024
8ddf250
defined new Column type, working on adjusting Table
Adamkob12 Apr 6, 2024
ec4fb50
added almost all the methods needed for ColumnWIP, need refactor now …
Adamkob12 Apr 6, 2024
c2aed7d
refactor + cleaning up methods and adding a couple more to ColumnWIP
Adamkob12 Apr 6, 2024
e4bb500
renamed ColumnWIP to Column and deleted previous Column
Adamkob12 Apr 6, 2024
2e7c06c
Revert "renamed ColumnWIP to Column and deleted previous Column"
Adamkob12 Apr 6, 2024
eb51eb6
no errors
Adamkob12 Apr 8, 2024
bb77e01
fixing bugs, passed all tests expcept one
Adamkob12 Apr 9, 2024
572a289
Table::alloc_columns
Adamkob12 Apr 9, 2024
d0b5b9d
fix some warnings
Adamkob12 Apr 9, 2024
dbd477a
checkpoint
Adamkob12 Apr 10, 2024
4809fe0
trying to solve abort (because of double free?) at test `panic_while_…
Adamkob12 Apr 10, 2024
3d09567
fixed double drop in unwind
Adamkob12 Apr 10, 2024
b522b3a
all tests passed
Adamkob12 Apr 10, 2024
2c76208
chipping away at TODOs
Adamkob12 Apr 10, 2024
20285b4
docs
Adamkob12 Apr 11, 2024
3aaebf2
doc nits
Adamkob12 Apr 11, 2024
a20de1a
added benchmark for adding removing a (very) lot of components per en…
Adamkob12 Apr 11, 2024
9c6d229
remove duplicate test
Adamkob12 Apr 11, 2024
6782cc7
clippy
Adamkob12 Apr 11, 2024
1c52357
typos
Adamkob12 Apr 11, 2024
d6467c1
doc tests
Adamkob12 Apr 11, 2024
ddaf16f
ci
Adamkob12 Apr 11, 2024
568cc42
ci
Adamkob12 Apr 11, 2024
9d55340
fixed double free
Adamkob12 Apr 12, 2024
5ef9e54
fix some ci (i think the other is bugged)
Adamkob12 Apr 12, 2024
fb794cc
expand thinarrayptr in debug mode
Adamkob12 Apr 12, 2024
3153f28
docs
Adamkob12 Apr 12, 2024
1c1690e
Merge branch 'main' into remove_lens_and_caps_from_table
Adamkob12 Apr 13, 2024
de25be0
x
Adamkob12 Apr 19, 2024
5732351
Update crates/bevy_ecs/src/storage/thin_array_ptr.rs
Adamkob12 Apr 19, 2024
1d44fdd
x
Adamkob12 Apr 19, 2024
faec660
x
Adamkob12 Apr 19, 2024
0ecff6b
expand add_remove_very_big benchmark
Adamkob12 Apr 19, 2024
8004d80
added ZSTs to add_remove_very_big benchmark
Adamkob12 Apr 19, 2024
ce583c6
checking why test failed
Adamkob12 Apr 19, 2024
8ec9eca
fixed test fail
Adamkob12 Apr 19, 2024
ac9d9f2
docs
Adamkob12 Apr 19, 2024
976c553
merge main into branch
Adamkob12 Apr 19, 2024
2a21b6b
typo
Adamkob12 Apr 19, 2024
abaa9a0
docs
Adamkob12 Apr 19, 2024
96b3e79
Merge branch 'main' into remove_lens_and_caps_from_table
Adamkob12 Apr 19, 2024
7f62022
Update crates/bevy_ecs/src/storage/thin_array_ptr.rs
Adamkob12 Apr 19, 2024
3a13021
added inline
Adamkob12 Apr 19, 2024
96a3602
abort on allocation panic
Adamkob12 Apr 19, 2024
49d1807
x
Adamkob12 Apr 19, 2024
fc8f66f
x
Adamkob12 Apr 19, 2024
e150dca
renamed some methods, fixed some docs
Adamkob12 Apr 21, 2024
451198d
added back some public methods that were removed from Column
Adamkob12 Apr 21, 2024
b5f6ddb
solve merge conflicts
Adamkob12 Apr 21, 2024
cba8158
ci
Adamkob12 Apr 21, 2024
81b47fe
fix edgecase where components wouldn't be dropped when removed
Adamkob12 Apr 21, 2024
4f35607
docs nits
Adamkob12 Apr 21, 2024
494b85a
pub -> pub(crate) in some methods in Table and ThinColumn | docs
Adamkob12 Apr 24, 2024
d44fe5b
Fix ZST components not being dropped, test to make sure
Adamkob12 May 13, 2024
22911a6
docs
Adamkob12 May 13, 2024
fbf6abf
Merge branch 'bevyengine:main' into remove_lens_and_caps_from_table
Adamkob12 May 13, 2024
457b8cc
LMerge remote-tracking branch 'refs/remotes/origin/remove_lens_and_ca…
Adamkob12 May 13, 2024
a109aef
clippy
Adamkob12 May 13, 2024
99826e6
Merge branch 'main' into remove_lens_and_caps_from_table
Adamkob12 May 13, 2024
ed8195b
x
Adamkob12 May 14, 2024
3845074
Merge remote-tracking branch 'refs/remotes/origin/remove_lens_and_cap…
Adamkob12 May 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
87 changes: 87 additions & 0 deletions benches/benches/bevy_ecs/components/add_remove_very_big_table.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#![allow(dead_code)]

use bevy_ecs::prelude::*;
use glam::*;

#[derive(Component, Copy, Clone)]
struct A(Mat4);
Adamkob12 marked this conversation as resolved.
Show resolved Hide resolved
#[derive(Component, Copy, Clone)]
struct B(Mat4);
#[derive(Component, Copy, Clone)]
struct C(Mat4);
#[derive(Component, Copy, Clone)]
struct D(Mat4);
#[derive(Component, Copy, Clone)]
struct E(Mat4);
#[derive(Component, Copy, Clone)]
struct F(Mat4);
#[derive(Component, Copy, Clone)]
struct A2(Mat4);
#[derive(Component, Copy, Clone)]
struct B2(Mat4);
#[derive(Component, Copy, Clone)]
struct C2(Mat4);
#[derive(Component, Copy, Clone)]
struct D2(Mat4);
#[derive(Component, Copy, Clone)]
struct E2(Mat4);
#[derive(Component, Copy, Clone)]
struct F2(Mat4);
#[derive(Component, Copy, Clone)]
struct A3(Mat4);
#[derive(Component, Copy, Clone)]
struct B3(Mat4);
#[derive(Component, Copy, Clone)]
struct C3(Mat4);
#[derive(Component, Copy, Clone)]
struct D3(Mat4);
#[derive(Component, Copy, Clone)]
struct E3(Mat4);
#[derive(Component, Copy, Clone)]
struct F3(Mat4);

pub struct Benchmark(World, Vec<Entity>);

impl Benchmark {
pub fn new() -> Self {
let mut world = World::default();
let mut entities = Vec::with_capacity(10_000);
for _ in 0..10_000 {
entities.push(
world
.spawn((
A(Mat4::from_scale(Vec3::ONE)),
B(Mat4::from_scale(Vec3::ONE)),
C(Mat4::from_scale(Vec3::ONE)),
D(Mat4::from_scale(Vec3::ONE)),
E(Mat4::from_scale(Vec3::ONE)),
A2(Mat4::from_scale(Vec3::ONE)),
B2(Mat4::from_scale(Vec3::ONE)),
C2(Mat4::from_scale(Vec3::ONE)),
D2(Mat4::from_scale(Vec3::ONE)),
E2(Mat4::from_scale(Vec3::ONE)),
A3(Mat4::from_scale(Vec3::ONE)),
B3(Mat4::from_scale(Vec3::ONE)),
C3(Mat4::from_scale(Vec3::ONE)),
D3(Mat4::from_scale(Vec3::ONE)),
E3(Mat4::from_scale(Vec3::ONE)),
))
.id(),
);
}

Self(world, entities)
}

pub fn run(&mut self) {
for entity in &self.1 {
self.0
.entity_mut(*entity)
.insert(F(Mat4::from_scale(Vec3::ONE)));
}

for entity in &self.1 {
self.0.entity_mut(*entity).remove::<F>();
}
}
}
13 changes: 13 additions & 0 deletions benches/benches/bevy_ecs/components/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod add_remove_big_sparse_set;
mod add_remove_big_table;
mod add_remove_sparse_set;
mod add_remove_table;
mod add_remove_very_big_table;
mod archetype_updates;
mod insert_simple;
mod insert_simple_unbatched;
Expand All @@ -14,6 +15,7 @@ criterion_group!(
components_benches,
add_remove,
add_remove_big,
add_remove_very_big,
insert_simple,
no_archetypes,
added_archetypes,
Expand Down Expand Up @@ -49,6 +51,17 @@ fn add_remove_big(c: &mut Criterion) {
group.finish();
}

fn add_remove_very_big(c: &mut Criterion) {
let mut group = c.benchmark_group("add_remove_very_big");
group.warm_up_time(std::time::Duration::from_millis(500));
group.measurement_time(std::time::Duration::from_secs(4));
group.bench_function("table", |b| {
let mut bench = add_remove_very_big_table::Benchmark::new();
b.iter(move || bench.run());
});
group.finish();
}

fn insert_simple(c: &mut Criterion) {
let mut group = c.benchmark_group("insert_simple");
group.warm_up_time(std::time::Duration::from_millis(500));
Expand Down
22 changes: 12 additions & 10 deletions crates/bevy_ecs/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,19 +390,21 @@ impl BundleInfo {
let component_id = *self.component_ids.get_unchecked(bundle_component);
match storage_type {
StorageType::Table => {
let column =
// SAFETY: If component_id is in self.component_ids, BundleInfo::new requires that
// the target table contains the component.
unsafe { table.get_column_mut(component_id).debug_checked_unwrap() };
// SAFETY: bundle_component is a valid index for this bundle
let status = unsafe { bundle_component_status.get_status(bundle_component) };
match status {
ComponentStatus::Added => {
column.initialize(table_row, component_ptr, change_tick);
}
ComponentStatus::Mutated => {
column.replace(table_row, component_ptr, change_tick);
}
ComponentStatus::Added => table.initialize_component(
table_row,
component_id,
component_ptr,
change_tick,
),
ComponentStatus::Mutated => table.replace_component(
table_row,
component_id,
component_ptr,
change_tick,
),
}
}
StorageType::SparseSet => {
Expand Down
1 change: 0 additions & 1 deletion crates/bevy_ecs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,6 @@ mod tests {
.collect::<Vec<_>>(),
&[(e1, A(1), B(3)), (e2, A(2), B(4))]
);

assert_eq!(world.entity_mut(e1).take::<A>(), Some(A(1)));
assert_eq!(
world
Expand Down
35 changes: 25 additions & 10 deletions crates/bevy_ecs/src/query/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -948,9 +948,8 @@ unsafe impl<T: Component> WorldQuery for &T {
) {
fetch.table_components = Some(
table
.get_column(component_id)
.get_column_data_slice(component_id)
.debug_checked_unwrap()
.get_data_slice()
.into(),
);
}
Expand Down Expand Up @@ -1106,11 +1105,19 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> {
&component_id: &ComponentId,
table: &'w Table,
) {
let column = table.get_column(component_id).debug_checked_unwrap();
fetch.table_data = Some((
column.get_data_slice().into(),
column.get_added_ticks_slice().into(),
column.get_changed_ticks_slice().into(),
table
.get_column_data_slice(component_id)
.debug_checked_unwrap()
.into(),
table
.get_column_added_ticks(component_id)
.debug_checked_unwrap()
.into(),
table
.get_column_changed_ticks(component_id)
.debug_checked_unwrap()
.into(),
));
}

Expand Down Expand Up @@ -1289,11 +1296,19 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
&component_id: &ComponentId,
table: &'w Table,
) {
let column = table.get_column(component_id).debug_checked_unwrap();
fetch.table_data = Some((
column.get_data_slice().into(),
column.get_added_ticks_slice().into(),
column.get_changed_ticks_slice().into(),
table
.get_column_data_slice(component_id)
Adamkob12 marked this conversation as resolved.
Show resolved Hide resolved
.debug_checked_unwrap()
.into(),
table
.get_column_added_ticks(component_id)
.debug_checked_unwrap()
.into(),
table
.get_column_changed_ticks(component_id)
.debug_checked_unwrap()
.into(),
));
}

Expand Down
17 changes: 7 additions & 10 deletions crates/bevy_ecs/src/query/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
component::{Component, ComponentId, StorageType, Tick},
entity::Entity,
query::{DebugCheckedUnwrap, FilteredAccess, WorldQuery},
storage::{Column, ComponentSparseSet, Table, TableRow},
storage::{ComponentSparseSet, Table, TableRow},
world::{unsafe_world_cell::UnsafeWorldCell, World},
};
use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
Expand Down Expand Up @@ -70,7 +70,6 @@ use std::{cell::UnsafeCell, marker::PhantomData};
/// [`matches_component_set`]: Self::matches_component_set
/// [`Query`]: crate::system::Query
/// [`State`]: Self::State

pub trait QueryFilter: WorldQuery {
/// Returns true if (and only if) this Filter relies strictly on archetypes to limit which
/// components are accessed by the Query.
Expand Down Expand Up @@ -645,10 +644,9 @@ unsafe impl<T: Component> WorldQuery for Added<T> {
&component_id: &ComponentId,
table: &'w Table,
) {
fetch.table_ticks = Some(
Column::get_added_ticks_slice(table.get_column(component_id).debug_checked_unwrap())
.into(),
);
fetch.table_ticks = table
.get_column_added_ticks(component_id)
Adamkob12 marked this conversation as resolved.
Show resolved Hide resolved
.map(|slice| slice.into());
}

#[inline(always)]
Expand Down Expand Up @@ -854,10 +852,9 @@ unsafe impl<T: Component> WorldQuery for Changed<T> {
&component_id: &ComponentId,
table: &'w Table,
) {
fetch.table_ticks = Some(
Column::get_changed_ticks_slice(table.get_column(component_id).debug_checked_unwrap())
.into(),
);
fetch.table_ticks = table
.get_column_changed_ticks(component_id)
Adamkob12 marked this conversation as resolved.
Show resolved Hide resolved
.map(|slice| slice.into());
}

#[inline(always)]
Expand Down
34 changes: 34 additions & 0 deletions crates/bevy_ecs/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,40 @@ impl<T> DebugCheckedUnwrap for Option<T> {
}
}

// These two impls are explicitly split to ensure that the unreachable! macro
// does not cause inlining to fail when compiling in release mode.
#[cfg(debug_assertions)]
impl<T, U> DebugCheckedUnwrap for Result<T, U> {
type Item = T;

#[inline(always)]
#[track_caller]
unsafe fn debug_checked_unwrap(self) -> Self::Item {
if let Ok(inner) = self {
inner
} else {
unreachable!()
}
}
}

// These two impls are explicitly split to ensure that the unreachable! macro
// does not cause inlining to fail when compiling in release mode.
#[cfg(not(debug_assertions))]
impl<T, U> DebugCheckedUnwrap for Result<T, U> {
type Item = T;

#[inline(always)]
#[track_caller]
unsafe fn debug_checked_unwrap(self) -> Self::Item {
if let Ok(inner) = self {
inner
} else {
std::hint::unreachable_unchecked()
}
}
}

#[cfg(not(debug_assertions))]
impl<T> DebugCheckedUnwrap for Option<T> {
type Item = T;
Expand Down