Skip to content

Commit d93354d

Browse files
Reduce high CPU usage during downloads (#291)
* Reduce CPU usage during downloads * Clean up comments
1 parent 91286f2 commit d93354d

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

Sources/Hub/Downloader.swift

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -262,16 +262,30 @@ final class Downloader: NSObject, Sendable {
262262

263263
var newNumRetries = numRetries
264264
do {
265+
// Batch collect bytes to reduce Data.append() overhead
266+
// Use ContiguousArray for better performance (no NSArray bridging overhead)
267+
let batchSize = 16384 // 16 kB
268+
var byteBatch = ContiguousArray<UInt8>()
269+
byteBatch.reserveCapacity(batchSize)
270+
265271
for try await byte in asyncBytes {
266-
buffer.append(byte)
272+
byteBatch.append(byte)
273+
274+
// Append batch to main buffer
275+
if byteBatch.count >= batchSize {
276+
buffer.append(contentsOf: byteBatch)
277+
byteBatch.removeAll(keepingCapacity: true)
278+
}
279+
267280
// When buffer is full, write to disk
268-
if buffer.count == chunkSize {
281+
if buffer.count >= chunkSize {
269282
if !buffer.isEmpty { // Filter out keep-alive chunks
270283
try tempFile.write(contentsOf: buffer)
284+
let bytesWritten = buffer.count
271285
buffer.removeAll(keepingCapacity: true)
272286

273-
totalDownloadedLocal += chunkSize
274-
await downloadResumeState.incDownloadedSize(chunkSize)
287+
totalDownloadedLocal += bytesWritten
288+
await downloadResumeState.incDownloadedSize(bytesWritten)
275289
newNumRetries = 5
276290
guard let expectedSize = await downloadResumeState.expectedSize else { continue }
277291
let progress = expectedSize != 0 ? Double(totalDownloadedLocal) / Double(expectedSize) : 0
@@ -289,6 +303,11 @@ final class Downloader: NSObject, Sendable {
289303
}
290304
}
291305

306+
// Flush remaining bytes from batch
307+
if !byteBatch.isEmpty {
308+
buffer.append(contentsOf: byteBatch)
309+
}
310+
292311
if !buffer.isEmpty {
293312
try tempFile.write(contentsOf: buffer)
294313
totalDownloadedLocal += buffer.count
@@ -445,12 +464,8 @@ actor Broadcaster<E: Sendable> {
445464

446465
func broadcast(state: E) async {
447466
latestState = state
448-
await withTaskGroup(of: Void.self) { group in
449-
for continuation in continuations.values {
450-
group.addTask {
451-
continuation.yield(state)
452-
}
453-
}
467+
for continuation in continuations.values {
468+
continuation.yield(state)
454469
}
455470
}
456471
}

0 commit comments

Comments
 (0)