├── .gitignore ├── Java Questions - Lost in translation.txt ├── README.md ├── instrumentation ├── pom.xml └── src │ └── main │ └── java │ └── vanilla │ └── java │ ├── ExampleMain.java │ ├── MyInstrumentation.java │ └── RLambda.java ├── pom.xml └── src ├── main └── java │ ├── java │ └── lang │ │ └── Object.java │ └── vanilla │ └── java │ ├── LatencyMain.java │ ├── MicroJitterSampler.java │ ├── OffHeapMapMain.java │ ├── Puzzle.java │ ├── SplitCompareMain.java │ ├── async │ ├── AsyncMain.java │ ├── SubmitMain.java │ └── ThreadLocalMain.java │ ├── bits │ └── BitSetScanMain.java │ ├── collection │ └── IteratorMain.java │ ├── engine │ ├── MapPubSubMain.java │ └── RemoteMapPubSubMain.java │ ├── exceptions │ ├── ExceptionSizeMain.java │ ├── NewInstanceMain.java │ ├── PretendItDidntHappen2Main.java │ ├── PretendItDidntHappenMain.java │ ├── RethrowMain.java │ ├── SuddenIOExceptionMain.java │ ├── ThrowableMain.java │ └── WhereIsMyExceptionMain.java │ ├── floatingpoint │ ├── BigDecimalRoundingMain.java │ ├── DecodingFPMain.java │ ├── ModErrorMain.java │ ├── ToDecimalMain.java │ └── UsingBigDecimalMain.java │ ├── jmh │ ├── CalcBenchmark.java │ ├── GregorianMicroBenchmark.java │ ├── MicroBenchmark.java │ ├── SimpleCalcBenchmark.java │ └── TimeBenchmark.java │ ├── lambda │ ├── CapturingMain.java │ ├── ConsumerMain.java │ ├── Counting.java │ ├── FunctionMain.java │ ├── Main.java │ ├── NestedPutIfAbsentMain.java │ ├── SerializableLambda.java │ ├── Singleton.java │ ├── StreamMain.java │ ├── StringToInt.java │ ├── StringToInts.java │ └── SuppliersMain.java │ ├── math │ ├── BytesMatrix.java │ ├── Fraction.java │ ├── MutableHashMain.java │ ├── NativeCompute.java │ ├── NativeMatrix.java │ ├── Prime.java │ └── SqrtMain.java │ ├── memory │ ├── ArrayAllocationMain.java │ └── VisualVMMain.java │ ├── objects │ ├── CleanerMain.java │ ├── HowManyObjects2Main.java │ └── HowManyObjectsMain.java │ ├── optimisation │ ├── MemoryOptimisation2Main.java │ ├── MemoryOptimisationMain.java │ ├── MemoryOptimisationXMain.java │ └── MemoryOptimisedMain.java │ ├── perfeg │ ├── cache │ │ └── CacheSizesPerMain.java │ ├── crypt │ │ └── OverflowMain.java │ ├── doublebracket │ │ └── DoubleBracketMain.java │ ├── hwlimits │ │ ├── ActiveSocketMain.java │ │ ├── FileReadingMain.java │ │ ├── FixedPointLimitMain.java │ │ ├── FloatingPointLimitMain.java │ │ ├── MemoryBusLimitMain.java │ │ └── TestPools.java │ ├── lambdas │ │ └── PriceSearchMain.java │ ├── mmap │ │ ├── api │ │ │ ├── Column.java │ │ │ ├── Row.java │ │ │ └── Table.java │ │ ├── flush │ │ │ └── FlushMain.java │ │ ├── mmap │ │ │ ├── MmapRow.java │ │ │ └── MmapTable.java │ │ └── oop │ │ │ ├── OopColumn.java │ │ │ ├── OopRow.java │ │ │ ├── OopTable.java │ │ │ └── RowEntry.java │ ├── tcp │ │ ├── EchoClientMain.java │ │ └── EchoServerMain.java │ └── virt │ │ └── VirtualMethodMain.java │ ├── references │ ├── AccessField.java │ ├── HashcodeMain.java │ ├── MyClass.java │ ├── ObjectMain.java │ ├── ObjectReferencesMain.java │ ├── ObjectSizeMain.java │ ├── OtherClass.java │ ├── ShowFields2Main.java │ └── ShowFieldsMain.java │ ├── tcp │ ├── TextEchoClientMain.java │ └── TextEchoServerMain.java │ ├── threads │ ├── CAS2PingPongMain.java │ ├── CASPingPongMain.java │ ├── ChronicleBytesCASPingPongMain.java │ ├── EncapsulationMain.java │ ├── ExecutorServiceMain.java │ ├── LockConditionPingPongMain.java │ ├── NativeCASPingPongMain.java │ ├── PrimeNumbersMain.java │ ├── PrimeNumbersStreamsMain.java │ ├── PrimesMain.java │ ├── PrintingThreadPoolMain.java │ ├── RequiresVolatileMain.java │ ├── ReverseFilterMain.java │ ├── SharedCASPingPongMain.java │ ├── SqrtMain.java │ └── WaitNotifyPingPongMain.java │ ├── unsafe │ ├── AccessRawMemoryMain.java │ ├── ByteBufferMain.java │ ├── DirectByteBufferMain.java │ ├── FasterHashCodePref.java │ ├── HashCodePerf.java │ ├── MemoryMappingMain.java │ ├── MyType.java │ ├── OSResizesMain.java │ ├── PingPongMain.java │ ├── Unsafe2Demo.java │ ├── Unsafe3Demo.java │ ├── Unsafe4Demo.java │ ├── Unsafe5Demo.java │ ├── UnsafeDemo.java │ ├── UnsafeIdentityDemo.java │ └── UnsafeResetHashCodeDemo.java │ └── util │ └── ArrayMap.java └── test └── java ├── test └── lang │ └── ObjectTest.java └── vanilla └── java ├── perfeg └── mmap │ ├── DataGenerator.java │ ├── PerformanceTest.java │ └── results.txt └── util └── ArrayMapTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.iml 3 | .idea 4 | target 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | -------------------------------------------------------------------------------- /Java Questions - Lost in translation.txt: -------------------------------------------------------------------------------- 1 | Java Questions - What are they talking about? 2 | 3 | Java 5 - The actual version was "Java 5.0" 4 | 5 | Java 4 - The actual version was "Java 1.4" although often "Java 1.4.2" is the version they have in mind. 6 | 7 | mb - This could refer to mega-bytes (10^6 bytes), mebi-bytes (1024^2 bytes) 8 | 9 | mb/s - This could refer to mega-bytes/second (disk), mebi-bytes/second (memory), 10 | mega-baud/second (network utilisation), mega-bits/second. 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Performance-Examples 2 | ==================== -------------------------------------------------------------------------------- /instrumentation/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Performance-Examples 7 | vanilla.java 8 | 1.0 9 | 10 | 4.0.0 11 | 12 | instrumentation 13 | 14 | 15 | 16 | org.ow2.asm 17 | asm-all 18 | 5.0.3 19 | 20 | 21 | com.sun 22 | tools 23 | 1.8.0 24 | system 25 | ${java.home}/../lib/tools.jar 26 | 27 | 28 | 29 | 30 | 31 | org.apache.maven.plugins 32 | maven-jar-plugin 33 | 2.4 34 | 35 | 36 | 37 | vanilla.java.MyInstrumentation 38 | vanilla.java.MyInstrumentation 39 | 40 | 41 | 42 | 43 | 44 | 45 | org.apache.maven.plugins 46 | maven-compiler-plugin 47 | 48 | 1.8 49 | 1.8 50 | UTF-8 51 | true 52 | true 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /instrumentation/src/main/java/vanilla/java/ExampleMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java; 2 | 3 | import org.objectweb.asm.ClassReader; 4 | import org.objectweb.asm.util.ASMifier; 5 | import org.objectweb.asm.util.TraceClassVisitor; 6 | 7 | import java.io.PrintWriter; 8 | import java.util.function.Predicate; 9 | import java.util.stream.Stream; 10 | 11 | /** 12 | * Created by peter 13 | */ 14 | public class ExampleMain { 15 | static { 16 | MyInstrumentation.loadAgent(); 17 | } 18 | 19 | public static void main(String[] args) { 20 | Predicate predicate = x -> x % 2 == 0; 21 | Stream.of(1, 2, 3, 4).filter(predicate).forEach(System.out::println); 22 | 23 | TraceClassVisitor traceClassVisitor = new TraceClassVisitor(null, new ASMifier(), new PrintWriter(System.out)); 24 | ClassReader cr = new ClassReader(((RLambda) predicate).byte$()); 25 | cr.accept(traceClassVisitor, 0); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /instrumentation/src/main/java/vanilla/java/MyInstrumentation.java: -------------------------------------------------------------------------------- 1 | package vanilla.java; 2 | 3 | import com.sun.tools.attach.VirtualMachine; 4 | import org.objectweb.asm.*; 5 | 6 | import java.lang.instrument.ClassFileTransformer; 7 | import java.lang.instrument.IllegalClassFormatException; 8 | import java.lang.instrument.Instrumentation; 9 | import java.lang.management.ManagementFactory; 10 | import java.nio.charset.StandardCharsets; 11 | import java.security.ProtectionDomain; 12 | import java.util.Arrays; 13 | 14 | import static org.objectweb.asm.Opcodes.*; 15 | 16 | /** 17 | * Created by peter 18 | */ 19 | public class MyInstrumentation { 20 | public static final String RLAMBDA = RLambda.class.getName().replace('.', '/'); 21 | 22 | private static Instrumentation instrumentation; 23 | 24 | public static Instrumentation getInstrumentation() { 25 | return instrumentation; 26 | } 27 | 28 | public static void setInstrumentation(Instrumentation instrumentation) { 29 | MyInstrumentation.instrumentation = instrumentation; 30 | instrumentation.addTransformer(new MyClassFileTransformer()); 31 | } 32 | 33 | public static void premain(String agentArgs, Instrumentation inst) { 34 | System.out.println("premain " + agentArgs + " " + inst); 35 | setInstrumentation(inst); 36 | 37 | } 38 | 39 | public static void agentmain(String agentArgs, Instrumentation inst) { 40 | System.out.println("agentmain " + agentArgs + " " + inst); 41 | setInstrumentation(inst); 42 | } 43 | 44 | public static void loadAgent() { 45 | if (instrumentation != null) return; 46 | 47 | System.out.println("dynamically loading javaagent"); 48 | String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName(); 49 | int p = nameOfRunningVM.indexOf('@'); 50 | String pid = nameOfRunningVM.substring(0, p); 51 | 52 | String path = MyInstrumentation.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 53 | if (!path.endsWith(".jar")) 54 | path = System.getProperty("user.home") + "/.m2/repository/vanilla/java/instrumentation/1.0/instrumentation-1.0.jar"; 55 | try { 56 | VirtualMachine vm = VirtualMachine.attach(pid); 57 | vm.loadAgent(path, ""); 58 | vm.detach(); 59 | } catch (Exception e) { 60 | throw new RuntimeException(e); 61 | } 62 | } 63 | 64 | public static void main(String[] args) { 65 | loadAgent(); 66 | } 67 | 68 | static class MyClassFileTransformer implements ClassFileTransformer { 69 | @Override 70 | public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, final byte[] classfileBuffer) throws IllegalClassFormatException { 71 | 72 | try { 73 | if (className == null || className.startsWith("vanilla/java/test/")) { 74 | 75 | final boolean[] altered = {false}; 76 | final ClassWriter classWriter = new ClassWriter(0); 77 | // TraceClassVisitor traceClassVisitor = new TraceClassVisitor(classWriter, new ASMifier(), new PrintWriter(System.out)); 78 | 79 | final ClassVisitor cv = new ClassVisitor(ASM5, classWriter) { 80 | String name = ""; 81 | 82 | /** 83 | * Called when a class is visited. This is the method called first 84 | */ 85 | @Override 86 | public void visit(int version, int access, String name, 87 | String signature, String superName, String[] interfaces) { 88 | if (interfaces.length > 0 && !Arrays.asList(interfaces).contains(RLAMBDA)) { 89 | altered[0] = true; 90 | System.out.println("Visiting class: " + name + ", Class Major Version: " + version + ", Super class: " + superName); 91 | if (!name.startsWith("java/")) { 92 | String[] sarr = new String[interfaces.length + 1]; 93 | System.arraycopy(interfaces, 0, sarr, 0, interfaces.length); 94 | sarr[interfaces.length] = RLAMBDA; 95 | interfaces = sarr; 96 | } 97 | } 98 | this.name = name; 99 | super.visit(version, access, name, signature, superName, interfaces); 100 | } 101 | 102 | /** 103 | * When a field is encountered 104 | */ 105 | @Override 106 | public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { 107 | // System.out.println("Field: " + name + " " + desc + " value:" + value); 108 | return super.visitField(access, name, desc, signature, value); 109 | } 110 | 111 | @Override 112 | public void visitEnd() { 113 | if (altered[0]) { 114 | MethodVisitor mv = super.visitMethod(ACC_PUBLIC, "byte$", "()[B", null, null); 115 | mv.visitCode(); 116 | Label l0 = new Label(); 117 | mv.visitLabel(l0); 118 | mv.visitLineNumber(35, l0); 119 | mv.visitLdcInsn(new String(classfileBuffer, StandardCharsets.ISO_8859_1)); 120 | mv.visitFieldInsn(GETSTATIC, "java/nio/charset/StandardCharsets", "ISO_8859_1", "Ljava/nio/charset/Charset;"); 121 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "getBytes", "(Ljava/nio/charset/Charset;)[B", false); 122 | mv.visitInsn(ARETURN); 123 | Label l1 = new Label(); 124 | mv.visitLabel(l1); 125 | mv.visitLocalVariable("this", "L" + name + ";", null, l0, l1, 0); 126 | mv.visitMaxs(2, 1); 127 | mv.visitEnd(); 128 | } 129 | 130 | // System.out.println("Method ends here"); 131 | super.visitEnd(); 132 | } 133 | 134 | }; 135 | new ClassReader(classfileBuffer).accept(cv, 0); 136 | if (altered[0]) 137 | return classWriter.toByteArray(); 138 | } 139 | } catch (Throwable e) { 140 | e.printStackTrace(); 141 | } 142 | return classfileBuffer; 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /instrumentation/src/main/java/vanilla/java/RLambda.java: -------------------------------------------------------------------------------- 1 | package vanilla.java; 2 | 3 | public interface RLambda { 4 | public byte[] byte$(); 5 | } 6 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | vanilla.java 8 | Performance-Examples 9 | 1.0 10 | 11 | 12 | 1.11.3 13 | UTF-8 14 | 15 | 16 | 17 | net.openhft 18 | koloboke-impl-jdk6-7 19 | 0.6.8 20 | 21 | 22 | net.openhft 23 | chronicle-engine 24 | 1.12.11 25 | 26 | 27 | org.slf4j 28 | slf4j-simple 29 | 1.7.6 30 | 31 | 32 | org.openjdk.jmh 33 | jmh-core 34 | ${jmh.version} 35 | 36 | 37 | 38 | org.openjdk.jmh 39 | jmh-generator-annprocess 40 | ${jmh.version} 41 | provided 42 | 43 | 44 | junit 45 | junit 46 | 4.12 47 | 48 | 49 | 50 | 51 | 52 | 53 | maven-compiler-plugin 54 | 3.1 55 | 56 | 1.8 57 | 1.8 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/LatencyMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java; 2 | 3 | import net.openhft.chronicle.core.util.Histogram; 4 | 5 | /** 6 | * Created by peter.lawrey on 26/11/2015. 7 | */ 8 | public class LatencyMain { 9 | public static void main(String... args) throws InterruptedException { 10 | long start = System.currentTimeMillis(); 11 | int count = 500_000; 12 | Histogram hist = new Histogram(); 13 | for (int i = 0; i < count; i++) { 14 | long start2 = System.nanoTime(); 15 | 16 | doWork(i); 17 | 18 | long time2 = System.nanoTime() - start2; 19 | hist.sample(time2); 20 | } 21 | 22 | System.out.println(hist.toMicrosFormat()); 23 | 24 | long time = System.currentTimeMillis() - start; 25 | double average = (double) time / count; 26 | System.out.printf("Average latency %.3f milli-seconds%n", average); 27 | } 28 | 29 | private static void doWork(int i) throws InterruptedException { 30 | Thread.sleep(1); 31 | if (i % 500 == 0) 32 | Thread.sleep(10); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/MicroJitterSampler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Higher Frequency Trading 3 | * 4 | * http://www.higherfrequencytrading.com 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package vanilla.java; 20 | 21 | import java.io.PrintStream; 22 | /* e.g. 23 | After 2430 seconds, the average per hour was 24 | 2us 78400 25 | 3us 122703 26 | 4us 345238 27 | 6us 216098 28 | 8us 78694 29 | 10us 3977528 30 | 14us 114495 31 | 20us 4931 32 | 30us 203 33 | 40us 35 34 | 60us 18 35 | 80us 11 36 | 100us 9 37 | 140us 132 38 | 200us 85 39 | 300us 473 40 | 400us 5 41 | 1ms 24 42 | */ 43 | 44 | /** 45 | * User: peter.lawrey Date: 30/06/13 Time: 13:13 46 | */ 47 | class MicroJitterSampler { 48 | 49 | private static final long[] DELAY = { 50 | 2 * 1000, 3 * 1000, 4 * 1000, 6 * 1000, 8 * 1000, 10 * 1000, 14 * 1000, 51 | 20 * 1000, 30 * 1000, 40 * 1000, 60 * 1000, 80 * 1000, 100 * 1000, 140 * 1000, 52 | 200 * 1000, 300 * 1000, 400 * 1000, 600 * 1000, 800 * 1000, 1000 * 1000, 53 | 2 * 1000 * 1000, 5 * 1000 * 1000, 10 * 1000 * 1000, 54 | 20 * 1000 * 1000, 50 * 1000 * 1000, 100 * 1000 * 1000 55 | }; 56 | private static final double UTIL = Double.parseDouble(System.getProperty("util", "50")); 57 | private final int[] count = new int[DELAY.length]; 58 | private long totalTime = 0; 59 | 60 | public static void main(String... ignored) throws InterruptedException { 61 | 62 | // warmup. 63 | new MicroJitterSampler().sample(1000 * 1000 * 1000); 64 | 65 | MicroJitterSampler microJitterSampler = new MicroJitterSampler(); 66 | while (!Thread.currentThread().isInterrupted()) { 67 | if (UTIL >= 100) { 68 | microJitterSampler.sample(30L * 1000 * 1000 * 1000); 69 | 70 | } else { 71 | long sampleLength = (long) ((1 / (1 - UTIL / 100) - 1) * 1000 * 1000); 72 | for (int i = 0; i < 30 * 1000; i += 2) { 73 | microJitterSampler.sample(sampleLength); 74 | //noinspection BusyWait 75 | Thread.sleep(1); 76 | } 77 | } 78 | 79 | microJitterSampler.print(System.out); 80 | } 81 | } 82 | 83 | private static String asString(long timeNS) { 84 | return timeNS < 1000 ? timeNS + "ns" : 85 | timeNS < 1000000 ? timeNS / 1000 + "us" : 86 | timeNS < 1000000000 ? timeNS / 1000000 + "ms" : 87 | timeNS / 1000000000 + "sec"; 88 | } 89 | 90 | void sample(long intervalNS) { 91 | long prev = System.nanoTime(); 92 | long end = prev + intervalNS; 93 | long now; 94 | do { 95 | now = System.nanoTime(); 96 | long time = now - prev; 97 | if (time >= DELAY[0]) { 98 | int i; 99 | for (i = 1; i < DELAY.length; i++) 100 | if (time < DELAY[i]) 101 | break; 102 | count[i - 1]++; 103 | } 104 | prev = now; 105 | } while (now < end); 106 | totalTime += intervalNS; 107 | } 108 | 109 | void print(PrintStream ps) { 110 | ps.println("After " + totalTime / 1000000000 + " seconds, the average per hour was"); 111 | for (int i = 0; i < DELAY.length; i++) { 112 | if (count[i] < 1) continue; 113 | long countPerHour = (long) Math.ceil(count[i] * 3600e9 / totalTime); 114 | ps.println(asString(DELAY[i]) + '\t' + countPerHour); 115 | } 116 | ps.println(); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/OffHeapMapMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java; 2 | 3 | import net.openhft.chronicle.map.ChronicleMap; 4 | import net.openhft.chronicle.map.ChronicleMapBuilder; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | 9 | public class OffHeapMapMain { 10 | public static void main(String... ignored) throws IOException { 11 | ChronicleMap map = ChronicleMapBuilder 12 | .of(String.class, CharSequence.class) 13 | .createPersistedTo(new File("/tmp/shared")); 14 | map.put("Hello", "world"); 15 | CharSequence s = map.get("Hello"); 16 | System.out.println("s= " + s); 17 | map.close(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/Puzzle.java: -------------------------------------------------------------------------------- 1 | package vanilla.java; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | /** 6 | * Created by peter_2 on 26/11/2014. 7 | */ 8 | public class Puzzle { 9 | public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { 10 | Integer i = 5; 11 | Field value = Integer.class.getDeclaredField("value"); 12 | value.setAccessible(true); 13 | value.setInt(i, 6); 14 | 15 | Integer x = 2; 16 | Integer y = 3; 17 | Integer z = x + y; 18 | System.out.println(x + " + " + y + " is " + z); 19 | Integer a = 5; 20 | Integer b = 6; 21 | System.out.println(5 + " & " + b + " is equals " + a.equals(b)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/SplitCompareMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | import net.openhft.chronicle.bytes.StopCharTesters; 5 | 6 | import java.util.Scanner; 7 | 8 | public class SplitCompareMain { 9 | 10 | static volatile String a, b, c, d; 11 | static volatile int e, f, g, h; 12 | 13 | public static void main(String[] args) throws InterruptedException { 14 | for (int i = 0; i < 10; i++) { 15 | testSplit(); 16 | testBytes(); 17 | } 18 | } 19 | 20 | private static void testScanner() { 21 | for (int t = 0; t < 3; t++) { 22 | long start = System.currentTimeMillis(); 23 | int count = 20000; 24 | for (int i = 0; i < count; i++) { 25 | String s = "a,b,c,d,1,2,3,4"; 26 | Scanner scan = new Scanner(s).useDelimiter(","); 27 | a = scan.next(); 28 | b = scan.next(); 29 | c = scan.next(); 30 | d = scan.next(); 31 | e = scan.nextInt(); 32 | f = scan.nextInt(); 33 | g = scan.nextInt(); 34 | h = scan.nextInt(); 35 | } 36 | long time = (System.currentTimeMillis() - start) * 1000 / count; 37 | System.out.println("Average time " + time + "us."); 38 | } 39 | } 40 | 41 | private static void testSplit() { 42 | long start = System.currentTimeMillis(); 43 | int count = 500000; 44 | for (int i = 0; i < count; i++) { 45 | String s = "a,b,c,d,1,2,3,4"; 46 | String[] parts = s.split(","); 47 | a = parts[0]; 48 | b = parts[1]; 49 | c = parts[2]; 50 | d = parts[3]; 51 | e = Integer.parseInt(parts[4]); 52 | f = Integer.parseInt(parts[5]); 53 | g = Integer.parseInt(parts[6]); 54 | h = Integer.parseInt(parts[7]); 55 | } 56 | long time = (System.currentTimeMillis() - start) * 100000 / count; 57 | System.out.println("Split: Average time " + time / 1e2 + "us."); 58 | } 59 | 60 | private static void testBytes() { 61 | Bytes bytes = Bytes.allocateDirect(32); 62 | long start = System.currentTimeMillis(); 63 | int count = 500000; 64 | for (int i = 0; i < count; i++) { 65 | bytes.clear(); 66 | String s = "a,b,c,d,1,2,3,4"; 67 | bytes.append8bit(s); 68 | a = bytes.parseUtf8(StopCharTesters.COMMA_STOP); 69 | b = bytes.parseUtf8(StopCharTesters.COMMA_STOP); 70 | c = bytes.parseUtf8(StopCharTesters.COMMA_STOP); 71 | d = bytes.parseUtf8(StopCharTesters.COMMA_STOP); 72 | e = (int) bytes.parseLong(); 73 | f = (int) bytes.parseLong(); 74 | g = (int) bytes.parseLong(); 75 | h = (int) bytes.parseLong(); 76 | } 77 | long time = (System.currentTimeMillis() - start) * 100000 / count; 78 | System.out.println("Bytes: Average time " + time / 1e2 + "us."); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/async/AsyncMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.async; 2 | 3 | import net.openhft.lang.thread.NamedThreadFactory; 4 | 5 | import java.util.concurrent.Callable; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | 9 | /** 10 | * Created by peter_2 on 27/11/2014. 11 | */ 12 | public class AsyncMain { 13 | static final ExecutorService main = Executors.newSingleThreadExecutor(); 14 | static final ExecutorService async = Executors.newCachedThreadPool(new NamedThreadFactory("async", true)); 15 | 16 | // Asynchronous processing example. 17 | public static void main(String[] args) { 18 | mainRun(() -> startOutput(0, 100)); 19 | } 20 | 21 | public static void startOutput(int i, int max) { 22 | if (i < max) 23 | asyncRun(() -> { 24 | System.out.println(i + " and 1000/i is " + 1000/i); 25 | return null; 26 | }, 27 | r -> startOutput(i + 1, max) 28 | ); 29 | else 30 | main.shutdown(); 31 | } 32 | 33 | public static void mainRun(Runnable run) { 34 | main.submit(run); 35 | } 36 | 37 | public static void asyncRun(Callable task, ResultProcessor rp) { 38 | async.submit(() -> { 39 | try { 40 | R result = task.call(); 41 | main.submit(() -> rp.accept(result)); 42 | } catch (Throwable e) { 43 | main.submit(() -> rp.onThrowable(e)); 44 | } 45 | return null; 46 | }); 47 | } 48 | } 49 | 50 | interface ResultProcessor { 51 | void accept(R result); 52 | default void onThrowable(Throwable t) { 53 | t.printStackTrace(System.out); 54 | accept(errorResult()); 55 | } 56 | default R errorResult() { 57 | return null; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/async/SubmitMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.async; 2 | 3 | import java.nio.file.Files; 4 | import java.nio.file.Paths; 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | 8 | /** 9 | * Created by peter.lawrey on 07/12/2015. 10 | */ 11 | public class SubmitMain { 12 | public static void main(String[] args) { 13 | ExecutorService es = Executors.newSingleThreadExecutor(); 14 | es.submit(() -> { 15 | Files.lines(Paths.get("filename.txt")).forEach(System.out::println); 16 | return null; 17 | }); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/async/ThreadLocalMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.async; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | 7 | /** 8 | * Created by peter_2 on 27/11/2014. 9 | */ 10 | public class ThreadLocalMain { 11 | 12 | /* 13 | static final ThreadLocal SDF = new ThreadLocal() { 14 | @Override 15 | protected SimpleDateFormat initialValue() { 16 | return new SimpleDateFormat("yyyy/MM/dd'T'HH:mm:ss.SSSZ"); 17 | } 18 | }; 19 | */ 20 | static final ThreadLocal SDF = ThreadLocal.withInitial( 21 | () -> new SimpleDateFormat("yyyy/MM/dd'T'HH:mm:ss.SSSZ")); 22 | 23 | public static Date parseDate(String text) { 24 | try { 25 | return SDF.get().parse(text); 26 | } catch (ParseException e) { 27 | throw new IllegalArgumentException(e); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/bits/BitSetScanMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.bits; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.Mode; 5 | import org.openjdk.jmh.annotations.Scope; 6 | import org.openjdk.jmh.annotations.State; 7 | import org.openjdk.jmh.runner.Runner; 8 | import org.openjdk.jmh.runner.RunnerException; 9 | import org.openjdk.jmh.runner.options.Options; 10 | import org.openjdk.jmh.runner.options.OptionsBuilder; 11 | import org.openjdk.jmh.runner.options.TimeValue; 12 | 13 | import java.util.BitSet; 14 | import java.util.concurrent.TimeUnit; 15 | 16 | /** 17 | * Created by peter on 31/12/15. 18 | */ 19 | 20 | @State(Scope.Thread) 21 | public class BitSetScanMain { 22 | 23 | public static final int NBITS = 1_000_000; 24 | final BitSet bs = new BitSet(NBITS); 25 | final byte[] bytes = new byte[100000000]; 26 | 27 | { 28 | for (int i = 0; i + i < NBITS; i++) { 29 | bs.set(i); 30 | bytes[i] = 1; 31 | } 32 | } 33 | 34 | public static void main(String[] args) throws RunnerException { 35 | long time = 10; 36 | Options opt = new OptionsBuilder() 37 | .include(BitSetScanMain.class.getSimpleName()) 38 | .warmupIterations(6) 39 | .forks(1) 40 | .mode(Mode.SampleTime) 41 | .measurementTime(TimeValue.seconds(time)) 42 | .timeUnit(TimeUnit.MICROSECONDS) 43 | .build(); 44 | 45 | new Runner(opt).run(); 46 | } 47 | 48 | @Benchmark 49 | public int countBitSet() { 50 | int count = 0; 51 | for (int i = 0; (i = bs.nextSetBit(i + 1)) >= 0; ) { 52 | count += i; 53 | } 54 | return count; 55 | } 56 | 57 | @Benchmark 58 | public int countBytesSet() { 59 | int count = 0; 60 | for (int i = 0, bytesLength = bytes.length; i < bytesLength; i++) { 61 | byte b = bytes[i]; 62 | if (b == 1) 63 | count += i; 64 | } 65 | return count; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/collection/IteratorMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.collection; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | 7 | /** 8 | * Created by peter.lawrey on 12/01/2016. 9 | */ 10 | public class IteratorMain { 11 | public static void main(String... args) { 12 | List strings = new ArrayList<>(); 13 | strings.add("A"); 14 | strings.add("B"); 15 | strings.add("C"); 16 | strings.add("D"); 17 | for (Iterator iterator = strings.iterator(); iterator.hasNext(); ) { 18 | String string = iterator.next(); 19 | // System.out.println(string); 20 | // if (string.equals("C")) 21 | // strings.remove(string); 22 | iterator.remove(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/engine/MapPubSubMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.engine; 2 | 3 | import net.openhft.chronicle.engine.api.map.MapEvent; 4 | import net.openhft.chronicle.engine.api.map.MapView; 5 | import net.openhft.chronicle.engine.api.pubsub.Reference; 6 | import net.openhft.chronicle.engine.api.pubsub.TopicPublisher; 7 | import net.openhft.chronicle.engine.api.tree.AssetTree; 8 | import net.openhft.chronicle.engine.tree.VanillaAssetTree; 9 | 10 | import java.io.IOException; 11 | 12 | /** 13 | * Created by peter.lawrey on 23/11/2015. 14 | */ 15 | public class MapPubSubMain { 16 | public static void main(String[] args) throws IOException { 17 | AssetTree tree = new VanillaAssetTree("client").forTesting(Throwable::printStackTrace); 18 | MapView map = tree.acquireMap("/group/map", String.class, String.class); 19 | map.put("one", "hello"); 20 | map.put("two", "bye"); 21 | System.out.println(map); 22 | 23 | map.registerSubscriber(s -> System.out.println("key: " + s)); 24 | 25 | Reference three = tree.acquireReference("/group/map/one", String.class); 26 | three.registerSubscriber(true, 0, s -> System.out.println("one: " + s)); 27 | three.publish("test"); 28 | 29 | long len = three.syncUpdate(s -> s + 2, s -> (long) s.length()); 30 | System.out.println("one.length() = " + len); 31 | three.asyncUpdate(s -> s.substring(0, 4) + " two"); 32 | System.out.println("one.get() = " + three.get()); 33 | 34 | tree.registerSubscriber("/group/map", MapEvent.class, event -> System.out.println("map-event: " + event)); 35 | 36 | TopicPublisher topicPublisher = tree.acquireTopicPublisher("/group/map", String.class, String.class); 37 | topicPublisher.publish("three", "333"); 38 | topicPublisher.publish("four", "444"); 39 | 40 | topicPublisher.publish("four", "4444"); 41 | map.remove("four"); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/engine/RemoteMapPubSubMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.engine; 2 | 3 | import net.openhft.chronicle.engine.api.map.MapEvent; 4 | import net.openhft.chronicle.engine.api.map.MapView; 5 | import net.openhft.chronicle.engine.api.pubsub.Reference; 6 | import net.openhft.chronicle.engine.api.pubsub.TopicPublisher; 7 | import net.openhft.chronicle.engine.api.query.Subscription; 8 | import net.openhft.chronicle.engine.api.tree.AssetTree; 9 | import net.openhft.chronicle.engine.server.ServerEndpoint; 10 | import net.openhft.chronicle.engine.tree.VanillaAssetTree; 11 | import net.openhft.chronicle.network.TCPRegistry; 12 | import net.openhft.chronicle.wire.WireType; 13 | 14 | import java.io.IOException; 15 | 16 | /** 17 | * Created by peter.lawrey on 23/11/2015. 18 | */ 19 | public class RemoteMapPubSubMain { 20 | public static void main(String[] args) throws IOException { 21 | // YamlLogging.setAll(true); 22 | TCPRegistry.createServerSocketChannelFor("test.host.port"); 23 | 24 | AssetTree remoteTree = new VanillaAssetTree("test").forServer(Throwable::printStackTrace); 25 | ServerEndpoint serverEndpoint = new ServerEndpoint("test.host.port", remoteTree); 26 | 27 | 28 | AssetTree tree = new VanillaAssetTree("client").forRemoteAccess("test.host.port", WireType.TEXT, Throwable::printStackTrace); 29 | MapView map = tree.acquireMap("/group/map", String.class, String.class); 30 | 31 | Subscription subscribe = map.entrySet() 32 | .query() 33 | .filter(e -> e.getKey().length() == 3) 34 | .map(e -> e.toString()) 35 | .subscribe(s -> System.out.println("query: " + s)); 36 | 37 | map.put("one", "hello"); 38 | map.put("two", "bye"); 39 | System.out.println(map); 40 | 41 | map.registerSubscriber(s -> System.out.println("key: " + s)); 42 | 43 | Reference three = tree.acquireReference("/group/map/one", String.class); 44 | three.registerSubscriber(true, 0, s -> System.out.println("one: " + s)); 45 | three.publish("test"); 46 | int len = three.syncUpdate(s -> s + 2, String::length); 47 | System.out.println("one.length() = " + len); 48 | three.asyncUpdate(s -> s.substring(0, 4) + " two"); 49 | System.out.println("one.get() = " + three.get()); 50 | 51 | tree.registerSubscriber("/group/map", MapEvent.class, event -> System.out.println("map-event: " + event)); 52 | 53 | TopicPublisher topicPublisher = tree.acquireTopicPublisher("/group/map", String.class, String.class); 54 | topicPublisher.publish("three", "333"); 55 | topicPublisher.publish("four", "444"); 56 | 57 | topicPublisher.publish("four", "4444"); 58 | map.remove("four"); 59 | 60 | TCPRegistry.reset(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/exceptions/ExceptionSizeMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.exceptions; 2 | 3 | import java.sql.SQLException; 4 | 5 | /** 6 | * Created by peter on 15/09/2016. 7 | */ 8 | public class ExceptionSizeMain { 9 | public static long memoryUsed() { 10 | Runtime runtime = Runtime.getRuntime(); 11 | return runtime.totalMemory() - runtime.freeMemory(); 12 | } 13 | 14 | public static void main(String[] args) { 15 | // load classes etc. 16 | new SQLException("Hello").getStackTrace(); 17 | long before = memoryUsed(); 18 | new SQLException("Hello").getStackTrace(); 19 | long after = memoryUsed(); 20 | if (before == after) 21 | throw new AssertionError("Need to set -XX:-UseTLAB"); 22 | System.out.println("Exception used " + (after - before) + " bytes."); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/exceptions/NewInstanceMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.exceptions; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Files; 5 | import java.nio.file.Paths; 6 | 7 | /** 8 | * Created by peter on 15/09/2016. 9 | */ 10 | public class NewInstanceMain { 11 | NewInstanceMain() throws IOException { 12 | Files.lines(Paths.get("no-such-file")).forEach(System.out::println); 13 | } 14 | 15 | public static void main(String[] args) throws IllegalAccessException, InstantiationException { 16 | NewInstanceMain.class.newInstance(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/exceptions/PretendItDidntHappen2Main.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.exceptions; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.FileReader; 5 | import java.io.IOException; 6 | 7 | /** 8 | * Created by peter on 13/09/2016. 9 | */ 10 | public class PretendItDidntHappen2Main { 11 | 12 | public static void main(String[] args) throws IOException { 13 | 14 | readFile(); 15 | } 16 | 17 | static void readFile() throws IOException { 18 | try (FileReader fr = new FileReader("my-file.txt"); 19 | BufferedReader br = new BufferedReader(fr)) { 20 | String line = br.readLine(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/exceptions/PretendItDidntHappenMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.exceptions; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.FileNotFoundException; 5 | import java.io.FileReader; 6 | 7 | /** 8 | * Created by peter on 13/09/2016. 9 | */ 10 | public class PretendItDidntHappenMain { 11 | 12 | public static void main(String[] args) { 13 | 14 | FileReader fr = null; 15 | try { 16 | fr = new FileReader("my-file.txt"); 17 | } catch (FileNotFoundException e) { 18 | // who know?? 19 | } 20 | BufferedReader br = new BufferedReader(fr); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/exceptions/RethrowMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.exceptions; 2 | 3 | import java.sql.SQLException; 4 | 5 | /** 6 | * Created by peter on 15/09/2016. 7 | */ 8 | public class RethrowMain { 9 | public static RuntimeException rethrow(Throwable throwable) throws T { 10 | throw (T) throwable; // rely on vacuous cast 11 | } 12 | 13 | public static void main(String[] args) { 14 | throw rethrow(new SQLException("O Noes")); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/exceptions/SuddenIOExceptionMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.exceptions; 2 | 3 | import java.nio.file.Files; 4 | import java.nio.file.Path; 5 | import java.nio.file.Paths; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | 9 | /** 10 | * Created by peter on 15/09/2016. 11 | */ 12 | public class SuddenIOExceptionMain { 13 | public static void main(String[] args) { 14 | ExecutorService es = Executors.newSingleThreadExecutor(); 15 | Path file = Paths.get(args[0]); 16 | es.submit(() -> { 17 | Files.lines(file).forEach(System.out::println); 18 | return null; 19 | }); 20 | 21 | es.submit(() -> { 22 | // Files.lines(file).forEach(System.out::println); 23 | }); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/exceptions/ThrowableMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.exceptions; 2 | 3 | /** 4 | * Created by peter on 13/09/2016. 5 | */ 6 | public class ThrowableMain { 7 | public static void main(String[] args) throws MyThrowable { 8 | try { 9 | throw new MyThrowable(); 10 | 11 | } catch (Exception e) { 12 | System.out.println("Exception "); 13 | e.printStackTrace(); 14 | 15 | } catch (Error e) { 16 | System.out.println("Error "); 17 | e.printStackTrace(); 18 | } 19 | } 20 | 21 | static class MyThrowable extends Throwable { 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/exceptions/WhereIsMyExceptionMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.exceptions; 2 | 3 | import java.util.concurrent.BlockingQueue; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.Executors; 6 | import java.util.concurrent.LinkedBlockingQueue; 7 | 8 | /** 9 | * Created by peter on 15/09/2016. 10 | */ 11 | public class WhereIsMyExceptionMain { 12 | public static void main(String[] args) throws InterruptedException { 13 | ExecutorService es = Executors.newSingleThreadExecutor(); 14 | BlockingQueue req = new LinkedBlockingQueue<>(); 15 | es.submit(() -> req.add(new RuntimeException())); 16 | es.shutdown(); 17 | throw req.take(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/floatingpoint/BigDecimalRoundingMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.floatingpoint; 2 | 3 | import java.math.BigDecimal; 4 | import java.math.MathContext; 5 | 6 | /** 7 | * Created by peter on 13/10/2016. 8 | */ 9 | public class BigDecimalRoundingMain { 10 | public static void main(String[] args) { 11 | BigDecimal seven = BigDecimal.valueOf(7); 12 | BigDecimal bd = BigDecimal.ONE 13 | .divide(seven, MathContext.DECIMAL128) 14 | .multiply(seven, MathContext.DECIMAL128); 15 | System.out.println(bd); 16 | 17 | double d = 1.0 / 49 * 49; 18 | d = Math.round(d * 100) / 100.0; 19 | System.out.println(d); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/floatingpoint/DecodingFPMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.floatingpoint; 2 | 3 | /** 4 | * Created by peter on 11/10/2016. 5 | */ 6 | public class DecodingFPMain { 7 | public static String printFP(double d) { 8 | long l = Double.doubleToRawLongBits(d); 9 | boolean sign = l >= 0; 10 | int exponent = (int) ((l >> 52) & ((1 << 11) - 1)); 11 | exponent -= 1023; 12 | long manitissa = l & ((1L << 52) - 1); 13 | manitissa += 1L << 52; 14 | String manitissaText = "1." + Long.toBinaryString(manitissa).substring(1); 15 | manitissaText = manitissaText.replaceAll("0+$", ""); 16 | return d + " ==\n" + (sign ? "+" : "-") + manitissaText + "*2^" + exponent; 17 | } 18 | 19 | public static void main(String[] args) { 20 | System.out.println(printFP(100)); 21 | System.out.println(printFP(10)); 22 | System.out.println(printFP(5)); 23 | System.out.println(printFP(3)); 24 | System.out.println(printFP(2)); 25 | System.out.println(printFP(1)); 26 | System.out.println(printFP(0.5)); 27 | 28 | System.out.println(printFP(0.1)); 29 | System.out.println(printFP(0.2)); 30 | System.out.println(printFP(0.1 + 0.2)); 31 | System.out.println(printFP(0.3)); 32 | 33 | System.out.println(printFP(Double.NEGATIVE_INFINITY)); 34 | System.out.println(printFP(-0.0)); 35 | System.out.println(printFP(0.0)); 36 | System.out.println(printFP(Double.POSITIVE_INFINITY)); 37 | System.out.println(printFP(Double.NaN)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/floatingpoint/ModErrorMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.floatingpoint; 2 | 3 | import java.math.BigDecimal; 4 | import java.math.MathContext; 5 | 6 | /** 7 | * Created by peter on 13/10/2016. 8 | */ 9 | public class ModErrorMain { 10 | public static void main(String[] args) { 11 | BigDecimal tenth = new BigDecimal(0.1); 12 | BigDecimal ten = BigDecimal.ONE.divide(tenth, MathContext.DECIMAL128); 13 | System.out.println(ten.subtract(new BigDecimal(99).multiply(tenth)).doubleValue()); 14 | 15 | System.out.println(1.0 % 0.1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/floatingpoint/ToDecimalMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.floatingpoint; 2 | 3 | /** 4 | * Created by peter on 18/11/2016. 5 | */ 6 | public class ToDecimalMain { 7 | public static String toDecimal(long l) { 8 | StringBuilder sb = new StringBuilder(); 9 | do { 10 | long digit = l % 10; 11 | sb.append((char) ('0' + digit)); 12 | l /= 10; 13 | } while (l > 0); 14 | 15 | return sb.reverse().toString(); 16 | } 17 | 18 | public static void main(String[] args) { 19 | System.out.println(toDecimal(12345)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/floatingpoint/UsingBigDecimalMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.floatingpoint; 2 | 3 | import java.math.BigDecimal; 4 | 5 | /** 6 | * Created by peter on 11/10/2016. 7 | */ 8 | public class UsingBigDecimalMain { 9 | public static void main(String[] args) { 10 | double a = 0.1; 11 | double b = 0.2; 12 | double c = 0.3; 13 | System.out.println(a + b == c); 14 | 15 | BigDecimal ba = new BigDecimal(a); 16 | BigDecimal bb = new BigDecimal(b); 17 | BigDecimal bc = new BigDecimal(c); 18 | System.out.println(" " + ba + 19 | "\n + " + bb + 20 | "\n== " + ba.add(bb) + 21 | "\n!= " + bc); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/jmh/CalcBenchmark.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.jmh; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.runner.Runner; 5 | import org.openjdk.jmh.runner.RunnerException; 6 | import org.openjdk.jmh.runner.options.Options; 7 | import org.openjdk.jmh.runner.options.OptionsBuilder; 8 | import org.openjdk.jmh.runner.options.TimeValue; 9 | 10 | import java.io.IOException; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | /** 14 | * Created by peter on 10/04/16. 15 | */ 16 | public class CalcBenchmark { 17 | static int n = 10000; 18 | 19 | public static void main(String[] args) throws RunnerException, IOException { 20 | long time = 2; 21 | Options opt = new OptionsBuilder() 22 | .include(CalcBenchmark.class.getSimpleName()) 23 | .warmupIterations(6) 24 | .forks(1) 25 | .measurementTime(TimeValue.seconds(time)) 26 | .timeUnit(TimeUnit.NANOSECONDS) 27 | .build(); 28 | 29 | new Runner(opt).run(); 30 | } 31 | 32 | @Benchmark 33 | public long calc() { 34 | return (n - 1L) * n / 2 * (n + 1) / 3 * (3 * n + 2) / 2; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/jmh/GregorianMicroBenchmark.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.jmh; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | import org.openjdk.jmh.annotations.Benchmark; 5 | import org.openjdk.jmh.annotations.Mode; 6 | import org.openjdk.jmh.annotations.Scope; 7 | import org.openjdk.jmh.annotations.State; 8 | import org.openjdk.jmh.runner.Runner; 9 | import org.openjdk.jmh.runner.RunnerException; 10 | import org.openjdk.jmh.runner.options.Options; 11 | import org.openjdk.jmh.runner.options.OptionsBuilder; 12 | import org.openjdk.jmh.runner.options.TimeValue; 13 | 14 | import java.io.*; 15 | import java.util.Calendar; 16 | import java.util.concurrent.TimeUnit; 17 | 18 | /** 19 | * Created by peter.lawrey on 26/11/2015. 20 | */ 21 | @State(Scope.Thread) 22 | public class GregorianMicroBenchmark { 23 | Bytes bytes = Bytes.allocateDirect(64).unchecked(true); 24 | 25 | public static void main(String[] args) throws RunnerException, IOException { 26 | long time = 10; 27 | Options opt = new OptionsBuilder() 28 | .include(GregorianMicroBenchmark.class.getSimpleName()) 29 | .warmupIterations(6) 30 | .forks(1) 31 | .mode(Mode.SampleTime) 32 | .measurementTime(TimeValue.seconds(time)) 33 | .timeUnit(TimeUnit.NANOSECONDS) 34 | .build(); 35 | 36 | new Runner(opt).run(); 37 | } 38 | 39 | @Benchmark 40 | public Object testGregorianCalendar() throws IOException, ClassNotFoundException { 41 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 42 | ObjectOutputStream oos = new ObjectOutputStream(baos); 43 | oos.writeObject(Calendar.getInstance()); 44 | return new ObjectInputStream( 45 | new ByteArrayInputStream( 46 | baos.toByteArray())).readObject(); 47 | } 48 | 49 | @Benchmark 50 | public long testSystemCurrentTimeMillis() throws IOException, ClassNotFoundException { 51 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 52 | DataOutputStream oos = new DataOutputStream(baos); 53 | oos.writeLong(System.currentTimeMillis()); 54 | return new DataInputStream( 55 | new ByteArrayInputStream( 56 | baos.toByteArray())).readLong(); 57 | } 58 | 59 | @Benchmark 60 | public long usingBytes() throws IOException, ClassNotFoundException { 61 | bytes.clear(); 62 | bytes.writeLong(System.currentTimeMillis()); 63 | return bytes.readLong(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/jmh/MicroBenchmark.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.jmh; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.Mode; 5 | import org.openjdk.jmh.annotations.Scope; 6 | import org.openjdk.jmh.annotations.State; 7 | import org.openjdk.jmh.runner.Runner; 8 | import org.openjdk.jmh.runner.RunnerException; 9 | import org.openjdk.jmh.runner.options.Options; 10 | import org.openjdk.jmh.runner.options.OptionsBuilder; 11 | import org.openjdk.jmh.runner.options.TimeValue; 12 | 13 | import java.util.concurrent.TimeUnit; 14 | import java.util.concurrent.locks.LockSupport; 15 | 16 | /** 17 | * Created by peter.lawrey on 26/11/2015. 18 | */ 19 | @State(Scope.Thread) 20 | public class MicroBenchmark { 21 | public static void main(String[] args) throws RunnerException { 22 | long time = 10; 23 | Options opt = new OptionsBuilder() 24 | .include(MicroBenchmark.class.getSimpleName()) 25 | .warmupIterations(6) 26 | .forks(1) 27 | .mode(Mode.SampleTime) 28 | .measurementTime(TimeValue.seconds(time)) 29 | .timeUnit(TimeUnit.MICROSECONDS) 30 | .build(); 31 | 32 | new Runner(opt).run(); 33 | } 34 | 35 | @Benchmark 36 | public long testMe() { 37 | LockSupport.parkNanos(1); 38 | return 0; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/jmh/SimpleCalcBenchmark.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.jmh; 2 | 3 | import org.openjdk.jmh.runner.RunnerException; 4 | 5 | import java.io.IOException; 6 | import java.util.concurrent.atomic.AtomicLong; 7 | 8 | /** 9 | * Created by peter on 10/04/16. 10 | */ 11 | public class SimpleCalcBenchmark { 12 | static final AtomicLong blackHole = new AtomicLong(); 13 | static int n = 10000; 14 | 15 | public static void main(String[] args) throws RunnerException, IOException { 16 | for (int i = 0; i < 5; i++) { 17 | long start = System.nanoTime(); 18 | long counter = 0; 19 | while (System.nanoTime() - start < 2e9) { 20 | for (int j = 0; j < 100; j++) { 21 | blackHole.lazySet(calc()); 22 | } 23 | counter += 100; 24 | } 25 | long time = System.nanoTime() - start; 26 | System.out.printf("Took an average of %.1f ns%n", (double) time / counter); 27 | } 28 | } 29 | 30 | public static long calc() { 31 | return (n - 1L) * n / 2 * (n + 1) / 3 * (3 * n + 2) / 2; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/jmh/TimeBenchmark.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.jmh; 2 | 3 | import org.openjdk.jmh.annotations.Benchmark; 4 | import org.openjdk.jmh.annotations.Scope; 5 | import org.openjdk.jmh.annotations.State; 6 | import org.openjdk.jmh.runner.Runner; 7 | import org.openjdk.jmh.runner.RunnerException; 8 | import org.openjdk.jmh.runner.options.Options; 9 | import org.openjdk.jmh.runner.options.OptionsBuilder; 10 | import org.openjdk.jmh.runner.options.TimeValue; 11 | 12 | import java.time.LocalDateTime; 13 | import java.time.temporal.ChronoUnit; 14 | import java.util.concurrent.TimeUnit; 15 | 16 | /** 17 | * Created by peter.lawrey on 26/11/2015. 18 | */ 19 | /* 20 | # JMH 1.11.2 (released 75 days ago) 21 | # VM version: JDK 1.8.0_60, VM 25.60-b23 22 | # VM invoker: C:\Program Files\Java\jdk1.8.0_60\jre\bin\java.exe 23 | # VM options: -Didea.launcher.port=7533 -Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 14.1.4\bin -Dfile.encoding=windows-1252 24 | # Warmup: 6 iterations, 1 s each 25 | # Measurement: 20 iterations, 10 s each 26 | # Timeout: 10 min per iteration 27 | # Threads: 1 thread, will synchronize iterations 28 | # Benchmark mode: Throughput, ops/time 29 | # Benchmark: vanilla.java.jmh.TimeBenchmark.usingLocalDateTime 30 | 31 | # Run progress: 0.00% complete, ETA 00:06:52 32 | # Fork: 1 of 1 33 | # Warmup Iteration 1: 1.316 ops/us 34 | # Warmup Iteration 2: 3.805 ops/us 35 | # Warmup Iteration 3: 4.262 ops/us 36 | # Warmup Iteration 4: 4.183 ops/us 37 | # Warmup Iteration 5: 4.444 ops/us 38 | # Warmup Iteration 6: 4.582 ops/us 39 | Iteration 1: 4.622 ops/us 40 | Iteration 2: 4.669 ops/us 41 | Iteration 3: 4.532 ops/us 42 | Iteration 4: 4.655 ops/us 43 | Iteration 5: 4.491 ops/us 44 | Iteration 6: 4.225 ops/us 45 | Iteration 7: 4.574 ops/us 46 | Iteration 8: 4.593 ops/us 47 | Iteration 9: 4.676 ops/us 48 | Iteration 10: 4.676 ops/us 49 | Iteration 11: 4.641 ops/us 50 | Iteration 12: 4.678 ops/us 51 | Iteration 13: 4.691 ops/us 52 | Iteration 14: 4.673 ops/us 53 | Iteration 15: 4.678 ops/us 54 | Iteration 16: 4.681 ops/us 55 | Iteration 17: 4.576 ops/us 56 | Iteration 18: 4.683 ops/us 57 | Iteration 19: 4.679 ops/us 58 | Iteration 20: 4.678 ops/us 59 | 60 | 61 | Result "usingLocalDateTime": 62 | 4.619 ±(99.9%) 0.095 ops/us [Average] 63 | (min, avg, max) = (4.225, 4.619, 4.691), stdev = 0.109 64 | CI (99.9%): [4.524, 4.713] (assumes normal distribution) 65 | 66 | 67 | # JMH 1.11.2 (released 75 days ago) 68 | # VM version: JDK 1.8.0_60, VM 25.60-b23 69 | # VM invoker: C:\Program Files\Java\jdk1.8.0_60\jre\bin\java.exe 70 | # VM options: -Didea.launcher.port=7533 -Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 14.1.4\bin -Dfile.encoding=windows-1252 71 | # Warmup: 6 iterations, 1 s each 72 | # Measurement: 20 iterations, 10 s each 73 | # Timeout: 10 min per iteration 74 | # Threads: 1 thread, will synchronize iterations 75 | # Benchmark mode: Throughput, ops/time 76 | # Benchmark: vanilla.java.jmh.TimeBenchmark.usingLong 77 | 78 | # Run progress: 50.00% complete, ETA 00:03:26 79 | # Fork: 1 of 1 80 | # Warmup Iteration 1: 122.478 ops/us 81 | # Warmup Iteration 2: 122.398 ops/us 82 | # Warmup Iteration 3: 125.233 ops/us 83 | # Warmup Iteration 4: 125.909 ops/us 84 | # Warmup Iteration 5: 125.710 ops/us 85 | # Warmup Iteration 6: 124.877 ops/us 86 | Iteration 1: 125.416 ops/us 87 | Iteration 2: 125.175 ops/us 88 | Iteration 3: 125.472 ops/us 89 | Iteration 4: 125.844 ops/us 90 | Iteration 5: 125.726 ops/us 91 | Iteration 6: 120.867 ops/us 92 | Iteration 7: 125.745 ops/us 93 | Iteration 8: 124.924 ops/us 94 | Iteration 9: 125.814 ops/us 95 | Iteration 10: 125.529 ops/us 96 | Iteration 11: 125.533 ops/us 97 | Iteration 12: 125.703 ops/us 98 | Iteration 13: 125.839 ops/us 99 | Iteration 14: 125.394 ops/us 100 | Iteration 15: 125.790 ops/us 101 | Iteration 16: 125.580 ops/us 102 | Iteration 17: 125.432 ops/us 103 | Iteration 18: 125.378 ops/us 104 | Iteration 19: 125.355 ops/us 105 | Iteration 20: 124.910 ops/us 106 | 107 | 108 | Result "usingLong": 109 | 125.271 ±(99.9%) 0.931 ops/us [Average] 110 | (min, avg, max) = (120.867, 125.271, 125.844), stdev = 1.072 111 | CI (99.9%): [124.340, 126.202] (assumes normal distribution) 112 | 113 | 114 | # Run complete. Total time: 00:06:53 115 | 116 | Benchmark Mode Cnt Score Error Units 117 | TimeBenchmark.usingLocalDateTime thrpt 20 4.619 ± 0.095 ops/us 118 | TimeBenchmark.usingLong thrpt 20 125.271 ± 0.931 ops/us 119 | 120 | */ 121 | @State(Scope.Thread) 122 | public class TimeBenchmark { 123 | public static void main(String[] args) throws RunnerException { 124 | long time = 2; 125 | Options opt = new OptionsBuilder() 126 | .include(TimeBenchmark.class.getSimpleName()) 127 | .warmupIterations(6) 128 | .forks(3) 129 | .measurementTime(TimeValue.seconds(time)) 130 | .timeUnit(TimeUnit.MICROSECONDS) 131 | .build(); 132 | 133 | new Runner(opt).run(); 134 | } 135 | 136 | @Benchmark 137 | public LocalDateTime usingLocalDateTime() { 138 | LocalDateTime now = LocalDateTime.now(); 139 | LocalDateTime inSecs = now.truncatedTo(ChronoUnit.SECONDS); 140 | LocalDateTime tomorrow = inSecs.plusDays(1); 141 | return tomorrow; 142 | } 143 | 144 | @Benchmark 145 | public long usingLong() { 146 | long now = System.currentTimeMillis(); 147 | now -= now % 1000; 148 | now += TimeUnit.DAYS.toMillis(1); 149 | return now; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/lambda/CapturingMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.lambda; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashSet; 5 | import java.util.function.Consumer; 6 | 7 | /** 8 | * Created by peter.lawrey on 23/11/2015. 9 | */ 10 | public class CapturingMain { 11 | public static void main(String[] args) { 12 | Consumer pa = printMe(); 13 | Consumer pb = printMe(); 14 | System.out.println(pa.getClass()); 15 | System.out.println(pa == pb); 16 | System.out.println(new HashSet<>(Arrays.asList(pa, pb))); 17 | 18 | Consumer p2a = printMe2(); 19 | Consumer p2b = printMe2(); 20 | System.out.println(p2a == p2b); 21 | System.out.println(new HashSet<>(Arrays.asList(p2a, p2b))); 22 | 23 | Consumer p3a = s -> System.out.println(s); 24 | Consumer p3b = s -> System.out.println(s); 25 | System.out.println(p3a == p3b); 26 | System.out.println(p3a.equals(p3b)); 27 | System.out.println(new HashSet<>(Arrays.asList(p3a, p3b))); 28 | } 29 | 30 | static Consumer printMe() { 31 | return s -> System.out.println(s); 32 | } 33 | 34 | static Consumer printMe2() { 35 | return System.out::println; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/lambda/ConsumerMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.lambda; 2 | 3 | import org.junit.Assert; 4 | 5 | import java.time.LocalDate; 6 | import java.util.Date; 7 | import java.util.function.Consumer; 8 | import java.util.function.IntConsumer; 9 | import java.util.function.LongConsumer; 10 | 11 | /** 12 | * Created by peter.lawrey on 23/11/2015. 13 | */ 14 | public class ConsumerMain { 15 | public static void main(String[] args) { 16 | IntConsumer ic = i -> System.out.println(args[i]); 17 | LongConsumer lc = l -> System.out.println(new Date(l)); 18 | Consumer ldc = date -> Assert.assertFalse(date.isLeapYear()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/lambda/Counting.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.lambda; 2 | 3 | import java.util.stream.IntStream; 4 | import java.util.stream.Stream; 5 | 6 | /** 7 | * Created by peter_2 on 24/11/2014. 8 | */ 9 | public class Counting { 10 | public static void main(String[] args) { 11 | Stream is = Stream.of(1, 2, 3, 4, 5); 12 | long count = is.count(); 13 | System.out.println("count is " + count); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/lambda/FunctionMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.lambda; 2 | 3 | import java.util.function.BiFunction; 4 | import java.util.function.Function; 5 | import java.util.function.IntFunction; 6 | import java.util.function.ToIntFunction; 7 | 8 | /** 9 | * Created by peter.lawrey on 23/11/2015. 10 | */ 11 | public class FunctionMain { 12 | public static void main(String[] args) { 13 | // IntFunction> newMap = € -> new TreeMap<>(); 14 | IntFunction is = (i) -> Integer.toString(i); 15 | ToIntFunction ls = (s) -> s.length(); 16 | Function app = s -> s + " test"; 17 | BiFunction bsss = String::concat; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/lambda/Main.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.lambda; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | 6 | /** 7 | * Created by peter.lawrey on 12/01/2016. 8 | */ 9 | public class Main { 10 | public static void main(String[] args) { 11 | 12 | // print(new ArrayList<>()); 13 | print(Arrays.asList(1, 2, 3, 4)); 14 | } 15 | 16 | public static > void print(Collection list) { 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/lambda/NestedPutIfAbsentMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.lambda; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | /** 7 | * Created by peter.lawrey on 26/11/2015. 8 | */ 9 | public class NestedPutIfAbsentMain { 10 | public static void main(String[] args) { 11 | Map map = new ConcurrentHashMap<>(); 12 | map.computeIfAbsent(Key.Hello, s -> { 13 | map.computeIfAbsent(Key.Hello, t -> 1); 14 | return 2; 15 | }); 16 | System.out.println(map); 17 | } 18 | 19 | enum Key {Hello} 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/lambda/SerializableLambda.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.lambda; 2 | 3 | import net.openhft.chronicle.core.util.SerializableConsumer; 4 | 5 | /** 6 | * Created by peter.lawrey on 23/11/2015. 7 | */ 8 | public class SerializableLambda { 9 | public static void main(String[] args) { 10 | // Serializable printMe = 11 | // (Consumer & Serializable) 12 | // s -> System.out.println(s); 13 | new SerializableLambda().call(); 14 | } 15 | 16 | private void call() { 17 | apply(s -> System.out.println(s)); 18 | } 19 | 20 | public void apply(SerializableConsumer cs) { 21 | cs.accept("Hello World"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/lambda/Singleton.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.lambda; 2 | 3 | /** 4 | * Created by peter.lawrey on 12/01/2016. 5 | */ 6 | public enum Singleton { 7 | INSTANCE; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/lambda/StreamMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.lambda; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | /** 7 | * Created by peter.lawrey on 23/11/2015. 8 | */ 9 | public class StreamMain { 10 | public static void main(String[] args) { 11 | /*AtomicInteger count = new AtomicInteger(); 12 | IntStream.range(2, 100000) 13 | .parallel() 14 | .filter(i -> IntStream.range(2, (int) Math.sqrt(i)) 15 | .noneMatch(j -> i % j == 0)) 16 | .boxed() 17 | .peek(i -> count.incrementAndGet()) 18 | .collect(Collectors.toList()) 19 | .stream() 20 | .sorted() 21 | .forEach(System.out::println); 22 | System.out.println("Primes: " + count); 23 | */ 24 | Map cache = new ConcurrentHashMap<>(); 25 | String result = cache.computeIfAbsent("hello", s -> expensive(s)); 26 | 27 | String hello = "Hello"; 28 | Integer i = 128; 29 | Map> cache2 = new ConcurrentHashMap<>(); 30 | String si = 31 | cache2.computeIfAbsent(hello, s -> new ConcurrentHashMap<>()) 32 | .computeIfAbsent(i, j -> hello + j); 33 | } 34 | 35 | private static String expensive(String s) { 36 | throw new UnsupportedOperationException("todo"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/lambda/StringToInt.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.lambda; 2 | 3 | /** 4 | * Created by peter.lawrey on 12/01/2016. 5 | */ 6 | @FunctionalInterface 7 | public interface StringToInt { 8 | static boolean isStringToInt(Object o) { 9 | return o instanceof StringToInt; 10 | } 11 | 12 | long getLongFor(String s); 13 | 14 | default int getIntFor(String s) { 15 | return Math.toIntExact(getLongFor(s)); 16 | } 17 | 18 | default int count() { 19 | return StringToInts.count(this); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/lambda/StringToInts.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.lambda; 2 | 3 | /** 4 | * Created by peter.lawrey on 12/01/2016. 5 | */ 6 | public enum StringToInts { 7 | ; 8 | 9 | public static int count(StringToInt stringToInt) { 10 | throw new UnsupportedOperationException("todo"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/lambda/SuppliersMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.lambda; 2 | 3 | import java.util.Map; 4 | import java.util.TreeMap; 5 | import java.util.function.*; 6 | 7 | /** 8 | * Created by peter.lawrey on 23/11/2015. 9 | */ 10 | public class SuppliersMain { 11 | public static void main(String[] args) { 12 | BooleanSupplier bs = () -> true; 13 | IntSupplier is = () -> 1; 14 | LongSupplier ls = System::currentTimeMillis; 15 | DoubleSupplier ds = Math::random; 16 | Supplier> ms = TreeMap::new; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/math/BytesMatrix.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.math; 2 | 3 | import net.openhft.chronicle.bytes.NativeBytesStore; 4 | 5 | /** 6 | * Created by peter.lawrey on 14/01/2016. 7 | */ 8 | public class BytesMatrix { 9 | private static final long MAX_ROWS_OFFSET = 0L; 10 | private static final long USED_ROWS_OFFSET = MAX_ROWS_OFFSET + Integer.SIZE; 11 | private static final long COLUMNS_OFFSET = USED_ROWS_OFFSET + Integer.SIZE; 12 | private static final long HEADER_SIZE = COLUMNS_OFFSET + Integer.SIZE; 13 | 14 | private final NativeBytesStore bytes; 15 | private final int maxRows; 16 | private final int columns; 17 | private int rowsUsed = 0; 18 | 19 | public BytesMatrix(int maxRows, int columns) { 20 | this.maxRows = maxRows; 21 | this.columns = columns; 22 | long size = calcSize(maxRows, columns); 23 | bytes = NativeBytesStore.lazyNativeBytesStoreWithFixedCapacity(size); 24 | bytes.writeInt(MAX_ROWS_OFFSET, maxRows); 25 | bytes.writeInt(USED_ROWS_OFFSET, 0); 26 | bytes.writeInt(COLUMNS_OFFSET, columns); 27 | } 28 | 29 | public static void main(String... args) { 30 | BytesMatrix bm = new BytesMatrix(1024 * 1024, 1024); 31 | // bm.set(1000000, 0, 1.0); 32 | while (true) 33 | Thread.yield(); 34 | } 35 | 36 | public long address() { 37 | return bytes.address(0); 38 | } 39 | 40 | private long calcSize(int rows, int columns) { 41 | return HEADER_SIZE + (long) rows * columns * Double.BYTES; 42 | } 43 | 44 | public void set(int row, int column, double value) { 45 | long index = index(row, column); 46 | bytes.writeDouble(index, value); 47 | } 48 | 49 | public double get(int row, int column) { 50 | long index = index(row, column); 51 | return bytes.readDouble(index); 52 | } 53 | 54 | private long index(int row, int column) { 55 | assert row < 0 || row >= maxRows; 56 | assert column < 0 || column >= columns; 57 | if (row >= rowsUsed) { 58 | bytes.zeroOut(rowsUsed * columns * Double.BYTES, (row + 1) * columns * Double.BYTES); 59 | bytes.writeInt(USED_ROWS_OFFSET, rowsUsed = row + 1); 60 | } 61 | return HEADER_SIZE + (row * columns + column) * Double.BYTES; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/math/Fraction.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.math; 2 | 3 | import java.math.BigDecimal; 4 | import java.math.BigInteger; 5 | 6 | /** 7 | * Created by plawrey on 12/14/15. 8 | */ 9 | public class Fraction { 10 | public static String toDecimal(long numerator, int denominator) { 11 | StringBuilder sb = new StringBuilder(); 12 | sb.append(numerator / denominator); 13 | numerator %= denominator; 14 | if (numerator == 0) 15 | return sb.toString(); 16 | sb.append('.'); 17 | // add digits? 18 | while (numerator != 0 && (denominator % 2 == 0 || denominator % 5 == 0)) { 19 | numerator *= 10; 20 | sb.append(numerator / denominator); 21 | numerator %= denominator; 22 | while (numerator % 2 == 0 && denominator % 2 == 0) { 23 | numerator /= 2; 24 | denominator /= 2; 25 | } 26 | if (numerator % 5 == 0 && denominator % 5 == 0) { 27 | numerator /= 5; 28 | denominator /= 5; 29 | } 30 | } 31 | if (numerator > 0) { 32 | int count = 0; 33 | BigInteger denBD = BigInteger.valueOf(denominator); 34 | for (BigInteger bi = BigInteger.TEN; ; bi = bi.multiply(BigInteger.TEN)) { 35 | count++; 36 | if (bi.subtract(BigInteger.ONE).mod(denBD).compareTo(BigInteger.ZERO) == 0) { 37 | String divide = bi.multiply(BigInteger.valueOf(numerator)).divide(denBD).toString(); 38 | sb.append('('); 39 | while (count-- > divide.length()) 40 | sb.append('0'); 41 | sb.append(divide).append(')'); 42 | break; 43 | } 44 | } 45 | } 46 | return sb.toString(); 47 | } 48 | 49 | public static void main(String[] args) { 50 | for (int i = 31; i < 10001; i++) { 51 | String x = toDecimal(1, i); 52 | if (x.length() > 1000) { 53 | System.out.println(i); 54 | System.out.println(x); 55 | System.out.println(BigDecimal.valueOf(1).divide(BigDecimal.valueOf(i), 2000, BigDecimal.ROUND_HALF_UP)); 56 | break; 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/math/MutableHashMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.math; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.ConcurrentSkipListMap; 5 | 6 | /** 7 | * Created by peter.lawrey on 02/02/2016. 8 | */ 9 | public class MutableHashMain { 10 | public static void main(String... args) { 11 | Map map = new ConcurrentSkipListMap<>(); 12 | 13 | map.computeIfAbsent(1, k -> { 14 | map.computeIfAbsent(1, j -> 2); 15 | return 1; 16 | }); 17 | 18 | System.out.println(map); 19 | 20 | /* 21 | Map map = new HashMap<>(128, 0.75f); 22 | Key key = new Key(0); 23 | for (int i = 0; i <= 10; i++) { 24 | key.num = i; 25 | map.put(key, "" + i); 26 | } 27 | map.entrySet().forEach(System.out::println); 28 | String s = map.get(new Key(10)); 29 | System.out.println("s: "+s); 30 | */ 31 | } 32 | 33 | static final int hash(Object key) { 34 | int h; 35 | return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 36 | } 37 | } 38 | 39 | class Key { 40 | int num; 41 | 42 | public Key(int i) { 43 | num = i; 44 | } 45 | 46 | @Override 47 | public boolean equals(Object o) { 48 | if (this == o) return true; 49 | if (o == null || getClass() != o.getClass()) return false; 50 | 51 | Key key = (Key) o; 52 | 53 | return num == key.num; 54 | 55 | } 56 | 57 | @Override 58 | public int hashCode() { 59 | return num * 0x79216473; 60 | } 61 | 62 | @Override 63 | public String toString() { 64 | return "Key{" + 65 | "num=" + num + 66 | '}'; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/math/NativeCompute.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.math; 2 | 3 | /** 4 | * Created by peter.lawrey on 14/01/2016. 5 | */ 6 | public class NativeCompute { 7 | public static double access(BytesMatrix matrix, int row, int column) { 8 | return access(matrix.address(), row, column); 9 | } 10 | 11 | public static native double access(long address, int row, int column); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/math/NativeMatrix.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.math; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | /** 8 | * Created by peter.lawrey on 14/01/2016. 9 | */ 10 | public class NativeMatrix { 11 | // TODO use Bytes instead. 12 | static final Unsafe UNSAFE; 13 | private static final long ROWS_OFFSET = 0L; 14 | private static final long COLUMNS_OFFSET = 4L; 15 | private static final long HEADER_SIZE = 8L; 16 | 17 | static { 18 | try { 19 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 20 | theUnsafe.setAccessible(true); 21 | UNSAFE = (Unsafe) theUnsafe.get(null); 22 | } catch (Exception e) { 23 | throw new AssertionError(e); 24 | } 25 | } 26 | 27 | private final long address; 28 | private final int rows; 29 | private final int columns; 30 | 31 | public NativeMatrix(int rows, int columns) { 32 | this.rows = rows; 33 | this.columns = columns; 34 | long size = calcSize(rows, columns); 35 | address = UNSAFE.allocateMemory(size); 36 | UNSAFE.setMemory(address, size, (byte) 0); 37 | UNSAFE.putInt(address + ROWS_OFFSET, rows); 38 | UNSAFE.putInt(address + COLUMNS_OFFSET, columns); 39 | } 40 | 41 | private long calcSize(int rows, int columns) { 42 | return HEADER_SIZE + rows * columns * Double.BYTES; 43 | } 44 | 45 | @Override 46 | protected void finalize() throws Throwable { 47 | UNSAFE.freeMemory(address); 48 | } 49 | 50 | public void set(int row, int column, double value) { 51 | long index = index(row, column); 52 | UNSAFE.putDouble(index, value); 53 | } 54 | 55 | public double get(int row, int column) { 56 | long index = index(row, column); 57 | return UNSAFE.getDouble(index); 58 | } 59 | 60 | private long index(int row, int column) { 61 | if (row < 0 || row >= rows) throw new IllegalArgumentException(); 62 | if (column < 0 || column >= columns) throw new IllegalArgumentException(); 63 | return HEADER_SIZE + (row * columns + column) * Double.BYTES; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/math/Prime.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.math; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | /** 6 | * Created by peter_2 on 25/11/2014. 7 | */ 8 | public class Prime { 9 | boolean isPrime(int n) { 10 | return (n & 1) != 0 && 11 | IntStream.rangeClosed(1, (int) Math.sqrt(n) / 2) 12 | .noneMatch(i -> n % (i * 2 + 1) == 0); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/math/SqrtMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.math; 2 | 3 | /** 4 | * Created by peter.lawrey on 26/01/2016. 5 | */ 6 | public class SqrtMain { 7 | public static double sqrt(double ans) { 8 | if (ans < 1) 9 | return 1.0 / sqrt(1.0 / ans); 10 | double guess = 1; 11 | double add = ans / 2; 12 | while (add >= Math.ulp(guess)) { 13 | double guess2 = guess + add; 14 | double result = guess2 * guess2; 15 | if (result < ans) 16 | guess = guess2; 17 | else if (result == ans) 18 | return guess2; 19 | add /= 2; 20 | } 21 | return guess; 22 | } 23 | 24 | public static void main(String[] args) { 25 | for (int i = 0; i <= 10; i++) 26 | System.out.println(i / 10.0 + ": " + sqrt(i / 10.0) + " vs " + Math.sqrt(i / 10.0)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/memory/ArrayAllocationMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.memory; 2 | 3 | /** 4 | * Created by peter on 23/02/16. 5 | */ 6 | public class ArrayAllocationMain { 7 | public static void main(String[] args) { 8 | 9 | long used1 = memoryUsed(); 10 | int[][] array = new int[200][2]; 11 | 12 | long used2 = memoryUsed(); 13 | int[][] array2 = new int[2][200]; 14 | 15 | long used3 = memoryUsed(); 16 | if (used1 == used2) { 17 | System.err.println("You need to turn off the TLAB with -XX:-UseTLAB"); 18 | } else { 19 | System.out.printf("Space used by int[200][2] is " + (used2 - used1) + " bytes%n"); 20 | System.out.printf("Space used by int[2][200] is " + (used3 - used2) + " bytes%n"); 21 | } 22 | } 23 | 24 | public static long memoryUsed() { 25 | Runtime rt = Runtime.getRuntime(); 26 | return rt.totalMemory() - rt.freeMemory(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/memory/VisualVMMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.memory; 2 | 3 | import java.io.IOException; 4 | import java.util.stream.IntStream; 5 | 6 | /** 7 | * Created by peter.lawrey on 11/01/2016. 8 | */ 9 | public class VisualVMMain { 10 | public static void main(String... args) throws IOException, InterruptedException { 11 | for (int i = 0; ; i++) { 12 | if (runTest(i) < 0) 13 | throw new AssertionError(); 14 | } 15 | } 16 | 17 | private static long runTest(int i) { 18 | return IntStream.range(0, 10) 19 | .map(x -> x + i) 20 | .count(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/objects/CleanerMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.objects; 2 | 3 | import sun.misc.Cleaner; 4 | 5 | import java.util.RandomAccess; 6 | 7 | /** 8 | * Created by peter on 11/10/2016. 9 | */ 10 | public class CleanerMain { 11 | public static void main(String[] args) throws InterruptedException { 12 | new RandomAccess() { 13 | public void finalize() { 14 | new Throwable(Thread.currentThread().getName()).printStackTrace(); 15 | } 16 | }; 17 | Cleaner.create(new Integer(1), () -> 18 | new Throwable(Thread.currentThread().getName()).printStackTrace()); 19 | System.gc(); 20 | Thread.sleep(1000); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/objects/HowManyObjects2Main.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.objects; 2 | 3 | import java.io.IOException; 4 | import java.util.stream.IntStream; 5 | 6 | /** 7 | * Created by peter.lawrey on 23/11/2015. 8 | */ 9 | public class HowManyObjects2Main { 10 | public static void main(String[] args) throws IOException { 11 | IntStream.range(0, 10) 12 | .distinct() 13 | .forEach(System.out::println); 14 | System.in.read(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/objects/HowManyObjectsMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.objects; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * Created by peter.lawrey on 23/11/2015. 7 | */ 8 | public class HowManyObjectsMain { 9 | public static void main(String[] args) throws IOException { 10 | String a = "hello"; 11 | String b = "world"; 12 | String c = a + ' ' + b; 13 | System.out.println(c); 14 | 15 | System.in.read(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/optimisation/MemoryOptimisation2Main.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.optimisation; 2 | 3 | import java.util.*; 4 | import java.util.concurrent.ExecutionException; 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | import java.util.concurrent.Future; 8 | import java.util.function.Function; 9 | import java.util.logging.Logger; 10 | 11 | /** 12 | * git clone https://github.com/peter-lawrey/Performance-Examples 13 | * mvn install 14 | *

15 | * Memory optimisation sample program. 16 | *

17 | * This is the inefficient version. 18 | *

19 | * Created by peter. 20 | */ 21 | public class MemoryOptimisation2Main { 22 | static final Logger LOGGER = Logger.getLogger(MemoryOptimisation2Main.class.getName()); 23 | 24 | public static void main(String... args) throws ExecutionException, InterruptedException { 25 | 26 | for (int t = 0; t < 5; t++) { 27 | final int range = 1000, samples = 10000000, tasks = 4; 28 | long start = System.nanoTime(); 29 | Map map = new HashMap<>(); 30 | ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); 31 | List>> futures = new ArrayList<>(); 32 | for (int i = 0; i < tasks; i++) 33 | futures.add(es.submit(() -> { 34 | Function mappingFunction = k -> new int[1]; 35 | Random rand = new Random(); 36 | Map map2 = new HashMap<>(); 37 | for (int j = 0; j < samples / tasks; j++) { 38 | int next = rand.nextInt(range); 39 | int[] counter = map2.computeIfAbsent(next, 40 | mappingFunction); 41 | counter[0]++; 42 | // int count = counter.incrementAndGet(); 43 | // LOGGER.finest(next + ": " + count); 44 | } 45 | return map2; 46 | })); 47 | 48 | for (Future> future : futures) { 49 | Map map2 = future.get(); 50 | for (Map.Entry entry : map2.entrySet()) { 51 | Integer count = map.computeIfAbsent(entry.getKey(), k -> 0); 52 | map.put(entry.getKey(), count + entry.getValue()[0]); 53 | } 54 | } 55 | es.shutdown(); 56 | long time = System.nanoTime() - start; 57 | System.out.println("expected " + samples / range + " vs " + map.get(0) + " and " + map.get(range - 1)); 58 | System.out.printf("Average time per sample %,.1f ns%n", (double) time / samples); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/optimisation/MemoryOptimisationMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.optimisation; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | import java.util.concurrent.*; 7 | import java.util.concurrent.atomic.AtomicInteger; 8 | import java.util.logging.Logger; 9 | 10 | /** 11 | * git clone https://github.com/peter-lawrey/Performance-Examples 12 | * mvn install 13 | * 14 | * Memory optimisation sample program. 15 | *

16 | * This is the inefficient version. 17 | *

18 | * Created by peter. 19 | */ 20 | public class MemoryOptimisationMain { 21 | static final Logger LOGGER = Logger.getLogger(MemoryOptimisationMain.class.getName()); 22 | 23 | public static void main(String... args) throws ExecutionException, InterruptedException { 24 | 25 | final int range = 1000, samples = 10000, tasks = 1; 26 | long start = System.nanoTime(); 27 | ConcurrentMap map = new ConcurrentHashMap<>(); 28 | ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); 29 | List> futures = new ArrayList<>(); 30 | Random rand = new Random(); 31 | 32 | https://github.com/peter-lawrey/Performance-Examples 33 | for (int i = 0; i < tasks; i++) 34 | futures.add(es.submit(() -> { 35 | for (int j = 0, len = samples / tasks; j < len; j++) { 36 | int next = rand.nextInt(range); 37 | AtomicInteger counter = map.computeIfAbsent(next, 38 | k -> new AtomicInteger()); 39 | int count = counter.incrementAndGet(); 40 | LOGGER.finest(next + ": " + count); 41 | } 42 | })); 43 | for (Future future : futures) { 44 | future.get(); 45 | } 46 | es.shutdown(); 47 | long time = System.nanoTime() - start; 48 | System.out.println("expected " + samples / range + " vs " + map.get(0) + " and " + map.get(range - 1)); 49 | System.out.printf("Average time per sample %,.1f ns%n", (double) time / samples); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/optimisation/MemoryOptimisationXMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.optimisation; 2 | 3 | import net.openhft.koloboke.collect.map.hash.HashIntIntMap; 4 | import net.openhft.koloboke.collect.map.hash.HashIntIntMaps; 5 | 6 | import java.util.concurrent.ConcurrentHashMap; 7 | import java.util.concurrent.ConcurrentMap; 8 | import java.util.logging.Logger; 9 | 10 | /** 11 | * Memory optimisation sample program. 12 | *

13 | * This is the inefficient version. 14 | *

15 | * Created by peter. 16 | */ 17 | public class MemoryOptimisationXMain { 18 | static final Logger LOGGER = Logger.getLogger(MemoryOptimisationXMain.class.getName()); 19 | 20 | public static void main(String... args) { 21 | 22 | for (int i = 0; i < 5; i++) { 23 | for (int s = 1 << 16; s >= 64; s >>>= 1) { 24 | ConcurrentMap map = new ConcurrentHashMap<>(); 25 | HashIntIntMap map2 = HashIntIntMaps.newMutableMap(s); 26 | int[] array = new int[s]; 27 | long t0 = System.nanoTime(); 28 | for (int j = 0; j < 10000000; j += s) { 29 | for (int k = 0; k < s; k++) { 30 | Integer count = map.getOrDefault(k, 0); 31 | map.put(k, count + 1); 32 | } 33 | } 34 | long t1 = System.nanoTime(); 35 | for (int j = 0; j < 10000000; j += s) { 36 | for (int k = 0; k < s; k++) { 37 | int count = map2.getOrDefault(k, 0); 38 | map2.put(k, count + 1); 39 | } 40 | } 41 | long t2 = System.nanoTime(); 42 | for (int j = 0; j < 10000000; j += s) { 43 | for (int k = 0; k < s; k++) { 44 | int count = array[k]; 45 | array[k] = count + 1; 46 | } 47 | } 48 | long t3 = System.nanoTime(); 49 | System.out.printf("%,d : %,d vs %,d vs %,d : %.1f vs %.1f %n", 50 | s, (t1 - t0) / 1000, (t2 - t1) / 1000, (t3 - t2) / 1000, 51 | (double) (t1 - t0) / (t2 - t1), (double) (t2 - t1) / (t3 - t2)); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/optimisation/MemoryOptimisedMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.optimisation; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | import java.util.concurrent.ExecutionException; 7 | import java.util.concurrent.ExecutorService; 8 | import java.util.concurrent.Executors; 9 | import java.util.concurrent.Future; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * Memory optimisation sample program. 14 | *

15 | * This is the inefficient version. 16 | *

17 | * Created by peter. 18 | */ 19 | public class MemoryOptimisedMain { 20 | static final Logger LOGGER = Logger.getLogger(MemoryOptimisedMain.class.getName()); 21 | 22 | public static void main(String... args) throws ExecutionException, InterruptedException { 23 | ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); 24 | for (int t = 0; t < 5; t++) { 25 | final int range = 1000; 26 | final int samples = 10000000; 27 | final int tasks = 4; 28 | long start = System.nanoTime(); 29 | int[] counters0 = new int[range]; 30 | List> futures = new ArrayList<>(); 31 | for (int i = 0; i < tasks; i++) 32 | futures.add(es.submit(() -> { 33 | Random rand = new Random(); 34 | int[] counters = new int[range]; 35 | for (int j = 0; j < samples / tasks; j++) { 36 | int next = rand.nextInt(range); 37 | counters[next]++; 38 | } 39 | return counters; 40 | })); 41 | for (Future future : futures) { 42 | int[] counters2 = future.get(); 43 | for (int i = 0; i < counters2.length; i++) 44 | counters0[i] += counters2[i]; 45 | } 46 | long time = System.nanoTime() - start; 47 | System.out.println("expected " + samples / range + " vs " + counters0[0] + " and " + counters0[range - 1]); 48 | System.out.printf("Average time per sample %.1f ns%n", (double) time / samples); 49 | } 50 | es.shutdown(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/cache/CacheSizesPerMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.cache; 2 | 3 | import java.util.Arrays; 4 | import java.util.concurrent.*; 5 | 6 | public class CacheSizesPerMain { 7 | static final ExecutorService[] pools = new ExecutorService[6]; 8 | 9 | static class ScanTask implements Callable { 10 | final byte[] in = new byte[8 * 1024 * 1024]; 11 | final byte[] out = new byte[8 * 1024 * 1024]; 12 | 13 | @Override 14 | public Void call() throws Exception { 15 | double sum = 0; 16 | for (int i = 0; i < in.length; i++) { 17 | byte v = in[i]; 18 | sum += out[i] = v; 19 | } 20 | if (sum != 0) 21 | throw new AssertionError(); 22 | return null; 23 | } 24 | } 25 | 26 | public static void main(String... ignored) throws InterruptedException, ExecutionException { 27 | for (int i = 0; i < pools.length; i++) 28 | pools[i] = Executors.newFixedThreadPool(1 << i); 29 | Callable[] tasks = new Callable[64]; 30 | for (int i = 0; i < tasks.length; i++) 31 | tasks[i] = new ScanTask(); 32 | 33 | long[] times = new long[pools.length]; 34 | for (int i = 0; i < pools.length; i++) { 35 | times[i] += timeTasks(pools[i], tasks); 36 | } 37 | 38 | for (int i = 0; i < pools.length; i++) { 39 | System.out.printf("%,d threads took %.3f ms%n", 40 | 1 << i, times[i] / 1e6); 41 | } 42 | for (ExecutorService pool : pools) { 43 | pool.shutdown(); 44 | } 45 | } 46 | 47 | private static long timeTasks(ExecutorService pool, Callable[] tasks) throws InterruptedException, ExecutionException { 48 | long start = System.nanoTime(); 49 | for (Future future : pool.invokeAll(Arrays.asList(tasks))) future.get(); 50 | return System.nanoTime() - start; 51 | } 52 | 53 | private static long timeCorrel(float[] x, float[] y, int bits) { 54 | long start = System.nanoTime(); 55 | int repeats = (1 << Math.max(1, 20 - bits)); 56 | for (int r = 0; r < repeats; r++) { 57 | int count = 1 << (bits - 4); // bits of bytes / (2 * 8) for two floats. 58 | float sum_x = 0, sum_y = 0, sum_sq_x = 0, sum_sq_y = 0, co_product = 0; 59 | for (int i = 0; i < count; i++) { 60 | sum_x += x[i]; 61 | sum_y += y[i]; 62 | sum_sq_x += x[i] * x[i]; 63 | sum_sq_y += y[i] * y[i]; 64 | co_product += x[i] * y[i]; 65 | } 66 | 67 | float correl = (count * co_product - sum_x * sum_y) / 68 | (float) Math.sqrt((count * sum_sq_x - sum_x * sum_x) * (count * sum_sq_y - sum_y * sum_y)); 69 | // it should be small, but not too small. 70 | if (Math.abs(correl) > 0.1 || correl == 0) 71 | throw new AssertionError("count=" + count + " correl=" + correl); 72 | } 73 | return (System.nanoTime() - start) / repeats; 74 | } 75 | 76 | private static float[] generateRandom(int count) { 77 | float[] d = new float[count]; 78 | for (int i = 0; i < count; i++) d[i] = (float) Math.random(); 79 | return d; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/crypt/OverflowMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.crypt; 2 | 3 | import java.math.BigInteger; 4 | /* 5 | True answer 4,169,684,317 took 33.971 μs, quick answer 4,169,684,317 took 2.290 μs 6 | True answer 400,254,361 took 11.181 μs, quick answer 400,254,361 took 0.152 μs 7 | True answer 3,612,330,789 took 7.723 μs, quick answer 3,612,330,789 took 0.095 μs 8 | True answer 858,641,345 took 6.938 μs, quick answer 858,641,345 took 0.155 μs 9 | True answer 2,169,526,829 took 7.011 μs, quick answer 2,169,526,829 took 0.156 μs 10 | True answer 4,231,348,777 took 5.169 μs, quick answer 4,231,348,777 took 0.051 μs 11 | True answer 1,807,631,477 took 4.922 μs, quick answer 1,807,631,477 took 0.051 μs 12 | True answer 3,579,038,417 took 3.974 μs, quick answer 3,579,038,417 took 0.052 μs 13 | True answer 3,923,287,037 took 4.679 μs, quick answer 3,923,287,037 took 0.051 μs 14 | True answer 2,169,903,033 took 5.381 μs, quick answer 2,169,903,033 took 0.051 μs 15 | */ 16 | public class OverflowMain { 17 | public static void main(String... args) { 18 | BigInteger two32 = BigInteger.valueOf(2).pow(32); 19 | 20 | int prime = 2106945901; 21 | int runs = 5000; 22 | for (int i = 0; i < 10; i++) { 23 | long[] answer1 = new long[runs]; 24 | long[] answer2 = new long[runs]; 25 | long start = System.nanoTime(); 26 | 27 | for (int j = 0; j < runs; j++) 28 | answer1[j] = BigInteger.valueOf(prime).modPow(BigInteger.valueOf(prime + j), two32).longValue(); 29 | long mid = System.nanoTime(); 30 | 31 | for (int j = 0; j < runs; j++) 32 | answer2[j] = powMod2_32(prime, prime+j); 33 | long end = System.nanoTime(); 34 | System.out.printf("True answer %,d took %.3f μs, quick answer %,d took %.3f μs%n", 35 | answer1[i], (mid - start) / 1e3 / runs, answer2[i], (end - mid) / 1e3 / runs); 36 | } 37 | } 38 | 39 | public static long powMod2_32(int prime, int number) { 40 | int answer2 = 1; 41 | int p = prime; 42 | for (int n = number; n > 0; n >>>= 1) { 43 | if ((n & 1) != 0) 44 | answer2 *= p; 45 | p *= p; 46 | } 47 | return answer2 & 0xFFFFFFFFL; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/doublebracket/DoubleBracketMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.doublebracket; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * @author plawrey 7 | */ 8 | public class DoubleBracketMain { 9 | public static void main(String... args) { 10 | final List list1 = new ArrayList() { 11 | { 12 | add("Hello"); 13 | add("World"); 14 | add("!!!"); 15 | } 16 | }; 17 | List list2 = new ArrayList(list1); 18 | Set set1 = new LinkedHashSet() { 19 | { 20 | addAll(list1); 21 | } 22 | }; 23 | Set set2 = new LinkedHashSet(); 24 | set2.addAll(list1); 25 | Map map1 = new LinkedHashMap() { 26 | { 27 | put(1, "one"); 28 | put(2, "two"); 29 | put(3, "three"); 30 | } 31 | }; 32 | Map map2 = new LinkedHashMap(); 33 | map2.putAll(map1); 34 | 35 | for (int i = 0; i < 10; i++) { 36 | long dbTimes = timeComparison(list1, list1) 37 | + timeComparison(set1, set1) 38 | + timeComparison(map1.keySet(), map1.keySet()) 39 | + timeComparison(map1.values(), map1.values()); 40 | long times = timeComparison(list2, list2) 41 | + timeComparison(set2, set2) 42 | + timeComparison(map2.keySet(), map2.keySet()) 43 | + timeComparison(map2.values(), map2.values()); 44 | if (i > 0) 45 | System.out.printf("double braced collections took %,d ns and plain collections took %,d ns%n", dbTimes, times); 46 | } 47 | } 48 | 49 | public static long timeComparison(Collection a, Collection b) { 50 | long start = System.nanoTime(); 51 | int runs = 1000000; 52 | for (int i = 0; i < runs; i++) 53 | compareCollections(a, b); 54 | long rate = (System.nanoTime() - start) / runs; 55 | return rate; 56 | } 57 | 58 | public static void compareCollections(Collection a, Collection b) { 59 | if (!a.equals(b) && a.hashCode() != b.hashCode() && !a.toString().equals(b.toString())) 60 | throw new AssertionError(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/hwlimits/ActiveSocketMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.hwlimits; 2 | 3 | import java.io.IOException; 4 | import java.net.InetSocketAddress; 5 | import java.nio.ByteBuffer; 6 | import java.nio.channels.ServerSocketChannel; 7 | import java.nio.channels.SocketChannel; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.concurrent.Callable; 11 | import java.util.concurrent.ExecutionException; 12 | 13 | import static vanilla.java.perfeg.hwlimits.TestPools.report; 14 | import static vanilla.java.perfeg.hwlimits.TestPools.runTests; 15 | 16 | /* 17 | Ubuntu i7 18 | Socket echo scalability 19 | threads percentage speed (1 == 100%) 20 | 1 100% 21 | 2 196% 22 | 4 367% 23 | 8 504% 24 | 16 505% 25 | 32 505% 26 | 27 | Win 7 i5 28 | Socket echo scalability 29 | threads percentage speed (1 == 100%) 30 | 1 100% 31 | 2 113% 32 | 4 138% 33 | 8 166% 34 | 16 184% 35 | 32 195% 36 | */ 37 | public class ActiveSocketMain { 38 | public static void main(String... ignored) throws ExecutionException, InterruptedException, IOException { 39 | ServerSocketChannel ssc = ServerSocketChannel.open(); 40 | ssc.bind(new InetSocketAddress(0)); 41 | 42 | List> runs = new ArrayList>(); 43 | for (int i = 0; i < 64; i++) { 44 | final SocketChannel s = SocketChannel.open(new InetSocketAddress("localhost", ssc.socket().getLocalPort())); 45 | final SocketChannel s2 = ssc.accept(); 46 | 47 | runs.add(new Callable() { 48 | @Override 49 | public Integer call() throws Exception { 50 | ByteBuffer send = ByteBuffer.allocateDirect(1024); 51 | ByteBuffer recv = ByteBuffer.allocateDirect(1024); 52 | int count = 0; 53 | for (int i = 0; i < 1000; i++) { 54 | // send one way 55 | send.clear(); 56 | while (send.hasRemaining()) 57 | s.write(send); 58 | 59 | recv.clear(); 60 | while (recv.hasRemaining()) 61 | s2.read(recv); 62 | 63 | // send back. 64 | send.clear(); 65 | while (send.hasRemaining()) 66 | s2.write(send); 67 | 68 | recv.clear(); 69 | while (recv.hasRemaining()) 70 | s.read(recv); 71 | 72 | count++; 73 | } 74 | return count; 75 | } 76 | }); 77 | } 78 | ssc.close(); 79 | for (int i = 0; i < 3; i++) 80 | report("Socket echo scalability", runTests(runs)); 81 | 82 | // todo close all the sockets. 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/hwlimits/FileReadingMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.hwlimits; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.nio.ByteBuffer; 8 | import java.nio.channels.FileChannel; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.concurrent.Callable; 12 | import java.util.concurrent.ExecutionException; 13 | 14 | import static vanilla.java.perfeg.hwlimits.TestPools.report; 15 | import static vanilla.java.perfeg.hwlimits.TestPools.runTests; 16 | 17 | /* 18 | Ubuntu, i7 SSD 19 | threads percentage speed (1 == 100%) 20 | 1 100% 21 | 2 113% 22 | 4 117% 23 | 8 119% 24 | 16 120% 25 | 32 151% 26 | 27 | Win 7, i3 SSD with compressed files 28 | * File reading scalability 29 | * threads percentage speed (1 == 100%) 30 | * 1 100% 31 | * 2 133% 32 | * 4 115% 33 | * 8 120% 34 | * 16 138% 35 | * 32 139% 36 | * 37 | * 38 | Win 7, i5 HDD 39 | File reading scalability 40 | threads percentage speed (1 == 100%) 41 | 1 100% 42 | 2 69% 43 | 4 72% 44 | 8 46% 45 | 16 41% 46 | 32 32% 47 | */ 48 | public class FileReadingMain { 49 | public static void main(String... memorySize) throws ExecutionException, InterruptedException, IOException { 50 | long sizeGB = memorySize.length > 0 ? Integer.parseInt(memorySize[0]) : 16; 51 | 52 | System.out.println("Writing temporary files of " + sizeGB + " GB"); 53 | List> runs = new ArrayList>(); 54 | for (int i = 0; i <= 64; i++) { 55 | final File tmpFile = new File(System.getProperty("user.dir") + "/deleteme" + i + ".dat"); //File.createTempFile("deleteme", "dat"); 56 | tmpFile.deleteOnExit(); 57 | createFile(tmpFile, (sizeGB << 30) / 64); 58 | runs.add(new Callable() { 59 | @Override 60 | public ByteBuffer call() throws Exception { 61 | FileChannel fc = new FileInputStream(tmpFile).getChannel(); 62 | ByteBuffer bb = ByteBuffer.allocateDirect(64 * 1024); 63 | do { 64 | bb.clear(); 65 | } while (fc.read(bb) > 0); 66 | fc.close(); 67 | return bb; 68 | } 69 | }); 70 | } 71 | System.out.println("... done"); 72 | 73 | for (int i = 0; i < 3; i++) 74 | report("File reading scalability", runTests(runs)); 75 | } 76 | 77 | private static void createFile(File tmpFile, long sizeBytes) throws IOException { 78 | FileChannel fc = new FileOutputStream(tmpFile).getChannel(); 79 | ByteBuffer bb = ByteBuffer.allocateDirect(64 * 1024); 80 | for (long i = 0; i < sizeBytes; i += bb.capacity()) { 81 | bb.clear(); 82 | fc.write(bb); 83 | } 84 | fc.close(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/hwlimits/FixedPointLimitMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.hwlimits; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.Callable; 6 | import java.util.concurrent.ExecutionException; 7 | 8 | import static vanilla.java.perfeg.hwlimits.TestPools.report; 9 | import static vanilla.java.perfeg.hwlimits.TestPools.runTests; 10 | 11 | /* 12 | Ubuntu i7. 13 | Fixed Point int scalability 14 | threads percentage speed (1 == 100%) 15 | 1 100% 16 | 2 196% 17 | 4 360% 18 | 8 564% 19 | 16 558% 20 | 32 552% 21 | 22 | Win 7, i5 23 | Fixed Point int scalability 24 | threads percentage speed (1 == 100%) 25 | 1 100% 26 | 2 184% 27 | 4 261% 28 | 8 269% 29 | 16 273% 30 | 32 285% 31 | */ 32 | public class FixedPointLimitMain { 33 | static class Complex { 34 | static final int FIXED_BITS = 16; 35 | static final int FACTOR = 1 << FIXED_BITS; 36 | 37 | int re, im; 38 | 39 | Complex(double re, double im) { 40 | this.re = (int) (re * FACTOR); 41 | this.im = (int) (im * FACTOR); 42 | } 43 | 44 | public void sqrtPlus(Complex a) { 45 | int re2 = (re * re - im * im) / FACTOR + a.re; 46 | int im2 = (re * im) / (FACTOR / 2) + a.im; 47 | re = re2; 48 | im = im2; 49 | } 50 | } 51 | 52 | public static void main(String... ignored) throws ExecutionException, InterruptedException { 53 | List> runs = new ArrayList>(); 54 | for (int i = -4; i <= 4; i++) 55 | for (int j = -4; j <= 4; j++) { 56 | final Complex start = new Complex(i / 1e3, j / 1e3); 57 | runs.add(new Callable() { 58 | @Override 59 | public Complex call() throws Exception { 60 | Complex complex = new Complex(0, 0); 61 | for (int i = 0; i < 100000; i++) 62 | complex.sqrtPlus(start); 63 | return complex; 64 | } 65 | }); 66 | } 67 | for (int i = 0; i < 3; i++) 68 | report("Fixed Point int scalability", runTests(runs)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/hwlimits/FloatingPointLimitMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.hwlimits; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.Callable; 6 | import java.util.concurrent.ExecutionException; 7 | 8 | import static vanilla.java.perfeg.hwlimits.TestPools.report; 9 | import static vanilla.java.perfeg.hwlimits.TestPools.runTests; 10 | 11 | /* 12 | * FP scalability 13 | * threads percentage speed (1 == 100%) 14 | * 1 100% 15 | * 2 196% 16 | * 4 386% 17 | * 8 709% 18 | * 16 689% 19 | * 32 676% 20 | 21 | Win 7, i5 22 | FP scalability 23 | threads percentage speed (1 == 100%) 24 | 1 100% 25 | 2 195% 26 | 4 308% 27 | 8 309% 28 | 16 318% 29 | 32 333% 30 | */ 31 | public class FloatingPointLimitMain { 32 | static class Complex { 33 | double re, im; 34 | 35 | Complex(double re, double im) { 36 | this.re = re; 37 | this.im = im; 38 | } 39 | 40 | public void sqrtPlus(Complex a) { 41 | double re2 = re * re - im * im + a.re; 42 | double im2 = 2 * re * im + a.im; 43 | re = re2; 44 | im = im2; 45 | } 46 | } 47 | 48 | public static void main(String... ignored) throws ExecutionException, InterruptedException { 49 | List> runs = new ArrayList>(); 50 | for (int i = -4; i <= 4; i++) 51 | for (int j = -4; j <= 4; j++) { 52 | final Complex start = new Complex(i / 1e3, j / 1e3); 53 | runs.add(new Callable() { 54 | @Override 55 | public Complex call() throws Exception { 56 | Complex complex = new Complex(0, 0); 57 | for (int i = 0; i < 100000; i++) 58 | complex.sqrtPlus(start); 59 | return complex; 60 | } 61 | }); 62 | } 63 | for (int i = 0; i < 3; i++) 64 | report("FP scalability", runTests(runs)); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/hwlimits/MemoryBusLimitMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.hwlimits; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.Callable; 6 | import java.util.concurrent.ExecutionException; 7 | 8 | import static vanilla.java.perfeg.hwlimits.TestPools.*; 9 | 10 | /* 11 | Ubuntu i7, 12 | Data copy scalability for 64 x 8 KB 13 | threads percentage speed (1 == 100%) 14 | 1 100% 15 | 2 167% 16 | 4 178% 17 | 8 148% 18 | 16 137% 19 | 32 125% 20 | Data copy scalability for 64 x 1 MB 21 | threads percentage speed (1 == 100%) 22 | 1 100% 23 | 2 133% 24 | 4 145% 25 | 8 136% 26 | 16 138% 27 | 32 139% 28 | 29 | Win 7, i5 30 | Data copy scalability for 64 MB as 8 KB 31 | threads percentage speed (1 == 100%) 32 | 1 100% 33 | 2 123% 34 | 4 128% 35 | 8 125% 36 | 16 124% 37 | 32 127% 38 | Data copy scalability for 64 MB as 1 MB 39 | threads percentage speed (1 == 100%) 40 | 1 100% 41 | 2 103% 42 | 4 108% 43 | 8 105% 44 | 16 107% 45 | 32 107% 46 | */ 47 | public class MemoryBusLimitMain { 48 | public static void main(String... ignored) throws ExecutionException, InterruptedException { 49 | List> runsS = new ArrayList>(); 50 | for (int i = 0; i <= 1024 * 1024; i++) { 51 | final long[] data = new long[8]; // 64-byte cache line. 52 | runsS.add(new Callable() { 53 | @Override 54 | public long[] call() throws Exception { 55 | return data.clone(); 56 | } 57 | }); 58 | } 59 | 60 | List> runsM = new ArrayList>(); 61 | for (int i = 0; i <= 8 * 1024; i++) { 62 | final long[] data = new long[1024]; // 8 KB. 63 | runsM.add(new Callable() { 64 | @Override 65 | public long[] call() throws Exception { 66 | return data.clone(); 67 | } 68 | }); 69 | } 70 | 71 | List> runsL = new ArrayList>(); 72 | for (int i = 0; i <= 64; i++) { 73 | final long[] data = new long[128 * 1024]; // 1 MB. 74 | runsL.add(new Callable() { 75 | @Override 76 | public long[] call() throws Exception { 77 | return data.clone(); 78 | } 79 | }); 80 | } 81 | long[] sumS = null, sumM = null, sumL = null; 82 | for (int i = 0; i < 5; i++) { 83 | sumS = add(sumS, runTests(runsS)); 84 | sumM = add(sumM, runTests(runsM)); 85 | sumL = add(sumL, runTests(runsL)); 86 | // re-arrange memory. 87 | System.gc(); 88 | } 89 | report("Data copy scalability for 64 MB as 64 B", sumS); 90 | report("Data copy scalability for 64 MB as 8 KB", sumM); 91 | report("Data copy scalability for 64 MB as 1 MB", sumL); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/hwlimits/TestPools.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.hwlimits; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.*; 6 | 7 | /** 8 | */ 9 | public enum TestPools { 10 | ; 11 | private static ExecutorService[] SERVICES = new ExecutorService[6]; 12 | 13 | static { 14 | ThreadFactory deamonThreadFactory = new ThreadFactory() { 15 | @Override 16 | public Thread newThread(Runnable r) { 17 | Thread t = new Thread(r); 18 | t.setDaemon(true); 19 | return t; 20 | } 21 | }; 22 | for (int i = 0; i < 6; i++) { 23 | SERVICES[i] = Executors.newFixedThreadPool(1 << i, deamonThreadFactory); 24 | } 25 | } 26 | 27 | /** 28 | * Run the collection of tasks with different numbers of threads and time them. 29 | * 30 | * @param runs tasks to run. 31 | * @return average times. 32 | */ 33 | public static long[] runTests(List> runs) throws ExecutionException, InterruptedException { 34 | long[] times = new long[SERVICES.length]; 35 | long start = System.nanoTime(); 36 | int count = 0; 37 | do { 38 | count++; 39 | for (int i = 0; i < SERVICES.length; i++) { 40 | long start2 = System.nanoTime(); 41 | List> futures = new ArrayList>(); 42 | for (Callable run : runs) 43 | futures.add(SERVICES[i].submit(run)); 44 | for (Future future : futures) { 45 | future.get(); 46 | } 47 | long time2 = System.nanoTime() - start2; 48 | times[i] += time2; 49 | } 50 | } while (System.nanoTime() < start + 5e9); 51 | for (int i = 0; i < times.length; i++) 52 | times[i] /= count; 53 | return times; 54 | } 55 | 56 | public static void report(String description, long[] times) { 57 | System.out.println(description); 58 | System.out.println("threads\tpercentage speed (1 == 100%)"); 59 | for (int i = 0; i < times.length; i++) 60 | System.out.printf("%3d\t%d%%%n", 1 << i, times[0] * 100 / times[i]); 61 | } 62 | 63 | public static long[] add(long[] a, long[] b) { 64 | if (a == null) return b; 65 | if (b == null) return a; 66 | long[] ret = new long[Math.min(a.length, b.length)]; 67 | for (int i = 0; i < ret.length; i++) 68 | ret[i] = a[i] + b[i]; 69 | return ret; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/lambdas/PriceSearchMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.lambdas; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.stream.Collectors; 6 | 7 | /** 8 | * User: peter 9 | * Date: 03/09/13 10 | * Time: 09:00 11 | */ 12 | public class PriceSearchMain { 13 | 14 | static List products = new ArrayList<>(); 15 | static volatile List filteredProducts; 16 | static double minPrice, maxPrice; 17 | 18 | public static void main(String[] args) { 19 | for (int sampleSize : new int[]{100_000, 30_000, 10_000, 3_000, 1_000, 300, 100, 30, 10, 3, 1}) { 20 | generateProducts(sampleSize); 21 | 22 | long time1 = 0, time2 = 0, time3 = 0; 23 | int count = 0; 24 | long start = System.currentTimeMillis(); 25 | do { 26 | for (double window : new double[]{0.1, 0.5, 0.9}) { 27 | minPrice = 0.5 - window / 2; 28 | maxPrice = 0.5 + window / 2; 29 | time1 += testLoopingFilter(); 30 | time2 += testFlitering(); 31 | time3 += testParallelFlitering(); 32 | count++; 33 | } 34 | } while (System.currentTimeMillis() - start < 2e3); 35 | System.out.printf("%,d: Average time per search was %,d as loop, %,d as stream(), %,d as parallelStream() in ns %n", 36 | sampleSize, time1 / count, time2 / count, time3 / count); 37 | } 38 | } 39 | 40 | private static void generateProducts(int sampleSize) { 41 | products.clear(); 42 | for (int i = 0; i < sampleSize; i++) { 43 | products.add(new Product(Math.random())); 44 | } 45 | } 46 | 47 | public static long testLoopingFilter() { 48 | long start = System.nanoTime(); 49 | List found = new ArrayList<>(); 50 | for (Product product : products) 51 | if (product.price > minPrice && product.price < maxPrice) 52 | found.add(product); 53 | filteredProducts = found; 54 | return System.nanoTime() - start; 55 | } 56 | 57 | public static long testFlitering() { 58 | long start = System.nanoTime(); 59 | filteredProducts = products.stream().filter(p -> p.price > minPrice).filter(p -> p.price < maxPrice).collect(Collectors.toList()); 60 | return System.nanoTime() - start; 61 | } 62 | 63 | public static long testParallelFlitering() { 64 | long start = System.nanoTime(); 65 | filteredProducts = products.parallelStream().filter(p -> p.price > minPrice).filter(p -> p.price < maxPrice).collect(Collectors.toList()); 66 | return System.nanoTime() - start; 67 | } 68 | 69 | static class Product { 70 | final double price; 71 | 72 | Product(double price) { 73 | this.price = price; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/mmap/api/Column.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.mmap.api; 2 | 3 | /** 4 | * @author plawrey 5 | */ 6 | public interface Column { 7 | String name(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/mmap/api/Row.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.mmap.api; 2 | 3 | /** 4 | * @author plawrey 5 | */ 6 | public interface Row { 7 | public void index(int index); 8 | 9 | public int index(); 10 | 11 | public boolean nextRecord(); 12 | 13 | public long time(); 14 | 15 | public long get(Column column); 16 | 17 | void addEntry(long time); 18 | 19 | void set(Column column, long value); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/mmap/api/Table.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.mmap.api; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * @author plawrey 7 | */ 8 | public interface Table { 9 | public int size(); 10 | 11 | public Row createRow(); 12 | 13 | public Column acquireColumn(String name); 14 | 15 | public void close() throws IOException; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/mmap/flush/FlushMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.mmap.flush; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.RandomAccessFile; 6 | import java.nio.ByteBuffer; 7 | import java.nio.channels.FileChannel; 8 | 9 | /** 10 | * @author peter.lawrey 11 | */ 12 | public class FlushMain { 13 | public static void main(String... args) throws IOException { 14 | File file = File.createTempFile("deleteme", "dat"); 15 | file.deleteOnExit(); 16 | int tests = 10000; 17 | long start = System.nanoTime(); 18 | FileChannel fc = new RandomAccessFile(file, "rwd").getChannel(); 19 | for (int i = 0; i < tests; i++) 20 | fc.write(ByteBuffer.wrap(new byte[8])); 21 | fc.close(); 22 | long time = System.nanoTime() - start; 23 | System.out.printf("Average latency %.1f us%n", time / tests / 1e3); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/mmap/mmap/MmapRow.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.mmap.mmap; 2 | 3 | import vanilla.java.perfeg.mmap.api.Column; 4 | import vanilla.java.perfeg.mmap.api.Row; 5 | 6 | /** 7 | * @author plawrey 8 | */ 9 | public class MmapRow implements Row { 10 | private final MmapTable mmapTable; 11 | private int index = 0; 12 | 13 | public MmapRow(MmapTable mmapTable) { 14 | this.mmapTable = mmapTable; 15 | } 16 | 17 | @Override 18 | public void index(int index) { 19 | this.index = index; 20 | } 21 | 22 | @Override 23 | public int index() { 24 | return index(); 25 | } 26 | 27 | @Override 28 | public boolean nextRecord() { 29 | return index++ < mmapTable.size(); 30 | } 31 | 32 | @Override 33 | public long time() { 34 | return mmapTable.time.get(index); 35 | } 36 | 37 | @Override 38 | public long get(Column column) { 39 | return ((MmapTable.MmapColumn) column).get(index); 40 | } 41 | 42 | @Override 43 | public void addEntry(long time) { 44 | index = mmapTable.incrSize(); 45 | } 46 | 47 | @Override 48 | public void set(Column column, long value) { 49 | ((MmapTable.MmapColumn) column).set(index, value); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/mmap/mmap/MmapTable.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.mmap.mmap; 2 | 3 | import sun.misc.Unsafe; 4 | import sun.nio.ch.DirectBuffer; 5 | import vanilla.java.perfeg.mmap.api.Column; 6 | import vanilla.java.perfeg.mmap.api.Row; 7 | import vanilla.java.perfeg.mmap.api.Table; 8 | 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.io.RandomAccessFile; 12 | import java.lang.reflect.Field; 13 | import java.nio.ByteBuffer; 14 | import java.nio.ByteOrder; 15 | import java.nio.channels.FileChannel; 16 | import java.util.LinkedHashMap; 17 | import java.util.Map; 18 | 19 | /** 20 | * @author plawrey 21 | */ 22 | public class MmapTable implements Table { 23 | static final Unsafe unsafe; 24 | 25 | static { 26 | try { 27 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 28 | theUnsafe.setAccessible(true); 29 | unsafe = (Unsafe) theUnsafe.get(null); 30 | } catch (Exception e) { 31 | throw new AssertionError(e); 32 | } 33 | } 34 | 35 | private final Map colMap = new LinkedHashMap(); 36 | private final String baseDir; 37 | private final FileChannel sizeFC; 38 | private final ByteBuffer sizeMM; 39 | final MmapColumn time; 40 | private int size; 41 | 42 | public MmapTable(String baseDir) throws IOException { 43 | this.baseDir = baseDir; 44 | new File(baseDir).mkdirs(); 45 | File file = new File(baseDir, ".size"); 46 | sizeFC = new RandomAccessFile(file, "rw").getChannel(); 47 | sizeMM = sizeFC.map(FileChannel.MapMode.READ_WRITE, 0, 4).order(ByteOrder.nativeOrder()); 48 | time = new LongColumn(new File(baseDir, "time")); 49 | size = sizeMM.getInt(0); 50 | } 51 | 52 | @Override 53 | public int size() { 54 | return size; 55 | } 56 | 57 | @Override 58 | public Row createRow() { 59 | return new MmapRow(this); 60 | } 61 | 62 | @Override 63 | public Column acquireColumn(String name) { 64 | try { 65 | return new IntColumn(new File(baseDir, name)); 66 | } catch (IOException ioe) { 67 | throw new AssertionError(ioe); 68 | } 69 | } 70 | 71 | @Override 72 | public void close() throws IOException { 73 | for (MmapColumn mmapColumn : colMap.values()) { 74 | mmapColumn.close(); 75 | } 76 | } 77 | 78 | public int incrSize() { 79 | sizeMM.putInt(0, size + 1); 80 | return size++; 81 | } 82 | 83 | private class LongColumn extends MmapColumn { 84 | public LongColumn(File file) throws IOException { 85 | super(file, 8); 86 | } 87 | 88 | @Override 89 | long get(int index) { 90 | return unsafe.getLong(address + (index << 3)); 91 | } 92 | 93 | @Override 94 | void set(int index, long value) { 95 | unsafe.putLong(address + (index << 3), value); 96 | } 97 | } 98 | 99 | private class IntColumn extends MmapColumn { 100 | public IntColumn(File file) throws IOException { 101 | super(file, 4); 102 | } 103 | 104 | @Override 105 | long get(int index) { 106 | return unsafe.getLong(address + (index << 2)); 107 | } 108 | 109 | @Override 110 | void set(int index, long value) { 111 | unsafe.putLong(address + (index << 2), value); 112 | } 113 | } 114 | 115 | abstract class MmapColumn implements Column { 116 | private final String name; 117 | private final FileChannel fc; 118 | protected final ByteBuffer bb; 119 | protected final long address; 120 | private final int dataSize; 121 | 122 | MmapColumn(File file, int dataSize) throws IOException { 123 | this.dataSize = dataSize; 124 | this.name = file.getName(); 125 | fc = new RandomAccessFile(file, "rw").getChannel(); 126 | int size = Integer.MAX_VALUE / 8 * dataSize; 127 | bb = fc.map(FileChannel.MapMode.READ_WRITE, 0, size).order(ByteOrder.nativeOrder()); 128 | address = ((DirectBuffer) bb).address(); 129 | } 130 | 131 | @Override 132 | public String name() { 133 | return name; 134 | } 135 | 136 | abstract long get(int index); 137 | 138 | abstract void set(int index, long value); 139 | 140 | void close() throws IOException { 141 | fc.truncate(size() * dataSize); 142 | fc.close(); 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/mmap/oop/OopColumn.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.mmap.oop; 2 | 3 | import vanilla.java.perfeg.mmap.api.Column; 4 | 5 | /** 6 | * @author plawrey 7 | */ 8 | public abstract class OopColumn implements Column { 9 | private final String name; 10 | 11 | public OopColumn(String name) { 12 | this.name = name; 13 | } 14 | 15 | @Override 16 | public String name() { 17 | return name; 18 | } 19 | 20 | public abstract long get(RowEntry rowEntry); 21 | 22 | public abstract void set(RowEntry rowEntry, long value); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/mmap/oop/OopRow.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.mmap.oop; 2 | 3 | import vanilla.java.perfeg.mmap.api.Column; 4 | import vanilla.java.perfeg.mmap.api.Row; 5 | 6 | /** 7 | * @author plawrey 8 | */ 9 | public class OopRow implements Row { 10 | private final OopTable oopTable; 11 | private int index = 0; 12 | 13 | public OopRow(OopTable oopTable) { 14 | this.oopTable = oopTable; 15 | } 16 | 17 | @Override 18 | public void index(int index) { 19 | this.index = index; 20 | } 21 | 22 | @Override 23 | public int index() { 24 | return index; 25 | } 26 | 27 | @Override 28 | public boolean nextRecord() { 29 | return ++index < oopTable.size(); 30 | } 31 | 32 | @Override 33 | public long time() { 34 | return oopTable.list.get(index).time; 35 | } 36 | 37 | @Override 38 | public long get(Column column) { 39 | return ((OopColumn) column).get(oopTable.list.get(index)); 40 | } 41 | 42 | @Override 43 | public void addEntry(long time) { 44 | index = oopTable.size(); 45 | oopTable.list.add(new RowEntry(time)); 46 | } 47 | 48 | @Override 49 | public void set(Column column, long value) { 50 | ((OopColumn) column).set(oopTable.list.get(index), value); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/mmap/oop/OopTable.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.mmap.oop; 2 | 3 | import vanilla.java.perfeg.mmap.api.Column; 4 | import vanilla.java.perfeg.mmap.api.Row; 5 | import vanilla.java.perfeg.mmap.api.Table; 6 | 7 | import java.io.File; 8 | import java.io.FileInputStream; 9 | import java.io.FileOutputStream; 10 | import java.io.IOException; 11 | import java.nio.ByteBuffer; 12 | import java.nio.ByteOrder; 13 | import java.nio.channels.FileChannel; 14 | import java.util.ArrayList; 15 | import java.util.LinkedHashMap; 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | /** 20 | * @author plawrey 21 | */ 22 | public class OopTable implements Table { 23 | final List list = new ArrayList(); 24 | final String baseDir; 25 | final Map columnMap = new LinkedHashMap(); 26 | 27 | public OopTable(String baseDir) throws IOException { 28 | this.baseDir = baseDir; 29 | 30 | File data = new File(baseDir, "data"); 31 | if (data.exists()) { 32 | FileChannel fc = new FileInputStream(data).getChannel(); 33 | ByteBuffer bb = ByteBuffer.allocateDirect(64 * 1024).order(ByteOrder.nativeOrder()); 34 | while (fc.read(bb) > 0) { 35 | bb.flip(); 36 | while (bb.remaining() >= RowEntry.SIZE) 37 | list.add(new RowEntry(bb)); 38 | bb.compact(); 39 | } 40 | fc.close(); 41 | } 42 | } 43 | 44 | { 45 | columnMap.put("bidPrice", new OopColumn("bidPrice") { 46 | @Override 47 | public long get(RowEntry rowEntry) { 48 | return rowEntry.bidPrice & 0xFFFFFFFFL; // unsigned int 49 | } 50 | 51 | @Override 52 | public void set(RowEntry rowEntry, long value) { 53 | rowEntry.bidPrice = (int) value; 54 | } 55 | }); 56 | columnMap.put("askPrice", new OopColumn("askPrice") { 57 | @Override 58 | public long get(RowEntry rowEntry) { 59 | return rowEntry.askPrice & 0xFFFFFFFFL; // unsigned int 60 | } 61 | 62 | @Override 63 | public void set(RowEntry rowEntry, long value) { 64 | rowEntry.askPrice = (int) value; 65 | } 66 | }); 67 | columnMap.put("midBP", new OopColumn("midBP") { 68 | @Override 69 | public long get(RowEntry rowEntry) { 70 | return rowEntry.midBP & 0xFFFFFFFFL; // unsigned int 71 | } 72 | 73 | @Override 74 | public void set(RowEntry rowEntry, long value) { 75 | rowEntry.midBP = (int) value; 76 | } 77 | }); 78 | } 79 | 80 | 81 | @Override 82 | public int size() { 83 | return list.size(); 84 | } 85 | 86 | @Override 87 | public Row createRow() { 88 | return new OopRow(this); 89 | } 90 | 91 | @Override 92 | public Column acquireColumn(String name) { 93 | return columnMap.get(name); 94 | } 95 | 96 | @Override 97 | public void close() throws IOException { 98 | new File(baseDir).mkdirs(); 99 | File data = new File(baseDir, "data"); 100 | FileChannel fc = new FileOutputStream(data).getChannel(); 101 | ByteBuffer bb = ByteBuffer.allocateDirect(64 * 1024).order(ByteOrder.nativeOrder()); 102 | for (RowEntry rowEntry : list) { 103 | if (bb.remaining() < RowEntry.SIZE) { 104 | bb.flip(); 105 | fc.write(bb); 106 | bb.compact(); 107 | } 108 | rowEntry.writeTo(bb); 109 | } 110 | bb.flip(); 111 | fc.write(bb); 112 | fc.close(); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/mmap/oop/RowEntry.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.mmap.oop; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | /** 6 | * @author plawrey 7 | */ 8 | class RowEntry { 9 | static final int SIZE = 8 + 3 * 4; 10 | 11 | final long time; 12 | int bidPrice; 13 | int askPrice; 14 | int midBP; 15 | 16 | public RowEntry(long time) { 17 | this.time = time; 18 | } 19 | 20 | public RowEntry(ByteBuffer bb) { 21 | time = bb.getLong(); 22 | bidPrice = bb.getInt(); 23 | askPrice = bb.getInt(); 24 | midBP = bb.getInt(); 25 | } 26 | 27 | public void writeTo(ByteBuffer bb) { 28 | bb.putLong(time); 29 | bb.putInt(bidPrice); 30 | bb.putInt(askPrice); 31 | bb.putInt(midBP); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/tcp/EchoClientMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.tcp; 2 | 3 | import net.openhft.affinity.Affinity; 4 | 5 | import java.io.*; 6 | import java.net.Socket; 7 | import java.util.Arrays; 8 | 9 | /** 10 | * @author peter.lawrey 11 | */ 12 | // On Loopback: Throughput was 3011.2 MB/s 13 | // Loopback echo latency was 7.8/8.2 12.7/38.2 us for 50/90 99/99.9%tile 14 | // 1m - Loopback echo latency was 7.8/8.2 12.3/34.9 81.7us for 50/90 99/99.9 99.99%tile 15 | // 10m - Loopback echo latency was 7.8/8.2 12.3/40.6 121.1us for 50/90 99/99.9 99.99%tile 16 | // 100m - Loopback echo latency was 7.8/7.8 11.9/35.3 56.2us for 50/90 99/99.9 99.99%tile 17 | 18 | // tests=100k, repeats=10 - Loop back echo latency was 29.1/31.6 32.4/32.4 32.4us for 50/90 99/99.9 99.99%tile 19 | public class EchoClientMain { 20 | static final int PORT = 54321; 21 | 22 | public static void main(String... args) throws IOException { 23 | Affinity.setAffinity(3); 24 | String hostname = args.length < 1 ? "localhost" : args[0]; 25 | int port = args.length < 2 ? PORT : Integer.parseInt(args[1]); 26 | int repeats = 1; 27 | 28 | Socket[] sockets = new Socket[repeats]; 29 | DataInputStream[] in = new DataInputStream[repeats]; 30 | DataOutputStream[] out = new DataOutputStream[repeats]; 31 | for (int j = 0; j < repeats; j++) { 32 | Socket socket = new Socket(hostname, port); 33 | // socket.setTcpNoDelay(true); 34 | sockets[j] = socket; 35 | out[j] = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); 36 | in[j] = new DataInputStream(new BufferedInputStream(socket.getInputStream())); 37 | } 38 | testThroughput(repeats, in, out); 39 | testLatency(repeats, in, out); 40 | for (Closeable socket : sockets) 41 | socket.close(); 42 | } 43 | 44 | private static void testThroughput(int repeats, DataInputStream[] in, DataOutputStream[] out) throws IOException { 45 | System.out.println("Starting throughput test"); 46 | int bufferSize = 32 * 1024; 47 | byte[] bytes = new byte[bufferSize]; 48 | int count = 0, window = 2; 49 | long start = System.nanoTime(); 50 | while (System.nanoTime() - start < 5e9) { 51 | for (int j = 0; j < repeats; j++) { 52 | out[j].write(bytes); 53 | out[j].flush(); 54 | } 55 | if (count >= window) 56 | for (int j = 0; j < repeats; j++) { 57 | in[j].readFully(bytes); 58 | } 59 | count++; 60 | } 61 | for (int end = 0; end < Math.min(count, window); end++) 62 | for (int j = 0; j < repeats; j++) { 63 | in[j].readFully(bytes); 64 | } 65 | long time = System.nanoTime() - start; 66 | System.out.printf("Throughput was %.1f MB/s%n", 1e3 * count * bufferSize * repeats / time); 67 | } 68 | 69 | private static void testLatency(int repeats, DataInputStream[] in, DataOutputStream[] out) throws IOException { 70 | System.out.println("Starting latency test"); 71 | int tests = 200000; 72 | long[] times = new long[tests * repeats]; 73 | int count = 0; 74 | for (int i = -20000; i < tests; i++) { 75 | long now = System.nanoTime(); 76 | for (int j = 0; j < repeats; j++) { 77 | out[j].writeLong(now); 78 | out[j].flush(); 79 | } 80 | 81 | for (int j = 0; j < repeats; j++) { 82 | long time = System.nanoTime() - in[j].readLong(); 83 | if (i >= 0) 84 | times[count++] = time; 85 | } 86 | } 87 | Arrays.sort(times); 88 | System.out.printf("Loop back echo latency was %.1f/%.1f %.1f/%.1f %.1fus for 50/90 99/99.9 99.99%%tile%n", 89 | times[tests / 2] / 1e3, times[tests * 9 / 10] / 1e3, 90 | times[tests - tests / 100] / 1e3, times[tests - tests / 1000] / 1e3, 91 | times[tests - tests / 10000] / 1e3); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/perfeg/tcp/EchoServerMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.tcp; 2 | 3 | import net.openhft.affinity.Affinity; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.OutputStream; 8 | import java.net.ServerSocket; 9 | import java.net.Socket; 10 | 11 | /** 12 | * @author peter.lawrey 13 | */ 14 | public class EchoServerMain { 15 | public static void main(String... args) throws IOException { 16 | Affinity.setAffinity(2); 17 | int port = args.length < 1 ? EchoClientMain.PORT : Integer.parseInt(args[0]); 18 | ServerSocket ss = new ServerSocket(port); 19 | System.out.println("listening on " + ss); 20 | while (true) { 21 | final Socket socket = ss.accept(); 22 | new Thread(new Runnable() { 23 | @Override 24 | public void run() { 25 | try { 26 | System.out.println("Connected " + socket); 27 | InputStream in = socket.getInputStream(); 28 | OutputStream out = socket.getOutputStream(); 29 | byte[] bytes = new byte[64 * 1024]; 30 | for (int len; (len = in.read(bytes)) > 0; ) { 31 | out.write(bytes, 0, len); 32 | } 33 | } catch (IOException ignored) { 34 | } finally { 35 | System.out.println("... disconnected " + socket); 36 | try { 37 | socket.close(); 38 | } catch (IOException ignored) { 39 | } 40 | } 41 | } 42 | }).start(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/references/AccessField.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.references; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | import static vanilla.java.references.ShowFields2Main.UNSAFE; 6 | 7 | /** 8 | * Created by peter.lawrey on 23/11/2015. 9 | */ 10 | public class AccessField { 11 | public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { 12 | MyClass mc = new MyClass(); 13 | mc.d = 12345.0; 14 | mc.l = 12345; 15 | 16 | Field d = mc.getClass().getDeclaredField("d"); 17 | d.setAccessible(true); 18 | Field l = mc.getClass().getDeclaredField("l"); 19 | l.setAccessible(true); 20 | 21 | d.set(mc, 2345.0); 22 | System.out.println("d: " + d.get(mc)); 23 | System.out.println("l: " + l.get(mc)); 24 | 25 | long dOff = UNSAFE.objectFieldOffset(d); 26 | long lOff = UNSAFE.objectFieldOffset(l); 27 | System.out.println("l as a long: " + Long.toString(UNSAFE.getLong(mc, lOff))); 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/references/HashcodeMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.references; 2 | 3 | 4 | import static vanilla.java.references.ShowFields2Main.UNSAFE; 5 | 6 | /** 7 | * Created by peter.lawrey on 23/11/2015. 8 | */ 9 | public class HashcodeMain { 10 | public static void main(String[] args) { 11 | Object o = new Object(); 12 | int hc0 = UNSAFE.getInt(o, 1L); 13 | System.out.println(Integer.toHexString(hc0)); 14 | 15 | System.out.println(o); 16 | System.out.println(o); 17 | 18 | int hc = UNSAFE.getInt(o, 1L); 19 | System.out.println(Integer.toHexString(hc)); 20 | 21 | UNSAFE.putInt(o, 1L, 0); 22 | System.out.println(o); 23 | System.out.println(Integer.toHexString(System.identityHashCode(o))); 24 | 25 | String s = "hello"; 26 | System.out.println(s.hashCode()); 27 | System.out.println(System.identityHashCode(s)); 28 | System.out.println(UNSAFE.getInt(s, 1L)); 29 | 30 | /* 31 | String s = "hello"; 32 | String s2 = new String("hello"); 33 | System.out.println(s.hashCode()); 34 | System.out.println(s2.hashCode()); 35 | 36 | UNSAFE.putInt(s, 1L, 1); 37 | UNSAFE.putInt(s2, 1L, 2); 38 | System.out.println(System.identityHashCode(s)); 39 | System.out.println(System.identityHashCode(s2)); 40 | */ 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/references/MyClass.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.references; 2 | 3 | /** 4 | * Created by peter.lawrey on 22/11/2015. 5 | */ 6 | public class MyClass extends OtherClass { 7 | boolean flag; 8 | byte b; 9 | short s; 10 | char c; 11 | int i; 12 | long l; 13 | float f; 14 | double d; 15 | Object o; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/references/ObjectMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.references; 2 | 3 | /** 4 | * Created by peter.lawrey on 23/11/2015. 5 | */ 6 | public class ObjectMain { 7 | public static void main(String[] args) { 8 | Character c = ' '; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/references/ObjectReferencesMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.references; 2 | 3 | import static vanilla.java.references.ShowFields2Main.UNSAFE; 4 | 5 | /** 6 | * Created by peter.lawrey on 23/11/2015. 7 | */ 8 | public class ObjectReferencesMain { 9 | public static void main(String[] args) { 10 | /* 11 | String s = "hello"; 12 | String t = new String("hello"); 13 | String u = t.intern(); 14 | System.out.println(s == t); 15 | System.out.println(s ==u); 16 | 17 | 18 | synchronized ("one") { 19 | 20 | } 21 | */ 22 | Integer[] objs = new Integer[10]; 23 | for (int i = 0; i < objs.length; i++) 24 | objs[i] = Integer.valueOf(i * 25); 25 | 26 | printAddresses(objs); 27 | 28 | System.gc(); 29 | 30 | printAddresses(objs); 31 | 32 | } 33 | 34 | private static void printAddresses(Object[] objs) { 35 | for (int i = 0; i < objs.length; i++) { 36 | int address = UNSAFE.getInt(objs, 37 | UNSAFE.ARRAY_OBJECT_BASE_OFFSET + i * UNSAFE.ARRAY_OBJECT_INDEX_SCALE); 38 | System.out.println(i + " address: " + Integer.toHexString(address)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/references/ObjectSizeMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.references; 2 | 3 | import java.util.BitSet; 4 | 5 | /** 6 | * Created by peter.lawrey on 22/11/2015. 7 | */ 8 | public class ObjectSizeMain { 9 | // https://github.com/peter-lawrey/Performance-Examples.git 10 | 11 | public static void main(String[] args) { 12 | 13 | for (int i = 0; i < 3; i++) { 14 | long used1 = memoryUsed(); 15 | 16 | BitSet flags = new BitSet(1000); 17 | // boolean[] flags = new boolean[1000]; 18 | for (int j = 0; j < 1000; j++) { 19 | flags.set(j, i % 2 == 0); 20 | // flags[i] = i % 2 == 0; 21 | } 22 | 23 | long used2 = memoryUsed(); 24 | if (used1 == used2) 25 | System.err.println("You need to turn off the TLAB with -XX:-UseTLAB"); 26 | else 27 | System.out.printf("Space used by one object is " + (used2 - used1) + " bytes%n"); 28 | } 29 | } 30 | 31 | public static long memoryUsed() { 32 | Runtime rt = Runtime.getRuntime(); 33 | return rt.totalMemory() - rt.freeMemory(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/references/OtherClass.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.references; 2 | 3 | /** 4 | * Created by peter.lawrey on 23/11/2015. 5 | */ 6 | public class OtherClass { 7 | boolean b; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/references/ShowFields2Main.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.references; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.lang.reflect.Field; 6 | import java.util.TreeMap; 7 | import java.util.stream.Collectors; 8 | import java.util.stream.Stream; 9 | 10 | /** 11 | * Created by peter.lawrey on 22/11/2015. 12 | */ 13 | public class ShowFields2Main { 14 | static final Unsafe UNSAFE; 15 | 16 | static { 17 | try { 18 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 19 | theUnsafe.setAccessible(true); 20 | UNSAFE = (Unsafe) theUnsafe.get(null); 21 | } catch (Exception e) { 22 | throw new AssertionError(e); 23 | } 24 | } 25 | 26 | public static void main(String[] args) { 27 | Stream.of(MyClass.class, MyClass.class.getSuperclass()) 28 | .flatMap(c -> Stream.of(c.getDeclaredFields())) 29 | .collect(Collectors.groupingBy(UNSAFE::objectFieldOffset, 30 | TreeMap::new, 31 | Collectors.reducing(null, (n, v) -> v))) 32 | .entrySet() 33 | .forEach(System.out::println); 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/references/ShowFieldsMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.references; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | /** 6 | * Created by peter.lawrey on 22/11/2015. 7 | */ 8 | public class ShowFieldsMain { 9 | public static void main(String... args) { 10 | for (Class c = MyClass.class; c != null; c = c.getSuperclass()) 11 | for (Field field : c.getDeclaredFields()) 12 | System.out.println(field); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/tcp/TextEchoClientMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.tcp; 2 | 3 | import java.io.*; 4 | import java.net.Socket; 5 | import java.nio.charset.StandardCharsets; 6 | import java.util.Arrays; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | /* 10 | * Created by plawrey on 12/14/15. 11 | * Throughput test 12 | * 13 | Throughput test wrote 44.2 MB/s 14 | 15 | Latency test for 100,000 TPS 16 | Latency distribution 50/90 99/99.9 (worst) was 528,477/1,069,998 1,163,770/1,173,065 (1,174,106) micro-seconds 17 | Latency test for 80,000 TPS 18 | Latency distribution 50/90 99/99.9 (worst) was 276,228/498,628 551,875/556,160 (556,636) micro-seconds 19 | Latency test for 60,000 TPS 20 | Latency distribution 50/90 99/99.9 (worst) was 14/22 1,759/3,031 (3,393) micro-seconds 21 | Latency test for 50,000 TPS 22 | Latency distribution 50/90 99/99.9 (worst) was 14/21 4,388/5,518 (5,641) micro-seconds 23 | Latency test for 40,000 TPS 24 | Latency distribution 50/90 99/99.9 (worst) was 14/15 22/485 (2,071) micro-seconds 25 | Latency test for 30,000 TPS 26 | Latency distribution 50/90 99/99.9 (worst) was 14/15 21/921 (3,360) micro-seconds 27 | Latency test for 20,000 TPS 28 | Latency distribution 50/90 99/99.9 (worst) was 15/19 24/46 (656) micro-seconds 29 | */ 30 | public class TextEchoClientMain { 31 | static final String HOST = System.getProperty("host", "localhost"); 32 | static final int PORT = Integer.getInteger("port", 65432); 33 | 34 | public static void main(String[] args) throws IOException { 35 | Socket s = new Socket(HOST, PORT); 36 | 37 | try (BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), StandardCharsets.UTF_8)); 38 | PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream(), StandardCharsets.UTF_8), true)) { 39 | 40 | 41 | System.out.println("Throughput test"); 42 | char[] chars = new char[1000]; 43 | Arrays.fill(chars, '*'); 44 | String text = new String(chars); 45 | long start = System.currentTimeMillis(); 46 | int count = 0; 47 | while (System.currentTimeMillis() < start + TimeUnit.SECONDS.toMillis(5)) { 48 | pw.println(text); 49 | br.readLine(); 50 | count++; 51 | } 52 | long time = System.currentTimeMillis() - start; 53 | System.out.printf("Throughput test wrote %.1f MB/s%n%n", (double) count / time); 54 | 55 | int warmup = 1000000; 56 | for (int rate : new int[]{warmup, 100000, 80000, 60000, 50000, 40000, 30000, 20000}) { 57 | if (rate != warmup) 58 | System.out.printf("Latency test for %,d TPS%n", rate); 59 | long[] times = new long[200000]; 60 | long start2 = System.nanoTime(); 61 | long spacing = (long) (1e9 / rate); 62 | long next = start2 + spacing; 63 | String smallText = "Hello World"; 64 | 65 | for (int i = 0; i < times.length; i++) { 66 | while (System.nanoTime() < next) ; 67 | // take timing from when it should have sent the message, not when it did 68 | long start3 = next; // System.nanoTime(); 69 | pw.println(smallText); 70 | br.readLine(); 71 | long time3 = System.nanoTime() - start3; 72 | times[i] = time3; 73 | next += spacing; 74 | } 75 | Arrays.sort(times); 76 | if (rate != warmup) 77 | System.out.printf("Latency distribution 50/90 99/99.9 (worst) was %,d/%,d %,d/%,d (%,d) micro-seconds%n", 78 | times[times.length / 2] / 1000, 79 | times[times.length * 9 / 10] / 1000, 80 | times[times.length * 99 / 100] / 1000, 81 | times[times.length * 999 / 1000] / 1000, 82 | times[times.length - 1] / 1000 83 | ); 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/tcp/TextEchoServerMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.tcp; 2 | 3 | import java.io.*; 4 | import java.net.ServerSocket; 5 | import java.net.Socket; 6 | import java.nio.charset.StandardCharsets; 7 | 8 | /** 9 | * Created by plawrey on 12/14/15. 10 | */ 11 | public class TextEchoServerMain { 12 | static final int PORT = Integer.getInteger("port", 65432); 13 | 14 | public static void main(String[] args) throws IOException { 15 | ServerSocket ss = new ServerSocket(PORT); 16 | while (true) { 17 | Socket s = ss.accept(); 18 | new Thread(() -> { 19 | System.out.println("Accepted " + s); 20 | try { 21 | try (BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), StandardCharsets.UTF_8)); 22 | PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream(), StandardCharsets.UTF_8), true)) { 23 | for (String line; (line = br.readLine()) != null; ) 24 | handle(line, pw); 25 | } 26 | } catch (IOException e) { 27 | e.printStackTrace(); 28 | } finally { 29 | System.out.println("... " + s + " closed"); 30 | } 31 | }).start(); 32 | } 33 | } 34 | 35 | static void handle(String line, PrintWriter pw) { 36 | pw.println(line); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/CAS2PingPongMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | import java.util.concurrent.atomic.AtomicBoolean; 6 | import java.util.concurrent.atomic.AtomicLong; 7 | 8 | /** 9 | * Created by peter.lawrey on 12/01/2016. 10 | */ 11 | public class CAS2PingPongMain { 12 | final AtomicBoolean toggle = new AtomicBoolean(); 13 | final AtomicLong count1 = new AtomicLong(); 14 | final AtomicLong count2 = new AtomicLong(); 15 | byte[] bytes1 = new byte[64]; 16 | byte[] bytes2 = new byte[64]; 17 | 18 | public static void main(String... args) throws InterruptedException { 19 | CAS2PingPongMain ppm = new CAS2PingPongMain(); 20 | 21 | Thread t1 = ppm.createThread(true, ppm.count1); 22 | Thread t2 = ppm.createThread(false, ppm.count2); 23 | long start = System.currentTimeMillis(); 24 | Thread.sleep(5000); 25 | t1.interrupt(); 26 | t2.interrupt(); 27 | long time = System.currentTimeMillis() - start; 28 | t1.join(); 29 | t2.join(); 30 | System.out.printf("Counted to %,d toggles per second.%n", 31 | (ppm.count1.get() + ppm.count2.get()) * 1000 / time); 32 | } 33 | 34 | @NotNull 35 | Thread createThread(boolean flag, AtomicLong count) { 36 | Thread thread = new Thread(() -> runLoop(flag, count), "toggle-" + flag); 37 | thread.start(); 38 | return thread; 39 | } 40 | 41 | void runLoop(boolean flag, AtomicLong count) { 42 | while (!Thread.currentThread().isInterrupted()) { 43 | if (toggle.compareAndSet(!flag, flag)) { 44 | // count.getAndUpdate(l -> (l + 1) % 24); 45 | count.incrementAndGet(); 46 | } 47 | } 48 | System.out.println(flag + " - finished"); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/CASPingPongMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | import java.util.concurrent.atomic.AtomicBoolean; 6 | import java.util.concurrent.atomic.AtomicLong; 7 | 8 | /** 9 | * Created by peter.lawrey on 12/01/2016. 10 | */ 11 | public class CASPingPongMain { 12 | final AtomicBoolean toggle = new AtomicBoolean(); 13 | final AtomicLong count = new AtomicLong(); 14 | 15 | public static void main(String... args) throws InterruptedException { 16 | CASPingPongMain ppm = new CASPingPongMain(); 17 | 18 | Thread t1 = ppm.createThread(true); 19 | Thread t2 = ppm.createThread(false); 20 | long start = System.currentTimeMillis(); 21 | Thread.sleep(5000); 22 | t1.interrupt(); 23 | t2.interrupt(); 24 | long time = System.currentTimeMillis() - start; 25 | t1.join(); 26 | t2.join(); 27 | System.out.printf("Counted to %,d toggles per second.%n", ppm.count.get() * 1000 / time); 28 | } 29 | 30 | @NotNull 31 | Thread createThread(boolean flag) { 32 | Thread thread = new Thread(() -> runLoop(flag), "toggle-" + flag); 33 | thread.start(); 34 | return thread; 35 | } 36 | 37 | void runLoop(boolean flag) { 38 | while (!Thread.currentThread().isInterrupted()) { 39 | if (toggle.compareAndSet(!flag, flag)) { 40 | // count.getAndUpdate(l -> (l + 1) % 24); 41 | count.incrementAndGet(); 42 | } 43 | } 44 | System.out.println(flag + " - finished"); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/ChronicleBytesCASPingPongMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | import net.openhft.chronicle.bytes.Bytes; 4 | import net.openhft.chronicle.bytes.MappedBytes; 5 | import net.openhft.chronicle.core.OS; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | import java.io.IOException; 9 | 10 | /** 11 | * Created by peter.lawrey on 12/01/2016. 12 | */ 13 | public class ChronicleBytesCASPingPongMain { 14 | static final int SIZE = 16; 15 | static final int COUNTER_OFFSET = 0; 16 | static final int TOGGLE_OFFSET = SIZE - 8; 17 | 18 | final Bytes bytes; 19 | 20 | public ChronicleBytesCASPingPongMain() throws IOException { 21 | bytes = MappedBytes.mappedBytes("deleteme", OS.pageSize()); 22 | 23 | bytes.writeLong(COUNTER_OFFSET, 0L); 24 | bytes.writeInt(TOGGLE_OFFSET, 0); 25 | } 26 | 27 | public static void main(String... args) throws InterruptedException, IOException { 28 | ChronicleBytesCASPingPongMain ppm = new ChronicleBytesCASPingPongMain(); 29 | boolean flag = Boolean.parseBoolean(args[0]); 30 | for (int i = 0; i < 10; ) 31 | if (ppm.toggleCompareAndSet(!flag, flag)) 32 | i++; 33 | System.out.println("toggling"); 34 | 35 | Thread t1 = ppm.createThread(flag); 36 | 37 | long start = System.currentTimeMillis(); 38 | Thread.sleep(5000); 39 | t1.interrupt(); 40 | long time = System.currentTimeMillis() - start; 41 | t1.join(); 42 | System.out.printf("Counted to %,d toggles per second. %n", ppm.getCount() * 1000 / time); 43 | } 44 | 45 | @NotNull 46 | Thread createThread(boolean flag) { 47 | Thread thread = new Thread(() -> runLoop(flag), "toggle-" + flag); 48 | thread.start(); 49 | return thread; 50 | } 51 | 52 | void runLoop(boolean flag) { 53 | while (!Thread.currentThread().isInterrupted()) { 54 | if (toggleCompareAndSet(!flag, flag)) 55 | countIncrement(); 56 | } 57 | System.out.println(flag + " - finished"); 58 | } 59 | 60 | public boolean toggleCompareAndSet(boolean from, boolean to) { 61 | return bytes.compareAndSwapInt(TOGGLE_OFFSET, from ? 1 : 0, to ? 1 : 0); 62 | } 63 | 64 | public void countIncrement() { 65 | bytes.addAndGetInt(COUNTER_OFFSET, 1); 66 | } 67 | 68 | public long getCount() { 69 | return bytes.readVolatileLong(COUNTER_OFFSET); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/EncapsulationMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | /** 4 | * Created by peter.lawrey on 12/01/2016. 5 | */ 6 | public class EncapsulationMain { 7 | private final String name; 8 | private final int activeCount; 9 | 10 | public EncapsulationMain(String name, int activeCount) { 11 | this.name = name; 12 | this.activeCount = activeCount; 13 | } 14 | 15 | public static void main(String[] args) { 16 | new EncapsulationMain("Hello", 1).run(); 17 | } 18 | 19 | public void run() { 20 | new Thread(() -> 21 | System.out.println("name: " + getName() + " count: " + activeCount()) 22 | ).start(); 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public int activeCount() { 30 | return activeCount; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/ExecutorServiceMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by peter.lawrey on 26/11/2015. 8 | */ 9 | public class ExecutorServiceMain { 10 | public static void main(String[] args) throws InterruptedException { 11 | long start = System.currentTimeMillis(); 12 | // int procs = Runtime.getRuntime().availableProcessors(); 13 | // ExecutorService es = Executors.newCachedThreadPool(); 14 | List list = new ArrayList<>(); 15 | for (int i = 1; i <= 10000; i++) { 16 | Thread t = new Thread(() -> { 17 | try { 18 | Thread.sleep(1); 19 | } catch (InterruptedException e) { 20 | e.printStackTrace(); 21 | } 22 | }); 23 | t.start(); 24 | list.add(t); 25 | } 26 | for (Thread thread : list) { 27 | thread.join(); 28 | } 29 | System.out.println("sent"); 30 | // es.shutdown(); 31 | // es.awaitTermination(10, TimeUnit.SECONDS); 32 | long time = System.currentTimeMillis() - start; 33 | System.out.printf("Time taken %.3f seconds%n", time / 1e3); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/LockConditionPingPongMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | import java.util.concurrent.locks.Condition; 6 | import java.util.concurrent.locks.ReentrantLock; 7 | 8 | /** 9 | * Created by peter.lawrey on 12/01/2016. 10 | */ 11 | public class LockConditionPingPongMain { 12 | final ReentrantLock lock = new ReentrantLock(); 13 | final Condition condition = lock.newCondition(); 14 | 15 | boolean toggle = false; 16 | long count = 0; 17 | 18 | public static void main(String... args) throws InterruptedException { 19 | LockConditionPingPongMain ppm = new LockConditionPingPongMain(); 20 | 21 | Thread t1 = ppm.createThread(true); 22 | Thread t2 = ppm.createThread(false); 23 | long start = System.currentTimeMillis(); 24 | Thread.sleep(5000); 25 | t1.interrupt(); 26 | t2.interrupt(); 27 | long time = System.currentTimeMillis() - start; 28 | t1.join(); 29 | t2.join(); 30 | System.out.println("Counted to " + ppm.count * 1000 / time + " toggles per second."); 31 | } 32 | 33 | @NotNull 34 | Thread createThread(boolean flag) { 35 | Thread thread = new Thread(() -> runLoop(flag), "toggle-" + flag); 36 | thread.start(); 37 | return thread; 38 | } 39 | 40 | void runLoop(boolean flag) { 41 | // Thread.currentThread().setName("toggle-"+flag); 42 | lock.lock(); 43 | try { 44 | while (!Thread.currentThread().isInterrupted()) { 45 | while (toggle == flag) { 46 | condition.await(); 47 | } 48 | toggle = flag; 49 | count++; 50 | condition.signalAll(); 51 | } 52 | } catch (InterruptedException e) { 53 | } finally { 54 | lock.unlock(); 55 | System.out.println(flag + " - finished"); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/NativeCASPingPongMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | import sun.misc.Unsafe; 5 | 6 | import java.lang.reflect.Field; 7 | 8 | /** 9 | * Created by peter.lawrey on 12/01/2016. 10 | */ 11 | public class NativeCASPingPongMain { 12 | static final int SIZE = 16; 13 | static final int COUNTER_OFFSET = 0; 14 | static final int TOGGLE_OFFSET = SIZE - 8; 15 | 16 | static final Unsafe UNSAFE; 17 | 18 | static { 19 | try { 20 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 21 | theUnsafe.setAccessible(true); 22 | UNSAFE = (Unsafe) theUnsafe.get(null); 23 | } catch (Exception e) { 24 | throw new AssertionError(e); 25 | } 26 | } 27 | 28 | final long address; 29 | 30 | public NativeCASPingPongMain() { 31 | address = UNSAFE.allocateMemory(SIZE); 32 | UNSAFE.putLong(address + COUNTER_OFFSET, 0L); 33 | UNSAFE.putInt(address + TOGGLE_OFFSET, 0); 34 | } 35 | 36 | public static void main(String... args) throws InterruptedException { 37 | NativeCASPingPongMain ppm = new NativeCASPingPongMain(); 38 | 39 | Thread t1 = ppm.createThread(true); 40 | Thread t2 = ppm.createThread(false); 41 | long start = System.currentTimeMillis(); 42 | Thread.sleep(5000); 43 | t1.interrupt(); 44 | t2.interrupt(); 45 | long time = System.currentTimeMillis() - start; 46 | t1.join(); 47 | t2.join(); 48 | System.out.printf("Counted to %,d toggles per second.%n", ppm.getCount() * 1000 / time); 49 | } 50 | 51 | @NotNull 52 | Thread createThread(boolean flag) { 53 | Thread thread = new Thread(() -> runLoop(flag), "toggle-" + flag); 54 | thread.start(); 55 | return thread; 56 | } 57 | 58 | void runLoop(boolean flag) { 59 | while (!Thread.currentThread().isInterrupted()) { 60 | if (toggleCompareAndSet(!flag, flag)) 61 | countIncrement(); 62 | } 63 | System.out.println(flag + " - finished"); 64 | } 65 | 66 | public boolean toggleCompareAndSet(boolean from, boolean to) { 67 | return UNSAFE.compareAndSwapInt(null, address + TOGGLE_OFFSET, from ? 1 : 0, to ? 1 : 0); 68 | } 69 | 70 | public void countIncrement() { 71 | UNSAFE.getAndAddLong(null, address + COUNTER_OFFSET, 1); 72 | } 73 | 74 | public long getCount() { 75 | return UNSAFE.getLongVolatile(null, address + COUNTER_OFFSET); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/PrimeNumbersMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.ExecutionException; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | import java.util.concurrent.Future; 9 | 10 | /** 11 | * Created by peter.lawrey on 26/11/2015. 12 | */ 13 | public class PrimeNumbersMain { 14 | public static void main(String[] args) throws ExecutionException, InterruptedException { 15 | long start = System.currentTimeMillis(); 16 | List primes = new ArrayList<>(); 17 | 18 | int procs = Runtime.getRuntime().availableProcessors(); 19 | ExecutorService es = Executors.newFixedThreadPool(procs); 20 | List> futures = new ArrayList<>(); 21 | for (int i = 2; i <= 10_000_000; i++) { //////// 22 | final int finalI = i; 23 | futures.add(es.submit(() -> { 24 | if (isPrime(finalI)) //////// 25 | return finalI; //////// 26 | return null; 27 | })); 28 | } 29 | for (Future future : futures) { 30 | Integer i = future.get(); 31 | if (i != null) 32 | primes.add(i); //////// 33 | } 34 | es.shutdown(); 35 | 36 | long time = System.currentTimeMillis() - start; 37 | System.out.printf("Took %.3f seconds%n", time / 1e3); 38 | System.out.println("Primes= " + primes.size()); 39 | } 40 | 41 | private static boolean isPrime(int i) { 42 | if ((i & 1) == 0) 43 | return false; 44 | for (int j = 3; j <= (int) Math.sqrt(i); j += 2) 45 | if (i % j == 0) 46 | return false; 47 | return true; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/PrimeNumbersStreamsMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | import java.util.concurrent.ExecutionException; 4 | import java.util.stream.IntStream; 5 | 6 | /** 7 | * Created by peter.lawrey on 26/11/2015. 8 | */ 9 | public class PrimeNumbersStreamsMain { 10 | 11 | public static void main(String[] args) throws ExecutionException, InterruptedException { 12 | long start = System.currentTimeMillis(); 13 | long primes = 14 | IntStream.rangeClosed(2, 500_000_000) 15 | .parallel() 16 | .filter(i -> isPrime(i)) 17 | .count(); 18 | 19 | long time = System.currentTimeMillis() - start; 20 | System.out.printf("Took %.3f seconds%n", time / 1e3); 21 | System.out.println("Primes= " + primes); 22 | } 23 | 24 | static boolean isPrime(int i) { 25 | if ((i & 1) == 0) 26 | return false; 27 | for (int j = 3; j <= (int) Math.sqrt(i); j += 2) 28 | if (i % j == 0) 29 | return false; 30 | return true; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/PrimesMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | /** 6 | * Created by peter.lawrey on 12/01/2016. 7 | */ 8 | public class PrimesMain { 9 | public static void main(String[] args) { 10 | for (int t = 0; t < 7; t++) { 11 | long start = System.currentTimeMillis(); 12 | int[] ints = IntStream.range(2, 1000000) 13 | .parallel() 14 | .filter(i -> i == 2 || (i & 1) != 0) 15 | .filter(i -> { 16 | int max = (int) Math.sqrt(i); 17 | return IntStream.range(3 / 2, (max - 1) / 2) 18 | // .parallel() 19 | .noneMatch(j -> i % (j * 2 + 1) == 0); 20 | }) 21 | .toArray(); 22 | long time = System.currentTimeMillis() - start; 23 | System.out.printf("Took %.3f seconds%n", time / 1e3); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/PrintingThreadPoolMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | /** 6 | * Created by peter.lawrey on 12/01/2016. 7 | */ 8 | public class PrintingThreadPoolMain { 9 | public static void main(String[] args) throws InterruptedException { 10 | for (int t = 0; t < 10; t++) { 11 | long start = System.currentTimeMillis(); 12 | IntStream.range(0, 1000) 13 | .forEach(System.out::println); 14 | long time = System.currentTimeMillis() - start; 15 | 16 | long start2 = System.currentTimeMillis(); 17 | for (int i = 0; i < 1000; i++) { 18 | System.out.println(i); 19 | } 20 | long time2 = System.currentTimeMillis() - start2; 21 | System.out.println("Multi-threaded time taken was " + time / 1e3 + " seconds"); 22 | System.out.println("Single threaded time taken was " + time2 / 1e3 + " seconds"); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/RequiresVolatileMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | public class RequiresVolatileMain { 4 | static volatile boolean value; 5 | 6 | public static void main(String... args) { 7 | new Thread(new MyRunnable(true), "Sets true").start(); 8 | new Thread(new MyRunnable(false), "Sets false").start(); 9 | new Thread(new MyValueMonitor()).start(); 10 | } 11 | 12 | private static class MyRunnable implements Runnable { 13 | private final boolean target; 14 | 15 | private MyRunnable(boolean target) { 16 | this.target = target; 17 | } 18 | 19 | @Override 20 | public void run() { 21 | while (true) { 22 | if (value != target) { 23 | value = target; 24 | } 25 | } 26 | } 27 | } 28 | 29 | static class MyValueMonitor implements Runnable { 30 | @Override 31 | public void run() { 32 | try { 33 | while (true) { 34 | Thread.sleep(100); 35 | System.out.println("value=" + value); 36 | } 37 | } catch (InterruptedException e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/ReverseFilterMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | /** 6 | * Created by peter.lawrey on 13/01/2016. 7 | */ 8 | public class ReverseFilterMain { 9 | public static void main(String[] args) { 10 | for (int t = 0; t < 5; t++) { 11 | long start = System.currentTimeMillis(); 12 | ThreadLocal sbtl = ThreadLocal.withInitial(StringBuilder::new); 13 | long count = IntStream.range(1, 100_000_000).parallel() 14 | .filter(i -> { 15 | StringBuilder sb = sbtl.get(); 16 | sb.setLength(0); 17 | sb.append(i).reverse(); 18 | return sb.indexOf("128") >= 0; 19 | }).count(); 20 | long time = System.currentTimeMillis() - start; 21 | System.out.printf("Took %.3f seconds to find %,d numbers%n", time / 1e3, count); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/SharedCASPingPongMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | import net.openhft.chronicle.core.OS; 4 | import org.jetbrains.annotations.NotNull; 5 | import sun.misc.Unsafe; 6 | import sun.nio.ch.DirectBuffer; 7 | 8 | import java.io.IOException; 9 | import java.io.RandomAccessFile; 10 | import java.lang.reflect.Field; 11 | import java.nio.MappedByteBuffer; 12 | import java.nio.channels.FileChannel; 13 | 14 | /** 15 | * Created by peter.lawrey on 12/01/2016. 16 | */ 17 | public class SharedCASPingPongMain { 18 | static final int SIZE = 16; 19 | static final int COUNTER_OFFSET = 0; 20 | static final int TOGGLE_OFFSET = SIZE - 8; 21 | 22 | static final Unsafe UNSAFE; 23 | 24 | static { 25 | try { 26 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 27 | theUnsafe.setAccessible(true); 28 | UNSAFE = (Unsafe) theUnsafe.get(null); 29 | } catch (Exception e) { 30 | throw new AssertionError(e); 31 | } 32 | } 33 | 34 | final long address; 35 | 36 | public SharedCASPingPongMain() throws IOException { 37 | RandomAccessFile raf = new RandomAccessFile("deleteme", "rw"); 38 | MappedByteBuffer map = raf.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, OS.pageSize()); 39 | address = ((DirectBuffer) map).address(); 40 | UNSAFE.putLong(address + COUNTER_OFFSET, 0L); 41 | UNSAFE.putInt(address + TOGGLE_OFFSET, 0); 42 | } 43 | 44 | public static void main(String... args) throws InterruptedException, IOException { 45 | SharedCASPingPongMain ppm = new SharedCASPingPongMain(); 46 | boolean flag = Boolean.parseBoolean(args[0]); 47 | for (int i = 0; i < 10; ) 48 | if (ppm.toggleCompareAndSet(!flag, flag)) 49 | i++; 50 | System.out.println("toggling"); 51 | 52 | Thread t1 = ppm.createThread(flag); 53 | long start = System.currentTimeMillis(); 54 | Thread.sleep(5000); 55 | t1.interrupt(); 56 | long time = System.currentTimeMillis() - start; 57 | t1.join(); 58 | System.out.printf("Counted to %,d toggles per second. %n", ppm.getCount() * 1000 / time); 59 | } 60 | 61 | @NotNull 62 | Thread createThread(boolean flag) { 63 | Thread thread = new Thread(() -> runLoop(flag), "toggle-" + flag); 64 | thread.start(); 65 | return thread; 66 | } 67 | 68 | void runLoop(boolean flag) { 69 | while (!Thread.currentThread().isInterrupted()) { 70 | if (toggleCompareAndSet(!flag, flag)) 71 | countIncrement(); 72 | } 73 | System.out.println(flag + " - finished"); 74 | } 75 | 76 | public boolean toggleCompareAndSet(boolean from, boolean to) { 77 | return UNSAFE.compareAndSwapInt(null, address + TOGGLE_OFFSET, from ? 1 : 0, to ? 1 : 0); 78 | } 79 | 80 | public void countIncrement() { 81 | UNSAFE.getAndAddLong(null, address + COUNTER_OFFSET, 1); 82 | } 83 | 84 | public long getCount() { 85 | return UNSAFE.getLongVolatile(null, address + COUNTER_OFFSET); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/SqrtMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | public class SqrtMain { 6 | 7 | public static void main(String[] args) { 8 | int procs = Runtime.getRuntime().availableProcessors(); 9 | System.out.println("Procs: " + procs); 10 | long start = System.nanoTime(); 11 | double sum = IntStream.range(0, (int) 300e6) 12 | .parallel() 13 | .mapToDouble(Math::sqrt) 14 | .sum(); 15 | long time = System.nanoTime() - start; 16 | System.out.printf("Took %.3f seconds%n", time / 1e9); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/threads/WaitNotifyPingPongMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.threads; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | /** 6 | * Created by peter.lawrey on 12/01/2016. 7 | */ 8 | public class WaitNotifyPingPongMain { 9 | boolean toggle = false; 10 | long count = 0; 11 | 12 | public static void main(String... args) throws InterruptedException { 13 | WaitNotifyPingPongMain wnppm = new WaitNotifyPingPongMain(); 14 | 15 | Thread t1 = wnppm.createThread(true); 16 | Thread t2 = wnppm.createThread(false); 17 | long start = System.currentTimeMillis(); 18 | Thread.sleep(5000); 19 | t1.interrupt(); 20 | t2.interrupt(); 21 | long time = System.currentTimeMillis() - start; 22 | t1.join(); 23 | t2.join(); 24 | System.out.printf("Counted to %,d toggles per second.%n", wnppm.count * 1000 / time); 25 | } 26 | 27 | @NotNull 28 | Thread createThread(boolean flag) { 29 | Thread thread = new Thread(() -> runLoop(flag), "toggle-" + flag); 30 | thread.start(); 31 | return thread; 32 | } 33 | 34 | synchronized void runLoop(boolean flag) { 35 | try { 36 | while (!Thread.currentThread().isInterrupted()) { 37 | while (toggle == flag) { 38 | wait(10); 39 | } 40 | toggle = flag; 41 | count++; 42 | notifyAll(); 43 | } 44 | } catch (InterruptedException ignore) { 45 | } finally { 46 | System.out.println(flag + " - finished"); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/AccessRawMemoryMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | /** 8 | * Created by peter on 02/04/16. 9 | */ 10 | public class AccessRawMemoryMain { 11 | // This only works if a GC doesn't move the object while attempting to access it. 12 | static final Unsafe UNSAFE; 13 | 14 | static { 15 | try { 16 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 17 | theUnsafe.setAccessible(true); 18 | UNSAFE = (Unsafe) theUnsafe.get(null); 19 | } catch (Exception e) { 20 | throw new AssertionError(e); 21 | } 22 | } 23 | 24 | // must be run with -XX:-UseCompressedOops 25 | // run with: -ea 26 | public static void main(String[] args) { 27 | Object i = 0x12345678; 28 | 29 | Object[] obj = {i}; 30 | assert Unsafe.ARRAY_OBJECT_INDEX_SCALE == 8; // 8 bytes per reference. 31 | long address = UNSAFE.getLong(obj, (long) Unsafe.ARRAY_OBJECT_BASE_OFFSET); 32 | System.out.printf("%x%n", address); 33 | for (int j = 0; j < 24; j++) 34 | System.out.printf("%02x ", UNSAFE.getByte(address + j) & 0xFF); 35 | System.out.println(); 36 | 37 | System.out.printf("`i` is a %s and is %x%n", i.getClass(), i); 38 | 39 | // now some really scary sh!t 40 | long longClassPointer = UNSAFE.getLong(0L, 8L); 41 | UNSAFE.putLong(i, 8L, longClassPointer); 42 | System.out.printf("`i` is now a %s and is %x%n", i.getClass(), i); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/ByteBufferMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | import java.io.IOException; 4 | import java.io.RandomAccessFile; 5 | import java.nio.MappedByteBuffer; 6 | import java.nio.channels.FileChannel; 7 | 8 | public class ByteBufferMain { 9 | public static void main(String... ignored) throws IOException { 10 | String name = "/tmp/deleteme"; 11 | FileChannel fc = new RandomAccessFile(name, "rw").getChannel(); 12 | MappedByteBuffer map = fc.map(FileChannel.MapMode.READ_WRITE, 0, 1 << 30); 13 | // map.putLong(0, 0x123456789ABCDEFL); 14 | long value = map.getLong(0); 15 | System.out.printf("Using 1 GB value= %x%n", value); 16 | for (; ; ) { 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/DirectByteBufferMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | import sun.nio.ch.DirectBuffer; 4 | 5 | import java.io.IOException; 6 | import java.io.RandomAccessFile; 7 | import java.nio.ByteBuffer; 8 | import java.nio.ByteOrder; 9 | import java.nio.channels.FileChannel; 10 | 11 | /** 12 | * Created by peter_2 on 26/11/2014. 13 | */ 14 | public class DirectByteBufferMain { 15 | public static void main(String[] args) throws IOException { 16 | // ByteBuffer bb = ByteBuffer.allocateDirect(1 << 30).order(ByteOrder.nativeOrder()); 17 | RandomAccessFile raf = new RandomAccessFile("deleteme", "rw"); 18 | ByteBuffer bb = raf.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 1 << 20).order(ByteOrder.nativeOrder()); 19 | 20 | long address = ((DirectBuffer) bb).address(); 21 | System.out.printf("address: %x%n", address); 22 | long l = UnsafeDemo.UNSAFE.getLong(address); 23 | System.out.printf("value was : %x%n", l); 24 | UnsafeDemo.UNSAFE.putLong(address, l + 0x101); 25 | UnsafeDemo.UNSAFE.getLong(0L); 26 | 27 | System.out.printf("value written: %x%n", bb.getLong(0)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/FasterHashCodePref.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | /** 8 | * Created by peter.lawrey on 07/02/2016. 9 | */ 10 | /* 11 | Object.hashCode takes 5 ns on average 12 | Object.hashCode takes 8 ns on average 13 | Object.hashCode takes 5 ns on average 14 | Object.hashCode takes 4 ns on average 15 | Object.hashCode takes 4 ns on average 16 | */ 17 | public class FasterHashCodePref { 18 | static final Unsafe UNSAFE; 19 | static int keep, keep2; 20 | static int counter; 21 | 22 | static { 23 | try { 24 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 25 | theUnsafe.setAccessible(true); 26 | UNSAFE = (Unsafe) theUnsafe.get(null); 27 | } catch (Exception e) { 28 | throw new AssertionError(e); 29 | } 30 | } 31 | 32 | public static void main(String[] args) { 33 | Object o = new Object(); 34 | Object o2 = new Object(); 35 | int runs = 100_000_000; 36 | for (int t = 0; t < 5; t++) { 37 | long start = System.nanoTime(); 38 | for (int i = 0; i < runs; i += 2) { 39 | UNSAFE.putOrderedInt(o, 1L, (counter += 0x5bc80bad) & 0x7FFFFFFF); 40 | UNSAFE.putOrderedInt(o2, 1L, (counter += 0x5bc80bad) & 0x7FFFFFFF); 41 | keep = o.hashCode(); // reload the hashCode 42 | keep2 = o2.hashCode(); // reload the hashCode 43 | } 44 | long time = System.nanoTime() - start; 45 | System.out.printf("Object.hashCode takes %,d ns on average%n", time / runs); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/HashCodePerf.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | /** 8 | * Created by peter.lawrey on 07/02/2016. 9 | */ 10 | /* 11 | Object.hashCode takes 80 ns on average 12 | Object.hashCode takes 42 ns on average 13 | Object.hashCode takes 42 ns on average 14 | Object.hashCode takes 43 ns on average 15 | Object.hashCode takes 45 ns on average 16 | */ 17 | public class HashCodePerf { 18 | static final Unsafe UNSAFE; 19 | static int keep; 20 | 21 | static { 22 | try { 23 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 24 | theUnsafe.setAccessible(true); 25 | UNSAFE = (Unsafe) theUnsafe.get(null); 26 | } catch (Exception e) { 27 | throw new AssertionError(e); 28 | } 29 | } 30 | 31 | public static void main(String[] args) { 32 | Object o = new Object(); 33 | int runs = 20_000_000; 34 | for (int t = 0; t < 5; t++) { 35 | long start = System.nanoTime(); 36 | for (int i = 0; i < runs; i++) { 37 | UNSAFE.putInt(o, 1L, 0); 38 | keep = o.hashCode(); // recompute the hashCode 39 | } 40 | long time = System.nanoTime() - start; 41 | System.out.printf("Object.hashCode takes %,d ns on average%n", time / runs); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/MemoryMappingMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | import net.openhft.lang.io.DirectBytes; 4 | import net.openhft.lang.io.MappedStore; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.nio.channels.FileChannel; 9 | 10 | public class MemoryMappingMain { 11 | public static void main(String... ignored) throws IOException { 12 | // this example only works on Linux 13 | File file = new File("/tmp/shared"); 14 | MappedStore ms = new MappedStore(file, FileChannel.MapMode.READ_WRITE, 64L << 40); 15 | DirectBytes bytes = ms.bytes(); 16 | // bytes.writeLong(0L, 1234); 17 | System.out.println("value=" + bytes.readLong(0L)); 18 | long end = System.currentTimeMillis() + 30 * 1000; 19 | while (end > System.currentTimeMillis()) ; 20 | ms.free(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/MyType.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | /** 4 | * Created by peter on 16/09/2016. 5 | */ 6 | class MyType { 7 | String s; 8 | int num; 9 | long time; 10 | double d; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/OSResizesMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Higher Frequency Trading 3 | * 4 | * http://www.higherfrequencytrading.com 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package vanilla.java.unsafe; 20 | 21 | import net.openhft.chronicle.map.ChronicleMap; 22 | import net.openhft.chronicle.map.ChronicleMapBuilder; 23 | import net.openhft.lang.Jvm; 24 | 25 | import java.io.File; 26 | import java.io.IOException; 27 | import java.io.InputStreamReader; 28 | import java.io.StringWriter; 29 | import java.util.Arrays; 30 | 31 | /** 32 | * This example shows that the OS resizes the usage of a CHM as needed. It is not as critical to worry about this. 33 | *

34 | * System memory: 7.7 GB, Extents of map: 2199.0 GB, disk used: 13MB, addressRange: 7d380b7bd000-7f380c000000 35 | *

36 | */ 37 | public class OSResizesMain { 38 | public static void main(String[] args) throws IOException, InterruptedException { 39 | File file = File.createTempFile("over-sized", "deleteme"); 40 | ChronicleMap map = ChronicleMapBuilder.of(String.class, String.class) 41 | .averageValueSize(50 * 1024 * 1024) 42 | .entries(1000 * 1000) 43 | .createPersistedTo(file); 44 | for (int i = 0; i < 10000; i++) { 45 | char[] chars = new char[i]; 46 | Arrays.fill(chars, '+'); 47 | map.put("key-" + i, new String(chars)); 48 | } 49 | long start = System.currentTimeMillis(); 50 | System.gc(); 51 | long time0 = System.currentTimeMillis() - start; 52 | System.out.printf("GC time: %,d ms%n", time0); 53 | System.out.printf("System memory: %.1f GB, Extents of map: %.1f GB, disk used: %sB, addressRange: %s%n", 54 | Double.parseDouble(run("head", "-1", "/proc/meminfo").split("\\s+")[1]) / 1e6, 55 | file.length() / 1e9, 56 | run("du", "-h", file.getAbsolutePath()).split("\\s")[0], 57 | run("grep", "over-sized", "/proc/" + Jvm.getProcessId() + "/maps").split("\\s")[0]); 58 | // show up in top. 59 | long time = System.currentTimeMillis(); 60 | while (time + 30000 > System.currentTimeMillis()) 61 | Thread.yield(); 62 | map.close(); 63 | file.delete(); 64 | } 65 | 66 | static String run(String... cmd) throws IOException, InterruptedException { 67 | ProcessBuilder pb = new ProcessBuilder(cmd); 68 | pb.redirectErrorStream(true); 69 | Process p = pb.start(); 70 | InputStreamReader reader = new InputStreamReader(p.getInputStream()); 71 | StringWriter sw = new StringWriter(); 72 | char[] chars = new char[512]; 73 | for (int len; (len = reader.read(chars)) > 0; ) 74 | sw.write(chars, 0, len); 75 | int exitValue = p.waitFor(); 76 | if (exitValue != 0) 77 | sw.write("\nexit=" + exitValue); 78 | p.destroy(); 79 | return sw.toString(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/PingPongMain.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | import sun.nio.ch.DirectBuffer; 4 | 5 | import java.io.IOException; 6 | import java.io.RandomAccessFile; 7 | import java.nio.ByteBuffer; 8 | import java.nio.ByteOrder; 9 | import java.nio.channels.FileChannel; 10 | 11 | /** 12 | * Created by peter on 16/09/2016. 13 | */ 14 | public class PingPongMain { 15 | public static void main(String[] args) throws IOException { 16 | RandomAccessFile raf = new RandomAccessFile("deleteme.too", "rw"); 17 | ByteBuffer bb = raf.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 1 << 20).order(ByteOrder.nativeOrder()); 18 | long address = ((DirectBuffer) bb).address(); 19 | 20 | boolean odd = args[0].equals("true"); 21 | int from = odd ? 0 : 1; 22 | int to = odd ? 1 : 0; 23 | long start = 0; 24 | for (int count = 0; count <= 10000001; ) { 25 | if (UnsafeDemo.UNSAFE.compareAndSwapLong(null, address, from, to)) { 26 | count++; 27 | if (count == 1) { 28 | start = System.nanoTime(); 29 | System.out.println("started"); 30 | } 31 | } else { 32 | // System.out.println(count + ": " + UnsafeDemo.UNSAFE.getLongVolatile(null, address)); 33 | } 34 | } 35 | long time = System.nanoTime() - start; 36 | System.out.printf("Took %.3f seconds%n", time / 1e9); 37 | System.out.println(bb.getLong(0)); 38 | raf.close(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/Unsafe2Demo.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | /** 8 | * Created by peter on 24/11/2014. 9 | */ 10 | public class Unsafe2Demo { 11 | 12 | static final Unsafe UNSAFE; 13 | 14 | static { 15 | try { 16 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 17 | theUnsafe.setAccessible(true); 18 | UNSAFE = (Unsafe) theUnsafe.get(null); 19 | } catch (Exception e) { 20 | throw new AssertionError(e); 21 | } 22 | } 23 | 24 | public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { 25 | Field value = String.class.getDeclaredField("value"); 26 | value.setAccessible(true); 27 | value.set("Hello", "Salut".toCharArray()); 28 | 29 | System.out.println("Hello"); 30 | 31 | synchronized ("one") { 32 | 33 | } 34 | /* 35 | Integer x = 5; 36 | Field value = Integer.class.getDeclaredField("value"); 37 | value.setAccessible(true); 38 | value.setInt(5, 6); 39 | 40 | Integer i = 3 + 2; 41 | System.out.println("3 + 2 = "+i); 42 | */ 43 | 44 | /* 45 | MyType mt = new MyType(); 46 | Field num = MyType.class.getDeclaredField("num"); 47 | Field num2 = MyType.class.getDeclaredField("num2"); 48 | long numOff = UNSAFE.objectFieldOffset(num); 49 | long num2Off = UNSAFE.objectFieldOffset(num2); 50 | 51 | mt.num = 1234; 52 | mt.num2 = 1234; 53 | System.out.printf("mt.num=%x%n", UNSAFE.getInt(mt, numOff)); 54 | System.out.printf("mt.num2=%x%n", UNSAFE.getInt(mt, num2Off)); 55 | 56 | mt.s = "Hello"; 57 | Field s = MyType.class.getDeclaredField("s"); 58 | long sOff = UNSAFE.objectFieldOffset(s); 59 | System.out.printf("mt.s=%x%n", UNSAFE.getInt(mt, sOff)); 60 | */ 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/Unsafe3Demo.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.io.IOException; 6 | import java.lang.reflect.Field; 7 | 8 | /** 9 | * Created by peter on 24/11/2014. 10 | */ 11 | public class Unsafe3Demo { 12 | 13 | static final Unsafe UNSAFE; 14 | 15 | static { 16 | try { 17 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 18 | theUnsafe.setAccessible(true); 19 | UNSAFE = (Unsafe) theUnsafe.get(null); 20 | } catch (Exception e) { 21 | throw new AssertionError(e); 22 | } 23 | } 24 | 25 | public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException { 26 | // todo don't do this. 27 | UNSAFE.getInt(0L); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/Unsafe4Demo.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.io.IOException; 6 | import java.lang.reflect.Field; 7 | 8 | /** 9 | * Created by peter on 24/11/2014. 10 | */ 11 | public class Unsafe4Demo { 12 | 13 | static final Unsafe UNSAFE; 14 | static final int x = 5; 15 | 16 | static { 17 | try { 18 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 19 | theUnsafe.setAccessible(true); 20 | UNSAFE = (Unsafe) theUnsafe.get(null); 21 | } catch (Exception e) { 22 | throw new AssertionError(e); 23 | } 24 | } 25 | 26 | public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, InstantiationException { 27 | System.out.println("Starting"); 28 | Object o = UNSAFE.staticFieldBase(Unsafe4Demo.class); 29 | Field _x = Unsafe4Demo.class.getDeclaredField("x"); 30 | _x.setAccessible(true); 31 | long xOff = UNSAFE.staticFieldOffset(_x); 32 | UNSAFE.compareAndSwapInt(o, xOff, 5, 42); 33 | System.out.println("x=" + UNSAFE.getInt(o, xOff) + " x is now " + _x.get(null)); 34 | 35 | /* 36 | MyEnum mt = (MyEnum) UNSAFE.allocateInstance(MyEnum.class); 37 | Field name = Enum.class.getDeclaredField("name"); 38 | name.setAccessible(true); 39 | name.set(mt, "A"); 40 | System.out.println("Done " + mt); 41 | System.out.println(mt.equals(MyEnum.A)); 42 | */ 43 | 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/Unsafe5Demo.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | /** 8 | * Created by peter on 24/11/2014. 9 | */ 10 | public class Unsafe5Demo { 11 | 12 | static final Unsafe UNSAFE; 13 | 14 | static { 15 | try { 16 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 17 | theUnsafe.setAccessible(true); 18 | UNSAFE = (Unsafe) theUnsafe.get(null); 19 | } catch (Exception e) { 20 | throw new AssertionError(e); 21 | } 22 | } 23 | 24 | public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { 25 | String s = "hello world"; 26 | System.out.println(Integer.toHexString(s.hashCode())); 27 | System.out.println(Integer.toHexString(System.identityHashCode(s))); 28 | int stringHashCode = UNSAFE.getInt(s, 1L); 29 | System.out.println("from header: " + Integer.toHexString(stringHashCode)); 30 | 31 | Field hash = String.class.getDeclaredField("hash"); 32 | hash.setAccessible(true); 33 | int origHashCode = hash.getInt(s); 34 | System.out.println("from hash: " + Integer.toHexString(origHashCode)); 35 | 36 | long offset = UNSAFE.objectFieldOffset(hash); 37 | System.out.println("offset: " + offset); 38 | 39 | int origHashCode2 = UNSAFE.getInt(s, offset); 40 | System.out.println("from int at " + offset + ": " + Integer.toHexString(origHashCode2)); 41 | UNSAFE.putInt(s, offset, 0x12345678); 42 | System.out.println("new string.hashCode is " + Integer.toHexString(s.hashCode())); 43 | 44 | } 45 | 46 | public static long memoryUsed() { 47 | Runtime rt = Runtime.getRuntime(); 48 | return rt.totalMemory() - rt.freeMemory(); 49 | } 50 | 51 | static class MyType { 52 | String s; 53 | int num; 54 | long time; 55 | double d; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/UnsafeDemo.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | /** 8 | * Created by peter on 24/11/2014. 9 | */ 10 | public class UnsafeDemo { 11 | 12 | static final Unsafe UNSAFE; 13 | 14 | static { 15 | try { 16 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 17 | theUnsafe.setAccessible(true); 18 | UNSAFE = (Unsafe) theUnsafe.get(null); 19 | } catch (Exception e) { 20 | throw new AssertionError(e); 21 | } 22 | } 23 | 24 | public static void main(String[] args) { 25 | new MyType(); 26 | memoryUsed(); 27 | 28 | long start = memoryUsed(); 29 | MyType mt = new MyType(); 30 | long end = memoryUsed(); 31 | System.out.printf("%s used %,d bytes%n", MyType.class, end - start); 32 | 33 | for (Field field : MyType.class.getDeclaredFields()) { 34 | long offset = UNSAFE.objectFieldOffset(field); 35 | System.out.printf("Field %s, offset %d%n", field, offset); 36 | } 37 | } 38 | 39 | public static long memoryUsed() { 40 | Runtime rt = Runtime.getRuntime(); 41 | return rt.totalMemory() - rt.freeMemory(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/UnsafeIdentityDemo.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | /** 8 | * Created by peter on 24/11/2014. 9 | */ 10 | public class UnsafeIdentityDemo { 11 | 12 | static final Unsafe UNSAFE; 13 | 14 | static { 15 | try { 16 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 17 | theUnsafe.setAccessible(true); 18 | UNSAFE = (Unsafe) theUnsafe.get(null); 19 | } catch (Exception e) { 20 | throw new AssertionError(e); 21 | } 22 | } 23 | 24 | public static void setIdentityHashCode(Object o, int code) { 25 | UNSAFE.putInt(o, 1l, code & 0x7FFF_FFF); 26 | } 27 | 28 | public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { 29 | Double d = 1.0; 30 | Double d2 = 1.0; 31 | setIdentityHashCode(d, 1); 32 | setIdentityHashCode(d2, 1); 33 | System.out.println("d: " + d + 34 | " System.identityHashCode(d): " + System.identityHashCode(d)); 35 | System.out.println("d2: " + d2 + 36 | " System.identityHashCode(d2): " + System.identityHashCode(d2)); 37 | System.out.println("d == d2: " + (d == d2)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/unsafe/UnsafeResetHashCodeDemo.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.unsafe; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | /** 8 | * Created by peter on 24/11/2014. 9 | */ 10 | public class UnsafeResetHashCodeDemo { 11 | 12 | static final Unsafe UNSAFE; 13 | 14 | static { 15 | try { 16 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 17 | theUnsafe.setAccessible(true); 18 | UNSAFE = (Unsafe) theUnsafe.get(null); 19 | } catch (Exception e) { 20 | throw new AssertionError(e); 21 | } 22 | } 23 | 24 | public static void main(String[] args) { 25 | new MyType(); 26 | memoryUsed(); 27 | 28 | long start = memoryUsed(); 29 | MyType mt = new MyType(); 30 | long end = memoryUsed(); 31 | System.out.printf("%s used %,d bytes%n", MyType.class, end - start); 32 | 33 | for (Field field : MyType.class.getDeclaredFields()) { 34 | long offset = UNSAFE.objectFieldOffset(field); 35 | System.out.printf("Field %s, offset %d%n", field, offset); 36 | } 37 | 38 | int hc = UNSAFE.getInt(mt, 1L); 39 | System.out.printf("Hash code is %x%n", hc); 40 | { 41 | int hc1 = mt.hashCode(); 42 | int hc2 = UNSAFE.getInt(mt, 1L); 43 | System.out.printf("Hash code is %x == %x%n", hc1, hc2); 44 | } 45 | 46 | for (int i = 0; i < 10; i++) { 47 | UNSAFE.putInt(mt, 1L, i); 48 | { 49 | int hc1 = mt.hashCode(); 50 | int hc2 = UNSAFE.getInt(mt, 1L); 51 | System.out.printf("Hash code is %x == %x%n", hc1, hc2); 52 | } 53 | } 54 | } 55 | 56 | public static long memoryUsed() { 57 | Runtime rt = Runtime.getRuntime(); 58 | return rt.totalMemory() - rt.freeMemory(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/vanilla/java/util/ArrayMap.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.util; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * Created by Peter on 16/06/2016. 7 | */ 8 | public class ArrayMap extends AbstractMap { 9 | final Map index; 10 | V[] values; 11 | 12 | public ArrayMap(Map index, V[] values) { 13 | this.index = index; 14 | this.values = values; 15 | } 16 | 17 | @Override 18 | public int size() { 19 | return index.size(); 20 | } 21 | 22 | @Override 23 | public boolean containsValue(Object value) { 24 | for (V v : values) { 25 | if (Objects.equals(v, value)) 26 | return true; 27 | } 28 | return false; 29 | } 30 | 31 | @Override 32 | public boolean containsKey(Object key) { 33 | return index.containsKey(key); 34 | } 35 | 36 | @Override 37 | public V get(Object key) { 38 | Integer idx = index.get(key); 39 | return idx == null || idx >= values.length ? null : values[idx]; 40 | } 41 | 42 | @Override 43 | public V put(K key, V value) { 44 | Integer idx = index.get(key); 45 | if (idx == null) 46 | throw new IllegalArgumentException("Cannot add a key " + key); 47 | if (values.length <= idx) 48 | values = Arrays.copyOf(values, idx + 1); 49 | V prev = values[idx]; 50 | values[idx] = value; 51 | return prev; 52 | } 53 | 54 | @Override 55 | public Set keySet() { 56 | return index.keySet(); 57 | } 58 | 59 | @Override 60 | public Collection values() { 61 | return Arrays.asList(values); 62 | } 63 | 64 | @Override 65 | public boolean equals(Object o) { 66 | return super.equals(o); 67 | } 68 | 69 | @Override 70 | public int hashCode() { 71 | int hashCode = 0; 72 | for (V value : values) { 73 | hashCode ^= Objects.hashCode(value); 74 | } 75 | return hashCode; 76 | } 77 | 78 | @Override 79 | public String toString() { 80 | return super.toString(); 81 | } 82 | 83 | @Override 84 | public Set> entrySet() { 85 | Map map = new LinkedHashMap<>(size(), 1.0f); 86 | for (Entry entry : index.entrySet()) { 87 | K key = entry.getKey(); 88 | Integer idx = entry.getValue(); 89 | V value = idx < values.length ? values[idx] : null; 90 | map.put(key, value); 91 | } 92 | return Collections.unmodifiableMap(map).entrySet(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/test/java/test/lang/ObjectTest.java: -------------------------------------------------------------------------------- 1 | package test.lang; 2 | 3 | import org.junit.Test; 4 | 5 | import java.lang.reflect.Field; 6 | import java.util.LinkedHashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * Created by peter on 10/03/16. 11 | */ 12 | public class ObjectTest { 13 | boolean[] booleans = {true, false}; 14 | byte[] bytes = {1, 2, 3}; 15 | char[] chars = "Hello World".toCharArray(); 16 | short[] shorts = {111, 222, 333}; 17 | float[] floats = {1.0f, 2.2f, 3.33f, 44.44f, 55.555f, 666.666f}; 18 | int[] ints = {1, 22, 333, 4_444, 55_555, 666_666}; 19 | double[] doubles = {Math.PI, Math.E}; 20 | long[] longs = {System.currentTimeMillis(), System.nanoTime()}; 21 | String[] words = "The quick brown fox jumps over the lazy dog".split(" "); 22 | 23 | @Test 24 | public void testToString() throws IllegalAccessException { 25 | 26 | Map arrays = new LinkedHashMap<>(); 27 | for (Field f : getClass().getDeclaredFields()) 28 | arrays.put(f.getName(), f.get(this)); 29 | arrays.entrySet().forEach(System.out::println); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/vanilla/java/perfeg/mmap/DataGenerator.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.mmap; 2 | 3 | import vanilla.java.perfeg.mmap.api.Column; 4 | import vanilla.java.perfeg.mmap.api.Row; 5 | import vanilla.java.perfeg.mmap.api.Table; 6 | 7 | import java.util.Random; 8 | 9 | /** 10 | * @author plawrey 11 | */ 12 | public enum DataGenerator { 13 | ; 14 | 15 | public static void generateDataFor(Table table, int size) { 16 | Row row = table.createRow(); 17 | Column bidPrice = table.acquireColumn("bidPrice"); 18 | Column askPrice = table.acquireColumn("askPrice"); 19 | Random rand = new Random(size); 20 | long bp = 1000, ap = 1001; 21 | int tickSize = 10; 22 | assert table.size() == 0; 23 | 24 | for (int i = 0; i < size; i++) { 25 | bp += (rand.nextInt(1) - rand.nextInt(1)) * tickSize; 26 | ap += (rand.nextInt(1) - rand.nextInt(1)) * tickSize; 27 | if (ap <= bp) { 28 | ap += tickSize; 29 | bp -= tickSize; 30 | } 31 | if (ap > bp + 10 * tickSize) { 32 | if (rand.nextBoolean() || bp < 500) 33 | bp += tickSize; 34 | else 35 | ap -= tickSize; 36 | } 37 | row.addEntry(i * 10); 38 | row.set(bidPrice, bp); 39 | row.set(askPrice, ap); 40 | 41 | } 42 | assert table.size() == size; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/vanilla/java/perfeg/mmap/PerformanceTest.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.perfeg.mmap; 2 | 3 | import org.junit.After; 4 | import org.junit.Test; 5 | import vanilla.java.perfeg.mmap.api.Column; 6 | import vanilla.java.perfeg.mmap.api.Row; 7 | import vanilla.java.perfeg.mmap.api.Table; 8 | import vanilla.java.perfeg.mmap.mmap.MmapTable; 9 | import vanilla.java.perfeg.mmap.oop.OopTable; 10 | 11 | import java.io.File; 12 | import java.io.IOException; 13 | 14 | /** 15 | * @author plawrey 16 | */ 17 | public class PerformanceTest { 18 | static final String TMP = System.getProperty("java.io.tmpdir"); 19 | 20 | @After 21 | public void cleanUp() { 22 | System.gc(); 23 | } 24 | 25 | @Test 26 | public void testOops() throws IOException { 27 | { 28 | long start = System.nanoTime(); 29 | OopTable table = new OopTable(TMP); 30 | new File(TMP, "data").deleteOnExit(); 31 | DataGenerator.generateDataFor(table, 100 * 1000 * 1000); 32 | table.close(); 33 | long time = System.nanoTime() - start; 34 | System.out.printf("OOPS: Took %.3f seconds to generate and save %,d entries%n", time / 1e9, table.size()); 35 | } 36 | for (int i = 0; i < 3; i++) { 37 | long start2 = System.nanoTime(); 38 | OopTable table2 = new OopTable(TMP); 39 | computeMidPriceBP(table2); 40 | System.gc(); 41 | table2.close(); 42 | long time2 = System.nanoTime() - start2; 43 | System.out.printf("OOPS: Took %.3f seconds calculate the mid BP, plus a GC and save %,d entries%n", time2 / 1e9, table2.size()); 44 | } 45 | } 46 | 47 | @Test 48 | public void testMmap() throws IOException { 49 | String dir = TMP + "/mmap"; 50 | { 51 | long start = System.nanoTime(); 52 | MmapTable table = new MmapTable(dir); 53 | DataGenerator.generateDataFor(table, 100 * 1000 * 1000); 54 | table.close(); 55 | long time = System.nanoTime() - start; 56 | System.out.printf("MMAP: Took %.3f seconds to generate and save %,d entries%n", time / 1e9, table.size()); 57 | deleteOnExit(dir); 58 | } 59 | for (int i = 0; i < 3; i++) { 60 | long start2 = System.nanoTime(); 61 | MmapTable table2 = new MmapTable(dir); 62 | computeMidPriceBP(table2); 63 | System.gc(); 64 | table2.close(); 65 | long time2 = System.nanoTime() - start2; 66 | System.out.printf("MMAP: Took %.3f seconds calculate the mid BP, plus a GC and save %,d entries%n", time2 / 1e9, table2.size()); 67 | } 68 | } 69 | 70 | private void deleteOnExit(String dir) { 71 | File file = new File(dir); 72 | if (file.isDirectory()) 73 | for (File f : file.listFiles()) { 74 | deleteOnExit(f.toString()); 75 | } 76 | file.deleteOnExit(); 77 | } 78 | 79 | private void computeMidPriceBP(Table table) { 80 | Row row = table.createRow(); 81 | Column bidPrice = table.acquireColumn("bidPrice"); 82 | Column askPrice = table.acquireColumn("askPrice"); 83 | Column midBP = table.acquireColumn("midBP"); 84 | long lastMp = (row.get(bidPrice) + row.get(askPrice)) / 2; 85 | while (row.nextRecord()) { 86 | long mp = (row.get(bidPrice) + row.get(askPrice)) / 2; 87 | long mpbp = 10000 * (mp - lastMp) / lastMp; 88 | row.set(midBP, mpbp); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/test/java/vanilla/java/perfeg/mmap/results.txt: -------------------------------------------------------------------------------- 1 | Using regular Java objects. 2 | 3 | OOPS: Took 0.269 seconds to generate and save 1,000,000 entries 4 | OOPS: Took 0.625 seconds calculate the mid BP, plus a GC and save 1,000,000 entries 5 | OOPS: Took 0.553 seconds calculate the mid BP, plus a GC and save 1,000,000 entries 6 | OOPS: Took 0.535 seconds calculate the mid BP, plus a GC and save 1,000,000 entries 7 | 8 | OOPS: Took 5.068 seconds to generate and save 10,000,000 entries 9 | OOPS: Took 5.785 seconds calculate the mid BP, plus a GC and save 10,000,000 entries 10 | OOPS: Took 4.065 seconds calculate the mid BP, plus a GC and save 10,000,000 entries 11 | OOPS: Took 4.386 seconds calculate the mid BP, plus a GC and save 10,000,000 entries 12 | 13 | OOPS: Took 11.663 seconds to generate and save 30,000,000 entries 14 | OOPS: Took 14.844 seconds calculate the mid BP, plus a GC and save 30,000,000 entries 15 | OOPS: Took 19.572 seconds calculate the mid BP, plus a GC and save 30,000,000 entries 16 | OOPS: Took 16.703 seconds calculate the mid BP, plus a GC and save 30,000,000 entries 17 | 18 | OOPS: Took 116.282 seconds to generate and save 100,000,000 entries 19 | OOPS: Took 86.722 seconds calculate the mid BP, plus a GC and save 100,000,000 entries 20 | OOPS: Took 73.079 seconds calculate the mid BP, plus a GC and save 100,000,000 entries 21 | OOPS: Took 95.796 seconds calculate the mid BP, plus a GC and save 100,000,000 entries 22 | 23 | OOPS: Took 340.588 seconds to generate and save 250,000,000 entries 24 | OOPS: Took 224.854 seconds calculate the mid BP, plus a GC and save 250,000,000 entries 25 | OOPS: Took 234.013 seconds calculate the mid BP, plus a GC and save 250,000,000 entries 26 | OOPS: Took 219.476 seconds calculate the mid BP, plus a GC and save 250,000,000 entries 27 | 28 | Using memory mapped files to store the data with the same abstractions. 29 | 30 | MMAP: Took 0.150 seconds to generate and save 1,000,000 entries 31 | MMAP: Took 0.079 seconds calculate the mid BP, plus a GC and save 1,000,000 entries 32 | MMAP: Took 0.054 seconds calculate the mid BP, plus a GC and save 1,000,000 entries 33 | MMAP: Took 0.056 seconds calculate the mid BP, plus a GC and save 1,000,000 entries 34 | 35 | MMAP: Took 0.976 seconds to generate and save 10,000,000 entries 36 | MMAP: Took 0.474 seconds calculate the mid BP, plus a GC and save 10,000,000 entries 37 | MMAP: Took 0.450 seconds calculate the mid BP, plus a GC and save 10,000,000 entries 38 | MMAP: Took 0.455 seconds calculate the mid BP, plus a GC and save 10,000,000 entries 39 | 40 | MMAP: Took 2.652 seconds to generate and save 30,000,000 entries 41 | MMAP: Took 1.351 seconds calculate the mid BP, plus a GC and save 30,000,000 entries 42 | MMAP: Took 1.335 seconds calculate the mid BP, plus a GC and save 30,000,000 entries 43 | MMAP: Took 1.295 seconds calculate the mid BP, plus a GC and save 30,000,000 entries 44 | 45 | MMAP: Took 8.596 seconds to generate and save 100,000,000 entries 46 | MMAP: Took 4.475 seconds calculate the mid BP, plus a GC and save 100,000,000 entries 47 | MMAP: Took 4.294 seconds calculate the mid BP, plus a GC and save 100,000,000 entries 48 | MMAP: Took 4.450 seconds calculate the mid BP, plus a GC and save 100,000,000 entries 49 | 50 | MMAP: Took 21.240 seconds to generate and save 250,000,000 entries 51 | MMAP: Took 11.150 seconds calculate the mid BP, plus a GC and save 250,000,000 entries 52 | MMAP: Took 11.132 seconds calculate the mid BP, plus a GC and save 250,000,000 entries 53 | MMAP: Took 11.008 seconds calculate the mid BP, plus a GC and save 250,000,000 entries -------------------------------------------------------------------------------- /src/test/java/vanilla/java/util/ArrayMapTest.java: -------------------------------------------------------------------------------- 1 | package vanilla.java.util; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Collections; 6 | import java.util.HashMap; 7 | import java.util.LinkedHashMap; 8 | import java.util.Map; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Created by Peter on 16/06/2016. 14 | */ 15 | public class ArrayMapTest { 16 | final Map empty = new ArrayMap<>(Collections.emptyMap(), new String[0]); 17 | final Map oneKey = new LinkedHashMap<>(); 18 | final Map one = new ArrayMap<>(oneKey, new String[]{"world"}); 19 | 20 | { 21 | oneKey.put("hello", 0); 22 | } 23 | 24 | @Test 25 | public void testSize() throws Exception { 26 | assertEquals(0, empty.size()); 27 | assertEquals(1, one.size()); 28 | } 29 | 30 | @Test 31 | public void testContainsValue() throws Exception { 32 | assertFalse(empty.containsValue("world")); 33 | assertTrue(one.containsValue("world")); 34 | } 35 | 36 | @Test 37 | public void testContainsKey() throws Exception { 38 | assertFalse(empty.containsKey("hello")); 39 | assertTrue(one.containsKey("hello")); 40 | } 41 | 42 | @Test 43 | public void testGet() throws Exception { 44 | assertNull(empty.get("hello")); 45 | assertEquals("world", one.get("hello")); 46 | } 47 | 48 | @Test 49 | public void testPut() throws Exception { 50 | assertEquals("world", one.put("hello", "there")); 51 | assertEquals("there", one.get("hello")); 52 | } 53 | 54 | @Test 55 | public void testKeySet() throws Exception { 56 | assertEquals("[]", empty.keySet().toString()); 57 | assertEquals("[hello]", one.keySet().toString()); 58 | } 59 | 60 | @Test 61 | public void testValues() throws Exception { 62 | assertEquals("[]", empty.values().toString()); 63 | assertEquals("[world]", one.values().toString()); 64 | } 65 | 66 | @Test 67 | public void testEquals() throws Exception { 68 | assertEquals(Collections.emptyMap(), empty); 69 | Map map = new HashMap<>(); 70 | map.put("hello", "world"); 71 | assertEquals(map, one); 72 | } 73 | 74 | @Test 75 | public void testHashCode() throws Exception { 76 | assertEquals(0, empty.hashCode()); 77 | assertEquals("world".hashCode(), one.hashCode()); 78 | } 79 | 80 | @Test 81 | public void testToString() throws Exception { 82 | assertEquals("{}", empty.toString()); 83 | assertEquals("{hello=world}", one.toString()); 84 | } 85 | } --------------------------------------------------------------------------------