Skip to content

Add optional Virtio memory balloon support#1276

Open
TastyHeadphones wants to merge 2 commits into
openai:mainfrom
TastyHeadphones:claude/distracted-cannon-778ea8
Open

Add optional Virtio memory balloon support#1276
TastyHeadphones wants to merge 2 commits into
openai:mainfrom
TastyHeadphones:claude/distracted-cannon-778ea8

Conversation

@TastyHeadphones

Copy link
Copy Markdown

This PR adds optional support for Apple Virtualization.framework's virtio memory balloon device. When enabled, Tart attaches a VZVirtioTraditionalMemoryBalloonDeviceConfiguration to the VM configuration, allowing supported guest operating systems to participate in best-effort memory reclaim. The feature is disabled by default and does not change existing VM behavior.

Usage

# enable the balloon device for a VM (persisted in the VM's config.json)
tart set <vm> --memory-balloon true

# optionally ask the guest to shrink its memory footprint to a target size
tart run --balloon-target-memory 1024 <vm>

What changed

  • VMConfig gains a memoryBalloon: Bool setting (default false). The key is only written to config.json when enabled, so configurations of VMs that don't use the feature remain byte-identical to those produced by older Tart versions.
  • tart set <vm> --memory-balloon true|false toggles the setting.
  • When enabled, VM.craftConfiguration() attaches a VZVirtioTraditionalMemoryBalloonDeviceConfiguration. The device is skipped for suspendable VMs (similarly to the entropy device) to not interfere with the save/restore support.
  • tart run --balloon-target-memory <MB> sets VZVirtioTraditionalMemoryBalloonDevice.targetVirtualMachineMemorySize at runtime, with validation: the balloon device must be enabled, the target cannot exceed the VM's configured memory size, cannot be below VZVirtualMachineConfiguration.minimumAllowedMemorySize, and is rejected together with --suspendable.
  • The target is re-applied every 15 seconds while the VM runs: testing showed that a target set immediately after start() is lost when the guest's virtio-balloon driver resets the device during boot (the same applies to guest reboots).
  • There is intentionally no standalone tart balloon <vm> command: Apple's runtime API is only reachable from the process that owns the VM, and Tart has no host-side control channel to a running tart run process (the control socket proxies into the guest agent). Rather than fake it, the target is a tart run option and the docs explain why.
  • No availability guards were needed: the balloon APIs are available since macOS 11 and the package targets macOS 13.
  • VM.craftConfiguration() is split into buildConfiguration() + validation, because VZVirtualMachineConfiguration.validate() requires the com.apple.security.virtualization entitlement that unit tests don't have.
  • Documentation added to docs/quick-start.md.

Tests

New MemoryBalloonTests suite (all passing):

  • legacy configs without the key decode to a disabled balloon
  • the key is omitted from JSON when disabled, persisted when enabled
  • tart set --memory-balloon argument parsing (including rejection of non-boolean values)
  • balloon target validation (disabled device, target > configured memory, overflow, target too small, valid targets)
  • the balloon device is only present in the crafted VZVirtualMachineConfiguration when enabled, and never for suspendable VMs

The rest of the unit test suite passes unchanged (except the pre-existing LayerizerTests crash on machines without a local Docker registry, which also occurs on main).

Manual validation (ARM64 Ubuntu guest, 4096 MB VM, macOS 26 host)

  • CLI error paths verified against a real VM (disabled device, oversized target, undersized target).
  • The guest's virtio_balloon driver binds to the device (/sys/bus/virtio/drivers/virtio_balloon present).
  • With --balloon-target-memory 1024, the guest ballooned from ~3.5 GB available down to ~505 MB available within one re-apply cycle, and shutdown remained clean.
  • Host-side observation, for transparency: after the guest touched and freed 2.5 GB, the VM helper process reported 2819 MB footprint / 2193 MB RSS without a target vs 4098 MB / 2457 MB with the balloon inflated — i.e. on this macOS version the ballooned pages stayed resident and host-side reclaim was not immediately visible without host memory pressure. The docs call this out explicitly.
  • A macOS guest was not tested (large image); the docs state macOS guests may show limited or no practical memory reduction.

Limitations

This is not dynamic memory hot-add, not transparent host memory overcommit, and not a guarantee that guests will return memory. It does not make a VM with 2 GB of real host memory appear as 32 GB to the guest — the guest still sees the configured memory size. Guest support is required, and practical results may vary.

🤖 Generated with Claude Code

Add a per-VM "memoryBalloon" setting (disabled by default) that, when
enabled via "tart set <name> --memory-balloon true", attaches a
VZVirtioTraditionalMemoryBalloonDeviceConfiguration to the VM,
allowing supported guest operating systems to participate in
best-effort memory reclaim.

A balloon target can be requested at run time via
"tart run --balloon-target-memory <MB>". The target is re-applied
periodically, since a target set before the guest's virtio-balloon
driver probes the device is lost when the guest resets the device
while booting (the same applies to guest reboots).

The balloon device is skipped for suspendable VMs (similarly to the
entropy device) to not interfere with the save/restore support.

VM.craftConfiguration() is split into a buildConfiguration() part and
a validation part, so that the device wiring can be unit-tested
without the "com.apple.security.virtualization" entitlement.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3678f45d82

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread Sources/tart/Commands/Run.swift
For macOS guests, "tart run --balloon-target-memory" now also enforces
the VM's own minimum supported memory size (dictated by the restore
image), similarly to how "tart set --memory" restricts the configured
memory size.

Addresses a PR review comment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@TastyHeadphones

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: 8de3a2e929

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

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