Move a whole box at once, since that is what a move does
Profiling a move by cycles rather than by instructions says the cost is not where the last session recorded it. In `apply_scalar` the `i64` division is **0.00%** of cycles and the multiply 1.5%: the time is in `saturating_add`, which is five instructions and no vector form for an `i32`, and a box that only moved does eight of them. Asking for them one scalar at a time, each behind a match on which kind of move this is, gives the compiler four short sequences where it had four adds in a row to pair up. So a translation is now asked for once for the whole region -- which is what a translation is -- and the match happens once above it rather than per scalar. `many` over 500 frames: 684M cycles to 660M, and 1,815,666,327 instructions to 1,742,553,104. Cycle counts are worth trusting here, which is the other thing to keep: three runs of one binary varied 0.23%. It is wall time that varies 2x on this machine, not the counters, and instructions alone cannot see a stall. Checked: fmt, clippy, 105 tests, all five shrinker cases at 300 seeds, and `tabs`, `text` and `random` byte-identical at 1920x1200. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cb1bba4682
commit
1940e85c70
2 files changed
+28
No files matched your search
@@ -292,6 +292,15 @@ impl UiSpan {
|
||||
pub const fn len(&self) -> Len {
|
||||
self.end - self.start
|
||||
}
|
||||
|
||||
/// Both ends by the same amount, which is what moving a box without
|
||||
/// changing its length does to every part of it.
|
||||
pub const fn translated(self, by: Len) -> Self {
|
||||
Self {
|
||||
start: self.start + by,
|
||||
end: self.end + by,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@@ -302,6 +311,17 @@ pub struct UiRegion {
|
||||
}
|
||||
|
||||
impl UiRegion {
|
||||
/// Every part of the box by the same amount on each axis. Done to the
|
||||
/// whole region rather than an end at a time, because that is what it is
|
||||
/// -- and because four adds in a row are four adds, where four asked for
|
||||
/// separately are four sequences.
|
||||
pub const fn translated(self, x: Len, y: Len) -> Self {
|
||||
Self {
|
||||
x: self.x.translated(x),
|
||||
y: self.y.translated(y),
|
||||
}
|
||||
}
|
||||
|
||||
pub const FULL: Self = Self {
|
||||
x: UiSpan::FULL,
|
||||
y: UiSpan::FULL,
|
||||
|
||||
@@ -1090,6 +1090,14 @@ impl RegionRemap {
|
||||
}
|
||||
|
||||
fn apply(&self, region: UiRegion) -> UiRegion {
|
||||
// A box that only moved carries every part of itself by the same two
|
||||
// amounts, and that is the common move. Asking it once for the whole
|
||||
// region is what lets it be eight adds in a row rather than four
|
||||
// sequences with a branch each -- measured, it is where the time in a
|
||||
// move goes.
|
||||
if let [AxisRemap::Translate(x), AxisRemap::Translate(y)] = self.axes {
|
||||
return region.translated(x, y);
|
||||
}
|
||||
UiRegion {
|
||||
x: self.axes[0].apply_span(region.x),
|
||||
y: self.axes[1].apply_span(region.y),
|
||||
|
||||
Reference in new issue
Block a user