/*
* Quasar: lightweight threads and actors for the JVM.
* Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 3.0
* as published by the Free Software Foundation.
*/
package co.paralleluniverse.strands;
import co.paralleluniverse.common.util.Debug;
import co.paralleluniverse.fibers.Fiber;
import co.paralleluniverse.fibers.SuspendExecution;
import co.paralleluniverse.strands.channels.Channel;
import co.paralleluniverse.strands.channels.Channels;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
public class StrandsBenchmark {
static final boolean HEAVYWEIGHT = false;
static final int RINGS = 2;
static final int STRANDS_PER_RING = 100;
static final int MESSAGES_PER_RING = 10000;
static final int bufferSize = 10;
public static void main(String args[]) throws Exception {
System.out.println("COMPILER: " + System.getProperty("java.vm.name"));
System.out.println("VERSION: " + System.getProperty("java.version"));
System.out.println("OS: " + System.getProperty("os.name"));
System.out.println("PROCESSORS: " + Runtime.getRuntime().availableProcessors());
System.out.println("FORK_JOIN: " + Debug.whereIs(ForkJoinPool.class));
System.out.println();
System.out.println("HEAVYWEIGHT: " + HEAVYWEIGHT);
System.out.println("RINGS: " + RINGS);
System.out.println("STRANDS_PER_RING: " + STRANDS_PER_RING);
System.out.println("MESSAGES_PER_RING: " + MESSAGES_PER_RING);
for (int i = 0; i < 3; i++) {
System.out.println("\nRun: " + i);
new StrandsBenchmark().run();
}
}
volatile Object blackHole;
void run() throws ExecutionException, InterruptedException {
final long start = System.nanoTime();
List<Strand> ringLeaders = new ArrayList<>();
for (int i = 0; i < RINGS; i++)
ringLeaders.add(createRing(HEAVYWEIGHT, STRANDS_PER_RING, MESSAGES_PER_RING));
final long afterInit = System.nanoTime();
for (Strand leader : ringLeaders)
leader.start();
final long afterStart = System.nanoTime();
for (Strand leader : ringLeaders)
leader.join();
final long end = System.nanoTime();
System.out.println("Init time (ms): " + TimeUnit.MILLISECONDS.convert(afterInit - start, TimeUnit.NANOSECONDS));
System.out.println("Start time (ms): " + TimeUnit.MILLISECONDS.convert(afterStart - afterInit, TimeUnit.NANOSECONDS));
System.out.println("Running time (ms): " + TimeUnit.MILLISECONDS.convert(end - afterStart, TimeUnit.NANOSECONDS));
System.out.println("Total time (ms): " + TimeUnit.MILLISECONDS.convert(end - start, TimeUnit.NANOSECONDS));
System.out.println("Black hole: " + blackHole);
}
Strand createRing(boolean heavyweight, int size, final int rounds) {
final Channel<String> firstChannel = Channels.newChannel(bufferSize);
Channel<String> c = firstChannel;
for (int i = 0; i < size - 1; i++)
c = createRelayStrand(heavyweight, c);
final Channel<String> lastChannel = c;
Strand ringLeader = newStrand(heavyweight, new SuspendableRunnable() {
@Override
public void run() throws SuspendExecution, InterruptedException {
lastChannel.send("number:"); // start things off
String m = null;
for (int i = 0; i < rounds; i++) {
m = firstChannel.receive();
lastChannel.send(createMessage(m));
}
lastChannel.close();
blackHole = m;
}
});
return ringLeader;
}
Channel<String> createRelayStrand(boolean heavyweight, final Channel<String> prev) {
final Channel<String> channel = Channels.newChannel(bufferSize);
Strand s = newStrand(heavyweight, new SuspendableRunnable() {
@Override
public void run() throws InterruptedException, SuspendExecution {
String m;
while ((m = channel.receive()) != null)
prev.send(createMessage(m));
prev.close();
}
});
s.start();
return channel;
}
Strand newStrand(boolean heavyweight, SuspendableRunnable target) {
if (heavyweight)
return Strand.of(new Thread(Strand.toRunnable(target)));
else
return Strand.of(new Fiber(target));
}
String createMessage(String receivedMessage) {
return receivedMessage.substring(0, 7) + ThreadLocalRandom.current().nextInt();
}
}