aboutsummaryrefslogtreecommitdiff
path: root/Benchmarks/ParseBenchmarkTarget/ParseBenchmarkTarget.swift
blob: a5346f201d743fcf9430afb57a24d778e331705a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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))
    }
  }

  // Source tokenization for syntax highlighting.
  Benchmark("lex example") { benchmark in
    for _ in benchmark.scaledIterations {
      blackHole(NorgLexer.tokenize(exampleSource))
    }
  }

  Benchmark("lex huge") { benchmark in
    for _ in benchmark.scaledIterations {
      blackHole(NorgLexer.tokenize(hugeSource))
    }
  }

  // Rewriting a single status marker — the write-back path for toggling a task.
  return Benchmark("update task status huge") { benchmark in
    for _ in benchmark.scaledIterations {
      blackHole(TaskScanner.updatedContent(hugeSource, line: 17, to: .done))
    }
  }
}