diff options
Diffstat (limited to 'docs/DEVELOPER_GUIDE.md')
| -rw-r--r-- | docs/DEVELOPER_GUIDE.md | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/docs/DEVELOPER_GUIDE.md b/docs/DEVELOPER_GUIDE.md index 74eff63..d9b7c98 100644 --- a/docs/DEVELOPER_GUIDE.md +++ b/docs/DEVELOPER_GUIDE.md @@ -87,7 +87,9 @@ The simulator is a GTK program. The scripts start it on a virtual display (Xvfb - Anything long runs as a `Jobs.Job` with a bounded step (`Kdf.ITERATIONS_PER_STEP` = 100). - Screens compute at most one SHA-512 code per event, in a timer event separate from drawing. - The scripted UI flow runs on the 255S profile, so a regression trips there. - - **M8 found that step sizes guessed from "bytecodes per loop" were 2 to 3 times too large**: a simple loop iteration costs 50 to 70 counted bytecodes, not 10 to 20. Every step of the 2D encoders, the cache packer and the run finder is now sized by measurement in `make watchdog`, which runs the largest input of each with *two* steps per event: a pass means every step uses at most half the budget. Do the same for any new job: add its worst input to `StressTest.start()`. + - **M8 found that step sizes guessed from "bytecodes per loop" were 2 to 3 times too large**: a simple loop iteration costs 50 to 70 counted bytecodes, not 10 to 20. Every step of the 2D encoders, the cache packer and the run finder is now sized by measurement in `make watchdog`, which runs the largest input of each with *two* steps per event: a pass means every step uses at most half the budget. Do the same for any new job: add its worst input to `StressTest.start()`. Work on the vault goes in a `StressTest.VaultCase`: a setup in bounded steps on a RAM backend, then the measured event, done for two identical vaults. + - Per-byte VM loops, measured on the Forerunner 70 in 2026-10: zeroing (`Bytes.wipe`) about 15 bytecodes per byte, the UTF-8 check 20 to 29. With about 60,000 bytecodes per step (half the 255S's event), a 4 KB buffer can't be wiped or checked in one step: `Jobs.Wiper` wipes 2 KB per step, `Bytes.utf8Prefix` checks in pieces, and `SealedBox.sealKeep`/`openKeep` hand AES's padded copies to the caller's wiper. + - The work after a correct PIN (promoting pending entries, applying "Require PIN") is a job too (`ChangeQueue.LockJob`), run by `PinView` before it continues. In 0.9.0 it ran in the event of the last PBKDF2 step and 16 waiting "Require PIN" changes tripped the watchdog on the Forerunner 70. - `Jobs.JobRunner` runs one step per 50 ms tick on the 512 KB watches and two on the others (`Jobs.stepsPerTick`, by app memory). `tools/gen_products.py --check` (part of `make lint`) fails if a product's `watchdogCount` doesn't match that rule. - Drawing counts too: one `fillRectangle` per run in `onUpdate` is fine up to about 1,500 runs per 120,000 bytecodes. `RunsPainter` paints larger codes into a buffered bitmap in steps first (the Venu X1 fits a QR with 8,000 runs). - `StringUtil.convertEncodedString` stops the app with an uncatchable "System Error" on invalid UTF-8; `try` doesn't help. Decode untrusted bytes with `Bytes.toUtf8`, which validates first. |
