Unm*_*yer 16 java optimization
我试图创建一个更快版本的String.equals()方法,并通过简单地复制它开始.我发现的结果非常令人困惑.当我运行复制粘贴版本,定时并将其与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);
}
Run Code Online (Sandbox Code Playgroud)
输出:
me = 258931
jvm = 14991
Run Code Online (Sandbox Code Playgroud)
我写的equals()方法是String.equals()方法中的一个复制粘贴版本.为什么JVM版本比它的复制粘贴版本更快.它不是真的有效吗?
有人可以解释为什么我看到这种明显的差异?
PS:如果你希望看到很大的差异,你可以创建长(真的,非常长)的字符串,最后只有一个字符不同.
NPE*_*NPE 16
为什么JVM版本比它的复制粘贴版本更快.它不是真的有效吗?
令人惊讶的是,事实并非如此.
字符串比较是一种无处不在的操作,几乎可以肯定你的JIT编译器具有内在的String.equals().这意味着编译器知道如何生成用于比较字符串的特制机器代码.当您使用时,程序员可以透明地完成此操作String.equals().
这可以解释为什么String.equals()比你的方法快得多,即使表面看起来相同.
快速搜索找到几个在HotSpot中提到这种内在的错误报告.例如,7041100:在null检查之前执行的String.equals内部的加载.
可在此处找到相关的HotSpot源.有问题的功能是:
848 Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2) {
Run Code Online (Sandbox Code Playgroud)
和
943 bool LibraryCallKit::inline_string_equals() {
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1163 次 |
| 最近记录: |