Skip to content

Commit 786e19a

Browse files
committed
Prevent using split by \.newLine for faster speed
1 parent 8b3ad69 commit 786e19a

4 files changed

Lines changed: 50 additions & 6 deletions

File tree

Pro

Submodule Pro updated from 80b755f to b442fe8

Tool/Sources/SharedUIComponents/SyntaxHighlighting.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import AppKit
22
import Foundation
33
import Highlightr
4+
import SuggestionModel
45
import SwiftUI
56

67
public func highlightedCodeBlock(
@@ -82,7 +83,7 @@ func convertToCodeLines(
8283
return false
8384
}
8485

85-
let separatedInput = input.split(omittingEmptySubsequences: false, whereSeparator: \.isNewline)
86+
let separatedInput = input.splitByNewLine(omittingEmptySubsequences: false)
8687
.map { String($0) }
8788
let commonLeadingSpaceCount = {
8889
if !droppingLeadingSpaces { return 0 }

Tool/Sources/SuggestionModel/String+LineEnding.swift

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,48 @@ import Foundation
22

33
public extension String {
44
/// The line ending of the string.
5+
///
6+
/// We are pretty safe to just check the last character here, in most case, a line ending
7+
/// will be in the end of the string.
8+
///
9+
/// For other situations, we can assume that they are "\n".
510
var lineEnding: Character? {
6-
last(where: \.isNewline)
11+
if let last, last.isNewline { return last }
12+
return "\n"
13+
}
14+
15+
func splitByNewLine(
16+
omittingEmptySubsequences: Bool = true,
17+
fast: Bool = true
18+
) -> [Substring] {
19+
if fast {
20+
let lineEndingInText = lineEnding ?? "\n"
21+
return split(
22+
separator: lineEndingInText,
23+
omittingEmptySubsequences: omittingEmptySubsequences
24+
)
25+
}
26+
return split(
27+
omittingEmptySubsequences: omittingEmptySubsequences,
28+
whereSeparator: \.isNewline
29+
)
730
}
831

932
/// Break a string into lines.
1033
func breakLines(
1134
proposedLineEnding: String? = nil,
1235
appendLineBreakToLastLine: Bool = false
1336
) -> [String] {
14-
let lineEnding = proposedLineEnding ?? String(lineEnding ?? "\n")
15-
let lines = split(omittingEmptySubsequences: false, whereSeparator: \.isNewline)
37+
let lineEndingInText = lineEnding ?? "\n"
38+
let lineEnding = proposedLineEnding ?? String(lineEndingInText)
39+
// Split on character for better performance.
40+
let lines = split(separator: lineEndingInText, omittingEmptySubsequences: false)
1641
var all = [String]()
1742
for (index, line) in lines.enumerated() {
1843
if !appendLineBreakToLastLine, index == lines.endIndex - 1 {
1944
all.append(String(line))
2045
} else {
21-
all.append(String(line) + String(lineEnding))
46+
all.append(String(line) + lineEnding)
2247
}
2348
}
2449
return all
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import Foundation
2+
import XCTest
3+
@testable import SuggestionModel
4+
5+
final class BreakLinePerformanceTests: XCTestCase {
6+
func test_breakLines() {
7+
let string = String(repeating: """
8+
Hello
9+
World
10+
11+
""", count: 50000)
12+
13+
measure {
14+
let _ = string.breakLines()
15+
}
16+
}
17+
}
18+

0 commit comments

Comments
 (0)