Path: blob/master/test/micro/org/openjdk/bench/vm/compiler/CopyLoop.java
41161 views
/*1* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/22package org.openjdk.bench.vm.compiler;2324import org.openjdk.jmh.annotations.Benchmark;25import org.openjdk.jmh.annotations.BenchmarkMode;26import org.openjdk.jmh.annotations.Mode;27import org.openjdk.jmh.annotations.OutputTimeUnit;28import org.openjdk.jmh.annotations.Scope;29import org.openjdk.jmh.annotations.Setup;30import org.openjdk.jmh.annotations.State;3132import java.util.concurrent.TimeUnit;3334/**35* Benchmark measuring effect of loop optimizations.36*/37@BenchmarkMode(Mode.AverageTime)38@OutputTimeUnit(TimeUnit.NANOSECONDS)39@State(Scope.Thread)40public class CopyLoop {4142private MyString s;43private Buf b;4445@Setup46public void setup() {47s = new MyString("foobarba");48b = new Buf();49}5051/**52* Basic implementation, as a Java programmer would write it.53*/54@Benchmark55public void testCharAtLoop() throws Exception {56for (int i = 0; i < s.length(); i++) {57int c = s.charAt(i);58b.byteBuf[i] = (byte) c;59}60}6162/** Inline charAt and remove the redundant bounds checks. */63@Benchmark64public void testInlineCharAtLoop() throws Exception {65for (int i = 0; i < s.count; i++) {66int c = s.value[i + s.offset];67b.byteBuf[i] = (byte) c;68}69}7071/**72* Unroll the loop (I cheat here because I know that the String will always be an even length, real implementation73* would require a pre-loop).74*/75@Benchmark76public void testInlineAndUnrollCharAtLoop() throws Exception {77int startI = 0;78if ((s.count & 0xFFFE) != s.count) {79int c = s.value[s.offset];80b.byteBuf[0] = (byte) c;81startI = 1;82}83for (int i = startI; i < s.count - 1; i += 2) {84int c = s.value[i + s.offset];85int d = s.value[i + s.offset + 1];86b.byteBuf[i] = (byte) c;87b.byteBuf[i + 1] = (byte) d;88}89}9091/** Hoist computation of constants outside of the loop. */92@Benchmark93public void testInlineAndUnrollAndHoistCharAtLoop() throws Exception {94byte[] byteBuf = b.byteBuf;95if (byteBuf == null) {96throw new NullPointerException();97}98char[] value = s.value;99int offset = s.offset;100101int startI = offset;102103if ((s.count & 0xFFFE) != s.count) {104int c = value[offset];105byteBuf[0] = (byte) c;106startI++;107}108109int maxI = s.count + offset - 1;110for (int i = startI; i < maxI; i += 2) {111int c = value[i];112int d = value[i + 1];113byteBuf[i] = (byte) c;114byteBuf[i + 1] = (byte) d;115}116}117118private static class Buf {119private byte[] byteBuf = new byte[100];120}121122public static final class MyString {123private char value[];124125private int offset;126127private int count;128129public MyString(String original) {130value = original.toCharArray();131offset = 0;132count = value.length;133}134135public int length() {136return count;137}138139public char charAt(int index) {140if ((index < 0) || (index >= count)) {141throw new StringIndexOutOfBoundsException(index);142}143return value[index + offset];144}145146}147148}149150151