I am trying to understand where the bottleneck is when browsing files from the SPIFFS, so I thought I would test separately the SPIFFS read speed and the HTTP download speed. Thinking the latter would probably not be the culprit, I wanted to rule it out so I started by wrapping up a sketch that allows me to download a variable size "file" (generated on the fly). The full sketch is below.
What I'm observing is that building the response one character at a time by repeatedly calling client.write() causes a very high overhead, slowing data transfer.
I compared with a static response using server.send() and there is a factor 1000 in transfer speed for a 1KB payload.
I read that the Nagle algorithm could be in the way so I added a "client.setNoDelay(true);", to no avail.
See this screencast for a how it feels.
So my questions are: what is the reason for this slow transfer and how can I reliably test http download speed ?
And while you're at it, if you have any experience on transfer speed or SPIFFS speed and how to optimize them, please feel free to comment of course.
Kind regards,
Vicne
PS: Test sketch:
#include <Arduino.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> // from lib https://github.com/tzapu/WiFiManager
ESP8266WebServer server(80);
void generateFixedContent() {
server.send(200, "application/octet-stream",
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
);
}
void generateVariableContent() {
if(server.args() == 0) return server.send(500, "text/plain", "Parameter 'size=xxx' is required");
int length = atoi(server.arg(0).c_str());
if(length <= 0) return server.send(500, "text/plain", "Wrong size for parameter");
WiFiClient client = server.client();
client.setNoDelay(true);
String header = "HTTP/1.0 200 OK\r\n";
header += "Content-Type: application/octet-stream\r\n";
header += "Content-Length: " + String(length) + "\r\n";
header += "Content-Disposition: attachment; filename=data_" + String(length) + ".dat\r\n";
header += "Connection: close\r\n";
header += "\r\n";
client.write(header.c_str(), header.length());
for (int i = 0; i< length; i++) {
client.write("A", 1);
}
}
void setup() {
WiFiManager wifiManager;
wifiManager.autoConnect("SpeedTest_CFG");
server.on("/", [](){
server.send(200, "text/html", "<html><body>Use <a href='/fixed'>/fixed</a> or <a href='/variable?size=1000'>/variable?size=1000</a> to generate 1000 bytes</body></html>");
});
server.on("/fixed", generateFixedContent);
server.on("/variable", generateVariableContent);
server.onNotFound([](){
server.send(404, "text/plain", "FileNotFound");
});
server.begin();
}
void loop() {
server.handleClient();
}