Add --max-concurrent-downloads flag for parallel layer downloads (#716)

Adds `--max-concurrent-downloads` flag to `container image pull` for
configurable concurrent layer downloads.

Fixes #715
Depends on apple/containerization#311

**Usage**:
```bash
container image pull nginx:latest --max-concurrent-downloads 6
```

**Changes**:
- Add CLI flag (default: 3)
- Thread parameter through XPC stack
- Update to use forked containerization with configurable concurrency

**Performance**: ~1.2-1.3x faster pulls for multi-layer images with
higher concurrency

**Tests**: Included standalone tests verify concurrency behavior and
parameter flow

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Santosh Bhavani
2025-12-07 15:56:50 -03:00
committed by GitHub
co-authored by Claude
parent 1e19a4d6e3
commit f7bcb687fd
11 changed files with 84 additions and 11 deletions
@@ -40,6 +40,9 @@ extension Application {
@OptionGroup(title: "Registry options")
var registryFlags: Flags.Registry
@OptionGroup(title: "Image fetch options")
var imageFetchFlags: Flags.ImageFetch
@OptionGroup
var global: Flags.Global
@@ -73,6 +76,7 @@ extension Application {
management: managementFlags,
resource: resourceFlags,
registry: registryFlags,
imageFetch: imageFetchFlags,
progressUpdate: progress.handler
)
@@ -47,6 +47,9 @@ extension Application {
@OptionGroup(title: "Progress options")
var progressFlags: Flags.Progress
@OptionGroup(title: "Image fetch options")
var imageFetchFlags: Flags.ImageFetch
@OptionGroup
var global: Flags.Global
@@ -97,6 +100,7 @@ extension Application {
management: managementFlags,
resource: resourceFlags,
registry: registryFlags,
imageFetch: imageFetchFlags,
progressUpdate: progress.handler
)
@@ -36,6 +36,9 @@ extension Application {
@OptionGroup
var progressFlags: Flags.Progress
@OptionGroup
var imageFetchFlags: Flags.ImageFetch
@Option(
name: .shortAndLong,
help: "Limit the pull to the specified architecture"
@@ -100,7 +103,8 @@ extension Application {
let taskManager = ProgressTaskCoordinator()
let fetchTask = await taskManager.startTask()
let image = try await ClientImage.pull(
reference: processedReference, platform: p, scheme: scheme, progressUpdate: ProgressTaskCoordinator.handler(for: fetchTask, from: progress.handler)
reference: processedReference, platform: p, scheme: scheme, progressUpdate: ProgressTaskCoordinator.handler(for: fetchTask, from: progress.handler),
maxConcurrentDownloads: self.imageFetchFlags.maxConcurrentDownloads
)
progress.set(description: "Unpacking image")