/**
*
* Copyright 2004 Hiram Chirino
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**/
package org.activemq.store.journal;
import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import junit.framework.TestCase;
import org.activemq.ActiveMQConnectionFactory;
import org.activemq.broker.impl.BrokerContainerImpl;
import org.activemq.message.ActiveMQQueue;
import EDU.oswego.cs.dl.util.concurrent.Callable;
import EDU.oswego.cs.dl.util.concurrent.Latch;
import EDU.oswego.cs.dl.util.concurrent.Semaphore;
/**
* Benchmarks the Journal Store by using an embeded broker to add and remove messages from
* the store.
*
* Make sure you run with jvm option -server (makes a big difference).
* The tests simulate storing 1000 1k jms messages to see the rate of
* processing msg/sec.
*
* @version $Revision: 1.1 $
*/
public class JournalBrokerBenchmark extends TestCase {
private static final int MESSAGE_COUNT = Integer.parseInt(System.getProperty("MESSAGE_COUNT","10000"));
private BrokerContainerImpl broker;
private ActiveMQQueue dest;
private ActiveMQConnectionFactory connectionFactory;
public static void main(String[] args) {
junit.textui.TestRunner.run(JournalBrokerBenchmark.class);
}
protected void setUp() throws Exception {
broker = new BrokerContainerImpl("localhost");
broker.addConnector("tcp://localhost:61616");
broker.start();
connectionFactory = new ActiveMQConnectionFactory(broker, "tcp://localhost:61616");
// connectionFactory.setTurboBoost(true);
// connectionFactory.setCachingEnabled(false);
// connectionFactory.setCopyMessageOnSend(true);
dest = new ActiveMQQueue("TEST");
}
protected void tearDown() throws Exception {
broker.stop();
}
static class ProgressPrinter {
private final int total;
private final int interval;
int percentDone=0;
int counter=0;
public ProgressPrinter(int total, int interval) {
this.total=total;
this.interval = interval;
}
synchronized public void increment() {
update(++counter);
}
synchronized public void update(int current) {
int at = 100*current/total;
if( (percentDone/interval) != (at/interval) ) {
percentDone=at;
System.out.println("Completed: "+percentDone+"%");
}
}
}
/**
* Moves about 6000 msg/sec on a Win XP 3.2 ghz Intel Machine.
*
* @throws Throwable
*/
public void testConcurrentSendReceive() throws Throwable {
final int PRODUCER_COUNT=Integer.parseInt(System.getProperty("PRODUCER_COUNT","10"));
final int CONSUMER_COUNT=Integer.parseInt(System.getProperty("CONSUMER_COUNT","10"));
final ProgressPrinter pp = new ProgressPrinter(MESSAGE_COUNT*2, 5);
final Semaphore connectionsEstablished = new Semaphore(1-(CONSUMER_COUNT+PRODUCER_COUNT));
final Latch startTest = new Latch();
final Semaphore testsFinished = new Semaphore(1-(CONSUMER_COUNT+PRODUCER_COUNT));
final Callable producer = new Callable() {
public Object call() throws JMSException, InterruptedException {
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(dest);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
BytesMessage message = session.createBytesMessage();
message.writeBytes(new byte[1024]);
connection.start();
connectionsEstablished.release();
startTest.acquire();
final int msgs = (MESSAGE_COUNT/PRODUCER_COUNT)+1;
for (int i = 0; i < msgs; i++) {
pp.increment();
producer.send(message);
}
testsFinished.release();
connection.close();
return null;
}
};
final Callable consumer = new Callable() {
public Object call() throws JMSException, InterruptedException {
final Latch doneLatch = new Latch();
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer consumer = session.createConsumer(dest);
connectionsEstablished.release();
startTest.acquire();
final int msgs = (MESSAGE_COUNT/CONSUMER_COUNT)-1;
consumer.setMessageListener(new MessageListener(){
int counter=0;
public void onMessage(Message msg) {
pp.increment();
counter++;
if( counter >= msgs ) {
doneLatch.release();
}
}
});
connection.start();
doneLatch.acquire();
testsFinished.release();
connection.close();
return null;
}
};
final Throwable workerError[] = new Throwable[1];
for( int i=0; i < PRODUCER_COUNT; i++ ) {
new Thread("Producer:"+i) {
public void run() {
try {
producer.call();
} catch (Throwable e) {
e.printStackTrace();
workerError[0] = e;
}
}
}.start();
}
for( int i=0; i < CONSUMER_COUNT; i++ ) {
new Thread("Consumer:"+i) {
public void run() {
try {
consumer.call();
} catch (Throwable e) {
workerError[0] = e;
}
}
}.start();
}
connectionsEstablished.acquire();
// System.out.println("ready.");
// System.in.read();System.in.read();
startTest.release();
long start = System.currentTimeMillis();
testsFinished.acquire();
long end = System.currentTimeMillis();
System.out.println(getName() + ": test duration: " + (end - start) + " ms, published+acked msg/s: "
+ (MESSAGE_COUNT * 1000f / (end - start)));
// System.out.println("ready.");
// System.in.read();System.in.read();
if( workerError[0] != null )
throw workerError[0];
}
}