`SerializeJson` sends many 1 bytes packets with `EthernetClient` (Massive Slowdown!)
Created by: EmperorArthur
No Buffering
The issue is that <Ethernet.h> does not buffer writes. This may be an issue on there end, but was possibly a deliberate decision to decrease latency, or simplify code. This means that even though the Wiznet chip has a 2K buffer, the example code below sends 101 packets!
While some of these issues are hard to solve (floats and dubles are sent as two packets), at the least it should be possible to send C strings as single packets.
This matters both from an overhead perspective, and because I have observed that large packet counts can significantly increase response time.
How to measure
- Install and start WireShark.
- Select the network interface the Arduino is connected to to start capturing packets.
- Set
ip.addr == 192.168.1.250
in the bar at the top to filter to only packets with the Ardunio. - Browse to
http://192.168.1.250
- Click on "HTTP/1.0 200 OK" when it appears (you may have to scroll)
- If you open up the drop down of reassembled TCP segments, you can scroll down them and watch it highlight what parts of the response belong to the highlighted packet.
Target platform and Compiler information:
- PlatformIO based configuration
- Controllino Maxi Power
- 6.17.2
- 2.0.0
- framework-arduino-avr 5.1.0
- toolchain-atmelavr 1.50400.190710 (5.4.0)
Same issue on the latest Arduino IDE.
Minimal Example:
#include <ArduinoJson.h>
#include <Ethernet.h>
#define IP_ADDRESS IPAddress(192,168,1,250)
byte MAC_ADDRESS[] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5};
#define DNS_ADDRESS IPAddress(1,1,1,1)
#define GATEWAY_ADDRESS IPAddress(192,168,1,1)
auto http_server = EthernetServer(80);
void setup() {
EthernetClass::begin(MAC_ADDRESS, IP_ADDRESS);
http_server.begin();
}
void loop() {
EthernetClient client = http_server.available();
if (!client) {
return;
}
StaticJsonDocument<500> document;
document["C String"] = "This is a C String.";
document["String"] = String("This is a String.");
document["int"] = static_cast<int>(123);
document["float"] = static_cast<float>(0.456);
document["double"] = static_cast<float>(0.789);
auto out = String(F("HTTP/1.0 200 OK\n"
"Content-Type: application/json\n"
"Connection: close\n"
"Content-Length: "));
out += measureJsonPretty(document);
out += "\n\n";
//serializeJsonPretty(document, out);
client.print(out);
serializeJsonPretty(document, client);
client.stop();
}