From 0fc91ef31c5a73e56cf67fe86aae15d12d06b8ef Mon Sep 17 00:00:00 2001 From: Michael Meeks Date: Thu, 19 Nov 2020 19:55:30 +0000 Subject: [PATCH] Adapt Buffer class to avoid repeated compactions. Avoid continually shuffling large output buffers down in memory, it kills CPU caches, does nothing useful, and we can just advance an offset instead. Of course, we do need to free memory - so do that for lots of common cases. Change-Id: I63240661ca87bdc0574acbce856771d9dde3fa94 Signed-off-by: Michael Meeks --- net/Buffer.hpp | 30 ++++++++++++++++++++++++------ net/Socket.cpp | 3 +-- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/net/Buffer.hpp b/net/Buffer.hpp index 328eba0fa..428bc684b 100644 --- a/net/Buffer.hpp +++ b/net/Buffer.hpp @@ -17,9 +17,10 @@ */ class Buffer { size_t _size; + size_t _offset; std::vector _buffer; public: - Buffer() : _size(0) + Buffer() : _size(0), _offset(0) { } size_t size() { return _size; } @@ -27,7 +28,7 @@ public: const char *getBlock() { - return &_buffer[0]; + return &_buffer[_offset]; } size_t getBlockSize() { @@ -35,17 +36,34 @@ public: } void eraseFirst(size_t len) { - _buffer.erase(_buffer.begin(), _buffer.begin() + len); - _size = _buffer.size(); + assert(_offset + len <= _buffer.size()); + + // avoid regular shuffling down larger chunks of data + if (_buffer.size() > 16384 && // lots of queued data + len < _buffer.size() && // not a complete erase + _offset < 16384 * 64 && // do cleanup a Mb at a time or so: + _size > 512) // early cleanup if what remains is small. + { + _offset += len; + _size -= len; + return; + } + + _buffer.erase(_buffer.begin(), _buffer.begin() + _offset + len); + _offset = 0; + _size = _buffer.size() - _offset; } void append(const char *data, const int len) { _buffer.insert(_buffer.end(), data, data + len); - _size = _buffer.size(); + _size = _buffer.size() - _offset; } void dumpHex(std::ostream &os, const char *legend, const char *prefix) { - Util::dumpHex(os, legend, prefix, _buffer); + if (_size > 0 || _offset > 0) + os << prefix << "Buffer size: " << _size << " offset: " << _offset << "\n"; + if (_buffer.size() > 0) + Util::dumpHex(os, legend, prefix, _buffer); } }; diff --git a/net/Socket.cpp b/net/Socket.cpp index 22adda44b..75297f561 100644 --- a/net/Socket.cpp +++ b/net/Socket.cpp @@ -554,8 +554,7 @@ void StreamSocket::dumpState(std::ostream& os) _socketHandler->dumpState(os); if (_inBuffer.size() > 0) Util::dumpHex(os, "\t\tinBuffer:\n", "\t\t", _inBuffer); - if (_outBuffer.size() > 0) - _outBuffer.dumpHex(os, "\t\toutBuffer:\n", "\t\t"); + _outBuffer.dumpHex(os, "\t\toutBuffer:\n", "\t\t"); } void StreamSocket::send(Poco::Net::HTTPResponse& response)