Measure the explorer, and cap edit mode at what it can carry
Three numbers, taken on the emulator through the app's own render report and written into EXPLORER.md; the fixture tree the sandbox now builds is what they were taken against. The viewer's scan was on the main thread. Decision 8 said off it, and the first version did it in a `remember` inside the composition, which is not that -- 460ms of frozen screen on a 1 MiB file, long enough that the accessibility tree cannot be read, which is exactly what "the app has stopped" looks like from outside. It runs on Dispatchers.Default now, with a spinner where the file will be. Reading a megabyte is otherwise fine: the viewer is a row per line, and it opens and scrolls 28,660 of them. Edit mode needed a cap, and not the one the plan expected. The cost that matters is not the highlighting -- 40ms a keystroke at 128 kB, which is survivable -- it is Compose laying out one enormous text in the field: 2,027ms per frame at 128 kB, with typed characters dropped, and no response at all at 1 MiB. Switching highlighting off would have saved nothing, since every arrangement of a single text field pays it. So EDIT_LIMIT is 32 kB, the largest size actually measured as usable, and above it the pencil is disabled with the reason in words beside it: a disabled control teaches what the thing can do but cannot say why it is off, and a reader who cannot edit a file they can plainly read would otherwise conclude the app is broken. `FileLines.of` is timed like everything else here, so the figure lands in the render report rather than needing a harness to ask for it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9c4d33273b
commit
2c12274285
6 files changed
+147
-24
No files matched your search
+51
-11
@@ -393,18 +393,51 @@ pure functions with tests.
|
||||
`~/repos/emulator-tools`, `ui-trace`'s tap-by-label action; then the
|
||||
two bench scripts onto it, with no coordinate tap left in `app/*.sh`.
|
||||
|
||||
## Numbers to measure, before deciding
|
||||
## What the measurements said (2026-09-04)
|
||||
|
||||
- Scan time for a 1 MiB source file on the emulator, and on the phone
|
||||
through the render report. That decides whether `FILE_LIMIT` is right
|
||||
and whether edit mode highlights every keystroke or only below a size.
|
||||
- Time to first line for a 1 MiB file over the tunnel: the read, the
|
||||
transfer, the scan, the first composition. If the transfer dominates,
|
||||
the route gains nothing from streaming; if the scan does, it moves to
|
||||
a worker with the plain text drawn first.
|
||||
- The `BasicTextField` at 20,000 lines: whether typing stays responsive.
|
||||
If not, edit mode gets a lower cap than the viewer, stated in the
|
||||
editor rather than discovered by a stuck keyboard.
|
||||
Taken on the emulator in a **debug** build, which runs Compose at a
|
||||
fraction of release speed and renders in software -- so these rank
|
||||
correctly against each other and are pessimistic in absolute terms.
|
||||
Generated Rust, through the app's own render report.
|
||||
|
||||
| file | lines | scan + cut | scan per keystroke | worst frame record |
|
||||
|--------|--------|------------|--------------------|--------------------|
|
||||
| 32 kB | 917 | 11ms | 10ms | 183ms |
|
||||
| 128 kB | 3,633 | -- | 40ms | 2,027ms |
|
||||
| 1 MB | 28,660 | 460ms | -- | -- |
|
||||
|
||||
Three things followed.
|
||||
|
||||
**The viewer's scan had to leave the main thread.** Decision 8 said "off
|
||||
the main thread" and the first version did it in a `remember` inside the
|
||||
composition, which is not that: 460ms of frozen screen at the size the
|
||||
server is willing to send, long enough that the accessibility tree cannot
|
||||
be read -- which is exactly what "the app has stopped" looks like from
|
||||
outside. It now runs on `Dispatchers.Default` with a spinner where the file
|
||||
will be.
|
||||
|
||||
**`FILE_LIMIT` at 1 MiB is right for reading.** Time to first line for a
|
||||
1 MiB file, tap to text on screen, was **2.4s** against the sandbox --
|
||||
1.2s of which is that server's deliberate `--delay`, and 460ms the scan.
|
||||
The transfer is not what dominates, so the route gains nothing from
|
||||
streaming.
|
||||
|
||||
**Edit mode needed a cap, and not the one that was expected.** The plan
|
||||
expected to be deciding a size below which highlighting stays on. That is
|
||||
not the cost that matters: highlighting 128 kB costs 40ms a keystroke,
|
||||
which is survivable, while laying the same text out in one
|
||||
`BasicTextField` costs two seconds -- characters typed into it were
|
||||
dropped, and a 1 MiB file stopped the app responding altogether. Since
|
||||
every arrangement of a single text field pays that, switching highlighting
|
||||
off would have saved nothing. So `EDIT_LIMIT` is **32 kB**, the largest
|
||||
size measured as usable, and above it the pencil is disabled with the
|
||||
reason said in words beside it -- a disabled control teaches what the thing
|
||||
can do but cannot say why it is off, and a reader who cannot edit a file
|
||||
they can plainly read would otherwise conclude the app is broken.
|
||||
|
||||
Reading is unaffected: the viewer opens and scrolls the 1 MiB file fine,
|
||||
because it is a `LazyColumn` of lines rather than one text object. That
|
||||
difference is the whole of decision 8.
|
||||
|
||||
## Later, deliberately not now
|
||||
|
||||
@@ -419,3 +452,10 @@ pure functions with tests.
|
||||
- Uploading from the phone into a directory. Attachments already do the
|
||||
upload half; this would be the same route with a chosen destination.
|
||||
- Search within a file, and find-in-files.
|
||||
- **A line-by-line editor**, which is the way past `EDIT_LIMIT`. The
|
||||
viewer already draws a file as rows and stays fast on a megabyte; an
|
||||
editor built the same way -- a field per line, or a field over the lines
|
||||
on screen -- would not pay Compose's cost of laying out one enormous
|
||||
text. It is a good deal more than this feature needed, and 32 kB covers
|
||||
the config files, notes and ordinary source files anybody edits from a
|
||||
phone.
|
||||
Reference in new issue
Block a user