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

静态空数组实例的性能优势

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

静态空数组实例的性能优势

我对这两个习惯用法在实际,现实世界中的实际性能差异最感兴趣。我没有进行微基准测试的经验(它可能不是解决此类问题的正确工具),但我还是尝试了一下。

该基准模拟了一个较为典型的“现实”设置。仅查看返回的数组,然后将其丢弃。没有参考信息,不需要参考相等性。

一个接口,两个实现:

public interface Parser {    String[] supportedSchemas();    void parse(String s);}public class NoopParserStaticArray implements Parser {    private static final String[] EMPTY_STRING_ARRAY = new String[0];    @Override public String[] supportedSchemas() {        return EMPTY_STRING_ARRAY;    }    @Override public void parse(String s) {        s.prePoints().count();    }}public class NoopParserNewArray implements Parser {    @Override public String[] supportedSchemas() {        return new String[0];    }    @Override public void parse(String s) {        s.prePoints().count();    }}

以及JMH基准测试:

import org.openjdk.jmh.annotations.Benchmark;public class EmptyArrayBenchmark {    private static final Parser NOOP_PARSER_STATIC_ARRAY = new NoopParserStaticArray();    private static final Parser NOOP_PARSER_NEW_ARRAY = new NoopParserNewArray();    @Benchmark    public void staticEmptyArray() {        Parser parser = NOOP_PARSER_STATIC_ARRAY;        for (String schema : parser.supportedSchemas()) { parser.parse(schema);        }    }    @Benchmark    public void newEmptyArray() {        Parser parser = NOOP_PARSER_NEW_ARRAY;        for (String schema : parser.supportedSchemas()) { parser.parse(schema);        }    }}

我的机器上的结果Java 1.8.0_51(HotSpot VM):

Benchmark        Mode  CntScore          Error  UnitsEmptyArrayBenchmark.staticEmptyArray  thrpt   60  3024653836.077 ± 37006870.221  ops/sEmptyArrayBenchmark.newEmptyArray     thrpt   60  3018798922.045 ± 33953991.627  ops/sEmptyArrayBenchmark.noop   thrpt   60  3046726348.436 ±  5802337.322  ops/s

在这种情况下,两种方法之间没有显着差异。实际上,它们与无操作情况是没有区别的:显然,JIT编译器认识到返回的数组始终为空,并完全优化了循环!

用管道

parser.supportedSchemas()
插入黑洞而不是在其上循环,使静态数组实例的方法具有约30%的优势。但是它们的大小绝对相同:

Benchmark        Mode  CntScore         Error  UnitsEmptyArrayBenchmark.staticEmptyArray  thrpt   60   338971639.355 ±  738069.217  ops/sEmptyArrayBenchmark.newEmptyArray     thrpt   60   266936194.767 ±  411298.714  ops/sEmptyArrayBenchmark.noop   thrpt   60  3055609298.602 ± 5694730.452  ops/s

最终,答案可能是通常的“取决于情况”。我有一种预感,在许多实际情况下, 将数组创建分解出去的 性能 优势并不明显。

我认为可以这样说

  • 如果方法合同使您每次可以自由返回一个新的空数组实例,并且
  • 除非您需要避免出现问题性或病理性使用模式和/或追求理论上的最佳性能,

然后

new String[0]
直接返回就可以了。

就个人而言,我喜欢的表现力和简洁性

return new String[0];
,而不必引入额外的静态场。


出乎我的意料,我写这篇文章一个月后,一位真正的性能工程师调查了这个问题:请参阅AlexeyShipilёv的博客文章“远古智慧的数组”中的这一部分:

如预期的那样, 在很小的集合大小上可以观察到唯一的影响,而这仅是对的边际改进

newFoo[0]
这种改进似乎并不能证明在事物的整体方案中缓存阵列是合理的。作为微小的微优化,在一些严格的代码中可能有意义,但我不在乎。

这样就解决了。我将勾选标记并将其专用于Alexey。



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

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

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