import Benchmark import Foundation import NorgKit let benchmarks: @Sendable () -> Benchmark? = { // Load the norg files from the Documentation directory. let fileManager = FileManager.default let currentDirectory = fileManager.currentDirectoryPath let documentationPath = (currentDirectory as NSString).appendingPathComponent("Documentation") let examplePath = (documentationPath as NSString).appendingPathComponent("example.norg") let hugePath = (documentationPath as NSString).appendingPathComponent("huge.norg") let exampleSource: String let hugeSource: String do { exampleSource = try String(contentsOfFile: examplePath, encoding: .utf8) } catch { print("Current directory: \(currentDirectory)") print("Failed to load example.norg from: \(examplePath)") print("Error: \(error)") fatalError("Failed to load example.norg") } do { hugeSource = try String(contentsOfFile: hugePath, encoding: .utf8) } catch { print("Failed to load huge.norg from: \(hugePath)") print("Error: \(error)") fatalError("Failed to load huge.norg") } Benchmark.defaultConfiguration.maxDuration = .seconds(3) Benchmark.defaultConfiguration.maxIterations = 500 let fileURL = URL(fileURLWithPath: "/vault/today.norg") Benchmark("parse example") { benchmark in for _ in benchmark.scaledIterations { blackHole(NorgParser.parse(exampleSource)) } } Benchmark("parse huge") { benchmark in for _ in benchmark.scaledIterations { blackHole(NorgParser.parse(hugeSource)) } } // Same parse, plus the tree-folding pass — the delta against "parse …" above // is the cost of building the hierarchy. Benchmark("parse tree example") { benchmark in for _ in benchmark.scaledIterations { blackHole(NorgParser.parseTree(exampleSource)) } } Benchmark("parse tree huge") { benchmark in for _ in benchmark.scaledIterations { blackHole(NorgParser.parseTree(hugeSource)) } } // Just the fold, over an already-parsed document, to isolate its cost. let hugeDocument = NorgParser.parse(hugeSource) Benchmark("fold huge") { benchmark in for _ in benchmark.scaledIterations { blackHole(hugeDocument.tree()) } } // Task scanning is meant to be cheap enough to run across an entire vault, so // it bypasses the full block parser. Benchmark("scan tasks example") { benchmark in for _ in benchmark.scaledIterations { blackHole(TaskScanner.scan(content: exampleSource, fileURL: fileURL)) } } Benchmark("scan tasks huge") { benchmark in for _ in benchmark.scaledIterations { blackHole(TaskScanner.scan(content: hugeSource, fileURL: fileURL)) } } // Rewriting a single status marker — the write-back path for toggling a task. // Line 17 (zero-based) is the first task in huge.norg, so this exercises the // full split / replace / re-join path rather than bailing out early. return Benchmark("update task status huge") { benchmark in for _ in benchmark.scaledIterations { blackHole(TaskScanner.updatedContent(hugeSource, line: 17, to: .done)) } } }