1 /*
2  * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 package org.openjdk.bench.java.lang;
24 
25 import org.openjdk.jmh.annotations.Benchmark;
26 import org.openjdk.jmh.annotations.BenchmarkMode;
27 import org.openjdk.jmh.annotations.Mode;
28 import org.openjdk.jmh.annotations.OperationsPerInvocation;
29 import org.openjdk.jmh.annotations.OutputTimeUnit;
30 import org.openjdk.jmh.annotations.Scope;
31 import org.openjdk.jmh.annotations.Setup;
32 import org.openjdk.jmh.annotations.State;
33 
34 import java.util.concurrent.TimeUnit;
35 
36 /**
37  * Benchmark measuring System.arraycopy in different ways.
38  */
39 @BenchmarkMode(Mode.AverageTime)
40 @OutputTimeUnit(TimeUnit.NANOSECONDS)
41 @State(Scope.Thread)
42 public class ArrayCopy {
43 
44     private static final byte[] TEST_BYTES = "HTTP/1.0".getBytes();
45     private static final char[] TEST_CHARS = new char[46];
46     private static final Object[] TEST_OBJECTS = new Object[200];  // Uses a minimum of 160 internal positions for internal copying
47 
48     // a length which the compiler cannot prove is a constant
49     public static int nonConstCharLength = TEST_CHARS.length;
50     public static int nonConstByteLength = TEST_BYTES.length;
51     public static int nonConstObjectLength = TEST_OBJECTS.length;
52 
53     // Use this array to copy objects in.
54     public char[] dummyCharArray = new char[TEST_CHARS.length];
55     public byte[] dummyByteArray = new byte[TEST_BYTES.length];
56     public Object[] dummyObjectArray = new Object[TEST_OBJECTS.length];
57 
58     @Setup
setup()59     public void setup() {
60         for (int i = 0; i < TEST_OBJECTS.length; i++) {
61             TEST_OBJECTS[i] = new Object();
62             dummyObjectArray[i] = new Object();
63         }
64     }
65 
66     /**
67      * This test case do the same work as testArrayCopy. We should make sure
68      * testArrayCopy is equally fast or better. Compare the two and you measure
69      * the system call versus explicit copy for-loop.
70      */
71     @Benchmark
copyLoop()72     public void copyLoop() {
73         for (int j = 0; j < dummyByteArray.length; j++) {
74             dummyByteArray[j] = TEST_BYTES[j];
75         }
76     }
77 
78     /**
79      * Test that we can optimize away the code since it should not have any side
80      * effects
81      */
82     @Benchmark
copyLoopLocalArray()83     public void copyLoopLocalArray() {
84         byte[] localDummyByteArray = new byte[TEST_BYTES.length];
85         for (int j = 0; j < localDummyByteArray.length; j++) {
86             localDummyByteArray[j] = TEST_BYTES[j];
87         }
88     }
89 
90     /**
91      * This test case do the same work as testArrayCopy. We should make sure
92      * testArrayCopy is equally fast or better. Compare the two and you measure
93      * the system call versus explicit copy for-loop.
94      * <p/>
95      * Uses non-provable constant length.
96      */
97     @Benchmark
copyLoopNonConst()98     public void copyLoopNonConst() {
99         for (int i = 0; i < nonConstByteLength; i++) {
100             dummyByteArray[i] = TEST_BYTES[i];
101         }
102     }
103 
104     /**
105      * This test case do the same work as testCopyLoop. We should make sure
106      * testArrayCopy is equally fast or better. Compare the two and you measure
107      * the system call versus explicit copy for-loop.
108      */
109     @Benchmark
arrayCopy()110     public void arrayCopy() {
111         System.arraycopy(TEST_BYTES, 0, dummyByteArray, 0, dummyByteArray.length);
112     }
113 
114     /**
115      * Test that we can optimize away the code since it should not have any side
116      * effects
117      */
118     @Benchmark
arrayCopyLocalArray()119     public void arrayCopyLocalArray() {
120         byte[] localDummyByteArray = new byte[TEST_BYTES.length];
121         System.arraycopy(TEST_BYTES, 0, localDummyByteArray, 0, localDummyByteArray.length);
122     }
123 
124     /**
125      * This test case do the same work as testCopyLoop. We should make sure
126      * testArrayCopy is equally fast or better. Compare the two and you measure
127      * the system call versus explicit copy for-loop.
128      * <p/>
129      * Uses non-provable constant length.
130      */
131     @Benchmark
arrayCopyNonConst()132     public void arrayCopyNonConst() {
133         System.arraycopy(TEST_BYTES, 0, dummyByteArray, 0, nonConstByteLength);
134     }
135 
136     @Benchmark
arrayCopyChar()137     public void arrayCopyChar() {
138         System.arraycopy(TEST_CHARS, 0, dummyCharArray, 0, dummyCharArray.length);
139     }
140 
141     @Benchmark
arrayCopyCharNonConst()142     public void arrayCopyCharNonConst() {
143         System.arraycopy(TEST_CHARS, 0, dummyCharArray, 0, nonConstCharLength);
144     }
145 
146     @Benchmark
arrayCopyObject()147     public void arrayCopyObject() {
148         System.arraycopy(TEST_OBJECTS, 0, dummyObjectArray, 0, dummyObjectArray.length);
149     }
150 
151     @Benchmark
arrayCopyObjectNonConst()152     public void arrayCopyObjectNonConst() {
153         System.arraycopy(TEST_OBJECTS, 0, dummyObjectArray, 0, nonConstObjectLength);
154     }
155 
156     /**
157      * This test copies inside a object array, that is same source array as dest
158      * array. Copies backwards in the array.
159      */
160     @Benchmark
161     @OperationsPerInvocation(40)
arrayCopyObjectSameArraysBackward()162     public void arrayCopyObjectSameArraysBackward() {
163         for (int i = 0; i < 40; i++) {
164             System.arraycopy(dummyObjectArray, i, dummyObjectArray, i + 40, 80);
165         }
166     }
167 
168     /**
169      * This test copies inside a object array, that is same source array as dest
170      * array. Copies forward in the array. There is a special version for this
171      * in JRockit.
172      */
173     @Benchmark
174     @OperationsPerInvocation(40)
arrayCopyObjectSameArraysForward()175     public void arrayCopyObjectSameArraysForward() {
176         for (int i = 0; i < 40; i++) {
177             System.arraycopy(dummyObjectArray, i + 40, dummyObjectArray, i, 80);
178         }
179     }
180 }
181