Skip to content

Smaller binaries and faster large transfers - #2

Merged
andrasbacsai merged 6 commits into
mainfrom
perf/release-profile
Sep 27, 2026
Merged

andrasbacsai merged 6 commits into
mainfrom
perf/release-profile

Conversation

@andrasbacsai

Copy link
Copy Markdown
Member

Summary

Smaller binaries and faster large transfers.

  • Smaller binaries: release profile with fat LTO, one codegen unit and strip. Static Linux x86_64: 50.3 MB → 27.8 MB.
  • Large uploads: minio-go multipart defaults (16 MiB minimum parts, 4 parts in parallel). Parts are read straight from the file. cp 2 GiB up: 5.9 s → 0.94 s (mc: 1.41 s). Memory: 111 → 47 MiB.
  • Large downloads: 1 MiB file writes instead of 8 KiB. cp 2 GiB down: 2.06 s → 0.81 s (mc: 0.87 s).
  • Static musl build: mimalloc instead of musl's malloc. mirror up: 1.03 s → 0.52 s.
  • Dockerfile: empty version build args are dropped (an empty SOURCE_DATE_EPOCH broke the C build).
  • Benchmark: new tests/bench/bench.sh, results in tests/bench/RESULTS.md.

Test plan

  • cargo test (1311+ tests), clippy, fmt
  • Live transfer suites and live_mc_parity against MinIO
  • Container build + tests/container_smoke.sh
  • Benchmark against mc (3 runs, results in tests/bench/RESULTS.md)
  • CI: Linux, macOS and Windows

🤖 Generated with Claude Code

andrasbacsai and others added 6 commits September 27, 2026 14:32
Static Linux x86_64 binary: 50.3 MB -> 27.8 MB. opt-level and panic
unwinding stay unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tests/bench/bench.sh runs cp/pipe/cat/mirror/ls/find/du/rm scenarios against a
throwaway tmpfs MinIO for mc, mx (glibc) and mx (musl) and prints a markdown
table; RESULTS.md records the first run and the likely causes of the gaps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
musl's malloc serializes allocations on one lock; parallel small-file
work used 1.5-2.8x the CPU of the glibc build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Uploads follow minio-go: single PUT up to 16 MiB (or --part-size), parts of
  OptimalPartInfo size (16 MiB multiples, 528 MiB for unknown lengths, as mc
  pipe), 4 parts in parallel unless -P/--concurrent say otherwise.
- Local-file multipart parts stream from file ranges (ByteStream::read_from)
  instead of Vec buffers; --checksum/object-lock uploads keep buffered parts.
  Progress counts bytes as the part bodies are sent.
- Downloads and local copies write through a 1 MiB buffer, so tokio does one
  blocking handoff per MiB instead of per 8 KiB.
- BlockingReader zeroes at most 64 KiB per read (large part buffers made it
  quadratic).

glibc release, 2 GiB file: cp up 5.84 s -> 0.94 s (mc 1.43 s), RSS 111 -> 49 MiB;
cp down 2.02 s -> 0.76 s (mc 0.79 s).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ter perf fixes

An empty SOURCE_DATE_EPOCH made GCC reject mimalloc's __DATE__ in
local and CI Docker builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reference mc can hang in sql (minio-go event stream); the harness
now kills commands after MX_PARITY_TIMEOUT seconds (default 120) and
the sql cases retry them. CI jobs get timeout-minutes so a hang no
longer runs for six hours.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@andrasbacsai
andrasbacsai merged commit bd9f4e4 into main Sep 27, 2026
6 checks passed
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