Skip to content
This repository was archived by the owner on Jan 21, 2025. It is now read-only.

Commit eef1bab

Browse files
Merge pull request #171 from mathieucarbou/buffcredit
in-flight buffer credits
2 parents b5fe1b1 + 0dce607 commit eef1bab

7 files changed

Lines changed: 48 additions & 13 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555

5656
- name: Install AsyncTCP (ESP32)
5757
if: ${{ matrix.core == 'esp32:esp32' }}
58-
run: ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL=true arduino-cli lib install --git-url https://github.com/mathieucarbou/AsyncTCP#v3.2.15
58+
run: ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL=true arduino-cli lib install --git-url https://github.com/mathieucarbou/AsyncTCP#v3.3.0
5959

6060
- name: Install ESPAsyncTCP (ESP8266)
6161
if: ${{ matrix.core == 'esp8266:esp8266' }}

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ lib_deps = mathieucarbou/ESPAsyncWebServer @ 3.4.0
8080

8181
**Dependencies:**
8282

83-
- **ESP32 with AsyncTCP**: `mathieucarbou/AsyncTCP @ 3.2.15`
84-
Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.2.15](https://github.com/mathieucarbou/AsyncTCP/releases)
83+
- **ESP32 with AsyncTCP**: `mathieucarbou/AsyncTCP @ 3.3.0`
84+
Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.3.0](https://github.com/mathieucarbou/AsyncTCP/releases)
8585

8686
- **ESP32 with AsyncTCPSock**: `https://github.com/mathieucarbou/AsyncTCPSock/archive/refs/tags/v1.0.3-dev.zip`
8787

@@ -99,7 +99,7 @@ AsyncTCPSock can be used instead of AsyncTCP by excluding AsyncTCP from the libr
9999
lib_compat_mode = strict
100100
lib_ldf_mode = chain
101101
lib_deps =
102-
; mathieucarbou/AsyncTCP @ 3.2.15
102+
; mathieucarbou/AsyncTCP @ 3.3.0
103103
https://github.com/mathieucarbou/AsyncTCPSock/archive/refs/tags/v1.0.3-dev.zip
104104
mathieucarbou/ESPAsyncWebServer @ 3.4.0
105105
lib_ignore =
@@ -116,7 +116,7 @@ Performance of `mathieucarbou/ESPAsyncWebServer @ 3.4.0`:
116116
> autocannon -c 10 -w 10 -d 20 http://192.168.4.1
117117
```
118118

119-
With `mathieucarbou/AsyncTCP @ 3.2.15`
119+
With `mathieucarbou/AsyncTCP @ 3.3.0`
120120

121121
[![](https://mathieu.carbou.me/ESPAsyncWebServer/perf-c10.png)](https://mathieu.carbou.me/ESPAsyncWebServer/perf-c10.png)
122122

docs/index.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ lib_deps = mathieucarbou/ESPAsyncWebServer @ 3.4.0
8080

8181
**Dependencies:**
8282

83-
- **ESP32 with AsyncTCP**: `mathieucarbou/AsyncTCP @ 3.2.15`
84-
Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.2.15](https://github.com/mathieucarbou/AsyncTCP/releases)
83+
- **ESP32 with AsyncTCP**: `mathieucarbou/AsyncTCP @ 3.3.0`
84+
Arduino IDE: [https://github.com/mathieucarbou/AsyncTCP#v3.3.0](https://github.com/mathieucarbou/AsyncTCP/releases)
8585

8686
- **ESP32 with AsyncTCPSock**: `https://github.com/mathieucarbou/AsyncTCPSock/archive/refs/tags/v1.0.3-dev.zip`
8787

@@ -99,7 +99,7 @@ AsyncTCPSock can be used instead of AsyncTCP by excluding AsyncTCP from the libr
9999
lib_compat_mode = strict
100100
lib_ldf_mode = chain
101101
lib_deps =
102-
; mathieucarbou/AsyncTCP @ 3.2.15
102+
; mathieucarbou/AsyncTCP @ 3.3.0
103103
https://github.com/mathieucarbou/AsyncTCPSock/archive/refs/tags/v1.0.3-dev.zip
104104
mathieucarbou/ESPAsyncWebServer @ 3.4.0
105105
lib_ignore =
@@ -116,7 +116,7 @@ Performance of `mathieucarbou/ESPAsyncWebServer @ 3.4.0`:
116116
> autocannon -c 10 -w 10 -d 20 http://192.168.4.1
117117
```
118118

119-
With `mathieucarbou/AsyncTCP @ 3.2.15`
119+
With `mathieucarbou/AsyncTCP @ 3.3.0`
120120

121121
[![](https://mathieu.carbou.me/ESPAsyncWebServer/perf-c10.png)](https://mathieu.carbou.me/ESPAsyncWebServer/perf-c10.png)
122122

library.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
{
2929
"owner": "mathieucarbou",
3030
"name": "AsyncTCP",
31-
"version": "^3.2.15",
31+
"version": "^3.3.0",
3232
"platforms": "espressif32"
3333
},
3434
{

platformio.ini

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ lib_deps =
3131
; bblanchon/ArduinoJson @ 5.13.4
3232
; bblanchon/ArduinoJson @ 6.21.5
3333
bblanchon/ArduinoJson @ 7.2.1
34-
mathieucarbou/AsyncTCP @ 3.2.15
34+
mathieucarbou/AsyncTCP @ 3.3.0
3535
board = esp32dev
3636
board_build.partitions = partitions-4MB.csv
3737
board_build.filesystem = littlefs
@@ -49,7 +49,7 @@ platform = https://github.com/pioarduino/platform-espressif32/releases/download/
4949
; board = esp32-s3-devkitc-1
5050
; board = esp32-c6-devkitc-1
5151
lib_deps =
52-
mathieucarbou/AsyncTCP @ 3.2.15
52+
mathieucarbou/AsyncTCP @ 3.3.0
5353

5454
[env:arduino-310]
5555
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/platform-espressif32.zip
@@ -102,7 +102,7 @@ board = ${sysenv.PIO_BOARD}
102102
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip
103103
board = ${sysenv.PIO_BOARD}
104104
lib_deps =
105-
mathieucarbou/AsyncTCP @ 3.2.15
105+
mathieucarbou/AsyncTCP @ 3.3.0
106106

107107
[env:ci-arduino-310]
108108
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/platform-espressif32.zip

src/WebResponseImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ class AsyncBasicResponse : public AsyncWebServerResponse {
4747

4848
class AsyncAbstractResponse : public AsyncWebServerResponse {
4949
private:
50+
// amount of responce data in-flight, i.e. sent, but not acked yet
51+
size_t _in_flight{0};
52+
// in-flight queue credits
53+
size_t _in_flight_credit{2};
5054
String _head;
5155
// Data is inserted into cache at begin().
5256
// This is inefficient with vector, but if we use some other container,

src/WebResponses.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,21 @@ size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest* request, size_t len, u
352352
request->client()->close();
353353
return 0;
354354
}
355+
// return a credit for each chunk of acked data (polls does not give any credits)
356+
if (len)
357+
++_in_flight_credit;
358+
359+
// for chunked responses ignore acks if there are no _in_flight_credits left
360+
if (_chunked && !_in_flight_credit) {
361+
#ifdef ESP32
362+
log_d("(chunk) out of in-flight credits");
363+
#endif
364+
return 0;
365+
}
366+
355367
_ackedLength += len;
368+
_in_flight -= (_in_flight > len) ? len : _in_flight;
369+
// get the size of available sock space
356370
size_t space = request->client()->space();
357371

358372
size_t headLen = _head.length();
@@ -364,16 +378,31 @@ size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest* request, size_t len, u
364378
String out = _head.substring(0, space);
365379
_head = _head.substring(space);
366380
_writtenLength += request->client()->write(out.c_str(), out.length());
381+
_in_flight += out.length();
382+
--_in_flight_credit; // take a credit
367383
return out.length();
368384
}
369385
}
370386

371387
if (_state == RESPONSE_CONTENT) {
388+
// for response data we need to control the queue and in-flight fragmentation. Sending small chunks could give low latency,
389+
// but flood asynctcp's queue and fragment socket buffer space for large responses.
390+
// Let's ignore polled acks and acks in case when we have more in-flight data then the available socket buff space.
391+
// That way we could balance on having half the buffer in-flight while another half is filling up, while minimizing events in asynctcp q
392+
if (_in_flight > space) {
393+
// log_d("defer user call %u/%u", _in_flight, space);
394+
// take the credit back since we are ignoring this ack and rely on other inflight data
395+
if (len)
396+
--_in_flight_credit;
397+
return 0;
398+
}
399+
372400
size_t outLen;
373401
if (_chunked) {
374402
if (space <= 8) {
375403
return 0;
376404
}
405+
377406
outLen = space;
378407
} else if (!_sendContentLength) {
379408
outLen = space;
@@ -422,6 +451,8 @@ size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest* request, size_t len, u
422451

423452
if (outLen) {
424453
_writtenLength += request->client()->write((const char*)buf, outLen);
454+
_in_flight += outLen;
455+
--_in_flight_credit; // take a credit
425456
}
426457

427458
if (_chunked) {

0 commit comments

Comments
 (0)