From 34a2a01e02449d381676d3f5086edaeb6e087bee Mon Sep 17 00:00:00 2001 From: Sean Rennie Date: Fri, 22 Sep 2023 19:03:19 +0100 Subject: [PATCH] fix a couple perf bottlenecks --- js/geodesy.ts | 31 ++++++++++++++++++++++++------- src/geodesy/coordinate.rs | 4 ++-- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/js/geodesy.ts b/js/geodesy.ts index bb0ddf5..7e550c6 100644 --- a/js/geodesy.ts +++ b/js/geodesy.ts @@ -97,10 +97,7 @@ function prepareCoordinates( const flatCoords = flattenCoords(coordinates); // Move the coordinates into WASM memory - const coordBufPtr = new GeodesyWasm.CoordBuffer( - new Float64Array(flatCoords), - dimensions, - ); + const coordBufPtr = new GeodesyWasm.CoordBuffer(flatCoords, dimensions); return [coordBufPtr, dimensions]; } @@ -139,8 +136,20 @@ function dimensionsAreConsistent( } } -function flattenCoords(coords: number[][]): number[] { - return coords.reduce((acc, val) => acc.concat(val), []); +function flattenCoords(coords: number[][]): Float64Array { + const dimension = coords[0].length; + const res = new Float64Array(coords.length * dimension); + + // Fastest way to flatten an array while creating a Float64Array + // It's faster than using Float64Array.set() because it avoids the overhead of + // creating a new Float64Array each item. + let index = 0; + for (let i = 0; i < coords.length; i++) { + for (let j = 0; j < dimension; j++) { + res[index++] = coords[i][j]; + } + } + return res; } function unflattenCoords( @@ -148,9 +157,17 @@ function unflattenCoords( dimensions: GeodesyWasm.CoordDimension, ): number[][] { const dim = dimensions === GeodesyWasm.CoordDimension.Two ? 2 : 3; + + // This is the fastest way to unflatten an array. + // It's faster than using Array.from(coords.subarray(i, i + dim)) because it avoids the overhead of + // creating a new a Float64Array on each item and calling subarray on it. const res: number[][] = []; for (let i = 0; i < coords.length; i += dim) { - res.push(Array.from(coords.subarray(i, i + dim))); + const row: number[] = []; + for (let j = 0; j < dim; j++) { + row.push(coords[i + j]); + } + res.push(row); } return res; } diff --git a/src/geodesy/coordinate.rs b/src/geodesy/coordinate.rs index c363c7d..9add46d 100644 --- a/src/geodesy/coordinate.rs +++ b/src/geodesy/coordinate.rs @@ -30,8 +30,8 @@ impl CoordBuffer { pub fn into_array(self) -> js_sys::Float64Array { let array = js_sys::Float64Array::new_with_length(self.0.buffer.len() as u32); - for (i, v) in self.0.buffer.iter().enumerate() { - array.set_index(i as u32, *v); + for (i, v) in self.0.buffer.into_iter().enumerate() { + array.set_index(i as u32, v); } array