Every append found the end of the buffer with strlen(), up to four
times per append and four appends per field, so building a response
cost the square of its size. /discovery fills a 4 KB buffer and spent
about 195 ms of its ~210 ms there (shades 126 ms, groups 69 ms), all on
the async_tcp task that serves every socket and web request.
Keep the length in the formatter and write every append at the end
through one helper. The web response and socket event subclasses and
ControllerChunker use the tracked length too. Output is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add Timing.h and use it to log what holds up the main loop, how long a
new socket client's setup takes, slow socket sends, and how long each
web request took and from which client. Socket connects and disconnects
are logged with how long the client stayed, and late pings as warnings.
Routine sends and pings are not logged, as each line costs several ms
on a 115200 baud console.
Report a stored crash once with the crashed and running build IDs, then
erase it, since it was reported on every boot and its backtrace only
decodes against the build that crashed. Mount the file system once.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When something didn't fit, the formatters skipped it silently, closing
brackets included, and clients got malformed JSON. Two writes could
also go past the buffer:
- AsyncJsonResp flushed when full and then wrote the value without
checking again, so a value bigger than the whole buffer overflowed.
It is now streamed straight out instead.
- JsonSockEvent::closeEvent added the closing ] when only one byte was
left, putting the terminator one byte past the buffer.
The formatters now set an overflowed() flag and log an error, and a
socket event that overflowed is logged and not sent.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
JsonFormatter and BufferedJsonFormatter move verbatim out of
WResp.cpp/WResp.h, which now include JsonFormatter.h. They don't need
the web server, so on their own they can be unit tested on the PC; the
native env builds the new file. AsyncJsonResp and JsonSockEvent stay
in WResp. No behaviour change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>