(websocket) use persistent member variable as temp variables to encode/decode zlib messages in order to reduce transient allocations

This commit is contained in:
Benjamin Sergeant 2020-04-13 21:38:15 -07:00
parent c57cf413fb
commit 37a054723a
6 changed files with 30 additions and 19 deletions

View File

@ -1,6 +1,10 @@
# Changelog
All changes to this project will be documented in this file.
## [9.2.4] - 2020-04-13
(websocket) use persistent member variable as temp variables to encode/decode zlib messages in order to reduce transient allocations
## [9.2.3] - 2020-04-13
(ws) add a --runtime option to ws cobra_subscribe to optionally limit how much time it will run

View File

@ -19,7 +19,7 @@ namespace ix
struct WebSocketMessage
{
WebSocketMessageType type;
std::string str;
const std::string& str;
size_t wireSize;
WebSocketErrorInfo errorInfo;
WebSocketOpenInfo openInfo;
@ -34,7 +34,7 @@ namespace ix
WebSocketCloseInfo c,
bool b = false)
: type(t)
, str(std::move(s))
, str(s)
, wireSize(w)
, errorInfo(e)
, openInfo(o)

View File

@ -87,6 +87,9 @@ namespace ix
//
size_t output;
// Clear output
out.clear();
if (in.empty())
{
// See issue #167
@ -174,6 +177,9 @@ namespace ix
_inflateState.avail_in = (uInt) inFixed.size();
_inflateState.next_in = (unsigned char*) (const_cast<char*>(inFixed.data()));
// Clear output
out.clear();
do
{
_inflateState.avail_out = (uInt) _compressBufferSize;

View File

@ -62,7 +62,7 @@ namespace ix
WebSocketTransport::WebSocketTransport()
: _useMask(true)
, _blockingSend(false)
, _compressedMessage(false)
, _receivedMessageCompressed(false)
, _readyState(ReadyState::CLOSED)
, _closeCode(WebSocketCloseConstants::kInternalErrorCode)
, _closeReason(WebSocketCloseConstants::kInternalErrorMessage)
@ -493,7 +493,7 @@ namespace ix
? MessageKind::MSG_TEXT
: MessageKind::MSG_BINARY;
_compressedMessage = _enablePerMessageDeflate && ws.rsv1;
_receivedMessageCompressed = _enablePerMessageDeflate && ws.rsv1;
// Continuation message needs to follow a non-fin TEXT or BINARY message
if (!_chunks.empty())
@ -516,9 +516,9 @@ namespace ix
if (ws.fin && _chunks.empty())
{
emitMessage(
_fragmentedMessageKind, frameData, _compressedMessage, onMessageCallback);
_fragmentedMessageKind, frameData, _receivedMessageCompressed, onMessageCallback);
_compressedMessage = false;
_receivedMessageCompressed = false;
}
else
{
@ -535,11 +535,11 @@ namespace ix
{
emitMessage(_fragmentedMessageKind,
getMergedChunks(),
_compressedMessage,
_receivedMessageCompressed,
onMessageCallback);
_chunks.clear();
_compressedMessage = false;
_receivedMessageCompressed = false;
}
else
{
@ -712,17 +712,16 @@ namespace ix
// When the RSV1 bit is 1 it means the message is compressed
if (compressedMessage && messageKind != MessageKind::FRAGMENT)
{
std::string decompressedMessage;
bool success = _perMessageDeflate->decompress(message, decompressedMessage);
bool success = _perMessageDeflate->decompress(message, _decompressedMessage);
if (messageKind == MessageKind::MSG_TEXT && !validateUtf8(decompressedMessage))
if (messageKind == MessageKind::MSG_TEXT && !validateUtf8(_decompressedMessage))
{
close(WebSocketCloseConstants::kInvalidFramePayloadData,
WebSocketCloseConstants::kInvalidFramePayloadDataMessage);
}
else
{
onMessageCallback(decompressedMessage, wireSize, !success, messageKind);
onMessageCallback(_decompressedMessage, wireSize, !success, messageKind);
}
}
else
@ -759,7 +758,6 @@ namespace ix
size_t payloadSize = message.size();
size_t wireSize = message.size();
std::string compressedMessage;
bool compressionError = false;
std::string::const_iterator message_begin = message.begin();
@ -767,7 +765,7 @@ namespace ix
if (compress)
{
if (!_perMessageDeflate->compress(message, compressedMessage))
if (!_perMessageDeflate->compress(message, _compressedMessage))
{
bool success = false;
compressionError = true;
@ -776,10 +774,10 @@ namespace ix
return WebSocketSendInfo(success, compressionError, payloadSize, wireSize);
}
compressionError = false;
wireSize = compressedMessage.size();
wireSize = _compressedMessage.size();
message_begin = compressedMessage.begin();
message_end = compressedMessage.end();
message_begin = _compressedMessage.begin();
message_end = _compressedMessage.end();
}
{

View File

@ -165,7 +165,7 @@ namespace ix
MessageKind _fragmentedMessageKind;
// Ditto for whether a message is compressed
bool _compressedMessage;
bool _receivedMessageCompressed;
// Fragments are 32K long
static constexpr size_t kChunkSize = 1 << 15;
@ -189,6 +189,9 @@ namespace ix
WebSocketPerMessageDeflateOptions _perMessageDeflateOptions;
std::atomic<bool> _enablePerMessageDeflate;
std::string _decompressedMessage;
std::string _compressedMessage;
// Used to control TLS connection behavior
SocketTLSOptions _socketTLSOptions;

View File

@ -6,4 +6,4 @@
#pragma once
#define IX_WEBSOCKET_VERSION "9.2.3"
#define IX_WEBSOCKET_VERSION "9.2.4"