تحسين المسارات الساخنة: COW وInlining وSpecialisation
طبّقوا @inline و@_specialize وتحسينات أنواع القيم استنادًا إلى بيانات أداة تحليل الأداء.
تحسين المسارات الساخنة: COW وInlining وSpecialisation درس مجاني في Swift Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 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، مثل Array وDictionary، أسلوب 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، المفعّل في Release، للمترجم تضمين الشيفرة وتخصيصها عبر حدود الملفات داخل الوحدة.
// 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 في بنى Release. وتحقق من كل تحسين باستخدام اختبارات قياس XCTMeasure.
الأسئلة الشائعة
هل درس «تحسين المسارات الساخنة: COW وInlining وSpecialisation» مجاني؟
نعم — نص درس «تحسين المسارات الساخنة: COW وInlining وSpecialisation» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Swift Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Swift Academy 4 دروس في المجموع.
ماذا ستتعلم في «تحسين المسارات الساخنة: COW وInlining وSpecialisation»؟
طبّقوا @inline و@_specialize وتحسينات أنواع القيم استنادًا إلى بيانات أداة تحليل الأداء. تتمرن على Swift Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Swift Academy؟
لا تُشترط خبرة سابقة. Swift Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «تحسين المسارات الساخنة: COW وInlining وSpecialisation»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Swift Academy هذا؟
نعم. كل درس في Swift Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أساسيات Instruments: Time Profiler
- أداتا Allocations وLeaks في Instruments
- مدقّق الخيط الرئيسي والتعليق
- تحسين المسارات الساخنة: COW وInlining وSpecialisation