From f03f80d1b3993f3a187166e053337bccfb268c6b Mon Sep 17 00:00:00 2001 From: David Montero Crespo Date: Mon, 10 Aug 2026 22:58:30 +0200 Subject: [PATCH] =?UTF-8?q?fix(micropython):=20sleepy=20isconnected()/stat?= =?UTF-8?q?us()=20=E2=80=94=20busy-waits=20starved=20idleSkip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The canonical MicroPython connect idiom is `while not wlan.isconnected(): pass` — a pure Python busy-wait, and most gallery WiFi examples use it. The emulated CPU only fast-forwards through WAITI idles, so a busy-wait pins the sim at real execution speed (~2% of the chip in a browser tab). Measured on the classic-ESP32 engine with a marker-bracketed harness: the connect+DHCP phase costs ~1.5M busy instructions under a sleepy poll loop and ~194M under the busy-wait — same firmware, same radio, 130x apart. At browser speed that is close to a minute of wall clock for the connect alone, which reads as "WiFi hangs" and got diagnosed as exactly that. The proxy now sleeps 20ms per unanswered isconnected()/status() poll, turning the user's busy loop into an idle loop without touching their code. Re-measured end-to-end with the real prelude: 226.8M -> 64.3M busy steps, and the made-up-SSID example connects with a 10.13.37.x lease on the in-browser engine. --- frontend/src/store/useSimulatorStore.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/frontend/src/store/useSimulatorStore.ts b/frontend/src/store/useSimulatorStore.ts index 1f2c9f06..2cca724b 100644 --- a/frontend/src/store/useSimulatorStore.ts +++ b/frontend/src/store/useSimulatorStore.ts @@ -2042,6 +2042,7 @@ export const useSimulatorStore = create((set, get) => { // debugs a connection they didn't make. const networkStub = wifiOn ? [ 'import network as _vlx_net', + 'import time as _vlx_time', '_VLX_SSIDS = ("Velxio-GUEST", "PICSimLabWifi", "Espressif", "MasseyWifi")', 'class _VlxWLAN:', ' def __init__(self, *a, **k):', @@ -2053,6 +2054,23 @@ export const useSimulatorStore = create((set, get) => { ' if ssid is None:', ' return self._w.connect()', ' return self._w.connect(ssid, key, **kw)', + // The sleepy poll pair. The canonical connect idiom is + // `while not wlan.isconnected(): pass` — a pure Python busy-wait. + // The emulated CPU only fast-forwards through WAITI idles, so a + // busy-wait pins the sim at real execution speed (~2% of the + // chip) and the handshake that costs ~1.5M instructions under a + // sleepy loop costs ~194M under a busy one — measured; it reads + // as "WiFi hangs". Sleeping 20ms per unanswered poll turns the + // user's busy loop into an idle loop without touching their code. + ' def isconnected(self):', + ' ok = self._w.isconnected()', + ' if not ok:', + ' _vlx_time.sleep_ms(20)', + ' return ok', + ' def status(self, *a):', + ' st = self._w.status(*a)', + ' _vlx_time.sleep_ms(20)', + ' return st', ' def __getattr__(self, n):', ' return getattr(self._w, n)', 'class _VlxNetwork:',