From c641da273415e22da190c2a924981405a91ecff6 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Wed, 30 Nov 2022 09:53:39 +0100 Subject: [PATCH] Speed up strongRound by avoiding string casting (#1716) I'm currently profiling my build pipeline and noticed that the `strongRound` function showed up a couple of times, followed immediately with a bit of GC cleanup shortly after. We can speed up that function by avoiding the string casting caused by `Number.prototype.toFixed()`. In my project's build pipeline with lots of svg icons this saves about 1.4s in total. js-tools-strongRound --- plugins/convertPathData.js | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/plugins/convertPathData.js b/plugins/convertPathData.js index a5f375bad..f9e07c428 100644 --- a/plugins/convertPathData.js +++ b/plugins/convertPathData.js @@ -951,6 +951,16 @@ function getIntersection(coords) { } } +/** + * Does the same as `Number.prototype.toFixed` but without casting + * the return value to a string. + * @type {(num: number, precision: number) => number} + */ +function toFixed(num, precision) { + const pow = 10 ** precision; + return Math.round(num * pow) / pow; +} + /** * Decrease accuracy of floating-point numbers * in path data keeping a specified number of decimals. @@ -960,16 +970,14 @@ function getIntersection(coords) { * @type {(data: number[]) => number[]} */ function strongRound(data) { - for (var i = data.length; i-- > 0; ) { - // @ts-ignore - if (data[i].toFixed(precision) != data[i]) { - // @ts-ignore - var rounded = +data[i].toFixed(precision - 1); + const precisionNum = precision || 0; + for (let i = data.length; i-- > 0; ) { + const fixed = toFixed(data[i], precisionNum); + if (fixed !== data[i]) { + const rounded = toFixed(data[i], precisionNum - 1); data[i] = - // @ts-ignore - +Math.abs(rounded - data[i]).toFixed(precision + 1) >= error - ? // @ts-ignore - +data[i].toFixed(precision) + toFixed(Math.abs(rounded - data[i]), precisionNum + 1) >= error + ? fixed : rounded; } }