栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

为什么“ new”关键字比赋值效率高得多?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

为什么“ new”关键字比赋值效率高得多?

TL; DR部分

好消息

您的测量确实显示出真实的效果。

坏消息

它之所以这样做是偶然的,因为您的基准测试存在许多技术缺陷,而它所暴露的效果可能并非您所想到的。

当且仅当 HotSpot的转义分析成功证明可以将生成的实例安全地分配到堆栈而不是堆上时,该

newCharacter()
方法才会更快。因此,效果不如您的问题所暗示的那么普遍。 __

效果说明

new Character()
更快的原因是 引用的局部性 :您的实例在堆栈中,并且通过CPU高速缓存命中对其进行的所有访问。重用缓存的实例时,必须

  1. 访问远程
    static
    字段;
  2. 解引用到远程数组;
  3. 将数组条目取消引用到远程
    Character
    实例;
  4. 访问
    char
    该实例中包含的内容。

每个取消引用都是潜在的CPU高速缓存未命中。此外,它强制将一部分高速缓存重定向到那些远程位置,从而在输入字符串和/或堆栈位置上导致更多的高速缓存未命中。

细节

我已经使用以下代码运行了此代码

jmh

@OutputTimeUnit(TimeUnit.MICROSECONDS)@BenchmarkMode(Mode.AverageTime)public class Chars {  static String string = "12345678901234567890"; static {    for (int i = 0; i < 10; i++) string += string;  }  @GenerateMicroBenchmark  public void newChar() {    int len = string.length();    for (int i = 0; i < len; i++) new Character(string.charAt(i));  }  @GenerateMicroBenchmark  public void justChar() {    int len = string.length();    for (int i = 0; i < len; i++) Character.valueOf(string.charAt(i));  }}

这保留了代码的本质,但消除了一些系统性错误,如预热和编译时间。结果如下:

Benchmark   Mode Thr    Cnt  Sec         Mean   Mean error    Unitso.s.Chars.justChar     avgt   1      3    5       39.062        6.587  usec/opo.s.Chars.newChar      avgt   1      3    5       19.114        0.653  usec/op

这是我对发生的事情的最佳猜测:

  • newChar
    您创建一个 的实例
    Character
    。HotSpot的转义分析可以证明实例永不转义,因此它允许堆栈分配,或者在特殊情况下
    Character
    ,可以完全取消分配,因为证明来自该数据从未使用过。

  • justChar
    你涉及查找到
    Character
    高速缓存阵列,其中有 一些 成本。

更新

为了回应Aleks的批评,我在基准测试中添加了更多方法。主要效果保持稳定,但是我们获得了有关次优效果的更多细粒度信息。

  @GenerateMicroBenchmark  public int newCharUsed() {    int len = string.length(), sum = 0;    for (int i = 0; i < len; i++) sum += new Character(string.charAt(i));    return sum;  }  @GenerateMicroBenchmark  public int justCharUsed() {    int len = string.length(), sum = 0;    for (int i = 0; i < len; i++) sum += Character.valueOf(string.charAt(i));    return sum;  }  @GenerateMicroBenchmark  public void newChar() {    int len = string.length();    for (int i = 0; i < len; i++) new Character(string.charAt(i));  }  @GenerateMicroBenchmark  public void justChar() {    int len = string.length();    for (int i = 0; i < len; i++) Character.valueOf(string.charAt(i));  }  @GenerateMicroBenchmark  public void newCharValue() {    int len = string.length();    for (int i = 0; i < len; i++) new Character(string.charAt(i)).charValue();  }  @GenerateMicroBenchmark  public void justCharValue() {    int len = string.length();    for (int i = 0; i < len; i++) Character.valueOf(string.charAt(i)).charValue();  }

描述:

  • 基本版本是
    justChar
    newChar
    ;
  • ...Value
    方法将
    charValue
    调用添加到基本版本中;
  • ...Used
    方法会
    charValue
    隐式地添加调用,并 使用 该值排除任何死代码消除。

结果:

Benchmark        Mode Thr    Cnt  Sec         Mean   Mean error    Unitso.s.Chars.justChar          avgt   1      3    1      246.847        5.969  usec/opo.s.Chars.justCharUsed      avgt   1      3    1      370.031       26.057  usec/opo.s.Chars.justCharValue     avgt   1      3    1      296.342       60.705  usec/opo.s.Chars.newCharavgt   1      3    1      123.302       10.596  usec/opo.s.Chars.newCharUsed       avgt   1      3    1      172.721        9.055  usec/opo.s.Chars.newCharValue      avgt   1      3    1      123.040        5.095  usec/op
  • 有证据表明,在和变体中都消除了 某些 死代码(DCE),但这只是部分的;
    justChar``newChar
  • 对于
    newChar
    变体,添加
    charValue
    没有任何作用,因此显然是DCE的;
  • justChar
    charValue
    确实有作用,因此似乎没有被消除;
  • newCharUsed
    和之间的稳定差异可以证明DCE的总体影响较小
    justCharUsed


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/497816.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号