1 /* 2 * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2021, Rado Smogura. All rights reserved. 4 * 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 * 25 */ 26 package org.openjdk.bench.jdk.incubator.vector; 27 28 import java.nio.ByteOrder; 29 import java.util.concurrent.TimeUnit; 30 import jdk.incubator.foreign.MemorySegment; 31 import jdk.incubator.foreign.ResourceScope; 32 import jdk.incubator.vector.ByteVector; 33 import jdk.incubator.vector.VectorSpecies; 34 import org.openjdk.jmh.annotations.Benchmark; 35 import org.openjdk.jmh.annotations.BenchmarkMode; 36 import org.openjdk.jmh.annotations.CompilerControl; 37 import org.openjdk.jmh.annotations.Fork; 38 import org.openjdk.jmh.annotations.Measurement; 39 import org.openjdk.jmh.annotations.Mode; 40 import org.openjdk.jmh.annotations.OutputTimeUnit; 41 import org.openjdk.jmh.annotations.Param; 42 import org.openjdk.jmh.annotations.Setup; 43 import org.openjdk.jmh.annotations.State; 44 import org.openjdk.jmh.annotations.Warmup; 45 46 @BenchmarkMode(Mode.AverageTime) 47 @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) 48 @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) 49 @State(org.openjdk.jmh.annotations.Scope.Benchmark) 50 @OutputTimeUnit(TimeUnit.NANOSECONDS) 51 @Fork(value = 1, jvmArgsAppend = { 52 "--add-modules=jdk.incubator.foreign,jdk.incubator.vector", 53 "-Dforeign.restricted=permit", 54 "--enable-native-access", "ALL-UNNAMED"}) 55 public class MemorySegmentVectorAccess { 56 private static final VectorSpecies<Byte> SPECIES = VectorSpecies.ofLargestShape(byte.class); 57 58 @Param("1024") 59 private int size; 60 61 byte[] byteIn; 62 byte[] byteOut; 63 64 MemorySegment nativeIn, nativeOut; 65 MemorySegment heapIn, heapOut; 66 67 MemorySegment nativeInRo, nativeOutRo; 68 MemorySegment heapInRo, heapOutRo; 69 70 @Setup 71 public void setup() { 72 nativeIn = MemorySegment.allocateNative(size, ResourceScope.newImplicitScope()); 73 nativeOut = MemorySegment.allocateNative(size, ResourceScope.newImplicitScope()); 74 75 byteIn = new byte[size]; 76 byteOut = new byte[size]; 77 78 heapIn = MemorySegment.ofArray(byteIn); 79 heapOut = MemorySegment.ofArray(byteOut); 80 81 nativeInRo = nativeIn.asReadOnly(); 82 nativeOutRo = nativeOut.asReadOnly(); 83 84 heapInRo = heapIn.asReadOnly(); 85 heapOutRo = heapOut.asReadOnly(); 86 } 87 88 @Benchmark 89 public void directSegments() { 90 copyMemory(nativeIn, nativeOut); 91 } 92 93 @Benchmark 94 public void heapSegments() { 95 copyMemory(heapIn, heapOut); 96 } 97 98 @Benchmark 99 public void pollutedSegments2() { 100 copyIntoNotInlined(nativeIn, nativeOut); 101 copyIntoNotInlined(heapIn, heapOut); 102 } 103 104 @Benchmark 105 public void pollutedSegments3() { 106 copyIntoNotInlined(nativeIn, nativeOut); 107 copyIntoNotInlined(heapIn, heapOut); 108 109 copyIntoNotInlined(nativeInRo, nativeOut); 110 copyIntoNotInlined(heapInRo, heapOut); 111 } 112 113 @Benchmark 114 public void pollutedSegments4() { 115 copyIntoNotInlined(nativeIn, heapOut); // Pollute if unswitch on 2nd param 116 copyIntoNotInlined(heapIn, heapOut); 117 118 copyIntoNotInlined(heapIn, nativeIn); // Pollute if unswitch on 1st param 119 copyIntoNotInlined(heapIn, nativeOut); 120 } 121 122 123 boolean readOnlyException; 124 125 @Benchmark 126 public void pollutedSegments5() { 127 copyIntoNotInlined(nativeIn, heapOut); 128 copyIntoNotInlined(heapIn, heapOut); 129 130 copyIntoNotInlined(heapIn, nativeIn); 131 copyIntoNotInlined(heapIn, nativeOut); 132 133 if (readOnlyException) { 134 try { 135 copyIntoNotInlined(heapIn, nativeOutRo); 136 } catch (Exception ignored) {} 137 readOnlyException = !readOnlyException; 138 } 139 } 140 141 @Benchmark 142 public void arrayCopy() { 143 byte[] in = byteIn; 144 byte[] out = byteOut; 145 146 for (int i = 0; i < SPECIES.loopBound(in.length); i += SPECIES.vectorByteSize()) { 147 final var v = ByteVector.fromArray(SPECIES, in, i); 148 v.intoArray(out, i); 149 } 150 } 151 152 @CompilerControl(CompilerControl.Mode.DONT_INLINE) 153 protected void copyIntoNotInlined(MemorySegment in, MemorySegment out) { 154 copyMemory(in, out); 155 } 156 157 @CompilerControl(CompilerControl.Mode.INLINE) 158 protected void copyMemory(MemorySegment in, MemorySegment out) { 159 for (long i = 0; i < SPECIES.loopBound(in.byteSize()); i += SPECIES.vectorByteSize()) { 160 final var v = ByteVector.fromMemorySegment(SPECIES, in, i, ByteOrder.nativeOrder()); 161 v.intoMemorySegment(out, i, ByteOrder.nativeOrder()); 162 } 163 } 164 }