简体   繁体   English

列表,原始类型和性能

[英]Lists, primitive types, and performance

I was curious about autoboxing and performance, because I'm doing a lot of speed sensitive math in my application, so I ran a little test... 我对自动装箱和性能感到好奇,因为我在我的应用程序中做了很多速度敏感的数学运算,所以我进行了一些测试......

public static void main(String[] args) {
    // Some initialization so I know it's not involved
    ArrayList<Integer> list = new ArrayList<Integer>();
    list.add(0);
    int[] regArray = new int[1];
    long total = 0;

    // This one uses an array and primitive type
    long start = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) {
        regArray[0] = i + 10;
        if (regArray[0] % 1000 == 0) total += regArray[0];
    }
    System.out.println("Runtime in millis: " + (System.currentTimeMillis() - start));
    System.out.println(total);

    // This one autoboxes, but still uses the Object type because it's a list
    total = 0;
    start = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) {
        list.set(0, i + 10);
        if (list.get(0) % 1000 == 0) total += list.get(0);
    }
    System.out.println("Runtime in millis: " + (System.currentTimeMillis() - start));
    System.out.println(total);

    // This one doesn't autobox
    total = 0;
    start = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) {
        list.set(0, new Integer(i + 10));
        if (list.get(0).intValue() % 1000 == 0) total += list.get(0).intValue();
    }
    System.out.println("Runtime in millis: " + (System.currentTimeMillis() - start));
    System.out.println(total);
}

Here's a sample output: 这是一个示例输出:

Runtime in millis: 78
50005000000
Runtime in millis: 250
50005000000
Runtime in millis: 250
50005000000

This seems to suggest I should stay away from List<> and subclasses in mathy, speed sensitive applications. 这似乎表明我应该远离List<>和mathy,速度敏感应用程序中的子类。 Do you agree, stackoverflow? 你同意,stackoverflow?

Edit: My actual use case is that I need to store a few hundred int s and float s that will change often and largely undpredictably (I say largely because they will stay within a narrowish range, but I don't know what they will do in that narrow range), and I need order millisecond response time on doing math on these numbers. 编辑:我的实际用例是我需要存储几百个intfloat s,它们会经常发生变化,而且很大程度上是不可预测的(我说主要是因为它们会保持在一个狭窄的范围内,但我不知道他们会做什么在那个狭窄的范围内),我需要在这些数字上进行数学运算时的毫秒级响应时间。

Microbenchmarking is hard! 微观标记很难! I rewrote your benchmark to use caliper : 我重写了你的基准来使用caliper

import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;

import java.util.ArrayList;

public class ListsBenchmark extends SimpleBenchmark {

    private final ArrayList<Integer> list = new ArrayList<Integer>();
    int[] regArray = new int[1];
    long total;

    @Override
    protected void setUp() throws Exception {
        list.add(0);
        total = 0;
    }

    public long timeArrayAndPrimitiveType(int reps) {
        for (int i = 0; i < reps; i++) {
            regArray[0] = i + 10;
            if (regArray[0] % 1000 == 0)
                total += regArray[0];
        }
        return total;
    }

    public long timeListWithAutoboxing(int reps) {
        for (int i = 0; i < reps; i++) {
            list.set(0, i + 10);
            if (list.get(0) % 1000 == 0)
                total += list.get(0);
        }
        return total;
    }

    public long timeNoAutoboxing(int reps) {
        for (int i = 0; i < reps; i++) {
            list.set(0, new Integer(i + 10));
            if (list.get(0).intValue() % 1000 == 0)
                total += list.get(0).intValue();
        }
        return total;
    }

    public static void main(String[] args) {
        Runner.main(ListsBenchmark.class, new String[]{});
    }

}

I haven't modified your original code. 我没有修改你的原始代码。 What I find out that is: 我发现的是:

  • array is around 3x times faster 数组大约快3倍
  • creating new Integer is slightly faster (!), maybe caching has some price or maybe it's just my architecture (32 bit Ubuntu with 4 cores and 3 GiB of memory laptop) 创建新的Integer稍微快一些(!),也许缓存有一些价格或者它只是我的架构(32位Ubuntu有4核和3 GiB内存笔记本电脑)

On chart (feel free to run it yourself!): 在图表上(随意自己运行!):

卡尺

If you have a predetermined number of ints, then storing them in an array (assuming they need storing and can't be streamed!) is generally faster than a java.util.ArrayList , yes. 如果你有一个预定数量的int,那么将它们存储在一个数组中(假设它们需要存储而不能流式传输!)通常比java.util.ArrayList更快,是的。

However, in many situations you may have a varying data size, so a dynamically resizable Collection then becomes extremely useful - the alternative is generally to write your own implementation of ArrayList ! 但是,在许多情况下,您可能具有不同的数据大小,因此动态可调整大小的集合变得非常有用 - 替代方法通常是编写您自己的ArrayList实现!

Fortunately, there are many third party libraries that implement Lists based on primitive types (int etc) rather than objects (Integer etc). 幸运的是,有许多第三方库基于原始类型(int等)而不是对象(Integer等)实现列表。 You could take a look at these. 你可以看看这些。

Writing a benchmark is a hard task, and your benchmark is not a good one, for at least the following reasons: 编写基准测试是一项艰巨的任务,并且您的基准测试不是很好,至少有以下原因:

  • doing everything in the main method, without letting Hotspot come in and JIT compile your code make the results wrong 在main方法中执行所有操作,不让Hotspot进入并且JIT编译代码会导致结果错误
  • Using new Integer() instead of Integer.valueOf() doesn't let you use the Integer cache 使用new Integer()而不是Integer.valueOf()不允许您使用Integer缓存
  • The values and operations are not realistic. 价值观和操作是不现实的。 Most of the time, values are close to 0, and not in the 10,000,000 range 大多数情况下,值接近0,而不是10,000,000范围

Primitives and arrays are faster than objects and collections generally, but without measuring your actual code, under realistic conditions, it's hard to tell if the gain you would have by using primitives and arrays would be significant or completely negligible. 基本体和数组通常比对象和集合更快,但是在没有测量实际代码的情况下,在实际条件下,很难判断使用基元和数组所获得的增益是重要的还是完全可以忽略不计。 Most of the time, performance is lost in IO operations. 大多数情况下,IO操作会丢失性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Drools中原始数据类型与非原始数据类型的性能 - Performance of primitive vs. non-primitive data types in Drools 基本数据类型的性能与其包装器类的关系 - Performance of Primitive Data types VS their Wrapper class 如果C#的原始类型实现方式不同,性能会有所不同吗? - Difference in performance if C#'s primitive types were implemented differently? Java Arrays.sort基本类型和对象的性能 - Java Arrays.sort performance for primitive types and objects Java性能难题:包装器类比原始类型更快? - Java performance puzzler: wrapper classes faster than primitive types? 是否有Java JSON解串器,可将字符串解码为列表字典或原始类型字典列表 - Is there a Java JSON deserializer that decodes a string into dictionary of lists or lists of dictionaries of primitive types 在番石榴中,基本类型的Lists.newArrayList()和Ints.asList()之间有什么区别(如果有) - In guava, what is the difference (if any) between Lists.newArrayList() and e.g. Ints.asList() for primitive types 用于原始类型的Jackson序列化器 - Jackson serializer for primitive types Jaxb封送处理原始类型 - Jaxb marshaling primitive types isAssignableFrom with reference和primitive类型 - isAssignableFrom with reference and primitive types
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM