Madan Jampani

Improved message decoding performance

...@@ -17,8 +17,8 @@ public class AsyncResponse<T> implements Response<T> { ...@@ -17,8 +17,8 @@ public class AsyncResponse<T> implements Response<T> {
17 private final long start = System.nanoTime(); 17 private final long start = System.nanoTime();
18 18
19 @Override 19 @Override
20 - public T get(long timeout, TimeUnit tu) throws TimeoutException { 20 + public T get(long timeout, TimeUnit timeUnit) throws TimeoutException {
21 - timeout = tu.toNanos(timeout); 21 + timeout = timeUnit.toNanos(timeout);
22 boolean interrupted = false; 22 boolean interrupted = false;
23 try { 23 try {
24 synchronized (this) { 24 synchronized (this) {
......
...@@ -2,14 +2,19 @@ package org.onlab.netty; ...@@ -2,14 +2,19 @@ package org.onlab.netty;
2 2
3 import java.io.IOException; 3 import java.io.IOException;
4 4
5 +import org.slf4j.Logger;
6 +import org.slf4j.LoggerFactory;
7 +
5 /** 8 /**
6 * Message handler that echos the message back to the sender. 9 * Message handler that echos the message back to the sender.
7 */ 10 */
8 public class EchoHandler implements MessageHandler { 11 public class EchoHandler implements MessageHandler {
9 12
13 + private final Logger log = LoggerFactory.getLogger(getClass());
14 +
10 @Override 15 @Override
11 public void handle(Message message) throws IOException { 16 public void handle(Message message) throws IOException {
12 - System.out.println("Received message. Echoing it back to the sender."); 17 + log.info("Received message. Echoing it back to the sender.");
13 message.respond(message.payload()); 18 message.respond(message.payload());
14 } 19 }
15 } 20 }
......
...@@ -11,6 +11,7 @@ public class Endpoint { ...@@ -11,6 +11,7 @@ public class Endpoint {
11 /** 11 /**
12 * Used for serialization. 12 * Used for serialization.
13 */ 13 */
14 + @SuppressWarnings("unused")
14 private Endpoint() { 15 private Endpoint() {
15 port = 0; 16 port = 0;
16 host = null; 17 host = null;
...@@ -67,4 +68,4 @@ public class Endpoint { ...@@ -67,4 +68,4 @@ public class Endpoint {
67 } 68 }
68 return true; 69 return true;
69 } 70 }
70 -} 71 +}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -86,4 +86,4 @@ public final class InternalMessage implements Message { ...@@ -86,4 +86,4 @@ public final class InternalMessage implements Message {
86 return message; 86 return message;
87 } 87 }
88 } 88 }
89 -} 89 +}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -53,4 +53,4 @@ public class KryoSerializer implements Serializer { ...@@ -53,4 +53,4 @@ public class KryoSerializer implements Serializer {
53 public void serialize(Object obj, ByteBuffer buffer) { 53 public void serialize(Object obj, ByteBuffer buffer) {
54 serializerPool.serialize(obj, buffer); 54 serializerPool.serialize(obj, buffer);
55 } 55 }
56 -} 56 +}
...\ No newline at end of file ...\ No newline at end of file
......
1 package org.onlab.netty; 1 package org.onlab.netty;
2 2
3 +import org.slf4j.Logger;
4 +import org.slf4j.LoggerFactory;
5 +
3 /** 6 /**
4 * A MessageHandler that simply logs the information. 7 * A MessageHandler that simply logs the information.
5 */ 8 */
6 public class LoggingHandler implements MessageHandler { 9 public class LoggingHandler implements MessageHandler {
7 10
11 + private final Logger log = LoggerFactory.getLogger(getClass());
12 +
8 @Override 13 @Override
9 public void handle(Message message) { 14 public void handle(Message message) {
10 - System.out.println("Received: " + message.payload()); 15 + log.info("Received message. Payload: " + message.payload());
11 } 16 }
12 } 17 }
......
...@@ -8,13 +8,18 @@ import io.netty.handler.codec.ReplayingDecoder; ...@@ -8,13 +8,18 @@ import io.netty.handler.codec.ReplayingDecoder;
8 import java.util.Arrays; 8 import java.util.Arrays;
9 import java.util.List; 9 import java.util.List;
10 10
11 -// TODO: Implement performance enchancements such as those described in the javadoc for ReplayingDecoder. 11 +/**
12 -public class MessageDecoder extends ReplayingDecoder<InternalMessage> { 12 + * Decoder for inbound messages.
13 + */
14 +public class MessageDecoder extends ReplayingDecoder<DecoderState> {
13 15
14 private final NettyMessagingService messagingService; 16 private final NettyMessagingService messagingService;
15 private final Serializer serializer; 17 private final Serializer serializer;
16 18
19 + private int contentLength;
20 +
17 public MessageDecoder(NettyMessagingService messagingService, Serializer serializer) { 21 public MessageDecoder(NettyMessagingService messagingService, Serializer serializer) {
22 + super(DecoderState.READ_HEADER_VERSION);
18 this.messagingService = messagingService; 23 this.messagingService = messagingService;
19 this.serializer = serializer; 24 this.serializer = serializer;
20 } 25 }
...@@ -25,16 +30,31 @@ public class MessageDecoder extends ReplayingDecoder<InternalMessage> { ...@@ -25,16 +30,31 @@ public class MessageDecoder extends ReplayingDecoder<InternalMessage> {
25 ByteBuf buffer, 30 ByteBuf buffer,
26 List<Object> out) throws Exception { 31 List<Object> out) throws Exception {
27 32
28 - byte[] preamble = new byte[MessageEncoder.PREAMBLE.length]; 33 + switch(state()) {
29 - buffer.readBytes(preamble); 34 + case READ_HEADER_VERSION:
30 - checkState(Arrays.equals(MessageEncoder.PREAMBLE, preamble), "Message has wrong preamble"); 35 + int headerVersion = buffer.readInt();
31 - 36 + checkState(headerVersion == MessageEncoder.HEADER_VERSION, "Unexpected header version");
32 - int bodySize = buffer.readInt(); 37 + checkpoint(DecoderState.READ_PREAMBLE);
33 - byte[] body = new byte[bodySize]; 38 + case READ_PREAMBLE:
34 - buffer.readBytes(body); 39 + byte[] preamble = new byte[MessageEncoder.PREAMBLE.length];
35 - 40 + buffer.readBytes(preamble);
36 - InternalMessage message = serializer.decode(body); 41 + checkState(Arrays.equals(MessageEncoder.PREAMBLE, preamble), "Message has wrong preamble");
37 - message.setMessagingService(messagingService); 42 + checkpoint(DecoderState.READ_CONTENT_LENGTH);
38 - out.add(message); 43 + case READ_CONTENT_LENGTH:
44 + contentLength = buffer.readInt();
45 + checkpoint(DecoderState.READ_SERIALIZER_VERSION);
46 + case READ_SERIALIZER_VERSION:
47 + int serializerVersion = buffer.readInt();
48 + checkState(serializerVersion == MessageEncoder.SERIALIZER_VERSION, "Unexpected serializer version");
49 + checkpoint(DecoderState.READ_CONTENT);
50 + case READ_CONTENT:
51 + InternalMessage message = serializer.deserialize(buffer.readBytes(contentLength).nioBuffer());
52 + message.setMessagingService(messagingService);
53 + out.add(message);
54 + checkpoint(DecoderState.READ_HEADER_VERSION);
55 + break;
56 + default:
57 + checkState(false, "Must not be here");
58 + }
39 } 59 }
40 } 60 }
......
...@@ -11,6 +11,9 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { ...@@ -11,6 +11,9 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> {
11 11
12 // onosiscool in ascii 12 // onosiscool in ascii
13 public static final byte[] PREAMBLE = "onosiscool".getBytes(); 13 public static final byte[] PREAMBLE = "onosiscool".getBytes();
14 + public static final int HEADER_VERSION = 1;
15 + public static final int SERIALIZER_VERSION = 1;
16 +
14 17
15 private final Serializer serializer; 18 private final Serializer serializer;
16 19
...@@ -24,6 +27,9 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { ...@@ -24,6 +27,9 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> {
24 InternalMessage message, 27 InternalMessage message,
25 ByteBuf out) throws Exception { 28 ByteBuf out) throws Exception {
26 29
30 + // write version
31 + out.writeInt(HEADER_VERSION);
32 +
27 // write preamble 33 // write preamble
28 out.writeBytes(PREAMBLE); 34 out.writeBytes(PREAMBLE);
29 35
...@@ -32,6 +38,9 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { ...@@ -32,6 +38,9 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> {
32 // write payload length 38 // write payload length
33 out.writeInt(payload.length); 39 out.writeInt(payload.length);
34 40
41 + // write serializer version
42 + out.writeInt(SERIALIZER_VERSION);
43 +
35 // write payload. 44 // write payload.
36 out.writeBytes(payload); 45 out.writeBytes(payload);
37 } 46 }
......
...@@ -134,6 +134,10 @@ public class NettyMessagingService implements MessagingService { ...@@ -134,6 +134,10 @@ public class NettyMessagingService implements MessagingService {
134 handlers.remove(type); 134 handlers.remove(type);
135 } 135 }
136 136
137 + public void setSerializer(Serializer serializer) {
138 + this.serializer = serializer;
139 + }
140 +
137 private MessageHandler getMessageHandler(String type) { 141 private MessageHandler getMessageHandler(String type) {
138 return handlers.get(type); 142 return handlers.get(type);
139 } 143 }
......
...@@ -4,16 +4,10 @@ public final class SimpleServer { ...@@ -4,16 +4,10 @@ public final class SimpleServer {
4 private SimpleServer() {} 4 private SimpleServer() {}
5 5
6 public static void main(String... args) throws Exception { 6 public static void main(String... args) throws Exception {
7 - NettyMessagingService server = new TestNettyMessagingService(); 7 + NettyMessagingService server = new NettyMessagingService(8080);
8 server.activate(); 8 server.activate();
9 + server.setSerializer(new KryoSerializer());
9 server.registerHandler("simple", new LoggingHandler()); 10 server.registerHandler("simple", new LoggingHandler());
10 server.registerHandler("echo", new EchoHandler()); 11 server.registerHandler("echo", new EchoHandler());
11 } 12 }
12 -
13 - public static class TestNettyMessagingService extends NettyMessagingService {
14 - protected TestNettyMessagingService() {
15 - Serializer serializer = new KryoSerializer();
16 - this.serializer = serializer;
17 - }
18 - }
19 } 13 }
......