> ## Documentation Index
> Fetch the complete documentation index at: https://superradcompanyinc-mintlify-8d0a72e9.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Optimization

> Choose the settings that can improve local sandbox performance

There is no single fastest setup. Start with the defaults, measure your workload, and change one setting at a time.

Run these commands before tuning anything:

```bash theme={null}
msb doctor
msb inspect worker
```

`msb doctor` checks host capabilities. `msb inspect` shows the settings that a sandbox actually uses.

## Quick guide

| If you want to                              | Start with                                     |
| ------------------------------------------- | ---------------------------------------------- |
| Create OCI sandboxes faster                 | A flat root disk with `clone=auto`             |
| Spread CPU-heavy work across physical cores | `cpu_placement: spread`                        |
| Favor cache locality                        | `cpu_placement: compact`                       |
| Tune large memory mappings                  | Keep THP at `madvise`, then benchmark `always` |
| Control buffered disk pressure on Linux     | Keep block writeback at `auto`                 |

## Storage layout: layered or flat

The default layered root shares OCI layers between sandboxes. A flat root turns the image into one ext4 disk and clones it for each sandbox. This can improve creation time and filesystem-heavy workloads on hosts with copy-on-write cloning.

```bash theme={null}
msb pull python:3.12 --materialize flat
msb create python:3.12 --name worker --root-disk flat:8G,clone=auto
```

`clone=auto` uses a native copy-on-write clone when available and falls back to a sparse copy. Use the layered root when image layer sharing or maximum portability matters more.

See [OCI images](/images/overview#oci-images) for image behavior and [Bootstrap](/sandboxes/bootstrap#flat-oci-rootfs) for flat root details.

## CPU placement

By default, sandbox vCPU threads follow the host scheduler. On Linux and Windows, microsandbox can place those threads for you.

### Choose a policy

| Policy    | What it does                                                       |
| --------- | ------------------------------------------------------------------ |
| `inherit` | Leaves placement to the host scheduler. This is the default.       |
| `auto`    | Uses available physical cores first, then shares CPUs when needed. |
| `spread`  | Spreads work across physical cores.                                |
| `compact` | Keeps work on fewer physical cores for better cache locality.      |

Start with `auto` on a dedicated host. Use `spread` for CPU-heavy throughput work. Use `compact` when cache locality or packing more sandboxes onto a host matters most.

<CodeGroup>
  ```bash CLI theme={null}
  msb create python:3.12 --name worker --cpus 2 --cpu-placement spread
  ```

  ```typescript TypeScript theme={null}
  import { Sandbox } from "microsandbox";

  await using sb = await Sandbox.builder("worker")
    .image("python:3.12")
    .cpus(2)
    .cpuPlacement("spread")
    .create();
  ```

  ```rust Rust theme={null}
  use microsandbox::sandbox::{CpuPlacement, Sandbox};

  let sb = Sandbox::builder("worker")
      .image("python:3.12")
      .cpus(2)
      .cpu_placement(CpuPlacement::Spread)
      .create()
      .await?;
  ```

  ```python Python theme={null}
  from microsandbox import CpuPlacement, Sandbox

  sb = await Sandbox.create(
      "worker",
      image="python:3.12",
      cpus=2,
      cpu_placement=CpuPlacement.SPREAD,
  )
  ```

  ```go Go theme={null}
  sb, err := m.CreateSandbox(ctx, "worker",
      m.WithImage("python:3.12"),
      m.WithCPUs(2),
      m.WithCPUPlacement(m.CPUPlacementSpread),
  )
  ```
</CodeGroup>

### Keep CPU and memory on one NUMA node

Large hosts can have more than one NUMA node. A placement profile can keep a sandbox's CPU and memory on the same node.

First, define a named profile in the [global config](/configuration):

```json theme={null}
{
  "runtime": {
    "placement_profiles": {
      "latency": {
        "numa": { "mode": "prefer_single" },
        "memory": { "mode": "follow_cpu" }
      }
    }
  }
}
```

Then select it when you create the sandbox:

```bash theme={null}
msb create python:3.12 \
  --name worker \
  --cpus 2 \
  --cpu-placement auto \
  --placement-profile latency
```

`prefer_single` uses one node when enough CPU and memory are available. Otherwise, it falls back to normal placement. Use `strict_single` when the sandbox should fail instead of falling back.

### What placement guarantees

* microsandbox coordinates only sandboxes that share the same `MSB_HOME`.
* Placement considers the sandbox's maximum CPU count, not only the CPUs online at boot.
* When exclusive CPU capacity runs out, normal policies may share logical CPUs.
* Placement does not isolate unrelated host processes or reserve dedicated cores.
* On macOS, managed policies fall back to `inherit` because hard CPU affinity is not available through a public API.
* If placement cannot be applied, normal policies fall back to `inherit`. A `strict_single` profile fails instead.

Use `msb inspect worker` to see the resolved policy and placement result.

## Transparent huge pages

Transparent huge pages, or THP, control how the guest handles large memory mappings.

| Policy    | Use it when                                          |
| --------- | ---------------------------------------------------- |
| `madvise` | You want the safe default                            |
| `always`  | Benchmarks show a gain for large, sustained mappings |
| `never`   | Predictable small-page behavior matters more         |

THP changes take effect the next time the sandbox boots. Keep `madvise` unless real workload tests show a clear improvement.

## Buffered block writeback

On Linux, block writeback limits how much buffered disk data active sandboxes can hold in host memory.

* `auto` chooses safe limits from the host. This is the recommended setting.
* `fixed` uses limits that you provide.
* `off` disables the limits for new sandboxes.

This setting has no effect on non-Linux hosts, read-only disks, or direct I/O. See [Global config](/configuration) for the available fields.

## Host interrupt acceleration

On Linux x86 hosts, AMD AVIC and Intel APICv can make virtual interrupt delivery faster. These are host KVM settings, not sandbox settings.

Check their status with `msb doctor`. Read [Linux troubleshooting](/troubleshooting/linux#interrupt-acceleration) before changing a KVM module because the change affects every VM on the host.

## Optimizations that are not knobs

microsandbox automatically selects compatible filesystem, guest kernel, interrupt, and vCPU affinity optimizations. These implementation details do not have user-facing settings.

## Measure the result

Keep the image, CPU and memory limits, storage, host power settings, and concurrency unchanged while comparing settings. Measure sandbox creation separately from workload performance.
