有什么办法创建没有初始化基本数组? [英] Is there any way to create a primitive array without initialization?

查看:122
本文介绍了有什么办法创建没有初始化基本数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如我们所知道的Java总是初始化数组在创建时。即新INT [百万] 总是在大多数返回所有元素的数组= 0。据我所知,它是一个对象数组必须的,但对于基本数组(除可能是布尔)情况下,我们不关心的初始值。

As we know Java always initialises arrays upon creation. I.e. new int[1000000] always returns an array with all elements = 0. I understand that it's a must for Object arrays, but for primitive arrays (except may be Boolean) in most cases we don't care about the initial values.

有谁知道一种方法来避免这种intialization?

Does anybody know a way to avoid this intialization?

推荐答案

我已经做了一些调查。还有就是在Java中创建未初始化数组没有合法的方式。即使JNI NewXxxArray创建初始化数组。因此,它是不可能知道数组的准确的成本归零。不过,我已经做了一些测量:

I've done some investigation. There is no legal way to create uninitialized array in Java. Even JNI NewXxxArray creates initialized arrays. So it is impossible to know exactly the cost of array zeroing. Nevertheless I've done some measurements:

1)1000字节数组创建不同的数组大小

1) 1000 byte arrays creation with different array size

        long t0 = System.currentTimeMillis();
        for(int i = 0; i < 1000; i++) {
//          byte[] a1 = new byte[1];
            byte[] a1 = new byte[1000000];
        }
        System.out.println(System.currentTimeMillis() - t0);

我的电脑上它给人&LT;为1ms的字节[1]〜500毫秒的byte [百万]。听起来IM pressive给我。

on my PC it gives < 1ms for byte[1] and ~500 ms for byte[1000000]. Sounds impressive to me.

2),我们没有在JDK快速(本地)方法填充数组,Arrays.fill是太慢了,所以让我们看看1000拷贝至少有多少百万大小的数组与当地System.arraycopy

2) We don't have a fast (native) method in JDK for filling arrays, Arrays.fill is too slow, so let's see at least how much 1000 copying of 1,000,000 size array takes with native System.arraycopy

    byte[] a1 = new byte[1000000];
    byte[] a2 = new byte[1000000];
    for(int i = 0; i < 1000; i++) {
        System.arraycopy(a1, 0, a2, 0, 1000000);
    }

这是700毫秒。

It is 700 ms.

这让我有理由相信,一个)创建长数组是昂贵二)似乎因无用的初始化是昂贵的。

It gives me reasons to believe that a) creating long arrays is expensive b) it seems to be expensive because of useless initialization.

3)让我们sun.misc.Unsafe <一个href=\"http://www.javasource$c$c.org/html/open-source/jdk/jdk-6u23/sun/misc/Unsafe.html\">http://www.javasource$c$c.org/html/open-source/jdk/jdk-6u23/sun/misc/Unsafe.html.它是从外部使用保护,但不要太多。

3) Let's take sun.misc.Unsafe http://www.javasourcecode.org/html/open-source/jdk/jdk-6u23/sun/misc/Unsafe.html. It is protected from external usage but not too much

    Field f = Unsafe.class.getDeclaredField("theUnsafe");
    f.setAccessible(true);
    Unsafe unsafe = (Unsafe)f.get(null);

下面是存储器分配测试成本

Here is the cost of memory allocation test

    for(int i = 0; i < 1000; i++) {
        long m = u.allocateMemory(1000000);
    }

这需要&LT; 1毫秒,如果你还记得,新的字节[百万]花了500毫秒。

It takes < 1 ms, if you remember, for new byte[1000000] it took 500ms.

4)不安全没有直接的数组的方法工作。它需要知道类字段,但反射示出的阵列没有字段。没有关于阵列内部很多信息,我想这是JVM /平台特定的。然而,这是,像任何其他的Java对象,头+字段。在我的电脑/ JVM,它看起来像

4) Unsafe has no direct methods to work with arrays. It needs to know class fields, but reflection shows no fields in an array. There is not much info about arrays internals, I guess it is JVM / platform specific. Nevertheless, it is, like any other Java Object, header + fields. On my PC/JVM it looks like

header - 8 bytes
int length - 4 bytes
long bufferAddress - 8 bytes

现在,使用不安全,我将创建字节[10],分配一个10字节的内存缓冲区,并把它作为我的数组的元素:

Now, using Unsafe, I will create byte[10], allocate a 10 byte memory buffer and use it as my array's elements:

    byte[] a = new byte[10];
    System.out.println(Arrays.toString(a));
    long mem = unsafe.allocateMemory(10);
    unsafe.putLong(a, 12, mem);
    System.out.println(Arrays.toString(a));

它打印

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[8, 15, -114, 24, 0, 0, 0, 0, 0, 0]

您可以看到大公阵列的数据不会被初始化。

You can see thay array's data are not initialized.

现在我会改变我们的数组的长度(尽管它仍指向10个字节的内存)

Now I'll change our array length (though it still points to 10 bytes memory)

    unsafe.putInt(a, 8, 1000000);
    System.out.println(a.length);

这表明1000000这只是证明思想工作。

it shows 1000000. It was just to prove that the idea works.

现在的性能测试。我将创建一个空的字节数组A1,分配1000000字节的缓冲区,分配这个缓冲区至A1一组a1.length =千万

Now performance test. I will create an empty byte array a1, allocate a buffer of 1000000 bytes, assign this buffer to a1 an set a1.length = 10000000

    long t0 = System.currentTimeMillis();
    for(int i = 0; i < 1000; i++) {
        byte[] a1 = new byte[0];
        long mem1 = unsafe.allocateMemory(1000000);
        unsafe.putLong(a1, 12, mem);
        unsafe.putInt(a1, 8, 1000000);
    }
    System.out.println(System.currentTimeMillis() - t0);

它需要10毫秒。

it takes 10ms.

5)有malloc和页头在C ++中,刚刚的malloc分配的内存块,释放calloc还用零初始化。

5) There are malloc and alloc in C++, malloc just allocates memory block , calloc also initializes it with zeroes.

CPP

...
JNIEXPORT void JNICALL Java_Test_malloc(JNIEnv *env, jobject obj, jint n) {
     malloc(n);
} 

Java的

private native static void malloc(int n);

for (int i = 0; i < 500; i++) {
    malloc(1000000);
}

结果的malloc - 78毫秒;释放calloc - 468毫秒

results malloc - 78 ms; calloc - 468 ms

结论


  1. 看来,Java数组的创建是因为无用的元素零缓慢。

  2. 我们无法改变它,但是Oracle可以。无需改变任何东西在JLS,只需添加本地方法java.lang.reflect.Array中像

  1. It seems that Java array creation is slow because of useless element zeroing.
  2. We cannot change it, but Oracle can. No need to change anything in JLS, just add native methods to java.lang.reflect.Array like

公共静态本地XXX [] newUninitialziedXxxArray(INT大小);

public static native xxx[] newUninitialziedXxxArray(int size);

对于所有基本数值类型(字节 - 双)和char类型。它可以在java.util.Arrays中使用的所有在JDK,像

for all primitive numeric types (byte - double) and char type. It could be used all over the JDK, like in java.util.Arrays

    public static int[] copyOf(int[] original, int newLength) {
        int[] copy = Array.newUninitializedIntArray(newLength);
        System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
        ...

或java.lang.String中

or java.lang.String

   public String concat(String str) {
        ...   
        char[] buf = Array.newUninitializedCharArray(count + otherLen);
        getChars(0, count, buf, 0);
        ...

这篇关于有什么办法创建没有初始化基本数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆