Это почти то же самое, что принятый ответ, но с некоторым дополнительным диалогом (я имел с Робом Нейпиром, его другими ответами и Мэттом, Оливером, Дэвидом из Slack) и ссылками.
Смотрите комментарии в этой дискуссии. Суть этого:
+
сильно перегружен (в некоторых случаях Apple исправила это)
+
Оператор сильно перегружен, как сейчас она имеет 27 различных функций , так что если вы конкатенация 4 строки , то есть у вас есть 3 +
операторов, компилятор должен проверить между 27 операторами , каждый раз, так что 27 ^ 3 раза. Но это не так.
Существует также проверка , чтобы увидеть , если lhs
и rhs
из +
функций являются действительными , если они вызываются через к сердечнику append
называется. Там вы можете увидеть несколько интенсивных проверок, которые могут произойти. Если строка хранится несмежно, что имеет место, если строка, с которой вы имеете дело, фактически соединена с NSString. Затем Swift должен собрать все буферы байтового массива в единый непрерывный буфер, который требует создания новых буферов. и затем вы в конечном итоге получите один буфер, содержащий строку, которую вы пытаетесь объединить вместе.
В двух словах, есть 3 кластера проверок компилятора, которые замедляют работу, т. Е. Каждое подвыражение должно быть пересмотрено в свете всего, что оно может вернуть . В результате объединение строк с интерполяцией, т. Е. Использование " My fullName is \(firstName) \(LastName)"
намного лучше, чем, "My firstName is" + firstName + LastName
поскольку интерполяция не имеет перегрузки
Swift 3 внесла некоторые улучшения. Для получения дополнительной информации прочитайте Как объединить несколько массивов без замедления компилятора? , Тем не менее, +
оператор по-прежнему перегружен, и для более длинных строк лучше использовать интерполяцию строк.
Использование опций (текущая проблема - решение доступно)
В этом очень простом проекте:
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"
}
Время компиляции для функций таково:
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()
Обратите внимание, насколько сумасшедшей является высокая продолжительность компиляции concatenatedOptionals
.
Это можно решить, выполнив:
let emptyString: String = ""
func concatenatedOptionals() -> String {
return (p2.firstName ?? emptyString) + emptyString + (p2.lastName ?? emptyString) + (p2.status ?? emptyString)
}
который компилируется в 88ms
Основной причиной проблемы является то, что компилятор не идентифицирует ""
как String
. Это на самом делеExpressibleByStringLiteral
Компилятор увидит ??
и должен будет перебрать все типы, которые соответствуют этому протоколу , пока не найдет тип, который может быть значением по умолчанию String
. Используя emptyString
жестко запрограммированный код String
, компилятору больше не нужно перебирать все соответствующие типыExpressibleByStringLiteral
Чтобы узнать, как регистрировать время компиляции, смотрите здесь или здесь
Другие подобные ответы Роба Нейпира на SO:
Почему сложение строк занимает так много времени?
Как объединить несколько массивов, не замедляя компилятор?
Swift Array содержит функцию, увеличивающую время сборки
var statement = "create table if not exists \(self.tableName()) (\(columns))"
?