Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Simplifying performance and stress testing with MQJavaRoundTrip

Kevin Braithwaite (braithwa@uk.ibm.com ), WebSphere Business Integration Message Broker performance specialist, IBM United Kingdom
Kevin Braithwaite photo.
Kevin Braithwaite is a Performance Specialist with the WebSphere Business Integration Message Broker performance team in IBM Hursley. Kevin works with development in evaluating new releases of WebSphere Business Integration Message Broker, and with customers to provide consultancy on design, configuration and tuning issues relating to this product. You can contact Kevin at: braithwa@uk.ibm.com .
Marc Carter, WebSphere MQ/JMS performance specialist, IBM United Kingdom
Marc Carter is a Performance Specialist with the WebSphere MQ JMS performance team in IBM Hursley. Marc works with development in evaluating new releases of WebSphere MQ and with customers to provide consultancy on design, configuration and tuning issues relating to this product.

Summary:  This article is an excellent starting place for investigating the potential throughput of WebSphere® MQ V5.3 applications that move messages from one queue to another. It shows you how to use MQJavaRoundTrip to test a WebSphere Business Integration Message Broker application and provides extensive code samples for creating the main class and the ClientThread class.

Date:  14 Jul 2004
Level:  Intermediate

Activity:  2279 views
Comments:  

Introduction

When rolling out a new WebSphere MQ V5.3 deliverable or prototype that involves the movement of messages between queues, it is beneficial to performance and stress test the new application. This could be useful when implementing a WebSphere Business Integration Message Broker V5 solution. For example, without measuring the throughput capability of the message flow, you cannot know the rate at which it can process messages. Tools which make such testing easier make the likelihood of testing greater.

MQJavaRoundTrip is a simple Java™ tool that connects to WebSphere MQ, repeatedly puts messages to a queue and waits for a reply on another queue while reporting throughput during the test. MQJavaRoundTrip will therefore allow a more scientific figure of potential throughput to be obtained than performing a capacity planning exercise.


How to use MQJavaRoundTrip

Before executing MQJavaRoundTrip system, certain setup information needs to be obtained. This includes such things as the name of the queue manager that your application is connected to, the queues to which messages are put to and got from by the client and the input message to be used.

Some systems may have several different input messages; MQJavaRoundTrip uses one message only and is intended to be used to obtain approximate figures. It may be necessary to run MQJavaRoundTrip several times specifying a different input message to obtain a more accurate throughput figure.

It should be noted that when using MQJavaRoundTrip to test a WebSphere Business Integration Message Broker application, it may be necessary to build appropriate headers on to the application data. A useful tool to build such a message with headers is RFHUTIL available from IBM's MQ SupportPac Web site under the code IH03.

MQJavaRoundTrip is run from the command line and a number of arguments are required. A detailed description of the arguments can be found in the section "Argument Breakdown". When running MQJavaRoundTrip, a number of decisions need to be made. MQJavaRoundTrip is a multithreaded application in that it can spawn several client threads capable of producing messages and putting them to the input queue and retrieving the subsequent reply from the output queue. Deciding on the number of threads to run depends largely on the desired findings. If the maximum throughput possible is sought, it may be necessary to run MQJavaRoundTrip several times with increasing numbers of threads until the throughput rate does't increase. This will be the point when the application being tested is running at its full potential.

A sensible starting point is to set the number of threads to one more than the number of CPUs. It is also necessary to decide upon how to connect to the queue manager, whether to connect directly to the API using bindings connections or whether to connect as an MQ Client (TCP/IP based communication) The persistence of the message along with other message specifics such as the Character Set of the character data within the message and the encoding of the numeric data within the message needs to be specified. If using MQJavaRoundTrip on a test rather than production system, it would be best to base these decisions on the production environment. For example if the connection to the queue manager would be made via a WebSphere MQ Java Client, then a Client connection rather than a Bindings connection should be used for MQJavaRoundTrip.

Once MQJavaRoundTrip has been invoked, it will print out confirmation of the connection to the queue manager and queues. Depending on the interval argument specified MQJavaRoundTrip will periodically print out the message rates per second. Once the test has completed, a final print out of average throughput will be produced. This average value does not take into account any "warm up" period of the messaging transport.

Argument breakdown

On running MQJavaRoundTrip with no arguments specified, the following output will be displayed. This details all of the possible command line arguments:


Running MQJavaRoundTrip with no arguments specified
usage: java MQJavaRoundTrip <ltargs>
 Controller properties:
  -n <clients>
 (parallel threads)
  -d <duration>
 (in seconds - 0=never stop)
  -z (quiet, minimal output)
  -v <interval>
 (statistics interval)
 Queue manager properties:
  -qm <qm>
 (queue manager name)
  -i <queue>
 (put requests to)
  -o <queue>
 (get replies from)
 Connection properties for Bindings :
  -b (use local bindings connection)
  -t (use trusted/fastpath bindings, must use -b too)
 Connection properties for TCP/IP client :
  -h <hostname>
 (QM machine)
  -c <channel>
 (QM svrconn - defaults to SYSTEM.DEF.SVRCONN)
  -p <port>
 (QM listener port - defaults to 1414)
 Message properties:
  -f <file>
 (user data to send)
  -x (use transactions one-per-message)
  -s (use persistent messages)
  -mc (message character set)
  -me (message encoding)
  -mf (message format)
  -id (use get-correlation-id from sent-mesg-id)
  -gid (fixed correlation id per thread)
  -w <timeout>
 (message wait timeout in seconds)
 

Table 1. Argument breakdown

-n <clients> This flag allows the user to specify the number (the default is 1) of client threads that the application should spawn. Each thread will execute its put-get loop in parallel.
-d <duration>This flag allows the user to specify how long the test should run for in seconds. Once the duration has passed the application will terminate and remove any handles on Queues and queue managers. By specifying a value of "0" the test will run indefinitely.
-zThis flag allows the user to specify that only the final average throughput rate should be output.
-v <interval>This flag allows the user to specify the interval at which the throughput rate is output in seconds. The default value is ten seconds.
-qm <qm>This flag allows the user to specify which WebSphere MQ queue manager to connect to.
-i <queue>This flag allows the user to specify the name of the queue, in the specified queue manager, to which MQJavaRoundTrip will put its requests.
-o <queue>This flag allows the user to specify the name of the queue, in the specified queue manager, from which MQJavaRoundTrip will wait for replies.
-b This flag allows the user to specify whether to connect to the queue manager through local bindings (the default is via TCP/IP "client connections"). This gives faster results but is only applicable if the client is on the same hardware as the queue manager.
-tThis flag allows the user to specify whether the binding connection being used is to be trusted, also known as fastpath bindings. This option will increase the performance at the cost of reduced safety checking. It is not usually recommended for a production system but may help with load generation from this performance testing client.
-h <hostname>This flag allows the user to specify the name/IP address of the machine which is hosting the queue manager. This is only relevant for client connections. N.B. If the -b flag is specified, all client connection settings are ignored.
-c <channel>This flag allows the user to specify the channel to be used when connecting to the queue manager (the default is SYSTEM.DEF.SVRCONN). This is only relevant for client connections. N.B. If the -b flag is specified all client connection settings are ignored.
-p <port>This flag allows the user to specify which port to use when connecting to the queue manager (the default is 1414). This is only relevant for client connections. N.B. If the -b flag is specified all client connection settings are ignored.
-f <file>This flag allows the user to specify the full path of the file to be used as the basis of the request message. This should be in the format of x:\temp\filename.msg
-xThis flag allows the user to specify that messages should be put and got transactionally (the default is to send non-transactionally). If transactional, the client loop will be: put, commit, get, commit.
-sThis flag allows the user to specify that sent messages should be persistent (the default is to send non-persistent.
-mc <ccsid>This flag allows the user to explicitly specify which character set identifier (CCSID) is set on sent messages (the default is to use the CCSID of the queue manager). See the WebSphere MQ "Using Java" manual for details if this applies to your scenario.
-me <message encoding>This flag allows the user to specify which representation should be used for numeric values within the message data. See the WebSphere MQ "Using Java" manual for details if this applies to your scenario.
-mf <format>format> This flag allows the user to specify to the receiving application (the application reading message from the input Queue) the nature of the data within the message. Typical examples are MQRFH2, MQSTR or XML. See the WebSphere MQ "Using Java" manual for details if this applies to your scenario.
-idThis flag informs the tool that replies will have their correlation-id set to the message-id of the request message. In order for this to work the server process under test must adhere to the same policy (i.e. it must copy the correlation-id into place from the message-id). The default is not do anything with correlation identifiers.
-gidThis flag informs the tool to generate a correlation-id for each thread and specify it in the request message. Reply messages must then have the same correlation-id. In order for this to work the server process under test must adhere to the same policy (that is, it must duplicate the correlation-id of the request message).
-wThis flag allows the user to specify how long the tool should wait for a reply to the message it originally put in seconds. If the application being tested is likely to take 10 seconds to process a single message the wait time should be specified as ~10 seconds. (the default is 5 seconds).

An example of how to use MQJavaRoundTrip:

java MQJavaRoundTrip -n 10 -d 60 -qm TEST_QM -i IN.QUEUE -o OUT.QUEUE -h 127.0.0.1 -c JAVA.CHANNEL -p 1414 -f inputmessage.xml -x -s -id

This will run for 60 seconds with 10 threads connecting via TCP/IP port 1414 to TEST_QM (hosted on 127.0.0.1). They will put persistent, transacted messages onto IN.QUEUE and wait for replies from OUT.QUEUE. They are expecting those replies to have a correlation-id matching the message-id of the request.


Code

MQJavaRoundTrip consists of two classes. The first "MQJavaRoundTrip" is the "main" class and such contains the main method required for executing a Java application. This class contains all of the code for setting up the connections to the queues and queue manager etc. The second class ClientThread is instantiated by the MQJavaRoundTrip class x number of times where x is the number of threads specified by the user. It is then the individual instances which do the actual putting and getting to the queues.


MQJavaRoundTrip (main class)
import com.ibm.mq.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Iterator;

public class MQJavaRoundTrip extends Thread {

	private static MQJavaRoundTrip instance = null;
	private boolean shutdown = false;
	private final ArrayList workers = new ArrayList();
	private Thread stats = null;
	final Properties arguments = new Properties();
	private byte[] inputFileBytes = null;
	private final java.text.NumberFormat numberFormat =
		java.text.NumberFormat.getInstance();
	boolean verbose = true;

	private MQJavaRoundTrip() {
		super("MQJavaRoundTrip");
		numberFormat.setMinimumFractionDigits(2);
		numberFormat.setMaximumFractionDigits(2);
		numberFormat.setGroupingUsed(false);
	}

	public static MQJavaRoundTrip getInstance() {
		if (instance == null) {
			instance = new MQJavaRoundTrip();
		}
		return instance;
	}

	void signalShutdown() {
		shutdown = true;
		interrupt();
	}

	public static void main(String args[]) {
		getInstance().parseArguments(args);
		getInstance().start();
	}

	public void run() {

		try {

			{
				if ( verbose ) System.out.println("Testing settings");
				MQQueueManager qm = getQueueManagerConnection();
				if ( verbose ) System.out.println("Connection to QM OK");
				MQQueue putQueue =
					qm.accessQueue(
						arguments.getProperty("i"),
						MQC.MQOO_OUTPUT
							| MQC.MQOO_INQUIRE
							| MQC.MQOO_FAIL_IF_QUIESCING);
				MQQueue getQueue =
					qm.accessQueue(
						arguments.getProperty("o"),
						MQC.MQOO_INPUT_SHARED
							| MQC.MQOO_INQUIRE
							| MQC.MQOO_FAIL_IF_QUIESCING);
				if ( verbose ) System.out.println("Connection to Queues OK");

				getQueue.close();
				putQueue.close();
				qm.disconnect();
			}

			readDataFromFile();

			createClientThreads();

			startStatisticsThread();

			startClientThreads();

			// Wait for the end fo the test
			int duration = Integer.parseInt(arguments.getProperty("d")) * 1000;
			if (duration <= 0) {
				((Thread) workers.get(0)).join();
			} else {
				Thread.sleep(duration);
			}

		} catch (InterruptedException e) {
			// No-op
		} catch (Throwable e) {
			// Display all other errors
			System.out.println(e);
			e.printStackTrace();
		} finally {
			shutdown = true;

			if ( verbose ) System.out.println("Instructing threads to stop");
			if (stats != null)
				stats.interrupt();
			// signal workers to die ....
			Iterator iter = workers.iterator();
			while (iter.hasNext()) {
				ClientThread worker = (ClientThread) iter.next();
				worker.shutdown = true;
				worker.interrupt(); // wake them if they are waiting
			} // end while workers

			if ( verbose ) System.out.println("Waiting for threads");
			iter = workers.iterator();
			try {
				while (iter.hasNext())
					 ((Thread) iter.next()).join();
			} catch (InterruptedException e) {}

			// Collect overall message rates
			iter = workers.iterator();
			double rate = 0;
			while (iter.hasNext()) {
				ClientThread worker = (ClientThread) iter.next();
				rate += (double) (worker.numberOfMessages * 1000)
					/ worker.runlength;
				worker.interrupt(); // wake them if they are waiting
			} // end while workers
			System.out.println(
				"Total rt/sec=" + numberFormat.format(rate));

		} // end try/catch/finally
	} // end run()

	private void startClientThreads() throws Exception {
		Iterator iter = workers.iterator();
		while (iter.hasNext()) {
			ClientThread worker = (ClientThread) iter.next();
			Thread.sleep(250 + (int) (Math.random() * 500));
			worker.start();
		} // end while
	} // end startClientThreads

	MQQueueManager getQueueManagerConnection() throws MQException {

		int connectionoptions = MQC.MQCNO_NONE;

		boolean bindings = arguments.getProperty("b") != null;
		if (bindings) {
			boolean fastpath = arguments.getProperty("f") != null;
			if (fastpath) {
				connectionoptions = MQC.MQCNO_FASTPATH_BINDING;
			} else {
				connectionoptions = MQC.MQCNO_STANDARD_BINDING;
			} // End elseif fastpath bindings
		} else { // End if bindings
			// if client connections
			MQEnvironment.hostname = arguments.getProperty("h");
			MQEnvironment.channel = arguments.getProperty("c");
			MQEnvironment.port = Integer.parseInt(arguments.getProperty("p"));
		}

		return new MQQueueManager(
			arguments.getProperty("qm"),
			connectionoptions);

	} // End getQueueManagerConnection

	private void createClientThreads() throws Exception {

		int nThreads = Integer.parseInt(arguments.getProperty("n"));

		for (int i = 1; i <= nThreads; i++) {

			String name = "Client" + i;
			if (arguments.getProperty("gid") != null) {
				byte addr[] = java.net.InetAddress.getLocalHost().getAddress();
				byte bytes[] = new byte[24];
				System.arraycopy(addr, 0, bytes, 0, addr.length);
				bytes[20] = (byte) i;
				bytes[21] = (byte) (i>> 8);
				bytes[22] = (byte) (i >> 16);
				bytes[23] = (byte) (i >> 24);

				workers.add(new ClientThread(name, bytes));
			} else {
				workers.add(new ClientThread(name));
			}

		} // end foreach thread
	} // end createClientThreads

	private void readDataFromFile() throws Exception {

		File theFileToRead = new File(arguments.getProperty("f"));
		inputFileBytes = new byte[(int) theFileToRead.length()];

		BufferedInputStream bIS =
			new BufferedInputStream(new FileInputStream(theFileToRead));
		bIS.read(inputFileBytes);
		bIS.close();

	} // End readDataFromFile

	// Create a new copy of the message
	MQMessage createMessage() throws Exception {

		MQMessage putMessage = new MQMessage();
		if (arguments.getProperty("mc") != null)
			putMessage.characterSet =
				Integer.parseInt(arguments.getProperty("mc"));
		if (arguments.getProperty("me") != null)
			putMessage.encoding = Integer.parseInt(arguments.getProperty("me"));
		if (arguments.getProperty("mf") != null)
			putMessage.format = arguments.getProperty("mf");
		putMessage.messageFlags = MQC.MQMT_REQUEST;
		if (arguments.getProperty("s") != null) {
			putMessage.persistence = MQC.MQPER_PERSISTENT;
		} else {
			putMessage.persistence = MQC.MQPER_NOT_PERSISTENT;
		}

		putMessage.write(inputFileBytes);

		return putMessage;
	} // end createMessage

	private void parseArguments(String[] args) {

		String currentkey = null;
		String currentvalue = "";
		arguments.setProperty("c", "SYSTEM.DEF.SVRCONN");
		arguments.setProperty("p", "1414");
		arguments.setProperty("n", "1");
		arguments.setProperty("d", "60");
		arguments.setProperty("w", "5");

		if (args.length == 0)
			printUsage();

		for (int i = 0; i < args.length; i++) {
			if (args[i].startsWith("-")) {
				if (currentkey != null) {
					arguments.setProperty(currentkey, currentvalue);
				}
				currentkey = args[i].substring(1);
				currentvalue = "true";
			} else if (currentvalue.equals("true")) {
				currentvalue = args[i];
			}
		} // end for
		if (currentkey != null)
			arguments.setProperty(currentkey, currentvalue);

		if ( arguments.getProperty("z")!=null ) verbose = false;

	} // end parseArguments

	private void printUsage() {
		System.out.println(
			"usage: java " + this.getClass().getName() + " <args;>");

		System.out.println(" Controller properties:");
		System.out.println(" -n <clients>     (parallel threads)");
		System.out.println(" -d <duration>    (in seconds - 0=never stop)");
		System.out.println(" -z               (quiet, minimal output)");
		System.out.println(" -v <interval>    (statistics interval)");		

		System.out.println(" Queue manager properties:");
		System.out.println(" -qm <qm>          (queue manager name)");
		System.out.println(" -i <queue>       (put requests to)");
		System.out.println(" -o <queue>       (get replies from)");

		System.out.println(" Connection properties for Bindings :");
		System.out.println(" -b               (use local bindings connection)");
		System.out.println(
			" -t               (use trusted/fastpath bindings, must use -b too)");

		System.out.println(" Connection properties for TCP/IP client :");
		System.out.println(" -h <hostname>    (QM machine)");
		System.out.println(
			" -c <channel>
			     (QM svrconn - defaults to SYSTEM.DEF.SVRCONN)");
		System.out.println(
			" -p <port>        (QM listener port - defaults to 1414)");

		System.out.println(" Message properties:");
		System.out.println(" -f <file>        (user data to send)");
		System.out.println(
			" -x               (use transactions one-per-message)");
		System.out.println(" -s               (use persistent messages)");
		System.out.println(" -mc              (message character set)");
		System.out.println(" -me              (message encoding)");
		System.out.println(" -mf              (message format)");
		System.out.println(
			" -id              (use get-correllation-id from sent-mesg-id)");
		System.out.println(
			" -gid             (fixed correllation id per thread)");
		System.out.println(
			" -w <timeout>     (message wait timeout in seconds)");

		System.exit(0);
	} // end printUsage

	private final void startStatisticsThread() throws Throwable {

		stats = new Thread("Stats") {
			private int prev[];
			private int curr[] = null;
			private void getValues() {
				// Get a snapshot of current "total messages"
				prev = curr;
				curr = new int[workers.size()];
				int i = 0;
				Iterator iter = workers.iterator();
				while (iter.hasNext() && i < curr.length) {
					ClientThread worker = (ClientThread) iter.next();
					curr[i++] = worker.numberOfMessages;
				}
			}
			public void run() {
				int diff;
				int total;
				final int interval = Integer.parseInt( arguments.getProperty("v") );
				final StringBuffer sb = new StringBuffer();

				getValues();

				while (!shutdown) {

					sb.setLength(0);
					try {
						Thread.sleep(interval * 1000);
						getValues();
						total = 0;
						// Calculate difference from last snapshot
						for (int j = 0; j < curr.length; j++) {
							diff = curr[j] - prev[j];
							total += diff;
						}
						sb.append("rt/sec=").append(
							numberFormat.format((double)
							     total / interval));

						System.out.println(sb);

					} catch (InterruptedException e) {}

				} // end while
			} // end run
		}; // end inner stats class
		stats.setDaemon(true);
		stats.start();
		
	} // end startstatisticsthread

} // End of file


MQJavaRoundTrip (ClientThread class)
import java.util.Date;

import com.ibm.mq.*;
//import com.ibm.mq.jms.services.ConfigEnvironment;

public class ClientThread extends Thread {

	private byte[] fixedCorrelId = null;
	private final static MQJavaRoundTrip parent = 
	    MQJavaRoundTrip.getInstance();
	int numberOfMessages = 0;
	boolean shutdown = false;
	long runlength = 0;

	public ClientThread(String name) {
		super(name);
	}

	public ClientThread(String name, byte[] correlId) {
		super(name);
		this.fixedCorrelId = correlId;
	}

	public void run() {

		MQQueueManager queueManager = null;
		MQQueue putQueue = null;
		MQQueue getQueue = null;

		if ( parent.verbose ) System.out.println(getName() + " : START");
		boolean transacted = parent.arguments.getProperty("x") != null;
		boolean useCorrelId =
			(parent.arguments.getProperty("id") != null)
				|| (fixedCorrelId != null);
		boolean copyCorrelId =
			(parent.arguments.getProperty("id") != null)
				&& (fixedCorrelId == null);

		// SETUP MESSAGES AND OPTIONS			
		MQPutMessageOptions pmo = new MQPutMessageOptions();
		MQGetMessageOptions gmo = new MQGetMessageOptions();

		gmo.waitInterval = 
			Integer.parseInt(parent.arguments.getProperty("w")) * 1000;
		gmo.matchOptions =
			useCorrelId ? MQC.MQMO_MATCH_CORREL_ID : MQC.MQMO_NONE;
		gmo.options = MQC.MQGMO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING;
		gmo.options |= transacted
			? MQC.MQGMO_SYNCPOINT
			: MQC.MQGMO_NO_SYNCPOINT;

		pmo.options = 
		    MQC.MQPMO_FAIL_IF_QUIESCING | MQC.MQPMO_NEW_MSG_ID;
		pmo.options |= transacted
			? MQC.MQPMO_SYNCPOINT
			: MQC.MQPMO_NO_SYNCPOINT;

		long startTime = 0;

		try {

			MQMessage outMessage = parent.createMessage();
			MQMessage inMessage = new MQMessage();

			if (fixedCorrelId != null) {
				outMessage.correlationId = fixedCorrelId;
				inMessage.correlationId = fixedCorrelId;
			}

			// Make connections to WMQ resources 
			queueManager = parent.getQueueManagerConnection();
			putQueue =
				queueManager.accessQueue(
					parent.arguments.getProperty("i"),
					MQC.MQOO_OUTPUT | MQC.MQOO_FAIL_IF_QUIESCING);
			getQueue =
				queueManager.accessQueue(
					parent.arguments.getProperty("o"),
					MQC.MQOO_INPUT_SHARED | MQC.MQOO_FAIL_IF_
					    QUIESCING);
			if ( parent.verbose ) System.out.println(getName() + ": connected");

			startTime = new Date().getTime();
			while (!shutdown) {

				
 {
					putQueue.put(outMessage, pmo);
					if (transacted) queueManager.commit();
					if (copyCorrelId) inMessage.correlationId = 
					    outMessage.messageId;
					getQueue.get(inMessage, gmo);
					if (transacted) queueManager.commit();
					numberOfMessages++;
				} catch (MQException e) {
					if (e.reasonCode == 
					    MQException.MQRC_NO_MSG_AVAILABLE)
						System.err.println(
							getName()
							     + " : Cannot see a response to message "
							+outMessage.messageId);
					throw e;
				} // End try catch

			} // End while ! shutdown
			
		} catch (Throwable e) {
			// Handle a fatal error
			System.err.println(
				getName() + " : Fatal Error.  Exception follows: \n" + e);
			parent.signalShutdown();
	
		} finally {
			// Clear up code carefully in fair weather or foul.
			runlength = new Date().getTime() - startTime;
			if (getQueue != null) {
				if ( parent.verbose ) System.out.println(
					getName() + " : Closing queue " + getQueue.name);
				try {
					getQueue.close();
				} catch (MQException e) {} finally {
					getQueue = null;
				}
			}
			if (putQueue != null) {
				if ( parent.verbose ) System.out.println(
					getName() + " : Closing queue " + putQueue.name);
				try {
					putQueue.close();
				} catch (MQException e) {} finally {
					putQueue = null;
				}
			}
			if (queueManager != null) {
				if ( parent.verbose ) System.out.println(
					getName()
						+ " : Closing queue manager "
						+ queueManager.name);
				try {
					queueManager.disconnect();
				} catch (MQException e) {} finally {
					queueManager = null;
				}
			}
			if ( parent.verbose ) System.out.println(getName() + " : STOP");
		} // End try/catch/finally
	} // End run method
}


Conclusion

This program is an excellent starting place for investigating the potential throughput of WebSphere MQ applications that move messages from one queue to another. Take care that the settings of this tool do match the scenario you are expecting. Incorrectly specifying message persistence, bindings connections or suchlike can give markedly different performance, both higher or lower.



Downloads

NameSizeDownload method
clientthread.zip2KBFTP|HTTP
mqjavaroundtrip.zip4KBFTP|HTTP

Information about download methods


About the authors

Kevin Braithwaite photo.

Kevin Braithwaite is a Performance Specialist with the WebSphere Business Integration Message Broker performance team in IBM Hursley. Kevin works with development in evaluating new releases of WebSphere Business Integration Message Broker, and with customers to provide consultancy on design, configuration and tuning issues relating to this product. You can contact Kevin at: braithwa@uk.ibm.com .

Marc Carter is a Performance Specialist with the WebSphere MQ JMS performance team in IBM Hursley. Marc works with development in evaluating new releases of WebSphere MQ and with customers to provide consultancy on design, configuration and tuning issues relating to this product.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=14532
ArticleTitle=Simplifying performance and stress testing with MQJavaRoundTrip
publish-date=07142004
author1-email=braithwa@uk.ibm.com
author1-email-cc=Copy email address
author2-email=mcarter@uk.ibm.com
author2-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers