import Foundation import Testing @testable import CodexBarCore @Suite(.serialized) struct CostUsageJsonlShapeBenchmarkTests { @Test func `scanner benchmark covers codex session history shape`() throws { let root = FileManager.default.temporaryDirectory.appendingPathComponent( "codexbar-cost-jsonl-shape-\(UUID().uuidString)", isDirectory: true) try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true) defer { try? FileManager.default.removeItem(at: root) } let divisor = Self.shapeDivisor() let plan = CodexJsonlShapePlan.localThirtyDaySample.scaled(divisor: divisor) let fileURL = root.appendingPathComponent("codex-shape.jsonl", isDirectory: false) let fixture = try CodexJsonlShapeFixture.write(plan: plan, to: fileURL) let maxLineBytes = 256 * 1024 let prefixBytes = 32 * 1024 let currentSummary = try self.summarizeScan( fileURL: fileURL, maxLineBytes: maxLineBytes, prefixBytes: prefixBytes, scanner: CostUsageJsonl.scan) let baselineSummary = try self.summarizeScan( fileURL: fileURL, maxLineBytes: maxLineBytes, prefixBytes: prefixBytes, scanner: self.scanWithFrontBufferBaseline) #expect(currentSummary.lineCount == fixture.lineCount) #expect(currentSummary.truncatedCount == fixture.truncatedLineCount) #expect(currentSummary.endOffset == fixture.byteCount) #expect(baselineSummary.lineCount == currentSummary.lineCount) #expect(baselineSummary.truncatedCount == currentSummary.truncatedCount) #expect(baselineSummary.endOffset == currentSummary.endOffset) _ = try self.summarizeScan( fileURL: fileURL, maxLineBytes: maxLineBytes, prefixBytes: prefixBytes, scanner: CostUsageJsonl.scan) _ = try self.summarizeScan( fileURL: fileURL, maxLineBytes: maxLineBytes, prefixBytes: prefixBytes, scanner: self.scanWithFrontBufferBaseline) let currentFastest = try self.fastestScanDurationNanoseconds( runs: 3, fileURL: fileURL, maxLineBytes: maxLineBytes, prefixBytes: prefixBytes, scanner: CostUsageJsonl.scan) let baselineFastest = try self.fastestScanDurationNanoseconds( runs: 3, fileURL: fileURL, maxLineBytes: maxLineBytes, prefixBytes: prefixBytes, scanner: self.scanWithFrontBufferBaseline) let currentMBps = Self.megabytesPerSecond(byteCount: fixture.byteCount, nanoseconds: currentFastest) let baselineMBps = Self.megabytesPerSecond(byteCount: fixture.byteCount, nanoseconds: baselineFastest) let speedup = Double(baselineFastest) / Double(currentFastest) print( "Codex JSONL shape benchmark: divisor=\(divisor) " + "bytes=\(fixture.byteCount) lines=\(fixture.lineCount) " + "truncated=\(fixture.truncatedLineCount) " + "current=\(Self.format(currentMBps))MB/s " + "baseline=\(Self.format(baselineMBps))MB/s " + "speedup=\(Self.format(speedup))x") } @Test func `synthetic codex rows preserve model attribution`() throws { let env = try CostUsageTestEnvironment() defer { env.cleanup() } let day = try env.makeLocalNoon(year: 2026, month: 5, day: 18) let iso0 = env.isoString(for: day) let iso1 = env.isoString(for: day.addingTimeInterval(1)) let iso2 = env.isoString(for: day.addingTimeInterval(2)) let model = "openai/gpt-5.5" let turnContext: [String: Any] = [ "type": "turn_context", "timestamp": iso0, "payload": [ "model": model, "instructions": "synthetic", ], ] let firstTokenCount = self.tokenCountWithoutModel( timestamp: iso1, input: 100, cached: 40, output: 10) let secondTokenCount = self.tokenCountWithoutModel( timestamp: iso2, input: 50, cached: 20, output: 5) let fileURL = try env.writeCodexSessionFile( day: day, filename: "synthetic-attribution.jsonl", contents: env.jsonl([turnContext, firstTokenCount, secondTokenCount])) let parsed = CostUsageScanner.parseCodexFile( fileURL: fileURL, range: CostUsageScanner.CostUsageDayRange(since: day, until: day)) let dayKey = CostUsageScanner.CostUsageDayRange.dayKey(from: day) #expect(parsed.days[dayKey]?["gpt-5.5"] == [150, 60, 15]) #expect(parsed.days[dayKey]?["gpt-5"] == nil) } private static func shapeDivisor() -> Int { let value = ProcessInfo.processInfo.environment["CODEXBAR_COST_JSONL_SHAPE_DIVISOR"] ?? "20" return max(1, Int(value) ?? 20) } private static func megabytesPerSecond(byteCount: Int64, nanoseconds: UInt64) -> Double { let seconds = Double(nanoseconds) / 1_000_000_000 guard seconds > 0 else { return 0 } return (Double(byteCount) / 1_000_000) / seconds } private static func format(_ value: Double) -> String { String(format: "%.1f", value) } private func tokenCountWithoutModel(timestamp: String, input: Int, cached: Int, output: Int) -> [String: Any] { [ "type": "event_msg", "timestamp": timestamp, "payload": [ "type": "token_count", "info": [ "last_token_usage": [ "input_tokens": input, "cached_input_tokens": cached, "output_tokens": output, ], ], ], ] } private func summarizeScan( fileURL: URL, maxLineBytes: Int, prefixBytes: Int, scanner: JsonlShapeScanner) throws -> JsonlShapeScanSummary { var lineCount = 0 var truncatedCount = 0 let endOffset = try scanner(fileURL, 0, maxLineBytes, prefixBytes) { line in lineCount += 1 if line.wasTruncated { truncatedCount += 1 } } return JsonlShapeScanSummary( lineCount: lineCount, truncatedCount: truncatedCount, endOffset: endOffset) } private func fastestScanDurationNanoseconds( runs: Int, fileURL: URL, maxLineBytes: Int, prefixBytes: Int, scanner: JsonlShapeScanner) throws -> UInt64 { var fastest = UInt64.max for _ in 0.. Void) throws -> Int64 { let handle = try FileHandle(forReadingFrom: fileURL) defer { try? handle.close() } let startOffset = max(0, offset) if startOffset > 0 { try handle.seek(toOffset: UInt64(startOffset)) } var buffer = Data() buffer.reserveCapacity(64 * 1024) var current = Data() current.reserveCapacity(4 * 1024) var lineBytes = 0 var truncated = false var bytesRead: Int64 = 0 func flushLine() { guard lineBytes > 0 else { return } onLine(.init(bytes: current, wasTruncated: truncated)) current.removeAll(keepingCapacity: true) lineBytes = 0 truncated = false } while true { let chunk = try handle.read(upToCount: 256 * 1024) ?? Data() if chunk.isEmpty { flushLine() break } bytesRead += Int64(chunk.count) buffer.append(chunk) while true { guard let nl = buffer.firstIndex(of: 0x0A) else { break } let linePart = buffer[.. maxLineBytes || lineBytes > prefixBytes { truncated = true current.removeAll(keepingCapacity: true) } else { current.append(contentsOf: linePart) } } flushLine() } } return startOffset + bytesRead } } private typealias JsonlShapeScanner = ( _ fileURL: URL, _ offset: Int64, _ maxLineBytes: Int, _ prefixBytes: Int, _ onLine: (CostUsageJsonl.Line) -> Void) throws -> Int64 private struct JsonlShapeScanSummary: Equatable { let lineCount: Int let truncatedCount: Int let endOffset: Int64 } private struct CodexJsonlShapePlan { static let localThirtyDaySample = CodexJsonlShapePlan( totalLines: 145_797, relevantLines: 57063, tokenCountWithoutModelLines: 22235, turnContextLines: 1935, longTurnContextLines: 207, linesOver32KiB: 2584, linesOver256KiB: 697) let totalLines: Int let relevantLines: Int let tokenCountWithoutModelLines: Int let turnContextLines: Int let longTurnContextLines: Int let linesOver32KiB: Int let linesOver256KiB: Int func scaled(divisor: Int) -> CodexJsonlShapePlan { CodexJsonlShapePlan( totalLines: self.scaled(self.totalLines, divisor: divisor), relevantLines: self.scaled(self.relevantLines, divisor: divisor), tokenCountWithoutModelLines: self.scaled(self.tokenCountWithoutModelLines, divisor: divisor), turnContextLines: self.scaled(self.turnContextLines, divisor: divisor), longTurnContextLines: self.scaled(self.longTurnContextLines, divisor: divisor), linesOver32KiB: self.scaled(self.linesOver32KiB, divisor: divisor), linesOver256KiB: self.scaled(self.linesOver256KiB, divisor: divisor)) } private func scaled(_ value: Int, divisor: Int) -> Int { max(1, Int((Double(value) / Double(divisor)).rounded())) } } private struct CodexJsonlShapeFixture { let byteCount: Int64 let lineCount: Int let truncatedLineCount: Int static func write(plan: CodexJsonlShapePlan, to fileURL: URL) throws -> CodexJsonlShapeFixture { FileManager.default.createFile(atPath: fileURL.path, contents: nil) let handle = try FileHandle(forWritingTo: fileURL) defer { try? handle.close() } var byteCount: Int64 = 0 var lineCount = 0 func writeLine(_ line: String) throws { let data = Data((line + "\n").utf8) try handle.write(contentsOf: data) byteCount += Int64(data.count) lineCount += 1 } let longTurnContextCount = min(plan.longTurnContextLines, plan.turnContextLines) let shortTurnContextCount = plan.turnContextLines - longTurnContextCount let largeIrrelevantOver256Count = plan.linesOver256KiB let largeIrrelevantOver32Count = max( 0, plan.linesOver32KiB - longTurnContextCount - largeIrrelevantOver256Count) let otherRelevantCount = max( 0, plan.relevantLines - plan.tokenCountWithoutModelLines - plan.turnContextLines) let writtenBeforeSmallIrrelevant = plan.tokenCountWithoutModelLines + shortTurnContextCount + longTurnContextCount + otherRelevantCount + largeIrrelevantOver32Count + largeIrrelevantOver256Count let smallIrrelevantCount = max(0, plan.totalLines - writtenBeforeSmallIrrelevant) try self.writeRepeated( count: plan.tokenCountWithoutModelLines, line: self.tokenCountWithoutModelLine, writer: writeLine) try self.writeRepeated( count: shortTurnContextCount, line: self.turnContextLine(fillerBytes: 2048), writer: writeLine) try self.writeRepeated( count: longTurnContextCount, line: self.turnContextLine(fillerBytes: 40 * 1024), writer: writeLine) try self.writeRepeated( count: otherRelevantCount, line: self.taskStartedLine, writer: writeLine) try self.writeRepeated( count: largeIrrelevantOver32Count, line: self.irrelevantLine(fillerBytes: 64 * 1024), writer: writeLine) try self.writeRepeated( count: largeIrrelevantOver256Count, line: self.irrelevantLine(fillerBytes: 300 * 1024), writer: writeLine) try self.writeRepeated( count: smallIrrelevantCount, line: self.irrelevantLine(fillerBytes: 512), writer: writeLine) return CodexJsonlShapeFixture( byteCount: byteCount, lineCount: lineCount, truncatedLineCount: longTurnContextCount + largeIrrelevantOver32Count + largeIrrelevantOver256Count) } private static let tokenCountWithoutModelLine = #"{"type":"event_msg","timestamp":"2026-05-18T00:00:00Z","payload":{"type":"token_count","info":"# + #"{"last_token_usage":{"input_tokens":100,"cached_input_tokens":40,"output_tokens":10}}}}"# private static let taskStartedLine = #"{"type":"event_msg","timestamp":"2026-05-18T00:00:00Z","payload":"# + #"{"type":"task_started","turn_id":"turn-0001"}}"# private static func turnContextLine(fillerBytes: Int) -> String { #"{"type":"turn_context","timestamp":"2026-05-18T00:00:00Z","payload":"# + #"{"model":"openai/gpt-5.5","instructions":""# + String(repeating: "x", count: fillerBytes) + #""}}"# } private static func irrelevantLine(fillerBytes: Int) -> String { #"{"type":"response_item","payload":""# + String(repeating: "x", count: fillerBytes) + #""}"# } private static func writeRepeated( count: Int, line: String, writer: (String) throws -> Void) throws { for _ in 0..