นี่เกือบจะเหมือนกับคำตอบที่ยอมรับ แต่มีบางบทสนทนาเพิ่มเติม (ฉันมีกับ Rob Napier คำตอบอื่น ๆ ของเขาและ Matt, Oliver, David จาก 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 ได้ทำการปรับปรุงบางอย่าง สำหรับข้อมูลเพิ่มเติมอ่านวิธีการรวมหลายอาร์เรย์โดยไม่ทำให้คอมไพเลอร์ช้าลง? . อย่างไรก็ตาม+
โอเปอเรเตอร์ยังคงโอเวอร์โหลดและดีกว่าที่จะใช้การแก้ไขสตริงสำหรับสตริงที่ยาวกว่า
การใช้ optionals (ปัญหาต่อเนื่อง - มีวิธีแก้ไข)
ในโครงการง่าย ๆ นี้:
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
ซึ่ง hardcoded เพื่อString
คอมไพเลอร์ไม่จำเป็นต้องวนซ้ำผ่านทุกประเภทที่สอดคล้องกันExpressibleByStringLiteral
หากต้องการเรียนรู้วิธีบันทึกเวลารวบรวมดูที่นี่หรือที่นี่
คำตอบที่คล้ายกันอื่น ๆ โดย Rob Napier บน SO:
เหตุใดการเพิ่มสตริงจึงใช้เวลานานในการสร้าง
วิธีการรวมหลายอาร์เรย์โดยไม่ทำให้คอมไพเลอร์ช้าลง?
Swift Array มีฟังก์ชั่นทำให้เวลาในการสร้างนาน
var statement = "create table if not exists \(self.tableName()) (\(columns))"
?