È quasi uguale alla risposta accettata, ma con alcuni dialoghi aggiunti (ho avuto con Rob Napier, le sue altre risposte e Matt, Oliver, David di Slack) e i collegamenti.
Vedi i commenti in questa discussione. L'essenza è:
+
è fortemente sovraccarico (Apple sembra aver risolto questo problema in alcuni casi)
L' +
operatore è pesantemente sovraccarico, al momento ha 27 funzioni diverse, quindi se si stanno concatenando 4 stringhe, ovvero se si hanno 3 +
operatori, il compilatore deve controllare tra 27 operatori ogni volta, quindi 27 ^ 3 volte. Ma non è così.
V'è anche un controllo per vedere se la lhs
e rhs
delle +
funzioni sono entrambe valide se sono chiama attraverso al nucleo append
chiamato. Lì puoi vedere che possono verificarsi numerosi controlli piuttosto intensi . Se la stringa viene archiviata in modo non contiguo, il che sembra essere il caso se la stringa con cui hai a che fare è effettivamente collegata a NSString. Swift deve quindi riassemblare tutti i buffer di array di byte in un singolo buffer contiguo e ciò richiede la creazione di nuovi buffer lungo il percorso. e alla fine ottieni un buffer che contiene la stringa che stai tentando di concatenare insieme.
In breve ci sono 3 gruppi di controlli del compilatore che ti rallenteranno, cioè ogni sottoespressione deve essere riconsiderata alla luce di tutto ciò che potrebbe restituire . Di conseguenza, concatenare le stringhe con l'interpolazione, ovvero l'uso " My fullName is \(firstName) \(LastName)"
è molto meglio che "My firstName is" + firstName + LastName
poiché l'interpolazione non ha alcun sovraccarico
Swift 3 ha apportato alcuni miglioramenti. Per ulteriori informazioni leggi Come unire più array senza rallentare il compilatore? . Tuttavia l' +
operatore è ancora sovraccarico ed è meglio usare l'interpolazione di stringhe per stringhe più lunghe
Utilizzo di optionals (problema in corso - soluzione disponibile)
In questo semplicissimo progetto:
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"
}
I tempi di compilazione per le funzioni sono tali:
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()
Nota quanto è alta la durata della compilation concatenatedOptionals
.
Questo può essere risolto facendo:
let emptyString: String = ""
func concatenatedOptionals() -> String {
return (p2.firstName ?? emptyString) + emptyString + (p2.lastName ?? emptyString) + (p2.status ?? emptyString)
}
che compila in 88ms
La causa principale del problema è che il compilatore non identifica ""
come a String
. In realtà lo èExpressibleByStringLiteral
Il compilatore vedrà ??
e dovrà scorrere tutti i tipi conformi a questo protocollo , fino a quando non trova un tipo che può essere predefinito String
. Usando il emptyString
quale è hardcoded String
, il compilatore non ha più bisogno di scorrere tutti i tipi diExpressibleByStringLiteral
Per informazioni su come registrare i tempi di compilazione, vedere qui o qui
Altre risposte simili di Rob Napier su SO:
Perché l'aggiunta di stringhe richiede così tanto tempo per essere costruita?
Come unire più array senza rallentare il compilatore?
Swift Array contiene funzioni che richiedono tempi di costruzione lunghi
var statement = "create table if not exists \(self.tableName()) (\(columns))"
:?