求R大解答。关于Apache commons中StringUtils和JDK String Split方法的区别

艺流觞 2013-09-03

   做了个小测试,代码如下:

 

    String s = "1 2 3 4 51 2 3 4 51 2 3 4";
    int times = 1;
    long stime = 0;

    stime = System.currentTimeMillis();
    for (int i = 0; i < times; i++) {
         String[] split = StringUtils.split(s, " ");
    }

    System.out.println(System.currentTimeMillis() - stime);

 

     stime = System.currentTimeMillis();
     Pattern p = Pattern.compile(" ");
     for (int i = 0; i < times; i++) {
           String[] split = p.split(s);
     }
     System.out.println(System.currentTimeMillis() - stime);


对比得到数据如下:

  times     StringUtils.split     string.split    
     1                6ms                   0ms    
    10               9ms                   1ms    
   100             10ms                  5ms  
  1000            11ms                 11ms  
 10000           19ms                 31ms  
100000          70ms                245ms  

      看着觉得很奇怪,为什么这个耗时不是线性增加的,而且在循环次数少的时候,jdk提供的split更快一些。完全搞不懂啊,求解释~


 

RednaxelaFX 2013-09-03
楼主先帖一下具体测试的环境(JDK版本,具体的java -version)然后咱们再来具体讨论
subchen 2013-09-04
我的运行结果: jdk1.7.0_15 64bit (Window 7)

默认启用 JIT
times   StringUtils.split     string.split  
1           20                 1  
10          0                  2  
100         3                  20  
1000        32                 33  
10000       13                 97  
100000      56                 102  

禁用 JIT
times   StringUtils.split     string.split  
1           17                 1  
10          0                  1  
100         3                  20  
1000        26                 61  
10000       101                491  
100000      826                4971  

应该是 StringUtils.split 没有用正则表达式,所有速度会快一点,但是第一次很慢,是因为 jvm 第一次 load StringUtils.class 消耗的时间。 如果前面用 class.forName() 先加载一次那么就会变得很快。

好像 JIT 对 StringUtils.split 的优化影响比较大。
RednaxelaFX 2013-09-04
我之所以问具体版本是因为这里坑很多。例如这帖对Server VM所描述的 http://rednaxelafx.iteye.com/blog/1038324
楼主至少要说明具体是Client VM还是Server VM

另外JDK7的String.split在您的例子里也不用正则表达式的。这是2009年加入的功能:http://hg.openjdk.java.net/jdk7u/jdk7u/jdk/rev/1ff977b938e5
xionghan00 2013-09-05
楼主的 java -version 结果如下:

java version "1.6.0_29"
Java(TM) SE Runtime Environment (build 1.6.0_29-b11)
Java HotSpot(TM) Client VM (build 20.4-b02, mixed mode)

R大过目一下~
xionghan00 2013-09-05
按 subchen 的提示,Class.forName() 预先加载StringUtils类之后,再作对比

times   StringUtils.split     string.split  
1           0                  1  
10          0                  1  
100         1                  4  
1000        3                  11  
10000       8                  47  
100000      58                 267 

看来这个测试中出现的疑惑主要还是因为类加载的耗时。R大给确认一下呢?
subchen 2013-09-05
果然如 R 大所说,JDK 7 对 String.split 做了优化, 哈哈。
Global site tag (gtag.js) - Google Analytics