Skip to content

Commit

Permalink
[perf] mutate rather than allocate a bunch of heap strings
Browse files Browse the repository at this point in the history
Bench output:

    encode 10_000 coordinates at precision 1e-5
                            time:   [123.68 µs 123.80 µs 123.94 µs]
                            change: [-74.528% -74.461% -74.401%] (p = 0.00 < 0.05)
                            Performance has improved.
    Found 6 outliers among 100 measurements (6.00%)
      4 (4.00%) high mild
      2 (2.00%) high severe

    encode 10_000 coordinates at precision 1e-6
                            time:   [136.60 µs 137.55 µs 138.55 µs]
                            change: [-73.205% -73.066% -72.932%] (p = 0.00 < 0.05)
                            Performance has improved.
    Found 11 outliers among 100 measurements (11.00%)
      9 (9.00%) high mild
      2 (2.00%) high severe
  • Loading branch information
michaelkirk committed May 6, 2024
1 parent cf0fb0e commit db9b5b9
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 6 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Speed up encode function (now runs in ~72% less time / 3.5x improvement):
* https://github.com/georust/polyline/pull/42

## 0.10.2

* fix decoder crashing with out-of-bounds error (https://github.com/georust/polyline/pull/37):
Expand Down
11 changes: 5 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,13 @@ where
}
}

fn encode(current: f64, previous: f64, factor: i32) -> Result<String, String> {
fn encode(current: f64, previous: f64, factor: i32, output: &mut String) -> Result<(), String> {
let current = scale(current, factor);
let previous = scale(previous, factor);
let mut coordinate = (current - previous) << 1;
if (current - previous) < 0 {
coordinate = !coordinate;
}
let mut output: String = "".to_string();
while coordinate >= 0x20 {
let from_char = char::from_u32(((0x20 | (coordinate & 0x1f)) + 63) as u32)
.ok_or("Couldn't convert character")?;
Expand All @@ -62,7 +61,7 @@ fn encode(current: f64, previous: f64, factor: i32) -> Result<String, String> {
}
let from_char = char::from_u32((coordinate + 63) as u32).ok_or("Couldn't convert character")?;
output.push(from_char);
Ok(output)
Ok(())
}

/// Encodes a Google Encoded Polyline.
Expand All @@ -83,16 +82,16 @@ where
let base: i32 = 10;
let factor: i32 = base.pow(precision);

let mut output = "".to_string();
let mut output = String::new();
let mut b = Coord { x: 0.0, y: 0.0 };

for (i, a) in coordinates.into_iter().enumerate() {
check(a.y, (MIN_LATITUDE, MAX_LATITUDE))
.map_err(|e| format!("Latitude error at position {0}: {1}", i, e))?;
check(a.x, (MIN_LONGITUDE, MAX_LONGITUDE))
.map_err(|e| format!("Longitude error at position {0}: {1}", i, e))?;
output = output + &encode(a.y, b.y, factor)?;
output = output + &encode(a.x, b.x, factor)?;
encode(a.y, b.y, factor, &mut output)?;
encode(a.x, b.x, factor, &mut output)?;
b = a;
}
Ok(output)
Expand Down

0 comments on commit db9b5b9

Please sign in to comment.