Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1955)

Unified Diff: sdk/lib/io/websocket_impl.dart

Issue 137833011: Use Int32x4List to optimize mask/unmask websockets. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Review update Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/io/websocket_impl.dart
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart
index 69a7f0eb69f36793cff1db27e937694c2ec5d299..0da50b2dfaa6116bcf850c17f690ec0a30255881 100644
--- a/sdk/lib/io/websocket_impl.dart
+++ b/sdk/lib/io/websocket_impl.dart
@@ -169,17 +169,15 @@ class _WebSocketProtocolTransformer implements StreamTransformer, EventSink {
} else {
assert(_state == PAYLOAD);
// The payload is not handled one byte at a time but in blocks.
- int payload = min(lastIndex - index, _remainingPayloadBytes);
- _remainingPayloadBytes -= payload;
+ int payloadLength = min(lastIndex - index, _remainingPayloadBytes);
+ _remainingPayloadBytes -= payloadLength;
// Unmask payload if masked.
if (_masked) {
- for (int i = index; i < index + payload; i++) {
- buffer[i] ^= _maskingBytes[_unmaskingIndex++ & 3];
- }
+ _unmask(index, payloadLength, buffer);
}
// Control frame and data frame share _payload builder.
- _payload.add(new Uint8List.view(buffer.buffer, index, payload));
- index += payload;
+ _payload.add(new Uint8List.view(buffer.buffer, index, payloadLength));
+ index += payloadLength;
if (_isControlFrame()) {
if (_remainingPayloadBytes == 0) _controlFrameEnd();
} else {
@@ -200,6 +198,43 @@ class _WebSocketProtocolTransformer implements StreamTransformer, EventSink {
}
}
+ void _unmask(int index, int length, Uint8List buffer) {
+ const int BLOCK_SIZE = 16;
+ // Skip Int32x4-version if message is small.
+ if (length >= BLOCK_SIZE) {
+ // Start by aligning to 16 bytes.
+ final int startOffset = BLOCK_SIZE - (index & 15);
+ final int end = index + startOffset;
+ for (int i = index; i < end; i++) {
+ buffer[i] ^= _maskingBytes[_unmaskingIndex++ & 3];
+ }
+ index += startOffset;
+ length -= startOffset;
+ final int blockCount = length ~/ BLOCK_SIZE;
+ if (blockCount > 0) {
+ // Create mask block.
+ int mask = 0;
+ for (int i = 3; i >= 0; i--) {
+ mask = (mask << 8) | _maskingBytes[(_unmaskingIndex + i) & 3];
+ }
+ Int32x4 blockMask = new Int32x4(mask, mask, mask, mask);
+ Int32x4List blockBuffer = new Int32x4List.view(
+ buffer.buffer, index, blockCount);
+ for (int i = 0; i < blockBuffer.length; i++) {
+ blockBuffer[i] ^= blockMask;
+ }
+ final int bytes = blockCount * BLOCK_SIZE;
+ index += bytes;
+ length -= bytes;
+ }
+ }
+ // Handle end.
+ final int end = index + length;
+ for (int i = index; i < end; i++) {
+ buffer[i] ^= _maskingBytes[_unmaskingIndex++ & 3];
+ }
+ }
+
void _lengthDone() {
if (_masked) {
if (!_serverSide) {
@@ -530,28 +565,45 @@ class _WebSocketOutgoingTransformer implements StreamTransformer, EventSink {
header.setRange(index, index + 4, maskBytes);
index += 4;
if (data != null) {
- var list;
+ Uint8List list;
// If this is a text message just do the masking inside the
// encoded data.
- if (opcode == _WebSocketOpcode.TEXT) {
+ if (opcode == _WebSocketOpcode.TEXT && data is Uint8List) {
list = data;
} else {
- list = new Uint8List(data.length);
+ if (data is Uint8List) {
+ list = new Uint8List.fromList(data);
+ } else {
+ list = new Uint8List(data.length);
+ for (int i = 0; i < data.length; i++) {
+ if (data[i] < 0 || 255 < data[i]) {
+ throw new ArgumentError(
+ "List element is not a byte value "
+ "(value ${data[i]} at index $i)");
+ }
+ list[i] = data[i];
+ }
+ }
}
- if (data is Uint8List) {
- for (int i = 0; i < data.length; i++) {
- list[i] = data[i] ^ maskBytes[i & 3];
+ const int BLOCK_SIZE = 16;
+ int blockCount = list.length ~/ BLOCK_SIZE;
+ if (blockCount > 0) {
+ // Create mask block.
+ int mask = 0;
+ for (int i = 3; i >= 0; i--) {
+ mask = (mask << 8) | maskBytes[i];
}
- } else {
- for (int i = 0; i < data.length; i++) {
- if (data[i] < 0 || 255 < data[i]) {
- throw new ArgumentError(
- "List element is not a byte value "
- "(value ${data[i]} at index $i)");
- }
- list[i] = data[i] ^ maskBytes[i & 3];
+ Int32x4 blockMask = new Int32x4(mask, mask, mask, mask);
+ Int32x4List blockBuffer = new Int32x4List.view(
+ list.buffer, 0, blockCount);
+ for (int i = 0; i < blockBuffer.length; i++) {
+ blockBuffer[i] ^= blockMask;
}
}
+ // Handle end.
+ for (int i = blockCount * BLOCK_SIZE; i < list.length; i++) {
+ list[i] ^= maskBytes[i & 3];
+ }
data = list;
}
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698