我试图创建一个更快的版本字符串.equals() http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#equals%28java.lang.Object%29方法并从简单地复制开始。我发现的结果非常令人困惑。当我运行复制粘贴版本、计时并将其与 JVM 版本进行比较时,JVM 版本更快。速度差异从 6 倍到 34 倍不等!简单来说,字符串越长,差异越大。
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
我编写的 equals() 方法是中找到的方法的复制粘贴版本字符串.equals() http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#equals%28java.lang.Object%29方法。为什么 JVM 版本比复制粘贴版本更快?效果上不是一样吗?
有人可以解释为什么我看到如此明显的差异吗?
PS:如果您希望看到较大的差异,您可以创建很长(非常非常长)的字符串,并且末尾只有一个字符不同。
为什么 JVM 版本比复制粘贴版本更快。效果上不是一样吗?
令人惊讶的是,事实并非如此。
字符串比较是一种普遍存在的操作,几乎可以肯定,您的即时编译器 http://en.wikipedia.org/wiki/Just-in-time_compilation有一个内在的String.equals()
。这意味着编译器知道如何生成特制的机器代码来比较字符串。当您使用时,这对程序员来说是透明地完成的String.equals()
.
这可以解释为什么String.equals()
比你的方法快得多,即使表面上它们看起来相同。
快速搜索发现几个错误报告提到了 HotSpot 中的此类内在函数。例如,7041100:在空检查之前执行的 String.equals 内在函数中的加载 https://bugs.java.com/bugdatabase/view_bug?bug_id=7041100.
相关HotSpot源码可以找到here http://hg.openjdk.java.net/jdk7/hotspot-comp/hotspot/file/e6d7eed3330c/src/share/vm/opto/library_call.cpp。有问题的函数是:
848 Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2) {
and
943 bool LibraryCallKit::inline_string_equals() {
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)