styled-components
styled-components copied to clipboard
perf: avoid regexp for generate alphabetic name fn
Removing RegExp to improve the speed of this helper fn.
Results:
generateAlphabeticName V1: 14.510s
generateAlphabeticName V2: 3.515s
Result: nJkmV
Benchmark:
var AD_REPLACER_R = /(a)(d)/gi;
/* This is the "capacity" of our alphabet i.e. 2x26 for all letters plus their capitalised
* counterparts */
var charsLength = 52;
/* start at 75 for 'a' until 'z' (25) and then start at 65 for capitalised letters */
var getAlphabeticChar = function (code) {
let temp = code + (code > 25 ? 39 : 97);
return String.fromCharCode(temp);
};
const D_LOWER_CHAR = 'd'.charCodeAt(0);
const D_CHAR = 'D'.charCodeAt(0);
const A_LOWER_CHAR = 'a'.charCodeAt(0);
const A_CHAR = 'A'.charCodeAt(0);
function ensureDashForAD(a, b) {
if (a.length === 0 || b.length === 0) {
return a + b;
}
const lastBChar = b.charCodeAt(b.length - 1);
if (lastBChar !== D_CHAR && lastBChar !== D_LOWER_CHAR) {
return a + b;
}
const lastAChar = a.charCodeAt(a.length - 1);
if (lastAChar !== A_CHAR && lastAChar !== A_LOWER_CHAR) {
return a + b;
}
return a + '-' + b;
}
function generateAlphabeticNameV1(code) {
let name = '';
let x;
/* get a char and divide by alphabet-length */
for (x = Math.abs(code); x > charsLength; x = (x / charsLength) | 0) {
name = getAlphabeticChar(x % charsLength) + name;
}
return (getAlphabeticChar(x % charsLength) + name).replace(AD_REPLACER_R, '$1-$2');
}
/* input a number, usually a hash and convert it to base-52 */
function generateAlphabeticNameV2(code) {
var name = '';
var x;
/* get a char and divide by alphabet-length */
for (x = Math.abs(code); x > charsLength; x = (x / charsLength) | 0) {
name = ensureDashForAD(getAlphabeticChar(x % charsLength), name);
}
return ensureDashForAD(getAlphabeticChar(x % charsLength), name);
}
let result = '';
console.time('generateAlphabeticName V1')
for (let i = 0; i < 1e8; i++) {
result = generateAlphabeticNameV1(i);
}
console.timeEnd('generateAlphabeticName V1')
console.time('generateAlphabeticName V2')
for (let i = 0; i < 1e8; i++) {
result = generateAlphabeticNameV2(i);
}
console.timeEnd('generateAlphabeticName V2')
console.log('Result:', result);
Perf for this library sometimes doesn't work the way you'd expect in my experience.
Which value represents this PR?
Ok I found a discrepancy in the benchmark code that I fixed in main and we can properly test this now
Ran it again and the perf is pretty much the same between latest and this branch
I know for sure this will be faster but maybe the impact on the benchmark is not much relevant, so is up to you to merge.
At least when I profiled some time ago, I was able to remove this function from the profile chart with this change, my benchmark was just rendering the same box multiple times.