Optymalizacja gorących ścieżek: COW, inlining i specjalizacja
Stosowanie @inline, @_specialize i optymalizacji typów wartości na podstawie danych profilera.
Optymalizacja gorących ścieżek: COW, inlining i specjalizacja to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Swift Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Swift Academy zawiera 4 lekcji w sumie.
Identyfikowanie przed optymalizacją
Zawsze należy najpierw wykonać profilowanie. Optymalizować należy wyłącznie kod wskazany przez Time Profiler jako często wykonywana ścieżka — przedwczesna optymalizacja jest stratą czasu.
// Measure → Identify → Optimise → Re-measure
// A 10ms function called once is less important than
// a 0.1ms function called 10,000 times per frameCopy-on-Write (COW)
Typy wartościowe Swift (Array, Dictionary) używają mechanizmu COW: pamięć jest współdzielona do momentu wykonania mutacji, co pozwala uniknąć niepotrzebnego kopiowania.
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 unchangedZapewnianie COW w typach niestandardowych
Aby zaimplementować COW w niestandardowych typach wartościowych, należy opakować zmienny stan w typ referencyjny i kopiować go przed mutacją.
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)
Wymusza wstawienie funkcji przez kompilator w każdym miejscu jej wywołania, eliminując narzut wywołania w przypadku małych funkcji wykonywanych w ciasnych pętlach.
@inline(__always)
func clamp(_ value: Float, _ min: Float, _ max: Float) -> Float {
return Swift.max(min, Swift.min(max, value))
}@inline(never)
Zapobiega wstawianiu funkcji, aby zmniejszyć rozmiar kodu lub wymusić potraktowanie danej ścieżki jako rzadko używanej.
@inline(never)
func handleUnexpectedError(_ error: Error) {
// Large error-handling block — never inline to keep hot path small
}@_specialize dla generyków
Informuje kompilator, aby wygenerował wyspecjalizowaną kopię funkcji generycznej dla określonego typu, umożliwiając statyczne wysyłanie i optymalizacje 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 }
}Optymalizacja całego modułu
WMO (włączone w trybie Release) pozwala kompilatorowi wstawiać funkcje i przeprowadzać specjalizację między granicami plików w obrębie modułu.
// Xcode: Build Settings → Swift Compiler → Code Generation
// Optimization Level: Optimize for Speed (-O)
// Compilation Mode: Whole Module
// Enables cross-file inlining and dead code eliminationUnikanie narzutu ARC
Częste tworzenie typów referencyjnych w często wykonywanych ścieżkach powoduje narzut związany z retain/release w ARC. Należy preferować typy wartościowe lub buforować odwołania.
// 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() }Używanie ContiguousArray
ContiguousArray gwarantuje ciągłe przechowywanie elementów (w przeciwieństwie do Array w przypadku elementów będących klasami), co poprawia wydajność pamięci podręcznej w ciasnych pętlach.
var nums = ContiguousArray<Float>(repeating: 0, count: 10_000)
// Faster iteration than Array<Float> for bridged-to-ObjC typesOgraniczanie wyszukiwań w tablicach świadków protokołów
Dynamiczne wysyłanie za pośrednictwem protokołów korzysta z tablic świadków. Generyki i specjalizacja zastępują wyszukiwania w tablicach świadków bezpośrednimi wywołaniami.
// 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 inlineTestowanie wydajności za pomocą XCTMeasure
Zawsze należy weryfikować optymalizacje za pomocą testów wydajności XCTMeasure w zestawie testów, aby zapobiegać regresjom.
func testNormalizePerformance() {
let data = Array(0..<100_000).map { Float($0) }
measure {
_ = normalize(data)
}
}Szybkie sprawdzenie
Co sprawdza isKnownUniquelyReferenced(_:) podczas implementowania mechanizmu Copy-on-Write?
Podsumowanie lekcji
Najpierw należy wykonać profilowanie za pomocą Instruments. W przypadku kolekcji należy korzystać z wbudowanego mechanizmu COW języka Swift; w niestandardowych typach wartościowych należy go implementować za pomocą isKnownUniquelyReferenced. @inline(__always) należy stosować w przypadku małych funkcji często wykonywanych, @_specialize w przypadku często wykonywanych fragmentów generycznych, a WMO włączać w kompilacjach Release. Każdą optymalizację należy weryfikować za pomocą testów wydajności XCTMeasure.
Ucz się Swift dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 122
- Lekcje
- 409
Często zadawane pytania
Czy lekcja „Optymalizacja gorących ścieżek: COW, inlining i specjalizacja” jest bezpłatna?
Tak — pełny tekst „Optymalizacja gorących ścieżek: COW, inlining i specjalizacja” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Swift Academy, przejdź na CoddyKit PRO. Kurs Swift Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Optymalizacja gorących ścieżek: COW, inlining i specjalizacja”?
Stosowanie @inline, @_specialize i optymalizacji typów wartości na podstawie danych profilera. Ćwiczysz Swift Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Swift Academy?
Nie wymagamy żadnego doświadczenia. Swift Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Optymalizacja gorących ścieżek: COW, inlining i specjalizacja”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Swift Academy?
Tak. Każda lekcja Swift Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Podstawy Instruments: Time Profiler
- Instruments Allocations i Leaks
- Main Thread Checker i zawieszanie aplikacji
- Optymalizacja gorących ścieżek: COW, inlining i specjalizacja