Search code examples
javascriptperformancegoogle-chromebenchmarkingv8

Performance comparison with V8


I'm currently testing multiple cases for parsing lines.

Each line is formatted like that:

"dHdX5jOa7ww9cGsW7jQF=dHdX5jOa7ww9cGsW7jQF=dHdX5jOa7ww9cGsW7jQF=dHdX5jOa7ww9cGsW7jQF"

There are a lot of lines of course, and I need to extract the key, and the value.

The key is delimited by the first "=" found. There is never a "=" char in the key.

The value is the rest of string next after the first "=" sign.

So for this exemple the result should be:

{
  key: "dHdX5jOa7ww9cGsW7jQF",
  value: "dHdX5jOa7ww9cGsW7jQF=dHdX5jOa7ww9cGsW7jQF=dHdX5jOa7ww9cGsW7jQF"
}

From here we can iterate on multiple solutions:

// the first one is not very efficient with split splice join method
function first(line) {
  const lineSplit = line.split('='),
        key       = lineSplit[0],
        value     = lineSplit.splice(1, lineSplit.length).join('=');

  return {
    key,
    value
  };
}

// the second one execute only what i want to do
// with built-in String prototype's functions
function optimized(line) {
  const index = line.indexOf("="),
        key   = line.substr(0, index),
        value = line.substr(index + 1, line.length);

  return {
    key,
    value
  };
}

// i tried to code the logic myself
function homemade(line) {
    const len = line.length;
    let value = "", key = "", valued = false;
    for (let i = 0; i < len; ++i) {
        const char = line[i];
        if (valued === false) {
            if (char !== '=') {
                key += char;
            } else {
                valued = true;
            }
        } else {
            value += char;
        }
    }

    return {
        key,
        value
    };
}

// and next recode substr and foreach built-in to implemant the same
// function but with homemade substr&foreach
String.prototype.substr2 = function(from, to){
    let str = "";
    for (let i = from; i < to; ++i) {
        str += this[i];
    }
    return str;
};

String.prototype.indexOf2 = function(occ){
    const len = this.length;
    for (let i = 0; i < len; ++i) {
        if (this[i] === occ) {
            return i;
        }
    }
    return -1;
};

function overload(line) {
  const index = line.indexOf2("="),
        key   = line.substr2(0, index),
        value = line.substr2(index + 1, line.length);

  return {
    key,
    value
  };
}

And voila the results with jsBench:

[I'm using Google Chrome Version 59.0.3071.104 (Official Build) (64-bit)]

enter image description here

You can checkout the results of these functions with your browser in this jsBench

I don't understand what is going on. I imagined that cannot be possible since I wrote only the code i needed with native for() and other stuffs like this...

My questions are:

Why the builtin string operations are obviously much faster ?

Why this repeated string concatenation is inneficient ?

Is there an alternative to it ?


Solution

  • Why the builtin string operations are obviously much faster ?

    Because they are optimized, and use internal implementation tricks that are not available to JavaScript code. For example, they avoid repeated string concatenation by building the result in one go.

    Why this repeated string concatenation is inefficient ?

    Because it creates many strings as intermediate results.

    Is there an alternative to it ?

    Use the builtin string operations :-)