Esto es casi lo mismo que la respuesta aceptada pero con un diálogo adicional (tuve con Rob Napier, sus otras respuestas y Matt, Oliver, David de Slack) y enlaces.
Ver los comentarios en esta discusión. La esencia de esto es:
+
está muy sobrecargado (Apple parece haber solucionado esto en algunos casos)
El +
operador está muy sobrecargado, a partir de ahora tiene 27 funciones diferentes, por lo que si está concatenando 4 cadenas, es decir, tiene 3 +
operadores, el compilador debe verificar entre 27 operadores cada vez, por lo que es 27 ^ 3 veces. Pero eso no es todo.
También hay una comprobación para ver si las funciones lhs
y rhs
de +
ambas son válidas si son llamadas a través del núcleo de las append
llamadas. Allí puede ver que hay varias comprobaciones intensivas que pueden ocurrir. Si la cadena se almacena de forma no contigua, lo que parece ser el caso si la cadena con la que está tratando está realmente unida a NSString. Swift luego tiene que volver a ensamblar todos los búferes de matriz de bytes en un solo búfer contiguo y eso requiere crear nuevos búferes en el camino. y finalmente obtienes un búfer que contiene la cadena que estás intentando concatenar juntos.
En pocas palabras, hay 3 grupos de comprobaciones del compilador que lo retrasarán, es decir, cada subexpresión debe reconsiderarse a la luz de todo lo que pueda devolver . Como resultado, la concatenación de cadenas con interpolación, es decir, el uso " My fullName is \(firstName) \(LastName)"
es mucho mejor que "My firstName is" + firstName + LastName
dado que la interpolación no tiene ninguna sobrecarga
Swift 3 ha realizado algunas mejoras. Para obtener más información, lea ¿Cómo fusionar varias matrices sin ralentizar el compilador? . No obstante, el +
operador todavía está sobrecargado y es mejor utilizar la interpolación de cadenas para cadenas más largas.
Uso de opcionales (problema continuo - solución disponible)
En este proyecto muy simple:
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"
}
El tiempo de compilación de las funciones es el siguiente:
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()
Observe cuán loca es la duración de la compilación concatenatedOptionals
.
Esto se puede resolver haciendo:
let emptyString: String = ""
func concatenatedOptionals() -> String {
return (p2.firstName ?? emptyString) + emptyString + (p2.lastName ?? emptyString) + (p2.status ?? emptyString)
}
que compila en 88ms
La causa raíz del problema es que el compilador no identifica el ""
como a String
. En realidad esExpressibleByStringLiteral
El compilador verá ??
y tendrá que recorrer todos los tipos que se hayan conformado a este protocolo , hasta que encuentre un tipo que pueda ser el predeterminado String
. Al usar el emptyString
que está codificado String
, el compilador ya no necesita recorrer todos los tipos deExpressibleByStringLiteral
Para aprender cómo registrar tiempos de compilación, vea aquí o aquí
Otras respuestas similares de Rob Napier en SO:
¿Por qué la adición de cadenas tarda tanto en construirse?
¿Cómo fusionar varias matrices sin ralentizar el compilador?
Swift Array contiene función que hace que los tiempos de construcción sean largos
var statement = "create table if not exists \(self.tableName()) (\(columns))"
?