Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: avoid regexp for generate alphabetic name fn #4316

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

H4ad
Copy link

@H4ad H4ad commented May 22, 2024

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);

return a + b;
}

return a + '-' + b;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using backticks could improve readability. What do you think?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For not much:

`${a}-${b}`

For this case, I think the current way is more readable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants