Java String =""与新String("")性能更改

use*_*766 1 java string performance microbenchmark

我在这篇文章中做了相同的测试: new String()vs literal string performance

意思是我想测试哪一个性能更好.正如我所料,结果是文字的分配更快.我不知道为什么,但我做了测试与一些更多的任务,我发现了一些奇怪:当我让程序做循环分配超过10000次的文字是相对没有那么多比少超过10000级更快的任务.并且在重复1.000.000时,它甚至比创建新对象更慢.

这是我的代码:

double tx = System.nanoTime();
for (int i = 0; i<1; i++){
    String s = "test";
}
double ty = System.nanoTime();

double ta = System.nanoTime();
for (int i = 0; i<1; i++){
    String s = new String("test");
}
double tb = System.nanoTime();

System.out.println((ty-tx));
System.out.println((tb-ta));
Run Code Online (Sandbox Code Playgroud)

我让它像上面写的那样运行.我只是在学习Java,而我的老板让我做测试,在我提出测试结果后,他让我找到答案,为什么会这样.我在谷歌或stackoverflow上找不到任何东西,所以我希望有人可以帮助我.

factor at         1 repetition   3,811565221
factor at        10 repetitions  4,393570401
factor at       100 repetitions  5,234779103
factor at     1,000 repetitions  7,909884116
factor at    10,000 repetitions  9,395538811
factor at   100,000 repetitions  2,355514697
factor at 1,000,000 repetitions  0,734826755
Run Code Online (Sandbox Code Playgroud)

谢谢!

Mar*_*nik 10

首先,你必须学习很多关于HotSpot内部的知识,特别是你的代码首先被解释,然后在编译成本机代码的某个点.

根据代码的静态和动态分析结果,在编译时会进行大量优化.

具体来说,在您的代码中,

String s = "test";
Run Code Online (Sandbox Code Playgroud)

是一个明确的无操作.编译器不会为此行发出任何代码.剩下的就是循环本身,如果HotSpot证明它没有可观察到的外部效果,整个循环可能会被消除.

第二,甚至是代码

String s = new String("test");
Run Code Online (Sandbox Code Playgroud)

可能会产生与上面几乎相同的东西,因为很容易证明你new String的实例无法从创建它的方法中逃脱.

使用您的代码,测量结果会混合解释的字节码的性能,编译代码所需的延迟以及通过堆栈替换进行交换,然后是本机代码的性能.

基本上,您正在进行的测量是测量除了您要测量的效果之外的所有测量.

为了使论证更加扎实,我重复了以下测试jmh:

@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 1, time = 1)
@Measurement(iterations = 3, time = 1)
@Threads(1)
@Fork(2)
public class Strings
{
  static final int ITERS = 1_000;
  @GenerateMicroBenchmark
  public void literal() {
    for (int i = 0; i < ITERS; i++) { String s = "test"; }
  }

  @GenerateMicroBenchmark
  public void newString() {
    for (int i = 0; i < ITERS; i++) { String s = new String("test"); }
  }
}
Run Code Online (Sandbox Code Playgroud)

这些是结果:

Benchmark     Mode   Samples         Mean   Mean error    Units
literal       avgt         6        0.625        0.023    ns/op
newString     avgt         6       43.778        3.283    ns/op
Run Code Online (Sandbox Code Playgroud)

您可以看到,在字符串文字的情况下,整个方法体被消除了,而new String循环仍然存在,但没有任何内容,因为每个循环迭代的时间仅为0.04纳秒.绝对没有String分配实例.