From c4253056cfead7d00d2fac8edb55f73cfdda850c Mon Sep 17 00:00:00 2001 From: Will Miles Date: Thu, 5 Sep 2024 22:25:52 -0400 Subject: [PATCH 1/3] AsyncResponseStream: Use DynamicBufferList Reduce allocator load by allocing in blocks. --- src/WebResponseImpl.h | 6 +++--- src/WebResponses.cpp | 34 ++++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/WebResponseImpl.h b/src/WebResponseImpl.h index 3ac57c23b..48595e18f 100644 --- a/src/WebResponseImpl.h +++ b/src/WebResponseImpl.h @@ -119,11 +119,11 @@ class AsyncProgmemResponse: public AsyncAbstractResponse { virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; }; -class cbuf; - class AsyncResponseStream: public AsyncAbstractResponse, public Print { private: - cbuf *_content; + DynamicBufferList _content; + DynamicBufferListPrint _print; + size_t _offset; public: AsyncResponseStream(const String& contentType, size_t bufferSize); ~AsyncResponseStream(); diff --git a/src/WebResponses.cpp b/src/WebResponses.cpp index 7554791ea..3d1563c7a 100644 --- a/src/WebResponses.cpp +++ b/src/WebResponses.cpp @@ -714,32 +714,42 @@ size_t AsyncProgmemResponse::_fillBuffer(uint8_t *data, size_t len){ * Response Stream (You can print/write/printf to it, up to the contentLen bytes) * */ -AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t bufferSize){ +AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t bufferSize) : _print(_content, bufferSize), _offset(0) { _code = 200; _contentLength = 0; _contentType = contentType; - _content = new cbuf(bufferSize); } AsyncResponseStream::~AsyncResponseStream(){ - delete _content; + ; } size_t AsyncResponseStream::_fillBuffer(uint8_t *buf, size_t maxLen){ - return _content->read((char*)buf, maxLen); + size_t read = 0; + while((maxLen > 0) && !_content.empty()) { + auto& dbuf = _content.front(); + auto to_read = std::min(dbuf.size() - _offset, maxLen); + memcpy(buf, dbuf.data() + _offset, to_read); + buf += to_read; + maxLen -= to_read; + read += to_read; + _offset += to_read; + if (_offset == dbuf.size()) { + _content.pop_front(); + _offset = 0; + } + } + + return read; } size_t AsyncResponseStream::write(const uint8_t *data, size_t len){ if(_started()) return 0; - - if(len > _content->room()){ - size_t needed = len - _content->room(); - _content->resizeAdd(needed); - } - size_t written = _content->write((const char*)data, len); - _contentLength += written; - return written; + + auto size = _print.write(data, len); + _contentLength += size; + return size; } size_t AsyncResponseStream::write(uint8_t data){ From 0e8446158325cdae8d627c0b47d58391c3030d72 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Fri, 6 Sep 2024 19:05:39 -0400 Subject: [PATCH 2/3] AsyncResponseStream: Use TCP_MSS as default size --- src/ESPAsyncWebServer.h | 2 +- src/WebResponseImpl.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ESPAsyncWebServer.h b/src/ESPAsyncWebServer.h index 58aa27df9..20be1cb47 100644 --- a/src/ESPAsyncWebServer.h +++ b/src/ESPAsyncWebServer.h @@ -249,7 +249,7 @@ class AsyncWebServerRequest { AsyncWebServerResponse *beginResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback=nullptr); AsyncWebServerResponse *beginResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr); AsyncWebServerResponse *beginChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr); - AsyncResponseStream *beginResponseStream(const String& contentType, size_t bufferSize=1460); + AsyncResponseStream *beginResponseStream(const String& contentType, size_t bufferSize=TCP_MSS); AsyncWebServerResponse *beginResponse_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback=nullptr); AsyncWebServerResponse *beginResponse_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback=nullptr); diff --git a/src/WebResponseImpl.h b/src/WebResponseImpl.h index 48595e18f..a8d8122fe 100644 --- a/src/WebResponseImpl.h +++ b/src/WebResponseImpl.h @@ -125,7 +125,7 @@ class AsyncResponseStream: public AsyncAbstractResponse, public Print { DynamicBufferListPrint _print; size_t _offset; public: - AsyncResponseStream(const String& contentType, size_t bufferSize); + AsyncResponseStream(const String& contentType, size_t bufferSize=TCP_MSS); ~AsyncResponseStream(); bool _sourceValid() const { return (_state < RESPONSE_END); } virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override; From 2a96c83ec2f5fb1db92763a62eb2512f1fb26c99 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Sun, 8 Sep 2024 16:35:42 -0400 Subject: [PATCH 3/3] Fix missing include --- src/WebResponseImpl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/WebResponseImpl.h b/src/WebResponseImpl.h index a8d8122fe..e0e0fc18a 100644 --- a/src/WebResponseImpl.h +++ b/src/WebResponseImpl.h @@ -28,6 +28,8 @@ #endif #include #include "default_init_allocator.h" +#include "DynamicBuffer.h" + // It is possible to restore these defines, but one can use _min and _max instead. Or std::min, std::max. class AsyncBasicResponse: public AsyncWebServerResponse {