Sobes.tech
Middle+

iOS-də nüsxə optimizasiyası mexanizmi haqqında danış.

sobes.tech Süni İntellekt

AI-dan cavab

iOS və macOS-də kopyalama optimallaşdırma mexanizmi, tez-tez Copy-on-Write (CoW) strukturu və ya dəyər semantikasının istifadəsi ilə əlaqələndirilir və məlumatların artıq kopyalanmasını qarşısını almağa imkan verir, struktur və ya dəyər semantikasına malik olan siniflər, məsələn, massivlər, lüğətlər, sətirlər və hətta öz strukturlarınız, EquatableHashable protokolunu həyata keçirirlərsə (məhz, ümumi hal).

CoW-nin mahiyyəti:

  1. Strukturın nüsxəsini yaratdıqda (məsələn, bir dəyişəni digərinə təyin etdikdə və ya dəyər kimi funksiyaya ötürəndə), məlumatların faktiki kopyalanması baş vermir. Hər iki dəyişən eyni yaddaşdakı məlumatlara istinad edir. Məlumatlara olan istinad sayğacı artırılır.
  2. Kopyalama, birindən biri məlumatları dəyişməyə çalışana qədər təxirə salınır.
  3. Yalnız dəyişiklik zamanı məlumatlar faktiki olaraq kopyalanır və yeni nüsxə dəyişdirilir. Əsas nüsxə orijinal məlumatlara istinad etməyə davam edir (əgər ən azı bir sahibi qalıbsa).

Üstünlüklər:

  • Kopyalama əməliyyatlarının yükünü azaldır, xüsusən böyük məlumat həcmləri üçün (massivlər, sətirlər).
  • Yaddaş istifadəsini azaldır, çünki bir neçə obyekt eyni məlumatları paylaşa bilər.
  • Dəyər semantikasına malik strukturların ötürülməsində performansı artırır.

CoW aktiv istifadə olunan nümunələr:

  • NSArray, NSDictionary, NSString: Objective-C-də bu siniflər CoW-dən istifadə edir.
  • Array, Dictionary, String Swift-də: Bu əsas tiplər Swift-də dəyər semantikasına malikdir və CoW istifadə edir.
var array1 = [1, 2, 3]
var array2 = array1 // Kopyalama baş vermir, hər iki dəyişən eyni məlumatlara istinad edir

array2.append(4) // Məlumatların faktiki kopyalanması və sonra əlavə edilmesi
// İndi array1 = [1, 2, 3] və array2 = [1, 2, 3, 4]

Əks təsirlər:

  • Hər dəyişiklikdə kopyalama ehtiyacını yoxlamaq üçün kiçik əlavə yük.
  • Gizli kopyalama ehtimalı, bu da gözlənilməz yerlərdə performansa təsir edə bilər.

Qeyd etmək lazımdır ki, CoW, dəyər semantikasına malik strukturlar üçün effektiv işləyir (struct, enum). Siniflər referans semantikasına malikdir və sinif nümunəsinin təyin olunması və ya ötürülməsi zamanı yalnız referans kopyalanır, obyektin öz məlumatları deyil.

Swift-də, əksər daxili kolleksiyalar və sətirlər dəyər semantikasına malikdir və CoW istifadə edir. Öz strukturlarınızı yaradırkən və referans tiplərini (məsələn, sinif) daxil edən strukturlar yaratdıqda, CoW strukturun özünə tətbiq olunur, lakin referans tipinin məzmununa deyil. Struktur daxilində referens tiplə əlaqəli xüsusiyyət dəyişdirildikdə, bütün struktur üçün CoW baş verməz, lakin referens tipinin özündə dəstəklənirsə, CoW tələb oluna bilər.

Swift-də, öz məlumat tiplərinizdə CoW-yi əl ilə həyata keçirmək üçün, məlumatların saxlanması üçün referans tipindən (məsələn, daxili struktur ilə sinif) və isKnownUniquelyReferenced kimi funksiyadan istifadə edə bilərsiniz.

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 {
            // Kontrol edin, konteyner unikal referanslıdırmı
            // Əgər yoxdursa, yeni nüsxə yaradın
            if !isKnownUniquelyReferenced(&_container) {
                _container = Container(newValue)
            } else {
                // Əks halda, məlumatları birbaşa konteynerdə dəyişin
                _container.value = newValue
            }
        }
    }

    init(data: [Int]) {
        _container = Container(data)
    }
}

var s1 = CustomStruct(data: [1, 2, 3])
var s2 = s1 // CoW: _container s1 və s2-də indi eyni Container-ə istinad edir

s2.data.append(4) // Setter çağırılır.
                   // isKnownUniquelyReferenced üçün _container s2-də false olacaq (çünki s1 də ona istinad edir).
                   // Yeni bir Container yaradılır və [1, 2, 3, 4] nüsxəsi ilə.
                   // s2._container indi ona istinad edir.
                   // s1._container hələ də köhnə Container-ə istinad edir.

print(s1.data) // Çıxış: [1, 2, 3]
print(s2.data) // Çıxış: [1, 2, 3, 4]