Jest to prawie taka sama jak zaakceptowana odpowiedź, ale z dodatkowymi dialogami (miałem z Robem Napierem, jego innymi odpowiedziami oraz Mattem, Oliverem, Davidem ze Slacka) i linkami.
Zobacz komentarze w tej dyskusji. Istota tego jest taka:
+
jest mocno przeciążony (wydaje się, że Apple naprawił to w niektórych przypadkach)
+
Operator jest mocno przeciążony, ponieważ od teraz ma 27 różnych funkcji, więc jeśli złączenie 4 strings czyli masz 3 +
operatorów kompilator musi się sprawdzić między 27 operatorów za każdym razem, więc to 27 ^ 3 razy. Ale to nie wszystko.
Istnieje również sprawdzić , czy lhs
i rhs
z +
funkcjami są zarówno ważne, jeżeli są one wywołuje aż do jądrze append
nazywa. Jak widać , może dojść do szeregu dość intensywnych kontroli . Jeśli ciąg jest przechowywany w sposób nieciągły, co wydaje się mieć miejsce, jeśli ciąg, z którym masz do czynienia, jest faktycznie mostkowany do NSString. Swift musi następnie ponownie złożyć wszystkie bufory tablicy bajtów w jeden ciągły bufor, co wymaga tworzenia nowych buforów po drodze. a potem w końcu otrzymujesz jeden bufor, który zawiera ciąg, który próbujesz połączyć.
Krótko mówiąc, istnieją 3 klastry kontroli kompilatora, które spowalniają Cię, tj. Każde wyrażenie podrzędne musi zostać ponownie przemyślane w świetle wszystkiego, co może zwrócić . W rezultacie łączenie ciągów za pomocą interpolacji, tj. Używanie " My fullName is \(firstName) \(LastName)"
jest znacznie lepsze niż "My firstName is" + firstName + LastName
ponieważ interpolacja nie ma żadnego przeciążenia
Swift 3 wprowadził pewne ulepszenia. Aby uzyskać więcej informacji, przeczytaj artykuł Jak scalić wiele tablic bez spowalniania kompilatora? . Niemniej jednak +
operator jest nadal przeciążony i lepiej jest używać interpolacji ciągów dla dłuższych ciągów
Wykorzystanie opcji (bieżący problem - dostępne rozwiązanie)
W tym bardzo prostym projekcie:
import UIKit
class ViewController: UIViewController {
let p = Person()
let p2 = Person2()
func concatenatedOptionals() -> String {
return (p2.firstName ?? "") + "" + (p2.lastName ?? "") + (p2.status ?? "")
}
func interpolationOptionals() -> String {
return "\(p2.firstName ?? "") \(p2.lastName ?? "")\(p2.status ?? "")"
}
func concatenatedNonOptionals() -> String {
return (p.firstName) + "" + (p.lastName) + (p.status)
}
func interpolatedNonOptionals() -> String {
return "\(p.firstName) \(p.lastName)\(p.status)"
}
}
struct Person {
var firstName = "Swift"
var lastName = "Honey"
var status = "Married"
}
struct Person2 {
var firstName: String? = "Swift"
var lastName: String? = "Honey"
var status: String? = "Married"
}
Czas kompilacji funkcji jest następujący:
21664.28ms /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:16:10 instance method concatenatedOptionals()
2.31ms /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:20:10 instance method interpolationOptionals()
0.96ms /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:24:10 instance method concatenatedNonOptionals()
0.82ms /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:28:10 instance method interpolatedNonOptionals()
Zwróć uwagę, jak szalony jest czas trwania kompilacji concatenatedOptionals
.
Można to rozwiązać, wykonując:
let emptyString: String = ""
func concatenatedOptionals() -> String {
return (p2.firstName ?? emptyString) + emptyString + (p2.lastName ?? emptyString) + (p2.status ?? emptyString)
}
który się kompiluje 88ms
Główną przyczyną problemu jest to, że kompilator nie identyfikuje ""
pliku jako String
. Właściwie toExpressibleByStringLiteral
Kompilator zobaczy ??
i będzie musiał przeglądać wszystkie typy, które są zgodne z tym protokołem , aż znajdzie typ, który może być domyślny String
. Używając emptyString
które jest zakodowane na stałe String
, kompilator nie musi już przechodzić przez wszystkie zgodne typyExpressibleByStringLiteral
Aby dowiedzieć się, jak rejestrować czasy kompilacji, zobacz tutaj lub tutaj
Inne podobne odpowiedzi Roba Napiera na SO:
Dlaczego tworzenie dodawania ciągów trwa tak długo?
Jak połączyć wiele tablic bez spowalniania kompilatora?
Swift Array zawiera funkcję, która wydłuża czas kompilacji
var statement = "create table if not exists \(self.tableName()) (\(columns))"
:?