--- title: "Rust: powf is slow" author: "James Pace" date: "2024/01/18" --- I'm currently working on my motion planner on a microcontroller project and was looking at switching from [libm][libm] to [micromath][micromath] as the library I use for standard math operations. For context, in Rust, normal math operations (like absolute value and square root for floats) are provided as part of the standard library (called `std`). The standard library is not available in environments that don't have a backing operating system. Crates than run in those environments thus can't use `std`, which is called being `no_std`. A lot of functions that are in `std` are actually in two other crates, `core` or `alloc` which can be used in `no_std` environments. The normal math functions aren't one of them, and therefore a different library has to be used. My intitial implementation of the planner used `libm` (largely because I found it first), and when I later found `micromath` I wanted to do some profiling comparisons to see which one was faster. I'm going to make a separate blog post with statistics from the profiling, but I wanted to write a quick article today talking about `powf`. One of the operations my planner does a lot is find the distance between two things. My initial implementation did something like ```rust fn distance(point1: &Point, point2: &Point) -> f32 { let squared_dist = powf((point2.x - point1.x), 2.0) + powf((point2.y - point1.y), 2.0); sqrt(squared_dist) } ``` which works fine. When I was profiling I switched to: ```rust fn distance(point1: &Point, point2: &Point) -> f32 { let squared_dist = powf((point2.x - point1.x), 2.0) + powf((point2.y - point1.y), 2.0); sqrt(squared_dist) } ``` which was noticeably faster for both `libm` and `micromath` particularly on the `microbit` that I was using for profiling. ## Does this replicate for `std::powf`? Not when building with `--release`. [^release-rant] ## How much faster? [^release-rant]: As an aside, I think I'm going to switch to using `--release` when building rust code all the time. The optimizations help a ton, to the extent I would never "use" software not built with `--release` and extrapolating performance, even experientially, from binaries built with the `dev` profile is just not transferrable at all. [libm]: https://github.com/rust-lang/libm [micromath]: https://github.com/tarcieri/micromath