1

I was looking at methods of hashing a string, when I noticed something very weird with my methods of optimization. I was trying to (unsafely) hash a bunch of strings and compare performance, and I took an excerpt out of this answer. My rig was as follows:

String.prototype.hash = function() {
  let hash = 0;
  for (let i = 0, len = this.length; i < len; i++) {
    let char = this.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash = hash & hash;
  }
  return hash;
}

let startDate = new Date().getTime();

for (let i = 0; i < 11111111; i++) 'Hello World!'.hash();

// Log the time before and after the loop.
console.log(new Date().getTime() - startDate);
// (int) => 9358

When hashing 11111111 strings of “Hello World”, I get a modest result of 9000 ms for the full execution. I figured eh, makes sense, it's a lot to compute. However, when I defined a regular function (see code below) to compute the hashes, I get an execution time of 250 milliseconds! 1/36 of what would've been with the prototype function.

function hashStr(string) {
  let hash = 0;
  for (let i = 0, len = string.length; i < len; i++) {
    let char = string.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash = hash & hash;
  }
  return hash;
}

let startDate = new Date().getTime();

for (let i = 0; i < 11111111; i++) hashStr('Hello World!');

// Log the time before and after the loop.
console.log(new Date().getTime() - startDate);
// (int) => 280

Is there something that I'm missing, is it a fault with my code? I can't imagine it's THAT much faster to compute without using prototype. Thanks for the help!

Commander
  • 13
  • 1
  • 5
  • FWIW: Here's a wrapper implementation I wrote a while back for computing hex strings of standard algorithm digests: https://tsplay.dev/WyOdbN – jsejcksn Dec 28 '21 at 23:46
  • What if you try using the prototype function directly? `String.prototype.has(array[1])`? – evolutionxbox Dec 28 '21 at 23:49
  • @jsejcksn Appreciated! I just need something super fast, and not particularly strict to compare evaluated strings. Thing is, the site in question that I need it for uses PageSpeed Insights, which evals all scripts. To make sure I'm overriding the right ones, I generate a hash for each and compare them to ones I have stored. If they match, I load my own script instead. – Commander Dec 28 '21 at 23:50
  • @evolutionxbox Would appear that I then get a result of round about 70ms. Weird! **EDIT**: Should say that I close and re-open the tab (doing this in devtools console) each time to clear site memory. Otherwise, performance in the function-based method could jump by 2000ms at least – Commander Dec 28 '21 at 23:52
  • 1
    Btw, no reason to fill an array with that many strings. You could just do `for (let i = 0; i < 11111111; i++) 'Hello World!'.hash();` and it would be the same. – Bergi Dec 29 '21 at 00:02
  • @Bergi Oh right, that's fair. Oops! – Commander Dec 29 '21 at 00:03
  • @evolutionxbox You probably meant `String.prototype.hash.call('Hello World!');` but that is just as slow. https://jsfiddle.net/mendesjuan/31z27uef/ – Ruan Mendes Dec 29 '21 at 00:18

0 Answers0