Java性能String.indexOf(char)与String.indexOf(单个String) [英] Java performance String.indexOf(char) vs String.indexOf(single String)

查看:167
本文介绍了Java性能String.indexOf(char)与String.indexOf(单个String)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为 String.indexOf(char)比使用单个字符&时 String.indexOf(String)单个字符串(例如,"x"和"x")

I think String.indexOf(char) is a little more faster than String.indexOf(String) when using single character & single String(ex, 'x' & "x")

为确保我的猜测,我编写了如下简单的测试代码.

To make sure my guessing, I wrote easy test code like below.

public static void main(String[] args) {
    IndexOfTest test = new IndexOfTest(Integer.parseInt(args[0]));

    test.run();
}

public IndexOfTest(int loop) {
    this.loop = loop;
}

public void run() {
    long start, end;
    start = System.currentTimeMillis();
    for(int i = 0 ; i < loop ; i++) {
        alphabet.indexOf("x");
    }
    end = System.currentTimeMillis();
    System.out.println("indexOf(String) : " + (end - start) + "ms");

    start = System.currentTimeMillis();
    for(int i = 0 ; i < loop ; i++) {
        alphabet.indexOf('x');
    }
    end = System.currentTimeMillis();
    System.out.println("indexOf(char) : " + (end - start) + "ms");

}

alphabet是具有"abcd ... xyzABCD ... XYZ"的String变量.

alphabet is String variable that has "abcd...xyzABCD...XYZ".

从这段代码中,我得到了这样的结果表...

from this code, I got result table like this...

loop     10^3  10^4  10^5  10^6  10^7

String      1     7     8     9     9

char        1     2     5    10    64

String.indexOf(String)看起来收敛到9ms,但是String.indexOf(char)呈指数增长.

String.indexOf(String) looks like converge to 9ms, however String.indexOf(char) increases exponentially.

我很困惑.在这种情况下,使用String是否有任何优化?还是我怎么知道这个结果?

I'm very confused. Is there any optimization for using String in this case? Or how I figure out this result?

我用以下两种基准测试方法运行jmh.每个方法都调用indexOf方法.

I ran jmh with below two benchmark method. Each method calls a indexOf method.

@State(Scope.Thread)
public class MyBenchmark {
    private String alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    @Benchmark
    public void indexOfString() {
        alphabet.indexOf("x");
    }

    @Benchmark
    public void indexOfChar() {
    alphabet.indexOf('x');
    }
}

结果:

Benchmark                   Mode  Cnt           Score        Error  Units
MyBenchmark.indexOfChar    thrpt   30   142106399.525 ±  51360.808  ops/s
MyBenchmark.indexOfString  thrpt   30  2178872840.575 ± 864573.421  ops/s

此结果还显示indexOf(String)更快..

This result also show indexOf(String) is faster..

我认为是时候考虑隐藏优化了

I think that it is time to think about hidden optimization

有什么主意吗?

推荐答案

您的JMH测试不正确,因为您不使用结果,因此 indexOf 调用可以是(或可以不是)完全由JIT编译器删除.在您的情况下,似乎JIT编译器确定 indexOf(String)没有副作用,并完全删除了此调用,但对 indexOf(char)却没有这样做代码>.始终使用结果(最简单的方法是从基准返回结果).这是我的版本:

Your JMH test is incorrect as you don't consume the result, so the indexOf call can be (or can be not) removed at all by JIT compiler. In your case it seems that JIT-compiler determined that indexOf(String) has no side-effect and removed this call at all, but did not do the same for indexOf(char). Always consume the result (the simplest way is to return it from the benchmark). Here's my version:

import java.util.*;
import java.util.concurrent.TimeUnit;

import org.openjdk.jmh.annotations.*;

@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Fork(3)
public class IndexOfTest { 
    private String str;
    private char c;
    private String s;

    @Setup
    public void setup() {
        str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        c = 'z';
        s = "z";
    }

    @Benchmark
    public int indexOfChar() {
        return str.indexOf('z');
    }

    @Benchmark
    public int indexOfString() {
        return str.indexOf("z");
    }

    @Benchmark
    public int indexOfCharIndirect() {
        return str.indexOf(c);
    }

    @Benchmark
    public int indexOfStringIndirect() {
        return str.indexOf(s);
    }
}

我测试了同一件事,但是增加了两个间接测试:从字段中加载搜索到的char或String时,因此在JIT编译期间其确切值是未知的.结果如下(Intel x64):

I test the same thing, but added two indirect tests: when searched char or String is loaded from the field, thus its exact value is unknown during the JIT-compilation. The results are the following (Intel x64):

# JMH 1.11.2 (released 27 days ago)
# VM version: JDK 1.8.0_45, VM 25.45-b02
Benchmark                          Mode  Cnt   Score   Error  Units
IndexOfTest.indexOfChar            avgt   30  25,364 ± 0,424  ns/op
IndexOfTest.indexOfCharIndirect    avgt   30  25,287 ± 0,210  ns/op
IndexOfTest.indexOfString          avgt   30  24,370 ± 0,100  ns/op
IndexOfTest.indexOfStringIndirect  avgt   30  27,198 ± 0,048  ns/op

如您所见,无论直接访问还是间接访问, indexOfChar 的执行方式都相同.对于直接访问, indexOfString 稍快,而对于间接访问, indexOfString 稍慢.这是因为 indexOf(String)是JVM固有的:实际上,其Java代码已由具有有效内联实现的JIT编译器代替.对于在JIT编译时已知的常量字符串,可以生成更有效的代码.

As you can see, indexOfChar performs in the same way regardless of direct or indirect access. The indexOfString is slightly faster for direct access, but somewhat slower for indirect. That's because indexOf(String) is a JVM intrinsic: its Java code is actually replaced by JIT compiler with efficient inline implementation. For constant string known at JIT compilation time it's possible to generate more efficient code.

通常,至少对于这样的短字符串没有太大的区别.因此,您可以将这两种方法中的任何一种用于单个符号匹配.

In general there's no big difference at least for such short strings. Thus you may use either of these methods for single symbol match.

这篇关于Java性能String.indexOf(char)与String.indexOf(单个String)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆