0Pricing
Swift Academy · บทเรียน

ปรับเส้นทางที่ใช้เวลามาก: COW การแทรกโค้ด และการปรับเฉพาะทาง

ใช้ @inline, @_specialize และการเพิ่มประสิทธิภาพชนิดค่าโดยอ้างอิงข้อมูลจากตัววิเคราะห์ประสิทธิภาพ

ปรับเส้นทางที่ใช้เวลามาก: COW การแทรกโค้ด และการปรับเฉพาะทาง เป็นบทเรียน Swift Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Swift Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน

ระบุจุดที่ต้องปรับปรุงก่อน

วิเคราะห์ประสิทธิภาพก่อนเสมอ ปรับปรุงเฉพาะโค้ดที่ Time Profiler ระบุว่าเป็นเส้นทางการทำงานที่ใช้ทรัพยากรมาก เพราะการปรับปรุงก่อนเวลาอันควรทำให้เสียเวลา

// Measure → Identify → Optimise → Re-measure
// A 10ms function called once is less important than
// a 0.1ms function called 10,000 times per frame

การคัดลอกเมื่อเขียน (COW)

ชนิดค่าใน Swift เช่น อาร์เรย์และพจนานุกรมใช้ COW โดยจะแชร์พื้นที่จัดเก็บจนกว่าจะเกิดการเปลี่ยนแปลง จึงหลีกเลี่ยงการคัดลอกที่ไม่จำเป็น

var a = [1, 2, 3, 4, 5]
var b = a         // no copy yet, shared buffer
b.append(6)       // copy happens here (b mutates)
print(a.count)    // 5 — a unchanged

การทำให้ COW ทำงานในชนิดข้อมูลแบบกำหนดเอง

นำ COW มาใช้ในชนิดค่าแบบกำหนดเองโดยห่อสถานะที่เปลี่ยนแปลงได้ไว้ในชนิดอ้างอิง และคัดลอกก่อนเปลี่ยนแปลง

struct Matrix {
  private class Storage { var data: [[Double]] }
  private var storage = Storage()
  private mutating func ensureUnique() {
    if !isKnownUniquelyReferenced(&storage) {
      storage = Storage(data: storage.data)  // copy on write
    }
  }
  mutating func set(row: Int, col: Int, value: Double) {
    ensureUnique()
    storage.data[row][col] = value
  }
}

@inline(__always)

บังคับให้คอมไพเลอร์แทรกฟังก์ชันลงในทุกตำแหน่งที่มีการเรียกใช้ เพื่อตัดค่าใช้จ่ายของการเรียกฟังก์ชันขนาดเล็กที่ถูกเรียกในลูปซึ่งทำงานถี่

@inline(__always)
func clamp(_ value: Float, _ min: Float, _ max: Float) -> Float {
  return Swift.max(min, Swift.min(max, value))
}

@inline(never)

ป้องกันการแทรกฟังก์ชัน เพื่อช่วยลดขนาดโค้ดหรือบังคับให้คอมไพเลอร์ถือว่าเส้นทางนั้นเป็นเส้นทางที่ทำงานน้อย (เกิดขึ้นไม่บ่อย)

@inline(never)
func handleUnexpectedError(_ error: Error) {
  // Large error-handling block — never inline to keep hot path small
}

@_specialize สำหรับเจเนอริก

สั่งให้คอมไพเลอร์สร้างสำเนาเฉพาะทางของฟังก์ชันเจเนอริกสำหรับชนิดข้อมูลหนึ่งโดยเฉพาะ ทำให้ใช้การส่งคำสั่งแบบคงที่และการปรับปรุงด้วย SIMD ได้

@_specialize(where T == Float)
@_specialize(where T == Double)
func normalize<T: FloatingPoint>(_ values: [T]) -> [T] {
  let max = values.max()!
  return values.map { $0 / max }
}

การปรับปรุงประสิทธิภาพทั้งโมดูล

WMO (เปิดใช้ในรุ่นเผยแพร่) อนุญาตให้คอมไพเลอร์แทรกฟังก์ชันและสร้างรูปแบบเฉพาะทางข้ามขอบเขตไฟล์ภายในโมดูลเดียวกัน

// Xcode: Build Settings → Swift Compiler → Code Generation
// Optimization Level: Optimize for Speed (-O)
// Compilation Mode: Whole Module
// Enables cross-file inlining and dead code elimination

การลดค่าใช้จ่ายของ ARC

การสร้างชนิดอ้างอิงบ่อยครั้งในเส้นทางการทำงานที่ใช้ทรัพยากรมากทำให้เกิดค่าใช้จ่ายจากการเพิ่มและลดการครอบครองของ ARC ให้เลือกใช้ชนิดค่า หรือเก็บการอ้างอิงไว้ใช้ซ้ำ

// HOT PATH:
for _ in 0..<1_000_000 {
  let obj = HeavyClass()  // alloc + dealloc + ARC overhead
}
// BETTER: allocate once outside the loop
let obj = HeavyClass()
for _ in 0..<1_000_000 { obj.process() }

การใช้ ContiguousArray

ContiguousArray รับรองว่าพื้นที่จัดเก็บจะต่อเนื่องกัน (ต่างจาก Array ที่มีองค์ประกอบชนิดคลาส) จึงช่วยเพิ่มประสิทธิภาพแคชในลูปที่ทำงานถี่

var nums = ContiguousArray<Float>(repeating: 0, count: 10_000)
// Faster iteration than Array<Float> for bridged-to-ObjC types

การลดการค้นหาตารางการทำงานตามโพรโทคอล

การส่งคำสั่งแบบไดนามิกของโพรโทคอลใช้ตารางการทำงานตามโพรโทคอล เจเนอริกร่วมกับการสร้างรูปแบบเฉพาะทางจะแทนที่การค้นหาตารางเหล่านี้ด้วยการเรียกโดยตรง

// Dynamic dispatch (slower for hot path):
func process(_ drawable: any Drawable) { drawable.draw() }
// Static dispatch after specialization:
func process<T: Drawable>(_ drawable: T) { drawable.draw() }
// Compiler may devirtualize and inline

การวัดประสิทธิภาพด้วย XCTMeasure

ตรวจสอบการปรับปรุงประสิทธิภาพด้วยการวัดประสิทธิภาพ XCTMeasure ในชุดการทดสอบเสมอ เพื่อป้องกันประสิทธิภาพถดถอย

func testNormalizePerformance() {
  let data = Array(0..<100_000).map { Float($0) }
  measure {
    _ = normalize(data)
  }
}

ตรวจสอบความเข้าใจ

isKnownUniquelyReferenced(_:) ตรวจสอบอะไรเมื่อนำการคัดลอกเมื่อเขียนมาใช้

ทบทวนบทเรียน

วิเคราะห์ประสิทธิภาพด้วย Instruments ก่อน ใช้ COW ที่มีมาใน Swift สำหรับคอลเลกชัน และนำมาใช้ในชนิดค่าแบบกำหนดเองด้วย isKnownUniquelyReferenced ใช้ @inline(__always) กับฟังก์ชันขนาดเล็กในเส้นทางการทำงานที่ใช้ทรัพยากรมาก ใช้ @_specialize กับจุดที่เจเนอริกใช้ทรัพยากรมาก และเปิดใช้ WMO ในรุ่นเผยแพร่ ตรวจสอบการปรับปรุงทุกครั้งด้วยการวัดประสิทธิภาพ XCTMeasure

คำถามที่พบบ่อย

บทเรียน “ปรับเส้นทางที่ใช้เวลามาก: COW การแทรกโค้ด และการปรับเฉพาะทาง” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ปรับเส้นทางที่ใช้เวลามาก: COW การแทรกโค้ด และการปรับเฉพาะทาง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Swift Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ปรับเส้นทางที่ใช้เวลามาก: COW การแทรกโค้ด และการปรับเฉพาะทาง”

ใช้ @inline, @_specialize และการเพิ่มประสิทธิภาพชนิดค่าโดยอ้างอิงข้อมูลจากตัววิเคราะห์ประสิทธิภาพ คุณปฏิบัติ Swift Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Swift Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Swift Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “ปรับเส้นทางที่ใช้เวลามาก: COW การแทรกโค้ด และการปรับเฉพาะทาง” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Swift Academy นี้ได้ไหม

ได้ บทเรียน Swift Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. พื้นฐาน Instruments: ตัววิเคราะห์เวลา
  2. Instruments สำหรับการจัดสรรและการรั่วไหล
  3. ตัวตรวจสอบเธรดหลักและการค้าง
  4. ปรับเส้นทางที่ใช้เวลามาก: COW การแทรกโค้ด และการปรับเฉพาะทาง
← กลับไปที่ Swift Academy