Hello Everyone,
I've been doing work around optimizations recently, and noticed that libextra
was taking an
inordinate amount of time to build. My investigations led me to find that well
over half the time
spent was on Loop Invariant Code motion, i.e. moving expressions that don't
change out of the loop.
One of the more common cases turns this:
while i < n {
data.field[i] = something(i);
i += 1;
}
into this:
let tmp = data.field;
while i < n {
tmp[i] = something(i);
}
since, the field access is invariant.
Anyway, the BigInt module uses this pattern a lot. It also has 112 functions
marked with
#[inline(always)]. This does two things: causes massive code bloat, 2 orders of
magnitude worth of
code bloat, and makes later passes work much, much harder. Many of the
functions in BigInt would
have been inlined multiple times into one function, and in some cases, those
functions would be
further inlined into other functions, despite blowing past the normal inline
cost limit.
This meant that a fairly simple, standard pass, was being called on over 100x
more code than it
needed to be. If you want to know why a full build takes so long, there is why.
Inlining is a pretty standard optimization, and is potentially done for every
function that isn't
marked with `#[inline(never)]`, but the compiler is smart enough to know when
it's not worth it.
`#[inline(always)]` is a very strong statement, and should be reserved for
cases where you are
certain that the function absolutely needs to be inlined, no exceptions.
Remember that "always"
means it, so every single function that uses it will get a copy.
Inlining is not a magic bullet for performance and the compiler passes are far
smarter at knowing
what is more efficient than you are.
Thank you for your time,
James Miller
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev