Skip to content

[Performance]: Postgres workload reports much higher cgroup/runtime memory than Docker despite similar process RSS #1698

@MarlonJD

Description

@MarlonJD

I have done the following

  • I have searched the existing issues
  • If possible, I've reproduced the issue using the main branch of this project

Steps to reproduce

I measured a public Postgres workload repeatedly on the same machine against Docker/OrbStack and Apple container.

Environment:

  • macOS 26.5.1 (25F80), arm64
  • Xcode 26.5 (17F42)
  • Apple container CLI 1.0.0 (release, commit ee848e3)
  • MacBook Pro Mac14,7, Apple M2, 16 GB memory
  • Docker/OrbStack baseline available on the same machine

Apple workload shape:

  1. Start Apple container services.
  2. For each iteration, create a fresh named volume.
  3. Run docker.io/library/postgres:16-alpine with:
    • POSTGRES_USER=app
    • POSTGRES_PASSWORD=<benchmark-only-password>
    • POSTGRES_DB=app
    • PGDATA=/var/lib/postgresql/data/pgdata
    • volume mounted at /var/lib/postgresql/data
  4. Wait for pg_isready.
  5. Capture:
    • container stats --no-stream
    • /proc/1/status inside the container
    • cgroup memory.current, memory.peak, and memory.max
    • du -sk /var/lib/postgresql/data
    • runtime-reported block I/O
  6. Run a short synthetic SQL loop using generate_series.
  7. Stop/delete the container and delete the named volume.

Docker/OrbStack used the same image, fresh volume-per-iteration shape, and the
same process/cgroup/disk probes where available.

Iteration counts:

Workload Docker/OrbStack Apple container
postgres-db-only 50 20
backend-shaped Postgres role 20 10

Problem description

For a small Postgres workload, the Postgres process RSS and data footprint are effectively the same between Docker/OrbStack and Apple container, but Apple reports much higher runtime/cgroup memory and higher DB block reads.

DB-only memory:

Runtime Process RSS p50 Cgroup current p50 Runtime memory p50
Docker/OrbStack 26.68 MiB 65.14 MiB 17.21 MiB
Apple container 26.57 MiB 187.45 MiB 187.01 MiB

Backend-shaped DB role memory:

Runtime Process RSS p50 Cgroup current p50 Runtime memory p50
Docker/OrbStack 26.65 MiB 67.33 MiB 20.09 MiB
Apple container 26.57 MiB 188.45 MiB 188.15 MiB

Disk footprint:

Workload Runtime Data footprint p50
DB-only Docker/OrbStack 45.70 MiB
DB-only Apple container 45.70 MiB
Backend DB Docker/OrbStack 45.78 MiB
Backend DB Apple container 45.79 MiB

Block read snapshots:

Workload Runtime Block read p50
DB-only Docker/OrbStack 0.00 MiB
DB-only Apple container 81.05 MiB
Backend DB Docker/OrbStack 3.09 MiB
Backend DB Apple container 81.05 MiB

I expected some overhead from Apple container's one-VM-per-container model, but the process RSS being the same while cgroup/runtime memory is roughly 187-188 MiB makes it hard to tell whether this is:

  • expected per-container VM/runtime overhead;
  • cgroup accounting that includes runtime/kernel/init memory;
  • a tunable default that should be documented for DB/backend workloads;
  • or an optimization opportunity.

Could maintainers clarify whether this memory profile is expected, and whether there are recommended flags or runtime settings for small DB containers where the process RSS is much lower than the reported cgroup/runtime memory?

Environment

  • OS: macOS 26.5.1 (25F80), arm64
  • Xcode: 26.5 (17F42)
  • Container: container CLI version 1.0.0 (build: release, commit: ee848e3)
  • Hardware: MacBook Pro Mac14,7, Apple M2, 16 GB memory

Notes

This came from a Compose-adapter feasibility benchmark. The backend-shaped Apple path used documented workarounds in my harness:

  • PGDATA=/var/lib/postgresql/data/pgdata, because mounting a named volume directly at the Postgres data root exposed lost+found.
  • DB-IP targeting instead of Compose-style service-name DNS.

So the backend-shaped result is not being presented as Compose parity. The DB-only result is the narrower signal: same Postgres image, same fresh-volume shape, same process RSS, same data footprint, but much higher Apple cgroup/runtime memory and block-read snapshots.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions