Don't retry a failed memory import on every use #240

Merged
SkippySteve merged 1 commit from fix/import-retry-backoff into main 2026-11-07 17:13:44 +00:00
SkippySteve commented 2026-11-07 17:07:40 +00:00 (Migrated from github.com)

Problem

On a machine that runs out of RAM, vkAllocateMemory fails for a guest pool and the same range is imported again on every later use. Issue #218 measured about 40 attempts a second, 7–130 ms each, which freezes the load zone for good.

Change

A range whose import failed is not tried again for two seconds. A different range is unaffected, and the same range is tried again after the hold. The failure log includes the VkResult from vkAllocateMemory when that is what failed. Bindings that already found no pool still find no pool.

Why this is safe

The hold is only a delay. It does not change a successful import, the mirror budget, or what happens when an import is refused: the lookup still returns no pool. At most 256 ranges are remembered; the oldest is dropped.

Testing

  • python -I -B tests/test_import_hold.py (g++ -std=c++20 -Werror): passed. It checks that a failed range stays held for the gap, that the next range is still tried, and that the list stops at 256.
  • Negative control: with the hold changed so a failed range is allowed again immediately, the same test exits 2 (import hold check 2 failed).
  • python -I -B nx2/test_nup_paths.py: 21 passed. python -I -B tests/test_make_game_cache.py: 6 passed. Both were already passing on main. nx2/unpack.py still warns about an unclosed file there.

Scope

This does not add another way to read a range that could not be imported. Happy to rename the hold or change the two seconds.

## Problem On a machine that runs out of RAM, `vkAllocateMemory` fails for a guest pool and the same range is imported again on every later use. Issue #218 measured about 40 attempts a second, 7–130 ms each, which freezes the load zone for good. ## Change A range whose import failed is not tried again for two seconds. A different range is unaffected, and the same range is tried again after the hold. The failure log includes the `VkResult` from `vkAllocateMemory` when that is what failed. Bindings that already found no pool still find no pool. ## Why this is safe The hold is only a delay. It does not change a successful import, the mirror budget, or what happens when an import is refused: the lookup still returns no pool. At most 256 ranges are remembered; the oldest is dropped. ## Testing - `python -I -B tests/test_import_hold.py` (g++ -std=c++20 -Werror): passed. It checks that a failed range stays held for the gap, that the next range is still tried, and that the list stops at 256. - Negative control: with the hold changed so a failed range is allowed again immediately, the same test exits 2 (`import hold check 2 failed`). - `python -I -B nx2/test_nup_paths.py`: 21 passed. `python -I -B tests/test_make_game_cache.py`: 6 passed. Both were already passing on main. `nx2/unpack.py` still warns about an unclosed file there. ## Scope This does not add another way to read a range that could not be imported. Happy to rename the hold or change the two seconds.
shayderrr commented 2026-11-07 17:13:39 +00:00 (Migrated from github.com)

Thanks!

Thanks!
Commenting is not possible because the repository is archived.
No description provided.