All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mentaqueue.test.producer.TestAtomicQueue Maven / Gradle / Ivy

There is a newer version: 1.3.1
Show newest version
/*
 * 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.AtomicQueue;
import org.mentaqueue.util.MutableLong;
import org.mentaqueue.wait.ParkWaitStrategy;

public class TestAtomicQueue {

	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.TestAtomicQueue 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(TestAtomicQueue.class.getSimpleName());
		
		RESULTS = new ArrayList(runs);
		
		for (int z = 0; z < runs; z++) {
			
			System.gc();
			Thread.sleep(100);

			final AtomicQueue queue = new AtomicQueue(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);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy