From 45724b63ecfd9d9a01c4490166a866be3184fcfa Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Mon, 19 Aug 2013 22:11:52 +0200 Subject: [PATCH] Improved masking performance by using ints instead of bytes. --- .../jetty/websocket/common/Generator.java | 29 +++++++++------ .../common/io/payload/DeMaskProcessor.java | 37 ++++++++++--------- .../io/payload/DeMaskProcessorTest.java | 4 +- 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Generator.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Generator.java index 6e1b7f12a35..10580b2d2e3 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Generator.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/Generator.java @@ -282,24 +282,29 @@ public class Generator { byte[] mask = frame.getMask(); buffer.put(mask); + int maskInt = ByteBuffer.wrap(mask).getInt(); // perform data masking here - byte mb; ByteBuffer payload = frame.getPayload(); if ((payload != null) && (payload.remaining() > 0)) { - int pos = payload.position(); - int limit = payload.limit(); - for (int i = pos; i < limit; i++) + int maskOffset = 0; + int start = payload.position(); + int end = payload.limit(); + int remaining; + while ((remaining = end - start) > 0) { - // get raw byte from buffer. - mb = payload.get(i); - - // mask, using offset information from frame windowing. - mb ^= mask[(i - pos) % 4]; - - // Mask each byte by its absolute position in the payload bytebuffer - payload.put(i,mb); + if (remaining >= 4) + { + payload.putInt(start, payload.getInt(start) ^ maskInt); + start += 4; + } + else + { + payload.put(start, (byte)(payload.get(start) ^ mask[maskOffset & 3])); + ++start; + ++maskOffset; + } } } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/DeMaskProcessor.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/DeMaskProcessor.java index ead2bc94ca5..9d6d062f0f6 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/DeMaskProcessor.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/payload/DeMaskProcessor.java @@ -24,39 +24,42 @@ import org.eclipse.jetty.websocket.api.extensions.Frame; public class DeMaskProcessor implements PayloadProcessor { - private boolean isMasked; - private byte mask[]; - private int offset; + private byte maskBytes[]; + private int maskOffset; @Override public void process(ByteBuffer payload) { - if (!isMasked) + if (maskBytes == null) { return; } + int maskInt = ByteBuffer.wrap(maskBytes).getInt(); int start = payload.position(); int end = payload.limit(); - for (int i = start; i < end; i++, offset++) + int offset = this.maskOffset; + int remaining; + while ((remaining = end - start) > 0) { - payload.put(i,(byte)(payload.get(i) ^ mask[offset % 4])); + if (remaining >= 4 && offset == 0) + { + payload.putInt(start, payload.getInt(start) ^ maskInt); + start +=4; + } + else + { + payload.put(start, (byte)(payload.get(start) ^ maskBytes[offset & 3])); + ++start; + ++offset; + } } } @Override public void reset(Frame frame) { - this.isMasked = frame.isMasked(); - if (isMasked) - { - this.mask = frame.getMask(); - } - else - { - this.mask = null; - } - - offset = 0; + this.maskBytes = frame.isMasked() ? frame.getMask() : null; + this.maskOffset = 0; } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/payload/DeMaskProcessorTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/payload/DeMaskProcessorTest.java index b3b9bdb94dd..5f53dbea640 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/payload/DeMaskProcessorTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/payload/DeMaskProcessorTest.java @@ -27,7 +27,6 @@ import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.common.ByteBufferAssert; import org.eclipse.jetty.websocket.common.UnitGenerator; import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.io.payload.DeMaskProcessor; import org.junit.Test; public class DeMaskProcessorTest @@ -37,7 +36,8 @@ public class DeMaskProcessorTest @Test public void testDeMaskText() { - String message = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"; + // Use a string that is not multiple of 4 in length to test if/else branches in DeMaskProcessor + String message = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF01"; WebSocketFrame frame = WebSocketFrame.text(message); frame.setMask(TypeUtil.fromHexString("11223344"));