Marquis Blount
Marquis Blount

Reputation: 8095

Why is string.charAt(x) much slower than string[x]

In Java (maybe the same for other langues as well) the charAt(x) method for accessing characters in a string is much slower than accessing the character elements in a char[]. This doesn't make much sense to me since String is using a char[] to represent the data.

Here is my test and results on this.

Testing charAt()

for(int i = 1000000; i >= 0; i--){
    char c = s.charAt(5);
}

charAt() elapsed time = 0.00261095

for(int i = 1000000; i >= 0; i--){
    char c = sArr[5];
}

arr[] elapsed time 0.001620297

From String.Java

public char charAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
}

Upvotes: 2

Views: 3572

Answers (4)

T.J. Crowder
T.J. Crowder

Reputation: 1073988

Offhand, I can think of at least a couple of reasons:

  1. charAt is a method call

  2. In Java 1.7.0_05 (thanks for the precise version, Holger) and below, within charAt, String does work to determine which entry in the underlying char[] to give you, since strings can share char[] arrays:

    if ((index < 0) || (index >= count)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index + offset];
    

    (offset is the offset in the shared char[].)

    In Java 1.7.0_06 and above, it still does a range check:

    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
    

So we can see that charAt does what you're doing (accessing a char[] entry), but also has to have the overhead of a method call and the range check (and in Java 7 and earlier, the index + offset calculation). It can't help but be a bit slower.

Then there's the possibility of measurement error, as naive micro-benchmarks in Java tend to be problematic.

Upvotes: 2

Marquis Blount
Marquis Blount

Reputation: 8095

The error check inside of the charAt() method is actually accounted for the difference. The test that I created wasn't “fair”, the char[x] test doesn't have error handling so the times were faster

//error check from charAt()

if ((index < 0) || (index >= value.length)) {
    throw new StringIndexOutOfBoundsException(index);
}

Updated arr[x] test with the following

    for(int i = 1000000; i >= 0; i--){
        if(dummy < 0 || dummy >= sArr.length) throw new IndexOutOfBoundsException();
        char c = sArr[5];
    }

updated time: arr[] elapsed time 0.002208887

A lot closer to charAt(i) now.

Upvotes: 1

fill͡pant͡
fill͡pant͡

Reputation: 1165

If you take a look at the source code of String, you will realise that once you call the method, two checks are being made on the provided index. Other than this, a method consumes some time by itself when called. These two combined are responsible for the time delay you noticed.

Upvotes: 2

Feek
Feek

Reputation: 297

Because charAt() is a method and it needs to be placed on the runtime stack and control needs to be altered each time it is called, which takes a little bit of time. To the best of my knowledge they both perform the same operation.

Upvotes: 0

Related Questions