Skip to content

Docs: 0.1.3 version refs, check count, what the 0.1.3 recording verified, event-handler patches in the session guide (PL8, PL7) - #4

Merged
kramsey458 merged 3 commits into
mainfrom
claude/docs-refresh
Sep 22, 2026
Merged

kramsey458 merged 3 commits into
mainfrom
claude/docs-refresh

Conversation

@kramsey458

Copy link
Copy Markdown
Contributor

Summary

Docs only. The repository docs still described 0.1.2 and said nothing from 0.1.1 onward had been played. Since then 0.1.1 and 0.1.3 have been recorded in the game. This PR updates the version references and the check count, and records what the 44-minute 0.1.3 recording 2026-09-21_23-13-11 verified in the game. TESTING items 2, 3 and 7 stay open. It also adds one paragraph to the session guide (docs/SESSION-README.md, embedded in the mod and copied into every session folder) about where a mod's patch on an event handler is charged.

No code, settings, file-format, Harmony or version changes. manifest.json and the csproj still say 0.1.3.

Items

PL8: versions, check count and verified-in-game notes (87036bd, 1032b3f)

  • README.md: says 0.1.3 instead of 0.1.2, and says what has been played since. The build output is named dist\PerformanceLog-<version>.zip (the version in packaging/manifest.json, which is how build.ps1 names it) instead of a fixed 0.1.2.
  • CLAUDE.md: the check count reads 91 (not "about 70") and points to TESTING.md for the current count. The "What is and is not verified" section no longer mentions only the 0.1.0 run.
  • docs/TESTING.md: a new section, "Verified in a real game: 0.1.3 with its defaults (2026-09-21)". It quotes the exact header lines and counts from session 2026-09-21_23-13-11:
    • singleton wrappers put in place|3 (0.1.0: 488601)
    • workingSet|from Windows, and workingMB 5587 to 7090
    • no singleton row with an empty mod
    • 310 of the 618 loading rows carry heap growth
    • Draw Calls Count|produced values
    • LoadAll|1
    • both deep-profile patches installed, 47081184 sampled component calls, and 3475 component rows over 47 classes
    • the mod's own cost estimate, 0.45% of a frame, with the caveat that every recording has patchCallNs|0, so this is not a measurement
    • Item 8 (deep as the default) and the parts of item 1 that a recording can show moved into that section.
    • Item 1 now covers only zipping a session folder while the game runs, which a recording cannot show.
    • Item 7 is narrowed: PerformanceSettings.Load() did run against the real Mod Settings services. There is a load row, the # config: values are the defaults after ApplyTo, and an unloaded ModSetting<T> reads default(T) (checked by decompiling ModSettings.Core), so it would have been clamped to its minimum. Whether the page renders, and whether a changed value reaches a session, stays open.
    • Items 2 and 3 are unchanged.
  • CHANGELOG.md: the 0.1.3 heading drops "not yet played", as the brief asks. The heading stays where it is. The repo does not call CHANGELOG release-only. The entry's last sentence said "Nobody has played it yet". It now says it had not been played at release and points to TESTING.md, and it no longer claims the five-minute check starts with overheadUs (that is step 10).
  • Test: none; docs only (the task says no test-first for docs). I checked every figure against the read-only recordings in Documents/Timberborn/PerformanceLog, Player.log, the code, and the decompiled ModSettings.Core. An independent reviewer re-derived all of them with its own scripts over the 26 recordings.

PL7: event-handler patches in the session guide (0f59baa)

  • docs/SESSION-README.md, under "Which mod is it?": a mod's patch on an event handler has no row of its own. That covers [OnEvent] methods and C# event handlers such as StockpileVisualizers.OnInventoryChanged, which MixedStorage patches. Its time is charged to whatever raised the event: an entity's tick (entMs and that entity's rows), a singleton's row, or otherMs. Events posted while the game loads wait for EventBus's post-load step and are charged there. The # patch|other| and # patch|shared| lines name these handlers in full, and a Watch entry with that name times the handler together with every patch on it (kind method). The # patch| bullet now also lists the other tag, which it had left out.
  • The two fixture README.md files were regenerated, so WriterTests.FixturesAreCurrent passes. Only those files are committed. See the second new finding for why the regenerated frames.csv was left out.
  • Test: none; docs only. I checked the claims against the decompiled EventBus (Post calls PostNow at once once PostLoad has set _ready; before that, events queue in _earlyEvents and PostLoad drains them), StockpileVisualizers (_inventory.InventoryChanged += OnInventoryChanged), Watch.cs (a Priority.First prefix and a Priority.Last postfix; non-public methods are resolved too) and PatchReport.cs. The real session's header has # patch|other|...StockpileVisualizers.OnInventoryChanged|postfix|kyler.mixedstorage, and its profile.csv has a post-load row for EventBus.

Tests

Suite Before (a1c6d1c) After (1032b3f)
C# (dotnet run --project tests -c Release -- --managed <Managed>) 91/91 91/91 (also 91/91 at 87036bd and 0f59baa)
Python (python -W error::ResourceWarning -m unittest discover -s tools -p test_perflog.py) 44 OK 44 OK
Mod build (dotnet build source/PerformanceLog.csproj -c Release) 0 errors 0 errors at 0f59baa; the built DLL embeds the new SESSION-README text

Co-op impact

None. Only Markdown changes, and neither simulation nor the wire format changes. The mod only observes.

Proposed CHANGELOG lines

The README.md in each session folder now explains that a mod's patch on a game event handler is charged to whatever raised the event, and how to time that handler with Watch. The repository docs now say what the 0.1.1 and 0.1.3 recordings verified in the game.

(CHANGELOG.md itself only changes as described under PL8: the 0.1.3 heading and that entry's last sentence.)

Needs in-game testing

  • PL7 (Watch on an event handler): with MixedStorage enabled, add Watch = Timberborn.StockpileVisualization.StockpileVisualizers.OnInventoryChanged to PerformanceLog.cfg in the mod's version-1.1 folder, then restart the game. Play 3 minutes while stockpiles fill. The frames.csv header should have # watch|Timberborn.StockpileVisualization.StockpileVisualizers.OnInventoryChanged(Object,InventoryChangedEventArgs)|watching, and profile.csv should have method rows for it. Remove the Watch line afterwards.
  • TESTING item 7 (settings page, still open): open Mod Settings from the main menu and check that Performance Log is listed with six sliders and a readable note. Set SlowFrameMs to 77, load a save, play a minute and leave. The new session's frames.csv should say # thresholdMs: 77.
  • TESTING item 1 (still open): while a session is recording, copy or zip its folder, and check that the copy has frames.csv, profile.csv, spikes.csv and events.csv with non-zero sizes.

Review

One adversarial reviewer (save compatibility and cross-mod interaction) approved. It re-ran both suites (91/91, 44 OK) and re-derived every figure in the new TESTING section from the recordings. It confirmed the item 7 narrowing by decompiling ModSettings.Core, and the SESSION-README claims against the decompiled game. It found three nits, all fixed in 1032b3f:

  • TESTING.md gave two frame counts for the same session (236917 from summary.md, 236918 from the closing lines, which also count the first frame). Now one figure.
  • README and TESTING's intro said the recording shows "the 0.1.1 fixes", while item 1 keeps one of them open. Both now say "every 0.1.1 fix a recording can show".
  • The rewritten CHANGELOG sentence kept an older false clause (that the five-minute check "starts by checking overheadUs"). Now it points to step 10.

Declined: README's "From 0.1.1 you can also copy or zip the folder while the game runs" (under the session-folder description) stays as it is. It describes what the mod does, and WriterTests.ReadableWhileRunning/RetriesWhenHeld check it automatically. TESTING.md tracks the separate question of whether it has been seen in the game.

Found along the way, not fixed here:

  • summary.md wrongly says "Unity's frame phases: NOT measured" whenever the player leaves to the menu. Session.Stop calls PlayerLoopTiming.Uninstall() (which sets Installed = 0) before RefreshSummary("finished"). All 11 of 26 real sessions that ended with "the game was left" say this, while their frames.csv says playerLoop|timed 8 phases. Only the summary line is wrong; the data is fine. The reviewer confirmed this. It needs its own fix.
  • Regenerating the fixtures is not reproducible: --write-sample writes different allocKB values on every run, because Probe.Frame reads the test process's real heap via GC.GetTotalMemory. FixturesAreCurrent compares only headers and the Markdown files, so it does not notice. Any PR that regenerates fixtures therefore churns frames.csv with meaningless diffs.

For the maintainer: 0.1.3 has now been played in the game. CLAUDE.md says a release stays a pre-release until it has been played, so whether to change the v0.1.3 GitHub release is your call. This PR does not touch it.

Expect small conflicts in docs/TESTING.md with #1, #2 and #3 (check counts, item 2's wording, #1's new item 9). Whichever lands second should keep both sides.

🤖 Generated with Claude Code

kramsey458 and others added 3 commits September 22, 2026 05:23
…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-<version>.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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
@kramsey458
kramsey458 marked this pull request as ready for review September 22, 2026 19:32
@kramsey458
kramsey458 merged commit 6030b1a into main Sep 22, 2026
4 checks passed
@kramsey458
kramsey458 deleted the claude/docs-refresh branch September 22, 2026 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant