Skip to content

Change swap to memcopy in Column::initialize_from_unchecked#24312

Open
SpecificProtagonist wants to merge 5 commits into
bevyengine:mainfrom
SpecificProtagonist:table-move-remove-swap
Open

Change swap to memcopy in Column::initialize_from_unchecked#24312
SpecificProtagonist wants to merge 5 commits into
bevyengine:mainfrom
SpecificProtagonist:table-move-remove-swap

Conversation

@SpecificProtagonist
Copy link
Copy Markdown
Contributor

Objective

When moving a component between tables, we move it to the end of the table before moving it to the new table; we can just move them directly to the new table.

Solution

I don't expect noticeable gains, but it doesn't make the code more complex. I'm not an expert in reading assembly and haven't benched this yet, but Column::initialize_from_unchecked now is half as long and calls memcpy instead of memmove.

@SpecificProtagonist SpecificProtagonist added A-ECS Entities, components, systems, and events C-Performance A change motivated by improving speed, memory usage or compile times D-Unsafe Touches with unsafe code in some way labels May 15, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in ECS May 15, 2026
@SpecificProtagonist SpecificProtagonist added the S-Needs-Review Needs reviewer attention (from anyone!) to move forward label May 15, 2026
Copy link
Copy Markdown
Contributor

@amtep amtep left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't feel qualified to approve unsafe code but I reviewed it anyway

Comment thread crates/bevy_ecs/src/storage/table/column.rs Outdated
Copy link
Copy Markdown
Contributor

@chescock chescock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks correct to me! We should benchmark before merging, but I would expect it to help.

&mut self,
other: &mut Column,
other_last_element_index: usize,
src: &mut Column,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that this makes the name more consistent with src_row!

Huh, now it's more obvious that the columns were dst, src, while the rows were src, dst. We definitely shouldn't change that in this PR, but I wonder whether it would be more clear to eventually move these to methods on src so that the order is consistent.

@SpecificProtagonist
Copy link
Copy Markdown
Contributor Author

I'm having trouble getting consistent results from the add_remove benchmarks. For example, this is a result of this PR vs main:

Results
Benchmarking add_remove/table: Warming up for 500.00 ms
Warning: Unable to complete 100 samples in 4.0s. You may wish to increase target time to 5.0s, enable flat sampling, or reduce sample count to 60.
add_remove/table        time:   [911.76 µs 913.88 µs 915.93 µs]
                        change: [−3.9149% −3.1080% −2.3349%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 2 outliers among 100 measurements (2.00%)
  2 (2.00%) high severe
add_remove/sparse_set   time:   [700.58 µs 704.79 µs 708.12 µs]
                        change: [−3.1290% −1.9753% −0.7540%] (p = 0.00 < 0.05)
                        Change within noise threshold.

add_remove_big/table    time:   [1.6716 ms 1.6918 ms 1.7164 ms]
                        change: [−5.8609% −4.0237% −2.2201%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 7 outliers among 100 measurements (7.00%)
  2 (2.00%) high mild
  5 (5.00%) high severe
Benchmarking add_remove_big/sparse_set: Warming up for 500.00 ms
Warning: Unable to complete 100 samples in 4.0s. You may wish to increase target time to 4.0s, enable flat sampling, or reduce sample count to 70.
add_remove_big/sparse_set
                        time:   [701.98 µs 705.65 µs 710.12 µs]
                        change: [−5.9676% −4.5271% −2.6401%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 8 outliers among 100 measurements (8.00%)
  4 (4.00%) high mild
  4 (4.00%) high severe

Benchmarking add_remove_very_big/table: Warming up for 500.00 ms
Warning: Unable to complete 100 samples in 4.0s. You may wish to increase target time to 4.2s, or reduce sample count to 90.
add_remove_very_big/table
                        time:   [57.735 ms 58.037 ms 58.428 ms]
                        change: [−3.9345% −3.0308% −2.1869%] (p = 0.00 < 0.05)
                        Performance has improved.
FoundBenchmarking add_remove/table: Warming up for 500.00 ms
Warning: Unable to complete 100 samples in 4.0s. You may wish to increase target time to 5.0s, enable flat sampling, or reduce sample count to 60.
add_remove/table        time:   [911.76 µs 913.88 µs 915.93 µs]
                        change: [−3.9149% −3.1080% −2.3349%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 2 outliers among 100 measurements (2.00%)
  2 (2.00%) high severe
add_remove/sparse_set   time:   [700.58 µs 704.79 µs 708.12 µs]
                        change: [−3.1290% −1.9753% −0.7540%] (p = 0.00 < 0.05)
                        Change within noise threshold.

add_remove_big/table    time:   [1.6716 ms 1.6918 ms 1.7164 ms]
                        change: [−5.8609% −4.0237% −2.2201%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 7 outliers among 100 measurements (7.00%)
  2 (2.00%) high mild
  5 (5.00%) high severe
Benchmarking add_remove_big/sparse_set: Warming up for 500.00 ms
Warning: Unable to complete 100 samples in 4.0s. You may wish to increase target time to 4.0s, enable flat sampling, or reduce sample count to 70.
add_remove_big/sparse_set
                        time:   [701.98 µs 705.65 µs 710.12 µs]
                        change: [−5.9676% −4.5271% −2.6401%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 8 outliers among 100 measurements (8.00%)
  4 (4.00%) high mild
  4 (4.00%) high severe

Benchmarking add_remove_very_big/table: Warming up for 500.00 ms
Warning: Unable to complete 100 samples in 4.0s. You may wish to increase target time to 4.2s, or reduce sample count to 90.
add_remove_very_big/table
                        time:   [57.735 ms 58.037 ms 58.428 ms]
                        change: [−3.9345% −3.0308% −2.1869%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 4 outliers among 100 measurements (4.00%)
  4 (4.00%) high severe
 4 outliers among 100 measurements (4.00%)
  4 (4.00%) high severe

But then re-running it with the same saved baseline showed add_remove_very_big at a 30% improvement instead. It's probably heavily influenced by where in memory the allocations end up at.

Comment thread crates/bevy_ecs/src/storage/blob_array.rs Outdated
Comment thread crates/bevy_ecs/src/storage/thin_array_ptr.rs Outdated
Comment thread crates/bevy_ecs/src/storage/table/column.rs Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-ECS Entities, components, systems, and events C-Performance A change motivated by improving speed, memory usage or compile times D-Unsafe Touches with unsafe code in some way S-Needs-Review Needs reviewer attention (from anyone!) to move forward

Projects

Status: Needs SME Triage

Development

Successfully merging this pull request may close these issues.

4 participants