001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.net.core;
005:
006: import com.tc.bytes.TCByteBuffer;
007: import com.tc.bytes.TCByteBufferFactory;
008: import com.tc.net.TCSocketAddress;
009: import com.tc.net.protocol.GenericNetworkMessage;
010: import com.tc.net.protocol.GenericNetworkMessageSink;
011: import com.tc.net.protocol.GenericProtocolAdaptor;
012: import com.tc.util.runtime.Os;
013:
014: import java.util.Arrays;
015:
016: import junit.framework.TestCase;
017:
018: /**
019: * @author teck
020: */
021: public class MessageLatencyTest extends TestCase {
022: private static final int NUM_MSGS = 10000;
023: private static final double PERCENTILE = 95;
024:
025: private TCConnectionManager connMgr;
026: private SimpleServer server;
027: private final Object lock = new Object();
028: private final RecordTimeSink serversink = new RecordTimeSink(true);
029: private final RecordTimeSink clientsink = new RecordTimeSink(false);
030:
031: protected void setUp() throws Exception {
032: connMgr = new TCConnectionManagerJDK14();
033: server = new SimpleServer(serversink);
034: server.start();
035: }
036:
037: protected void tearDown() throws Exception {
038: connMgr.shutdown();
039: server.stop();
040: }
041:
042: public static void main(String args[]) throws Exception {
043: MessageLatencyTest test = new MessageLatencyTest();
044: test.setUp();
045: test.testLatency();
046: test.tearDown();
047: }
048:
049: public void testLatency() throws Exception {
050: final TCConnection conn = connMgr
051: .createConnection(new GenericProtocolAdaptor(clientsink));
052: conn.connect(new TCSocketAddress(server.getServerAddr()
053: .getPort()), 3000);
054:
055: for (int i = 0; i < NUM_MSGS; i++) {
056: TCByteBuffer data = TCByteBufferFactory.getInstance(false,
057: 8);
058:
059: final long sent = System.currentTimeMillis();
060: data.putLong(sent);
061: data.position(0);
062:
063: final GenericNetworkMessage msg = new GenericNetworkMessage(
064: conn, data);
065:
066: synchronized (lock) {
067: conn.putMessage(msg);
068: lock.wait();
069: }
070: }
071:
072: Arrays.sort(serversink.recvTimes);
073: Arrays.sort(clientsink.recvTimes);
074:
075: final int withinPercentile = (int) (NUM_MSGS * (PERCENTILE / 100));
076:
077: long serversum = 0;
078: for (int i = 0; i < withinPercentile; i++) {
079: serversum += serversink.recvTimes[i];
080: }
081:
082: long clientsum = 0;
083: for (int i = 0; i < withinPercentile; i++) {
084: clientsum += clientsink.recvTimes[i];
085: }
086:
087: // Account for System.currentTimeMillis() resolution suckage on windows
088: final double benchmark = Os.isWindows() ? 2.0 : 1.0;
089: final double serveravg = ((double) serversum / (double) withinPercentile);
090: final double clientavg = ((double) clientsum / (double) withinPercentile);
091:
092: System.out.println("Client->Server Average Latency: "
093: + serveravg + " milliseconds");
094: System.out.println("Server->Client Average Latency: "
095: + clientavg + " milliseconds");
096:
097: assertTrue(
098: "Server Avergage latency is not in acceptable range ("
099: + serveravg + " > " + benchmark + ")",
100: (serveravg <= benchmark));
101: assertTrue(
102: "Client Avergage latency is not in acceptable range ("
103: + clientavg + " > " + benchmark + ")",
104: (clientavg <= benchmark));
105: }
106:
107: class RecordTimeSink implements GenericNetworkMessageSink {
108: final boolean respond;
109: int ctr = 0;
110: long recvTimes[] = new long[NUM_MSGS];
111:
112: RecordTimeSink(boolean respond) {
113: this .respond = respond;
114: }
115:
116: public void putMessage(GenericNetworkMessage msg) {
117: long recvTime = System.currentTimeMillis();
118: long sentTime = msg.getPayload()[0].getLong();
119:
120: long diff = recvTime - sentTime;
121:
122: if ((ctr % 100) == 0) {
123: System.out.println("Latency was " + diff
124: + " milliseconds");
125: }
126:
127: recvTimes[ctr++] = diff;
128:
129: TCByteBuffer data = TCByteBufferFactory.getInstance(false,
130: 8);
131:
132: final long sent = System.currentTimeMillis();
133: data.putLong(sent);
134: data.position(0);
135:
136: if (respond) {
137: final GenericNetworkMessage response = new GenericNetworkMessage(
138: msg.getSource(), data);
139: msg.getSource().putMessage(response);
140: } else {
141: synchronized (lock) {
142: lock.notify();
143: }
144: }
145: }
146: }
147:
148: }
|