Papaskinkite apie kopijavimo optimizavimo mechanizmą iOS-те.
sobes.tech AI
Atsakymas iš AI
Mechanizmas, skirtas kopijavimo optimizavimui iOS ir macOS, dažnai susijęs su Copy-on-Write (CoW) struktūra arba reikšmės semantika, leidžia išvengti perteklinio duomenų kopijavimo perduodant struktūras arba klases su reikšmės semantika, tokias kaip masyvai, žodynai, eilutės ir netgi savos struktūros, jei jos įgyvendina Equatable ir Hashable protokolus (ne griežtai, bet dažniausiai).
CoW esmė:
- Kai kuriama struktūros kopija (pavyzdžiui, priskiriant vieną kintamąjį kitam arba perduodant funkcijai kaip reikšmę), faktinis duomenų kopijavimas nevyksta. Abi kintamosios nurodo į tas pačias duomenų vietas atmintyje. Skaitiklis, sekantis nuorodų skaičių, didėja.
- Kopijavimas atidedamas, kol viena iš kopijų nepabandys pakeisti duomenų.
- Tik pakeitimo metu duomenys tikrai kopijuojami, ir pakeičiama jau nauja kopija. Pradinė kopija toliau nurodo į pradinius duomenis, jei ji turi bent vieną savininką.
Privalumai:
- Sumažėja kopijavimo operacijų išlaidos, ypač dideliems duomenų kiekiams (masyvai, eilutės).
- Sumažėja atminties naudojimas, nes keli subjektai gali naudoti tuos pačius duomenis.
- Pagerėja našumas perduodant struktūras su reikšmės semantika.
Pavyzdžiai, kur CoW aktyviai naudojamas:
- NSArray, NSDictionary, NSString: Objective-C šiose klasėse CoW naudojama optimizacijai.
- Swift Array, Dictionary, String: Šie baziniai tipai Swift turi reikšmės semantiką ir naudoja CoW.
var array1 = [1, 2, 3]
var array2 = array1 // Duomenų kopijavimas nevyksta, abi kintamosios nurodo į tą patį duomenų rinkinį
array2.append(4) // Tikras duomenų kopijavimas atliekamas array2, tada pridedama
// Dabar array1 = [1, 2, 3], o array2 = [1, 2, 3, 4]
Svarbūs dalykai:
- Maži papildomi kaštai patikrinimui, ar reikalinga kopija, kiekvienos pakeitimo metu.
- Paslėptas kopijavimas, kuris gali paveikti našumą netikėtose vietose.
Svarbu žinoti, kad CoW efektyviai veikia struktūrose su reikšmės semantika (struct, enum). Klasės turi nuorodų semantiką, ir priskyrimo ar perdavimo metu kopijuojama tik nuoroda, o ne patys duomenys.
Dauguma įmontuotų kolekcijų ir eilutės Swift'e veikia su reikšmės semantika ir naudoja CoW. Kurdami savo struktūras, kurios apima nuorodų tipus (pvz., klasę), CoW bus taikoma pačiai struktūrai, bet ne nuorodų turiniui. Pakeitus nuorodų tipą viduje struktūros, tai neįtakos visos struktūros CoW, tačiau gali būti reikalinga CoW pačiam nuorodų tipui, jei jis tai palaiko.
Savo duomenų tipų rankiniu būdu įgyvendinti CoW Swift'e galima naudojant nuorodų tipo kombinaciją duomenų saugojimui (pvz., klasė su vidine struktūra) ir unikalumo patikrinimą prieš pakeitimą (isKnownUniquelyReferenced):
class Container<T> {
var value: T
init(_ value: T) {
self.value = value
}
}
struct CustomStruct {
private var _container: Container<[Int]>
var data: [Int] {
get { return _container.value }
set {
// Patikriname, ar konteineris yra unikalus
if !isKnownUniquelyReferenced(&_container) {
_container = Container(newValue)
} else {
_container.value = newValue
}
}
}
init(data: [Int]) {
_container = Container(data)
}
}
var s1 = CustomStruct(data: [1, 2, 3])
var s2 = s1 // CoW: _container s1 ir s2 dabar nurodo tą patį Container
s2.data.append(4) // Setter data iškviečiamas:
// isKnownUniquelyReferenced(_container) — false (nes s1 taip pat nurodo)
// Sukuriamas naujas Container su kopija [1, 2, 3, 4], s2._container dabar nurodo jį
// s1._container vis dar nurodo seną Container, [1, 2, 3]
print(s1.data) // Išvestis: [1, 2, 3]
print(s2.data) // Išvestis: [1, 2, 3, 4]