/* * Copyright (C) 2014 Robert Stupp, Koeln, Germany, robert-stupp.de * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.caffinitas.ohc.jmh; import java.io.IOException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import org.caffinitas.ohc.alloc.IAllocator; import org.caffinitas.ohc.alloc.JNANativeAllocator; import org.caffinitas.ohc.alloc.UnsafeAllocator; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.annotations.Param; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Threads; import org.openjdk.jmh.annotations.Warmup; @BenchmarkMode({ /*Mode.AverageTime, */Mode.Throughput }) @State(Scope.Benchmark) @Warmup(iterations = 2) @Measurement(iterations = 3) @Threads(4) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Fork(value = 1, jvmArgsAppend = "-Xmx512M") public class AllocatorBenchmark { @Param({ "128", /*"256", "512", "1024", "1536", "2048", "4096", */"8192" }) private int size = 128; @Param({ "Unsafe", "JNA" }) private String allocatorType = "JNA"; private IAllocator allocator; @State(Scope.Thread) public static class Rand extends FasterRandom {} @State(Scope.Benchmark) public static class Allocations { final AtomicLong[] adrs = new AtomicLong[1024]; { for (int i = 0; i < adrs.length; i++) adrs[i] = new AtomicLong(); } void allocate(IAllocator allocator, Rand rand, int size) { int idx = rand.nextInt(adrs.length); AtomicLong adr = adrs[idx]; while (true) { long a = adr.get(); if (a == 0L) { break; } if (adr.compareAndSet(a, 0L)) { allocator.free(a); break; } } long a = allocator.allocate(size); if (!adr.compareAndSet(0L, a)) { allocator.free(a); } } void freeAll(IAllocator allocator) { for (AtomicLong al : adrs) { long adr = al.get(); if (adr != 0L) allocator.free(adr); } } } @Setup public void createAllocator() { switch (allocatorType) { case "Unsafe": allocator = new UnsafeAllocator(); break; case "JNA": allocator = new JNANativeAllocator(); break; } } @TearDown public void tearDown(Allocations allocations) throws IOException { allocations.freeAll(allocator); } @Benchmark @Threads(value = 1) public void allocateSingleThreaded(Rand rand, Allocations state) { state.allocate(allocator, rand, size); } @Benchmark @Threads(value = 4) public void allocateMultiThreaded(Rand rand, Allocations state) { state.allocate(allocator, rand, size); } }