From 03d3552ee0f5f702eec1e3fbff8f2950044e853b Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Wed, 21 Jun 2023 12:46:15 +0800 Subject: [PATCH 1/2] Avoid unnecessary memory allocation/relocation --- src/base/http/connection.cpp | 19 +++++++++++++++++-- src/base/net/smtp.cpp | 2 +- src/base/path.cpp | 2 +- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/base/http/connection.cpp b/src/base/http/connection.cpp index fc4b18e90..617b64163 100644 --- a/src/base/http/connection.cpp +++ b/src/base/http/connection.cpp @@ -46,6 +46,10 @@ Connection::Connection(QTcpSocket *socket, IRequestHandler *requestHandler, QObj { m_socket->setParent(this); + // reserve common size for requests, don't use the max allowed size which is too big for + // memory constrained platforms + m_receivedData.reserve(1024 * 1024); + // reset timer when there are activity m_idleTimer.start(); connect(m_socket, &QIODevice::readyRead, this, [this]() @@ -66,7 +70,18 @@ Connection::~Connection() void Connection::read() { - m_receivedData.append(m_socket->readAll()); + // reuse existing buffer and avoid unnecessary memory allocation/relocation + const qsizetype previousSize = m_receivedData.size(); + const qint64 bytesAvailable = m_socket->bytesAvailable(); + m_receivedData.resize(previousSize + bytesAvailable); + const qint64 bytesRead = m_socket->read((m_receivedData.data() + previousSize), bytesAvailable); + if (Q_UNLIKELY(bytesRead < 0)) + { + m_socket->close(); + return; + } + if (Q_UNLIKELY(bytesRead < bytesAvailable)) + m_receivedData.chop(bytesAvailable - bytesRead); while (!m_receivedData.isEmpty()) { @@ -116,7 +131,7 @@ void Connection::read() resp.headers[HEADER_CONNECTION] = u"keep-alive"_s; sendResponse(resp); - m_receivedData = m_receivedData.mid(result.frameSize); + m_receivedData.remove(0, result.frameSize); } break; diff --git a/src/base/net/smtp.cpp b/src/base/net/smtp.cpp index 3bd7aba32..94f833810 100644 --- a/src/base/net/smtp.cpp +++ b/src/base/net/smtp.cpp @@ -191,7 +191,7 @@ void Smtp::readyRead() const int pos = m_buffer.indexOf("\r\n"); if (pos < 0) return; // Loop exit condition const QByteArray line = m_buffer.left(pos); - m_buffer = m_buffer.mid(pos + 2); + m_buffer.remove(0, (pos + 2)); qDebug() << "Response line:" << line; // Extract response code const QByteArray code = line.left(3); diff --git a/src/base/path.cpp b/src/base/path.cpp index b41d6e140..5ec30549d 100644 --- a/src/base/path.cpp +++ b/src/base/path.cpp @@ -318,7 +318,7 @@ void Path::stripRootFolder(PathList &filePaths) return; for (Path &filePath : filePaths) - filePath.m_pathStr = filePath.m_pathStr.mid(commonRootFolder.m_pathStr.size() + 1); + filePath.m_pathStr.remove(0, (commonRootFolder.m_pathStr.size() + 1)); } void Path::addRootFolder(PathList &filePaths, const Path &rootFolder) From b3d2ba7d07a291481480bc361e87b93051c6a385 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Fri, 23 Jun 2023 03:07:45 +0800 Subject: [PATCH 2/2] Initialize regex only once This code path is commonly used so let it initialize only once. --- src/base/http/requestparser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/http/requestparser.cpp b/src/base/http/requestparser.cpp index 66f60b458..540f6481c 100644 --- a/src/base/http/requestparser.cpp +++ b/src/base/http/requestparser.cpp @@ -189,7 +189,7 @@ bool RequestParser::parseRequestLine(const QString &line) { // [rfc7230] 3.1.1. Request Line - const QRegularExpression re(u"^([A-Z]+)\\s+(\\S+)\\s+HTTP\\/(\\d\\.\\d)$"_s); + static const QRegularExpression re(u"^([A-Z]+)\\s+(\\S+)\\s+HTTP\\/(\\d\\.\\d)$"_s); const QRegularExpressionMatch match = re.match(line); if (!match.hasMatch())