原始数据类型的性能 VS 它们的 Wrapper 类

Posted

技术标签:

【中文标题】原始数据类型的性能 VS 它们的 Wrapper 类【英文标题】:Performance of Primitive Data types VS their Wrapper class 【发布时间】:2016-11-01 19:35:02 【问题描述】:

我尝试测量原始数据类型及其包装类的执行时间,以计算相同的数字。我知道包装类比原始数据类型花费更多时间。

在我的以下代码中,原语 t1=5 的执行时间和包装类 t2=31 的执行时间。

import java.io.*;
import java.util.*;
public class Performance

  public static long primitive(int count)
     
   long startTime = System.currentTimeMillis();
   for(int i=0;i<10000;i++)
     count++;
    System.out.println(count);
   long stopTime = System.currentTimeMillis();
   long elapsedTime = stopTime - startTime;
   return elapsedTime;

  public static long wrapper(Integer count)

    long startTime = System.currentTimeMillis();
    for(int i=0;i<10000;i++)
      count++;
      System.out.println(count);
    long stopTime = System.currentTimeMillis();
    long elapsedTime = stopTime - startTime;
    return elapsedTime;
 

  public static void main(String args[])
  

   Integer c = new Integer(0);
   long t2=Performance.wrapper(c);
    int count=0;
   long t1=Performance.primitive(count);
  System.out.println("t1="+t1+"t2="+t2);

  

是否由于 Wrapper 类(整数)或其他任何对象的创建而导致性能差异?

【问题讨论】:

不要自己创建包装器,而是尝试使用铸造/自动装箱。 Integer 缓存在字节范围内。无论如何,您的微基准测试方法并不完全符合您获得准确结果所需的方法(jvm 预热、更多运行方式、nano vs millis 等) 您也可以尝试翻转处理顺序以在原语之前尝试您的包装器,看看您是否看到相同的东西。不过,我同意 Rogue 的观点——你正在做的微基准测试存在一些问题。如果您想详细了解原因,请查看github.com/google/caliper。 您可能希望更新您关心的为什么问题。您可能会得到更好的答案。 @Snekse 先生,非常感谢。当我在原语之前翻转 wrapper 的处理顺序时。我也一样。 然后您测量输出“计数”的时间。您应该将 System.out 移到“stopTime”后面。 IO操作可能会影响效果显着。 【参考方案1】:

你在这里弄错了重要的东西。

首先,编写一个好的微基准测试远远超出了您在代码中所做的工作;请参阅 here 了解一些指南。

然后:您必须了解要进行基准测试的事物。对不起,你显然没有。喜欢这里:

public static long wrapper(Integer count)

  long startTime = System.currentTimeMillis();
  for(int i=0;i<10000;i++)
    count++

整数对象是不可变的。此代码不仅“添加” Integer 对象,而且每次迭代创建一个新的 Integer 对象。

当然:您的代码甚至没有使用计算结果。如果 JVM/JIT 注意到这一点,它可能会完全丢弃那个循环和添加结构。所以你的方法至少应该返回 count 的最终值;调用者应该打印该结果。

并回答您的具体问题:当然,使用引用类型包装类需要付出一定的代价。当您的程序处理(真正)大量要处理的元素时,使用整数列表确实比使用 int 数组的成本要高得多。如果您不注意并且在代码中执行隐式自动装箱/拆箱,那真的可以hurt

但这里真正的答案是:你专注于错误的事情。你看,你的首要应该是做一个伟大的设计,然后是一个经过良好测试的、健壮的、可读的、可维护的实现。当然,您不应该做完全愚蠢的事情并浪费性能,但是,在担心性能之前,您最好担心您的 Java 技能。

长话短说:专注于理解 java 和“我如何创造一个好的设计”;现在忘记关于“性能”的事情。只有当“性能”是您的应用程序中的一个真正问题时,您才需要处理它。然后您进行真实分析以确定根本原因并修复它。

【讨论】:

以上是关于原始数据类型的性能 VS 它们的 Wrapper 类的主要内容,如果未能解决你的问题,请参考以下文章

原始类型包装器

[Java]_[初级]_[装箱和拆箱的陷阱-不要使用==进行包裹类型wrapper class比较]

[Java]_[初级]_[装箱和拆箱的陷阱-不要使用==进行包裹类型wrapper class比较]

原始性能表格 - Spring Boot 2 Webflux vs. Spring Boot 1

不覆盖原始样式的媒体查询样式

js按值传递和按引用传递