diff options
author | Ningsheng Jian <ningsheng.jian@linaro.org> | 2017-11-07 18:38:01 +0800 |
---|---|---|
committer | Ningsheng Jian <ningsheng.jian@linaro.org> | 2017-11-16 09:46:55 +0800 |
commit | e715fe64e96acb6131af937d0c8bba2537ea13f4 (patch) | |
tree | 702384eb404c3fd6acbbc3321261847e9fc27398 /src/main/java/org/linaro/benchmarks/benchmarksgame/chameneosredux.java | |
parent | 3811e9930ddb1d2b3a1463ad6c876af324331335 (diff) |
1. Port benchmark cases from art-testing.
2. Add some more benchmarks for basic OPs.
3. Fix some jmh result variance.
Signed-off-by: Zhongwei Yao <zhongwei.yao@linaro.org>
Signed-off-by: Yang Zhang <yang.zhang@linaro.org>
Signed-off-by: Ningsheng Jian <ningsheng.jian@linaro.org>
Change-Id: I514658696b63e468158325be3b84494553773705
Diffstat (limited to 'src/main/java/org/linaro/benchmarks/benchmarksgame/chameneosredux.java')
-rw-r--r-- | src/main/java/org/linaro/benchmarks/benchmarksgame/chameneosredux.java | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/src/main/java/org/linaro/benchmarks/benchmarksgame/chameneosredux.java b/src/main/java/org/linaro/benchmarks/benchmarksgame/chameneosredux.java new file mode 100644 index 0000000..6733d6b --- /dev/null +++ b/src/main/java/org/linaro/benchmarks/benchmarksgame/chameneosredux.java @@ -0,0 +1,253 @@ +/* + * This benchmark has been ported from "The Computer Language Benchmarks Game" suite and slightly + * modified to fit the benchmarking framework. + * + * The original file is `chameneosredux/chameneosredux.java` from the archive + * available at + * http://benchmarksgame.alioth.debian.org/download/benchmarksgame-sourcecode.zip. + * See LICENSE file in the same folder (BSD 3-clause) + * + * The Computer Language Benchmarks Game + * http://benchmarksgame.alioth.debian.org/ + * + * contributed by Michael Barker + */ + +/* + * Description: Symmetrical thread rendezvous requests. + * Main Focus: TODO + * + */ + +package org.linaro.benchmarks.benchmarksgame; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import org.openjdk.jmh.annotations.*; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Benchmark) + + +/** + * This implementation uses the java.util.concurrent.atomic library + * i.e. (compare and set) to avoid locking. Real threads are used, but + * are set up as a thread pool and meeting requests are pushed onto a + * queue that feeds the thread pool. + */ +// CHECKSTYLE.OFF: .* +public class chameneosredux { + + enum Colour { + blue, + red, + yellow + } + + private static Colour doCompliment(final Colour c1, final Colour c2) { + switch (c1) { + case blue: + switch (c2) { + case blue: + return Colour.blue; + case red: + return Colour.yellow; + case yellow: + return Colour.red; + } + case red: + switch (c2) { + case blue: + return Colour.yellow; + case red: + return Colour.red; + case yellow: + return Colour.blue; + } + case yellow: + switch (c2) { + case blue: + return Colour.red; + case red: + return Colour.blue; + case yellow: + return Colour.yellow; + } + } + + throw new RuntimeException("Error"); + } + + static final class MeetingPlace { + + private final AtomicInteger meetingsLeft; + private final AtomicReference<Creature> creatureRef = new AtomicReference<Creature>(); + + public MeetingPlace(final int meetings) { + meetingsLeft = new AtomicInteger(meetings); + } + + public void meet(final Creature incoming) { + Colour newColour = null; + Creature first = null; + Creature next = null; + do { + first = creatureRef.get(); + next = incoming; + if (first != null) { + newColour = doCompliment(incoming.colour, first.colour); + next = null; + } + } while (!creatureRef.compareAndSet(first, next)); + + if (first != null) { + final int meetings = meetingsLeft.decrementAndGet(); + if (meetings >= 0) { + first.setColour(incoming.id, newColour); + incoming.setColour(first.id, newColour); + } else { + first.complete(); + incoming.complete(); + } + } + } + } + + static final class Dispatcher implements Runnable { + private final BlockingQueue<Creature> q; + + public Dispatcher(final BlockingQueue<Creature> q) { + this.q = q; + } + + public void run() { + try { + while (true) { + q.take().run(); + } + } catch (final InterruptedException e) { + } + } + } + + static final class Creature { + + private final int id; + private final MeetingPlace place; + private final BlockingQueue<Creature> q; + private final CountDownLatch latch; + private int count = 0; + private int sameCount = 0; + private Colour colour; + + public Creature(final MeetingPlace place, final Colour colour, + final BlockingQueue<Creature> q, final CountDownLatch latch) { + this.id = System.identityHashCode(this); + this.place = place; + this.latch = latch; + this.colour = colour; + this.q = q; + } + + public void complete() { + latch.countDown(); + } + + public void setColour(final int id, final Colour newColour) { + this.colour = newColour; + count++; + sameCount += 1 ^ Integer.signum(abs(this.id - id)); + q.add(this); + } + + private int abs(final int x) { + final int y = x >> 31; + return (x ^ y) - y; + } + + public void run() { + place.meet(this); + } + + public int getCount() { + return count; + } + + @Override + public String toString() { + return String.valueOf(count) + getNumber(sameCount); + } + } + + private int run(final int n, final Colour...colours) { + final int len = colours.length; + final MeetingPlace place = new MeetingPlace(n); + final Creature[] creatures = new Creature[len]; + final BlockingQueue<Creature> q = new ArrayBlockingQueue<Creature>(len); + final CountDownLatch latch = new CountDownLatch(len - 1); + + for (int i = 0; i < len; i++) { + creatures[i] = new Creature(place, colours[i], q, latch); + } + + final Thread[] ts = new Thread[len]; + for (int i = 0, h = ts.length; i < h; i++) { + ts[i] = new Thread(new Dispatcher(q)); + ts[i].setDaemon(true); + ts[i].start(); + } + + for (final Creature creature : creatures) { + q.add(creature); + } + + try { + latch.await(); + for (final Thread t : ts) { + t.interrupt(); + } + for (final Thread t : ts) { + t.join(); + } + } catch (final InterruptedException e1) { + System.err.println("Existing with error: " + e1); + } + + int total = 0; + for (final Creature creature : creatures) { + total += creature.getCount(); + } + return total; + } + + private static final String[] NUMBERS = { + "zero", "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine" + }; + + private static String getNumber(final int n) { + final StringBuilder sb = new StringBuilder(); + final String nStr = String.valueOf(n); + for (int i = 0; i < nStr.length(); i++) { + sb.append(" "); + sb.append(NUMBERS[Character.getNumericValue(nStr.charAt(i))]); + } + + return sb.toString(); + } + // CHECKSTYLE.ON: .* + + private static final int PREDEFINED_N = 600; + + @Benchmark + public void jmhTimeChameneosRedux() { + run(PREDEFINED_N, Colour.blue, Colour.red, Colour.yellow); + run(PREDEFINED_N, Colour.blue, Colour.red, Colour.yellow, Colour.red, Colour.yellow, + Colour.blue, Colour.red, Colour.yellow, Colour.red, Colour.blue); + } +} |