We parallelize our billion-row parser using structured concurrency, splitting a memory-mapped file into newline-aligned chunks and processing them concurrently with a Swift Task Group before merging the per-chunk results. Along the way we cover @unchecked Sendable on pointer-backed types, why the SIMD experiment didn't pay off compared to memchr, benchmarking with hyperfine, and tuning chunk count against processor count. All of this ends up taking the run from 50 seconds down to about 5.
Links The One Billion Row Challenge withTaskGroup(of:returning:body:) TaskGroup Sendable UnsafeRawPointer UnsafeBufferPointer ProcessInfo.activeProcessorCount Dictionary.merge(_:uniquingKeysWith:) hyperfine btop Code A Sendable wrapper around the memory-mapped file, so chunks can be handed to concurrent tasks: struct MappedFile: @unchecked Sendable { let base: UnsafeRawPointer let size: Int var bytes: UnsafePointer<UInt8> { base.assumingMemoryBound(to: UInt8.self) } } Splitting the file into newline-aligned ranges, using memchr to walk forward from each naive split point to the next line feed: func chunkRanges(in file: MappedFile, count: Int) -> [Range<Int>] { let targetSize = file.size / count var ranges: [Range<Int>] = [] var start = 0 for i in 1...count { var end = min(i * targetSize, file.size) if i < count { let newline = memchr(file.base + end, Int32(UInt8(ascii: "\n")), file.size - end)! end += file.base.advanced(by: end).distance(to: newline) + 1 } else { end = file.size } ranges.append(start..<end) start = end } return ranges } Fanning the chunks out across a task group and merging the per-chunk results: let ranges = chunkRanges(in: file, count: ProcessInfo.processInfo.activeProcessorCount) var merged = await withTaskGroup(of: Results.self) { group in for range in ranges { group.addTask { processResults(in: file, range: range) } } var merged = Results() for await results in group { merged.merge(results) { a, b in Entry( min: min(a.min, b.min), max: max(a.max, b.max), sum: a.sum + b.sum, count: a.count + b.count ) } } return merged }