mirror of
https://github.com/apple/container.git
synced 2026-09-20 22:55:40 +00:00
Add configurable concurrent layer downloads (#311)
Adds `maxConcurrentDownloads` parameter to `ImageStore.pull()`. Performance improvement: ~1.2-1.3x faster pulls for multi-layer images with higher concurrency. Signed-off-by: Santosh Bhavani <santosh.bhavani@live.com>
This commit is contained in:
@@ -30,13 +30,15 @@ extension ImageStore {
|
||||
let contentStore: ContentStore
|
||||
let progress: ProgressHandler?
|
||||
let name: String
|
||||
let maxConcurrentDownloads: Int
|
||||
|
||||
public init(name: String, contentStore: ContentStore, client: ContentClient, ingestDir: URL, progress: ProgressHandler? = nil) {
|
||||
public init(name: String, contentStore: ContentStore, client: ContentClient, ingestDir: URL, progress: ProgressHandler? = nil, maxConcurrentDownloads: Int = 3) {
|
||||
self.client = client
|
||||
self.ingestDir = ingestDir
|
||||
self.contentStore = contentStore
|
||||
self.progress = progress
|
||||
self.name = name
|
||||
self.maxConcurrentDownloads = maxConcurrentDownloads
|
||||
}
|
||||
|
||||
/// Pull the required image layers for the provided descriptor and platform(s) into the given directory using the provided client. Returns a descriptor to the Index manifest.
|
||||
@@ -120,13 +122,15 @@ extension ImageStore {
|
||||
private func fetchAll(_ descriptors: [Descriptor]) async throws {
|
||||
try await withThrowingTaskGroup(of: Void.self) { group in
|
||||
var iterator = descriptors.makeIterator()
|
||||
for _ in 0..<8 {
|
||||
// Start initial batch of concurrent downloads based on maxConcurrentDownloads
|
||||
for _ in 0..<self.maxConcurrentDownloads {
|
||||
if let desc = iterator.next() {
|
||||
group.addTask {
|
||||
try await self.fetch(desc)
|
||||
}
|
||||
}
|
||||
}
|
||||
// As tasks complete, add new ones to maintain concurrency
|
||||
for try await _ in group {
|
||||
if let desc = iterator.next() {
|
||||
group.addTask {
|
||||
|
||||
@@ -192,7 +192,7 @@ extension ImageStore {
|
||||
/// - Returns: A `Containerization.Image` object to the newly pulled image.
|
||||
public func pull(
|
||||
reference: String, platform: Platform? = nil, insecure: Bool = false,
|
||||
auth: Authentication? = nil, progress: ProgressHandler? = nil
|
||||
auth: Authentication? = nil, progress: ProgressHandler? = nil, maxConcurrentDownloads: Int = 3
|
||||
) async throws -> Image {
|
||||
|
||||
let matcher = createPlatformMatcher(for: platform)
|
||||
@@ -206,7 +206,8 @@ extension ImageStore {
|
||||
|
||||
let rootDescriptor = try await client.resolve(name: name, tag: tag)
|
||||
let (id, tempDir) = try await self.contentStore.newIngestSession()
|
||||
let operation = ImportOperation(name: name, contentStore: self.contentStore, client: client, ingestDir: tempDir, progress: progress)
|
||||
let operation = ImportOperation(
|
||||
name: name, contentStore: self.contentStore, client: client, ingestDir: tempDir, progress: progress, maxConcurrentDownloads: maxConcurrentDownloads)
|
||||
do {
|
||||
let index = try await operation.import(root: rootDescriptor, matcher: matcher)
|
||||
return try await self.lock.withLock { lock in
|
||||
|
||||
Reference in New Issue
Block a user