简体   繁体   中英

JavaScript string equality performance comparison

I have a noob javascript question. Let's say we have two very large strings (~ million characters or more) that are equal - they have the same length and the same content. Let's say we have these two function that both do the same thing (compare strings):

function equals1(a, b) {
    return a === b;
}

function equals2(a, b) {
    if (a.length !== b.length) {
           return false;
    }
    for (var i = 0; i < a.length; ++i) {
        if (a[i] !== b[i]) {
            return false;
         }
    }
    return true;
}

Why is the first function (equals1()) almost as twice as fast as the second one? How can the second one be improved so that it performs as good as the first one?

第一个函数速度更快,因为它不必检查i < a.length一百万次,而无需对i一百万次递增运算。

Most probably Javascript is doing string interning ( Do common JavaScript implementations use string interning? ) according to a person that is in ECMAScript committee. I thought that then === would be O(1) but based on performance test of the original poster it is O(n) as doubling the string doubles the time for the equality.. That is really sad that string interning is not used they way it should be.

Update: JSPerf

The orginal poster claims should be backed up for O(N) complexity From http://jsperf.com/eqaulity-is-constant-time It seems that even if I have 16x bigger string the time doesn't change more than 1-2%

So please reconsider those things that I have striked-through and your down votes

In other words:

when you do

var str1 = "stringwithmillionchars"; //stored in address 51242
var str2 = "stringwithmillionchars"; //stored in address 12313

the "stringwithmillionchars" will be stored once let's say in address 201012 of memory and both str1 and str2 will be "pointing in this address 201012. This address could be determined with some kind of hashing to map to specific locations in memory.

So when doing

"stringwithmillionchars"==="stringwithmillionchars"

would look like

getContentOfAddress(51242)===getContentOfAddress(12313)

or 201012 === 201012

which takes O(1)/constant time

The for loop in your example (equals2()) has O(N) time, where N the length of both strings. That is because it has to do N comparisons between each pair of characters and N comparisons between i and str.length.

Note: the address numbers were chosen randomly for illustration purposes..

Important : Based on performance comparisons from my question( Why Javascript ===/== string equality sometimes has constant time complexity and some times has linear time complexity ) interning happens only when the strings are assigned directly with quotes otherwise the comparison will take linear time instead of constant because char-to-char comparison happens.

The first does the same things. If the strings are different lengths, it will return false. Then it checks to see if the characters are the same at the same indices. However, it is implemented at the JS implementation level, so it is running as fast as C, C++, Java or whatever language the JavaScript implementation is written in.

You can do something like the following to make your equals2 function twice faster:

function equals2(a, b) {
    if (a.length !== b.length) {
           return false;
    }
    for (var i = 0; i < a.length/2; ++i) {
        if (a[i] !== b[i] || a[a.length-i-1] !== b[b.length-i-1]) {
            return false;
         }
    }
    return true;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM