Skip to content

perf(memory): reduce repeated write-tracking range scans - #1310

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
TibixDev:pr/write-tracking-range-scans
Oct 9, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
TibixDev:pr/write-tracking-range-scans

Conversation

@TibixDev

@TibixDev TibixDev commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

What

Scan version stamps within each contiguous leaf instead of finding the leaf for every block. On Linux, collect nearby watched pages together within existing queue epochs.

Select the range before collection. Widen it only when Linux confirms full watched coverage. Keep the requested range on Windows, for uncached reads, and for threads without epochs. Do not retry a failed collection.

Related: #1201 and #1202 change queue scheduling and retain more collected ranges. This change keeps epoch boundaries and the existing cache size.

Tested

Fedora 44, Release build:

  • Write tracking and graphics tests.
  • Write tracking with collection caching disabled and with the shared cache enabled.
  • Write-history comparisons across a sparse-leaf boundary; guest writes, driver writes, partial unwatches, and epoch changes.
  • Contribution checks.

Isolated comparison against upstream a9ba39c9: unchanged 64 MiB checks fell from 510 to 208 ns. A saved 4,172-request replay used 11–12% less time. Checks that found a write at the first block were about 1 ns slower. These are component timings, not title frame times. Windows was not tested.

Checklist

  • Current main; related PRs are described above.
  • One topic.
  • No new code comments.
  • Unsupported paths still throw; UI stubs are documented.
  • No notes, logs, or images in the repository.
  • No new third-party code.
  • General behavior.
  • Depends on: none.
  • AI-assisted: yes.

@github-actions github-actions Bot added the agc libSceAgc* label Oct 8, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

When the widened walk fails, GuestMemory.cpp:1017 walks the requested pages again. Retrying after a failed attempt isn't allowed here (#182); please decide the range before the first walk. For numbers, see #1324.

@TibixDev

TibixDev commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

The range is now selected before the walk. Linux widens it only after checking watched coverage. Windows keeps the requested range because its arena check does not prove that neighboring pages are committed. A failed walk returns without a retry.

I also compared upstream a9ba39c9 with that upstream plus this revised PR alone. Both used the same test harness and libc.prx. Fedora 44, GCC 16 Release, Ryzen 5 5600, CPU 3; six runs per variant in ABBA order. Each run had one warmup and nine measured batches. Values below are medians of the six run medians.

Version checks, ns/check (upstream → PR):

Range Unchanged Write at first block Write at last block
64 KiB 17.7 → 17.6 17.5 → 18.2 17.8 → 17.7
1 MiB 23.3 → 20.7 17.6 → 18.4 22.8 → 20.7
4 MiB 44.8 → 28.9 17.3 → 18.5 55.7 → 28.6
32 MiB 266.2 → 113.7 17.7 → 18.2 263.3 → 113.7
64 MiB 510.0 → 208.4 17.4 → 18.4 515.5 → 207.4

The saved 4,172-request replay fell from 471.4 to 418.4 ns/request with clean pages, and from 496.3 to 435.6 ns/request with a write every 64 requests: 11.2% and 12.2% less time. The observed run ranges did not overlap for either replay case.

The early-exit cases are about 1 ns slower. This replay preserves request ranges and epochs, not the complete game workload; it does not establish a frame-time gain.

Write-history and graphics tests pass. Write-tracking tests also pass with caching disabled and with the shared cache enabled. Windows was not tested.

@popcoder565

Copy link
Copy Markdown
Contributor

Tested on Windows, since the description says it wasn't: Windows 10 (19045), RTX 3060 Laptop (driver 616.92), MinGW-w64 GCC 15.2.0, Release, main da40273 merged with f26ea47.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 8, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

Conflicts with main in tests/WriteTracking.cpp (new cases landed at the same spot); please rebase.

Scan version stamps within contiguous leaves. On Linux, collect nearby
pages within queue epochs only after confirming full watched coverage.
Keep the requested range on Windows. Select the range before collection
and do not retry a failed walk.

Test sparse-leaf boundaries, write histories, partial unwatches and epochs.
Fedora 44 Release tests pass with default, disabled and shared caching.
Isolated upstream comparison reduces the saved collect replay by 11-12%.
Windows was not tested.

AI-assisted: yes.
@adriadam10

Copy link
Copy Markdown
Collaborator

Rebased on current main (conflict in tests/WriteTracking.cpp with the new unwatch/private-mapping cases; kept both sets). Linux build + full ctest pass (553/553), including agc_write_tracking. The range is selected before the walk with no retry, as asked in #182, and the Windows path keeps the linear scan. Merging once CI is green on the rebased head.

@adriadam10
adriadam10 force-pushed the pr/write-tracking-range-scans branch from f26ea47 to 1a0c999 Compare October 9, 2026 22:58
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 9, 2026
@adriadam10
adriadam10 merged commit 2edaf7f into boykopovar:main Oct 9, 2026
8 checks passed
SleglJan pushed a commit to SleglJan/AnyPS5 that referenced this pull request Oct 10, 2026
…nge-scans

perf(memory): reduce repeated write-tracking range scans
SoRadGaming added a commit to SoRadGaming/AnyPS5 that referenced this pull request Oct 19, 2026
Linux widens a collect of at most one 64 KiB block to the whole block within an epoch (boykopovar#1310), so
the memo serves the block's other ranges. Windows kept the requested range because it was not
tested there. On Windows with boykopovar#5596's resident direct memory every walk is a GetWriteWatch call,
and ASTRO BOT's hub walks about 50k ranges of at most 64 KiB per 10 s on queue 0.

Windows coverage does not know which pages of a block are committed or inaccessible, and a walk
refuses such a range before it collects anything. So a widened walk that fails is retried over the
requested pages; without that, a collect beside uncommitted pages of its block fails.

agc_driver_image_table_reuse expected one more table resolution on Windows than on Linux, from
the narrower collects; it now expects Linux's count on both.

The new uncommitted-pages test resets its range before releasing it, so the arena does not hand
the next test an address inside memory that is still committed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc*

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants