csz icon indicating copy to clipboard operation
csz copied to clipboard

Optimize hash function by using `String.prototype.slice`

Open auxves opened this issue 5 years ago • 3 comments

Currently, the hash function uses String.prototype.replace, which is much slower than String.prototype.slice. This pull request implements the latter.

Benchmark

Here

auxves avatar Apr 08 '20 04:04 auxves

Very good point! Thanks for the suggestion. I think those numbers might be slightly misleading but slice certainly seems faster than replace by some margin (just not 100x) see here.

Happy to include this in the next release!

lukejacksonn avatar Apr 09 '20 10:04 lukejacksonn

Luke, here are a couple alternatives:

Just a simple counter is the fastest solution possible.

let count = 0;
const className = 'csz-' + count++;

A perfect hash function will always create the same class names in order and prevent collisions, but this is about 30% slower than Math.random().

https://stackoverflow.com/questions/31257147/is-it-possible-for-math-random-math-random Math.random() === Math.random() (true if executed in the same millisecond)

var seed = 1;
var m = new Uint32Array(1);
function hash() {
  m[0] = seed++;
  m[0] = (m[0] ^ m[0] >> 16) * 0x7feb352d
  m[0] = (m[0] ^ m[0] >> 16) * 0x846ca68b
  m[0] ^= m[0] >> 16;
  return m[0].toString(36);
}

B-Teague avatar Jul 13 '20 18:07 B-Teague

A perfect hash function will always create the same class names in order and prevent collisions,

I have been using this little hash routine borrowed from csstag (similar project to csz, but with CSS Modules and a heavyweight PostCSS plugin chain under the hood, instead of Stylis):

https://github.com/sgtpep/csstag/blob/8e13922dfc5590c0bd47c29f3aeb3db0303cb1cd/src/index.js#L59-L63

const hashCode = (str) =>
  [...str].reduce(
    (hash, char) => ((hash << 5) - hash + char.charCodeAt(0)) | 0,
    0,
  );

Usage:

const STYLE = "body > p { background-color: red; }";
const hashString = window.atob(hashCode(STYLE)).slice(0, 5);

danielweck avatar Jul 14 '20 20:07 danielweck