From 87036bdfe9fe6c574013c1d08ae88c4035ad664f Mon Sep 17 00:00:00 2001 From: Kyler Ramsey Date: Tue, 22 Sep 2026 05:23:29 -0700 Subject: [PATCH 1/3] PL8: bring the version, check count and verified-in-game notes up to date README said 0.1.2 and that nothing after 0.1.0 had been played; it now says 0.1.3, what has been played since, and that the zip is dist\PerformanceLog-.zip (the manifest's version, as build.ps1 names it). CLAUDE.md said "about 70" C# checks; it is 91 at 0.1.3, and it now points at docs/TESTING.md for the current count. Its "what is verified" note mentioned only the 0.1.0 run. docs/TESTING.md said nothing from 0.1.1 onward had run in a game. The 0.1.3 session 2026-09-21_23-13-11 (43.9 minutes, ten mods, defaults) shows item 1 (the 0.1.1 fixes: 3 wrapper swaps, workingMB 5587-7090, game singletons labelled "game", heap growth on 310 loading rows, Draw Calls largest 37554, LoadAll 1) and item 8 (deep installed, 47081184 sampled component calls, 3475 component rows). They move to a new "verified in a real game" section with the lines that show them. Item 1 keeps only zipping a folder while the game runs, which no recording can show. Items 2, 3 and 7 stay open; item 7 now notes that PerformanceSettings.Load() ran against the real Mod Settings services (a load row in profile.csv, and defaults that an unloaded setting would have clamped to 1 or 0). The mod's own cost estimate (0.45% of a frame) is recorded with the caveat that it rests on patchCallNs 0. The CHANGELOG's 0.1.3 heading drops "not yet played", and its note that nobody had played it now says that was at release. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 5 +++-- CLAUDE.md | 13 +++++------ README.md | 9 +++++--- docs/TESTING.md | 57 ++++++++++++++++++++++++++++++++++--------------- 4 files changed, 56 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf9e497..c044c3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 0.1.3 (preview, not yet played) +## 0.1.3 (preview) **The defaults now capture the most detail a session can hold without anyone touching a setting**, so every recording made from a plain install is as informative as this mod can make it. @@ -17,7 +17,8 @@ install is as informative as this mod can make it. rather than the depth of any one row, and the budget system above already throttles itself if measuring gets expensive, so there was no clear "more detail" case for moving them, only a "more rows" one. - Expect a real, measurable increase in the mod's own cost from this alone — deep's component sampling plus double the sampling budget. - Nobody has played it yet; the five-minute check in `docs/TESTING.md` now starts by checking `overheadUs` is still reasonable. + Nobody had played it when it was released (it has been since: see `docs/TESTING.md`); the five-minute check there now starts by checking `overheadUs` + is still reasonable. ## 0.1.2 (preview, not yet played) diff --git a/CLAUDE.md b/CLAUDE.md index 0b0e53b..28291cd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -47,7 +47,7 @@ packaging/ manifest.json, PerformanceLog.cfg. build.ps1 builds, tests and ``` .\build.ps1 -SkipTests build + package -dotnet run --project tests -c Release all C# checks (about 70) +dotnet run --project tests -c Release all C# checks (91 at 0.1.3; docs/TESTING.md keeps the current count) python -m unittest discover -s tools -p "test_perflog.py" dotnet run --project tests -c Release -- --print-columns dotnet run --project tests -c Release -- --write-sample tests/fixtures/sample-with-mod @@ -106,12 +106,13 @@ To read the game's own code (the way every patch target here was checked): `ilsp ## What is and is not verified -0.1.0 was run once in the real game (2026-09-20, 31 minutes, nine mods including BeaverBuddies, clean exit). Its recording is why 0.1.1 exists: see `CHANGELOG.md` and `docs/TESTING.md` -(what that run proved, what it broke, and what is still unproven). When you are given a recording, start with the `# capability` and `# capability-final` lines in the `frames.csv` -header and the "Read first" section of `summary.md`: they say which parts worked. `python tools/perflog.py report ` prints a `KNOWN ISSUE` line for every known defect of the -version that made it (`KNOWN_ISSUES` in `tools/perflog.py`); add to that list whenever a version is found to record something wrong. +0.1.0 was first run in the real game on 2026-09-20 (31 minutes, nine mods including BeaverBuddies, clean exit). Its recording is why 0.1.1 exists; 0.1.1 and 0.1.3 have been +recorded in the game since. See `CHANGELOG.md` and `docs/TESTING.md` (what those runs proved, what the first one broke, and what is still unproven). When you are given a +recording, start with the `# capability` and `# capability-final` lines in the `frames.csv` header and the "Read first" section of `summary.md`: they say which parts worked. +`python tools/perflog.py report ` prints a `KNOWN ISSUE` line for every known defect of the version that made it (`KNOWN_ISSUES` in `tools/perflog.py`); add to that list +whenever a version is found to record something wrong. -Two lessons from that run that shape how to change this code: +Lessons from the first run that shape how to change this code: - **Count what a patch really does.** `# capability-final|patchCalls|...` showed 488601 wrapper swaps in 122150 frames: the hit counters are how a defect that only exists in the game shows up. Keep a counter for anything done once per game or per frame. - **The game keeps more than one singleton service alive** (the application's and the game's, both updated every frame), so anything remembered "per service" must hold several diff --git a/README.md b/README.md index 8701ad6..66eaafe 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,11 @@ A Timberborn 1.1 mod (built against **1.1.2.4**) that measures **where the game' person, or an AI assistant such as Claude, can read to find out why a game is slow. It is a diagnostic tool for finding performance problems in the game and in other mods. It does nothing else. -Version **0.1.2** is a **preview**. Its automated checks run against the game's real assemblies, and version 0.1.0 has been played once (a 31 minute session with +Version **0.1.3** is a **preview**. Its automated checks run against the game's real assemblies. Version 0.1.0 was the first to be played (a 31 minute session with nine mods, ending in a normal exit): every patch applied and the recording was complete. That first recording also showed several defects, fixed in 0.1.1; 0.1.2 -adds an in-game settings page and has not itself been played yet. See [CHANGELOG.md](CHANGELOG.md) for what changed in each version. If a part fails to start it +added an in-game settings page, and 0.1.3 made the most detailed profile the default. 0.1.1 and 0.1.3 have been played since, and a 44 minute 0.1.3 recording with +ten mods shows the 0.1.1 fixes and the new defaults working; whether a value changed on the settings page reaches a recording is not verified yet. See +[CHANGELOG.md](CHANGELOG.md) for what changed in each version. If a part fails to start it says so in the log and the summary, that part stays off, and the game carries on. Read [docs/TESTING.md](docs/TESTING.md) for what is and is not verified, and how to check it in a game in five minutes. @@ -134,7 +136,8 @@ Install the .NET 8 SDK and Python 3, and have Timberborn (and the Harmony Worksh .\build.ps1 -GameDir 'C:\Program Files (x86)\Steam\steamapps\common\Timberborn' ``` -builds the mod, runs the checks, and creates `dist\PerformanceLog-0.1.2.zip`. `.\build.ps1 -Install` also copies it into your `Mods` folder. The checks alone: +builds the mod, runs the checks, and creates `dist\PerformanceLog-.zip` (the version in `packaging/manifest.json`). `.\build.ps1 -Install` also copies it into +your `Mods` folder. The checks alone: ``` dotnet run --project tests -c Release diff --git a/docs/TESTING.md b/docs/TESTING.md index 776e3c4..c36ca83 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -1,8 +1,8 @@ # What has been checked, and how to check the rest in a game -Version 0.1.0 was run in a game once (the first recording, below); 0.1.1 fixed what that showed, 0.1.2 added an in-game settings page, and 0.1.3 changed -the defaults to `Profile = deep` and a wider sampling budget, for the most detail with nothing configured. Nothing from 0.1.1 onward has been tested with -the game running. This is the honest list. +Version 0.1.0 was the first to run in a game (the first recording, below); 0.1.1 fixed what that showed, 0.1.2 added an in-game settings page, and 0.1.3 +changed the defaults to `Profile = deep` and a wider sampling budget, for the most detail with nothing configured. 0.1.1 and 0.1.3 have both been played +since, and a 0.1.3 recording (below) shows the 0.1.1 fixes and the `deep` default working. This is the honest list. ## Verified by the automated checks @@ -56,13 +56,42 @@ Did not work, or was wrong (all fixed in 0.1.1, see the changelog): the wrapper loading steps, the `LoadAll never ran` counter, and `prDraw`/`prBatches` 0. Not available in this game, and not going to be: `GC Allocated In Frame`, `GC Allocation In Frame Count` and `Batches Count` do not exist in Unity 6's player (they are not in `UnityPlayer.dll`), and -the mod's probe rejected `GC.GetAllocatedBytesForCurrentThread` (the method is in the game's `mscorlib.dll` and Mono runtime; 0.1.0 did not record why, 0.1.1 does), so **allocation is the size of the managed -heap and is coarse**. The per-singleton `KB/s` figures are therefore only good in aggregate. +the mod's probe rejected `GC.GetAllocatedBytesForCurrentThread` (the method is in the game's `mscorlib.dll` and Mono runtime; 0.1.0 did not record why, and every recording since says it +`did not count a 64 KB allocation (read 0, then 0)`), so **allocation is the size of the managed heap and is coarse**. The per-singleton `KB/s` figures are therefore only good in aggregate. + +## Verified in a real game: 0.1.3 with its defaults (2026-09-21) + +Session `2026-09-21_23-13-11`: the same computer, game and Unity as the first recording, ten mods (BeaverBuddies MultiColony 1.4.0-beta2, Late Game Performance 0.4.23, +MixedStorage 0.5.8, Hungry Pathing 0.1.0, Optimized Local Housing 1.0.1, Persistent Work Areas 0.1.3, The Tipsy Tail 0.2.7.0, Mod Settings, Harmony and this mod) and every +setting at its default (the `# config:` header line). 43.9 minutes: 236917 frames and 25511 ticks (76% of the frames at speed 7), a colony of 359 beavers and 11.7 thousand +entities, nine saves (eight queued, one on exit) and a normal exit (`session-end`, "the game was left"). The window was in the background for 81% of the frames, so this +recording says little about the frame rate. + +What it shows, and the line that shows it: +- **The 0.1.1 fixes** (item 1 of the list below until this recording; zipping a folder while the game runs is still there): + - Each singleton service is wrapped once: `# capability-final|patchCalls|singleton wrappers put in place|3` in 236918 frames (0.1.0: 488601 in 122150). Every 0.1.1 and + 0.1.3 recording that reached its closing lines says 2 to 5. + - `workingMB` is 5587 to 7090 in the `S` rows, and `# capability|workingSet|from Windows`. + - The game's own singletons are labelled `game`: no singleton row in `profile.csv` has an empty `mod`. + - Loading steps carry the heap growth: 310 of the 618 loading rows in `profile.csv` have a non-zero `allocKB`, and `summary.md` lists the steps that grew the heap most + (`WorldEntitiesLoader` 411 MB of 2212 MB in all steps). + - `prDraw` is non-zero: `# capability-final|profilerRecorder|Draw Calls Count|produced values, largest 37554`, about 16.6 thousand draw calls a frame on average. + - `# capability-final|patchCalls|SingletonLifecycleService.LoadAll|1`, not `never ran`, and the allocation source line says why the exact counter is not used (above). +- **`Profile = deep` as the default** (item 8 of the list below until this recording): `# capability|patch|TickableEntity.Tick|installed` and + `# capability|patch|MeteredTickableComponent.Tick|installed`, `# capability-final|patchCalls|MeteredTickableComponent.Tick (sampled calls)|47081184`, and 3475 `component` + rows in `profile.csv` for 47 component classes (`BehaviorManager` the biggest). All eight 0.1.3 recordings so far say `# profile: deep`. +- **The settings page's `Load()` against the real Mod Settings services** (part of item 7): `profile.csv` has a `load` row for `PerformanceLog.PerformanceSettings` + (once, 0.10 ms), and the `# config:` header line has the six numbers at their defaults after `PerformanceSettings.ApplyTo` ran on them; a setting `Load()` had not + filled would have read 0 and been clamped to its minimum (`SlowFrameMs` 1, `SpikeContributors` 0). `Player.log` (it keeps only the latest launch, session + `2026-09-22_00-39-06`) has no warning or exception from this mod or Mod Settings. +- **What measuring cost, by the mod's own estimate:** `overheadUs` + `probeUs` averaged 50 µs of an 11.1 ms frame, 0.45% (0.5% in the windows at speed 7 with the game in front, + 0.8% in the costliest window), under the report's 2% line. That estimate rests on a patch cost the calibration read as 0 (`# calibration|...|patchCallNs|0`, as in every + recording so far), which charges each per-call patch either the 40 ns default or next to nothing, not a measurement; item 2 still stands. ## Still not verified: needs the running game -1. **The 0.1.1 fixes themselves**: that each service is wrapped once (`# capability-final|patchCalls|singleton wrappers put in place` should be a handful, not hundreds of thousands), that the four files - can be zipped while the game runs, that `workingMB` is non-zero, that game singletons show `game`, that loading steps show a heap growth, and that `prDraw` is non-zero. +1. **Copying or zipping a session folder while the game runs** (0.1.1): a recording cannot show it. `WriterTests.ReadableWhileRunning` and `RetriesWhenHeld` check it outside + the game. The other 0.1.1 fixes are verified in the game (above). 2. **Overhead** measured against a game running without the mod. The mod's own estimate (0.1.0: 0.3% of a frame paused, 0.8% at speed 7) left out the wrapper swapping and used a default cost for a patch; 0.1.1 measures the patch cost, but nobody has compared the frame rate with the mod off. See the checklist. 3. **Co-op**: with BeaverBuddies actually connected to another player. It has only been seen running with BeaverBuddies loaded in a single-player game. @@ -71,16 +100,10 @@ heap and is coarse**. The per-singleton `KB/s` figures are therefore only good i a mod whose DLL is not in its own folder may still read as unknown. 6. **The report's advice on a bad recording.** The first recording was mostly paused and in the background, so the findings for real problems (a slow simulation, a saving hitch, a memory leak, a mod that costs too much) have been exercised on made-up sessions and one real, healthy one. -7. **The in-game settings page (0.1.2, entirely unplayed)**: that Mod Settings actually shows it, that `RangeIntModSetting` renders as something usable and - the readonly note as readable text, and that `PerformanceSettings.Load()` does not throw against the real `ISettings`/`ModRepository`/`ModSettingsOwnerRegistry` - (only checked against `null`s standing in for them, which never calls `Load()`; see `Settings.cs`'s own notes). Then that a value changed there actually - reaches `Session.Start` — change `SlowFrameMs`, load a save, and check `frames.csv`'s `# thresholdMs` header line against what was set. -8. **`Profile = deep` as the default (0.1.3, entirely unplayed)**: the first recording used `standard`, so the patch on `MeteredTickableComponent.Tick` - (every entity component, sampled) has never actually run in a real game — only had its target validated against the real assemblies. Check that it - installs (`# capability|patch|TickableEntity.Tick`/`MeteredTickableComponent.Tick|installed` in the header) and that `profile.csv` gets `component` - rows. Check the real cost too: the wider sampling budget (0.5% → 1%) plus component sampling should cost more than the first recording's 0.3-0.8% of - a frame, and `overheadUs`/`probeUs` should still land well under the report's 2% warning line — if not, that is exactly what `OverheadBudgetPercent` - is for, and it is worth lowering the default again. +7. **The in-game settings page (0.1.2)**: that Mod Settings actually shows it, that `RangeIntModSetting` renders as something usable and the readonly note as + readable text, and that a value changed there actually reaches `Session.Start` — change `SlowFrameMs`, load a save, and check `frames.csv`'s `# thresholdMs` + header line against what was set. Every 0.1.3 recording so far has the default `# thresholdMs: 50`. (`PerformanceSettings.Load()` against the real + `ISettings`/`ModRepository`/`ModSettingsOwnerRegistry` is verified in the game, above.) ## Five-minute check in a game From 0f59baacf0390e735dd3c630b53bfe7093adc7c1 Mon Sep 17 00:00:00 2001 From: Kyler Ramsey Date: Tue, 22 Sep 2026 05:25:48 -0700 Subject: [PATCH 2/3] PL7: say where a mod's patch on an event handler is charged Timing is inclusive per key, and the game runs event handlers at once: EventBus.Post calls every [OnEvent] method synchronously once the bus is ready, and C# events such as Inventory.InventoryChanged (which StockpileVisualizers.OnInventoryChanged listens to, and MixedStorage patches) fire inside the code that changed something. So a mod's patch on a handler has no row of its own: its time lands in the entity, component or singleton that raised the event, or in otherMs. Events posted while the game loads are queued until EventBus.PostLoad and are charged to its post-load row. The session guide (docs/SESSION-README.md, copied into every session folder) now says so in "Which mod is it?", points at the # patch|other| and # patch|shared| lines that name these handlers, and says that a Watch entry with that name times the handler with every patch on it (Watch patches with Priority.First/Last). The # patch| bullet also lists the "other" tag it had left out. Both fixtures' README.md are regenerated from it; their frames.csv is left as it was, because regenerating also rewrites allocKB values that differ from run to run. Co-Authored-By: Claude Opus 5 --- docs/SESSION-README.md | 12 +++++++++--- tests/fixtures/sample-with-mod/README.md | 12 +++++++++--- tests/fixtures/sample-without-mod/README.md | 12 +++++++++--- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/docs/SESSION-README.md b/docs/SESSION-README.md index d6f7769..4f863e7 100644 --- a/docs/SESSION-README.md +++ b/docs/SESSION-README.md @@ -80,9 +80,15 @@ Start by writing down what the complaint is, because the causes differ: - `profile.csv` and `spikes.csv` carry `mod`. Add up `ms` per mod within a kind (do not add kinds together where they overlap: `entity` and `component` rows both live inside `entMs`). -- `# patch|` lines in the `frames.csv` header list which mod patches which hot method (`hot`), which methods several mods patch (`shared`), and the - order they run in. A mod patching `Ticker.Update` or `TickableEntity.Tick` puts its cost into `tickMs` or `entMs` without a row of its own; a - `Watch` entry in the config (see the repo's README) times such a method directly (kind `method`). +- `# patch|` lines in the `frames.csv` header list which mod patches which hot method (`hot`), which methods several mods patch (`shared`), every + other method another mod patches (`other`), and the order they run in. A mod patching `Ticker.Update` or `TickableEntity.Tick` puts its cost + into `tickMs` or `entMs` without a row of its own; a `Watch` entry in the config (see the repo's README) times such a method directly (kind `method`). +- **A mod's patch on an event handler is charged to whatever raised the event.** The game calls a handler (an `[OnEvent]` method, or one hooked to a + C# event, such as `StockpileVisualizers.OnInventoryChanged`) at once, inside the code that changed something, so the patch has no row of its own: its + time is in whatever was running (an entity's tick, in `entMs` and that entity's `entity` and `component` rows; a singleton's row; or `otherMs` when + nothing timed was running). An event posted while the game loads waits for `EventBus`'s `post-load` step, so its `[OnEvent]` handlers are charged + there. The `# patch|other|` and `# patch|shared|` lines name these handlers in full; a `Watch` entry with that name times one, with every patch on it + (kind `method`). - To be sure it is a mod, **compare two recordings** of the same save at the same speed with and without it: `python tools/perflog.py compare ` (in the Performance Log repository). Say what else differed. diff --git a/tests/fixtures/sample-with-mod/README.md b/tests/fixtures/sample-with-mod/README.md index 2687cb5..d2fb981 100644 --- a/tests/fixtures/sample-with-mod/README.md +++ b/tests/fixtures/sample-with-mod/README.md @@ -80,9 +80,15 @@ Start by writing down what the complaint is, because the causes differ: - `profile.csv` and `spikes.csv` carry `mod`. Add up `ms` per mod within a kind (do not add kinds together where they overlap: `entity` and `component` rows both live inside `entMs`). -- `# patch|` lines in the `frames.csv` header list which mod patches which hot method (`hot`), which methods several mods patch (`shared`), and the - order they run in. A mod patching `Ticker.Update` or `TickableEntity.Tick` puts its cost into `tickMs` or `entMs` without a row of its own; a - `Watch` entry in the config (see the repo's README) times such a method directly (kind `method`). +- `# patch|` lines in the `frames.csv` header list which mod patches which hot method (`hot`), which methods several mods patch (`shared`), every + other method another mod patches (`other`), and the order they run in. A mod patching `Ticker.Update` or `TickableEntity.Tick` puts its cost + into `tickMs` or `entMs` without a row of its own; a `Watch` entry in the config (see the repo's README) times such a method directly (kind `method`). +- **A mod's patch on an event handler is charged to whatever raised the event.** The game calls a handler (an `[OnEvent]` method, or one hooked to a + C# event, such as `StockpileVisualizers.OnInventoryChanged`) at once, inside the code that changed something, so the patch has no row of its own: its + time is in whatever was running (an entity's tick, in `entMs` and that entity's `entity` and `component` rows; a singleton's row; or `otherMs` when + nothing timed was running). An event posted while the game loads waits for `EventBus`'s `post-load` step, so its `[OnEvent]` handlers are charged + there. The `# patch|other|` and `# patch|shared|` lines name these handlers in full; a `Watch` entry with that name times one, with every patch on it + (kind `method`). - To be sure it is a mod, **compare two recordings** of the same save at the same speed with and without it: `python tools/perflog.py compare ` (in the Performance Log repository). Say what else differed. diff --git a/tests/fixtures/sample-without-mod/README.md b/tests/fixtures/sample-without-mod/README.md index 2687cb5..d2fb981 100644 --- a/tests/fixtures/sample-without-mod/README.md +++ b/tests/fixtures/sample-without-mod/README.md @@ -80,9 +80,15 @@ Start by writing down what the complaint is, because the causes differ: - `profile.csv` and `spikes.csv` carry `mod`. Add up `ms` per mod within a kind (do not add kinds together where they overlap: `entity` and `component` rows both live inside `entMs`). -- `# patch|` lines in the `frames.csv` header list which mod patches which hot method (`hot`), which methods several mods patch (`shared`), and the - order they run in. A mod patching `Ticker.Update` or `TickableEntity.Tick` puts its cost into `tickMs` or `entMs` without a row of its own; a - `Watch` entry in the config (see the repo's README) times such a method directly (kind `method`). +- `# patch|` lines in the `frames.csv` header list which mod patches which hot method (`hot`), which methods several mods patch (`shared`), every + other method another mod patches (`other`), and the order they run in. A mod patching `Ticker.Update` or `TickableEntity.Tick` puts its cost + into `tickMs` or `entMs` without a row of its own; a `Watch` entry in the config (see the repo's README) times such a method directly (kind `method`). +- **A mod's patch on an event handler is charged to whatever raised the event.** The game calls a handler (an `[OnEvent]` method, or one hooked to a + C# event, such as `StockpileVisualizers.OnInventoryChanged`) at once, inside the code that changed something, so the patch has no row of its own: its + time is in whatever was running (an entity's tick, in `entMs` and that entity's `entity` and `component` rows; a singleton's row; or `otherMs` when + nothing timed was running). An event posted while the game loads waits for `EventBus`'s `post-load` step, so its `[OnEvent]` handlers are charged + there. The `# patch|other|` and `# patch|shared|` lines name these handlers in full; a `Watch` entry with that name times one, with every patch on it + (kind `method`). - To be sure it is a mod, **compare two recordings** of the same save at the same speed with and without it: `python tools/perflog.py compare ` (in the Performance Log repository). Say what else differed. From 1032b3fbe1433651f5ea8a9efd1a753cde957b33 Mon Sep 17 00:00:00 2001 From: Kyler Ramsey Date: Tue, 22 Sep 2026 05:35:35 -0700 Subject: [PATCH 3/3] PL8: tighten the verified-in-game wording after review Review of the PL8 docs found three small inaccuracies: - TESTING.md quoted two frame counts for the same session (236917 from summary.md, 236918 from the closing lines, which count the first frame too). The wrapper bullet now says "for the whole recording" instead of a second figure. - README.md and TESTING.md's intro said the 0.1.3 recording shows "the 0.1.1 fixes" working, while TESTING.md keeps one of them (zipping a session folder while the game runs) open because a recording cannot show it. Both now say "every 0.1.1 fix a recording can show". - The rewritten last sentence of the CHANGELOG 0.1.3 entry kept an older false clause: the five-minute check does not start by checking overheadUs; its step 10 measures the cost. It now says that. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 4 ++-- README.md | 2 +- docs/TESTING.md | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c044c3a..4bd7cef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,8 +17,8 @@ install is as informative as this mod can make it. rather than the depth of any one row, and the budget system above already throttles itself if measuring gets expensive, so there was no clear "more detail" case for moving them, only a "more rows" one. - Expect a real, measurable increase in the mod's own cost from this alone — deep's component sampling plus double the sampling budget. - Nobody had played it when it was released (it has been since: see `docs/TESTING.md`); the five-minute check there now starts by checking `overheadUs` - is still reasonable. + Nobody had played it when it was released (it has been since: see `docs/TESTING.md`); step 10 of the five-minute check there measures + what it costs. ## 0.1.2 (preview, not yet played) diff --git a/README.md b/README.md index 66eaafe..070bfaf 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ the game and in other mods. It does nothing else. Version **0.1.3** is a **preview**. Its automated checks run against the game's real assemblies. Version 0.1.0 was the first to be played (a 31 minute session with nine mods, ending in a normal exit): every patch applied and the recording was complete. That first recording also showed several defects, fixed in 0.1.1; 0.1.2 added an in-game settings page, and 0.1.3 made the most detailed profile the default. 0.1.1 and 0.1.3 have been played since, and a 44 minute 0.1.3 recording with -ten mods shows the 0.1.1 fixes and the new defaults working; whether a value changed on the settings page reaches a recording is not verified yet. See +ten mods shows the new defaults and every 0.1.1 fix a recording can show working; whether a value changed on the settings page reaches a recording is not verified yet. See [CHANGELOG.md](CHANGELOG.md) for what changed in each version. If a part fails to start it says so in the log and the summary, that part stays off, and the game carries on. Read [docs/TESTING.md](docs/TESTING.md) for what is and is not verified, and how to check it in a game in five minutes. diff --git a/docs/TESTING.md b/docs/TESTING.md index c36ca83..ecf49a7 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -2,7 +2,7 @@ Version 0.1.0 was the first to run in a game (the first recording, below); 0.1.1 fixed what that showed, 0.1.2 added an in-game settings page, and 0.1.3 changed the defaults to `Profile = deep` and a wider sampling budget, for the most detail with nothing configured. 0.1.1 and 0.1.3 have both been played -since, and a 0.1.3 recording (below) shows the 0.1.1 fixes and the `deep` default working. This is the honest list. +since, and a 0.1.3 recording (below) shows the `deep` default and every 0.1.1 fix a recording can show working. This is the honest list. ## Verified by the automated checks @@ -69,7 +69,7 @@ recording says little about the frame rate. What it shows, and the line that shows it: - **The 0.1.1 fixes** (item 1 of the list below until this recording; zipping a folder while the game runs is still there): - - Each singleton service is wrapped once: `# capability-final|patchCalls|singleton wrappers put in place|3` in 236918 frames (0.1.0: 488601 in 122150). Every 0.1.1 and + - Each singleton service is wrapped once: `# capability-final|patchCalls|singleton wrappers put in place|3` for the whole recording (0.1.0: 488601 in 122150 frames). Every 0.1.1 and 0.1.3 recording that reached its closing lines says 2 to 5. - `workingMB` is 5587 to 7090 in the `S` rows, and `# capability|workingSet|from Windows`. - The game's own singletons are labelled `game`: no singleton row in `profile.csv` has an empty `mod`.