I was attempting to create a faster version of String.equals() method and started by simply copying it. The result I found was quite confusing. When I ran the copy pasted version, timed it and compared it against the JVM one, the JVM version was faster. The difference ranged from 6x to 34x faster! Simply put, the longer the string, larger is the difference.
boolean equals(final char a[], final char b[]) {
int n = a.length;
int i = 0;
while (n-- != 0) {
if (a[i] != b[i]) return false;
i++;
}
return true;
}
public static void main() throws Exception {
String a = "blah balh balh";
String b = "blah balh balb";
long me = 0, jvm = 0;
Field value = String.class.getDeclaredField("value");
value.setAccessible(true);
final char lhs[] = (char[]) value.get(a);
final char rhs[] = (char[]) value.get(b);
for (int i = 0; i < 100; i++) {
long t = System.nanoTime();
equals(lhs, rhs);
t = System.nanoTime() - t;
me += t;
}
for (int i = 0; i < 100; i++) {
long t = System.nanoTime();
a.equals(b);
t = System.nanoTime() - t;
jvm += t;
}
System.out.println("me = " + me);
System.out.println("jvm = " + jvm);
}
Output:
me = 258931
jvm = 14991
The equals() method I wrote is a copy-pasted version of the one found in String.equals() method. Why is the JVM version faster than its copy-pasted version? Isn't it effectively the same?
Could someone explain why I see such visible differences?
PS: If you wish to see large differences, you could create long (really, really long) strings with just one character differing at the end.