Skip to content

Commit 783d9f1

Browse files
committed
Improved memory allocations in TcpConnection class
Reduced allocations/reallocations, better handling and recovery from oversized messages. Updated doxygen docs.
1 parent eb96025 commit 783d9f1

2,626 files changed

Lines changed: 3398 additions & 3371 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"request": "launch",
2222
"program": "${input:unitTestProgramWin}",
2323
"args": [
24-
"--gtest_filter=AsioTest.testCase_testNetUtils_GetIpAndSubnetMasks",
24+
"--gtest_filter=AsioTest.testCase_TestSimpleSync_Large",
2525
"--gtest_break_on_failure",
2626
"--gtest_catch_exceptions=0"
2727
],

Include/Asio/AsioDefines.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ namespace tcp
166166
/*! \brief Default internal receive buffer's initial reserved size in bytes. */
167167
enum eDefReservedSize : size_t
168168
{
169-
DEFAULT_RESERVED_SIZE = 512 * 1024
169+
DEFAULT_SMALL_RESERVED_SIZE = 65536,
170+
DEFAULT_LARGE_RESERVED_SIZE = 1048576
170171
};
171172

172173
/*! \brief Maximum number of unsent async messages allowed on TCP socket IO Service queue */

Include/Asio/MessageUtils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class CORE_LIBRARY_DLL_SHARED_API MessageHandler final
116116
* \brief Get next message to use from pool.
117117
* \return A new message object or a one from the pool.
118118
*/
119-
defs::default_received_message_ptr_t GetNewMessgeObject() const;
119+
defs::default_received_message_ptr_t GetNewMessageObject() const;
120120

121121
private:
122122
mutable std::mutex m_mutex;

Include/Asio/TcpConnection.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <deque>
3535
#include <utility>
3636
#include <atomic>
37+
#include <array>
3738

3839
/*! \brief The core_lib namespace. */
3940
namespace core_lib
@@ -282,7 +283,7 @@ class CORE_LIBRARY_DLL_SHARED_API TcpConnection final
282283
/*! \brief Structure holding socket connection options and behavioural settings. */
283284
TcpConnSettings m_settings;
284285
/*! \brief Socket receive buffer. */
285-
defs::char_buffer_t m_receiveBuffer;
286+
std::array<char, DEFAULT_SMALL_RESERVED_SIZE> m_receiveBuffer;
286287
/*! \brief Message buffer. */
287288
defs::char_buffer_t m_messageBuffer;
288289
/*! \brief Unsent async message reservation counter (thread-safe). */

Source/Asio/MessageUtils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ void MessageHandler::MessageReceivedHandler(defs::char_buf_cspan_t message) cons
135135
#endif
136136
}
137137

138-
auto receivedMessage = GetNewMessgeObject();
138+
auto receivedMessage = GetNewMessageObject();
139139

140140
if (!TryConvertToPod<defs::MessageHeader>(receivedMessage->header, message))
141141
{
@@ -199,7 +199,7 @@ void MessageHandler::InitialiseMsgPool(size_t memPoolMsgCount, size_t defaultMsg
199199
std::generate(m_msgPool.begin(), m_msgPool.end(), generateMsg);
200200
}
201201

202-
defs::default_received_message_ptr_t MessageHandler::GetNewMessgeObject() const
202+
defs::default_received_message_ptr_t MessageHandler::GetNewMessageObject() const
203203
{
204204
defs::default_received_message_ptr_t newMessage;
205205

Source/Asio/TcpConnection.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,7 @@ TcpConnection::TcpConnection(asio_compat::io_service_t& ioSer
7070
"Reserving memory for receive and send buffers as: " << DEFAULT_RESERVED_SIZE << " bytes");
7171
#endif
7272

73-
m_receiveBuffer.reserve(DEFAULT_RESERVED_SIZE);
74-
m_messageBuffer.reserve(DEFAULT_RESERVED_SIZE);
73+
m_messageBuffer.reserve(DEFAULT_LARGE_RESERVED_SIZE);
7574
}
7675

7776
boost_tcp_t::socket& TcpConnection::Socket()
@@ -301,11 +300,9 @@ void TcpConnection::StartAsyncRead(const defs::connection_t& endPoint)
301300

302301
void TcpConnection::AsyncReadFromSocket(size_t amountToRead)
303302
{
304-
m_receiveBuffer.resize(amountToRead);
305-
306303
// Wrap in strand just to be safe in case of multiple threads running the IO service.
307304
boost_asio::async_read(m_socket,
308-
boost_asio::buffer(m_receiveBuffer),
305+
boost_asio::buffer(m_receiveBuffer.data(), amountToRead),
309306
asio_compat::wrap(m_strand,
310307
boost::bind(&TcpConnection::ReadComplete,
311308
shared_from_this(),
@@ -351,6 +348,7 @@ void TcpConnection::ReadComplete(const boost_sys::error_code& error, size_t byte
351348
// back_inserter solution.
352349
auto const currentSize = m_messageBuffer.size();
353350
m_messageBuffer.resize(currentSize + bytesReceived);
351+
354352
auto dataWritePos = m_messageBuffer.data() + currentSize;
355353
std::copy(m_receiveBuffer.data(), m_receiveBuffer.data() + bytesReceived, dataWritePos);
356354

@@ -394,8 +392,16 @@ void TcpConnection::ReadComplete(const boost_sys::error_code& error, size_t byte
394392
else if (std::numeric_limits<size_t>::max() == numBytes)
395393
{
396394
// We have a problem.
395+
numBytes = m_settings.minAmountToRead;
397396
clearMsgBuf = true;
398397
}
398+
else
399+
{
400+
// We do not want to ever reallocate the m_receiveBuffer beyond its initial
401+
// size, as this would cause a significant performance hit. We will always
402+
// read in up to DEFAULT_SMALL_RESERVED_SIZE chunks.
403+
numBytes = std::min(numBytes, static_cast<size_t>(DEFAULT_SMALL_RESERVED_SIZE));
404+
}
399405
}
400406
catch (...)
401407
{
@@ -411,7 +417,16 @@ void TcpConnection::ReadComplete(const boost_sys::error_code& error, size_t byte
411417

412418
if (clearMsgBuf)
413419
{
414-
m_messageBuffer.clear();
420+
if (m_messageBuffer.capacity() > DEFAULT_LARGE_RESERVED_SIZE)
421+
{
422+
defs::char_buffer_t tmp;
423+
tmp.reserve(DEFAULT_LARGE_RESERVED_SIZE);
424+
m_messageBuffer.swap(tmp);
425+
}
426+
else
427+
{
428+
m_messageBuffer.clear();
429+
}
415430
}
416431

417432
if (numBytes > 0)

docs/Doxyfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ PROJECT_NAME = "Core Library"
4848
# could be handy for archiving the generated documentation or if some version
4949
# control system is used.
5050

51-
PROJECT_NUMBER = 2.0.3
51+
PROJECT_NUMBER = 2.0.4
5252

5353
# Using the PROJECT_BRIEF tag one can provide an optional one line description
5454
# for a project that appears at the top of each page and should give viewers a

docs/html/_abstract_factory_8h_source.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<tbody>
2727
<tr id="projectrow">
2828
<td id="projectalign">
29-
<div id="projectname">Core Library<span id="projectnumber">&#160;2.0.3</span>
29+
<div id="projectname">Core Library<span id="projectnumber">&#160;2.0.4</span>
3030
</div>
3131
<div id="projectbrief">Library containing core utilities and tools for threading, networking, logging, INI and CSV file management etc.</div>
3232
</td>

docs/html/_allocator_8h_source.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<tbody>
2727
<tr id="projectrow">
2828
<td id="projectalign">
29-
<div id="projectname">Core Library<span id="projectnumber">&#160;2.0.3</span>
29+
<div id="projectname">Core Library<span id="projectnumber">&#160;2.0.4</span>
3030
</div>
3131
<div id="projectbrief">Library containing core utilities and tools for threading, networking, logging, INI and CSV file management etc.</div>
3232
</td>

docs/html/_asio_compatibility_8hpp.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<tbody>
2727
<tr id="projectrow">
2828
<td id="projectalign">
29-
<div id="projectname">Core Library<span id="projectnumber">&#160;2.0.3</span>
29+
<div id="projectname">Core Library<span id="projectnumber">&#160;2.0.4</span>
3030
</div>
3131
<div id="projectbrief">Library containing core utilities and tools for threading, networking, logging, INI and CSV file management etc.</div>
3232
</td>

0 commit comments

Comments
 (0)