Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么String.equals对于不相同(但相等)的字符串对象要慢得多?_Java_String_Performance_Equals - Fatal编程技术网

Java 为什么String.equals对于不相同(但相等)的字符串对象要慢得多?

Java 为什么String.equals对于不相同(但相等)的字符串对象要慢得多?,java,string,performance,equals,Java,String,Performance,Equals,我正在深入研究isString.equals()是否真的那么糟糕,在尝试对其进行基准测试时,遇到了一些令人惊讶的结果 使用,我编写了一个简单的测试(最后是代码和pom),查看函数在1秒内可以运行多少次 Benchmark Mode Samples Score Score error Units c.s.SimpleBenchmark.testEqualsIntern thrpt 5 69

我正在深入研究is
String.equals()
是否真的那么糟糕,在尝试对其进行基准测试时,遇到了一些令人惊讶的结果

使用,我编写了一个简单的测试(最后是代码和pom),查看函数在1秒内可以运行多少次

Benchmark Mode Samples Score Score error Units c.s.SimpleBenchmark.testEqualsIntern thrpt 5 698910949.710 47115846.650 ops/s c.s.SimpleBenchmark.testEqualsNew thrpt 5 529118.774 21164.872 ops/s c.s.SimpleBenchmark.testIsEmpty thrpt 5 470846539.546 19922172.099 ops/s maven的.pom(如果您希望复制它,可以自己快速设置):


4.0.0
com.shagie
长凳
1
罐子
使用JMH的字符串基准测试
3
org.openjdk.jmh
jmh核
${jmh.version}
org.openjdk.jmh
jmh发生器
${jmh.version}
假如
UTF-8
0.9.5
1.6
基准
org.apache.maven.plugins
maven编译器插件
3.1
${javac.target}
${javac.target}
${javac.target}
org.apache.maven.plugins
maven阴影插件
2.2
包裹
阴凉处
${uberjar.name}
org.openjdk.jmh.Main
maven清洁插件
2.5
maven部署插件
2.8.1
maven安装插件
2.5.1
maven jar插件
2.4
maven javadoc插件
2.9.1
maven资源插件
2.6
maven站点插件
3.3
maven源插件
2.2.1
maven surefire插件
2.17
这是自动生成的(对组和工件进行了适当的调整):

$mvn原型:生成\
-DinteractiveMode=false\
-DarchetypeGroupId=org.openjdk.jmh\
-DarchetypeArtifactId=jmh java基准原型\
-DgroupId=org.sample\
-DartifactId=测试\
-Dversion=1.0
要运行测试,请执行以下操作:

$mvn干净安装
$java-jar target/benchmarks.jar“.*SimpleBenchmark.*”—wi 5-i 5-f 1
这将是一个问题,它运行的Java版本是:

$java-version
java版本“1.6.0_65”
Java(TM)SE运行时环境(build 1.6.0_65-b14-462-11M4609)
Java HotSpot(TM)64位服务器虚拟机(构建20.65-b04-462,混合模式)

硬件(可能会受到质疑)是英特尔至强处理器上的OS X,10.9.4。

解释似乎是(在第一种情况下,
intern()
'd),JVM能够测试引用相等性,这是一种直接的数值比较

相反,非引用相等(值相等)的测试必须迭代两个字符串的字符序列。你观察到的结果并不像你认为的那么重要。JIT和其他优化正在进行,性能在实践中可能会提高(因为不是每个字符串都是相等的,当它们不相等时,它可能会短路)

最后,微观基准是出了名的不可靠。但是您已经发现了一种性能优化,它是通过设计内置到JVM中的。引用相等性检查要快得多。

public int testequalintern(){
public int testEqualsIntern() {
    int count = 0;
    String str = EMPTY;

    for(int i = 0; i < ITERATIONS; i++) {
        if(str.equals(EMPTY)) {
            count++;
        }
    }
    return count;
}
整数计数=0; 字符串str=空; 对于(int i=0;i
这里str.equals(EMPTY)将首先通过==检查相等性,它将返回true,因为str和EMPTY都具有相同的引用,并且都在字符串池中,并且操作将变得更快,但在

public int testEqualsNew() {
    int count = 0;
    String str = NEW_EMPTY;

    for(int i = 0; i < ITERATIONS; i++) {
        if(str.equals(EMPTY)) {
            count++;
        }
    }
    return count;
}
public int testEqualsNew(){
整数计数=0;
字符串str=NEW_空;
对于(int i=0;i

空字符串在字符串池中,而NEW_EMPTY不是池的一部分,两者都有不同的引用,因为空字符串是文字常量,而NEW_EMPTY不是。因此equals()首先尝试比较equality by==将返回false,因为两者都有不同的引用,并且它将检查内容,因此在本例中equals()将花费更多的时间。

针对新字符串测试equality不会产生荒谬的性能影响。您看到的效果很简单,Hotspot在一种情况下能够优化循环,但在另一种情况下却不能

以下是OpenJDK 7(IcedTea7 2.1.7)(7u3-2.1.7-1)64位服务器的
testEqualsIntern
热点程序集转储,显示了无环结果(为
TesteSempty
生成了类似的代码):

当你将一件事的1000次迭代与另一件事的1次迭代进行比较时,结果相差1000倍也就不足为奇了

在向迭代添加四个零之后,我运行了相同的测试,正如预期的那样,
testequalintern
采用了equa
public int testEqualsNew() {
    int count = 0;
    String str = NEW_EMPTY;

    for(int i = 0; i < ITERATIONS; i++) {
        if(str.equals(EMPTY)) {
            count++;
        }
    }
    return count;
}
Decoding compiled method 0x00007fb360a1a0d0:
Code:
[Entry Point]
[Constants]
  # {method} 'testEqualsIntern' '()I' in 'Test'
  #           [sp+0x20]  (sp of caller)
  0x00007fb360a1a200: mov    0x8(%rsi),%r10d
  0x00007fb360a1a204: cmp    %r10,%rax
  0x00007fb360a1a207: jne    0x00007fb3609f38a0  ;   {runtime_call}
  0x00007fb360a1a20d: data32 xchg %ax,%ax
[Verified Entry Point]
  0x00007fb360a1a210: push   %rbp
  0x00007fb360a1a211: sub    $0x10,%rsp
  0x00007fb360a1a215: nop                       ;*synchronization entry
                                                ; - Test::testEqualsIntern@-1 (line 8)
  0x00007fb360a1a216: mov    $0x3e8,%eax
  0x00007fb360a1a21b: add    $0x10,%rsp
  0x00007fb360a1a21f: pop    %rbp
  0x00007fb360a1a220: test   %eax,0x6232dda(%rip)        # 0x00007fb366c4d000
                                                ;   {poll_return}
  0x00007fb360a1a226: retq
....[Hottest Region 1]..............................................................................
[0x7fb9e11acda0:0x7fb9e11acdc8] in org.sample.generated.MyBenchmark_testEqualsIntern::testEqualsIntern_thrpt_jmhLoop

                                                                ; - org.sample.generated.MyBenchmark_testEqualsIntern::testEqualsIntern_thrpt_jmhLoop@19 (line 103)
                  0x00007fb9e11acd82: movzbl 0x94(%rdx),%r11d   ;*getfield isDone
                                                                ; - org.sample.generated.MyBenchmark_testEqualsIntern::testEqualsIntern_thrpt_jmhLoop@29 (line 105)
                  0x00007fb9e11acd8a: mov    $0x2,%ebp
                  0x00007fb9e11acd8f: test   %r11d,%r11d
                  0x00007fb9e11acd92: jne    0x00007fb9e11acdcc  ;*ifeq
                                                                 ; - org.sample.generated.MyBenchmark_testEqualsIntern::testEqualsIntern_thrpt_jmhLoop@32 (line 105)
                  0x00007fb9e11acd94: nopl   0x0(%rax,%rax,1)
                  0x00007fb9e11acd9c: xchg   %ax,%ax            ;*aload
                                                                ; - org.sample.generated.MyBenchmark_testEqualsIntern::testEqualsIntern_thrpt_jmhLoop@13 (line 103)
6.50%    3.37%    0x00007fb9e11acda0: mov    0xb0(%rdi),%r11d   ;*getfield i1
                                                                ; - org.openjdk.jmh.infra.Blackhole::consume@2 (line 350)
                                                                ; - org.sample.generated.MyBenchmark_testEqualsIntern::testEqualsIntern_thrpt_jmhLoop@19 (line 103)
0.06%    0.05%    0x00007fb9e11acda7: mov    0xb4(%rdi),%r10d   ;*getfield i2
                                                                ; - org.openjdk.jmh.infra.Blackhole::consume@15 (line 350)
                                                                ; - org.sample.generated.MyBenchmark_testEqualsIntern::testEqualsIntern_thrpt_jmhLoop@19 (line 103)
0.06%    0.09%    0x00007fb9e11acdae: cmp    $0x3e8,%r10d
0.03%             0x00007fb9e11acdb5: je     0x00007fb9e11acdf1  ;*return
                                                                ; - org.openjdk.jmh.infra.Blackhole::consume@38 (line 354)
                                                                ; - org.sample.generated.MyBenchmark_testEqualsIntern::testEqualsIntern_thrpt_jmhLoop@19 (line 103)
48.85%   44.47%    0x00007fb9e11acdb7: movzbl 0x94(%rdx),%ecx    ;*getfield isDone
                                                                ; - org.sample.generated.MyBenchmark_testEqualsIntern::testEqualsIntern_thrpt_jmhLoop@29 (line 105)
0.33%    0.62%    0x00007fb9e11acdbe: add    $0x1,%rbp          ; OopMap{r9=Oop rbx=Oop rdi=Oop rdx=Oop off=226}
                                                                ;*ifeq
                                                                ; - org.sample.generated.MyBenchmark_testEqualsIntern::testEqualsIntern_thrpt_jmhLoop@32 (line 105)
0.03%    0.05%    0x00007fb9e11acdc2: test   %eax,0x16543238(%rip)        # 0x00007fb9f76f0000
                                                                ;   {poll}
42.31%   49.43%    0x00007fb9e11acdc8: test   %ecx,%ecx
                   0x00007fb9e11acdca: je     0x00007fb9e11acda0  ;*aload_2
                                                                ; - org.sample.generated.MyBenchmark_testEqualsIntern::testEqualsIntern_thrpt_jmhLoop@35 (line 106)
                  0x00007fb9e11acdcc: mov    $0x7fb9f706fe40,%r10
                  0x00007fb9e11acdd6: callq  *%r10              ;*invokestatic nanoTime
                                                                ; - org.sample.generated.MyBenchmark_testEqualsIntern::testEqualsIntern_thrpt_jmhLoop@36 (line 106)
                  0x00007fb9e11acdd9: mov    %rbp,0x10(%rbx)    ;*putfield operations
                                                                ; - org.sample.generated.MyBenchmark_testEqualsIntern::testEqualsIntern_thrpt_jmhLoop@51 (line 108)
                  0x00007fb9e11acddd: mov    %rax,0x28(%rbx)    ;*putfield stopTime
                                                                ; - org.sample.generated.MyBenchmark_testEqualsIntern::testEqualsIntern_thrpt_jmhLoop@39 (line 106)
....................................................................................................
public void testEqualsIntern_avgt_jmhLoop(InfraControl control, RawResults result, MyBenchmark_1_jmh l_mybenchmark0_0, Blackhole_1_jmh l_blackhole1_1) throws Throwable {
    long operations = 0;
    long realTime = 0;
    result.startTime = System.nanoTime();
    do {
        l_blackhole1_1.consume(l_mybenchmark0_0.testEqualsIntern());
        operations++;
    } while(!control.isDone);
    result.stopTime = System.nanoTime();
    result.realTime = realTime;
    result.operations = operations;
}