Skip to content

Commit 75aac7c

Browse files
WebSocket frame encoding: avoid redundant allocations on frame masking (#12969)
Motivation: When masking is enabled, redundant intermediate bytebuffer + array is created for each websocket message. Modifications: Remove intermediate bytebuffer used to hold frame mask, use int mask directly. Result: No redundant allocations on frame masking
1 parent 7127e60 commit 75aac7c

1 file changed

Lines changed: 8 additions & 12 deletions

File tree

codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameEncoder.java

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ public WebSocket08FrameEncoder(boolean maskPayload) {
106106
@Override
107107
protected void encode(ChannelHandlerContext ctx, WebSocketFrame msg, List<Object> out) throws Exception {
108108
final ByteBuf data = msg.content();
109-
byte[] mask;
110109

111110
byte opcode;
112111
if (msg instanceof TextWebSocketFrame) {
@@ -175,9 +174,8 @@ protected void encode(ChannelHandlerContext ctx, WebSocketFrame msg, List<Object
175174

176175
// Write payload
177176
if (maskPayload) {
178-
int random = PlatformDependent.threadLocalRandom().nextInt(Integer.MAX_VALUE);
179-
mask = ByteBuffer.allocate(4).putInt(random).array();
180-
buf.writeBytes(mask);
177+
int mask = PlatformDependent.threadLocalRandom().nextInt(Integer.MAX_VALUE);
178+
buf.writeInt(mask);
181179

182180
if (data.isReadable()) {
183181

@@ -189,13 +187,7 @@ protected void encode(ChannelHandlerContext ctx, WebSocketFrame msg, List<Object
189187

190188
if (srcOrder == dstOrder) {
191189
// Use the optimized path only when byte orders match
192-
// Remark: & 0xFF is necessary because Java will do signed expansion from
193-
// byte to int which we don't want.
194-
long longMask = (long) (mask[0] & 0xff) << 24
195-
| (mask[1] & 0xff) << 16
196-
| (mask[2] & 0xff) << 8
197-
| (mask[3] & 0xff);
198-
longMask |= longMask << 32;
190+
long longMask = mask | (long) mask << 32;
199191

200192
// If the byte order of our buffers it little endian we have to bring our mask
201193
// into the same format, because getInt() and writeInt() will use a reversed byte order
@@ -215,7 +207,7 @@ protected void encode(ChannelHandlerContext ctx, WebSocketFrame msg, List<Object
215207
int maskOffset = 0;
216208
for (; i < end; i++) {
217209
byte byteData = data.getByte(i);
218-
buf.writeByte(byteData ^ mask[maskOffset++ & 3]);
210+
buf.writeByte(byteData ^ byteAtIndex(mask, maskOffset++ & 3));
219211
}
220212
}
221213
out.add(buf);
@@ -236,4 +228,8 @@ protected void encode(ChannelHandlerContext ctx, WebSocketFrame msg, List<Object
236228
}
237229
}
238230
}
231+
232+
private static int byteAtIndex(int mask, int index) {
233+
return (mask >> 8 * (3 - index)) & 0xFF;
234+
}
239235
}

0 commit comments

Comments
 (0)