Copy On Write
1回の書き込みでコピーする理由
値タイプの場合、変数または関数に渡されるパラメータに割り当てると、割り当てられた値がコピーされます.
ただし、非常に大きな価格タイプを処理するときにレプリケーションを行うと、コストが非常に高くなります.
したがって、これらの問題を最小限に抑えるために、特定の値タイプを変更したり、1回以上参照した場合にのみコピーしたりすることができ、パフォーマンスが向上する.
つまり、修正(書き込み)時にコピーします.
単純に値を渡すのではなく、既存の値を参照することで、不要なレプリケーションを削減し、メモリを節約できます.
操作例を見てみましょう.
変数配列の配列をarray 2に割り当てる場合、アドレス値は同じです.
array 2を変更すると、array 2のアドレス値が変更されます.var array = [1,2,3]
var array2 = array
address(o1: &array) //0x100517000
address(o1: &array2) //0x100517000
array2.append(4) // array2가 변경
address(o1: &array) //0x100517000
address(o1: &array2) //0x102b04330
var array = [1,2,3]
var array2 = array
address(o1: &array) //0x100517000
address(o1: &array2) //0x100517000
array2.append(4) // array2가 변경
address(o1: &array) //0x100517000
address(o1: &array2) //0x102b04330
func address(o1: UnsafeRawPointer) {
let address = String(format: "%p", Int(bitPattern: o1))
print(address)
}
func address<T: AnyObject>(o2: UnsafePointer<T>) {
let address = String(format: "%p", Int(bitPattern: o2))
print(o2.pointee)
print(address)
withUnsafePointer(to: T.self) { pointer in
pointer.pointee
pointer
}
}
末尾の問題
すべての値タイプに対して、書き込み時のコピーはサポートされていますか?
NO
COWは、SWIFT標準ライブラリで定義されている値タイプ「集合タイプ」(Array、Dictionary、Set)でのみ実現できます.カスタム値タイプでは、サポートされていない場合、ユーザーは直接COWを実現できます.
カスタム構造で1回の書き込み時コピーを実現する方法について説明します。
final class Ref<T> {
var val : T
init(_ v : T) {val = v}
}
struct Box<T> {
var ref : Ref<T>
init(_ x : T) { ref = Ref(x) }
var value: T {
get {
return ref.val
}
set {
if (!isKnownUniquelyReferenced(&ref)) {
//참조카운트 1이 아니라면 (=여러곳에서 참조되고 있다면)
print(isKnownUniquelyReferenced(&ref))
ref = Ref(newValue)
print("새로운 인스턴스 생성")
return
}
ref.val = newValue
}
}
}
//주소 구하는 함수
func address(o1: UnsafeRawPointer) {
let address = String(format: "%p", Int(bitPattern: o1))
print(address)
}
var box = Box<[Int]>([1,2,3])
var copy = box
address(o1: &box.value) //0x10072bda0
address(o1: ©.value) //0x10072bda0
box.value = [3]
address(o1: &box.value) //**0x10072c1c0**
address(o1: ©.value) //0x10072bda0
Jenericタイプpropertyを持つclassタイプを定義します.
上記で定義したクラスタイプpropertyを持つ構造を定義します.
次にstructでvalueという計算プログラムを定義し、getterとsetterを持つようにします.
getterが呼び出されると、値が直接渡されます.
setterを呼び出す場合は、組み込まれたグローバル関数isKnownUniquelyReferenced関数を使用します.
オブジェクトの参照数が1の場合はtrue、1より大きい場合はfalseを返します.
COW制限
1回目の修正操作が2回目、3回目より長い→オーバーヘッド発生
疑問点
Reference
https://medium.com/@lucianoalmeida1/understanding-swift-copy-on-write-mechanisms-52ac31d68f2f
https://github.com/apple/swift/blob/main/docs/OptimizationTips.rst#id28
Reference
この問題について(Copy On Write), 我々は、より多くの情報をここで見つけました
https://velog.io/@dev_jane/Copy-On-Write
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
Reference
この問題について(Copy On Write), 我々は、より多くの情報をここで見つけました https://velog.io/@dev_jane/Copy-On-Writeテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol