Sobes.tech
Middle+

Պատմեք ինձ iOS-ում պատճենման օպտիմիզացիայի մեխանիզմի մասին։

sobes.tech AI

Պատասխան AI-ից

Մեխանիզմը օպտիմիզացման համար Copy-on-Write (CoW) կամ արժեքային սեմանտիկայի օգտագործմամբ iOS և macOS-ում թույլ է տալիս խուսափել ավելորդ տվյալների կրկնօրինակումից՝ երբ փոխանցվում են արժեքային սեմանտիկայի կառուցվածքներ կամ դասեր, ինչպիսիք են զանգվածները, բառարանները, տողերը և նույնիսկ սեփական կառուցվածքները, եթե դրանք իրականացնում են Equatable և Hashable պրոտոկոլները (ոչ խիստ, բայց սովորական դեպք):

CoW-ի հիմնական գաղափարը՝

  1. Երբ ստեղծվում է կառուցվածքի պատճենը (օրինակ՝ մի փոփոխականի փոխարեն մյուսին նշանակելը, կամ փոխանցում ֆունկցիային արժեքով), իրական տվյալների կրկնօրինակում չի կատարվում: Երկու փոփոխականներն pointing են նույն տվյալների վրա: Դատարկիչը ավելանում է:
  2. Կրկնօրինակումն հետաձգվում է, մինչև մեկը փոխի տվյալները:
  3. Միայն փոփոխության ժամանակ տվյալները իրականում կրկնօրինակում են, և արդեն նոր պատճենն է փոփոխվում: Արտաքին պատճենը շարունակում է ցույց տալ սկզբնական տվյալները, եթե այն ունի առնվազն մեկ սեփականատեր:

Առավելություններ՝

  • Փոքր ծախսեր կրկնօրինակման գործողությունների համար, հատկապես մեծ տվյալների համար (մասիվներ, տողեր):
  • Հիշողության ավելի արդյունավետ օգտագործում, քանի որ մի քանի օբյեկտ կարող է միաժամանակ օգտագործել նույն տվյալները:
  • Գործնականության բարձրացում արժեքային սեմանտիկայի կառուցվածքների փոխանցման ժամանակ:

Օգտագործման օրինակներ՝

  • NSArray, NSDictionary, NSString: Objective-C-ում այս դասերը օգտագործում են CoW-ը օպտիմիզացման համար:
  • Array, Dictionary, String in Swift: Այս հիմնական տիպերը Swift-ում ունեն արժեքային սեմանտիկա և օգտագործում են CoW:
var array1 = [1, 2, 3]
var array2 = array1 // Տվյալների կրկնօրինակում չի կատարվում, երկու փոփոխականներն pointing են նույն տվյալների վրա

array2.append(4) // Կատարվում է իրական տվյալների կրկնօրինակում array2-ի համար, ապա append
// Այժմ array1 = [1, 2, 3] և array2 = [1, 2, 3, 4]

Կարծրություններ՝

  • Փոքր ծախսեր ստուգումների համար՝ անհրաժեշտ է կրկնօրինակում կամ ոչ:
  • Անհրաժեշտության դեպքում թաքնված կրկնօրինակում, որը կարող է ազդել կատարողականության վրա:

Հիշեք, որ CoW արդյունավետ է արժեքային սեմանտիկայի կառուցվածքների համար (struct, enum): Դասերը ունեն հղման սեմանտիկա, և պատճենը կատարվում է միայն հղումը, ոչ թե տվյալները:

Swift-ում մեծ մասամբ ինտեգրված հավաքածուները և տողերը աշխատում են արժեքային սեմանտիկայով և օգտագործում են CoW:

Իմ սեփական կառուցվածքները, որոնք պարունակում են հղման տիպեր (օրինակ՝ դաս), CoW կիրառվում է հենց կառուցվածքի վրա, բայց ոչ՝ հղման տիպի բովանդակության վրա:

Փոխելիս՝ հղման տիպի հատկությունը՝ չի առաջացնի CoW ամբողջ կառուցվածքի համար, բայց կարող է պահանջել CoW հղման տիպի համար, եթե այն աջակցում է:

Իմ սեփական տվյալների տիպերի համար CoW ձեռքով իրականացման համար՝ կարող եք օգտագործել հղման տիպի համադրություն տվյալների պահպանումը (օրինակ՝ դաս, որը պարունակում է ներքին կառուցվածք) և հղման եզակիության ստուգում՝ 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 {
            // Ստուգում՝ արդյոք կոնտեյները եզակի է
            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 և s2-ում այժմ pointing են նույն Container-ի վրա

s2.data.append(4) // Setter data է կանչվում:
                   // isKnownUniquelyReferenced(_container)՝ false (քանի որ s1 նույնպես նշում է)
                   // Ստեղծվում է նոր Container՝ կոպիայով [1, 2, 3, 4], s2._container now pointing է այդին
                   // s1._container դեռ pointing է հին Container-ին՝ [1, 2, 3]

print(s1.data) // Արտածում՝ [1, 2, 3]
print(s2.data) // Արտածում՝ [1, 2, 3, 4]