tom

Corrected some IO loop tests.

...@@ -7,6 +7,7 @@ import java.io.IOException; ...@@ -7,6 +7,7 @@ import java.io.IOException;
7 import java.nio.channels.Selector; 7 import java.nio.channels.Selector;
8 8
9 import static com.google.common.base.Preconditions.checkArgument; 9 import static com.google.common.base.Preconditions.checkArgument;
10 +import static java.lang.System.currentTimeMillis;
10 11
11 /** 12 /**
12 * Abstraction of an I/O processing loop based on an NIO selector. 13 * Abstraction of an I/O processing loop based on an NIO selector.
...@@ -118,4 +119,41 @@ public abstract class SelectorLoop implements Runnable { ...@@ -118,4 +119,41 @@ public abstract class SelectorLoop implements Runnable {
118 notifyAll(); 119 notifyAll();
119 } 120 }
120 121
122 + /**
123 + * Waits for the loop execution to start.
124 + *
125 + * @param timeout number of milliseconds to wait
126 + * @return true if loop started in time
127 + */
128 + public final synchronized boolean awaitStart(long timeout) {
129 + long max = currentTimeMillis() + timeout;
130 + while (state != State.STARTED && (currentTimeMillis() < max)) {
131 + try {
132 + wait(timeout);
133 + } catch (InterruptedException e) {
134 + throw new RuntimeException("Interrupted", e);
135 + }
136 + }
137 + return state == State.STARTED;
138 + }
139 +
140 + /**
141 + * Waits for the loop execution to stop.
142 + *
143 + * @param timeout number of milliseconds to wait
144 + * @return true if loop finished in time
145 + */
146 + public final synchronized boolean awaitStop(long timeout) {
147 + long max = currentTimeMillis() + timeout;
148 + while (state != State.STOPPED && (currentTimeMillis() < max)) {
149 + try {
150 + wait(timeout);
151 + } catch (InterruptedException e) {
152 + throw new RuntimeException("Interrupted", e);
153 + }
154 + }
155 + return state == State.STOPPED;
156 + }
157 +
158 +
121 } 159 }
......
1 package org.onlab.nio; 1 package org.onlab.nio;
2 2
3 import org.junit.Before; 3 import org.junit.Before;
4 -import org.junit.Ignore;
5 import org.junit.Test; 4 import org.junit.Test;
6 5
7 import java.net.InetAddress; 6 import java.net.InetAddress;
8 -import java.text.DecimalFormat;
9 import java.util.Random; 7 import java.util.Random;
8 +import java.util.logging.Level;
9 +import java.util.logging.Logger;
10 10
11 import static org.onlab.junit.TestTools.delay; 11 import static org.onlab.junit.TestTools.delay;
12 12
...@@ -15,55 +15,51 @@ import static org.onlab.junit.TestTools.delay; ...@@ -15,55 +15,51 @@ import static org.onlab.junit.TestTools.delay;
15 */ 15 */
16 public class IOLoopIntegrationTest { 16 public class IOLoopIntegrationTest {
17 17
18 - private static final int MILLION = 1000000;
19 - private static final int TIMEOUT = 60;
20 -
21 private static final int THREADS = 6; 18 private static final int THREADS = 6;
22 - private static final int MSG_COUNT = 20 * MILLION; 19 + private static final int TIMEOUT = 60;
23 - private static final int MSG_SIZE = 128; 20 + private static final int MESSAGE_LENGTH = 128;
24 21
25 - private static final long MIN_MPS = 10 * MILLION; 22 + private static final int MILLION = 1000000;
23 + private static final int MSG_COUNT = 40 * MILLION;
26 24
27 @Before 25 @Before
28 public void warmUp() throws Exception { 26 public void warmUp() throws Exception {
27 + Logger.getLogger("").setLevel(Level.SEVERE);
29 try { 28 try {
30 - run(MILLION, MSG_SIZE, 15, 0); 29 + runTest(MILLION, MESSAGE_LENGTH, 15);
31 } catch (Throwable e) { 30 } catch (Throwable e) {
32 System.err.println("Failed warmup but moving on."); 31 System.err.println("Failed warmup but moving on.");
33 e.printStackTrace(); 32 e.printStackTrace();
34 } 33 }
35 } 34 }
36 35
37 - @Ignore 36 +
38 @Test 37 @Test
39 public void basic() throws Exception { 38 public void basic() throws Exception {
40 - run(MSG_COUNT, MSG_SIZE, TIMEOUT, MIN_MPS); 39 + runTest(MILLION, MESSAGE_LENGTH, TIMEOUT);
41 } 40 }
42 41
42 + public void longHaul() throws Exception {
43 + runTest(MSG_COUNT, MESSAGE_LENGTH, TIMEOUT);
44 + }
43 45
44 - private void run(int count, int size, int timeout, double mps) throws Exception { 46 + private void runTest(int count, int size, int timeout) throws Exception {
45 - DecimalFormat f = new DecimalFormat("#,##0"); 47 + // Use a random port to prevent conflicts.
46 - System.out.print(f.format(count * THREADS) + 48 + int port = IOLoopTestServer.PORT + new Random().nextInt(100);
47 - (mps > 0.0 ? " messages: " : " message warm-up: "));
48 -
49 - // Setup the test on a random port to avoid intermittent test failures
50 - // due to the port being already bound.
51 - int port = IOLoopServer.PORT + new Random().nextInt(100);
52 49
53 InetAddress ip = InetAddress.getLoopbackAddress(); 50 InetAddress ip = InetAddress.getLoopbackAddress();
54 - IOLoopServer sss = new IOLoopServer(ip, THREADS, size, port); 51 + IOLoopTestServer server = new IOLoopTestServer(ip, THREADS, size, port);
55 - IOLoopClient ssc = new IOLoopClient(ip, THREADS, count, size, port); 52 + IOLoopTestClient client = new IOLoopTestClient(ip, THREADS, count, size, port);
56 53
57 - sss.start(); 54 + server.start();
58 - ssc.start(); 55 + client.start();
59 - delay(250); // give the server and client a chance to go 56 + delay(100); // Pause to allow loops to get going
60 57
61 - ssc.await(timeout); 58 + client.await(timeout);
62 - ssc.report(); 59 + client.report();
63 60
64 - delay(1000); 61 + server.stop();
65 - sss.stop(); 62 + server.report();
66 - sss.report();
67 } 63 }
68 64
69 } 65 }
......
...@@ -22,15 +22,18 @@ import java.util.concurrent.Semaphore; ...@@ -22,15 +22,18 @@ import java.util.concurrent.Semaphore;
22 import java.util.concurrent.TimeUnit; 22 import java.util.concurrent.TimeUnit;
23 import java.util.concurrent.TimeoutException; 23 import java.util.concurrent.TimeoutException;
24 24
25 +import static java.lang.String.format;
26 +import static java.lang.System.out;
25 import static org.onlab.junit.TestTools.delay; 27 import static org.onlab.junit.TestTools.delay;
28 +import static org.onlab.nio.IOLoopTestServer.PORT;
26 import static org.onlab.util.Tools.namedThreads; 29 import static org.onlab.util.Tools.namedThreads;
27 30
28 /** 31 /**
29 * Auxiliary test fixture to measure speed of NIO-based channels. 32 * Auxiliary test fixture to measure speed of NIO-based channels.
30 */ 33 */
31 -public class IOLoopClient { 34 +public class IOLoopTestClient {
32 35
33 - private static Logger log = LoggerFactory.getLogger(IOLoopClient.class); 36 + private static Logger log = LoggerFactory.getLogger(IOLoopTestClient.class);
34 37
35 private final InetAddress ip; 38 private final InetAddress ip;
36 private final int port; 39 private final int port;
...@@ -55,6 +58,18 @@ public class IOLoopClient { ...@@ -55,6 +58,18 @@ public class IOLoopClient {
55 */ 58 */
56 public static void main(String[] args) 59 public static void main(String[] args)
57 throws IOException, InterruptedException, ExecutionException, TimeoutException { 60 throws IOException, InterruptedException, ExecutionException, TimeoutException {
61 + startStandalone(args);
62 +
63 + System.exit(0);
64 + }
65 +
66 + /**
67 + * Starts a standalone IO loop test client.
68 + *
69 + * @param args command-line arguments
70 + */
71 + public static void startStandalone(String[] args)
72 + throws IOException, InterruptedException, ExecutionException, TimeoutException {
58 InetAddress ip = InetAddress.getByName(args.length > 0 ? args[0] : "127.0.0.1"); 73 InetAddress ip = InetAddress.getByName(args.length > 0 ? args[0] : "127.0.0.1");
59 int wc = args.length > 1 ? Integer.parseInt(args[1]) : 6; 74 int wc = args.length > 1 ? Integer.parseInt(args[1]) : 6;
60 int mc = args.length > 2 ? Integer.parseInt(args[2]) : 50 * 1000000; 75 int mc = args.length > 2 ? Integer.parseInt(args[2]) : 50 * 1000000;
...@@ -63,15 +78,13 @@ public class IOLoopClient { ...@@ -63,15 +78,13 @@ public class IOLoopClient {
63 78
64 log.info("Setting up client with {} workers sending {} {}-byte messages to {} server... ", 79 log.info("Setting up client with {} workers sending {} {}-byte messages to {} server... ",
65 wc, mc, ml, ip); 80 wc, mc, ml, ip);
66 - IOLoopClient sc = new IOLoopClient(ip, wc, mc, ml, IOLoopServer.PORT); 81 + IOLoopTestClient client = new IOLoopTestClient(ip, wc, mc, ml, PORT);
67 82
68 - sc.start(); 83 + client.start();
69 delay(2000); 84 delay(2000);
70 85
71 - sc.await(to); 86 + client.await(to);
72 - sc.report(); 87 + client.report();
73 -
74 - System.exit(0);
75 } 88 }
76 89
77 /** 90 /**
...@@ -84,7 +97,7 @@ public class IOLoopClient { ...@@ -84,7 +97,7 @@ public class IOLoopClient {
84 * @param port socket port 97 * @param port socket port
85 * @throws IOException if unable to create IO loops 98 * @throws IOException if unable to create IO loops
86 */ 99 */
87 - public IOLoopClient(InetAddress ip, int wc, int mc, int ml, int port) throws IOException { 100 + public IOLoopTestClient(InetAddress ip, int wc, int mc, int ml, int port) throws IOException {
88 this.ip = ip; 101 this.ip = ip;
89 this.port = port; 102 this.port = port;
90 this.msgCount = mc; 103 this.msgCount = mc;
...@@ -112,8 +125,9 @@ public class IOLoopClient { ...@@ -112,8 +125,9 @@ public class IOLoopClient {
112 } 125 }
113 126
114 // Wait for all of them to get going 127 // Wait for all of them to get going
115 -// for (CustomIOLoop l : iloops) 128 + for (CustomIOLoop l : iloops) {
116 -// l.waitForStart(TIMEOUT); 129 + l.awaitStart(1000);
130 + }
117 131
118 // ... and Next open all connections; one-per-loop 132 // ... and Next open all connections; one-per-loop
119 for (CustomIOLoop l : iloops) { 133 for (CustomIOLoop l : iloops) {
...@@ -162,11 +176,10 @@ public class IOLoopClient { ...@@ -162,11 +176,10 @@ public class IOLoopClient {
162 */ 176 */
163 public void report() { 177 public void report() {
164 DecimalFormat f = new DecimalFormat("#,##0"); 178 DecimalFormat f = new DecimalFormat("#,##0");
165 - log.info("{} messages; {} bytes; {} mps; {} Mbs", 179 + out.println(format("Client: %s messages; %s bytes; %s mps; %s Mbs",
166 - f.format(messages.total()), 180 + f.format(messages.total()), f.format(bytes.total()),
167 - f.format(bytes.total()), 181 + f.format(messages.throughput()),
168 - f.format(messages.throughput()), 182 + f.format(bytes.throughput() / (1024 * msgLength))));
169 - f.format(bytes.throughput() / (1024 * 128)));
170 } 183 }
171 184
172 185
...@@ -186,19 +199,20 @@ public class IOLoopClient { ...@@ -186,19 +199,20 @@ public class IOLoopClient {
186 } 199 }
187 200
188 @Override 201 @Override
189 - protected synchronized void removeStream(MessageStream<TestMessage> b) { 202 + protected synchronized void removeStream(MessageStream<TestMessage> stream) {
190 - super.removeStream(b); 203 + super.removeStream(stream);
191 - 204 +
192 - messages.add(b.messagesIn().total()); 205 + messages.add(stream.messagesIn().total());
193 - bytes.add(b.bytesIn().total()); 206 + bytes.add(stream.bytesIn().total());
194 - b.messagesOut().reset(); 207 +
195 - b.bytesOut().reset(); 208 +// out.println(format("Disconnected client; inbound %s mps, %s Mbps; outbound %s mps, %s Mbps",
196 -// 209 +// FORMAT.format(stream.messagesIn().throughput()),
197 - log.info("Disconnected client; inbound {} mps, {} Mbps; outbound {} mps, {} Mbps", 210 +// FORMAT.format(stream.bytesIn().throughput() / (1024 * msgLength)),
198 - IOLoopServer.FORMAT.format(b.messagesIn().throughput()), 211 +// FORMAT.format(stream.messagesOut().throughput()),
199 - IOLoopServer.FORMAT.format(b.bytesIn().throughput() / (1024 * 128)), 212 +// FORMAT.format(stream.bytesOut().throughput() / (1024 * msgLength))));
200 - IOLoopServer.FORMAT.format(b.messagesOut().throughput()), 213 +
201 - IOLoopServer.FORMAT.format(b.bytesOut().throughput() / (1024 * 128))); 214 + stream.messagesOut().reset();
215 + stream.bytesOut().reset();
202 } 216 }
203 217
204 @Override 218 @Override
......
...@@ -18,15 +18,17 @@ import java.util.List; ...@@ -18,15 +18,17 @@ import java.util.List;
18 import java.util.concurrent.ExecutorService; 18 import java.util.concurrent.ExecutorService;
19 import java.util.concurrent.Executors; 19 import java.util.concurrent.Executors;
20 20
21 +import static java.lang.String.format;
22 +import static java.lang.System.out;
21 import static org.onlab.junit.TestTools.delay; 23 import static org.onlab.junit.TestTools.delay;
22 import static org.onlab.util.Tools.namedThreads; 24 import static org.onlab.util.Tools.namedThreads;
23 25
24 /** 26 /**
25 * Auxiliary test fixture to measure speed of NIO-based channels. 27 * Auxiliary test fixture to measure speed of NIO-based channels.
26 */ 28 */
27 -public class IOLoopServer { 29 +public class IOLoopTestServer {
28 30
29 - private static Logger log = LoggerFactory.getLogger(IOLoopServer.class); 31 + private static Logger log = LoggerFactory.getLogger(IOLoopTestServer.class);
30 32
31 private static final int PRUNE_FREQUENCY = 1000; 33 private static final int PRUNE_FREQUENCY = 1000;
32 34
...@@ -34,8 +36,8 @@ public class IOLoopServer { ...@@ -34,8 +36,8 @@ public class IOLoopServer {
34 static final long TIMEOUT = 1000; 36 static final long TIMEOUT = 1000;
35 37
36 static final boolean SO_NO_DELAY = false; 38 static final boolean SO_NO_DELAY = false;
37 - static final int SO_SEND_BUFFER_SIZE = 1024 * 1024; 39 + static final int SO_SEND_BUFFER_SIZE = 128 * 1024;
38 - static final int SO_RCV_BUFFER_SIZE = 1024 * 1024; 40 + static final int SO_RCV_BUFFER_SIZE = 128 * 1024;
39 41
40 static final DecimalFormat FORMAT = new DecimalFormat("#,##0"); 42 static final DecimalFormat FORMAT = new DecimalFormat("#,##0");
41 43
...@@ -59,19 +61,29 @@ public class IOLoopServer { ...@@ -59,19 +61,29 @@ public class IOLoopServer {
59 * @throws IOException if unable to crate IO loops 61 * @throws IOException if unable to crate IO loops
60 */ 62 */
61 public static void main(String[] args) throws IOException { 63 public static void main(String[] args) throws IOException {
64 + startStandalone(args);
65 + System.exit(0);
66 + }
67 +
68 + /**
69 + * Starts a standalone IO loop test server.
70 + *
71 + * @param args command-line arguments
72 + */
73 + private static void startStandalone(String[] args) throws IOException {
62 InetAddress ip = InetAddress.getByName(args.length > 0 ? args[0] : "127.0.0.1"); 74 InetAddress ip = InetAddress.getByName(args.length > 0 ? args[0] : "127.0.0.1");
63 int wc = args.length > 1 ? Integer.parseInt(args[1]) : 6; 75 int wc = args.length > 1 ? Integer.parseInt(args[1]) : 6;
64 int ml = args.length > 2 ? Integer.parseInt(args[2]) : 128; 76 int ml = args.length > 2 ? Integer.parseInt(args[2]) : 128;
65 77
66 log.info("Setting up the server with {} workers, {} byte messages on {}... ", 78 log.info("Setting up the server with {} workers, {} byte messages on {}... ",
67 wc, ml, ip); 79 wc, ml, ip);
68 - IOLoopServer ss = new IOLoopServer(ip, wc, ml, PORT); 80 + IOLoopTestServer server = new IOLoopTestServer(ip, wc, ml, PORT);
69 - ss.start(); 81 + server.start();
70 82
71 // Start pruning clients. 83 // Start pruning clients.
72 while (true) { 84 while (true) {
73 delay(PRUNE_FREQUENCY); 85 delay(PRUNE_FREQUENCY);
74 - ss.prune(); 86 + server.prune();
75 } 87 }
76 } 88 }
77 89
...@@ -84,7 +96,7 @@ public class IOLoopServer { ...@@ -84,7 +96,7 @@ public class IOLoopServer {
84 * @param port listen port 96 * @param port listen port
85 * @throws IOException if unable to create IO loops 97 * @throws IOException if unable to create IO loops
86 */ 98 */
87 - public IOLoopServer(InetAddress ip, int wc, int ml, int port) throws IOException { 99 + public IOLoopTestServer(InetAddress ip, int wc, int ml, int port) throws IOException {
88 this.workerCount = wc; 100 this.workerCount = wc;
89 this.msgLength = ml; 101 this.msgLength = ml;
90 this.ipool = Executors.newFixedThreadPool(workerCount, namedThreads("io-loop")); 102 this.ipool = Executors.newFixedThreadPool(workerCount, namedThreads("io-loop"));
...@@ -107,9 +119,10 @@ public class IOLoopServer { ...@@ -107,9 +119,10 @@ public class IOLoopServer {
107 } 119 }
108 apool.execute(aloop); 120 apool.execute(aloop);
109 121
110 -// for (CustomIOLoop l : iloops) 122 + for (CustomIOLoop l : iloops) {
111 -// l.waitForStart(TIMEOUT); 123 + l.awaitStart(TIMEOUT);
112 -// aloop.waitForStart(TIMEOUT); 124 + }
125 + aloop.awaitStart(TIMEOUT);
113 } 126 }
114 127
115 /** 128 /**
...@@ -121,10 +134,11 @@ public class IOLoopServer { ...@@ -121,10 +134,11 @@ public class IOLoopServer {
121 l.shutdown(); 134 l.shutdown();
122 } 135 }
123 136
124 -// for (CustomIOLoop l : iloops) 137 + for (CustomIOLoop l : iloops) {
125 -// l.waitForFinish(TIMEOUT); 138 + l.awaitStop(TIMEOUT);
126 -// aloop.waitForFinish(TIMEOUT); 139 + }
127 -// 140 + aloop.awaitStop(TIMEOUT);
141 +
128 messages.freeze(); 142 messages.freeze();
129 bytes.freeze(); 143 bytes.freeze();
130 } 144 }
...@@ -134,11 +148,10 @@ public class IOLoopServer { ...@@ -134,11 +148,10 @@ public class IOLoopServer {
134 */ 148 */
135 public void report() { 149 public void report() {
136 DecimalFormat f = new DecimalFormat("#,##0"); 150 DecimalFormat f = new DecimalFormat("#,##0");
137 - log.info("{} messages; {} bytes; {} mps; {} Mbs", 151 + out.println(format("Server: %s messages; %s bytes; %s mps; %s Mbs",
138 - f.format(messages.total()), 152 + f.format(messages.total()), f.format(bytes.total()),
139 - f.format(bytes.total()), 153 + f.format(messages.throughput()),
140 - f.format(messages.throughput()), 154 + f.format(bytes.throughput() / (1024 * msgLength))));
141 - f.format(bytes.throughput() / (1024 * 128)));
142 } 155 }
143 156
144 /** 157 /**
...@@ -175,11 +188,11 @@ public class IOLoopServer { ...@@ -175,11 +188,11 @@ public class IOLoopServer {
175 messages.add(stream.messagesIn().total()); 188 messages.add(stream.messagesIn().total());
176 bytes.add(stream.bytesIn().total()); 189 bytes.add(stream.bytesIn().total());
177 190
178 - log.info("Disconnected client; inbound {} mps, {} Mbps; outbound {} mps, {} Mbps", 191 +// out.println(format("Disconnected server; inbound %s mps, %s Mbps; outbound %s mps, %s Mbps",
179 - FORMAT.format(stream.messagesIn().throughput()), 192 +// FORMAT.format(stream.messagesIn().throughput()),
180 - FORMAT.format(stream.bytesIn().throughput() / (1024 * 128)), 193 +// FORMAT.format(stream.bytesIn().throughput() / (1024 * msgLength)),
181 - FORMAT.format(stream.messagesOut().throughput()), 194 +// FORMAT.format(stream.messagesOut().throughput()),
182 - FORMAT.format(stream.bytesOut().throughput() / (1024 * 128))); 195 +// FORMAT.format(stream.bytesOut().throughput() / (1024 * msgLength))));
183 } 196 }
184 197
185 @Override 198 @Override
......