org.mentaqueue.test.producer.TestVolatileQueue Maven / Gradle / Ivy
/*
* MentaQueue => http://mentaqueue.soliveirajr.com
* Copyright (C) 2012 Sergio Oliveira Jr. ([email protected])
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.mentaqueue.test.producer;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.mentaqueue.VolatileQueue;
import org.mentaqueue.util.MutableLong;
import org.mentaqueue.wait.ParkWaitStrategy;
public class TestVolatileQueue {
private static final boolean PRINT_RUNS = false;
private static final NumberFormat NUMBER_FORMATTER = new DecimalFormat("#,###,###");
private static long START_TIME;
private static List RESULTS;
private static long opsPerSec;
public static void main(String[] args) throws Exception {
if (args.length != 6) {
System.out.println("format: java -Xms1g -Xmx4g -XX:NewSize=512m -XX:MaxNewSize=1024m -cp target/classes org.mentaqueue.test.producer.TestVolatileQueue IGNORE OUTLIERS RUNS MESSAGES BUFFER_SIZE NON_BATCHING");
System.out.println("IGNORE => How many initial runs will be ignored when calculating the average (warmup runs)?");
System.out.println("OUTLIERS => How many best and worst to remove?");
System.out.println("RUNS => How many times to run the test?");
System.out.println("MESSAGES => How many messages to send to the other thread? (in thousands)");
System.out.println("BUFFER_SIZE => How many messages can the buffer hold? (in multiples of 1024)");
System.out.println("BATCHING => You can pass false here if you want to test the impact of batching. (Non-batching must be worse!)");
System.out.println();
return;
}
// final SpinYieldParkWaitStrategy consumerWaitStrategy = new SpinYieldParkWaitStrategy(); // avoid interface type on purpose for performance...
final ParkWaitStrategy consumerWaitStrategy = new ParkWaitStrategy(); // avoid interface type on purpose for performance...
// final SpinYieldParkWaitStrategy waitStrategy = new SpinYieldParkWaitStrategy(true); // avoid interface type on purpose for performance...
final ParkWaitStrategy producerWaitStrategy = new ParkWaitStrategy(true); // avoid interface type on purpose for performance...
final int ignore = Integer.parseInt(args[0]);
final int outliers = Integer.parseInt(args[1]);
final int runs = Integer.parseInt(args[2]);
final long messages = Long.parseLong(args[3]) * 1000L;
final int bufferSize = Integer.parseInt(args[4]) * 1024;
final boolean batching = Boolean.parseBoolean(args[5]);
int totalIterations = runs - ignore - 2 * outliers;
if (totalIterations <= 0) {
System.out.println("Please increase the number of RUNS!");
return;
}
System.out.print(TestVolatileQueue.class.getSimpleName());
RESULTS = new ArrayList(runs);
for (int z = 0; z < runs; z++) {
System.gc();
Thread.sleep(100);
final VolatileQueue queue = new VolatileQueue(bufferSize, MutableLong.BUILDER);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
long count = 0;
while (count < messages) {
long avail = queue.available();
if (avail > 0) {
if (!batching) {
avail = 1; // force non-batching
}
for (int x = 0; x < avail; x++) {
MutableLong ml = queue.poll();
if (ml != null) {
if (ml.get() != count) {
throw new IllegalStateException("This should never happen: expectedSeq=" + count + " receivedSeq=" + ml.get());
} else {
count++;
}
} else {
throw new IllegalStateException("This should never happen!");
}
}
consumerWaitStrategy.reset();
queue.done();
} else {
consumerWaitStrategy.waitForOtherThread();
}
}
}
}, "Consumer");
t.start();
START_TIME = System.nanoTime();
for (int i = 0; i < messages; i++) {
MutableLong ml = queue.nextToOffer();
if (ml == null) {
producerWaitStrategy.waitForOtherThread();
i--; // @#&$@(*(@#$_*_@#*)_@#($*()@# bug !!!!
} else {
ml.set(i);
queue.offer(ml);
producerWaitStrategy.reset();
}
}
long totalTime = System.nanoTime() - START_TIME;
long opsPerSecond = totalTime / messages;
RESULTS.add(opsPerSecond);
if (PRINT_RUNS) {
System.out.println(NUMBER_FORMATTER.format(opsPerSecond) + " nanoseconds/message");
} else {
System.out.print('.');
}
t.join();
}
System.out.println(" DONE");
int originalTotal = RESULTS.size();
// remove ones for JVM warmup...
List list = removeWarmUp(RESULTS, ignore);
// remove worst ones
for(int i = 0; i < outliers; i++) removeMin(list);
// remove 2 best ones
for(int i = 0; i < outliers; i++) removeMax(list);
long totalTime = addValues(list);
opsPerSec = totalTime / list.size();
System.out.println("Average: " + NUMBER_FORMATTER.format(opsPerSec) + " nanoseconds/message (sample_size=" + originalTotal + ", warmup=" + ignore + ", outliers=" + outliers * 2 + ", runs_considered = " + list.size() + ")");
}
public static long getResult() {
return opsPerSec;
}
private static long addValues(List list) {
long total = 0;
for(long l : list) {
total += l;
}
return total;
}
private static List removeWarmUp(List list, int ignored) {
Iterator iter = list.iterator();
for(int i = 0; i < ignored; i++) {
if (iter.hasNext()) {
iter.next();
iter.remove();
}
}
return list;
}
private static void removeMax(List list) {
int max = 0;
for(int i = 0; i < list.size(); i++) {
long currMax = list.get(max);
long currValue = list.get(i);
if (currValue > currMax) {
max = i;
}
}
list.remove(max);
}
private static void removeMin(List list) {
int min = 0;
for(int i = 0; i < list.size(); i++) {
long currMin = list.get(min);
long currValue = list.get(i);
if (currValue < currMin) {
min = i;
}
}
list.remove(min);
}
}