Java performance-System. arraycopy, system. arraycopy

Source: Internet
Author: User

Java performance-System. arraycopy, system. arraycopy

When I was young, I was willful. I also copied the array, wrote a for loop, and moved back and forth. When I grew up, I found the benefits of System. arraycopy.

To test the difference between the two, I wrote a simple procedure with an int value [100000] For comparison, and used nanoTime in the middle to calculate the time difference:

The procedure is as follows:

        int[] a = new int[100000];        for(int i=0;i<a.length;i++){            a[i] = i;        }                int[] b = new int[100000];                int[] c = new int[100000];        for(int i=0;i<c.length;i++){            c[i] = i;        }                int[] d = new int[100000];                for(int k=0;k<10;k++){            long start1 = System.nanoTime();            for(int i=0;i<a.length;i++){                b[i] = a[i];            }            long end1 = System.nanoTime();            System.out.println("end1 - start1 = "+(end1-start1));                                    long start2 = System.nanoTime();            System.arraycopy(c, 0, d, 0, 100000);            long end2 = System.nanoTime();            System.out.println("end2 - start2 = "+(end2-start2));                        System.out.println();        }

To avoid Memory instability and unexpected running results, I declare all the spaces at the beginning and execute them only 10 times in a loop. the following result is obtained:

end1 - start1 = 366806end2 - start2 = 109154end1 - start1 = 380529end2 - start2 = 79849end1 - start1 = 421422end2 - start2 = 68769end1 - start1 = 344463end2 - start2 = 72020end1 - start1 = 333174end2 - start2 = 77277end1 - start1 = 377335end2 - start2 = 82285end1 - start1 = 370608end2 - start2 = 66937end1 - start1 = 349067end2 - start2 = 86532end1 - start1 = 389974end2 - start2 = 83362end1 - start1 = 347937end2 - start2 = 63638

It can be seen that the performance of System. arraycopy is very good. To see how this underlying layer is handled, I find some code of openJDK missing:

System. arraycopy is a native function. You need to check the code at the native layer:

    public static native void arraycopy(Object src,  int  srcPos,                                        Object dest, int destPos,                                        int length);

Find the corresponding openjdk6-src/hotspot/src/share/vm/prims/jvm. cpp, which has the entry to JVM_ArrayCopy:

JVM_ENTRY(void, JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos,                               jobject dst, jint dst_pos, jint length))  JVMWrapper("JVM_ArrayCopy");  // Check if we have null pointers  if (src == NULL || dst == NULL) {    THROW(vmSymbols::java_lang_NullPointerException());  }  arrayOop s = arrayOop(JNIHandles::resolve_non_null(src));  arrayOop d = arrayOop(JNIHandles::resolve_non_null(dst));  assert(s->is_oop(), "JVM_ArrayCopy: src not an oop");  assert(d->is_oop(), "JVM_ArrayCopy: dst not an oop");  // Do copy  Klass::cast(s->klass())->copy_array(s, src_pos, d, dst_pos, length, thread);JVM_END

The previous statements are all judgments. We know that the last copy_array (s, src_pos, d, dst_pos, length, thread) is a real copy. Let's look at it further, in openjdk6-src/hotspot/src/share/vm/oops/typeArrayKlass. cpp:

Void typeArrayKlass: copy_array (arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) {assert (s-> is_typeArray (), "must be type array"); // Check destination if (! D-> is_typeArray () | element_type ()! = TypeArrayKlass: cast (d-> klass ()-> element_type () {THROW (vmSymbols: java_lang_ArrayStoreException ());} // Check is all offsets and lengths are non negative if (src_pos <0 | dst_pos <0 | length <0) {THROW (vmSymbols: java_lang_ArrayIndexOutOfBoundsException ());} // Check if the ranges are valid if (unsigned int) length + (unsigned int) src_pos)> (unsigned int) s-> length ()) | (unsigned int) length + (unsigned int) dst_pos)> (unsigned int) d-> length () {THROW (vmSymbols :: java_lang_ArrayIndexOutOfBoundsException ();} // Check zero copy if (length = 0) return; // This is an attempt to make the copy_array fast. int l2es = log2_element_size (); int ihs = array_header_in_bytes ()/wordSize; char * src = (char *) (oop *) s + ihs) + (size_t) src_pos <l2es); char * dst = (char *) (oop *) d + ihs) + (size_t) dst_pos <l2es); Copy :: conjoint_memory_atomic (src, dst, (size_t) length <l2es); // still process copy here}

Before this function, there are still a bunch of judgments until the last sentence is the real copy statement.

Find the corresponding function in openjdk6-src/hotspot/src/share/vm/utilities/copy. cpp:

// Copy bytes; larger units are filled atomically if everything is aligned.void Copy::conjoint_memory_atomic(void* from, void* to, size_t size) {  address src = (address) from;  address dst = (address) to;  uintptr_t bits = (uintptr_t) src | (uintptr_t) dst | (uintptr_t) size;  // (Note:  We could improve performance by ignoring the low bits of size,  // and putting a short cleanup loop after each bulk copy loop.  // There are plenty of other ways to make this faster also,  // and it's a slippery slope.  For now, let's keep this code simple  // since the simplicity helps clarify the atomicity semantics of  // this operation.  There are also CPU-specific assembly versions  // which may or may not want to include such optimizations.)  if (bits % sizeof(jlong) == 0) {    Copy::conjoint_jlongs_atomic((jlong*) src, (jlong*) dst, size / sizeof(jlong));  } else if (bits % sizeof(jint) == 0) {    Copy::conjoint_jints_atomic((jint*) src, (jint*) dst, size / sizeof(jint));  } else if (bits % sizeof(jshort) == 0) {    Copy::conjoint_jshorts_atomic((jshort*) src, (jshort*) dst, size / sizeof(jshort));  } else {    // Not aligned, so no need to be atomic.    Copy::conjoint_jbytes((void*) src, (void*) dst, size);  }}

The above code shows which copy function to choose, we choose conjoint_jints_atomic, In the openjdk6-src/hotspot/src/share/vm/utilities/copy. hpp further view:

// jints,                 conjoint, atomic on each jint  static void conjoint_jints_atomic(jint* from, jint* to, size_t count) {    assert_params_ok(from, to, LogBytesPerInt);    pd_conjoint_jints_atomic(from, to, count);  }

Continue down, in openjdk6-src/hotspot/src/cpu/zero/vm/copy_zero.hpp:

static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) {  _Copy_conjoint_jints_atomic(from, to, count);}

Continue to view down, in openjdk6-src/hotspot/src/OS _cpu/linux_zero/vm/OS _linux_zero.cpp:

void _Copy_conjoint_jints_atomic(jint* from, jint* to, size_t count) {    if (from > to) {      jint *end = from + count;      while (from < end)        *(to++) = *(from++);    }    else if (from < to) {      jint *end = from;      from += count - 1;      to   += count - 1;      while (from >= end)        *(to--) = *(from--);    }  }

As you can see, it is the logic for assigning values to memory blocks. This avoids the time for many references to roll back and forth, and it will inevitably get faster.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.