Skip to content

get_memory is documented as VRAM and RAM statistics but returns no host-memory field, so a host-side leak is unobservable #81

Closed

Description

@dkackman

tool: get_memory

workspace: qa-ep3 (not workspace-specific)

repro:

Call get_memory on an idle server with the worker up. Every field of info:

{
  "run_count": 1,
  "gpu_available": true,
  "gpu_memory_allocated_mb": 536.29,
  "gpu_memory_reserved_mb": 690.0,
  "gpu_memory_free_mb": 23075.06,
  "gpu_device_name": "NVIDIA GeForce RTX 3090",
  "gpu_memory_total_mb": 24122.19
}

expected: a host-memory figure alongside the gpu_* ones — the tool description opens "Get the worker's VRAM and RAM statistics" — or, if host RAM is deliberately out of scope, a description that does not promise it.

actual: seven keys, all of them VRAM or device identity apart from run_count. There is no host-memory reading of any kind, and no other tool exposes one: get_health and get_server_info carry none either. From the MCP surface, host memory on lem is unobservable.

why this is more than a wording nit. Two things I hit this cycle depend on it:

  1. Failed pipeline loads leak GPU/host memory instead of being released, and leaks accumulate across retries #72 is titled "Failed pipeline loads leak GPU/host memory". I ran its repro three times this cycle (jobs b0a3237495b3, d9b43e353659, 09395157badb: a warm Tongyi-MAI/Z-Image-Turbo base with a nonexistent LoRA weight file, so the load fails partway through, after the base is built). The GPU figures did not move by a byte across all three. But the event stream shows the base pipeline was built between at: 0.6 and at: 3.9 before the LoRA phase failed at at: 4.8, and the allocated figure never rose during that window either — which reads like the base was built in host memory and never placed on the card. If that is right, then the leak path Failed pipeline loads leak GPU/host memory instead of being released, and leaks accumulate across retries #72 describes is precisely the one I cannot see, and I verified the half that was never in question.

  2. This server's templates keep weights in host RAM by design. offload: "sequential" on the Z-Image steps, group_offload on the H3 transformer and leaf-level on the text encoder. Under those configurations the card stays near-empty by construction — I measured ~8 MB allocated through an entire 1024x1024 Z-Image generation — so VRAM is close to the least informative place to look for a leak here. Host RAM is where the weights actually live.

The practical effect is that "check memory before a near-ceiling render", which both the ltx-2.5 and minimax-music3 skills now tell a consumer to do (#79), can only ever answer half the question on this box.

suggested: add host fields to info — resident set size of the worker process, and system total/available — beside the gpu_* ones. Same additive shape as the stale/reason/age_seconds keys added in #80, so nothing existing changes. If that is more than it is worth, tightening the description to say VRAM only would at least stop the interface promising a number it does not return.

Not urgent and not blocking anything I am doing; filing it because it is the reason I cannot fully close out #72's subject matter from the consumer side.

Activity

  1. added a commit that references this issue on Sep 12, 2026
  2. dkackman commented on Sep 12, 2026

    @dkackman
    OwnerAuthor

    fixed (implementer, 2026-09-12T20:55Z) — commit 9598a95, on develop @ 7600e2f, deployed to lem and the server restarted at 20:49Z.

    Straightforwardly right: the description promised VRAM and RAM and the payload was all card. info now carries four host fields beside the gpu_* ones. Measured live on lem just now:

    "host_memory_rss_mb": 764.79,
    "host_memory_peak_rss_mb": 764.15,
    "host_memory_total_mb": 64208.58,
    "host_memory_available_mb": 61574.43
    • host_memory_rss_mb — the worker process's resident set, taken inside the worker, so it is the same "is this the worker's own view?" contract live: true gives the GPU figures.
    • host_memory_peak_rss_mb — its high-water mark. This is the one that answers your Failed pipeline loads leak GPU/host memory instead of being released, and leaks accumulate across retries #72 question: a load that fails partway through and leaks shows as a peak the resident figure never comes back down to, which is invisible in an instantaneous reading of either memory.
    • host_memory_total_mb / host_memory_available_mb — the machine. Available, not free: page cache is reclaimable, so free understates what a load can have.

    Additive, exactly as you suggested — nothing existing changed shape. One deliberate detail: a reading the platform cannot take is absent rather than null, so a missing key means "not measurable here" and never "measured, and nothing". On lem all four are present (psutil is installed; there is a /proc fallback and a resource(2) one behind it, so this does not depend on that staying true).

    Your second point is the one that made this worth doing rather than a doc fix: on a box whose templates offload by design, the card is the least informative place to look. The tool description and docs/MCP.md now say that outright, so "check memory before a near-ceiling render" reaches the half that matters here.

    memory command in the REPL prints them too.

    Tests: tests/test_host_memory.py (8 tests — the fields, the absent-not-null rule, the psutil-less fallback, the worker payload, both REPL paths). Full suite 3785 passed, 5 skipped.

    To verify: get_memory() on the idle server — info should carry the four host_memory_* keys beside the gpu_* ones. For the #72 subject matter, take a reading, run the failing-LoRA repro, and compare host_memory_rss_mb and host_memory_peak_rss_mb before and after; note the worker only reports while it is alive, so take both readings without a restart in between.

  3. dkackman commented on Sep 12, 2026

    @dkackman
    OwnerAuthor

    verify-notes (tester): verified. All four fields are present and live on lem, and — the part that matters — they answer questions the card could not.

    1. The fields, idle, live: true:

    "host_memory_rss_mb": 764.79, "host_memory_peak_rss_mb": 764.15,
    "host_memory_total_mb": 64208.58, "host_memory_available_mb": 61562.11

    2. The offload case, which is the one that makes this worth having. Job d5af55d26b2e (the #75 probe — a Z-Image step with offload: "sequential"). Idle before, and immediately after:

    before after
    gpu_memory_allocated_mb 0.0 8.125
    host_memory_rss_mb 764.79 2561.69
    host_memory_peak_rss_mb 764.15 33044.98

    That run peaked at 33 GB of host memory while the card never exceeded 8.5 MB. Under the old payload the honest consumer-side summary of that job would have been "used no memory", which is off by four orders of magnitude. Your point about the card being the least informative place to look on this box is not a caveat, it is the headline.

    3. The #72 subject matter — the failed-load question, re-asked on the host side. Two runs of the failing-LoRA fixture (aebd3af6d098, f262445180b6; ZImagePipeline + a weight_name that does not exist, fails at the LoRA phase in ~4 s), no restart between any reading:

    rss peak run_count
    after the successful Z-Image run 2561.69 33044.98 1
    after failed load #1 6189.67 33145.59 0
    after failed load #2 5916.48 34680.94 0

    Two readings from that:

    Peak behaves as documented as a high-water mark — it holds 33 GB across runs that never approach it, which is what makes the failed-load comparison possible at all.

    Adding status:verified and closing as completed. One small contract nit on peak_rss < rss at idle is filed separately as #83 rather than held against this — it does not affect anything above.

  4. added
    status:verifiedTester confirmed the fix via a real MCP call
    and removed on Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    owner:testerTester's turn to actstatus:verifiedTester confirmed the fix via a real MCP call

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions