native macOS codings agent orchestrator prowl.onev.cat
Something went wrong. Try again.
4.8 kB · 121 lines
Swift
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122import Foundationimport Testing
@testable import supacode
extension PerformanceBenchmarks { /// Pins the #644/#652 untracked line-count scanner against the pre-#644 /// `Data.reduce` reader it replaced. Two shapes matter: sparse text is where /// `memchr` wins, and newline-dense input is where pure `memchr` regressed /// past the original until the hybrid raw-pointer fallback bounded it. @Suite struct LineCountScanBenchmarks { @Test func scannerOutpacesTheReduceReaderOnSparseText() throws { try assertScannerBeatsReference( data: Self.sparseText(byteCount: Self.inputByteCount), name: "sparse", minimumRatio: 3 ) }
/// Optimized builds only: the dense case is a race between two Swift-level /// loops (the hybrid's raw-pointer fallback vs `Data.Iterator`), and under /// `-Onone` the fallback loses — see `BenchmarkMeasurement.isOptimizedBuild`. @Test(.enabled(if: BenchmarkMeasurement.isOptimizedBuild)) func scannerStaysAheadOfTheReduceReaderOnAllNewlineInput() throws { try assertScannerBeatsReference( data: Data(repeating: 0x0A, count: Self.inputByteCount), name: "all-newline", minimumRatio: 2 ) }
private func assertScannerBeatsReference(data: Data, name: String, minimumRatio: Double) throws { let fileManager = FileManager.default let tempRoot = fileManager.temporaryDirectory.appending(path: UUID().uuidString) defer { try? fileManager.removeItem(at: tempRoot) } try fileManager.createDirectory(at: tempRoot, withIntermediateDirectories: true) try data.write(to: tempRoot.appending(path: "input.txt"))
// Both implementations must agree before their speed is compared. let shippedCount = GitClient.countLinesInFiles( ["input.txt"], relativeTo: tempRoot, cache: UntrackedLineCountCache() ) let referenceCount = Self.referenceCountLines(in: tempRoot.appending(path: "input.txt")) #expect(shippedCount.skippedFileCount == 0) #expect(shippedCount.lines == referenceCount)
let medians = BenchmarkMeasurement.interleavedMedians( reference: { _ = Self.referenceCountLines(in: tempRoot.appending(path: "input.txt")) }, shipped: { // A fresh cache each round keeps this a scan benchmark; the cached // path is pinned separately by the byte-budget proxy tests. _ = GitClient.countLinesInFiles( ["input.txt"], relativeTo: tempRoot, cache: UntrackedLineCountCache() ) } ) BenchmarkMeasurement.report(suite: "LineCountScan", name: name, medians: medians) #expect( BenchmarkMeasurement.ratio(medians) >= minimumRatio, "shipped scanner was only \(BenchmarkMeasurement.ratio(medians))x the reduce reader on \(name)" ) }
private static var inputByteCount: Int { (BenchmarkMeasurement.isFullMode ? 2_048 : 256) * 1_024 }
/// Text shaped like a `sample(1)` capture — the workload #644 was written /// against: moderate lines, leading indentation, pure ASCII. private static func sparseText(byteCount: Int) -> Data { var out = Data(capacity: byteCount + 128) var lineNumber = 0 while out.count < byteCount { let indent = String(repeating: " ", count: 4 + (lineNumber % 5) * 2) let line = "\(indent)\(1_200 + lineNumber % 800) Thread_\(90_000 + lineNumber) com.apple.main-thread\n" out.append(Data(line.utf8)) lineNumber += 1 } return out.prefix(byteCount) }
/// The pre-#644 reader, verbatim: 64 KiB chunks walked through /// `Data.Iterator` with a value-witness call per byte. private static func referenceCountLines(in fileURL: URL) -> Int? { guard let handle = try? FileHandle(forReadingFrom: fileURL) else { return nil } defer { try? handle.close() }
let binaryProbeByteCount = 8_192 let chunkByteCount = 64 * 1_024 var probedByteCount = 0 var lineCount = 0 var isEmpty = true var lastByte: UInt8?
while true { guard let chunk = try? handle.read(upToCount: chunkByteCount), !chunk.isEmpty else { break } isEmpty = false if probedByteCount < binaryProbeByteCount { let remainingProbeCount = binaryProbeByteCount - probedByteCount let probe = chunk.prefix(remainingProbeCount) if probe.contains(0x00) { return nil } probedByteCount += probe.count } lineCount += chunk.reduce(0) { $0 + ($1 == 0x0A ? 1 : 0) } lastByte = chunk.last }
if !isEmpty, lastByte != 0x0A { lineCount += 1 } return lineCount } }}