Sobes.tech
Middle+

Rääkige mulle iOS-i koopiamise optimeerimise mehhanismist.

sobes.tech AI

Vastus AI-lt

Mehhanism, mis optimeerib kopeerimist iOS ja macOS, sageli seotud Copy-on-Write (CoW) struktuuri või väärtuse semantikaga, võimaldab vältida liigset andmete kopeerimist, edastades struktuure või klasse väärtuse semantikaga, nagu massiivid, sõnastikud, stringid ja isegi omad struktuurid, kui need rakendavad Equatable ja Hashable protokolle (mitte rangelt, kuid tüüpiline juhtum).

CoW olemus:

  1. Struktuuri koopiat luues (näiteks määrates ühe muutuja teisele või edastades funktsioonile väärtusena), ei toimu tegelikku andmete koopiat. Mõlemad muutujad viitavad samadele andmetele mälus. Viidete loendur suureneb.
  2. Kopeerimine lükkub edasi, kuni üks koopia püüab andmeid muuta.
  3. Ainult muutmise hetkel kopeeritakse andmed tõeliselt ja muudetakse juba uus koopia. Algne koopia jätkab viitamist algsetele andmetele, kui tal on veel üks omanik.

Eelised:

  • Vähendab koopiate operatsioonide kulusid, eriti suurte andmekogumite puhul (massivid, stringid).
  • Vähendab mälu kasutust, kuna mitu üksust võivad jagada samu andmeid.
  • Suurendab jõudlust väärtuse semantikaga struktuuride edastamisel.

Näited, kus CoW aktiivselt kasutatakse:

  • NSArray, NSDictionary, NSString: Objective-C-s kasutavad need klassid CoW optimeerimiseks.
  • Swift Array, Dictionary, String: Need põhityypid Swiftis on väärtuse semantikaga ja kasutavad CoW.
var array1 = [1, 2, 3]
var array2 = array1 // Andmete kopeerimine ei toimu, mõlemad muutujad viitavad samale andmekogule

array2.append(4) // Toimub tõeline andmete kopeerimine array2 jaoks, siis lisamine
// Nüüd array1 = [1, 2, 3], ja array2 = [1, 2, 3, 4]

Oluline on:

  • Väikesed lisakulud kontrollimiseks, kas on vaja koopiat teha, iga muutmise ajal.
  • Varjatud koopiatamine, mis võib mõjutada jõudlust ootamatutes kohtades.

Oluline on meeles pidada, et CoW töötab tõhusalt väärtuse semantikaga struktuuridel (struct, enum). Klassidel on viidese semantika ning määrates või edastades klassi eksemplari, kopeeritakse ainult viide, mitte andmed.

Enamik sisseehitatud kollektsioone ja stringe Swiftis töötavad väärtuse semantikaga ja kasutavad CoW-d. Oma struktuure luues, mis sisaldavad viidete tüüpe (näiteks klassi), rakendub CoW ise struktuurile, mitte viidetüübi sisule. Muutused viidete tüübi omaduses, mis asub struktuuri sees, ei käivita CoW-d kogu struktuurile, kuid võivad nõuda CoW-d viidete tüübi enda jaoks, kui see seda toetab.

Sinu andmetüüpide käsitsi rakendamiseks Swiftis, võid kasutada viidete tüübi kombinatsiooni andmete salvestamiseks (näiteks klass sisemise struktuuriga) ja unikaalsuse kontrollimiseks enne muutmist (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 {
            // Kontrollime, kas konteiner on unikaalne
            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 ja s2 nüüd viitavad samale Containerile

s2.data.append(4) // Setter data kutsutakse:
                   // isKnownUniquelyReferenced(_container) — false (sest s1 samuti viitab sellele)
                   // Luues uue Containeri koopiaga [1, 2, 3, 4], s2._container viitab sellele
                   // s1._container ikka viitab vanale Containerile, [1, 2, 3]

print(s1.data) // Väljund: [1, 2, 3]
print(s2.data) // Väljund: [1, 2, 3, 4]