使用 JIT 编译器的 Collections.emptyList 和空 ArrayList 的性能

2024-01-12

使用之间是否有性能差异Collections.emptyList()或一个空的ArrayList,特别是在使用 JIT 编译器时?

我可以想象 - 例如 - JIT 编译器不会执行内联或静态方法调用,因为执行的方法取决于类型。

Edit我知道Collections.emptyList()返回一个不可变列表,同时ArrayList是可变对象。

我的意思是,如果我将其中一个或另一个作为参数传递给方法,并且该方法不修改列表,是否会限制 JIT 编译器优化该方法的可能性?

一个简单的例子(只是为了澄清我的意思):

int sum(List<Integer> list)
{
    int sum = 0;

    for(int i=0;i<list.size();++i)
      sum += list.get(i);

    return sum;
}

如果我只调用这个方法ArrayListJIT 编译器可以内联ArrayList.get()。如果我也拨打电话Collections.empty()这是不可能的。

那是对的吗?


免责声明

下面写的所有内容仅适用于热点 JVM https://en.wikipedia.org/wiki/HotSpot.

简短的答案

JIT 编译器不执行内联或静态方法调用,因为 执行的方法取决于类型。

这与事实相反。看我的回答。

使用之间是否有性能差异 Collections.emptyList() 或空 ArrayList,尤其是在使用 JIT 编译器?

在极少数情况下 - 是的。查看微基准测试结果。

如果我只使用 ArrayList 调用此方法,JIT 编译器可以 内联 ArrayList.get()。如果我也使用 Collections.empty() 进行调用 这是不可能的。那是对的吗?

简短的回答 - 这取决于。 JIT 编译器足够智能,可以识别单态、双态和多态调用模式并提供适当的实现。

Answer

为了获得详细的答案,我建议阅读以下内容post http://shipilev.net/blog/2015/black-magic-method-dispatch/关于方法调度的黑魔法。简而言之

C2 基于以下内容进行了有趣的配置文件引导优化 观察到的类型概况。如果只有一个接收器类型(即 是,调用站点是单态),它可以简单地检查 预测类型,并直接内联目标。同样的优化 如果观察到两种接收器类型(即 是,调用站点是双态),以两个分支为代价。

让我们考虑以下 JMH 示例(如果您还没有了解 JMH 那么我建议阅读它here http://openjdk.java.net/projects/code-tools/jmh/).

@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(value = 5)
public class ExampleBench {

    @Param("10000")
    private int count;

    List<Integer>[] arrays;
    List<Integer>[] empty;
    List<Integer>[] bimorphic;
    List<Integer>[] polimorphic;

    @Setup
    public void setup(){
        Random r = new Random(0xBAD_BEEF);
        arrays = new List[count];
        empty = new List[count];
        bimorphic = new List[count];
        polimorphic = new List[count];
        for (int i = 0; i < arrays.length; i++) {
            bimorphic[i] = r.nextBoolean() ? new ArrayList<Integer>(0) : Collections.<Integer>emptyList();
            int i1 = r.nextInt(3);
            switch (i1) {
                case 0 : polimorphic[i] = new ArrayList<>(0);
                    break;
                case 1 : polimorphic[i] = new LinkedList<>();
                    break;
                case 2 : polimorphic[i] = Collections.emptyList();
                    break;
            }
            arrays[i] = new ArrayList<>(0);
            empty[i] = Collections.emptyList();
        }
    }

    @Benchmark
    public float arrayList() {
        List<Integer>[] l = arrays;
        int c = count;
        float result = 0;
        for (int i = 0; i < c; i++) {
            result += sum(l[i]);
        }
        return result;
    }

    @Benchmark
    public float emptyList() {
        List<Integer>[] l = empty;
        int c = count;
        float result = 0;
        for (int i = 0; i < c; i++) {
            result += sum(l[i]);
        }
        return result;
    }

    @Benchmark
    public float biList() {
        List<Integer>[] l = bimorphic;
        int c = count;
        float result = 0;
        for (int i = 0; i < c; i++) {
            result += sum(l[i]);
        }
        return result;
    }

    @Benchmark
    public float polyList() {
        List<Integer>[] l = polimorphic;
        int c = count;
        float result = 0;
        for (int i = 0; i < c; i++) {
            result += sum(l[i]);
        }
        return result;
    }

    int sum(List<Integer> list) {
        int sum = 0;
        for (int i = 0; i < list.size(); ++i) {
            sum += list.get(i);
        }
        return sum;
    }
}

结果是:

Benchmark               (count)  Mode  Cnt       Score       Error  Units
ExampleBench.arrayList    10000  avgt    5   22902.547 ± 27665.651  ns/op
ExampleBench.biList       10000  avgt    5   50459.552 ±   739.379  ns/op
ExampleBench.emptyList    10000  avgt    5    3745.469 ±   211.794  ns/op
ExampleBench.polyList     10000  avgt    5  164879.943 ±  5830.008  ns/op

在单态和双态调用的情况下,JIT 用具体实现代替虚拟调用。例如,如果arrayList()我们有以下输出-XX:+PrintInlining:

@ 27   edu.jvm.runtime.ExampleBench::sum (38 bytes)   inline (hot)
   @ 6   java.util.ArrayList::size (5 bytes)   accessor
    \-> TypeProfile (15648/15648 counts) = java/util/ArrayList

for emptyList():

@ 27   edu.jvm.runtime.ExampleBench::sum (38 bytes)   inline (hot)
   @ 6   java.util.Collections$EmptyList::size (2 bytes)   inline (hot)
    \-> TypeProfile (9913/9913 counts) = java/util/Collections$EmptyList

for biList():

@ 27   edu.jvm.runtime.ExampleBench::sum (38 bytes)   inline (hot)
   @ 6   java.util.Collections$EmptyList::size (2 bytes)   inline (hot)
   @ 6   java.util.ArrayList::size (5 bytes)   accessor
    \-> TypeProfile (2513/5120 counts) = java/util/ArrayList
    \-> TypeProfile (2607/5120 counts) = java/util/Collections$EmptyList

的情况下polyList()JIT 不内联任何实现并使用真正的虚拟调用。

在这些方法中使用内联函数有什么优点?让我们看看编译器生成的代码arrayList():

0x00007ff9e51bce50: cmp $0xf80036dc,%r10d     ;instance of 'java/util/ArrayList'
0x00007ff9e51bce57: jne L0000                 ;if false go to L0000 (invokeinterface size)
0x00007ff9e51bce59: mov 0x10(%rdx),%ebp       ;*getfield size optimization java.util.ArrayList::size@1 

.....

0x00007ff9e51bce6d: retq
             L0000: mov $0xffffffde,%esi      ; true virtual call starts here
0x00007ff9e51bce73: mov %rdx,(%rsp)
0x00007ff9e51bce77: callq 0x00007ff9e50051a0  ; OopMap{[0]=Oop off=92}
                                              ;*invokeinterface size
                                              ; - edu.jvm.runtime.ExampleBench::sum@6 (line 119)
                                              ;   {runtime_call}

如您所见,JIT 通过以下方式替换了虚拟调用getfield.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 JIT 编译器的 Collections.emptyList 和空 ArrayList 的性能 的相关文章

  • Spring webflow 应用程序:HTTP 302 暂时移动

    我的 java 应用程序中的每个请求都会生成另外 2 个带有 HTTP 302 错误的请求 例如 如果请求查看名为板 html 这个请求是从首页 html 我收到按以下顺序生成的 3 个请求 POST home html 302 Moved
  • 有效地查找正则表达式的所有重叠匹配项

    这是后续与 java 正则表达式匹配的所有重叠子字符串 https stackoverflow com q 11303309 244526 有没有办法让这段代码更快 public static void allMatches String
  • JUnit 使用 Mockito 测试异步方法

    我已经使用 Spring Framework 版本 5 0 5 RELEASE 在 Java 1 8 类中实现了异步方法 public class ClassToBeTested Autowired private MyComponent
  • Maven + Cobertura:无法找到[您的班级]。你指定了源目录吗?

    我有 MyMath 类 有两个简单的方法 multi 和 add 和测试类只会测试多种方法 public class MainTest Test public void testMultiply MyMath tester new MyMa
  • 在气球内显示带有照片的多个地标的最佳做法是什么?

    我有一个项目如下 从手机上拍摄几张照片 将照片保存在网络系统中 然后将照片显示在其中的谷歌地球上 我读过很多文章 但它们都使用 fetchKml 我读过的一篇好文章是使用 php 但使用 fetchKml 我不知道是否可以使用 parseK
  • 如何在 OpenAPI 3.0 中定义字节数组

    我正在将 API 从 Swagger 2 0 迁移到 OpenAPI 3 0 在 DTO 中 我有一个指定为字节数组的字段 Swagger 对 DTO 的定义 Job type object properties body type str
  • 业务代表与服务定位器

    Business Delegate 和 Service Locator 之间有什么区别 两者都负责封装查找和创建机制 如果 Business Delegate 使用 Service Locator 来隐藏查找和创建机制 那么 Busines
  • 会话 bean 中的 EntityManager 异常处理

    我有一个托管无状态会话 bean 其中注入了 EntityManager em 我想做的是拥有一个具有唯一列的数据库表 然后我运行一些尝试插入实体的算法 但是 如果实体存在 它将更新它或跳过它 我想要这样的东西 try em persist
  • JSP 标签+ scriptlet。如何启用脚本?

    我有一个使用标签模板的页面 我的 web xml 非常基本 我只是想在页面中运行一些代码 不 我对标签或其他替代品不感兴趣 我想使用不好的做法 scriptlet 哈哈 到目前为止 我收到了 HTTP ERROR 500 错误 Script
  • 您能让 Tomcat 6 stdout.log 文件表现得像 log4j DailyRollingFileAppender 吗?

    我们使用的是 Tomcat 6 的 Windows 安装 默认情况下 我们应用程序的 log4j 输出将转到 catalina base logs stdout log 文件 该日志文件仅在我们重新启动 Tomcat 时滚动 并且文件名始终
  • 嵌入式 tomcat 7 servlet 3.0 注释不起作用

    我有一个精简的测试项目 其中包含 Servlet 版本 3 0 用注释声明 如下所示 WebServlet test public class TestServlet extends HttpServlet private static f
  • 如何消除 jQuery Mobile 中的悬停延迟?

    我正在使用 jQuery Mobile 制作一个网站 当我将鼠标悬停在按钮上时 它会更改其类 并扩展其颜色 但感觉需要半秒左右才能完成 有没有办法减少这种延迟 您可以覆盖hoverDelay无需修改 jQuery Mobile js 库 要
  • RMI 服务器:rmiregistry 或 LocateRegistry.createRegistry

    对于服务器端的RMI 我们需要启动吗rmiregistry程序 或者只是调用LocateRegistry createRegistry 如果两者都可以的话 各有什么优点和缺点 他们是同一件事 rmiregistry是一个单独的程序 您可以从
  • java中的比较器链

    正在阅读Oracle 关于接口的 Java 教程 https docs oracle com javase tutorial java IandI createinterface html其中给出了一个例子Card 打牌 我试图理解接口中的
  • 使用 Maven 3 时 Cobertura 代码覆盖率为 0%

    读完这篇文章后 将 Cobertura 与 Maven 3 0 2 一起使用的正确方法是什么 https stackoverflow com questions 6931360 what is the proper way to use c
  • 将字符串中的字符向左移动

    我是 Stack Overflow 的新手 有一道编程课的实验室问题一直困扰着我 该问题要求我们将字符串 s 的元素向左移动 k 次 例如 如果输入是 Hello World 和3 它将输出 lo WorldHel 对于非常大的 k 值 它
  • Scala repl 抛出错误

    当我打字时scala在终端上启动 repl 它会抛出此错误 scala gt init error error while loading AnnotatedElement class file usr lib jvm java 8 ora
  • 日期时间解析异常

    解析日期时 我的代码中不断出现异常错误 日期看起来像这样 Wed May 21 00 00 00 EDT 2008 这是尝试读取它的代码 DateTimeFormatter formatter DateTimeFormatter ofPat
  • VB.NET 是否优化字符串文字的串联?

    如同this https stackoverflow com questions 288794 does c optimize the concatenation of string literals问题 但对于 VB NET 来说 因为我
  • 如何在Java中跨类共享变量,我尝试了静态不起作用

    类 Testclass1 有一个变量 有一些执行会改变变量的值 现在在同一个包中有类 Testclass2 我将如何访问 Testclass2 中变量的更新值 由 Testclass1 更新 试过这个没用 注意 Testclass1和Tes

随机推荐

  • ZF2 - 需要在特定条件失败时显示特定错误消息

    我正在使用 ZF2 表单验证 我必须验证两个字段 用户名 和 密码 一切正常 但我收到类似的消息 Please enter username Username can not be less than 3 characters Please
  • 在 Eclipse 启动时禁用插件

    我刚刚为 Eclipse 安装了一个插件 但结果 Eclipse 将不再启动 它说 有一个错误 或一些此类无信息的消息 如何在不加载插件的情况下启动 Eclipse 以便我可以实际卸载有问题的软件 正如另一个人提到的 您可以尝试 clean
  • 处理 R 中冲突的命名空间(不同包中的相同函数名称):重置包命名空间的优先级

    不同包的命名空间之间的名称冲突R可能是危险的 并且使用package function不幸的是没有普遍化R 是否有一个函数可以重置包命名空间相对于当前加载的所有其他命名空间的优先级 我们当然可以detach然后重新加载包 但是没有其他更实用
  • 如何使用 Google App Engine 重定向所有 URL

    我该如何配置app yaml文件将所有 URL 重定向到另一个 URL 例如我想要http example appspot com hello or http example appspot com hello28928723重定向到htt
  • 有 CSS 父选择器吗?

    我该如何选择 li 是锚元素的直接父元素吗 举个例子 我的 CSS 应该是这样的 li lt a active property value 显然 有多种方法可以使用 JavaScript 实现此目的 但我希望 CSS Level 2 本身
  • 使用 terraform 获取金库秘密值

    我正在使用带有 consul 的保管库服务器作为存储后端 并尝试使用 terraform 中的保管库提供程序获取密码值 但它并没有获得它的价值 我将我的秘密存储在位置秘密 实例中 main tf provider vault address
  • 如何加速 Mongodump,转储未完成

    在尝试使用来自大约 50 亿个数据库的查询来运行数据库转储时 进度条时间似乎表明此转储不会在任何合理的时间 100 多天 内完成 大约 22 小时后 查询似乎以 0 结束后也冻结了 之后的行是metadata json 行 转储行是 mon
  • 复制同名属性的简单代码?

    我有一个old这个问题在我脑海里停留了很长时间 当我在 Spring 中编写代码时 有很多 DTO 域对象的脏代码和无用代码 对于语言级别 我对 Java 毫无希望 但在 Kotlin 中看到了一些曙光 这是我的问题 Style 1我们通常
  • 在 pyqt4 中旋转像素图会产生不需要的翻译

    我正在尝试编写一个简单的应用程序 在按下按钮时旋转 png 图像 我一切正常 只是当图像旋转时 它偏离了东南方向的中心 我本以为它不是绕着中心旋转 但每旋转 45 度它就会回到原点 这很奇怪 对于一个关键事件 我只是简单地调用 pixmap
  • 堆叠 LSTM 网络中每个 LSTM 层的输入是什么?

    我在理解堆叠 LSTM 网络中各层的输入输出流时遇到一些困难 假设我创建了一个如下所示的堆叠 LSTM 网络 parameters time steps 10 features 2 input shape time steps featur
  • 如果指令具有独立的作用域,为什么 ng-transinclude 的作用域不是其指令作用域的子级?

    给定一个指令 container1 具有嵌入和隔离作用域 当链接指令时 我有这些作用域 Scope 004 lt scope of the body Scope 005 lt scope of directive container1 Sc
  • 如何使用 phpstorm 和 xdebug 为 symfony2 设置远程调试

    Problem 我希望能够调试我的 symfony2 项目 我想成为 能够在我的代码中设置断点 运行远程调试并 能够在交互时单步执行代码中的所有断点 与我的申请 背景信息和当前设置 我使用的IDE是phpstorm Apache 和 myS
  • 如何清除 CrashLoopBackOff

    当 Kubernetes Pod 进入CrashLoopBackOff状态 您将解决根本问题 如何强制重新安排时间 要应用新配置 应创建新 Pod 旧 Pod 将被删除 如果您的 pod 是由以下人员自动创建的Deployment or D
  • 组名称无效:组名称必须以单词字符开头

    当我将 Regex 类与正则表达式一起使用时 我收到以下异常 named a asdf System ArgumentException parsing named a asdf Invalid group name Group names
  • MySQL SHOW COLUMNS 返回顺序

    我需要找到特定表中的列 这没有问题 SHOW COLUMNS FROM tablename LIKE ColumnPrefix 但我需要知道它们将返回什么顺序 最好选择按字母顺序对结果进行升序排序 我没有使用过运气ORDER BY 有任何想
  • 何时使用 mysql_real_escape_string?

    我什么时候应该使用 mysql real escape string 仅当我将行插入数据库时 才出现这种情况吗 或者只有当我有用户输入时 Thanks 每当您构建将针对数据库运行的查询时 您都应该使用 mysql real escape s
  • 如何使用 .htaccess 创建干净的 url

    这是我的 htaccess 代码 RewriteEngine On RewriteRule a zA Z0 9 movie php name 1 RewriteEngine on RewriteCond HTTP HOST www exam
  • MySQL如何存储数据

    我环顾谷歌但没有找到任何好的答案 它将数据存储在一个大文件中吗 它使用什么方法使数据访问比仅仅读写常规文件更快 这个问题有点老了 但我还是决定回答它 因为我一直在对此进行一些挖掘 我的答案是基于linux文件系统 基本上 mySQL 将数据
  • url 重写中附加文档根

    我想重写网址http www example com books PHP wrox http www example com books PHP wrox to http www example com manuals opensource
  • 使用 JIT 编译器的 Collections.emptyList 和空 ArrayList 的性能

    使用之间是否有性能差异Collections emptyList 或一个空的ArrayList 特别是在使用 JIT 编译器时 我可以想象 例如 JIT 编译器不会执行内联或静态方法调用 因为执行的方法取决于类型 Edit我知道Collec