mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 13:52:15 +01:00
refactor: time steps with ElapsedTimer::lap()
loop(), socket client init and /discovery each read a step's time and restarted the timer by hand. lap() does both. Also put the request timing comment back on timeRequest() and say why /discovery logs its steps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
293e013aa2
commit
4544eb6469
6 changed files with 53 additions and 28 deletions
|
|
@ -140,19 +140,16 @@ void SocketEmitter::initClients() {
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
ElapsedTimer total, step;
|
ElapsedTimer total, step;
|
||||||
settings.emitSockets(slot);
|
settings.emitSockets(slot);
|
||||||
logElapsed(TAG, "Socket init settings", step.us());
|
logElapsed(TAG, "Socket init settings", step.lap());
|
||||||
if(!ws.hasClient(asyncId)) { this->newClients[i] = 255; continue; }
|
if(!ws.hasClient(asyncId)) { this->newClients[i] = 255; continue; }
|
||||||
step.restart();
|
|
||||||
somfy.emitState(slot);
|
somfy.emitState(slot);
|
||||||
logElapsed(TAG, "Socket init somfy state", step.us());
|
logElapsed(TAG, "Socket init somfy state", step.lap());
|
||||||
if(!ws.hasClient(asyncId)) { this->newClients[i] = 255; continue; }
|
if(!ws.hasClient(asyncId)) { this->newClients[i] = 255; continue; }
|
||||||
step.restart();
|
|
||||||
git.emitUpdateCheck(slot);
|
git.emitUpdateCheck(slot);
|
||||||
logElapsed(TAG, "Socket init update check", step.us());
|
logElapsed(TAG, "Socket init update check", step.lap());
|
||||||
if(!ws.hasClient(asyncId)) { this->newClients[i] = 255; continue; }
|
if(!ws.hasClient(asyncId)) { this->newClients[i] = 255; continue; }
|
||||||
step.restart();
|
|
||||||
net.emitSockets(slot);
|
net.emitSockets(slot);
|
||||||
logElapsed(TAG, "Socket init network", step.us());
|
logElapsed(TAG, "Socket init network", step.lap());
|
||||||
logElapsed(TAG, "Socket init total", total.us());
|
logElapsed(TAG, "Socket init total", total.us());
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -140,26 +140,22 @@ void loop() {
|
||||||
// Each step only logs when it holds up the loop for LOOP_SLOW_MS or more.
|
// Each step only logs when it holds up the loop for LOOP_SLOW_MS or more.
|
||||||
ElapsedTimer timing;
|
ElapsedTimer timing;
|
||||||
net.loop();
|
net.loop();
|
||||||
logIfSlow(TAG, "Loop net", timing.us(), LOOP_SLOW_MS);
|
logIfSlow(TAG, "Loop net", timing.lap(), LOOP_SLOW_MS);
|
||||||
timing.restart();
|
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
somfy.loop();
|
somfy.loop();
|
||||||
logIfSlow(TAG, "Loop somfy", timing.us(), LOOP_SLOW_MS);
|
logIfSlow(TAG, "Loop somfy", timing.lap(), LOOP_SLOW_MS);
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
if(net.connected() || net.softAPOpened) {
|
if(net.connected() || net.softAPOpened) {
|
||||||
if(!rebootDelay.reboot && net.connected() && !net.softAPOpened) {
|
if(!rebootDelay.reboot && net.connected() && !net.softAPOpened) {
|
||||||
timing.restart();
|
|
||||||
git.loop();
|
git.loop();
|
||||||
logIfSlow(TAG, "Loop git", timing.us(), LOOP_SLOW_MS);
|
logIfSlow(TAG, "Loop git", timing.lap(), LOOP_SLOW_MS);
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
}
|
}
|
||||||
timing.restart();
|
|
||||||
webServer.loop();
|
webServer.loop();
|
||||||
logIfSlow(TAG, "Loop web server", timing.us(), LOOP_SLOW_MS);
|
logIfSlow(TAG, "Loop web server", timing.lap(), LOOP_SLOW_MS);
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
timing.restart();
|
|
||||||
sockEmit.loop();
|
sockEmit.loop();
|
||||||
logIfSlow(TAG, "Loop sockets", timing.us(), LOOP_SLOW_MS);
|
logIfSlow(TAG, "Loop sockets", timing.lap(), LOOP_SLOW_MS);
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
}
|
}
|
||||||
if(rebootDelay.reboot && millis() > rebootDelay.rebootTime) {
|
if(rebootDelay.reboot && millis() > rebootDelay.rebootTime) {
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,14 @@ class ElapsedTimer {
|
||||||
ElapsedTimer() : _start(micros()) {}
|
ElapsedTimer() : _start(micros()) {}
|
||||||
void restart() { _start = micros(); }
|
void restart() { _start = micros(); }
|
||||||
uint32_t us() const { return micros() - _start; }
|
uint32_t us() const { return micros() - _start; }
|
||||||
|
// The time since the last lap (or start) and starts the next one, for
|
||||||
|
// timing a series of steps.
|
||||||
|
uint32_t lap() {
|
||||||
|
const uint32_t now = micros();
|
||||||
|
const uint32_t us = now - _start;
|
||||||
|
_start = now;
|
||||||
|
return us;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Whether logElapsed() would print a timing this long. Check it before
|
// Whether logElapsed() would print a timing this long. Check it before
|
||||||
|
|
|
||||||
22
src/Web.cpp
22
src/Web.cpp
|
|
@ -703,8 +703,8 @@ void Web::handleDiscovery(AsyncWebServerRequest *request) {
|
||||||
char connType[10] = "Unknown";
|
char connType[10] = "Unknown";
|
||||||
if(net.connType == conn_types_t::ethernet) strcpy(connType, "Ethernet");
|
if(net.connType == conn_types_t::ethernet) strcpy(connType, "Ethernet");
|
||||||
else if(net.connType == conn_types_t::wifi) strcpy(connType, "Wifi");
|
else if(net.connType == conn_types_t::wifi) strcpy(connType, "Wifi");
|
||||||
// This handler takes about 200ms on the async_tcp task for no obvious
|
// This handler runs on the async_tcp task, which also serves the sockets,
|
||||||
// reason, so time each part to find out where it goes.
|
// so a slow one is logged with where its time went.
|
||||||
ElapsedTimer total, step;
|
ElapsedTimer total, step;
|
||||||
uint32_t usHead, usMem, usRooms, usShades, usGroups, usSend;
|
uint32_t usHead, usMem, usRooms, usShades, usGroups, usSend;
|
||||||
AsyncJsonResp resp;
|
AsyncJsonResp resp;
|
||||||
|
|
@ -720,7 +720,7 @@ void Web::handleDiscovery(AsyncWebServerRequest *request) {
|
||||||
resp.addElem("chipModel", settings.chipModel);
|
resp.addElem("chipModel", settings.chipModel);
|
||||||
resp.addElem("connType", connType);
|
resp.addElem("connType", connType);
|
||||||
resp.addElem("checkForUpdate", settings.checkForUpdate);
|
resp.addElem("checkForUpdate", settings.checkForUpdate);
|
||||||
usHead = step.us(); step.restart();
|
usHead = step.lap();
|
||||||
resp.beginObject("memory");
|
resp.beginObject("memory");
|
||||||
resp.addElem("max", ESP.getMaxAllocHeap());
|
resp.addElem("max", ESP.getMaxAllocHeap());
|
||||||
resp.addElem("free", ESP.getFreeHeap());
|
resp.addElem("free", ESP.getFreeHeap());
|
||||||
|
|
@ -728,20 +728,20 @@ void Web::handleDiscovery(AsyncWebServerRequest *request) {
|
||||||
resp.addElem("total", ESP.getHeapSize());
|
resp.addElem("total", ESP.getHeapSize());
|
||||||
resp.addElem("uptime", (uint64_t)millis());
|
resp.addElem("uptime", (uint64_t)millis());
|
||||||
resp.endObject();
|
resp.endObject();
|
||||||
usMem = step.us(); step.restart();
|
usMem = step.lap();
|
||||||
resp.beginArray("rooms");
|
resp.beginArray("rooms");
|
||||||
serializeRooms(resp);
|
serializeRooms(resp);
|
||||||
resp.endArray();
|
resp.endArray();
|
||||||
usRooms = step.us(); step.restart();
|
usRooms = step.lap();
|
||||||
resp.beginArray("shades");
|
resp.beginArray("shades");
|
||||||
serializeShades(resp);
|
serializeShades(resp);
|
||||||
resp.endArray();
|
resp.endArray();
|
||||||
usShades = step.us(); step.restart();
|
usShades = step.lap();
|
||||||
resp.beginArray("groups");
|
resp.beginArray("groups");
|
||||||
serializeGroups(resp);
|
serializeGroups(resp);
|
||||||
resp.endArray();
|
resp.endArray();
|
||||||
resp.endObject();
|
resp.endObject();
|
||||||
usGroups = step.us(); step.restart();
|
usGroups = step.lap();
|
||||||
resp.endResponse();
|
resp.endResponse();
|
||||||
usSend = step.us();
|
usSend = step.us();
|
||||||
net.needsBroadcast = true;
|
net.needsBroadcast = true;
|
||||||
|
|
@ -1279,10 +1279,6 @@ void Web::handleNotFound(AsyncWebServerRequest *request) {
|
||||||
request->send(404, _encoding_text, g_async_content);
|
request->send(404, _encoding_text, g_async_content);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logs how long a request takes to handle and, once the connection closes, how
|
|
||||||
// long the whole exchange took. The total includes chunked bodies like
|
|
||||||
// /controller that are built while they are sent, after the handler returns.
|
|
||||||
// The server name must be a literal as the disconnect handler keeps it.
|
|
||||||
// Logs how long part of a request took, when it is worth logging.
|
// Logs how long part of a request took, when it is worth logging.
|
||||||
static void logRequestTime(const char *server, AsyncWebServerRequest *request, const IPAddress &ip, const char *part, uint32_t us) {
|
static void logRequestTime(const char *server, AsyncWebServerRequest *request, const IPAddress &ip, const char *part, uint32_t us) {
|
||||||
if(!worthLogging(us)) return;
|
if(!worthLogging(us)) return;
|
||||||
|
|
@ -1291,6 +1287,10 @@ static void logRequestTime(const char *server, AsyncWebServerRequest *request, c
|
||||||
ip[0], ip[1], ip[2], ip[3], part);
|
ip[0], ip[1], ip[2], ip[3], part);
|
||||||
logElapsed(TAG, what, us);
|
logElapsed(TAG, what, us);
|
||||||
}
|
}
|
||||||
|
// Logs how long a request takes to handle and, once the connection closes, how
|
||||||
|
// long the whole exchange took. The total includes chunked bodies like
|
||||||
|
// /controller that are built while they are sent, after the handler returns.
|
||||||
|
// The server name must be a literal as the disconnect handler keeps it.
|
||||||
static void timeRequest(AsyncWebServerRequest *request, ArMiddlewareNext next, const char *server) {
|
static void timeRequest(AsyncWebServerRequest *request, ArMiddlewareNext next, const char *server) {
|
||||||
ElapsedTimer timer;
|
ElapsedTimer timer;
|
||||||
// Taken now as the client may already be gone when the disconnect runs.
|
// Taken now as the client may already be gone when the disconnect runs.
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,9 @@ typedef uint8_t byte;
|
||||||
|
|
||||||
// Fixed so anything formatted from it is deterministic.
|
// Fixed so anything formatted from it is deterministic.
|
||||||
inline unsigned long millis() { return 0; }
|
inline unsigned long millis() { return 0; }
|
||||||
inline unsigned long micros() { return 0; }
|
// Tests that measure time set this.
|
||||||
|
inline unsigned long stubMicros = 0;
|
||||||
|
inline unsigned long micros() { return stubMicros; }
|
||||||
inline bool getLocalTime(struct tm *info, uint32_t ms = 5000) {
|
inline bool getLocalTime(struct tm *info, uint32_t ms = 5000) {
|
||||||
(void)ms;
|
(void)ms;
|
||||||
time_t now = time(nullptr);
|
time_t now = time(nullptr);
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,26 @@ static void test_worthLogging_from_the_threshold() {
|
||||||
TEST_ASSERT_TRUE(worthLogging(UINT32_MAX));
|
TEST_ASSERT_TRUE(worthLogging(UINT32_MAX));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* ElapsedTimer
|
||||||
|
********************************************************************/
|
||||||
|
static void test_elapsedTimer_lap_times_each_step() {
|
||||||
|
stubMicros = 1000;
|
||||||
|
ElapsedTimer timer;
|
||||||
|
stubMicros = 1250;
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(250, timer.lap());
|
||||||
|
stubMicros = 1300;
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(50, timer.lap());
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(0, timer.us());
|
||||||
|
}
|
||||||
|
static void test_elapsedTimer_lap_across_micros_wrap() {
|
||||||
|
stubMicros = 0xFFFFFF00UL;
|
||||||
|
ElapsedTimer timer;
|
||||||
|
stubMicros = 0x100;
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(0x200, timer.lap());
|
||||||
|
stubMicros = 0;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
@ -51,5 +71,7 @@ int main(int argc, char **argv) {
|
||||||
RUN_TEST(test_logLock_no_wait_allowed);
|
RUN_TEST(test_logLock_no_wait_allowed);
|
||||||
RUN_TEST(test_worthLogging_fast_timings_are_skipped);
|
RUN_TEST(test_worthLogging_fast_timings_are_skipped);
|
||||||
RUN_TEST(test_worthLogging_from_the_threshold);
|
RUN_TEST(test_worthLogging_from_the_threshold);
|
||||||
|
RUN_TEST(test_elapsedTimer_lap_times_each_step);
|
||||||
|
RUN_TEST(test_elapsedTimer_lap_across_micros_wrap);
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue