【问题标题】:Java performance: true vs. Boolean.TRUEJava 性能:true 与 Boolean.TRUE
【发布时间】:2011-08-02 11:49:44
【问题描述】:

以下哪项在性能和内存使用效率方面更好?

Boolean isItTrue(arg){ 
    return Boolean.TRUE;
}

boolean isItTrue(arg){
    return Boolean.TRUE
}

Boolean isItTrue(arg){
    return true;
}

boolean isItTrue(arg){
    return true;
}

使用原始类型应该更快更容易,但另一方面,当使用对静态对象的引用时,不会创建新值。还是在编译器级别进行了优化,将所有truefalse 替换为对静态对象的引用以节省内存?

【问题讨论】:

  • 可能是微优化。它是在什么上下文中调用的?
  • 可能可以帮助这个thread

标签: java performance boolean memory-footprint


【解决方案1】:

首先,使用任何一个比其他任何一个的性能优势很可能太小而无法相关。在绝大多数情况下,代码的简单性/可读性/可维护性要重要得多。


这些示例均不涉及创建 Boolean 实例。

理论上,这 4 个中的 3 个可能触发 Boolean 类的初始化AND,否则您的应用程序不会这样做。在那个极不可能事件中,您的整个应用程序将分配 2 个原本不会被分配的对象。初始化可能需要几微秒,并且从长远来看会消耗几个字节的 RAM(小于 50)。


这将等于或比所有其他的更快,因为它只需将寄存器设置为零。

boolean isItTrue(arg){
    return true;
}

单独来看,这必须从内存中加载静态引用,而不是将寄存器归零。但是,在某些情况下,JIT 编译器可能会对此进行优化。

Boolean isItTrue(arg){ 
    return Boolean.TRUE;
}

从表面上看,这涉及对Boolean.valueOf(true) 的调用以“装箱”true,但 JIT 编译器应该能够通过内联调用将其优化为与前一个相同的代码。

Boolean isItTrue(arg){
    return true;
}

从表面上看,这涉及调用Boolean.booleanValue(Boolean.TRUE) 以“拆箱”Boolean。此调用可以内联。 JIT 编译器也有可能避免加载对Boolean 对象的引用并获取其值字段。

boolean isItTrue(arg){
    return Boolean.TRUE
}

底线是 4 种替代方案的相对性能取决于 JIT 编译器在优化方面的成功程度。这将取决于上下文、JIT 编译器的具体情况、JVM 设置等。在最好的情况下,JIT 编译器可以(至少在理论上)为所有这些生成相同的(最佳)代码。

【讨论】:

    【解决方案2】:

    如果有任何性能提升,它是如此微不足道,以至于无关紧要。 Boolean.TRUE 和 Boolean.FALSE 在任何情况下都不会返回新对象。

    【讨论】:

      【解决方案3】:

      对于此类微优化,代码维护人员应更加清晰。问题不应该是“哪个更小/更快”,首先要表达你的意思。

      如果方法返回一个布尔对象,那么接收者需要确定它是否有可能为空,如果它为空,它可能意味着不同于真/假的东西,比如“我们不知道”。

      所以返回 boolean 类型,如果这就是你的意思,否则,如果你想允许 Null,那么 Boolean。

      如果返回一个布尔值那么

      return true; // or false
      

      必须比依赖自动装箱更好,同样是为了清晰和性能。

      如果返回布尔值则

      return Boolean.TRUE
      

      必须是好的,它只是避免产生额外的垃圾,就像我反对微优化一样,我认为故意低效没有任何价值。我认为这也更清楚,因为您明显匹配返回类型。

      【讨论】:

        【解决方案4】:

        他们会更快。我认为这两者之间不会有任何区别。

        Boolean isItTrue(arg){ 
            return Boolean.TRUE;
        }
        
        boolean isItTrue(arg){
            return true;
        }
        

        但其他实现会更慢,因为它将在后端装箱和拆箱,这需要一些处理器时间。


        编辑

        我通过实施 4 种不同的方式收集了一些事实。只是想和你分享,如果它的写作方式,我不这样做。

        Boolean isItTrue(){ 
            return Boolean.TRUE;
        }
        
        Free Memory before start --> 16030936
        Time taken in Secs --> 7.844
        Free Memory After Process --> 15940472
        Memory Usage --> 90464
        

        boolean isItTrue(){
            return Boolean.TRUE;
        }
        
        Free Memory before start --> 16030936
        Time taken in Secs --> 10.109
        Free Memory After Process --> 15940472
        Memory Usage --> 90464
        

        Boolean isItTrue(){
            return true;
        }
        
        Free Memory before start --> 16030936
        Time taken in Secs --> 7.906
        Free Memory After Process --> 15940472
        Memory Usage --> 90464
        

        boolean isItTrue(){
            return true;
        }
        
        Free Memory before start --> 16030936
        Time taken in Secs --> 7.828
        Free Memory After Process --> 15940472
        Memory Usage --> 90464
        

        主类

        public static void main(String[] args){
            NewClass n = new NewClass();
        
            long sysTime = System.currentTimeMillis();
        
            Runtime rt = Runtime.getRuntime();
            long freeMem = rt.freeMemory();
            System.out.println( "Free Memory before start --> " + freeMem );
            for( int i = 0; i < Integer.MAX_VALUE; i++ ){
                n.isItTrue();
            }
            System.out.println( "Time taken in Secs --> " + (System.currentTimeMillis() - sysTime)/1000D);
            System.out.println( "Free Memory After Process --> " + rt.freeMemory() );
            System.out.println( "Memory Usage --> " + ( freeMem - rt.freeMemory() ) );
        }
        

        【讨论】:

        • 我不认为你声称“他们会更快”是正确的。任何性能差异都是微小的。
        • 嘿,我在实现之后添加了一些事实。看看吧。
        • 微基准测试是出了名的难以正确编写(因此通常的建议是分析您的实际应用程序)。看看ibm.com/developerworks/java/library/j-jtp02225/index.htmlwikis.sun.com/display/HotSpotInternals/MicroBenchmarks
        • 此基准测试存在可能导致结果无效的缺陷。即使这些数字是有效的,它们也不能代表该方法的可能使用方式,因此也不能代表 JIT 编译器优化它们的上下文。最后,对于 2^31 次调用,最好到最差的增量是 2.3 秒 == 小于 1 纳秒 == 库存硬件上的 2 或 3 个 CPU 时钟滴答。如果这是有代表性的,那么它显然处于对典型应用程序的性能影响最小的水平。
        【解决方案5】:

        最后一个

        boolean isItTrue(arg){
            return true;
        }
        

        我只在方法有时需要返回null时才使用Boolean

        【讨论】:

          【解决方案6】:

          我的经验法则如下:

          1. 默认选择是原始类型 (boolean)。
          2. 如果我需要可空性或需要将值存储在容器中,我使用类 (Boolean)。

          考虑到这一点,我的默认选择是:

          boolean isItTrue(arg){
              return true;
          }
          

          就性能而言,唯一可以肯定的是,很难想象使用Boolean 会比使用boolean 更快 的场景。会慢还是一样取决于很多事情,一般无法回答。

          如果您真的关心这一点,请在重要的地方分析代码!

          【讨论】:

            【解决方案7】:

            按照这种逻辑,对静态对象本身的引用与真值一样昂贵,甚至更多。

            使用对象可能比原语要慢一些,但我不担心:区别无关紧要。

            【讨论】:

              【解决方案8】:

              使用最后一个(只是boolean)。即使编译器将它们全部优化为相同的东西,至少你让编译器的工作更容易(你知道这不是一件容易的工作!)。

              此外,它的击键次数更少(无需按 shift)。但实际上,您应该使用包装类的唯一原因是您需要能够将其设置为 null,并用于像 LinkedList&lt;E&gt; 这样的通用数据结构。

              【讨论】:

                【解决方案9】:

                java.lang.Boolean 占用 16 个字节。

                如果您只是在寻找性能和内存大小问题,这就是要走的路:

                boolean isItTrue(arg){
                    return true;
                }
                

                【讨论】:

                • 您不会节省任何空间,因为如果您的程序导致 Boolean 类被初始化,那么无论如何都会创建 Boolean.TRUEBoolean.FALSE 对象。
                • 它会在后台初始化一个布尔值吗?我的印象是它没有。
                • 不在后台。但是 JVM 规范说,如果使用任何静态、调用任何静态方法或创建任何对象实例(以及其他事情),就会发生初始化。如果其中任何一个发生,将创建 TRUEFALSE 实例并使用空间......无论您的应用程序是否使用这些实例。
                • Boolean.TRUE 是一个静态字段,可在自动装箱到 Boolean 的所有 trues 中重复使用
                猜你喜欢
                • 2011-06-21
                • 2013-05-02
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-05-09
                • 2012-08-06
                • 2011-10-02
                相关资源
                最近更新 更多