Isso é quase o mesmo que a resposta aceita, mas com alguns diálogos adicionais (tive com Rob Napier, suas outras respostas e Matt, Oliver, David do Slack) e links.
Veja os comentários nesta discussão. A essência disso é:
+
está sobrecarregado (a Apple parece ter corrigido isso em alguns casos)
O +
operador está sobrecarregado, a partir de agora possui 27 funções diferentes; portanto, se você estiver concatenando 4 strings, ou seja, você tem 3 +
operadores, o compilador deve verificar entre 27 operadores a cada vez, ou seja, 27 ^ 3 vezes. Mas não é isso.
Há também uma verificação para ver se o lhs
e rhs
das +
funções são válidos se forem chama até o núcleo da append
chamada. Lá você pode ver que existem várias verificações intensivas que podem ocorrer. Se a sequência for armazenada de forma não contígua, o que parece ser o caso se a sequência com a qual você está lidando for realmente conectada ao NSString. O Swift precisa montar novamente todos os buffers da matriz de bytes em um único buffer contíguo, o que requer a criação de novos buffers ao longo do caminho. e, eventualmente, você obtém um buffer que contém a string que você está tentando concatenar juntos.
Em poucas palavras, existem três grupos de verificações do compilador que o atrasarão, ou seja, cada subexpressão deve ser reconsiderada à luz de tudo o que possa retornar . Como resultado, concatenar seqüências de caracteres com interpolação, ou seja, usar " My fullName is \(firstName) \(LastName)"
é muito melhor do que "My firstName is" + firstName + LastName
uma vez que a interpolação não possui sobrecarga
O Swift 3 fez algumas melhorias. Para obter mais informações, leia Como mesclar várias matrizes sem diminuir a velocidade do compilador? . No entanto, o +
operador ainda está sobrecarregado e é melhor usar a interpolação de strings para strings mais longos
Uso de opcionais (problema contínuo - solução disponível)
Neste projeto muito simples:
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"
}
O tempo de compilação para as funções é o seguinte:
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 o quão louca é a duração da compilação concatenatedOptionals
.
Isso pode ser resolvido fazendo:
let emptyString: String = ""
func concatenatedOptionals() -> String {
return (p2.firstName ?? emptyString) + emptyString + (p2.lastName ?? emptyString) + (p2.status ?? emptyString)
}
que compila em 88ms
A causa raiz do problema é que o compilador não identifica o ""
como a String
. É realmenteExpressibleByStringLiteral
O compilador verá ??
e precisará percorrer todos os tipos que estão em conformidade com este protocolo , até encontrar um tipo que possa ser o padrão String
. Ao usar o emptyString
código codificado String
, o compilador não precisa mais percorrer todos os tipos conformes deExpressibleByStringLiteral
Para saber como registrar os tempos de compilação, veja aqui ou aqui
Outras respostas semelhantes de Rob Napier no SO:
Por que a adição de strings leva tanto tempo para construir?
Como mesclar várias matrizes sem diminuir a velocidade do compilador?
Swift Array contém a função que aumenta o tempo de construção
var statement = "create table if not exists \(self.tableName()) (\(columns))"
:?