The Shore yard times the island's rebuild, and the rebuild builds each layer's buffers directly #131

Owner

Tracker: #3610

Step 4a of plan #3558. It gives the coast work of #3620 and #3621 its instrument and room inside its cost budget. Nothing a player sees changes, so there is no changelog entry.

  • The Shore yard times the island's rebuild (src/mock/shore.ts). On its known 256² map it makes the calls view.ts's presentSurface makes that the coast work changes: landLoops, buildSurface with the Toybox look's ground materials, and the shore field's update and upload, then one render. It runs 3 warm-up rebuilds, times 15 as one span, and reports the mean and each part's mean in data-rebuild and in its text. Its shore field timings stay as they are.
  • buildSurface builds each layer's buffers directly (src/client/render/island.ts). The flat caps (land and woods) are triangulated with Earcut on flat arrays, and the bank strips and highway ribbons are written straight into one buffer per material, with no per-run geometries and no mergeGeometries. It draws the same triangles.
  • Tests: a new src/mock/island.test.ts checks over generated islands (seeds 1–8, 64² and 128², Island and Land, Lakes 0, 0.25 and 1) that each flat cap's triangles, the land's and the woods', face up and that their areas sum to its loops' area, outer less holes, to 1e-3. It lives beside the yards because src/client/boundary.test.ts keeps every file under src/client, tests included, from importing the server's map generator. At 64² Island, seeds 6 and 7 collapse in the generator, so that size takes seeds 9 and 10 in their place. The test searches seeds 1–16. It fails, naming the case, when a size, landform and lake share gets fewer than 8 maps there, and when the generator throws anything other than a collapse. map.phone.ts checks that the yard's rebuild of its known 256² map takes at most 40 ms.
  • WOODS_SHADE moves from view.ts to ground.ts, so that the yard draws the woods with the view's shade.

Evidence

Same geometry. In Node at 256², Lakes 0.25, seeds 11 and 42, the head's buildSurface gives the same three meshes as main's, with the same positions, colours and index buffers bit for bit. Seed 11 has 32,994 grass, 4,766 woods and 49,532 road triangles, 87,292 in all. Cap normals differ by 6e-17, because main's rotated ShapeGeometry left that much in z. Bank normals differ by up to 2.7e-4, because main accumulated them in float32 and the head accumulates them in float64.

The rebuild's cost in the Shore yard, Playwright WebKit (iPhone 15 landscape), on s32. Each arm ran 5 sessions of 7 runs, interleaved with the other. Each figure is the median of the runs' means in ms:

arm rebuild landLoops buildSurface shore field render
main 672fc28 24.93 3.07 20.87 0.33 0.67
head 15.07 3.13 11.07 0.27 0.67
delta −9.86 +0.06 −9.80 −0.06 0

The phone estimate is 7.5 × −9.86 = −74 ms per rebuild. Every session's median lies within 0.2 ms of the overall figure. The shore field's own timings are unchanged on both arms (first build 26 ms, reveal 0.7 ms). Main's arm is the head's src/mock/shore.ts over main's modules, built from a git archive of 672fc28. Its only change is that the yard defines const WOODS_SHADE = 0.9 itself, because main's ground.ts does not export it.

Map Yard renders, main against the head, in every finish at 1× and 0.5× under reduced motion. Triangle counts are equal. Two loads of main differ from each other in 39–52k pixels, so the comparison counts only pixels two loads of main agree on. A third load of main changes 5,955–9,162 of them, and the head changes 5,676–9,188. That is load-to-load noise, so the renders do not change.

The seed search ends. In a scratch vitest run with generateIsland mocked to always throw a collapse, the test fails in 0.4 s with "64² landform 0 lakes 0: 0 of 8 maps in seeds 1–16". The search before the bound was still running at 2 minutes with nothing printed past RUN. With a TypeError at seed 3 alone, the test now fails with that TypeError, where before it passed. Unmocked, both versions pass.

Tracker: [#3610](https://sak.swipelab.com/tasks/3610) Step 4a of plan [#3558](https://sak.swipelab.com/tasks/3558). It gives the coast work of [#3620](https://sak.swipelab.com/tasks/3620) and [#3621](https://sak.swipelab.com/tasks/3621) its instrument and room inside its cost budget. Nothing a player sees changes, so there is no changelog entry. - **The Shore yard times the island's rebuild** (src/mock/shore.ts). On its known 256² map it makes the calls view.ts's `presentSurface` makes that the coast work changes: `landLoops`, `buildSurface` with the Toybox look's ground materials, and the shore field's update and upload, then one render. It runs 3 warm-up rebuilds, times 15 as one span, and reports the mean and each part's mean in `data-rebuild` and in its text. Its shore field timings stay as they are. - **`buildSurface` builds each layer's buffers directly** (src/client/render/island.ts). The flat caps (land and woods) are triangulated with Earcut on flat arrays, and the bank strips and highway ribbons are written straight into one buffer per material, with no per-run geometries and no `mergeGeometries`. It draws the same triangles. - **Tests:** a new src/mock/island.test.ts checks over generated islands (seeds 1–8, 64² and 128², Island and Land, Lakes 0, 0.25 and 1) that each flat cap's triangles, the land's and the woods', face up and that their areas sum to its loops' area, outer less holes, to 1e-3. It lives beside the yards because src/client/boundary.test.ts keeps every file under src/client, tests included, from importing the server's map generator. At 64² Island, seeds 6 and 7 collapse in the generator, so that size takes seeds 9 and 10 in their place. The test searches seeds 1–16. It fails, naming the case, when a size, landform and lake share gets fewer than 8 maps there, and when the generator throws anything other than a collapse. map.phone.ts checks that the yard's rebuild of its known 256² map takes at most 40 ms. - `WOODS_SHADE` moves from view.ts to ground.ts, so that the yard draws the woods with the view's shade. ## Evidence **Same geometry.** In Node at 256², Lakes 0.25, seeds 11 and 42, the head's `buildSurface` gives the same three meshes as main's, with the same positions, colours and index buffers bit for bit. Seed 11 has 32,994 grass, 4,766 woods and 49,532 road triangles, 87,292 in all. Cap normals differ by 6e-17, because main's rotated ShapeGeometry left that much in z. Bank normals differ by up to 2.7e-4, because main accumulated them in float32 and the head accumulates them in float64. **The rebuild's cost** in the Shore yard, Playwright WebKit (iPhone 15 landscape), on s32. Each arm ran 5 sessions of 7 runs, interleaved with the other. Each figure is the median of the runs' means in ms: | arm | rebuild | landLoops | buildSurface | shore field | render | |---|---|---|---|---|---| | main 672fc28 | 24.93 | 3.07 | 20.87 | 0.33 | 0.67 | | head | 15.07 | 3.13 | 11.07 | 0.27 | 0.67 | | delta | −9.86 | +0.06 | −9.80 | −0.06 | 0 | The phone estimate is 7.5 × −9.86 = −74 ms per rebuild. Every session's median lies within 0.2 ms of the overall figure. The shore field's own timings are unchanged on both arms (first build 26 ms, reveal 0.7 ms). Main's arm is the head's src/mock/shore.ts over main's modules, built from a `git archive` of 672fc28. Its only change is that the yard defines `const WOODS_SHADE = 0.9` itself, because main's ground.ts does not export it. **Map Yard renders,** main against the head, in every finish at 1× and 0.5× under reduced motion. Triangle counts are equal. Two loads of main differ from each other in 39–52k pixels, so the comparison counts only pixels two loads of main agree on. A third load of main changes 5,955–9,162 of them, and the head changes 5,676–9,188. That is load-to-load noise, so the renders do not change. **The seed search ends.** In a scratch vitest run with `generateIsland` mocked to always throw a collapse, the test fails in 0.4 s with "64² landform 0 lakes 0: 0 of 8 maps in seeds 1–16". The search before the bound was still running at 2 minutes with nothing printed past RUN. With a TypeError at seed 3 alone, the test now fails with that TypeError, where before it passed. Unmocked, both versions pass.
agra merged commit bcae85a6e0 into task/3558-build-inside-the-city-and-a-flat-map 2026-10-22 09:44:57 +03:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
agra/mini-alert!131
No description provided.