jit 会优化新对象吗

2023-12-26

我创建这个类是为了不可变并且具有流畅的 API:

public final class Message {
    public final String email;
    public final String escalationEmail;
    public final String assignee;
    public final String conversationId;
    public final String subject;
    public final String userId;

    public Message(String email, String escalationEmail, String assignee, String conversationId, String subject, String userId) {
        this.email = email;
        this.escalationEmail = escalationEmail;
        this.assignee = assignee;
        this.conversationId = conversationId;
        this.subject = subject;
        this.userId = userId;
    }

    public Message() {
        email = "";
        escalationEmail = "";
        assignee = "";
        conversationId = "";
        subject = "";
        userId = "";
    }

    public Message email(String e) { return new Message(e, escalationEmail, assignee, conversationId, subject, userId); }
    public Message escalationEmail(String e) { return new Message(email, e, assignee, conversationId, subject, userId); }
    public Message assignee(String a) { return new Message(email, escalationEmail, a, conversationId, subject, userId); }
    public Message conversationId(String c) { return new Message(email, escalationEmail, assignee, c, subject, userId); }
    public Message subject(String s) { return new Message(email, escalationEmail, assignee, conversationId, s, userId); }
    public Message userId(String u) { return new Message(email, escalationEmail, assignee, conversationId, subject, u); }

}

我的问题是,当像这样创建新对象时,优化器是否能够避免大量对象创建:

Message m = new Message()
    .email("f[email protected] /cdn-cgi/l/email-protection")
    .assignee("[email protected] /cdn-cgi/l/email-protection")
    .subject("subj");

制作一个单独的可变构建器对象有什么好处吗?

更新2:阅读 apangin 的答案后,我的基准测试无效。我将其保留在这里,以供参考如何不进行基准测试:)

Update:我冒昧地用这段代码自己测量了这一点:

public final class Message {
public final String email;
public final String escalationEmail;
public final String assignee;
public final String conversationId;
public final String subject;
public final String userId;

public static final class MessageBuilder {
    private String email;
    private String escalationEmail;
    private String assignee;
    private String conversationId;
    private String subject;
    private String userId;

    MessageBuilder email(String e) { email = e; return this; }
    MessageBuilder escalationEmail(String e) { escalationEmail = e; return this; }
    MessageBuilder assignee(String e) { assignee = e; return this; }
    MessageBuilder conversationId(String e) { conversationId = e; return this; }
    MessageBuilder subject(String e) { subject = e; return this; }
    MessageBuilder userId(String e) { userId = e; return this; }

    public Message create() {
        return new Message(email, escalationEmail, assignee, conversationId, subject, userId);
    }

}

public static MessageBuilder createNew() {
    return new MessageBuilder();
}

public Message(String email, String escalationEmail, String assignee, String conversationId, String subject, String userId) {
    this.email = email;
    this.escalationEmail = escalationEmail;
    this.assignee = assignee;
    this.conversationId = conversationId;
    this.subject = subject;
    this.userId = userId;
}

public Message() {
    email = "";
    escalationEmail = "";
    assignee = "";
    conversationId = "";
    subject = "";
    userId = "";
}

public Message email(String e) { return new Message(e, escalationEmail, assignee, conversationId, subject, userId); }
public Message escalationEmail(String e) { return new Message(email, e, assignee, conversationId, subject, userId); }
public Message assignee(String a) { return new Message(email, escalationEmail, a, conversationId, subject, userId); }
public Message conversationId(String c) { return new Message(email, escalationEmail, assignee, c, subject, userId); }
public Message subject(String s) { return new Message(email, escalationEmail, assignee, conversationId, s, userId); }
public Message userId(String u) { return new Message(email, escalationEmail, assignee, conversationId, subject, u); }


static String getString() {
    return new String("hello");
    // return "hello";
}

public static void main(String[] args) {
    int n = 1000000000;

    long before1 = System.nanoTime();

    for (int i = 0; i < n; ++i) {
        Message m = new Message()
                .email(getString())
                .assignee(getString())
                .conversationId(getString())
                .escalationEmail(getString())
                .subject(getString())
                .userId(getString());
    }

    long after1 = System.nanoTime();

    long before2 = System.nanoTime();

    for (int i = 0; i < n; ++i) {
        Message m = Message.createNew()
                .email(getString())
                .assignee(getString())
                .conversationId(getString())
                .escalationEmail(getString())
                .subject(getString())
                .userId(getString())
                .create();
    }

    long after2 = System.nanoTime();



    System.out.println("no builder  : " + (after1 - before1)/1000000000.0);
    System.out.println("with builder: " + (after2 - before2)/1000000000.0);
}


}

我发现如果字符串参数不是新对象,但都是相同的(请参阅 getString 中的注释代码),差异是显着的(构建器更快)

在我想象的更现实的场景中,当所有字符串都是新对象时,差异可以忽略不计,并且 JVM 启动会导致第一个字符串稍微慢一点(我尝试了两种方法)。

使用“新字符串”,代码总共也慢了很多倍(我不得不减少n),也许表明正在对“新消息”进行一些优化,但对“新字符串”没有进行优化。


是的,HotSpot JIT 可以消除本地上下文中的冗余分配。

这种优化是由逃逸分析 http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html#escapeAnalysis从 JDK 6u23 开始启用。它经常与栈上分配相混淆,但实际上它更强大,因为它不仅允许在栈上分配对象,还可以通过用变量替换对象字段(标量替换)来完全消除分配,这些变量会受到进一步的影响。优化。

优化控制由-XX:+EliminateAllocationsJVM 选项默认为 ON。


由于分配消除优化,您创建的两个示例Message对象以同样的方式有效地工作。它们不分配中间对象;只是最后一张。

您的基准测试显示了误导性的结果,因为它收集了许多常见的陷阱 http://www.oracle.com/technetwork/articles/java/architect-benchmarking-2266277.html微基准测试:

  • 它在一个方法中整合了多个基准;
  • 它测量一个OSR stub https://stackoverflow.com/questions/9105505/differences-between-just-in-time-compilation-and-on-stack-replacement而不是最终编译版本;
  • 它不进行预热迭代;
  • 它不消耗结果等。

让我们正确测量它JMH http://openjdk.java.net/projects/code-tools/jmh/。作为奖励,JMH 拥有分配分析器(-prof gc)显示每次迭代实际分配了多少字节。我添加了运行的第三个测试EliminateAllocations禁用优化以显示差异。

package bench;

import org.openjdk.jmh.annotations.*;

@State(Scope.Benchmark)
public class MessageBench {

    @Benchmark
    public Message builder() {
        return Message.createNew()
                .email(getString())
                .assignee(getString())
                .conversationId(getString())
                .escalationEmail(getString())
                .subject(getString())
                .userId(getString())
                .create();
    }

    @Benchmark
    public Message immutable() {
        return new Message()
                .email(getString())
                .assignee(getString())
                .conversationId(getString())
                .escalationEmail(getString())
                .subject(getString())
                .userId(getString());
    }

    @Benchmark
    @Fork(jvmArgs = "-XX:-EliminateAllocations")
    public Message immutableNoOpt() {
        return new Message()
                .email(getString())
                .assignee(getString())
                .conversationId(getString())
                .escalationEmail(getString())
                .subject(getString())
                .userId(getString());
    }

    private String getString() {
        return "hello";
    }
}

这是结果。两个都builder and immutable性能相同,每次迭代仅分配 40 个字节(正好是一个迭代的大小)Message目的)。

Benchmark                                        Mode  Cnt     Score     Error   Units
MessageBench.builder                             avgt   10     6,232 ±   0,111   ns/op
MessageBench.immutable                           avgt   10     6,213 ±   0,087   ns/op
MessageBench.immutableNoOpt                      avgt   10    41,660 ±   2,466   ns/op

MessageBench.builder:·gc.alloc.rate.norm         avgt   10    40,000 ±   0,001    B/op
MessageBench.immutable:·gc.alloc.rate.norm       avgt   10    40,000 ±   0,001    B/op
MessageBench.immutableNoOpt:·gc.alloc.rate.norm  avgt   10   280,000 ±   0,001    B/op
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

jit 会优化新对象吗 的相关文章

  • 按键时关闭 ModalWindow

    我希望能够在用户按下某个键 在我的例子中是 ESC 时关闭 ModalWindow 我有一个用于按键的 Javascript 侦听器 它调用取消按钮 ID 的单击事件 jQuery modalWindowInfo closeButtonId
  • Junit:如何测试从属性文件读取属性的方法

    嗨 我有课ReadProperty其中有一个方法ReadPropertyFile返回类型的Myclass从属性文件读取参数值并返回Myclass目的 我需要帮助来测试ReadPropertyFile方法与JUnit 如果可能的话使用模拟文件
  • 如何循环遍历所有组合,例如48 选择 5 [重复]

    这个问题在这里已经有答案了 可能的重复 如何在java中从大小为n的集合中迭代生成k个元素子集 https stackoverflow com questions 4504974 how to iteratively generate k
  • 使用 LinkedList 实现下一个和上一个按钮

    这可能是一个愚蠢的问题 但我很难思考清楚 我编写了一个使用 LinkedList 来移动加载的 MIDI 乐器的方法 我想制作一个下一个和一个上一个按钮 以便每次单击该按钮时都会遍历 LinkedList 如果我硬编码itr next or
  • 如何使用assertEquals 和 Epsilon 在 JUnit 中断言两个双精度数?

    不推荐使用双打的assertEquals 我发现应该使用带有Epsilon的形式 这是因为双打不可能100 严格 但无论如何我需要比较两个双打 预期结果和实际结果 但我不知道该怎么做 目前我的测试如下 Test public void te
  • Java 集合的并集或交集

    建立并集或交集的最简单方法是什么Set在 Java 中 我见过这个简单问题的一些奇怪的解决方案 例如手动迭代这两个集合 最简单的单行解决方案是这样的 set1 addAll set2 Union set1 retainAll set2 In
  • 无法创建请求的服务[org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]-MySQL

    我是 Hibernate 的新手 我目前正在使用 Spring boot 框架并尝试通过 hibernate 创建数据库表 我知道以前也问过同样的问题 但我似乎无法根据我的环境找出如何修复错误 休眠配置文件
  • volatile、final 和synchronized 安全发布的区别

    给定一个带有变量 x 的 A 类 变量 x 在类构造函数中设置 A x 77 我们想将 x 发布到其他线程 考虑以下 3 种变量 x 线程安全 发布的情况 1 x is final 2 x is volatile 3 x 设定为同步块 sy
  • Spring Boot Data JPA 从存储过程接收多个输出参数

    我尝试通过 Spring Boot Data JPA v2 2 6 调用具有多个输出参数的存储过程 但收到错误 DEBUG http nio 8080 exec 1 org hibernate engine jdbc spi SqlStat
  • tomcat 中受密码保护的应用程序

    我正在使用 JSP Servlet 开发一个Web应用程序 并且我使用了Tomcat 7 0 33 as a web container 所以我的要求是tomcat中的每个应用程序都会password像受保护的manager applica
  • 在我的 Spring Boot 示例中无法打开版本 3 中的 Swagger UI

    我在 Spring Boot 示例中打开 swagger ui 时遇到问题 当我访问 localhost 8080 swagger ui 或 localhost 8080 root api name swagger ui 时出现这种错误 S
  • 关键字“table”附近的语法不正确,无法提取结果集

    我使用 SQL Server 创建了一个项目 其中包含以下文件 UserDAO java public class UserDAO private static SessionFactory sessionFactory static se
  • 专门针对 JSP 的测试驱动开发

    在理解 TDD 到底是什么之前 我就已经开始编写测试驱动的代码了 在没有实现的情况下调用函数和类可以帮助我以更快 更有效的方式理解和构建我的应用程序 所以我非常习惯编写代码 gt 编译它 gt 看到它失败 gt 通过构建其实现来修复它的过程
  • 最新的 Hibernate 和 Derby:无法建立 JDBC 连接

    我正在尝试创建一个使用 Hibernate 连接到 Derby 数据库的准系统项目 我正在使用 Hibernate 和 Derby 的最新版本 但我得到的是通用的Unable to make JDBC Connection error 这是
  • 我如何在java中读取二进制数据文件

    因此 我正在为学校做一个项目 我需要读取二进制数据文件并使用它来生成角色的统计数据 例如力量和智慧 它的设置是让前 8 位组成一个统计数据 我想知道执行此操作的实际语法是什么 是不是就像读文本文件一样 这样 File file new Fi
  • 如何使用mockito模拟构建器

    我有一个建造者 class Builder private String name private String address public Builder setName String name this name name retur
  • 使用反射覆盖最终静态字段是否有限制?

    在我的一些单元测试中 我在最终静态字段上的反射中遇到了奇怪的行为 下面是说明我的问题的示例 我有一个基本的 Singleton 类 其中包含一个 Integer public class BasicHolder private static
  • 在java中为组合框分配键

    我想添加一个JComboBox在 Swing 中这很简单 但我想为组合中的每个项目分配值 我有以下代码 JComboBox jc1 new JComboBox jc1 addItem a jc1 addItem b jc1 addItem
  • Spring Rest 和 Jsonp

    我正在尝试让我的 Spring Rest 控制器返回jsonp但我没有快乐 如果我想返回 json 但我有返回的要求 完全相同的代码可以正常工作jsonp我添加了一个转换器 我在网上找到了用于执行 jsonp 转换的源代码 我正在使用 Sp
  • Java中super关键字的范围和使用

    为什么无法使用 super 关键字访问父类变量 使用以下代码 输出为 feline cougar c c class Feline public String type f public Feline System out print fe

随机推荐

  • 作为 Snakemake 工作流程输入的值数组

    我开始将我的工作流程从Nextflow to Snakemake并且已经在我的管道开始处碰壁了 管道通常以数字列表开头 代表我们检测器的 运行编号 我所拥有的例如是run list txt like detector id run numb
  • 如何使用 EF Core 在 ASP.NET Core 中取消应用迁移

    当我跑步时PM gt Remove Migration context BloggingContext在 VS2015 中使用 EF Core 的 ASP NET Core 项目出现以下错误 System InvalidOperationE
  • fastApi 中的 python 全局变量无法正常工作

    我有一个简单的 fastApi 演示应用程序 它实现了一个功能 通过调用名为changeResponse的post api来获取不同的响应json changeResponse api只是改变了一个全局变量 另一个api通过同一个全局变量返
  • 手机上的陀螺仪漂移

    很多帖子都讨论了陀螺仪漂移问题 有些人说陀螺仪读数有漂移 但其他人说积分有漂移 原始陀螺仪读数有漂移 link https stackoverflow com questions 1586658 combine gyroscope and
  • 在 ASCIIFoldingFilter 中使用静态“foldToAscii”方法

    我一直在使用 ASCII 折叠过滤器来处理变音符号 不仅适用于弹性搜索中的文档 还适用于各种其他类型的字符串 public static String normalizeText String text boolean shouldTrim
  • 单个解析服务器中的多个应用程序

    我花了整整一周的时间将 parse com 上托管的应用程序迁移到解析服务器 设法使一切完美运行 唯一的问题是让它在单个硬件上运行多个应用程序 而无需为此分配服务器应用程序它有 它会变得昂贵 我读了这个讨论 https github com
  • android 多数据源的分页库DataSource.Factory

    我有多个数据源 但只有一个DataSourceFactory 因此 所有来源都共享一个工厂 我需要每个数据源一个 DataSourceFactory 在我的应用程序中 我有多个 RecyclerViews 视图 因此有多个自定义数据源 那么
  • PHP 5.4 中删除 safe_mode 后的安全性在哪里

    我心里有一个棘手的问题 safe modePHP 5 4 中已删除 那么此删除的安全性如何 这是否意味着任何应用程序都可以执行任何程序 为此目的使用什么技术来防止此类暴力行为 本文 http ilia ws archives 18 PHPs
  • java.lang.SecurityException AWSCredentialsProvider 签名者信息不匹配

    我正在使用 2 个亚马逊提供的库 redshift jdbc42 1 2 27 1051 and aws java sdk core 1 11 600 两个库都定义了一个类AWSCredentialsProvider包装下com amazo
  • 将文件从服务器下载到 Ionic2 应用程序中

    我需要在我的中实现一个功能Ionic2用户可以将特定视频文件下载到 Ionic2 应用程序中 经检查Ionic Native部分 我发现以下插件可用 File 文件选择器 文件开启器 文件路径 但找不到诸如 cordova 插件 文件传输
  • 如何在Windows 10上更改Node JS进程名称?

    我有一个node js在 Windows 10 上运行的进程 我想更改进程的名称 以便可以获得一些性能详细信息 我尝试改变流程 标题的财产process对象但是 它不会反映在电源外壳中 我只能找到node作为进程名称 有没有其他方法可以更改
  • Exhaustive-deps 规则无法将自定义挂钩的结果识别为 React 参考

    想象一个钩子 export function useMounted const mounted React useRef
  • Spring Boot 多数据库:没有 EntityManagerFactoryBuilder 类型的合格 bean

    我们的 Spring Boot 应用程序中有两个数据库 称为源数据库和目标数据库 这是这些的配置 源配置 package com alex myapp config import javax persistence EntityManage
  • PHP 字符串类型提示 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在另一个线程完成时停止一个线程

    我有这个代码 Thread thread1 new Thread this DoSomething1 Thread thread2 new Thread this DoSomething2 thread1 Start thread2 Sta
  • OpenSSL:加密/解密例程的输入和输出缓冲区可以相同吗?

    例如 在 int EVP EncryptUpdate EVP CIPHER CTX ctx unsigned char out int outl unsigned char in int inl can out in 我只是偶然发现这个问题
  • 如何限制临时表的大小?

    我的数据库中有较大的 InnoDB 表 显然 用户能够使用 JOIN 进行 SELECT 从而生成临时的大型 因此位于磁盘上 表 有时 它们太大以至于耗尽了磁盘空间 导致各种奇怪的问题 有没有办法限制临时表的最大大小对于磁盘上的表 这样表就
  • 将参数值作为rails中的查询字符串传递给redirect_to

    这应该很简单 但我似乎找不到简单的答案 如何将当前请求中的参数值传递到redirect to 调用中 我想将一些表单值传递到 GET 重定向的查询字符串中 我想做这样的事情 redirect to thing foo gt params f
  • 查找多个 NumPy 数组的中值

    我有一个创建大约 50 个数组的 for 循环 数组的长度为 240 我试图找出计算数组每个元素的中值的最佳方法 本质上 我想获取循环中创建的每个数组的第一个元素 将它们放入列表中 然后找到中位数 然后对其他 239 个元素执行相同的操作
  • jit 会优化新对象吗

    我创建这个类是为了不可变并且具有流畅的 API public final class Message public final String email public final String escalationEmail public